2014-03-15 16:59:03 +00:00
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
2016-07-06 04:09:17 +00:00
// Copyright (C) 2011-2016 by Matthew "Inuyasha" Walsh.
// Copyright (C) 1999-2016 by Sonic Team Junior.
2014-03-15 16:59:03 +00:00
//
// 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 <unistd.h>
# 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"
2018-08-28 20:08:47 +00:00
// Addfile
# include "filesrch.h"
2014-03-15 16:59:03 +00:00
# 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"
2016-08-12 01:42:11 +00:00
# include "k_kart.h" // SRB2kart
2018-08-31 17:18:19 +00:00
# include "d_player.h" // KITEM_ constants
2014-03-15 16:59:03 +00:00
// Condition Sets
# include "m_cond.h"
// And just some randomness for the exits.
# include "m_random.h"
# ifdef PC_DOS
# include <stdio.h> // 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
2018-08-28 20:08:47 +00:00
# if defined (__GNUC__) && (__GNUC__ >= 4)
# define FIXUPO0
# endif
2014-03-15 16:59:03 +00:00
# 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 [ 32 ] =
{
2018-03-06 01:14:50 +00:00
{ " \x82 Sonic \x80 \n \x82 Speed: \x80 7 \n \x82 Weight: \x80 3 " , " " , " sonic " } ,
2017-10-18 03:14:51 +00:00
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
2014-03-15 16:59:03 +00:00
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " } ,
{ " ??? " , " " , " " }
} ;
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 ] [ 25 ] ;
# 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 setupcontrols_secondaryplayer ;
2017-12-08 07:29:01 +00:00
static boolean setupcontrols_thirdplayer ;
static boolean setupcontrols_fourthplayer ;
2017-12-17 03:32:43 +00:00
static INT32 ( * setupcontrols ) [ 2 ] ; // pointer to the gamecontrols of the player being edited
2014-03-15 16:59:03 +00:00
// 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 ;
2018-08-28 20:08:47 +00:00
# define lsheadingheight 16
2014-03-15 16:59:03 +00:00
// Sky Room
2018-03-02 00:00:16 +00:00
//static void M_CustomLevelSelect(INT32 choice);
//static void M_CustomWarp(INT32 choice);
2014-03-15 16:59:03 +00:00
FUNCNORETURN static ATTRNORETURN void M_UltimateCheat ( INT32 choice ) ;
static void M_LoadGameLevelSelect ( INT32 choice ) ;
static void M_GetAllEmeralds ( INT32 choice ) ;
static void M_DestroyRobots ( INT32 choice ) ;
static void M_LevelSelectWarp ( INT32 choice ) ;
static void M_Credits ( INT32 choice ) ;
static void M_PandorasBox ( INT32 choice ) ;
static void M_EmblemHints ( INT32 choice ) ;
2018-03-29 05:14:47 +00:00
static char * M_GetConditionString ( condition_t cond ) ;
2014-03-15 16:59:03 +00:00
menu_t SR_MainDef , SR_UnlockChecklistDef ;
// Misc. Main Menu
static void M_SinglePlayerMenu ( INT32 choice ) ;
static void M_Options ( INT32 choice ) ;
2018-09-08 16:02:03 +00:00
static void M_Manual ( INT32 choice ) ;
2014-03-15 16:59:03 +00:00
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 ) ;
2018-03-02 00:00:16 +00:00
//static void M_SecretsMenu(INT32 choice);
2014-03-15 16:59:03 +00:00
static void M_SetupChoosePlayer ( INT32 choice ) ;
static void M_QuitSRB2 ( INT32 choice ) ;
menu_t SP_MainDef , MP_MainDef , OP_MainDef ;
menu_t MISC_ScrambleTeamDef , MISC_ChangeTeamDef ;
// Single Player
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
//static void M_LoadGame(INT32 choice);
2014-03-15 16:59:03 +00:00
static void M_TimeAttack ( INT32 choice ) ;
2018-07-04 21:57:50 +00:00
static boolean M_QuitTimeAttackMenu ( void ) ;
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
//static void M_NightsAttack(INT32 choice);
2014-03-15 16:59:03 +00:00
static void M_Statistics ( INT32 choice ) ;
2017-10-21 02:01:07 +00:00
static void M_HandleStaffReplay ( INT32 choice ) ;
2014-03-15 16:59:03 +00:00
static void M_ReplayTimeAttack ( INT32 choice ) ;
static void M_ChooseTimeAttack ( INT32 choice ) ;
2018-01-22 00:15:26 +00:00
//static void M_ChooseNightsAttack(INT32 choice);
2014-03-15 16:59:03 +00:00
static void M_ModeAttackRetry ( INT32 choice ) ;
static void M_ModeAttackEndGame ( INT32 choice ) ;
static void M_SetGuestReplay ( INT32 choice ) ;
static void M_ChoosePlayer ( INT32 choice ) ;
2018-07-01 18:29:13 +00:00
menu_t SP_LevelStatsDef ;
2014-11-12 00:55:07 +00:00
static menu_t SP_TimeAttackDef , SP_ReplayDef , SP_GuestReplayDef , SP_GhostDef ;
2018-01-22 00:15:26 +00:00
//static menu_t SP_NightsAttackDef, SP_NightsReplayDef, SP_NightsGuestReplayDef, SP_NightsGhostDef;
2014-03-15 16:59:03 +00:00
// Multiplayer
# ifndef NONET
static void M_StartServerMenu ( INT32 choice ) ;
static void M_ConnectMenu ( INT32 choice ) ;
# endif
static void M_StartSplitServerMenu ( INT32 choice ) ;
static void M_StartServer ( INT32 choice ) ;
# ifndef NONET
static void M_Refresh ( INT32 choice ) ;
static void M_Connect ( INT32 choice ) ;
static void M_ChooseRoom ( INT32 choice ) ;
# endif
static void M_SetupMultiPlayer ( INT32 choice ) ;
static void M_SetupMultiPlayer2 ( INT32 choice ) ;
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2017-12-08 07:29:01 +00:00
static void M_SetupMultiPlayer3 ( INT32 choice ) ;
static void M_SetupMultiPlayer4 ( INT32 choice ) ;
2018-01-01 18:11:24 +00:00
# endif
2014-03-15 16:59:03 +00:00
// Options
// Split into multiple parts due to size
// Controls
2017-12-04 01:00:31 +00:00
menu_t OP_ControlsDef , /*OP_ControlListDef,*/ OP_MoveControlsDef ;
2018-01-24 21:53:20 +00:00
menu_t /*OP_MPControlsDef, OP_CameraControlsDef, OP_MiscControlsDef,*/ OP_CustomControlsDef , OP_SpectateControlsDef ;
2018-01-01 18:11:24 +00:00
menu_t OP_MouseOptionsDef , OP_Mouse2OptionsDef ;
menu_t OP_Joystick1Def , OP_Joystick2Def ;
# ifndef NOFOURPLAYER
menu_t OP_Joystick3Def , OP_Joystick4Def ;
# endif
2014-03-15 16:59:03 +00:00
static void M_VideoModeMenu ( INT32 choice ) ;
static void M_Setup1PControlsMenu ( INT32 choice ) ;
static void M_Setup2PControlsMenu ( INT32 choice ) ;
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2017-12-08 07:29:01 +00:00
static void M_Setup3PControlsMenu ( INT32 choice ) ;
static void M_Setup4PControlsMenu ( INT32 choice ) ;
2018-01-01 18:11:24 +00:00
# endif
2014-03-15 16:59:03 +00:00
static void M_Setup1PJoystickMenu ( INT32 choice ) ;
static void M_Setup2PJoystickMenu ( INT32 choice ) ;
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2017-12-08 07:29:01 +00:00
static void M_Setup3PJoystickMenu ( INT32 choice ) ;
static void M_Setup4PJoystickMenu ( INT32 choice ) ;
2018-01-01 18:11:24 +00:00
# endif
2014-03-15 16:59:03 +00:00
static void M_AssignJoystick ( INT32 choice ) ;
static void M_ChangeControl ( 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 ;
2018-06-30 22:18:13 +00:00
static void M_ToggleSFX ( INT32 choice ) ;
static void M_ToggleDigital ( INT32 choice ) ;
//static void M_ToggleMIDI(INT32 choice);
2018-06-15 00:18:29 +00:00
static void M_RestartAudio ( void ) ;
2014-03-15 16:59:03 +00:00
//Misc
2018-06-15 00:18:29 +00:00
menu_t /*OP_DataOptionsDef,*/ OP_ScreenshotOptionsDef , OP_EraseDataDef ;
2018-08-09 21:59:52 +00:00
menu_t OP_HUDOptionsDef , OP_ChatOptionsDef ;
2014-03-15 16:59:03 +00:00
menu_t OP_GameOptionsDef , OP_ServerOptionsDef ;
2018-06-15 00:18:29 +00:00
//menu_t OP_NetgameOptionsDef, OP_GametypeOptionsDef;
2014-03-15 16:59:03 +00:00
menu_t OP_MonitorToggleDef ;
static void M_ScreenshotOptions ( INT32 choice ) ;
static void M_EraseData ( INT32 choice ) ;
2018-08-28 20:08:47 +00:00
static void M_Addons ( INT32 choice ) ;
static void M_AddonsOptions ( INT32 choice ) ;
static patch_t * addonsp [ NUM_EXT + 5 ] ;
# define numaddonsshown 4
2014-03-15 16:59:03 +00:00
// Drawing functions
static void M_DrawGenericMenu ( void ) ;
static void M_DrawCenteredMenu ( void ) ;
2018-08-28 20:08:47 +00:00
static void M_DrawAddons ( void ) ;
2014-03-15 16:59:03 +00:00
static void M_DrawSkyRoom ( void ) ;
static void M_DrawChecklist ( void ) ;
static void M_DrawEmblemHints ( void ) ;
static void M_DrawPauseMenu ( void ) ;
2018-07-02 00:55:01 +00:00
static void M_DrawLevelSelectOnly ( boolean leftfade , boolean rightfade ) ;
2014-03-15 16:59:03 +00:00
static void M_DrawServerMenu ( void ) ;
static void M_DrawImageDef ( void ) ;
static void M_DrawLoad ( void ) ;
static void M_DrawLevelStats ( void ) ;
static void M_DrawTimeAttackMenu ( void ) ;
2018-01-22 00:15:26 +00:00
//static void M_DrawNightsAttackMenu(void);
2014-03-15 16:59:03 +00:00
static void M_DrawSetupChoosePlayerMenu ( void ) ;
static void M_DrawControl ( void ) ;
2018-06-30 22:18:13 +00:00
static void M_DrawVideoMenu ( void ) ;
2018-08-09 21:59:52 +00:00
static void M_DrawHUDOptions ( void ) ;
2014-03-15 16:59:03 +00:00
static void M_DrawVideoMode ( void ) ;
2018-08-31 17:18:19 +00:00
static void M_DrawMonitorToggles ( void ) ;
2014-03-15 16:59:03 +00:00
# ifdef HWRENDER
static void M_OGL_DrawFogMenu ( void ) ;
static void M_OGL_DrawColorMenu ( void ) ;
# endif
# ifndef NONET
static void M_DrawConnectMenu ( void ) ;
2018-06-30 15:01:03 +00:00
static void M_DrawMPMainMenu ( void ) ;
2014-03-15 16:59:03 +00:00
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_ExitPandorasBox ( void ) ;
static boolean M_QuitMultiPlayerMenu ( void ) ;
2018-08-28 20:08:47 +00:00
static void M_HandleAddons ( INT32 choice ) ;
2014-03-15 16:59:03 +00:00
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 ) ;
2018-08-31 17:18:19 +00:00
static void M_HandleMonitorToggles ( INT32 choice ) ;
2014-03-15 16:59:03 +00:00
// Consvar onchange functions
static void Nextmap_OnChange ( void ) ;
static void Newgametype_OnChange ( void ) ;
2018-01-22 00:15:26 +00:00
//static void Dummymares_OnChange(void);
2017-10-21 02:01:07 +00:00
static void Dummystaff_OnChange ( void ) ;
2014-03-15 16:59:03 +00:00
// ==========================================================================
// CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE.
// ==========================================================================
static CV_PossibleValue_t map_cons_t [ ] = {
2018-08-15 15:12:36 +00:00
{ 0 , " MIN " } ,
2018-07-08 23:07:54 +00:00
{ NUMMAPS , " MAX " } ,
{ 0 , NULL }
2014-03-15 16:59:03 +00:00
} ;
2014-04-14 05:14:58 +00:00
consvar_t cv_nextmap = { " nextmap " , " 1 " , CV_HIDEN | CV_CALL , map_cons_t , Nextmap_OnChange , 0 , NULL , NULL , 0 , 0 , NULL } ;
2014-03-15 16:59:03 +00:00
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 CV_AddValue!
CV_PossibleValue_t gametype_cons_t [ ] =
{
2017-11-28 06:13:23 +00:00
{ GT_RACE , " Race " } , { GT_MATCH , " Battle " } ,
2017-02-07 22:19:04 +00:00
/* // SRB2kart
2014-03-15 16:59:03 +00:00
{ GT_COOP , " Co-op " } ,
{ GT_COMPETITION , " Competition " } ,
{ GT_RACE , " Race " } ,
{ GT_MATCH , " Match " } ,
{ GT_TEAMMATCH , " Team Match " } ,
{ GT_TAG , " Tag " } ,
{ GT_HIDEANDSEEK , " Hide and Seek " } ,
{ GT_CTF , " CTF " } ,
2017-02-07 22:19:04 +00:00
*/
2014-03-15 16:59:03 +00:00
{ 0 , NULL }
} ;
2017-02-07 22:19:04 +00:00
consvar_t cv_newgametype = { " newgametype " , " Race " , CV_HIDEN | CV_CALL , gametype_cons_t , Newgametype_OnChange , 0 , NULL , NULL , 0 , 0 , NULL } ;
2014-03-15 16:59:03 +00:00
static CV_PossibleValue_t serversort_cons_t [ ] = {
{ 0 , " Ping " } ,
2014-03-17 12:13:16 +00:00
{ 1 , " Modified State " } ,
{ 2 , " Most Players " } ,
{ 3 , " Least Players " } ,
{ 4 , " Max Players " } ,
{ 5 , " Gametype " } ,
2014-03-15 16:59:03 +00:00
{ 0 , NULL }
} ;
consvar_t cv_serversort = { " serversort " , " Ping " , CV_HIDEN | 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 } ;
2018-07-06 17:08:35 +00:00
CV_PossibleValue_t ghost_cons_t [ ] = { { 0 , " Hide " } , { 1 , " Show Character " } , { 2 , " Show All " } , { 0 , NULL } } ;
2014-03-15 16:59:03 +00:00
CV_PossibleValue_t ghost2_cons_t [ ] = { { 0 , " Hide " } , { 1 , " Show " } , { 0 , NULL } } ;
2017-10-21 02:01:07 +00:00
consvar_t cv_ghost_besttime = { " ghost_besttime " , " Show All " , CV_SAVE , ghost_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2018-01-22 00:15:26 +00:00
consvar_t cv_ghost_bestlap = { " ghost_bestlap " , " Show All " , CV_SAVE , ghost_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2017-10-21 02:01:07 +00:00
consvar_t cv_ghost_last = { " ghost_last " , " Show All " , CV_SAVE , ghost_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2014-03-15 16:59:03 +00:00
consvar_t cv_ghost_guest = { " ghost_guest " , " Show " , CV_SAVE , ghost2_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2017-10-18 03:14:51 +00:00
consvar_t cv_ghost_staff = { " ghost_staff " , " Show " , CV_SAVE , ghost2_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2014-03-15 16:59:03 +00:00
//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.
2018-06-30 15:01:03 +00:00
# ifndef NOFOURPLAYER
2018-06-30 22:18:13 +00:00
static void Dummysplitplayers_OnChange ( void ) ;
static CV_PossibleValue_t dummysplitplayers_cons_t [ ] = { { 2 , " Two " } , { 3 , " Three " } , { 4 , " Four " } , { 0 , NULL } } ;
static consvar_t cv_dummysplitplayers = { " dummysplitplayers " , " Two " , CV_HIDEN | CV_CALL , dummysplitplayers_cons_t , Dummysplitplayers_OnChange , 0 , NULL , NULL , 0 , 0 , NULL } ;
2018-06-30 15:01:03 +00:00
# endif
2018-06-30 22:18:13 +00:00
2014-03-15 16:59:03 +00:00
static CV_PossibleValue_t dummyteam_cons_t [ ] = { { 0 , " Spectator " } , { 1 , " Red " } , { 2 , " Blue " } , { 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 } } ;
2018-01-22 00:15:26 +00:00
/*static CV_PossibleValue_t dummymares_cons_t[] = {
2014-03-15 16:59:03 +00:00
{ - 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 }
2018-01-22 00:15:26 +00:00
} ; */
2017-10-21 02:01:07 +00:00
static CV_PossibleValue_t dummystaff_cons_t [ ] = { { 0 , " MIN " } , { 100 , " MAX " } , { 0 , NULL } } ;
2014-03-15 16:59:03 +00:00
static consvar_t cv_dummyteam = { " dummyteam " , " Spectator " , CV_HIDEN , dummyteam_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 } ;
2018-01-22 00:15:26 +00:00
//static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dummymares_cons_t, Dummymares_OnChange, 0, NULL, NULL, 0, 0, NULL};
2017-10-21 02:01:07 +00:00
static consvar_t cv_dummystaff = { " dummystaff " , " 0 " , CV_HIDEN | CV_CALL , dummystaff_cons_t , Dummystaff_OnChange , 0 , NULL , NULL , 0 , 0 , NULL } ;
2014-03-15 16:59:03 +00:00
// ==========================================================================
// 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 [ ] =
{
2018-08-28 20:08:47 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Extras " , & SR_UnlockChecklistDef , 76 } ,
{ IT_CALL | IT_STRING , NULL , " 1 Player " , M_SinglePlayerMenu , 84 } ,
2018-07-02 00:55:01 +00:00
# ifdef NONET
M_StartSplitServerMenu
2018-08-28 20:08:47 +00:00
{ IT_CALL | IT_STRING , NULL , " Splitscreen " , M_StartSplitServerMenu , 92 } ,
2018-07-02 00:55:01 +00:00
# else
2018-08-28 20:08:47 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Multiplayer " , & MP_MainDef , 92 } ,
2018-07-02 00:55:01 +00:00
# endif
2018-08-28 20:08:47 +00:00
{ IT_CALL | IT_STRING , NULL , " Options " , M_Options , 100 } ,
{ IT_CALL | IT_STRING , NULL , " Addons " , M_Addons , 108 } ,
2018-03-02 00:00:16 +00:00
{ IT_CALL | IT_STRING , NULL , " Quit Game " , M_QuitSRB2 , 116 } ,
2014-03-15 16:59:03 +00:00
} ;
typedef enum
{
secrets = 0 ,
singleplr ,
multiplr ,
options ,
2018-08-28 20:08:47 +00:00
addons ,
2014-03-15 16:59:03 +00:00
quitdoom
} main_e ;
2018-08-28 20:08:47 +00:00
static menuitem_t MISC_AddonsMenu [ ] =
{
{ IT_KEYHANDLER | IT_NOTHING , NULL , " " , M_HandleAddons , 0 } , // dummy menuitem for the control func
} ;
2014-03-15 16:59:03 +00:00
// ---------------------------------
// 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 [ ] =
{
2018-08-28 20:08:47 +00:00
{ 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 } ,
2014-03-15 16:59:03 +00:00
{ IT_CALL | IT_STRING , NULL , " Continue " , M_SelectableClearMenus , 40 } ,
2018-07-02 00:55:01 +00:00
{ IT_CALL | IT_STRING , NULL , " P1 Setup... " , M_SetupMultiPlayer , 48 } , // splitscreen
{ IT_CALL | IT_STRING , NULL , " P2 Setup... " , M_SetupMultiPlayer2 , 56 } , // splitscreen
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2018-07-02 00:55:01 +00:00
{ IT_CALL | IT_STRING , NULL , " P3 Setup... " , M_SetupMultiPlayer3 , 64 } , // splitscreen
{ IT_CALL | IT_STRING , NULL , " P4 Setup... " , M_SetupMultiPlayer4 , 72 } , // splitscreen
2018-01-01 18:11:24 +00:00
# endif
2014-03-15 16:59:03 +00:00
{ IT_STRING | IT_CALL , NULL , " Spectate " , M_ConfirmSpectate , 48 } ,
{ IT_STRING | IT_CALL , NULL , " Enter Game " , M_ConfirmEnterGame , 48 } ,
2018-07-21 15:45:08 +00:00
{ IT_STRING | IT_CALL , NULL , " Cancel Join " , M_ConfirmSpectate , 48 } ,
2014-03-15 16:59:03 +00:00
{ IT_STRING | IT_SUBMENU , NULL , " Switch Team... " , & MISC_ChangeTeamDef , 48 } ,
2018-07-02 00:55:01 +00:00
{ IT_CALL | IT_STRING , NULL , " Player Setup... " , M_SetupMultiPlayer , 56 } , // alone
2014-03-15 16:59:03 +00:00
{ 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
{
2018-08-28 20:08:47 +00:00
mpause_addons = 0 ,
mpause_scramble ,
2014-03-15 16:59:03 +00:00
mpause_switchmap ,
mpause_continue ,
mpause_psetupsplit ,
mpause_psetupsplit2 ,
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2017-12-18 10:56:38 +00:00
mpause_psetupsplit3 ,
mpause_psetupsplit4 ,
2018-01-01 18:11:24 +00:00
# endif
2014-03-15 16:59:03 +00:00
mpause_spectate ,
mpause_entergame ,
2018-07-21 15:45:08 +00:00
mpause_canceljoin ,
2014-03-15 16:59:03 +00:00
mpause_switchteam ,
mpause_psetup ,
mpause_options ,
mpause_title ,
mpause_quit
} mpause_e ;
// ---------------------
// Pause Menu SP Edition
// ---------------------
static menuitem_t SPauseMenu [ ] =
{
// Pandora's Box will be shifted up if both options are available
{ IT_CALL | IT_STRING , NULL , " Pandora's Box... " , M_PandorasBox , 16 } ,
{ IT_CALL | IT_STRING , NULL , " Emblem Hints... " , M_EmblemHints , 24 } ,
{ IT_CALL | IT_STRING , NULL , " Level Select... " , M_LoadGameLevelSelect , 32 } ,
{ 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_pandora = 0 ,
spause_hints ,
spause_levelselect ,
spause_continue ,
spause_retry ,
spause_options ,
spause_title ,
spause_quit
} spause_e ;
// -----------------
// 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 , " Select Team " , & cv_dummyteam , 30 } ,
{ IT_WHITESTRING | IT_CALL , NULL , " Confirm " , M_ConfirmTeamChange , 90 } ,
} ;
static menuitem_t MISC_ChangeLevelMenu [ ] =
{
2018-06-30 15:01:03 +00:00
{ IT_STRING | IT_CVAR , NULL , " Game Type " , & cv_newgametype , 68 } ,
{ IT_STRING | IT_CVAR , NULL , " Level " , & cv_nextmap , 78 } ,
2018-06-30 22:18:13 +00:00
{ IT_WHITESTRING | IT_CALL , NULL , " Change Level " , M_ChangeLevel , 130 } ,
2014-03-15 16:59:03 +00:00
} ;
static menuitem_t MISC_HelpMenu [ ] =
{
2018-09-10 11:39:59 +00:00
{ 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 } ,
2018-09-25 21:33:22 +00:00
{ IT_KEYHANDLER | IT_NOTHING , NULL , " MANUAL12 " , M_HandleImageDef , 1 } ,
{ IT_KEYHANDLER | IT_NOTHING , NULL , " MANUAL99 " , M_HandleImageDef , 0 } ,
2014-03-15 16:59:03 +00:00
} ;
// --------------------------------
// Sky Room and all of its submenus
// --------------------------------
// Prefix: SR_
// Pause Menu Pandora's Box Options
static menuitem_t SR_PandorasBox [ ] =
{
{ IT_STRING | IT_CVAR , NULL , " Rings " , & cv_dummyrings , 20 } ,
{ IT_STRING | IT_CVAR , NULL , " Lives " , & cv_dummylives , 30 } ,
{ IT_STRING | IT_CVAR , NULL , " Continues " , & cv_dummycontinues , 40 } ,
{ IT_STRING | IT_CVAR , NULL , " Gravity " , & cv_gravity , 60 } ,
{ IT_STRING | IT_CVAR , NULL , " Throw Rings " , & cv_ringslinger , 70 } ,
{ IT_STRING | IT_CALL , NULL , " Get All Emeralds " , M_GetAllEmeralds , 90 } ,
{ IT_STRING | IT_CALL , NULL , " Destroy All Robots " , M_DestroyRobots , 100 } ,
{ IT_STRING | IT_CALL , NULL , " Ultimate Cheat " , M_UltimateCheat , 130 } ,
} ;
// Sky Room Custom Unlocks
static menuitem_t SR_MainMenu [ ] =
{
{ IT_STRING | IT_SUBMENU , NULL , " Secrets Checklist " , & SR_UnlockChecklistDef , 0 } ,
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom1
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom2
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom3
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom4
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom5
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom6
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom7
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom8
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom9
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom10
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom11
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom12
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom13
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom14
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom15
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom16
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom17
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom18
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom19
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom20
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom21
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom22
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom23
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom24
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom25
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom26
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom27
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom28
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom29
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom30
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom31
{ IT_DISABLED , NULL , " " , NULL , 0 } , // Custom32
} ;
static menuitem_t SR_LevelSelectMenu [ ] =
{
2018-06-30 15:01:03 +00:00
{ IT_STRING | IT_CVAR , NULL , " Level " , & cv_nextmap , 78 } ,
{ IT_WHITESTRING | IT_CALL , NULL , " Start " , M_LevelSelectWarp , 130 } ,
2014-03-15 16:59:03 +00:00
} ;
static menuitem_t SR_UnlockChecklistMenu [ ] =
{
2018-03-04 23:57:34 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " NEXT " , & MainDef , 192 } ,
2014-03-15 16:59:03 +00:00
} ;
static menuitem_t SR_EmblemHintMenu [ ] =
{
{ IT_STRING | IT_CVAR , NULL , " Emblem Radar " , & cv_itemfinder , 10 } ,
{ IT_WHITESTRING | IT_SUBMENU , NULL , " Back " , & SPauseDef , 20 }
} ;
// --------------------------------
// 1 Player and all of its submenus
// --------------------------------
// Prefix: SP_
// Single Player Main
static menuitem_t SP_MainMenu [ ] =
{
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
//{IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 92},
2014-03-15 16:59:03 +00:00
{ IT_SECRET , NULL , " Record Attack " , M_TimeAttack , 100 } ,
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
//{IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 108},
{ IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED , NULL , " Statistics " , M_Statistics , 108 } ,
2014-03-15 16:59:03 +00:00
} ;
enum
{
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
//sploadgame,
2014-03-15 16:59:03 +00:00
sprecordattack ,
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
//spnightsmode,
2014-03-15 16:59:03 +00:00
spstatistics
} ;
// Single Player Load Game
static menuitem_t SP_LoadGameMenu [ ] =
{
{ IT_KEYHANDLER | IT_NOTHING , NULL , " " , M_HandleLoadSave , ' \0 ' } , // dummy menuitem for the control func
} ;
// Single Player Level Select
static menuitem_t SP_LevelSelectMenu [ ] =
{
2018-06-30 15:01:03 +00:00
{ IT_STRING | IT_CVAR , NULL , " Level " , & cv_nextmap , 78 } ,
{ IT_WHITESTRING | IT_CALL , NULL , " Start " , M_LevelSelectWarp , 130 } ,
2014-03-15 16:59:03 +00:00
} ;
// Single Player Time Attack
static menuitem_t SP_TimeAttackMenu [ ] =
{
2018-07-02 00:55:01 +00:00
{ IT_STRING | IT_CVAR | IT_CV_STRING , NULL , " Name " , & cv_playername , 0 } ,
2018-07-12 14:45:00 +00:00
{ IT_STRING | IT_CVAR , NULL , " Character " , & cv_chooseskin , 13 } ,
2018-07-02 00:55:01 +00:00
{ IT_STRING | IT_CVAR , NULL , " Color " , & cv_playercolor , 26 } ,
{ IT_STRING | IT_CVAR , NULL , " Level " , & cv_nextmap , 78 } ,
2014-03-15 16:59:03 +00:00
2018-07-02 00:55:01 +00:00
{ IT_DISABLED , NULL , " Guest... " , & SP_GuestReplayDef , 98 } ,
{ IT_DISABLED , NULL , " Replay... " , & SP_ReplayDef , 108 } ,
2018-07-06 17:08:35 +00:00
{ IT_WHITESTRING | IT_SUBMENU , NULL , " Ghosts... " , & SP_GhostDef , 118 } ,
2018-07-01 18:29:13 +00:00
{ IT_WHITESTRING | IT_CALL | IT_CALL_NOTMODIFIED , NULL , " Start " , M_ChooseTimeAttack , 130 } ,
2014-03-15 16:59:03 +00:00
} ;
enum
{
2018-07-02 00:55:01 +00:00
taname ,
2014-03-15 16:59:03 +00:00
taplayer ,
2017-10-21 02:01:07 +00:00
tacolor ,
2018-07-02 00:55:01 +00:00
talevel ,
2014-03-15 16:59:03 +00:00
taguest ,
tareplay ,
taghost ,
tastart
} ;
static menuitem_t SP_ReplayMenu [ ] =
{
2018-07-02 00:55:01 +00:00
{ IT_WHITESTRING | IT_CALL , NULL , " Replay Best Time " , M_ReplayTimeAttack , 90 } ,
{ IT_WHITESTRING | IT_CALL , NULL , " Replay Best Lap " , M_ReplayTimeAttack , 98 } ,
2014-03-15 16:59:03 +00:00
2018-07-02 00:55:01 +00:00
{ 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 } ,
2014-03-15 16:59:03 +00:00
2018-07-02 00:55:01 +00:00
{ IT_WHITESTRING | IT_SUBMENU , NULL , " Back " , & SP_TimeAttackDef , 130 }
2014-03-15 16:59:03 +00:00
} ;
2018-01-22 00:15:26 +00:00
/*static menuitem_t SP_NightsReplayMenu[] =
2014-11-12 00:55:07 +00:00
{
2017-10-21 02:01:07 +00:00
{ IT_WHITESTRING | IT_CALL , NULL , " Replay Best Score " , M_ReplayTimeAttack , 0 } ,
2014-11-12 00:55:07 +00:00
{ IT_WHITESTRING | IT_CALL , NULL , " Replay Best Time " , M_ReplayTimeAttack , 16 } ,
2017-10-21 02:01:07 +00:00
{ IT_WHITESTRING | IT_CALL , NULL , " Replay Last " , M_ReplayTimeAttack , 21 } ,
{ IT_WHITESTRING | IT_CALL , NULL , " Replay Guest " , M_ReplayTimeAttack , 29 } ,
{ IT_WHITESTRING | IT_KEYHANDLER , NULL , " Replay Staff " , M_HandleStaffReplay , 37 } ,
2014-11-12 00:55:07 +00:00
{ IT_WHITESTRING | IT_SUBMENU , NULL , " Back " , & SP_NightsAttackDef , 50 }
2018-01-22 00:15:26 +00:00
} ; */
2014-11-12 00:55:07 +00:00
2014-03-15 16:59:03 +00:00
static menuitem_t SP_GuestReplayMenu [ ] =
{
2018-07-02 00:55:01 +00:00
{ 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 } ,
2014-03-15 16:59:03 +00:00
2018-07-02 00:55:01 +00:00
{ IT_WHITESTRING | IT_CALL , NULL , " Delete Guest Replay " , M_SetGuestReplay , 120 } ,
2014-03-15 16:59:03 +00:00
2018-07-02 00:55:01 +00:00
{ IT_WHITESTRING | IT_SUBMENU , NULL , " Back " , & SP_TimeAttackDef , 130 }
2014-03-15 16:59:03 +00:00
} ;
2018-01-22 00:15:26 +00:00
/*static menuitem_t SP_NightsGuestReplayMenu[] =
2014-11-12 00:55:07 +00:00
{
{ IT_WHITESTRING | IT_CALL , NULL , " Save Best Score as Guest " , M_SetGuestReplay , 8 } ,
{ IT_WHITESTRING | IT_CALL , NULL , " Save Best Time as Guest " , M_SetGuestReplay , 16 } ,
{ IT_WHITESTRING | IT_CALL , NULL , " Save Last as Guest " , M_SetGuestReplay , 24 } ,
{ IT_WHITESTRING | IT_CALL , NULL , " Delete Guest Replay " , M_SetGuestReplay , 37 } ,
{ IT_WHITESTRING | IT_SUBMENU , NULL , " Back " , & SP_NightsAttackDef , 50 }
2018-01-22 00:15:26 +00:00
} ; */
2014-11-12 00:55:07 +00:00
2014-03-15 16:59:03 +00:00
static menuitem_t SP_GhostMenu [ ] =
{
2018-07-02 00:55:01 +00:00
{ 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 } ,
2018-07-06 17:08:35 +00:00
{ IT_DISABLED , NULL , " Guest " , & cv_ghost_guest , 112 } ,
{ IT_DISABLED , NULL , " Staff Attack " , & cv_ghost_staff , 120 } ,
2014-03-15 16:59:03 +00:00
2018-07-02 00:55:01 +00:00
{ IT_WHITESTRING | IT_SUBMENU , NULL , " Back " , & SP_TimeAttackDef , 130 }
2014-03-15 16:59:03 +00:00
} ;
2018-01-22 00:15:26 +00:00
/*static menuitem_t SP_NightsGhostMenu[] =
2014-11-12 00:55:07 +00:00
{
2017-10-18 03:14:51 +00:00
{ IT_STRING | IT_CVAR , NULL , " Best Score " , & cv_ghost_bestscore , 0 } ,
{ IT_STRING | IT_CVAR , NULL , " Best Time " , & cv_ghost_besttime , 8 } ,
{ IT_STRING | IT_CVAR , NULL , " Last " , & cv_ghost_last , 16 } ,
2014-11-12 00:55:07 +00:00
2017-10-18 03:14:51 +00:00
{ IT_STRING | IT_CVAR , NULL , " Guest " , & cv_ghost_guest , 29 } ,
{ IT_STRING | IT_CVAR , NULL , " Staff Attack " , & cv_ghost_staff , 37 } ,
2014-11-12 00:55:07 +00:00
2017-10-21 02:01:07 +00:00
{ IT_WHITESTRING | IT_SUBMENU , NULL , " Back " , & SP_NightsAttackDef , 50 }
2018-01-22 00:15:26 +00:00
} ; */
2014-11-12 00:55:07 +00:00
2014-03-15 16:59:03 +00:00
// Single Player Nights Attack
2018-01-22 00:15:26 +00:00
/*static menuitem_t SP_NightsAttackMenu[] =
2014-03-15 16:59:03 +00:00
{
{ IT_STRING | IT_CVAR , NULL , " Level " , & cv_nextmap , 44 } ,
2014-11-12 00:55:07 +00:00
{ IT_STRING | IT_CVAR , NULL , " Show Records For " , & cv_dummymares , 54 } ,
{ IT_DISABLED , NULL , " Guest Option... " , & SP_NightsGuestReplayDef , 108 } ,
{ IT_DISABLED , NULL , " Replay... " , & SP_NightsReplayDef , 118 } ,
{ IT_DISABLED , NULL , " Ghosts... " , & SP_NightsGhostDef , 128 } ,
2016-08-20 05:18:43 +00:00
{ IT_WHITESTRING | IT_CALL | IT_CALL_NOTMODIFIED , NULL , " Start " , M_ChooseNightsAttack , 138 } ,
2018-01-22 00:15:26 +00:00
} ; */
2014-03-15 16:59:03 +00:00
enum
{
nalevel ,
narecords ,
2014-11-12 00:55:07 +00:00
naguest ,
nareplay ,
naghost ,
2014-03-15 16:59:03 +00:00
nastart
} ;
// Statistics
static menuitem_t SP_LevelStatsMenu [ ] =
{
{ IT_KEYHANDLER | IT_NOTHING , NULL , " " , M_HandleLevelStats , ' \0 ' } , // dummy menuitem for the control func
} ;
// 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!
menuitem_t PlayerMenu [ 32 ] =
{
{ IT_CALL , NULL , NULL , M_ChoosePlayer , 0 } ,
2017-10-18 03:14:51 +00:00
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
2014-03-15 16:59:03 +00:00
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 } ,
{ IT_DISABLED , NULL , NULL , M_ChoosePlayer , 0 }
} ;
// -----------------------------------
// Multiplayer and all of its submenus
// -----------------------------------
// Prefix: MP_
2018-01-01 18:11:24 +00:00
2018-07-06 17:08:35 +00:00
# ifndef NONET
2017-12-17 03:32:43 +00:00
2018-06-30 15:01:03 +00:00
static menuitem_t MP_MainMenu [ ] =
{
2018-07-06 17:08:35 +00:00
{ IT_HEADER , NULL , " Host a game " , NULL , 0 } ,
{ IT_STRING | IT_CALL , NULL , " Internet/LAN... " , M_StartServerMenu , 10 } ,
{ IT_STRING | IT_CALL , NULL , " Splitscreen... " , M_StartSplitServerMenu , 18 } ,
{ IT_HEADER , NULL , " Join a game " , NULL , 32 } ,
{ IT_STRING | IT_CALL , NULL , " Server browser... " , M_ConnectMenu , 42 } ,
{ IT_STRING | IT_KEYHANDLER , NULL , " Specify IPv4 address: " , M_HandleConnectIP , 50 } ,
{ IT_HEADER , NULL , " Player setup " , NULL , 80 } ,
{ IT_STRING | IT_CALL , NULL , " Name, character, color... " , M_SetupMultiPlayer , 90 } ,
2014-03-15 16:59:03 +00:00
} ;
2018-06-30 15:01:03 +00:00
# endif
2014-03-15 16:59:03 +00:00
static menuitem_t MP_ServerMenu [ ] =
{
2018-08-15 14:22:50 +00:00
{ IT_STRING | IT_CVAR , NULL , " Max. Player Count " , & cv_maxplayers , 10 } ,
2014-03-15 16:59:03 +00:00
# ifndef NONET
2018-06-30 15:01:03 +00:00
{ IT_STRING | IT_CALL , NULL , " Room... " , M_RoomMenu , 20 } ,
{ IT_STRING | IT_CVAR | IT_CV_STRING , NULL , " Server Name " , & cv_servername , 30 } ,
2014-03-15 16:59:03 +00:00
# endif
2018-08-15 14:22:50 +00:00
{ IT_STRING | IT_CVAR , NULL , " Game Type " , & cv_newgametype , 68 } ,
2018-06-30 15:01:03 +00:00
{ IT_STRING | IT_CVAR , NULL , " Level " , & cv_nextmap , 78 } ,
2014-03-15 16:59:03 +00:00
2018-06-30 15:01:03 +00:00
{ IT_WHITESTRING | IT_CALL , NULL , " Start " , M_StartServer , 130 } ,
2014-03-15 16:59:03 +00:00
} ;
2018-06-30 15:01:03 +00:00
// Separated splitscreen and normal servers.
static menuitem_t MP_SplitServerMenu [ ] =
2014-03-15 16:59:03 +00:00
{
2018-06-30 15:01:03 +00:00
# ifndef NOFOURPLAYER
2018-08-15 14:22:50 +00:00
{ IT_STRING | IT_CVAR , NULL , " Number of players " , & cv_dummysplitplayers , 10 } ,
2014-03-15 16:59:03 +00:00
# endif
2018-08-15 14:22:50 +00:00
{ IT_STRING | IT_CVAR , NULL , " Game Type " , & cv_newgametype , 68 } ,
2018-06-30 15:01:03 +00:00
{ IT_STRING | IT_CVAR , NULL , " Level " , & cv_nextmap , 78 } ,
2018-06-30 22:18:13 +00:00
# ifdef NOFOURPLAYER
2018-08-15 14:22:50 +00:00
{ IT_STRING | IT_CALL , NULL , " P1 Setup... " , M_SetupMultiPlayer , 110 } ,
{ IT_STRING | IT_CALL , NULL , " P2 Setup... " , M_SetupMultiPlayer2 , 120 } ,
2018-06-30 22:18:13 +00:00
# else
2018-08-15 14:22:50 +00:00
{ IT_STRING | IT_CALL , NULL , " P1 Setup... " , M_SetupMultiPlayer , 90 } ,
{ IT_STRING | IT_CALL , NULL , " P2 Setup... " , M_SetupMultiPlayer2 , 100 } ,
{ IT_GRAYEDOUT , NULL , " P3 Setup... " , M_SetupMultiPlayer3 , 110 } ,
{ IT_GRAYEDOUT , NULL , " P4 Setup... " , M_SetupMultiPlayer4 , 120 } ,
2018-06-30 22:18:13 +00:00
# endif
2018-06-30 15:01:03 +00:00
{ IT_WHITESTRING | IT_CALL , NULL , " Start " , M_StartServer , 130 } ,
} ;
2018-06-30 22:18:13 +00:00
# ifndef NOFOURPLAYER
static void Dummysplitplayers_OnChange ( void )
{
UINT8 i = 2 ; // player 2 is the last unchanging setup
2018-07-02 12:20:04 +00:00
while ( i < 4 )
2018-06-30 22:18:13 +00:00
{
2018-07-02 12:20:04 +00:00
if ( i < cv_dummysplitplayers . value )
MP_SplitServerMenu [ 3 + i ] . status = IT_STRING | IT_CALL ;
2018-06-30 22:18:13 +00:00
else
2018-07-02 12:20:04 +00:00
MP_SplitServerMenu [ 3 + i ] . status = IT_GRAYEDOUT ;
i + + ;
2018-06-30 22:18:13 +00:00
}
}
# endif
2018-06-30 15:01:03 +00:00
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 } ,
2014-03-15 16:59:03 +00:00
} ;
# 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 , " <Offline Mode> " , 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 [ ] =
{
2018-06-15 00:18:29 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Control Setup... " , & OP_ControlsDef , 10 } ,
2014-03-15 16:59:03 +00:00
2018-06-15 00:18:29 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Video Options... " , & OP_VideoOptionsDef , 30 } ,
{ IT_SUBMENU | IT_STRING , NULL , " Sound Options... " , & OP_SoundOptionsDef , 40 } ,
2014-03-15 16:59:03 +00:00
2018-08-02 22:52:07 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " HUD Options... " , & OP_HUDOptionsDef , 60 } ,
2018-06-15 00:18:29 +00:00
{ IT_STRING | IT_CALL , NULL , " Screenshot Options... " , M_ScreenshotOptions , 70 } ,
2018-03-02 00:00:16 +00:00
2018-06-15 00:18:29 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Gameplay Options... " , & OP_GameOptionsDef , 90 } ,
{ IT_SUBMENU | IT_STRING , NULL , " Server Options... " , & OP_ServerOptionsDef , 100 } ,
2018-08-28 20:08:47 +00:00
{ IT_STRING | IT_CALL , NULL , " Add-on Options... " , M_AddonsOptions , 110 } ,
2018-06-15 00:18:29 +00:00
2018-09-22 22:00:46 +00:00
{ IT_CALL | IT_STRING , NULL , " Tricks & Secrets (F1) " , M_Manual , 130 } ,
{ IT_CALL | IT_STRING , NULL , " Play Credits " , M_Credits , 140 } ,
{ IT_SUBMENU | IT_STRING , NULL , " Erase Data... " , & OP_EraseDataDef , 150 } ,
2014-03-15 16:59:03 +00:00
} ;
static menuitem_t OP_ControlsMenu [ ] =
{
2018-06-30 15:01:03 +00:00
{ IT_CALL | IT_STRING , NULL , " Player 1 Controls... " , M_Setup1PControlsMenu , 10 } ,
{ IT_CALL | IT_STRING , NULL , " Player 2 Controls... " , M_Setup2PControlsMenu , 20 } ,
2018-01-01 18:11:24 +00:00
# ifdef NOFOURPLAYER
{ IT_STRING | IT_CVAR , NULL , " Controls per key " , & cv_controlperkey , 40 } ,
# else
2018-06-30 15:01:03 +00:00
{ IT_CALL | IT_STRING , NULL , " Player 3 Controls... " , & M_Setup3PControlsMenu , 30 } ,
{ IT_CALL | IT_STRING , NULL , " Player 4 Controls... " , & M_Setup4PControlsMenu , 40 } ,
2014-03-15 16:59:03 +00:00
2017-12-08 07:29:01 +00:00
{ IT_STRING | IT_CVAR , NULL , " Controls per key " , & cv_controlperkey , 60 } ,
2018-01-01 18:11:24 +00:00
# endif
2014-03-15 16:59:03 +00:00
} ;
static menuitem_t OP_MoveControlsMenu [ ] =
{
2018-06-30 15:01:03 +00:00
{ 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_SPACE , NULL , " " , NULL , 76 } ,
{ IT_CONTROL , NULL , " Talk key " , M_ChangeControl , gc_talkkey } ,
//{IT_CONTROL, NULL, "Team-Talk key", M_ChangeControl, gc_teamkey },
{ IT_CONTROL , NULL , " Rankings/Scores " , M_ChangeControl , gc_scores } ,
2018-09-10 01:50:33 +00:00
{ IT_CONTROL , NULL , " Open/Close Menu (ESC) " , M_ChangeControl , gc_systemmenu } ,
2018-06-30 15:01:03 +00:00
{ IT_CONTROL , NULL , " Pause " , M_ChangeControl , gc_pause } ,
{ IT_CONTROL , NULL , " Console " , M_ChangeControl , gc_console } ,
2018-09-10 01:50:33 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Gamepad Options... " , & OP_Joystick1Def , 120 } ,
{ IT_SUBMENU | IT_STRING , NULL , " Spectator Controls... " , & OP_SpectateControlsDef , 128 } ,
{ IT_SUBMENU | IT_STRING , NULL , " Custom Lua Actions... " , & OP_CustomControlsDef , 136 } ,
2018-01-24 21:53:20 +00:00
} ;
static menuitem_t OP_SpectateControlsMenu [ ] =
{
2018-06-30 15:01:03 +00:00
{ 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_CONTROL , NULL , " Reset Camera " , M_ChangeControl , gc_camreset } ,
{ IT_CONTROL , NULL , " Toggle Chasecam " , M_ChangeControl , gc_camtoggle } ,
{ IT_STRING | IT_CVAR , NULL , " Chasecam " , & cv_chasecam , 52 } ,
{ IT_STRING | IT_CVAR , NULL , " Crosshair " , & cv_crosshair , 60 } ,
2014-03-15 16:59:03 +00:00
} ;
2017-12-04 01:00:31 +00:00
static menuitem_t OP_CustomControlsMenu [ ] =
{
2018-06-30 15:01:03 +00:00
{ 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 } ,
2017-12-04 01:00:31 +00:00
} ;
2017-10-26 06:43:02 +00:00
// Obsolete thanks to Kart
/*static menuitem_t OP_MPControlsMenu[] =
2014-03-15 16:59:03 +00:00
{
2016-08-21 02:15:06 +00:00
// {IT_CALL | IT_STRING2, NULL, "Next Weapon", M_ChangeControl, gc_driftleft },
// {IT_CALL | IT_STRING2, NULL, "Prev Weapon", M_ChangeControl, gc_driftright },
// {IT_CALL | IT_STRING2, NULL, "Weapon Slot 1", M_ChangeControl, gc_wepslot1 },
// {IT_CALL | IT_STRING2, NULL, "Weapon Slot 2", M_ChangeControl, gc_wepslot2 },
// {IT_CALL | IT_STRING2, NULL, "Weapon Slot 3", M_ChangeControl, gc_wepslot3 },
// {IT_CALL | IT_STRING2, NULL, "Weapon Slot 4", M_ChangeControl, gc_wepslot4 },
// {IT_CALL | IT_STRING2, NULL, "Weapon Slot 5", M_ChangeControl, gc_wepslot5 },
// {IT_CALL | IT_STRING2, NULL, "Weapon Slot 6", M_ChangeControl, gc_wepslot6 },
// {IT_CALL | IT_STRING2, NULL, "Weapon Slot 7", M_ChangeControl, gc_wepslot7 },
2017-12-04 01:00:31 +00:00
} ;
2014-03-15 16:59:03 +00:00
static menuitem_t OP_CameraControlsMenu [ ] =
{
2016-08-21 02:15:06 +00:00
// {IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, gc_lookup },
// {IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, gc_lookdown },
// {IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, gc_centerview },
// {IT_CALL | IT_STRING2, NULL, "Mouselook", M_ChangeControl, gc_mouseaiming },
2014-03-15 16:59:03 +00:00
} ;
static menuitem_t OP_MiscControlsMenu [ ] =
{
2014-03-23 16:00:29 +00:00
{ IT_CALL | IT_STRING2 , NULL , " Custom Action 1 " , M_ChangeControl , gc_custom1 } ,
{ IT_CALL | IT_STRING2 , NULL , " Custom Action 2 " , M_ChangeControl , gc_custom2 } ,
{ IT_CALL | IT_STRING2 , NULL , " Custom Action 3 " , M_ChangeControl , gc_custom3 } ,
2014-03-15 16:59:03 +00:00
{ IT_CALL | IT_STRING2 , NULL , " Pause " , M_ChangeControl , gc_pause } ,
{ IT_CALL | IT_STRING2 , NULL , " Console " , M_ChangeControl , gc_console } ,
2017-10-26 06:43:02 +00:00
{ IT_CALL | IT_STRING2 , NULL , " Talk key " , M_ChangeControl , gc_talkkey } ,
{ IT_CALL | IT_STRING2 , NULL , " Team-Talk key " , M_ChangeControl , gc_teamkey } ,
{ IT_CALL | IT_STRING2 , NULL , " Rankings/Scores " , M_ChangeControl , gc_scores } ,
{ IT_CALL | IT_STRING2 , NULL , " Spectate " , M_ChangeControl , gc_spectate } ,
2017-12-04 01:00:31 +00:00
} ; */
2014-03-15 16:59:03 +00:00
static menuitem_t OP_Joystick1Menu [ ] =
{
2018-06-30 15:01:03 +00:00
{ IT_STRING | IT_CALL , NULL , " Select Gamepad... " , M_Setup1PJoystickMenu , 10 } ,
2018-03-11 22:07:28 +00:00
{ 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 } ,
2014-03-15 16:59:03 +00:00
} ;
static menuitem_t OP_Joystick2Menu [ ] =
{
2018-06-30 15:01:03 +00:00
{ IT_STRING | IT_CALL , NULL , " Select Gamepad... " , M_Setup2PJoystickMenu , 10 } ,
2018-03-11 22:07:28 +00:00
{ 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 } ,
2014-03-15 16:59:03 +00:00
} ;
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2017-12-08 07:29:01 +00:00
static menuitem_t OP_Joystick3Menu [ ] =
{
2018-06-30 15:01:03 +00:00
{ IT_STRING | IT_CALL , NULL , " Select Gamepad... " , M_Setup3PJoystickMenu , 10 } ,
2018-03-11 22:07:28 +00:00
{ 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 } ,
2017-12-08 07:29:01 +00:00
} ;
static menuitem_t OP_Joystick4Menu [ ] =
{
2018-06-30 15:01:03 +00:00
{ IT_STRING | IT_CALL , NULL , " Select Gamepad... " , M_Setup4PJoystickMenu , 10 } ,
2018-03-11 22:07:28 +00:00
{ 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 } ,
2017-12-08 07:29:01 +00:00
} ;
2018-01-01 18:11:24 +00:00
# endif
2017-12-08 07:29:01 +00:00
2014-03-15 16:59:03 +00:00
static menuitem_t OP_JoystickSetMenu [ ] =
{
2018-07-03 20:18:17 +00:00
{ 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 } ,
2014-03-15 16:59:03 +00:00
} ;
2018-06-30 15:01:03 +00:00
/*static menuitem_t OP_MouseOptionsMenu[] =
2014-03-15 16:59:03 +00:00
{
{ IT_STRING | IT_CVAR , NULL , " Use Mouse " , & cv_usemouse , 10 } ,
{ IT_STRING | IT_CVAR , NULL , " Always MouseLook " , & cv_alwaysfreelook , 30 } ,
{ IT_STRING | IT_CVAR , NULL , " Mouse Move " , & cv_mousemove , 40 } ,
{ IT_STRING | IT_CVAR , NULL , " Invert Mouse " , & cv_invertmouse , 50 } ,
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2015-01-01 19:50:31 +00:00
NULL , " Mouse X Speed " , & cv_mousesens , 60 } ,
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
NULL , " Mouse Y Speed " , & cv_mouseysens , 70 } ,
2014-03-15 16:59:03 +00:00
} ;
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 , " Always MouseLook " , & cv_alwaysfreelook2 , 30 } ,
{ IT_STRING | IT_CVAR , NULL , " Mouse Move " , & cv_mousemove2 , 40 } ,
2015-01-01 19:50:31 +00:00
{ IT_STRING | IT_CVAR , NULL , " Invert Mouse " , & cv_invertmouse2 , 50 } ,
2014-03-15 16:59:03 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2015-01-01 19:50:31 +00:00
NULL , " Mouse X Speed " , & cv_mousesens2 , 60 } ,
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
NULL , " Mouse Y Speed " , & cv_mouseysens2 , 70 } ,
2018-06-30 15:01:03 +00:00
} ; */
2014-03-15 16:59:03 +00:00
static menuitem_t OP_VideoOptionsMenu [ ] =
{
2018-06-30 22:18:13 +00:00
{ IT_STRING | IT_CALL , NULL , " Set Resolution... " , M_VideoModeMenu , 10 } ,
2014-07-25 23:10:24 +00:00
# if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
2018-08-05 15:34:51 +00:00
{ IT_STRING | IT_CVAR , NULL , " Fullscreen " , & cv_fullscreen , 20 } ,
2014-03-15 16:59:03 +00:00
# endif
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-08-05 15:34:51 +00:00
NULL , " Gamma " , & cv_usegamma , 30 } ,
2018-08-09 21:59:52 +00:00
{ 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 , 75 } ,
2018-06-15 00:18:29 +00:00
2018-08-09 21:59:52 +00:00
{ IT_STRING | IT_CVAR , NULL , " Show FPS " , & cv_ticrate , 90 } ,
{ IT_STRING | IT_CVAR , NULL , " Vertical Sync " , & cv_vidwait , 100 } ,
2018-08-05 15:34:51 +00:00
# ifdef HWRENDER
2018-08-09 21:59:52 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " OpenGL Options... " , & OP_OpenGLOptionsDef , 115 } ,
2018-08-05 15:34:51 +00:00
# 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_fps ,
op_video_vsync ,
# ifdef HWRENDER
op_video_ogl ,
# endif
2014-03-15 16:59:03 +00:00
} ;
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 [ ] =
{
2018-06-15 00:18:29 +00:00
{ IT_STRING | IT_CVAR , NULL , " Field of View " , & cv_grfov , 10 } ,
2014-03-15 16:59:03 +00:00
{ IT_STRING | IT_CVAR , NULL , " Quality " , & cv_scr_depth , 20 } ,
{ IT_STRING | IT_CVAR , NULL , " Texture Filter " , & cv_grfiltermode , 30 } ,
{ IT_STRING | IT_CVAR , NULL , " Anisotropic " , & cv_granisotropicmode , 40 } ,
# 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
{ IT_SUBMENU | IT_STRING , NULL , " Fog... " , & OP_OpenGLFogDef , 80 } ,
{ IT_SUBMENU | IT_STRING , NULL , " Gamma... " , & OP_OpenGLColorDef , 90 } ,
} ;
# 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 } ,
2018-06-15 00:18:29 +00:00
{ IT_STRING | IT_KEYHANDLER , NULL , " Fog Color " , M_HandleFogColor , 20 } ,
{ IT_STRING | IT_CVAR , NULL , " Fog Density " , & cv_grfogdensity , 30 } ,
2014-03-15 16:59:03 +00:00
{ IT_STRING | IT_CVAR , NULL , " Software Fog " , & cv_grsoftwarefog , 40 } ,
} ;
static menuitem_t OP_OpenGLColorMenu [ ] =
{
2018-06-15 00:18:29 +00:00
{ 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 } ,
2014-03-15 16:59:03 +00:00
} ;
# endif
static menuitem_t OP_SoundOptionsMenu [ ] =
{
2018-06-30 22:18:13 +00:00
{ IT_KEYHANDLER | IT_STRING , NULL , " SFX " , M_ToggleSFX , 10 } ,
2018-06-15 00:18:29 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-06-30 22:18:13 +00:00
NULL , " SFX Volume " , & cv_soundvolume , 18 } ,
{ IT_KEYHANDLER | IT_STRING , NULL , " Music " , M_ToggleDigital , 30 } ,
2018-06-15 00:18:29 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-06-30 22:18:13 +00:00
NULL , " Music Volume " , & cv_digmusicvolume , 38 } ,
/* -- :nonnathisshit:
{ IT_KEYHANDLER | IT_STRING , NULL , " MIDI " , M_ToggleMIDI , 50 } ,
2018-06-15 00:18:29 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-06-30 22:18:13 +00:00
NULL , " MIDI Volume " , & cv_midimusicvolume , 58 } ,
2014-03-15 16:59:03 +00:00
# ifdef PC_DOS
2018-06-15 00:18:29 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
NULL , " CD Volume " , & cd_volume , 40 } ,
2018-06-30 22:18:13 +00:00
# endif* /
{ IT_STRING | IT_CALL , NULL , " Restart Audio System " , M_RestartAudio , 50 } ,
2018-08-02 22:52:07 +00:00
{ IT_STRING | IT_CVAR , NULL , " Reverse L/R Channels " , & stereoreverse , 65 } ,
{ IT_STRING | IT_CVAR , NULL , " Surround Sound " , & surround , 75 } ,
2018-06-15 00:18:29 +00:00
2018-08-02 22:52:07 +00:00
{ IT_STRING | IT_CVAR , NULL , " Chat sounds " , & cv_chatnotifications , 90 } ,
2018-07-29 17:35:56 +00:00
{ IT_STRING | IT_CVAR , NULL , " Character voices " , & cv_kartvoices , 100 } ,
{ IT_STRING | IT_CVAR , NULL , " Powerup Warning " , & cv_kartinvinsfx , 110 } ,
2014-03-15 16:59:03 +00:00
2018-08-02 22:52:07 +00:00
{ IT_KEYHANDLER | IT_STRING , NULL , " Sound Test " , M_HandleSoundTest , 125 } ,
2014-03-15 16:59:03 +00:00
} ;
2018-06-15 00:18:29 +00:00
/*static menuitem_t OP_DataOptionsMenu[] =
2014-03-15 16:59:03 +00:00
{
{ IT_STRING | IT_CALL , NULL , " Screenshot Options... " , M_ScreenshotOptions , 10 } ,
{ IT_STRING | IT_SUBMENU , NULL , " Erase Data... " , & OP_EraseDataDef , 30 } ,
2018-06-15 00:18:29 +00:00
} ; */
2014-03-15 16:59:03 +00:00
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 } ,
2018-06-15 00:18:29 +00:00
{ IT_STRING | IT_CALL , NULL , " Erase Unlockable Data " , M_EraseData , 20 } ,
2014-03-15 16:59:03 +00:00
{ IT_STRING | IT_CALL , NULL , " \x85 " " Erase ALL Data " , M_EraseData , 40 } ,
} ;
2018-08-28 20:08:47 +00:00
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 ,
} ;
2018-06-15 00:18:29 +00:00
static menuitem_t OP_HUDOptionsMenu [ ] =
2014-03-15 16:59:03 +00:00
{
2018-08-02 22:52:07 +00:00
{ IT_STRING | IT_CVAR , NULL , " Show HUD (F3) " , & cv_showhud , 10 } ,
2014-03-21 18:42:55 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-06-15 00:18:29 +00:00
NULL , " HUD Visibility " , & cv_translucenthud , 20 } ,
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
2018-08-09 21:59:52 +00:00
{ IT_STRING | IT_SUBMENU , NULL , " Online chat options... " , & OP_ChatOptionsDef , 35 } ,
{ IT_STRING | IT_CVAR , NULL , " Background Glass " , & cons_backcolor , 45 } ,
2018-02-08 03:33:27 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-08-09 21:59:52 +00:00
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 } ,
} ;
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
2018-08-09 21:59:52 +00:00
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...
2018-08-02 22:52:07 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-08-09 21:59:52 +00:00
NULL , " Window width " , & cv_chatwidth , 25 } ,
2018-08-02 22:52:07 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-08-09 21:59:52 +00:00
NULL , " Window height " , & cv_chatheight , 35 } ,
{ IT_STRING | IT_CVAR , NULL , " Message fadeout time " , & cv_chattime , 50 } ,
{ IT_STRING | IT_CVAR , NULL , " Show tint behind messages " , & cv_chatbacktint , 60 } ,
2018-06-15 00:18:29 +00:00
} ;
static menuitem_t OP_GameOptionsMenu [ ] =
{
{ IT_STRING | IT_SUBMENU , NULL , " Random Item Toggles... " , & OP_MonitorToggleDef , 10 } ,
2014-03-15 16:59:03 +00:00
2018-06-15 00:18:29 +00:00
{ IT_STRING | IT_CVAR , NULL , " Game Speed " , & cv_kartspeed , 30 } ,
{ IT_STRING | IT_CVAR , NULL , " Frantic Items " , & cv_kartfrantic , 40 } ,
2018-08-08 19:48:29 +00:00
{ IT_SECRET , NULL , " Encore Mode " , & cv_kartencore , 50 } ,
2014-03-15 16:59:03 +00:00
2018-06-29 16:49:02 +00:00
{ IT_STRING | IT_CVAR , NULL , " Number of Laps " , & cv_basenumlaps , 70 } ,
{ IT_STRING | IT_CVAR , NULL , " Exit Countdown Timer " , & cv_countdowntime , 80 } ,
2018-06-15 00:18:29 +00:00
2018-06-29 16:49:02 +00:00
//{IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 100},
2018-08-02 22:52:07 +00:00
{ IT_STRING | IT_CVAR , NULL , " Starting Bumpers " , & cv_kartbumpers , 100 } ,
2018-06-29 16:49:02 +00:00
{ IT_STRING | IT_CVAR , NULL , " Karma Comeback " , & cv_kartcomeback , 110 } ,
2018-06-15 00:18:29 +00:00
2018-06-29 16:49:02 +00:00
{ IT_STRING | IT_CVAR , NULL , " Force Character # " , & cv_forceskin , 130 } ,
{ IT_STRING | IT_CVAR , NULL , " Restrict Character Changes " , & cv_restrictskinchange , 140 } ,
2014-03-15 16:59:03 +00:00
} ;
static menuitem_t OP_ServerOptionsMenu [ ] =
{
# ifndef NONET
{ IT_STRING | IT_CVAR | IT_CV_STRING ,
2018-06-15 00:18:29 +00:00
NULL , " Server Name " , & cv_servername , 10 } ,
2014-03-15 16:59:03 +00:00
# endif
2018-06-15 00:18:29 +00:00
{ IT_STRING | IT_CVAR , NULL , " Intermission Timer " , & cv_inttime , 40 } ,
2018-08-05 15:34:51 +00:00
{ IT_STRING | IT_CVAR , NULL , " Map Progression " , & cv_advancemap , 50 } ,
{ IT_STRING | IT_CVAR , NULL , " Voting Timer " , & cv_votetime , 60 } ,
Do a bunch of major modifications to the voting system's rule change system!
* Add `kartvoterulechanges`, or "Voting Rule Changes" on the menu, to allow some user control over event frequency.
* "Never" - does what it says on the tin.
* "Sometimes" - 1/8 chance of Encore if host has unlocked it, only gametype change when buffer is full
* "Frequent" - 1/2 chance of Encore if host has unlocked it, gametype change every 5 maps
* "Always" - If host has unlocked Encore, alternates between Encore and Gametype. Otherwise, always a gametype change
* There's probably room for a setting between "Sometimes" and "Frequent", but I didn't want to overload the host with options and these were the ones that made sense.
* Better handling of buffer refreshes, to prevent two of the same map appearing next to each other in the voting unless there literally aren't that many maps.
* Mostly unrelated: Minor bugfix for Y_SetupVoteFinish, preventing music changes/random sounds playing on the You Will Join Next Race screen. (Branch-appropriate, at least.)
2018-09-11 14:41:41 +00:00
{ IT_STRING | IT_CVAR , NULL , " Voting Rule Changes " , & cv_kartvoterulechanges , 70 } ,
2014-03-15 16:59:03 +00:00
# ifndef NONET
Do a bunch of major modifications to the voting system's rule change system!
* Add `kartvoterulechanges`, or "Voting Rule Changes" on the menu, to allow some user control over event frequency.
* "Never" - does what it says on the tin.
* "Sometimes" - 1/8 chance of Encore if host has unlocked it, only gametype change when buffer is full
* "Frequent" - 1/2 chance of Encore if host has unlocked it, gametype change every 5 maps
* "Always" - If host has unlocked Encore, alternates between Encore and Gametype. Otherwise, always a gametype change
* There's probably room for a setting between "Sometimes" and "Frequent", but I didn't want to overload the host with options and these were the ones that made sense.
* Better handling of buffer refreshes, to prevent two of the same map appearing next to each other in the voting unless there literally aren't that many maps.
* Mostly unrelated: Minor bugfix for Y_SetupVoteFinish, preventing music changes/random sounds playing on the You Will Join Next Race screen. (Branch-appropriate, at least.)
2018-09-11 14:41:41 +00:00
{ 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, "Join on Map Change", &cv_joinnextround, 110},
2018-06-15 00:18:29 +00:00
Do a bunch of major modifications to the voting system's rule change system!
* Add `kartvoterulechanges`, or "Voting Rule Changes" on the menu, to allow some user control over event frequency.
* "Never" - does what it says on the tin.
* "Sometimes" - 1/8 chance of Encore if host has unlocked it, only gametype change when buffer is full
* "Frequent" - 1/2 chance of Encore if host has unlocked it, gametype change every 5 maps
* "Always" - If host has unlocked Encore, alternates between Encore and Gametype. Otherwise, always a gametype change
* There's probably room for a setting between "Sometimes" and "Frequent", but I didn't want to overload the host with options and these were the ones that made sense.
* Better handling of buffer refreshes, to prevent two of the same map appearing next to each other in the voting unless there literally aren't that many maps.
* Mostly unrelated: Minor bugfix for Y_SetupVoteFinish, preventing music changes/random sounds playing on the You Will Join Next Race screen. (Branch-appropriate, at least.)
2018-09-11 14:41:41 +00:00
{ IT_STRING | IT_CVAR , NULL , " Allow WAD Downloading " , & cv_downloading , 110 } ,
{ IT_STRING | IT_CVAR , NULL , " Attempts to resynchronise " , & cv_resynchattempts , 120 } ,
2014-03-15 16:59:03 +00:00
# endif
} ;
2018-06-15 00:18:29 +00:00
/*static menuitem_t OP_NetgameOptionsMenu[] =
2014-03-15 16:59:03 +00:00
{
{ IT_STRING | IT_CVAR , NULL , " Time Limit " , & cv_timelimit , 10 } ,
{ IT_STRING | IT_CVAR , NULL , " Point Limit " , & cv_pointlimit , 18 } ,
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
{ IT_STRING | IT_CVAR , NULL , " Frantic Items " , & cv_kartfrantic , 34 } ,
{ IT_STRING | IT_CVAR , NULL , " Item Respawn " , & cv_itemrespawn , 50 } ,
2018-06-14 03:37:37 +00:00
{ IT_STRING | IT_CVAR , NULL , " Item Respawn Delay " , & cv_itemrespawntime , 58 } ,
2014-03-15 16:59:03 +00:00
2018-06-14 03:37:37 +00:00
{ IT_STRING | IT_CVAR , NULL , " Player Respawn Delay " , & cv_respawntime , 74 } ,
2014-03-15 16:59:03 +00:00
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
{ IT_STRING | IT_CVAR , NULL , " Force Skin # " , & cv_forceskin , 90 } ,
2018-06-14 03:37:37 +00:00
{ IT_STRING | IT_CVAR , NULL , " Restrict Skin Changes " , & cv_restrictskinchange , 98 } ,
2014-03-15 16:59:03 +00:00
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
//{IT_STRING | IT_CVAR, NULL, "Autobalance Teams", &cv_autobalance, 114},
//{IT_STRING | IT_CVAR, NULL, "Scramble Teams on Map Change", &cv_scrambleonchange, 122},
2018-06-15 00:18:29 +00:00
} ; */
2014-03-15 16:59:03 +00:00
2018-06-15 00:18:29 +00:00
/*static menuitem_t OP_GametypeOptionsMenu[] =
2014-03-15 16:59:03 +00:00
{
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
{ IT_HEADER , NULL , " RACE " , NULL , 2 } ,
{ IT_STRING | IT_CVAR , NULL , " Game Speed " , & cv_kartspeed , 10 } ,
2018-07-23 22:50:41 +00:00
{ IT_STRING | IT_CVAR , NULL , " Encore Mode " , & cv_kartencore , 18 } ,
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
{ IT_STRING | IT_CVAR , NULL , " Number of Laps " , & cv_numlaps , 26 } ,
{ IT_STRING | IT_CVAR , NULL , " Use Map Lap Counts " , & cv_usemapnumlaps , 34 } ,
2014-03-15 16:59:03 +00:00
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
{ IT_HEADER , NULL , " BATTLE " , NULL , 50 } ,
2018-07-03 19:14:47 +00:00
{ IT_STRING | IT_CVAR , NULL , " Starting Bumpers " , & cv_kartbumpers , 58 } ,
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
{ IT_STRING | IT_CVAR , NULL , " Karma Comeback " , & cv_kartcomeback , 66 } ,
2018-06-15 00:18:29 +00:00
} ; */
2014-03-15 16:59:03 +00:00
2018-09-08 16:02:03 +00:00
# define ITEMTOGGLEBOTTOMRIGHT
2014-03-15 16:59:03 +00:00
static menuitem_t OP_MonitorToggleMenu [ ] =
{
2018-08-31 17:18:19 +00:00
// Mostly handled by the drawing function.
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
// Instead of using this for dumb monitors, lets use the new item bools we have :V
2018-08-31 17:18:19 +00:00
{ 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 } ,
2018-08-31 18:41:37 +00:00
{ IT_KEYHANDLER | IT_NOTHING , NULL , " Toggle All " , M_HandleMonitorToggles , 0 } ,
2018-08-31 17:18:19 +00:00
{ 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 } ,
2018-09-08 16:02:03 +00:00
{ IT_KEYHANDLER | IT_NOTHING , NULL , " Orbinauts " , M_HandleMonitorToggles , KITEM_ORBINAUT } ,
2018-08-31 17:18:19 +00:00
{ IT_KEYHANDLER | IT_NOTHING , NULL , " Orbinauts x3 " , M_HandleMonitorToggles , KRITEM_TRIPLEORBINAUT } ,
{ IT_KEYHANDLER | IT_NOTHING , NULL , " Orbinauts x4 " , M_HandleMonitorToggles , KRITEM_QUADORBINAUT } ,
2018-09-08 16:02:03 +00:00
{ IT_KEYHANDLER | IT_NOTHING , NULL , " Mines " , M_HandleMonitorToggles , KITEM_MINE } ,
2018-08-31 17:18:19 +00:00
{ 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 } ,
2018-08-31 18:41:37 +00:00
{ IT_KEYHANDLER | IT_NOTHING , NULL , " Invinciblity " , M_HandleMonitorToggles , KITEM_INVINCIBILITY } ,
2018-08-31 17:18:19 +00:00
{ 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 } ,
2018-09-08 16:02:03 +00:00
{ IT_KEYHANDLER | IT_NOTHING , NULL , " Kitchen Sinks " , M_HandleMonitorToggles , KITEM_KITCHENSINK } ,
# ifdef ITEMTOGGLEBOTTOMRIGHT
{ IT_KEYHANDLER | IT_NOTHING , NULL , " --- " , M_HandleMonitorToggles , 255 } ,
# endif
2014-03-15 16:59:03 +00:00
} ;
// ==========================================================================
// ALL MENU DEFINITIONS GO HERE
// ==========================================================================
// Main Menu and related
menu_t MainDef = CENTERMENUSTYLE ( NULL , MainMenu , NULL , 72 ) ;
2018-08-28 20:08:47 +00:00
menu_t MISC_AddonsDef =
{
NULL ,
sizeof ( MISC_AddonsMenu ) / sizeof ( menuitem_t ) ,
& MainDef ,
MISC_AddonsMenu ,
M_DrawAddons ,
50 , 28 ,
0 ,
NULL
} ;
2014-03-15 16:59:03 +00:00
menu_t MAPauseDef = PAUSEMENUSTYLE ( MAPauseMenu , 40 , 72 ) ;
menu_t SPauseDef = PAUSEMENUSTYLE ( SPauseMenu , 40 , 72 ) ;
menu_t MPauseDef = PAUSEMENUSTYLE ( MPauseMenu , 40 , 72 ) ;
// Misc Main Menu
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_ChangeLevelDef = MAPICONMENUSTYLE ( NULL , MISC_ChangeLevelMenu , & MPauseDef ) ;
menu_t MISC_HelpDef = IMAGEDEF ( MISC_HelpMenu ) ;
2018-07-01 18:29:13 +00:00
//
// 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
| | gamestate = = GS_TIMEATTACK )
{
highlightflags = V_ORANGEMAP ;
return ;
}
2018-07-02 00:55:01 +00:00
if ( currentMenu - > drawroutine = = M_DrawServerMenu )
2018-07-01 18:29:13 +00:00
gt = cv_newgametype . value ;
2018-07-02 00:55:01 +00:00
else if ( ! Playing ( ) )
{
highlightflags = V_YELLOWMAP ;
return ;
2018-07-01 18:29:13 +00:00
}
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
}
2014-03-15 16:59:03 +00:00
// Sky Room
menu_t SR_PandoraDef =
{
" M_PANDRA " ,
sizeof ( SR_PandorasBox ) / sizeof ( menuitem_t ) ,
& SPauseDef ,
SR_PandorasBox ,
M_DrawGenericMenu ,
60 , 40 ,
0 ,
M_ExitPandorasBox
} ;
menu_t SR_MainDef =
{
" M_SECRET " ,
sizeof ( SR_MainMenu ) / sizeof ( menuitem_t ) ,
& MainDef ,
SR_MainMenu ,
M_DrawSkyRoom ,
60 , 40 ,
0 ,
NULL
} ;
2018-06-30 15:01:03 +00:00
menu_t SR_LevelSelectDef = MAPICONMENUSTYLE ( NULL , SR_LevelSelectMenu , & SR_MainDef ) ;
2014-03-15 16:59:03 +00:00
menu_t SR_UnlockChecklistDef =
{
NULL ,
1 ,
2018-03-02 00:07:07 +00:00
& MainDef , //&SR_MainDef
2014-03-15 16:59:03 +00:00
SR_UnlockChecklistMenu ,
M_DrawChecklist ,
280 , 185 ,
0 ,
NULL
} ;
menu_t SR_EmblemHintDef =
{
NULL ,
sizeof ( SR_EmblemHintMenu ) / sizeof ( menuitem_t ) ,
& SPauseDef ,
SR_EmblemHintMenu ,
M_DrawEmblemHints ,
60 , 150 ,
0 ,
NULL
} ;
// Single Player
menu_t SP_MainDef = CENTERMENUSTYLE ( NULL , SP_MainMenu , & MainDef , 72 ) ;
menu_t SP_LoadDef =
{
" M_PICKG " ,
1 ,
& SP_MainDef ,
SP_LoadGameMenu ,
M_DrawLoad ,
68 , 46 ,
0 ,
NULL
} ;
menu_t SP_LevelSelectDef = MAPICONMENUSTYLE ( NULL , SP_LevelSelectMenu , & SP_LoadDef ) ;
menu_t SP_LevelStatsDef =
{
" M_STATS " ,
1 ,
& SP_MainDef ,
SP_LevelStatsMenu ,
M_DrawLevelStats ,
280 , 185 ,
0 ,
NULL
} ;
static menu_t SP_TimeAttackDef =
{
" M_ATTACK " ,
sizeof ( SP_TimeAttackMenu ) / sizeof ( menuitem_t ) ,
& MainDef , // Doesn't matter.
SP_TimeAttackMenu ,
M_DrawTimeAttackMenu ,
2018-07-02 00:55:01 +00:00
34 , 40 ,
2014-03-15 16:59:03 +00:00
0 ,
2018-07-04 21:57:50 +00:00
M_QuitTimeAttackMenu
2014-03-15 16:59:03 +00:00
} ;
static menu_t SP_ReplayDef =
{
" M_ATTACK " ,
sizeof ( SP_ReplayMenu ) / sizeof ( menuitem_t ) ,
& SP_TimeAttackDef ,
SP_ReplayMenu ,
M_DrawTimeAttackMenu ,
2018-07-02 00:55:01 +00:00
34 , 40 ,
2014-03-15 16:59:03 +00:00
0 ,
NULL
} ;
static menu_t SP_GuestReplayDef =
{
" M_ATTACK " ,
sizeof ( SP_GuestReplayMenu ) / sizeof ( menuitem_t ) ,
& SP_TimeAttackDef ,
SP_GuestReplayMenu ,
M_DrawTimeAttackMenu ,
2018-07-02 00:55:01 +00:00
34 , 40 ,
2014-03-15 16:59:03 +00:00
0 ,
NULL
} ;
static menu_t SP_GhostDef =
{
" M_ATTACK " ,
sizeof ( SP_GhostMenu ) / sizeof ( menuitem_t ) ,
& SP_TimeAttackDef ,
SP_GhostMenu ,
M_DrawTimeAttackMenu ,
2018-07-02 00:55:01 +00:00
34 , 40 ,
2014-03-15 16:59:03 +00:00
0 ,
NULL
} ;
2018-01-22 00:15:26 +00:00
/*static menu_t SP_NightsAttackDef =
2014-03-15 16:59:03 +00:00
{
" M_NIGHTS " ,
sizeof ( SP_NightsAttackMenu ) / sizeof ( menuitem_t ) ,
& MainDef , // Doesn't matter.
SP_NightsAttackMenu ,
M_DrawNightsAttackMenu ,
32 , 40 ,
0 ,
NULL
} ;
2014-11-12 00:55:07 +00:00
static menu_t SP_NightsReplayDef =
{
" M_NIGHTS " ,
sizeof ( SP_NightsReplayMenu ) / sizeof ( menuitem_t ) ,
& SP_NightsAttackDef ,
SP_NightsReplayMenu ,
M_DrawNightsAttackMenu ,
32 , 120 ,
0 ,
NULL
} ;
static menu_t SP_NightsGuestReplayDef =
{
" M_NIGHTS " ,
sizeof ( SP_NightsGuestReplayMenu ) / sizeof ( menuitem_t ) ,
& SP_NightsAttackDef ,
SP_NightsGuestReplayMenu ,
M_DrawNightsAttackMenu ,
32 , 120 ,
0 ,
NULL
} ;
static menu_t SP_NightsGhostDef =
{
" M_NIGHTS " ,
sizeof ( SP_NightsGhostMenu ) / sizeof ( menuitem_t ) ,
& SP_NightsAttackDef ,
SP_NightsGhostMenu ,
M_DrawNightsAttackMenu ,
32 , 120 ,
0 ,
NULL
2018-01-22 00:15:26 +00:00
} ; */
2014-11-12 00:55:07 +00:00
2014-03-15 16:59:03 +00:00
menu_t SP_PlayerDef =
{
" M_PICKP " ,
sizeof ( PlayerMenu ) / sizeof ( menuitem_t ) , //player_end,
& SP_MainDef ,
PlayerMenu ,
M_DrawSetupChoosePlayerMenu ,
24 , 32 ,
0 ,
NULL
} ;
2018-07-06 17:08:35 +00:00
# ifndef NONET
2014-03-15 16:59:03 +00:00
// Multiplayer
2018-06-30 15:01:03 +00:00
menu_t MP_MainDef =
{
" M_MULTI " ,
sizeof ( MP_MainMenu ) / sizeof ( menuitem_t ) ,
& MainDef ,
MP_MainMenu ,
M_DrawMPMainMenu ,
2018-07-06 17:08:35 +00:00
42 , 50 ,
2018-06-30 15:01:03 +00:00
0 ,
M_CancelConnect
} ;
2014-03-15 16:59:03 +00:00
menu_t MP_ServerDef = MAPICONMENUSTYLE ( " M_MULTI " , MP_ServerMenu , & MP_MainDef ) ;
2018-07-06 17:08:35 +00:00
# endif
2018-07-01 18:29:13 +00:00
menu_t MP_SplitServerDef = MAPICONMENUSTYLE ( " M_MULTI " , MP_SplitServerMenu , & MP_MainDef ) ;
2014-03-15 16:59:03 +00:00
# ifndef NONET
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 =
{
2017-11-28 06:13:23 +00:00
NULL , //"M_SPLAYR"
2014-03-15 16:59:03 +00:00
sizeof ( MP_PlayerSetupMenu ) / sizeof ( menuitem_t ) ,
& MP_MainDef ,
MP_PlayerSetupMenu ,
M_DrawSetupMultiPlayerMenu ,
2018-07-02 13:43:52 +00:00
36 , 14 ,
2014-03-15 16:59:03 +00:00
0 ,
M_QuitMultiPlayerMenu
} ;
// Options
2018-03-04 23:42:06 +00:00
menu_t OP_MainDef =
{
" M_OPTTTL " ,
sizeof ( OP_MainMenu ) / sizeof ( menuitem_t ) ,
& MainDef ,
OP_MainMenu ,
2018-06-15 00:18:29 +00:00
M_DrawGenericMenu ,
2018-03-04 23:42:06 +00:00
60 , 30 ,
0 ,
NULL
} ;
2014-03-15 16:59:03 +00:00
menu_t OP_ControlsDef = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_ControlsMenu , & OP_MainDef , 60 , 30 ) ;
2017-12-04 01:00:31 +00:00
//menu_t OP_ControlListDef = DEFAULTMENUSTYLE("M_CONTRO", OP_ControlListMenu, &OP_ControlsDef, 60, 30);
menu_t OP_MoveControlsDef = CONTROLMENUSTYLE ( OP_MoveControlsMenu , & OP_ControlsDef ) ;
2017-10-26 06:43:02 +00:00
//menu_t OP_MPControlsDef = CONTROLMENUSTYLE(OP_MPControlsMenu, &OP_ControlListDef);
2017-12-04 01:00:31 +00:00
//menu_t OP_CameraControlsDef = CONTROLMENUSTYLE(OP_CameraControlsMenu, &OP_ControlListDef);
//menu_t OP_MiscControlsDef = CONTROLMENUSTYLE(OP_MiscControlsMenu, &OP_ControlListDef);
menu_t OP_CustomControlsDef = CONTROLMENUSTYLE ( OP_CustomControlsMenu , & OP_MoveControlsDef ) ;
2018-01-24 21:53:20 +00:00
menu_t OP_SpectateControlsDef = CONTROLMENUSTYLE ( OP_SpectateControlsMenu , & OP_MoveControlsDef ) ;
2018-06-30 15:01:03 +00:00
/*
2014-03-15 16:59:03 +00:00
menu_t OP_P1ControlsDef = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_P1ControlsMenu , & OP_ControlsDef , 60 , 30 ) ;
menu_t OP_P2ControlsDef = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_P2ControlsMenu , & OP_ControlsDef , 60 , 30 ) ;
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2017-12-08 07:29:01 +00:00
menu_t OP_P3ControlsDef = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_P3ControlsMenu , & OP_ControlsDef , 60 , 30 ) ;
menu_t OP_P4ControlsDef = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_P4ControlsMenu , & OP_ControlsDef , 60 , 30 ) ;
2018-01-01 18:11:24 +00:00
# endif
2014-03-15 16:59:03 +00:00
menu_t OP_MouseOptionsDef = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_MouseOptionsMenu , & OP_P1ControlsDef , 60 , 30 ) ;
menu_t OP_Mouse2OptionsDef = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_Mouse2OptionsMenu , & OP_P2ControlsDef , 60 , 30 ) ;
2018-06-30 15:01:03 +00:00
*/
menu_t OP_Joystick1Def = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_Joystick1Menu , & OP_MoveControlsDef , 60 , 30 ) ;
menu_t OP_Joystick2Def = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_Joystick2Menu , & OP_MoveControlsDef , 60 , 30 ) ;
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2018-06-30 15:01:03 +00:00
menu_t OP_Joystick3Def = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_Joystick3Menu , & OP_MoveControlsDef , 60 , 30 ) ;
menu_t OP_Joystick4Def = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_Joystick4Menu , & OP_MoveControlsDef , 60 , 30 ) ;
2018-01-01 18:11:24 +00:00
# endif
2014-03-15 16:59:03 +00:00
menu_t OP_JoystickSetDef =
{
" M_CONTRO " ,
sizeof ( OP_JoystickSetMenu ) / sizeof ( menuitem_t ) ,
& OP_Joystick1Def ,
OP_JoystickSetMenu ,
M_DrawJoystick ,
50 , 40 ,
0 ,
NULL
} ;
2018-06-30 22:18:13 +00:00
menu_t OP_VideoOptionsDef =
{
" M_VIDEO " ,
sizeof ( OP_VideoOptionsMenu ) / sizeof ( menuitem_t ) ,
& OP_MainDef ,
OP_VideoOptionsMenu ,
M_DrawVideoMenu ,
2018-08-05 15:34:51 +00:00
30 , 30 ,
2018-06-30 22:18:13 +00:00
0 ,
NULL
} ;
2014-03-15 16:59:03 +00:00
menu_t OP_VideoModeDef =
{
" M_VIDEO " ,
1 ,
& OP_VideoOptionsDef ,
OP_VideoModeMenu ,
M_DrawVideoMode ,
48 , 26 ,
0 ,
NULL
} ;
2018-06-15 00:18:29 +00:00
menu_t OP_SoundOptionsDef =
{
" M_SOUND " ,
sizeof ( OP_SoundOptionsMenu ) / sizeof ( menuitem_t ) ,
& OP_MainDef ,
OP_SoundOptionsMenu ,
M_DrawSkyRoom ,
2018-08-05 15:34:51 +00:00
30 , 30 ,
2018-06-15 00:18:29 +00:00
0 ,
NULL
} ;
2018-07-01 18:29:13 +00:00
menu_t OP_HUDOptionsDef =
{
" M_HUD " ,
sizeof ( OP_HUDOptionsMenu ) / sizeof ( menuitem_t ) ,
& OP_MainDef ,
OP_HUDOptionsMenu ,
2018-08-09 21:59:52 +00:00
M_DrawHUDOptions ,
2018-07-01 18:29:13 +00:00
30 , 30 ,
0 ,
NULL
} ;
2018-08-09 21:59:52 +00:00
menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE ( " M_HUD " , OP_ChatOptionsMenu , & OP_HUDOptionsDef , 30 , 30 ) ;
2014-03-15 16:59:03 +00:00
menu_t OP_GameOptionsDef = DEFAULTMENUSTYLE ( " M_GAME " , OP_GameOptionsMenu , & OP_MainDef , 30 , 30 ) ;
2018-07-01 18:29:13 +00:00
menu_t OP_ServerOptionsDef = DEFAULTMENUSTYLE ( " M_SERVER " , OP_ServerOptionsMenu , & OP_MainDef , 24 , 30 ) ;
2014-03-15 16:59:03 +00:00
2018-06-15 00:18:29 +00:00
//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);
2018-08-31 17:18:19 +00:00
menu_t OP_MonitorToggleDef =
2014-03-15 16:59:03 +00:00
{
2018-08-31 17:18:19 +00:00
" M_GAME " ,
2014-03-15 16:59:03 +00:00
sizeof ( OP_MonitorToggleMenu ) / sizeof ( menuitem_t ) ,
2018-08-31 17:18:19 +00:00
& OP_GameOptionsDef ,
2014-03-15 16:59:03 +00:00
OP_MonitorToggleMenu ,
M_DrawMonitorToggles ,
2018-08-31 17:18:19 +00:00
47 , 30 ,
2014-03-15 16:59:03 +00:00
0 ,
NULL
2018-08-31 17:18:19 +00:00
} ;
2014-03-15 16:59:03 +00:00
# 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
2018-06-15 00:18:29 +00:00
//menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30);
2018-06-15 00:46:07 +00:00
menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE ( " M_SCSHOT " , OP_ScreenshotOptionsMenu , & OP_MainDef , 30 , 30 ) ;
2018-08-28 20:08:47 +00:00
menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE ( " M_ADDONS " , OP_AddonsOptionsMenu , & OP_MainDef , 30 , 30 ) ;
menu_t OP_EraseDataDef = DEFAULTMENUSTYLE ( " M_DATA " , OP_EraseDataMenu , & OP_MainDef , 30 , 30 ) ;
2014-03-15 16:59:03 +00:00
// ==========================================================================
// 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 ;
2017-10-21 02:01:07 +00:00
UINT8 active ;
lumpnum_t l ;
2014-03-15 16:59:03 +00:00
// 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 ) ) ;
2018-07-06 17:08:35 +00:00
if ( currentMenu = = & SP_TimeAttackDef )
2014-03-15 16:59:03 +00:00
{
2018-07-06 17:08:35 +00:00
// 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 ;
2014-11-12 00:55:07 +00:00
2018-07-06 17:08:35 +00:00
if ( ! gpath )
return ;
2017-10-21 02:01:07 +00:00
2018-07-06 17:08:35 +00:00
sprintf ( gpath , " %s " PATHSEP " replay " PATHSEP " %s " PATHSEP " %s " , srb2home , timeattackfolder , G_BuildMapName ( cv_nextmap . value ) ) ;
2014-11-12 00:55:07 +00:00
2017-10-21 02:01:07 +00:00
CV_StealthSetValue ( & cv_dummystaff , 0 ) ;
2014-11-12 00:55:07 +00:00
active = false ;
2014-03-15 16:59:03 +00:00
SP_TimeAttackMenu [ taguest ] . status = IT_DISABLED ;
SP_TimeAttackMenu [ tareplay ] . status = IT_DISABLED ;
2018-07-06 17:08:35 +00:00
//SP_TimeAttackMenu[taghost].status = IT_DISABLED;
2014-03-15 16:59:03 +00:00
// Check if file exists, if not, disable REPLAY option
2018-07-06 17:08:35 +00:00
for ( i = 0 ; i < 4 ; i + + )
{
2014-03-15 16:59:03 +00:00
SP_ReplayMenu [ i ] . status = IT_DISABLED ;
SP_GuestReplayMenu [ i ] . status = IT_DISABLED ;
}
2018-07-06 17:08:35 +00:00
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 ) ) ) {
2014-03-15 16:59:03 +00:00
SP_ReplayMenu [ 0 ] . status = IT_WHITESTRING | IT_CALL ;
SP_GuestReplayMenu [ 0 ] . status = IT_WHITESTRING | IT_CALL ;
2017-10-21 02:01:07 +00:00
active | = 3 ;
2014-03-15 16:59:03 +00:00
}
2018-07-06 17:08:35 +00:00
if ( FIL_FileExists ( va ( " %s-%s-lap-best.lmp " , gpath , cv_chooseskin . string ) ) ) {
2014-03-15 16:59:03 +00:00
SP_ReplayMenu [ 1 ] . status = IT_WHITESTRING | IT_CALL ;
SP_GuestReplayMenu [ 1 ] . status = IT_WHITESTRING | IT_CALL ;
2017-10-21 02:01:07 +00:00
active | = 3 ;
2014-03-15 16:59:03 +00:00
}
2018-07-06 17:08:35 +00:00
if ( FIL_FileExists ( va ( " %s-%s-last.lmp " , gpath , cv_chooseskin . string ) ) ) {
2014-03-15 16:59:03 +00:00
SP_ReplayMenu [ 2 ] . status = IT_WHITESTRING | IT_CALL ;
SP_GuestReplayMenu [ 2 ] . status = IT_WHITESTRING | IT_CALL ;
2017-10-21 02:01:07 +00:00
active | = 3 ;
}
2018-07-06 17:08:35 +00:00
if ( FIL_FileExists ( va ( " %s-guest.lmp " , gpath ) ) )
{
2018-01-22 00:15:26 +00:00
SP_ReplayMenu [ 3 ] . status = IT_WHITESTRING | IT_CALL ;
SP_GuestReplayMenu [ 3 ] . status = IT_WHITESTRING | IT_CALL ;
2018-07-06 17:08:35 +00:00
SP_GhostMenu [ 3 ] . status = IT_STRING | IT_CVAR ;
2018-01-22 00:15:26 +00:00
active | = 3 ;
}
2018-07-06 17:08:35 +00:00
if ( ( l = W_CheckNumForName ( va ( " %sS01 " , G_BuildMapName ( cv_nextmap . value ) ) ) ) ! = LUMPERROR )
{
2018-01-22 00:15:26 +00:00
SP_ReplayMenu [ 4 ] . status = IT_WHITESTRING | IT_KEYHANDLER ;
2018-07-06 17:08:35 +00:00
SP_GhostMenu [ 4 ] . status = IT_STRING | IT_CVAR ;
2017-10-21 02:01:07 +00:00
CV_StealthSetValue ( & cv_dummystaff , 1 ) ;
active | = 1 ;
2014-03-15 16:59:03 +00:00
}
2018-07-06 17:08:35 +00:00
2014-03-15 16:59:03 +00:00
if ( active ) {
2017-10-21 02:01:07 +00:00
if ( active & 1 )
SP_TimeAttackMenu [ tareplay ] . status = IT_WHITESTRING | IT_SUBMENU ;
if ( active & 2 )
SP_TimeAttackMenu [ taguest ] . status = IT_WHITESTRING | IT_SUBMENU ;
2014-03-15 16:59:03 +00:00
}
2018-07-06 17:08:35 +00:00
else if ( itemOn = = tareplay ) // Reset lastOn so replay isn't still selected when not available.
2014-03-15 16:59:03 +00:00
{
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 ) ;
2018-07-06 22:59:05 +00:00
free ( gpath ) ;
2014-03-15 16:59:03 +00:00
}
}
2018-01-22 00:15:26 +00:00
/*static void Dummymares_OnChange(void)
2014-03-15 16:59:03 +00:00
{
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 ) ;
}
2018-01-22 00:15:26 +00:00
} */
2014-03-15 16:59:03 +00:00
2017-10-21 02:01:07 +00:00
static void Dummystaff_OnChange ( void )
{
lumpnum_t l ;
if ( ( l = W_CheckNumForName ( va ( " %sS01 " , G_BuildMapName ( cv_nextmap . value ) ) ) ) = = LUMPERROR )
{
CV_StealthSetValue ( & cv_dummystaff , 0 ) ;
return ;
}
else
{
UINT8 numstaff = 1 ;
while ( numstaff < 100 & & ( 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 ) ;
}
}
2014-03-15 16:59:03 +00:00
// Newgametype. Used for gametype changes.
static void Newgametype_OnChange ( void )
{
2018-08-15 15:12:36 +00:00
if ( cv_nextmap . value & & menuactive )
2014-03-15 16:59:03 +00:00
{
2018-08-15 15:12:36 +00:00
if ( ! mapheaderinfo [ cv_nextmap . value - 1 ] )
2014-03-15 16:59:03 +00:00
P_AllocMapHeader ( ( INT16 ) ( cv_nextmap . value - 1 ) ) ;
2017-02-07 22:19:04 +00:00
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)))
2014-03-15 16:59:03 +00:00
{
INT32 value = 0 ;
switch ( cv_newgametype . value )
{
case GT_COOP :
2017-02-07 22:19:04 +00:00
value = TOL_RACE ; // SRB2kart
2014-03-15 16:59:03 +00:00
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 ) ) ;
2018-06-30 22:18:13 +00:00
//CV_AddValue(&cv_nextmap, -1);
//CV_AddValue(&cv_nextmap, 1);
2014-03-15 16:59:03 +00:00
}
}
}
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 ;
}
2018-08-28 20:08:47 +00:00
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 ) ;
}
2014-03-15 16:59:03 +00:00
// ==========================================================================
// 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 ;
2018-07-06 19:40:42 +00:00
if ( choice = = - 1 )
{
2018-07-06 19:55:22 +00:00
if ( cv = = & cv_playercolor )
2018-07-06 19:40:42 +00:00
{
2018-07-06 19:55:22 +00:00
SINT8 skinno = R_SkinAvailable ( cv_chooseskin . string ) ;
2018-07-29 17:35:56 +00:00
if ( skinno ! = - 1 )
CV_SetValue ( cv , skins [ skinno ] . prefcolor ) ;
return ;
2018-07-06 19:40:42 +00:00
}
CV_Set ( cv , cv - > defaultvalue ) ;
return ;
}
2018-07-29 17:35:56 +00:00
choice = ( choice < < 1 ) - 1 ;
2014-03-15 16:59:03 +00:00
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 ) )
{
2018-07-29 17:35:56 +00:00
CV_SetValue ( cv , cv - > value + choice ) ;
2014-03-15 16:59:03 +00:00
}
else if ( cv - > flags & CV_FLOAT )
{
char s [ 20 ] ;
2018-07-29 17:35:56 +00:00
sprintf ( s , " %f " , FIXED_TO_FLOAT ( cv - > value ) + ( choice ) * ( 1.0f / 16.0f ) ) ;
2014-03-15 16:59:03 +00:00
CV_Set ( cv , s ) ;
}
else
2018-07-29 17:35:56 +00:00
CV_AddValue ( cv , choice ) ;
2014-03-15 16:59:03 +00:00
}
static boolean M_ChangeStringCvar ( INT32 choice )
{
consvar_t * cv = ( consvar_t * ) currentMenu - > menuitems [ itemOn ] . itemaction ;
2018-06-30 22:18:13 +00:00
char buf [ MAXSTRINGLENGTH ] ;
2014-03-15 16:59:03 +00:00
size_t len ;
2018-06-30 22:18:13 +00:00
if ( shiftdown & & choice > = 32 & & choice < = 127 )
choice = shiftxform [ choice ] ;
2014-03-15 16:59:03 +00:00
switch ( choice )
{
case KEY_BACKSPACE :
len = strlen ( cv - > string ) ;
if ( len > 0 )
{
2018-06-30 22:18:13 +00:00
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
2014-03-15 16:59:03 +00:00
M_Memcpy ( buf , cv - > string , len ) ;
buf [ len - 1 ] = 0 ;
CV_Set ( cv , buf ) ;
}
return true ;
2018-06-30 22:18:13 +00:00
case KEY_DEL :
if ( cv - > string [ 0 ] )
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
CV_Set ( cv , " " ) ;
}
return true ;
2014-03-15 16:59:03 +00:00
default :
if ( choice > = 32 & & choice < = 127 )
{
len = strlen ( cv - > string ) ;
if ( len < MAXSTRINGLENGTH - 1 )
{
2018-06-30 22:18:13 +00:00
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
2014-03-15 16:59:03 +00:00
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
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
do
{
if ( ! itemOn )
itemOn = currentMenu - > numitems - 1 ;
else
itemOn - - ;
} while ( oldItemOn ! = itemOn & & ( currentMenu - > menuitems [ itemOn ] . status & IT_TYPE ) = = IT_SPACE ) ;
}
2016-07-06 04:09:17 +00:00
// 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 ;
2014-03-15 16:59:03 +00:00
//
// M_Responder
//
boolean M_Responder ( event_t * ev )
{
INT32 ch = - 1 ;
// INT32 i;
static tic_t joywait = 0 , mousewait = 0 ;
static INT32 pmousex = 0 , pmousey = 0 ;
static INT32 lastx = 0 , lasty = 0 ;
void ( * routine ) ( INT32 choice ) ; // for some casting problem
if ( dedicated | | ( demoplayback & & titledemo )
| | gamestate = = GS_INTRO | | gamestate = = GS_CUTSCENE | | gamestate = = GS_GAMEEND
| | gamestate = = GS_CREDITS | | gamestate = = GS_EVALUATION )
return false ;
2016-07-06 04:09:17 +00:00
if ( noFurtherInput )
{
// Ignore input after enter/escape/other buttons
// (but still allow shift keyup so caps doesn't get stuck)
return false ;
}
2014-03-15 16:59:03 +00:00
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 :
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 ( ) )
{
if ( ev - > data3 = = - 1 )
{
ch = KEY_UPARROW ;
joywait = I_GetTime ( ) + NEWTICRATE / 7 ;
}
else if ( ev - > data3 = = 1 )
{
ch = KEY_DOWNARROW ;
joywait = I_GetTime ( ) + NEWTICRATE / 7 ;
}
if ( ev - > data2 = = - 1 )
{
ch = KEY_LEFTARROW ;
joywait = I_GetTime ( ) + NEWTICRATE / 17 ;
}
else if ( ev - > data2 = = 1 )
{
ch = KEY_RIGHTARROW ;
joywait = I_GetTime ( ) + NEWTICRATE / 17 ;
}
}
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 ;
2017-12-25 07:09:06 +00:00
else if ( ch = = gamecontrol [ gc_systemmenu ] [ 0 ] ) // allow remappable ESC key
ch = KEY_ESCAPE ;
2014-03-15 16:59:03 +00:00
// F-Keys
if ( ! menuactive )
{
2016-07-06 04:09:17 +00:00
noFurtherInput = true ;
2017-12-25 07:09:06 +00:00
2014-03-15 16:59:03 +00:00
switch ( ch )
{
case KEY_F1 : // Help key
if ( modeattacking )
return true ;
M_StartControlPanel ( ) ;
2018-09-08 16:02:03 +00:00
M_Manual ( INT32_MAX ) ;
2014-03-15 16:59:03 +00:00
itemOn = 0 ;
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 ( ) ;
2016-07-06 04:09:17 +00:00
M_Options ( 0 ) ;
2014-03-15 16:59:03 +00:00
currentMenu = & OP_SoundOptionsDef ;
itemOn = 0 ;
return true ;
# ifndef DC
case KEY_F5 : // Video Mode
if ( modeattacking )
return true ;
M_StartControlPanel ( ) ;
2016-07-06 04:09:17 +00:00
M_Options ( 0 ) ;
2014-03-15 16:59:03 +00:00
M_VideoModeMenu ( 0 ) ;
return true ;
# endif
case KEY_F6 : // Empty
return true ;
case KEY_F7 : // Options
if ( modeattacking )
return true ;
M_StartControlPanel ( ) ;
2016-07-06 04:09:17 +00:00
M_Options ( 0 ) ;
2014-03-15 16:59:03 +00:00
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 ;
}
2016-07-06 04:09:17 +00:00
noFurtherInput = false ; // turns out we didn't care
2014-03-15 16:59:03 +00:00
return false ;
}
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 ] . alphaKey ! = MM_EVENTHANDLER )
{
if ( ch = = ' ' | | ch = = ' n ' | | ch = = ' y ' | | ch = = KEY_ESCAPE | | ch = = KEY_ENTER )
{
if ( routine )
routine ( ch ) ;
M_StopMessage ( 0 ) ;
2016-07-06 04:09:17 +00:00
noFurtherInput = true ;
2014-03-15 16:59:03 +00:00
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
2017-12-17 03:32:43 +00:00
| | ev - > type = = ev_joystick2 | | ev - > type = = ev_joystick3 | | ev - > type = = ev_joystick4 )
2014-03-15 16:59:03 +00:00
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 )
{
if ( shiftdown & & ch > = 32 & & ch < = 127 )
ch = shiftxform [ ch ] ;
if ( M_ChangeStringCvar ( ch ) )
return true ;
else
routine = NULL ;
}
else
routine = M_ChangeCvar ;
}
// 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 ) )
{
2018-07-29 17:35:56 +00:00
if ( currentMenu ! = & OP_SoundOptionsDef | | itemOn > 3 )
2014-03-15 16:59:03 +00:00
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 ) )
{
2018-07-29 17:35:56 +00:00
if ( currentMenu ! = & OP_SoundOptionsDef | | itemOn > 3 )
2014-03-15 16:59:03 +00:00
S_StartSound ( NULL , sfx_menu1 ) ;
routine ( 1 ) ;
}
return true ;
case KEY_ENTER :
2016-07-06 04:09:17 +00:00
noFurtherInput = true ;
2014-03-15 16:59:03 +00:00
currentMenu - > lastOn = itemOn ;
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 ) & & modifiedgame & & ! savemoddata )
{
S_StartSound ( NULL , sfx_menu1 ) ;
M_StartMessage ( M_GetText ( " This cannot be done in a modified 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 :
2016-07-06 04:09:17 +00:00
noFurtherInput = true ;
2014-03-15 16:59:03 +00:00
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 ;
}
2018-01-22 00:15:26 +00:00
if ( currentMenu = = & SP_TimeAttackDef ) //|| currentMenu == &SP_NightsAttackDef
2014-03-15 16:59:03 +00:00
{
// D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate.
menuactive = false ;
D_StartTitle ( ) ;
}
else
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 ] . alphaKey ) ;
return true ;
}
2018-07-06 19:40:42 +00:00
if ( routine & & ( ( currentMenu - > menuitems [ itemOn ] . status & IT_TYPE ) = = IT_ARROWS
| | ( currentMenu - > menuitems [ itemOn ] . status & IT_TYPE ) = = IT_CVAR ) )
{
2018-07-06 19:55:22 +00:00
consvar_t * cv = ( consvar_t * ) currentMenu - > menuitems [ itemOn ] . itemaction ;
if ( cv = = & cv_chooseskin
| | cv = = & cv_dummystaff
| | cv = = & cv_nextmap
| | cv = = & cv_newgametype )
return true ;
2018-07-29 17:35:56 +00:00
if ( currentMenu ! = & OP_SoundOptionsDef | | itemOn > 3 )
2018-07-06 19:40:42 +00:00
S_StartSound ( NULL , sfx_menu1 ) ;
routine ( - 1 ) ;
return true ;
}
2014-03-15 16:59:03 +00:00
// Why _does_ backspace go back anyway?
2018-09-16 00:13:29 +00:00
//currentMenu->lastOn = itemOn;
//if (currentMenu->prevMenu)
// M_SetupNextMenu(currentMenu->prevMenu);
2014-03-15 16:59:03 +00:00
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 ;
2016-07-06 04:09:17 +00:00
if ( menuactive )
{
// now that's more readable with a faded background (yeah like Quake...)
if ( ! WipeInAction )
2018-06-26 14:14:59 +00:00
V_DrawFadeScreen ( 0xFF00 , 16 ) ;
2014-03-15 16:59:03 +00:00
2016-07-06 04:09:17 +00:00
if ( currentMenu - > drawroutine )
2018-07-01 18:29:13 +00:00
{
M_GetGametypeColor ( ) ;
2016-07-06 04:09:17 +00:00
currentMenu - > drawroutine ( ) ; // call current menu Draw routine
2018-07-01 18:29:13 +00:00
}
2014-03-15 16:59:03 +00:00
2016-07-06 04:09:17 +00:00
// Draw version down in corner
// ... but only in the MAIN MENU. I'm a picky bastard.
if ( currentMenu = = & MainDef )
2014-03-15 16:59:03 +00:00
{
2016-07-06 04:09:17 +00:00
if ( customversionstring [ 0 ] ! = ' \0 ' )
{
2018-01-29 01:37:53 +00:00
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 ) ;
2016-07-06 04:09:17 +00:00
}
else
{
# ifdef DEVELOP // Development -- show revision / branch info
2018-01-29 01:37:53 +00:00
V_DrawThinString ( vid . dupx , vid . height - 20 * vid . dupy , V_NOSCALESTART | V_TRANSLUCENT | V_ALLOWLOWERCASE , " KART DEV EXE " ) ;
V_DrawThinString ( vid . dupx , vid . height - 10 * vid . dupy , V_NOSCALESTART | V_TRANSLUCENT | V_ALLOWLOWERCASE , va ( " %s " , VERSIONSTRINGW ) ) ;
2016-07-06 04:09:17 +00:00
# else // Regular build
2018-01-29 01:37:53 +00:00
V_DrawThinString ( vid . dupx , vid . height - 10 * vid . dupy , V_NOSCALESTART | V_TRANSLUCENT | V_ALLOWLOWERCASE , va ( " %s " , VERSIONSTRING ) ) ;
2016-07-06 04:09:17 +00:00
# endif
}
2014-03-15 16:59:03 +00:00
}
2016-07-06 04:09:17 +00:00
}
// focus lost notification goes on top of everything, even the former everything
if ( window_notinfocus )
{
M_DrawTextBox ( ( BASEVIDWIDTH / 2 ) - ( 60 ) , ( BASEVIDHEIGHT / 2 ) - ( 16 ) , 13 , 2 ) ;
if ( gamestate = = GS_LEVEL & & ( P_AutoPause ( ) | | paused ) )
2018-07-01 18:29:13 +00:00
V_DrawCenteredString ( BASEVIDWIDTH / 2 , ( BASEVIDHEIGHT / 2 ) - ( 4 ) , highlightflags , " Game Paused " ) ;
2014-03-15 16:59:03 +00:00
else
2018-07-01 18:29:13 +00:00
V_DrawCenteredString ( BASEVIDWIDTH / 2 , ( BASEVIDHEIGHT / 2 ) - ( 4 ) , highlightflags , " Focus Lost " ) ;
2014-03-15 16:59:03 +00:00
}
}
//
// M_StartControlPanel
//
void M_StartControlPanel ( void )
{
// time attack HACK
if ( modeattacking & & demoplayback )
{
G_CheckDemoStatus ( ) ;
2018-07-02 00:55:01 +00:00
S_ChangeMusicInternal ( " racent " , true ) ;
2014-03-15 16:59:03 +00:00
return ;
}
// intro might call this repeatedly
if ( menuactive )
{
CON_ToggleOff ( ) ; // move away console
return ;
}
menuactive = true ;
if ( ! Playing ( ) )
{
// Secret menu!
2018-03-02 00:00:16 +00:00
//MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
2014-03-15 16:59:03 +00:00
currentMenu = & MainDef ;
itemOn = singleplr ;
}
else if ( modeattacking )
{
currentMenu = & MAPauseDef ;
itemOn = mapause_continue ;
}
else if ( ! ( netgame | | multiplayer ) ) // Single Player
{
if ( gamestate ! = GS_LEVEL | | ultimatemode ) // intermission, so gray out stuff.
{
SPauseMenu [ spause_pandora ] . status = ( M_SecretUnlocked ( SECRET_PANDORA ) ) ? ( IT_GRAYEDOUT ) : ( IT_DISABLED ) ;
SPauseMenu [ spause_retry ] . status = IT_GRAYEDOUT ;
}
else
{
INT32 numlives = 2 ;
SPauseMenu [ spause_pandora ] . status = ( M_SecretUnlocked ( SECRET_PANDORA ) ) ? ( IT_STRING | IT_CALL ) : ( IT_DISABLED ) ;
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 ) ;
}
// We can always use level select though. :33
SPauseMenu [ spause_levelselect ] . status = ( gamecomplete ) ? ( IT_STRING | IT_CALL ) : ( IT_DISABLED ) ;
// And emblem hints.
SPauseMenu [ spause_hints ] . status = ( M_SecretUnlocked ( SECRET_EMBLEMHINTS ) ) ? ( IT_STRING | IT_CALL ) : ( IT_DISABLED ) ;
// Shift up Pandora's Box if both pandora and levelselect are active
/*if (SPauseMenu[spause_pandora].status != (IT_DISABLED)
& & SPauseMenu [ spause_levelselect ] . status ! = ( IT_DISABLED ) )
SPauseMenu [ spause_pandora ] . alphaKey = 24 ;
else
SPauseMenu [ spause_pandora ] . alphaKey = 32 ; */
currentMenu = & SPauseDef ;
itemOn = spause_continue ;
}
else // multiplayer
{
MPauseMenu [ mpause_switchmap ] . status = IT_DISABLED ;
2018-08-28 20:08:47 +00:00
MPauseMenu [ mpause_addons ] . status = IT_DISABLED ;
2014-03-15 16:59:03 +00:00
MPauseMenu [ mpause_scramble ] . status = IT_DISABLED ;
MPauseMenu [ mpause_psetupsplit ] . status = IT_DISABLED ;
MPauseMenu [ mpause_psetupsplit2 ] . status = IT_DISABLED ;
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2017-12-18 10:56:38 +00:00
MPauseMenu [ mpause_psetupsplit3 ] . status = IT_DISABLED ;
MPauseMenu [ mpause_psetupsplit4 ] . status = IT_DISABLED ;
2018-01-01 18:11:24 +00:00
# endif
2014-03-15 16:59:03 +00:00
MPauseMenu [ mpause_spectate ] . status = IT_DISABLED ;
MPauseMenu [ mpause_entergame ] . status = IT_DISABLED ;
2018-07-21 15:45:08 +00:00
MPauseMenu [ mpause_canceljoin ] . status = IT_DISABLED ;
2014-03-15 16:59:03 +00:00
MPauseMenu [ mpause_switchteam ] . status = IT_DISABLED ;
MPauseMenu [ mpause_psetup ] . status = IT_DISABLED ;
2017-12-18 10:56:38 +00:00
// Reset these in case splitscreen messes things up
MPauseMenu [ mpause_options ] . alphaKey = 64 ;
MPauseMenu [ mpause_title ] . alphaKey = 80 ;
MPauseMenu [ mpause_quit ] . alphaKey = 88 ;
2014-03-15 16:59:03 +00:00
2017-11-11 05:34:37 +00:00
if ( ( server | | IsPlayerAdmin ( consoleplayer ) ) )
2014-03-15 16:59:03 +00:00
{
MPauseMenu [ mpause_switchmap ] . status = IT_STRING | IT_CALL ;
2018-08-28 20:08:47 +00:00
MPauseMenu [ mpause_addons ] . status = IT_STRING | IT_CALL ;
2014-03-15 16:59:03 +00:00
if ( G_GametypeHasTeams ( ) )
MPauseMenu [ mpause_scramble ] . status = IT_STRING | IT_SUBMENU ;
}
if ( splitscreen )
2017-12-18 10:56:38 +00:00
{
2014-03-15 16:59:03 +00:00
MPauseMenu [ mpause_psetupsplit ] . status = MPauseMenu [ mpause_psetupsplit2 ] . status = IT_STRING | IT_CALL ;
2017-12-18 10:56:38 +00:00
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2017-12-19 02:11:59 +00:00
if ( splitscreen > 1 )
2017-12-18 10:56:38 +00:00
{
MPauseMenu [ mpause_psetupsplit3 ] . status = IT_STRING | IT_CALL ;
2017-12-19 02:11:59 +00:00
if ( splitscreen = = 2 )
2017-12-18 10:56:38 +00:00
{
MPauseMenu [ mpause_options ] . alphaKey = 72 ;
MPauseMenu [ mpause_title ] . alphaKey = 88 ;
MPauseMenu [ mpause_quit ] . alphaKey = 96 ;
}
2017-12-19 02:11:59 +00:00
if ( splitscreen = = 3 )
2017-12-18 10:56:38 +00:00
{
MPauseMenu [ mpause_psetupsplit4 ] . status = IT_STRING | IT_CALL ;
MPauseMenu [ mpause_options ] . alphaKey = 80 ;
MPauseMenu [ mpause_title ] . alphaKey = 96 ;
MPauseMenu [ mpause_quit ] . alphaKey = 104 ;
}
}
2018-01-01 18:11:24 +00:00
# endif
2017-12-18 10:56:38 +00:00
}
2014-03-15 16:59:03 +00:00
else
{
MPauseMenu [ mpause_psetup ] . status = IT_STRING | IT_CALL ;
if ( G_GametypeHasTeams ( ) )
MPauseMenu [ mpause_switchteam ] . status = IT_STRING | IT_SUBMENU ;
else if ( G_GametypeHasSpectators ( ) )
2018-07-21 15:45:08 +00:00
{
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 ;
}
2014-03-15 16:59:03 +00:00
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
menuactive = false ;
}
//
// M_SetupNextMenu
//
void M_SetupNextMenu ( menu_t * menudef )
{
INT16 i ;
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 )
{
2016-07-06 04:09:17 +00:00
// reset input trigger
noFurtherInput = false ;
2014-03-15 16:59:03 +00:00
if ( dedicated )
return ;
if ( - - skullAnimCounter < = 0 )
skullAnimCounter = 8 ;
//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 )
{
CV_RegisterVar ( & cv_nextmap ) ;
CV_RegisterVar ( & cv_newgametype ) ;
CV_RegisterVar ( & cv_chooseskin ) ;
CV_RegisterVar ( & cv_autorecord ) ;
if ( dedicated )
return ;
// Menu hacks
2018-06-30 15:01:03 +00:00
# ifndef NOFOURPLAYER
CV_RegisterVar ( & cv_dummysplitplayers ) ;
# endif
2014-03-15 16:59:03 +00:00
CV_RegisterVar ( & cv_dummyteam ) ;
CV_RegisterVar ( & cv_dummyscramble ) ;
CV_RegisterVar ( & cv_dummyrings ) ;
CV_RegisterVar ( & cv_dummylives ) ;
CV_RegisterVar ( & cv_dummycontinues ) ;
2018-01-22 00:15:26 +00:00
//CV_RegisterVar(&cv_dummymares);
2017-10-21 02:01:07 +00:00
CV_RegisterVar ( & cv_dummystaff ) ;
2014-03-15 16:59:03 +00:00
quitmsg [ QUITMSG ] = M_GetText ( " Eggman's tied explosives \n to your girlfriend, and \n will activate them if \n you press the 'Y' key! \n Press 'N' to save her! \n \n (Press 'Y' to quit) " ) ;
quitmsg [ QUITMSG1 ] = M_GetText ( " What would Tails say if \n he saw you quitting the game? \n \n (Press 'Y' to quit) " ) ;
quitmsg [ QUITMSG2 ] = M_GetText ( " Hey! \n Where do ya think you're goin'? \n \n (Press 'Y' to quit) " ) ;
quitmsg [ QUITMSG3 ] = M_GetText ( " Forget your studies! \n Play some more! \n \n (Press 'Y' to quit) " ) ;
2018-06-30 22:18:13 +00:00
quitmsg [ QUITMSG4 ] = M_GetText ( " You're trying to say you \n like Sonic R better than \n this, aren't you? \n \n (Press 'Y' to quit) " ) ;
2014-03-15 16:59:03 +00:00
quitmsg [ QUITMSG5 ] = M_GetText ( " Don't leave yet -- there's a \n super 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, \n Eggman will take over the world! \n \n (Press 'Y' to quit) " ) ;
2018-06-28 23:35:52 +00:00
quitmsg [ QUIT2MSG1 ] = M_GetText ( " On your mark, \n get set, \n hit the 'N' key! \n \n (Press 'Y' to quit) " ) ;
quitmsg [ QUIT2MSG2 ] = M_GetText ( " Aw c'mon, just \n a few more laps! \n \n (Press 'Y' to quit) " ) ;
2014-03-15 16:59:03 +00:00
quitmsg [ QUIT2MSG3 ] = M_GetText ( " Did you get all those Chaos Emeralds? \n \n (Press 'Y' to quit) " ) ;
2018-06-28 23:35:52 +00:00
quitmsg [ QUIT2MSG4 ] = M_GetText ( " If you leave, I'll use \n my Jawz on you! \n \n (Press 'Y' to quit) " ) ;
2014-03-15 16:59:03 +00:00
quitmsg [ QUIT2MSG5 ] = M_GetText ( " Don't go! \n You might find the hidden \n levels! \n \n (Press 'Y' to quit) " ) ;
quitmsg [ QUIT2MSG6 ] = M_GetText ( " Hit the 'N' key, Sonic! \n The 'N' key! \n \n (Press 'Y' to quit) " ) ;
quitmsg [ QUIT3MSG ] = M_GetText ( " Are you really going to give up? \n We 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) " ) ;
2018-06-28 23:35:52 +00:00
quitmsg [ QUIT3MSG2 ] = M_GetText ( " Press 'N' to unlock \n the Golden Kart! \n \n (Press 'Y' to quit) " ) ;
2018-07-02 22:17:30 +00:00
quitmsg [ QUIT3MSG3 ] = M_GetText ( " Couldn't handle \n the banana meta? \n \n (Press 'Y' to quit) " ) ;
2017-02-26 22:37:52 +00:00
quitmsg [ QUIT3MSG4 ] = M_GetText ( " Every time you press 'Y', an \n SRB2Kart Developer cries... \n \n (Press 'Y' to quit) " ) ;
2018-06-28 23:35:52 +00:00
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 \n difficult for you? \n \n (Press 'Y' to quit) " ) ;
2014-03-15 16:59:03 +00:00
# ifdef HWRENDER
// Permanently hide some options based on render mode
if ( rendermode = = render_soft )
2018-08-05 15:34:51 +00:00
OP_VideoOptionsMenu [ op_video_ogl ] . status = IT_DISABLED ;
2014-03-15 16:59:03 +00:00
# endif
# ifndef NONET
CV_RegisterVar ( & cv_serversort ) ;
# endif
//todo put this somewhere better...
CV_RegisterVar ( & cv_allcaps ) ;
}
// ==========================================================================
// 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)
2018-06-30 22:18:13 +00:00
static void M_DrawSlider ( INT32 x , INT32 y , const consvar_t * cv , boolean ontop )
2014-03-15 16:59:03 +00:00
{
INT32 i ;
INT32 range ;
patch_t * p ;
for ( i = 0 ; cv - > PossibleValue [ i + 1 ] . strvalue ; i + + ) ;
2018-06-30 22:18:13 +00:00
x = BASEVIDWIDTH - x - SLIDER_WIDTH ;
2014-03-15 16:59:03 +00:00
2018-06-30 22:18:13 +00:00
if ( ontop )
{
2018-07-29 17:35:56 +00:00
V_DrawCharacter ( x - 16 - ( skullAnimCounter / 5 ) , y ,
2018-07-01 18:29:13 +00:00
' \x1C ' | highlightflags , false ) ; // left arrow
2018-06-30 22:18:13 +00:00
V_DrawCharacter ( x + ( SLIDER_RANGE * 8 ) + 8 + ( skullAnimCounter / 5 ) , y ,
2018-07-01 18:29:13 +00:00
' \x1D ' | highlightflags , false ) ; // right arrow
2018-06-30 22:18:13 +00:00
}
2014-03-15 16:59:03 +00:00
2018-06-30 22:18:13 +00:00
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 ) ;
}
2014-03-15 16:59:03 +00:00
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 ) ;
2018-06-30 22:18:13 +00:00
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 ;
2014-03-15 16:59:03 +00:00
// draw the slider cursor
p = W_CachePatchName ( " M_SLIDEC " , PU_CACHE ) ;
2018-06-30 22:18:13 +00:00
V_DrawScaledPatch ( x - 4 + ( ( ( SLIDER_RANGE ) * 8 + 4 ) * range ) / 100 , y , 0 , p ) ;
2014-03-15 16:59:03 +00:00
}
//
// 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 , 239 ) ;
//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 )
{
2018-01-22 00:15:26 +00:00
case ET_TIME : //case ET_SCORE: case ET_RINGS:
2014-03-15 16:59:03 +00:00
curtype = 1 ; break ;
2018-01-22 00:15:26 +00:00
/*case ET_NGRADE: case ET_NTIME:
curtype = 2 ; break ; */
2014-03-15 16:59:03 +00:00
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_CACHE ) ) ;
else
V_DrawSmallScaledPatch ( x , y , 0 , W_CachePatchName ( " NEEDIT " , PU_CACHE ) ) ;
emblem = M_GetLevelEmblems ( - 1 ) ;
x - = 12 ;
}
}
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_DrawGenericMenu ( void )
{
2018-07-02 13:43:52 +00:00
INT32 x , y , w , i , cursory = 0 ;
2014-03-15 16:59:03 +00:00
// 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 ) ) ;
}
}
2017-09-28 13:39:47 +00:00
/* FALLTHRU */
2014-03-15 16:59:03 +00:00
case IT_NOTHING :
case IT_DYBIGSPACE :
2018-06-30 15:01:03 +00:00
y = currentMenu - > y + currentMenu - > menuitems [ i ] . alphaKey ; //+= LINEHEIGHT;
2014-03-15 16:59:03 +00:00
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 ] . alphaKey )
y = currentMenu - > y + currentMenu - > menuitems [ i ] . alphaKey ;
if ( i = = itemOn )
cursory = y ;
if ( ( currentMenu - > menuitems [ i ] . status & IT_DISPLAY ) = = IT_STRING )
V_DrawString ( x , y , 0 , currentMenu - > menuitems [ i ] . text ) ;
else
2018-07-01 18:29:13 +00:00
V_DrawString ( x , y , highlightflags , currentMenu - > menuitems [ i ] . text ) ;
2014-03-15 16:59:03 +00:00
// Cvar specific handling
switch ( currentMenu - > menuitems [ i ] . status & IT_TYPE )
case IT_CVAR :
{
consvar_t * cv = ( consvar_t * ) currentMenu - > menuitems [ i ] . itemaction ;
switch ( currentMenu - > menuitems [ i ] . status & IT_CVARTYPE )
{
case IT_CV_SLIDER :
2018-06-30 22:18:13 +00:00
M_DrawSlider ( x , y , cv , ( i = = itemOn ) ) ;
2014-03-15 16:59:03 +00:00
case IT_CV_NOPRINT : // color use this
case IT_CV_INVISSLIDER : // monitor toggles use this
break ;
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 :
2018-07-02 13:43:52 +00:00
w = V_StringWidth ( cv - > string , 0 ) ;
V_DrawString ( BASEVIDWIDTH - x - w , y ,
2018-07-01 18:29:13 +00:00
( ( cv - > flags & CV_CHEAT ) & & ! CV_IsSetToDefault ( cv ) ? warningflags : highlightflags ) , cv - > string ) ;
2018-06-30 22:18:13 +00:00
if ( i = = itemOn )
{
2018-07-02 13:43:52 +00:00
V_DrawCharacter ( BASEVIDWIDTH - x - 10 - w - ( skullAnimCounter / 5 ) , y ,
2018-07-01 18:29:13 +00:00
' \x1C ' | highlightflags , false ) ; // left arrow
2018-06-30 22:18:13 +00:00
V_DrawCharacter ( BASEVIDWIDTH - x + 2 + ( skullAnimCounter / 5 ) , y ,
2018-07-01 18:29:13 +00:00
' \x1D ' | highlightflags , false ) ; // right arrow
2018-06-30 22:18:13 +00:00
}
2014-03-15 16:59:03 +00:00
break ;
}
break ;
}
y + = STRINGHEIGHT ;
break ;
case IT_STRING2 :
V_DrawString ( x , y , 0 , currentMenu - > menuitems [ i ] . text ) ;
2017-09-28 13:39:47 +00:00
/* FALLTHRU */
2014-03-15 16:59:03 +00:00
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 ] . alphaKey )
y = currentMenu - > y + currentMenu - > menuitems [ i ] . alphaKey ;
2017-09-28 13:39:47 +00:00
/* FALLTHRU */
2014-03-15 16:59:03 +00:00
case IT_TRANSTEXT2 :
V_DrawString ( x , y , V_TRANSLUCENT , currentMenu - > menuitems [ i ] . text ) ;
y + = SMALLLINEHEIGHT ;
break ;
case IT_QUESTIONMARKS :
if ( currentMenu - > menuitems [ i ] . alphaKey )
y = currentMenu - > y + currentMenu - > menuitems [ i ] . alphaKey ;
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 ] . alphaKey )
y = currentMenu - > y + currentMenu - > menuitems [ i ] . alphaKey ;
2018-07-01 18:29:13 +00:00
V_DrawString ( x - 16 , y , highlightflags , currentMenu - > menuitems [ i ] . text ) ;
2014-03-15 16:59:03 +00:00
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 ) ) ;
2018-07-01 18:29:13 +00:00
V_DrawString ( currentMenu - > x , cursory , highlightflags , currentMenu - > menuitems [ itemOn ] . text ) ;
2014-03-15 16:59:03 +00:00
}
}
static void M_DrawPauseMenu ( void )
{
2018-07-15 22:13:36 +00:00
#if 0
2018-01-28 04:52:01 +00:00
if ( ! netgame & & ! multiplayer & & ( gamestate = = GS_LEVEL | | gamestate = = GS_INTERMISSION | | gamestate = = GS_VOTING ) )
2014-03-15 16:59:03 +00:00
{
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 ) ;
2018-06-05 21:28:46 +00:00
if ( strlen ( mapheaderinfo [ gamemap - 1 ] - > zonttl ) > 0 )
2018-02-08 23:14:56 +00:00
{
2018-06-05 21:28:46 +00:00
if ( strlen ( mapheaderinfo [ gamemap - 1 ] - > actnum ) > 0 )
2018-07-01 18:29:13 +00:00
V_DrawString ( 40 , 28 , highlightflags , va ( " %s %s %s " , mapheaderinfo [ gamemap - 1 ] - > lvlttl , mapheaderinfo [ gamemap - 1 ] - > zonttl , mapheaderinfo [ gamemap - 1 ] - > actnum ) ) ;
2018-02-08 23:14:56 +00:00
else
2018-07-01 18:29:13 +00:00
V_DrawString ( 40 , 28 , highlightflags , va ( " %s %s " , mapheaderinfo [ gamemap - 1 ] - > lvlttl , mapheaderinfo [ gamemap - 1 ] - > zonttl ) ) ;
2018-02-08 23:14:56 +00:00
}
2014-03-15 16:59:03 +00:00
else
2018-02-08 23:14:56 +00:00
{
2018-06-05 21:28:46 +00:00
if ( strlen ( mapheaderinfo [ gamemap - 1 ] - > actnum ) > 0 )
2018-07-01 18:29:13 +00:00
V_DrawString ( 40 , 28 , highlightflags , va ( " %s %s " , mapheaderinfo [ gamemap - 1 ] - > lvlttl , mapheaderinfo [ gamemap - 1 ] - > actnum ) ) ;
2018-02-08 23:14:56 +00:00
else
2018-07-01 18:29:13 +00:00
V_DrawString ( 40 , 28 , highlightflags , mapheaderinfo [ gamemap - 1 ] - > lvlttl ) ;
2018-02-08 23:14:56 +00:00
}
2014-03-15 16:59:03 +00:00
// Set up the detail boxes.
{
emblem_t * emblem = M_GetLevelEmblems ( gamemap ) ;
while ( emblem )
{
INT32 emblemslot ;
char targettext [ 9 ] , currenttext [ 9 ] ;
switch ( emblem - > type )
{
2018-01-22 00:15:26 +00:00
/*case ET_SCORE:
2014-03-15 16:59:03 +00:00
snprintf ( targettext , 9 , " %d " , emblem - > var ) ;
snprintf ( currenttext , 9 , " %u " , G_GetBestScore ( gamemap ) ) ;
targettext [ 8 ] = 0 ;
currenttext [ 8 ] = 0 ;
emblemslot = 0 ;
2018-01-22 00:15:26 +00:00
break ; */
2014-03-15 16:59:03 +00:00
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 ;
2018-01-22 00:15:26 +00:00
/*case ET_RINGS:
2014-03-15 16:59:03 +00:00
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 ;
2018-01-22 00:15:26 +00:00
break ; */
2014-03-15 16:59:03 +00:00
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_CACHE ) ) ;
else
V_DrawSmallScaledPatch ( 40 , 44 + ( i * 8 ) , 0 , W_CachePatchName ( " NEEDIT " , PU_CACHE ) ) ;
switch ( emblem - > type )
{
2018-01-22 00:15:26 +00:00
/*case ET_SCORE:
2014-03-15 16:59:03 +00:00
case ET_NGRADE :
2018-07-01 18:29:13 +00:00
V_DrawString ( 56 , 44 + ( i * 8 ) , highlightflags , " SCORE: " ) ;
2018-01-22 00:15:26 +00:00
break ; */
2014-03-15 16:59:03 +00:00
case ET_TIME :
2018-01-22 00:15:26 +00:00
//case ET_NTIME:
2018-07-01 18:29:13 +00:00
V_DrawString ( 56 , 44 + ( i * 8 ) , highlightflags , " TIME: " ) ;
2014-03-15 16:59:03 +00:00
break ;
2018-01-22 00:15:26 +00:00
/*case ET_RINGS:
2018-07-01 18:29:13 +00:00
V_DrawString ( 56 , 44 + ( i * 8 ) , highlightflags , " RINGS: " ) ;
2018-01-22 00:15:26 +00:00
break ; */
2014-03-15 16:59:03 +00:00
}
V_DrawRightAlignedString ( 284 , 44 + ( i * 8 ) , V_MONOSPACE , emblem_text [ i ] ) ;
}
}
2018-07-15 22:13:36 +00:00
# endif
2014-03-15 16:59:03 +00:00
M_DrawGenericMenu ( ) ;
}
static void M_DrawCenteredMenu ( void )
{
INT32 x , y , 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 ) ) ;
}
}
2017-09-28 13:39:47 +00:00
/* FALLTHRU */
2014-03-15 16:59:03 +00:00
case IT_NOTHING :
case IT_DYBIGSPACE :
y + = 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 ] . alphaKey )
y = currentMenu - > y + currentMenu - > menuitems [ i ] . alphaKey ;
if ( i = = itemOn )
cursory = y ;
if ( ( currentMenu - > menuitems [ i ] . status & IT_DISPLAY ) = = IT_STRING )
V_DrawCenteredString ( x , y , 0 , currentMenu - > menuitems [ i ] . text ) ;
else
2018-07-01 18:29:13 +00:00
V_DrawCenteredString ( x , y , highlightflags , currentMenu - > menuitems [ i ] . text ) ;
2014-03-15 16:59:03 +00:00
// Cvar specific handling
switch ( currentMenu - > menuitems [ i ] . status & IT_TYPE )
case IT_CVAR :
{
consvar_t * cv = ( consvar_t * ) currentMenu - > menuitems [ i ] . itemaction ;
switch ( currentMenu - > menuitems [ i ] . status & IT_CVARTYPE )
{
case IT_CV_SLIDER :
2018-06-30 22:18:13 +00:00
M_DrawSlider ( x , y , cv , ( i = = itemOn ) ) ;
2014-03-15 16:59:03 +00:00
case IT_CV_NOPRINT : // color use this
break ;
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 :
V_DrawString ( BASEVIDWIDTH - x - V_StringWidth ( cv - > string , 0 ) , y ,
2018-07-01 18:29:13 +00:00
( ( cv - > flags & CV_CHEAT ) & & ! CV_IsSetToDefault ( cv ) ? warningflags : highlightflags ) , cv - > string ) ;
2014-03-15 16:59:03 +00:00
break ;
}
break ;
}
y + = STRINGHEIGHT ;
break ;
case IT_STRING2 :
V_DrawCenteredString ( x , y , 0 , currentMenu - > menuitems [ i ] . text ) ;
2017-09-28 13:39:47 +00:00
/* FALLTHRU */
2014-03-15 16:59:03 +00:00
case IT_DYLITLSPACE :
y + = SMALLLINEHEIGHT ;
break ;
case IT_QUESTIONMARKS :
if ( currentMenu - > menuitems [ i ] . alphaKey )
y = currentMenu - > y + currentMenu - > menuitems [ i ] . alphaKey ;
V_DrawCenteredString ( x , y , V_TRANSLUCENT | V_OLDSPACING , M_CreateSecretMenuOption ( currentMenu - > menuitems [ i ] . text ) ) ;
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 ;
}
}
// DRAW THE SKULL CURSOR
if ( ( ( currentMenu - > menuitems [ itemOn ] . status & IT_DISPLAY ) = = IT_PATCH )
| | ( ( currentMenu - > menuitems [ itemOn ] . status & IT_DISPLAY ) = = IT_NOTHING ) )
{
V_DrawScaledPatch ( x + SKULLXOFF , cursory - 5 , 0 ,
W_CachePatchName ( " M_CURSOR " , PU_CACHE ) ) ;
}
else
{
V_DrawScaledPatch ( x - V_StringWidth ( currentMenu - > menuitems [ itemOn ] . text , 0 ) / 2 - 24 , cursory , 0 ,
W_CachePatchName ( " M_CURSOR " , PU_CACHE ) ) ;
2018-07-01 18:29:13 +00:00
V_DrawCenteredString ( x , cursory , highlightflags , currentMenu - > menuitems [ itemOn ] . text ) ;
2014-03-15 16:59:03 +00:00
}
}
//
// 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 ;
2018-07-06 17:08:35 +00:00
skins_cons_t [ j ] . value = j + 1 ;
2014-03-15 16:59:03 +00:00
}
else
{
skins_cons_t [ j ] . strvalue = NULL ;
skins_cons_t [ j ] . value = 0 ;
2018-07-04 21:57:50 +00:00
break ;
2014-03-15 16:59:03 +00:00
}
}
2018-07-04 21:57:50 +00:00
j = R_SkinAvailable ( cv_skin . string ) ;
if ( j = = - 1 )
j = 0 ;
2014-03-15 16:59:03 +00:00
2018-07-04 21:57:50 +00:00
CV_SetValue ( & cv_chooseskin , j + 1 ) ; // This causes crash sometimes?!
2014-03-15 16:59:03 +00:00
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 )
{
2018-08-15 15:12:36 +00:00
// Random map!
if ( mapnum = = - 1 )
return ( gamestate ! = GS_TIMEATTACK & & ! modeattacking ) ;
2014-03-15 16:59:03 +00:00
// 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?
2018-07-04 21:57:50 +00:00
if ( mapheaderinfo [ mapnum ] - > menuflags & LF2_HIDEINMENU & & mapnum + 1 ! = gamemap )
2014-03-15 16:59:03 +00:00
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_MATCH | | gt = = GT_TEAMMATCH ) & & ( mapheaderinfo [ mapnum ] - > typeoflevel & TOL_MATCH ) )
return true ;
if ( ( gt = = GT_TAG | | gt = = GT_HIDEANDSEEK ) & & ( mapheaderinfo [ mapnum ] - > typeoflevel & TOL_TAG ) )
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 ( M_MapLocked ( mapnum + 1 ) )
return false ; // not unlocked
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 ;
}
// 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 = & MainDef ;
else
MessageDef . prevMenu = currentMenu ;
MessageDef . menuitems [ 0 ] . text = message ;
MessageDef . menuitems [ 0 ] . alphaKey = ( 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 ) ;
2016-08-20 05:18:43 +00:00
// hack: draw RA background in RA menus
if ( gamestate = = GS_TIMEATTACK )
V_DrawPatchFill ( W_CachePatchName ( " SRB2BACK " , PU_CACHE ) ) ;
2014-03-15 16:59:03 +00:00
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 )
{
2018-09-08 16:02:03 +00:00
// this is probably what the V_DrawFixedPatch screen-fill bullshit was for, right
//V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); -- never mind, screen fade
2014-03-15 16:59:03 +00:00
// 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 ) ;
2018-09-25 21:33:22 +00:00
if ( patch - > height < = BASEVIDHEIGHT )
2014-03-15 16:59:03 +00:00
V_DrawScaledPatch ( 0 , 0 , 0 , patch ) ;
else
V_DrawSmallScaledPatch ( 0 , 0 , 0 , patch ) ;
}
2018-09-08 16:02:03 +00:00
if ( currentMenu - > menuitems [ itemOn ] . alphaKey )
{
2018-09-10 11:39:59 +00:00
V_DrawString ( 2 , BASEVIDHEIGHT - 10 , V_YELLOWMAP , va ( " %d " , ( itemOn < < 1 ) - 1 ) ) ; // intentionally not highlightflags, unlike below
2018-09-08 16:02:03 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - 2 , BASEVIDHEIGHT - 10 , V_YELLOWMAP , va ( " %d " , itemOn < < 1 ) ) ; // ditto
}
2018-09-10 11:39:59 +00:00
else
{
INT32 x = ( ( itemOn ? 3 : 1 ) * BASEVIDWIDTH ) > > 2 , y = ( BASEVIDHEIGHT > > 1 ) - 4 ;
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 " ) ;
}
2014-03-15 16:59:03 +00:00
}
// Handles the ImageDefs. Just a specialized function that
// uses left and right movement.
static void M_HandleImageDef ( INT32 choice )
{
2018-09-08 16:02:03 +00:00
boolean exitmenu = false ;
2014-03-15 16:59:03 +00:00
switch ( choice )
{
case KEY_RIGHTARROW :
2018-09-08 16:02:03 +00:00
if ( itemOn > = ( INT16 ) ( currentMenu - > numitems - 1 ) )
2014-03-15 16:59:03 +00:00
break ;
S_StartSound ( NULL , sfx_menu1 ) ;
2018-09-08 16:02:03 +00:00
itemOn + + ;
2014-03-15 16:59:03 +00:00
break ;
case KEY_LEFTARROW :
2018-09-08 16:02:03 +00:00
if ( ! itemOn )
2014-03-15 16:59:03 +00:00
break ;
S_StartSound ( NULL , sfx_menu1 ) ;
2018-09-08 16:02:03 +00:00
itemOn - - ;
2014-03-15 16:59:03 +00:00
break ;
case KEY_ESCAPE :
case KEY_ENTER :
2018-09-08 16:02:03 +00:00
exitmenu = true ;
2014-03-15 16:59:03 +00:00
break ;
}
2018-09-08 16:02:03 +00:00
if ( exitmenu )
{
if ( currentMenu - > prevMenu )
M_SetupNextMenu ( currentMenu - > prevMenu ) ;
else
M_ClearMenus ( true ) ;
}
2014-03-15 16:59:03 +00:00
}
// ======================
// MISC MAIN MENU OPTIONS
// ======================
2018-08-28 20:08:47 +00:00
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 ) )
{
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 ) ;
2018-08-29 13:19:08 +00:00
addonsp [ EXT_KART ] = W_CachePatchName ( " M_FKART " , PU_STATIC ) ;
2018-08-28 20:08:47 +00:00
//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 ) ;
MISC_AddonsDef . prevMenu = currentMenu ;
M_SetupNextMenu ( & MISC_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 , t ) > > FRACBITS ) ;
// border
V_DrawFill ( x - 1 , vpadding , 1 , h , 120 ) ;
V_DrawFill ( x + width , vpadding , 1 , h , 120 ) ;
V_DrawFill ( x - 1 , vpadding - 1 , width + 2 , 1 , 120 ) ;
V_DrawFill ( x - 1 , vpadding + h , width + 2 , 1 , 120 ) ;
// 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_lose);\
M_SetupNextMenu ( MISC_AddonsDef . prevMenu ) ; \
M_StartMessage ( va ( " \x82 %s \x80 \n This folder no longer exists! \n Aborting to main menu. \n \n (Press a key) \n " , M_AddonsHeaderPath ( ) ) , NULL , MM_NOTHING )
# define CLEARNAME Z_Free(refreshdirname);\
refreshdirname = NULL
static void M_AddonsClearName ( INT32 choice )
{
CLEARNAME ;
M_StopMessage ( choice ) ;
}
// returns whether to do message draw
static boolean M_AddonsRefresh ( void )
{
if ( ( refreshdirmenu & REFRESHDIR_NORMAL ) & & ! preparefilemenu ( true ) )
{
UNEXIST ;
return true ;
}
if ( refreshdirmenu & REFRESHDIR_ADDFILE )
{
char * message = NULL ;
if ( refreshdirmenu & REFRESHDIR_NOTLOADED )
{
S_StartSound ( NULL , sfx_lose ) ;
if ( refreshdirmenu & REFRESHDIR_MAX )
message = va ( " %c%s \x80 \n Maximum number of add-ons reached. \n A file could not be loaded. \n If you want 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 \n A file was not loaded. \n Check 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_skid ) ;
message = va ( " %c%s \x80 \n A file was loaded with %s. \n Check the console log for more information. \n \n (Press a key) \n " , ( ' \x80 ' + ( highlightflags > > V_CHARCOLORSHIFT ) ) , refreshdirname , ( ( refreshdirmenu & REFRESHDIR_ERROR ) ? " errors " : " warnings " ) ) ;
}
if ( message )
{
M_StartMessage ( message , M_AddonsClearName , MM_EVENTHANDLER ) ;
return true ;
}
S_StartSound ( NULL , sfx_strpst ) ;
CLEARNAME ;
}
return false ;
}
# ifdef FIXUPO0
# pragma GCC optimize ("0")
# endif
static void M_DrawAddons ( void )
{
INT32 x , y ;
2018-09-23 12:22:00 +00:00
ssize_t i , m ;
2018-08-28 20:08:47 +00:00
const UINT8 * flashcol = NULL ;
2018-09-23 12:22:00 +00:00
UINT8 hilicol ;
2018-08-28 20:08:47 +00:00
// 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
{
x = FixedDiv ( ( ( ssize_t ) ( numwadfiles ) - ( ssize_t ) ( mainwads + 1 ) ) < < FRACBITS , ( ( ssize_t ) MAX_WADFILES - ( ssize_t ) ( mainwads + 1 ) ) < < FRACBITS ) ;
y = FixedDiv ( ( ( ( ssize_t ) packetsizetally - ( ssize_t ) mainwadstally ) < < FRACBITS ) , ( ( ( ( ssize_t ) MAXFILENEEDED * sizeof ( UINT8 ) - ( ssize_t ) mainwadstally ) - ( 5 + 22 ) ) < < FRACBITS ) ) ; // 5+22 = (a.ext + checksum length) is minimum addition to packet size tally
if ( x > y )
y = x ;
if ( y > 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 ;
2018-09-23 12:22:00 +00:00
hilicol = V_GetStringColormap ( highlightflags ) [ 120 ] ;
2018-08-28 20:08:47 +00:00
V_DrawString ( x - 21 , ( y - 16 ) + ( lsheadingheight - 12 ) , highlightflags | V_ALLOWLOWERCASE , M_AddonsHeaderPath ( ) ) ;
2018-09-23 12:22:00 +00:00
V_DrawFill ( x - 21 , ( y - 16 ) + ( lsheadingheight - 3 ) , MAXSTRINGLENGTH * 8 + 6 , 1 , hilicol ) ;
2018-08-28 20:08:47 +00:00
V_DrawFill ( x - 21 , ( y - 16 ) + ( lsheadingheight - 2 ) , MAXSTRINGLENGTH * 8 + 6 , 1 , 30 ) ;
2018-09-23 12:22:00 +00:00
m = ( BASEVIDHEIGHT - currentMenu - > y + 2 ) - ( y - 1 ) ;
V_DrawFill ( x - 21 , y - 1 , MAXSTRINGLENGTH * 8 + 6 , m , 239 ) ;
// 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 ) ;
2018-08-28 20:08:47 +00:00
// get bottom...
2018-09-23 12:22:00 +00:00
m = dir_on [ menudepthleft ] + numaddonsshown + 1 ;
if ( m > ( ssize_t ) sizedirmenu )
m = sizedirmenu ;
2018-08-28 20:08:47 +00:00
// then top...
2018-09-23 12:22:00 +00:00
i = m - ( 2 * numaddonsshown + 1 ) ;
2018-08-28 20:08:47 +00:00
// then adjust!
if ( i < 0 )
{
2018-09-23 12:22:00 +00:00
if ( ( m - = i ) > ( ssize_t ) sizedirmenu )
m = sizedirmenu ;
2018-08-28 20:08:47 +00:00
i = 0 ;
}
if ( i ! = 0 )
V_DrawString ( 19 , y + 4 - ( skullAnimCounter / 5 ) , highlightflags , " \x1A " ) ;
if ( skullAnimCounter < 4 )
flashcol = V_GetStringColormap ( highlightflags ) ;
2018-09-23 12:22:00 +00:00
for ( ; i < m ; i + + )
2018-08-28 20:08:47 +00:00
{
UINT32 flags = V_ALLOWLOWERCASE ;
if ( y > BASEVIDHEIGHT ) break ;
if ( dirmenu [ i ] )
# define type (UINT8)(dirmenu[i][DIR_TYPE])
{
if ( type & EXT_LOADED )
2018-09-23 12:34:49 +00:00
{
flags | = V_TRANSLUCENT ;
V_DrawSmallScaledPatch ( x - ( 16 + 4 ) , y , V_TRANSLUCENT , addonsp [ ( type & ~ EXT_LOADED ) ] ) ;
2018-08-28 20:08:47 +00:00
V_DrawSmallScaledPatch ( x - ( 16 + 4 ) , y , 0 , addonsp [ NUM_EXT + 2 ] ) ;
2018-09-23 12:34:49 +00:00
}
else
V_DrawSmallScaledPatch ( x - ( 16 + 4 ) , y , 0 , addonsp [ ( type & ~ EXT_LOADED ) ] ) ;
2018-08-28 20:08:47 +00:00
if ( ( size_t ) i = = dir_on [ menudepthleft ] )
{
V_DrawFixedPatch ( ( x - ( 16 + 4 ) ) < < FRACBITS , ( y ) < < FRACBITS , FRACUNIT / 2 , 0 , addonsp [ NUM_EXT + 1 ] , flashcol ) ;
flags = V_ALLOWLOWERCASE | highlightflags ;
}
# define charsonside 14
if ( dirmenu [ i ] [ DIR_LEN ] > ( 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 ;
}
2018-09-23 12:22:00 +00:00
if ( m ! = ( ssize_t ) sizedirmenu )
2018-08-28 20:08:47 +00:00
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 , ( ( ! modifiedgame | | savemoddata ) ? 0 : V_TRANSLUCENT ) , addonsp [ NUM_EXT + 4 ] ) ;
if ( modifiedgame )
V_DrawSmallScaledPatch ( x , y + 4 , 0 , addonsp [ NUM_EXT + 2 ] ) ;
}
# ifdef FIXUPO0
# pragma GCC reset_options
# endif
static void M_AddonExec ( INT32 ch )
{
if ( ch ! = ' y ' & & ch ! = KEY_ENTER )
return ;
S_StartSound ( NULL , sfx_zoom ) ;
2018-08-29 13:19:08 +00:00
COM_BufAddText ( va ( " exec \" %s%s \" " , menupath , dirmenu [ dir_on [ menudepthleft ] ] + DIR_STRING ) ) ;
2018-08-28 20:08:47 +00:00
}
# 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
2018-09-23 15:13:58 +00:00
#if 0 // much slower
if ( ! preparefilemenu ( true ) )
2018-08-28 20:08:47 +00:00
{
UNEXIST ;
return ;
2018-09-23 15:13:58 +00:00
}
# else // streamlined
searchfilemenu ( tempname ) ;
# endif
2018-08-28 20:08:47 +00:00
}
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_lose ) ;
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 ) )
{
S_StartSound ( NULL , sfx_skid ) ;
M_StartMessage ( va ( " %c%s \x80 \n This 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 ) )
{
UNEXIST ;
return ;
}
}
else
{
S_StartSound ( NULL , sfx_menu1 ) ;
dir_on [ menudepthleft ] = 1 ;
}
refresh = false ;
}
else
{
S_StartSound ( NULL , sfx_lose ) ;
M_StartMessage ( va ( " %c%s \x80 \n This 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 ) )
{
UNEXIST ;
return ;
}
break ;
case EXT_TXT :
M_StartMessage ( va ( " %c%s \x80 \n This file may not be a console script. \n Attempt 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_lose ) ;
M_StartMessage ( va ( " %c%s \x80 \n This copy of SRB2 was compiled \n without 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 :
2018-08-29 13:19:08 +00:00
case EXT_KART :
2018-08-28 20:08:47 +00:00
//case EXT_PK3:
2018-08-29 13:19:08 +00:00
COM_BufAddText ( va ( " addfile \" %s%s \" " , menupath , dirmenu [ dir_on [ menudepthleft ] ] + DIR_STRING ) ) ;
2018-08-28 20:08:47 +00:00
break ;
default :
S_StartSound ( NULL , sfx_lose ) ;
}
}
if ( refresh )
refreshdirmenu | = REFRESHDIR_NORMAL ;
}
break ;
case KEY_ESCAPE :
exitmenu = true ;
break ;
default :
break ;
}
if ( exitmenu )
{
closefilemenu ( true ) ;
2018-09-09 14:17:41 +00:00
// Secret menu!
//MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
2018-08-28 20:08:47 +00:00
if ( currentMenu - > prevMenu )
M_SetupNextMenu ( currentMenu - > prevMenu ) ;
else
M_ClearMenus ( true ) ;
}
}
2014-03-15 16:59:03 +00:00
static void M_PandorasBox ( INT32 choice )
{
( void ) choice ;
CV_StealthSetValue ( & cv_dummyrings , max ( players [ consoleplayer ] . health - 1 , 0 ) ) ;
CV_StealthSetValue ( & cv_dummylives , players [ consoleplayer ] . lives ) ;
CV_StealthSetValue ( & cv_dummycontinues , players [ consoleplayer ] . continues ) ;
M_SetupNextMenu ( & SR_PandoraDef ) ;
}
static boolean M_ExitPandorasBox ( void )
{
if ( cv_dummyrings . value ! = max ( players [ consoleplayer ] . health - 1 , 0 ) )
COM_ImmedExecute ( va ( " setrings %d " , cv_dummyrings . value ) ) ;
if ( cv_dummylives . value ! = players [ consoleplayer ] . lives )
COM_ImmedExecute ( va ( " setlives %d " , cv_dummylives . value ) ) ;
if ( cv_dummycontinues . value ! = players [ consoleplayer ] . continues )
COM_ImmedExecute ( va ( " setcontinues %d " , cv_dummycontinues . value ) ) ;
return true ;
}
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 ;
2017-03-02 14:28:52 +00:00
// We allow switching to spectator even if team changing is not allowed
2014-03-15 16:59:03 +00:00
M_ClearMenus ( true ) ;
COM_ImmedExecute ( " changeteam spectator " ) ;
}
static void M_ConfirmEnterGame ( INT32 choice )
{
( void ) choice ;
2018-07-21 15:45:08 +00:00
/*if (!cv_allowteamchange.value)
2017-03-02 14:28:52 +00:00
{
M_StartMessage ( M_GetText ( " The server is not allowing \n team changes at this time. \n Press a key. \n " ) , NULL , MM_NOTHING ) ;
return ;
2018-07-21 15:45:08 +00:00
} */
2014-03-15 16:59:03 +00:00
M_ClearMenus ( true ) ;
COM_ImmedExecute ( " changeteam playing " ) ;
}
static void M_ConfirmTeamScramble ( INT32 choice )
{
( void ) choice ;
M_ClearMenus ( true ) ;
switch ( cv_dummyscramble . value )
{
case 0 :
COM_ImmedExecute ( " teamscramble 1 " ) ;
break ;
case 1 :
COM_ImmedExecute ( " teamscramble 2 " ) ;
break ;
}
}
static void M_ConfirmTeamChange ( INT32 choice )
{
( void ) choice ;
if ( ! cv_allowteamchange . value & & cv_dummyteam . value )
{
M_StartMessage ( M_GetText ( " The server is not allowing \n team changes at this time. \n Press a key. \n " ) , NULL , MM_NOTHING ) ;
return ;
}
M_ClearMenus ( true ) ;
switch ( cv_dummyteam . value )
{
case 0 :
COM_ImmedExecute ( " changeteam spectator " ) ;
break ;
case 1 :
COM_ImmedExecute ( " changeteam red " ) ;
break ;
case 2 :
COM_ImmedExecute ( " changeteam blue " ) ;
break ;
}
}
static void M_Options ( INT32 choice )
{
( void ) choice ;
2018-06-15 00:18:29 +00:00
// if the player is not admin or server, disable gameplay & server options
OP_MainMenu [ 5 ] . status = OP_MainMenu [ 6 ] . status = ( Playing ( ) & & ! ( server | | IsPlayerAdmin ( consoleplayer ) ) ) ? ( IT_GRAYEDOUT ) : ( IT_STRING | IT_SUBMENU ) ;
2014-03-15 16:59:03 +00:00
2018-06-15 00:18:29 +00:00
// if the player is playing _at all_, disable the erase data & credits options
2018-09-22 22:00:46 +00:00
OP_MainMenu [ 9 ] . status = ( Playing ( ) ) ? ( IT_GRAYEDOUT ) : ( IT_STRING | IT_CALL ) ;
OP_MainMenu [ 10 ] . status = ( Playing ( ) ) ? ( IT_GRAYEDOUT ) : ( IT_STRING | IT_SUBMENU ) ;
2014-03-15 16:59:03 +00:00
2018-08-08 19:48:29 +00:00
OP_GameOptionsMenu [ 3 ] . status =
( M_SecretUnlocked ( SECRET_ENCORE ) ) ? ( IT_CVAR | IT_STRING ) : IT_SECRET ; // cv_kartencore
2014-03-15 16:59:03 +00:00
OP_MainDef . prevMenu = currentMenu ;
M_SetupNextMenu ( & OP_MainDef ) ;
}
2018-09-08 16:02:03 +00:00
static void M_Manual ( INT32 choice )
{
( void ) choice ;
MISC_HelpDef . prevMenu = ( choice = = INT32_MAX ? NULL : currentMenu ) ;
M_SetupNextMenu ( & MISC_HelpDef ) ;
}
2014-03-15 16:59:03 +00:00
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 ( " Retry this act from the last starpost? \n \n (Press 'Y' to confirm) \n " ) , M_RetryResponse , MM_YESNO ) ;
}
static void M_SelectableClearMenus ( INT32 choice )
{
( void ) choice ;
M_ClearMenus ( true ) ;
}
// ======
// CHEATS
// ======
static void M_UltimateCheat ( INT32 choice )
{
( void ) choice ;
I_Quit ( ) ;
}
static void M_GetAllEmeralds ( INT32 choice )
{
( void ) choice ;
emeralds = ( ( EMERALD7 ) * 2 ) - 1 ;
M_StartMessage ( M_GetText ( " You now have all 7 emeralds. \n Use them wisely. \n With great power comes great ring drain. \n " ) , NULL , MM_NOTHING ) ;
G_SetGameModified ( multiplayer ) ;
}
static void M_DestroyRobotsResponse ( INT32 ch )
{
if ( ch ! = ' y ' & & ch ! = KEY_ENTER )
return ;
// Destroy all robots
P_DestroyRobots ( ) ;
G_SetGameModified ( multiplayer ) ;
}
static void M_DestroyRobots ( INT32 choice )
{
( void ) choice ;
M_StartMessage ( M_GetText ( " Do you want to destroy all \n robots in the current level? \n \n (Press 'Y' to confirm) \n " ) , M_DestroyRobotsResponse , MM_YESNO ) ;
}
static void M_LevelSelectWarp ( INT32 choice )
{
boolean fromloadgame = ( currentMenu = = & SP_LevelSelectDef ) ;
( void ) choice ;
if ( W_CheckNumForName ( G_BuildMapName ( cv_nextmap . value ) ) = = LUMPERROR )
{
// CONS_Alert(CONS_WARNING, "Internal game map '%s' not found\n", G_BuildMapName(cv_nextmap.value));
return ;
}
startmap = ( INT16 ) ( cv_nextmap . value ) ;
fromlevelselect = true ;
if ( fromloadgame )
G_LoadGame ( ( UINT32 ) cursaveslot , startmap ) ;
else
{
cursaveslot = - 1 ;
M_SetupChoosePlayer ( 0 ) ;
}
}
// ========
// SKY ROOM
// ========
UINT8 skyRoomMenuTranslations [ MAXUNLOCKABLES ] ;
2018-03-29 05:14:47 +00:00
static char * M_GetConditionString ( condition_t cond )
2018-03-29 05:14:29 +00:00
{
switch ( cond . type )
{
case UC_PLAYTIME :
2018-03-29 15:43:56 +00:00
return va ( " Play for %i:%02i:%02i " ,
2018-03-29 05:14:29 +00:00
G_TicsToHours ( cond . requirement ) ,
G_TicsToMinutes ( cond . requirement , false ) ,
G_TicsToSeconds ( cond . requirement ) ) ;
case UC_MATCHESPLAYED :
2018-03-29 15:43:56 +00:00
return va ( " Play %d matches " , cond . requirement ) ;
2018-03-29 05:14:29 +00:00
case UC_GAMECLEAR :
if ( cond . requirement > 1 )
2018-03-29 15:43:56 +00:00
return va ( " Beat game %d times " , cond . requirement ) ;
2018-03-29 05:14:29 +00:00
else
2018-03-29 15:43:56 +00:00
return va ( " Beat the game " ) ;
2018-03-29 05:14:29 +00:00
case UC_ALLEMERALDS :
if ( cond . requirement > 1 )
2018-03-29 15:43:56 +00:00
return va ( " Beat game w/ all emeralds %d times " , cond . requirement ) ;
2018-03-29 05:14:29 +00:00
else
2018-03-29 15:43:56 +00:00
return va ( " Beat game w/ all emeralds " ) ;
2018-03-29 05:14:29 +00:00
case UC_OVERALLTIME :
2018-03-29 15:43:56 +00:00
return va ( " Get overall time of %i:%02i:%02i " ,
2018-03-29 05:14:29 +00:00
G_TicsToHours ( cond . requirement ) ,
G_TicsToMinutes ( cond . requirement , false ) ,
G_TicsToSeconds ( cond . requirement ) ) ;
case UC_MAPVISITED :
2018-03-29 15:43:56 +00:00
return va ( " Visit %s " , G_BuildMapTitle ( cond . requirement - 1 ) ) ;
2018-03-29 05:14:29 +00:00
case UC_MAPBEATEN :
2018-03-29 15:43:56 +00:00
return va ( " Beat %s " , G_BuildMapTitle ( cond . requirement - 1 ) ) ;
2018-03-29 05:14:29 +00:00
case UC_MAPALLEMERALDS :
2018-03-29 15:43:56 +00:00
return va ( " Beat %s w/ all emeralds " , G_BuildMapTitle ( cond . requirement - 1 ) ) ;
2018-03-29 05:14:29 +00:00
case UC_MAPTIME :
2018-03-29 15:43:56 +00:00
return va ( " Beat %s in %i:%02i.%02i " , G_BuildMapTitle ( cond . extrainfo1 - 1 ) ,
2018-03-29 05:14:29 +00:00
G_TicsToMinutes ( cond . requirement , true ) ,
G_TicsToSeconds ( cond . requirement ) ,
G_TicsToCentiseconds ( cond . requirement ) ) ;
case UC_TOTALEMBLEMS :
2018-03-29 15:43:56 +00:00
return va ( " Get %d emblems " , cond . requirement ) ;
2018-03-29 05:14:29 +00:00
case UC_EXTRAEMBLEM :
2018-03-29 15:43:56 +00:00
return va ( " Get \" %s \" emblem " , extraemblems [ cond . requirement - 1 ] . name ) ;
2018-03-29 05:14:29 +00:00
default :
2018-06-25 13:18:30 +00:00
return NULL ;
2018-03-29 05:14:29 +00:00
}
}
2018-03-29 16:01:04 +00:00
# define NUMCHECKLIST 23
2014-03-15 16:59:03 +00:00
static void M_DrawChecklist ( void )
{
2018-06-25 13:18:30 +00:00
UINT32 i , line = 0 , c ;
INT32 lastid ;
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < MAXUNLOCKABLES ; i + + )
{
if ( unlockables [ i ] . name [ 0 ] = = 0 | | unlockables [ i ] . nochecklist
2018-08-08 19:48:29 +00:00
| | ! unlockables [ i ] . conditionset | | unlockables [ i ] . conditionset > MAXCONDITIONSETS
| | ! M_Achieved ( unlockables [ i ] . showconditionset - 1 ) )
2014-03-15 16:59:03 +00:00
continue ;
2018-03-29 05:14:29 +00:00
+ + line ;
2018-07-01 18:29:13 +00:00
V_DrawString ( 8 , ( line * 8 ) , V_RETURN8 | ( unlockables [ i ] . unlocked ? recommendedflags : warningflags ) , unlockables [ i ] . name ) ;
2014-03-15 16:59:03 +00:00
2018-03-29 15:43:56 +00:00
if ( conditionSets [ unlockables [ i ] . conditionset - 1 ] . numconditions )
2018-03-29 05:14:29 +00:00
{
2018-03-29 15:43:56 +00:00
c = 0 ;
lastid = - 1 ;
2018-03-29 05:14:29 +00:00
2018-03-29 15:43:56 +00:00
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 ) ;
2018-03-29 05:14:29 +00:00
2018-03-29 15:43:56 +00:00
if ( ! str )
continue ;
+ + line ;
2018-03-29 05:14:29 +00:00
2018-06-25 13:18:30 +00:00
if ( lastid = = - 1 | | cond . id ! = ( UINT32 ) lastid )
2018-03-29 15:43:56 +00:00
{
2018-07-01 18:29:13 +00:00
V_DrawString ( 16 , ( line * 8 ) , V_MONOSPACE | V_ALLOWLOWERCASE | ( achieved ? highlightflags : 0 ) , " * " ) ;
V_DrawString ( 32 , ( line * 8 ) , V_MONOSPACE | V_ALLOWLOWERCASE | ( achieved ? highlightflags : 0 ) , str ) ;
2018-03-29 15:43:56 +00:00
}
else
{
2018-07-01 18:29:13 +00:00
V_DrawString ( 32 , ( line * 8 ) , V_MONOSPACE | V_ALLOWLOWERCASE | ( achieved ? highlightflags : 0 ) , " & " ) ;
V_DrawString ( 48 , ( line * 8 ) , V_MONOSPACE | V_ALLOWLOWERCASE | ( achieved ? highlightflags : 0 ) , str ) ;
2018-03-29 15:43:56 +00:00
}
lastid = cond . id ;
}
2018-03-29 05:14:29 +00:00
}
2018-03-29 15:43:56 +00:00
+ + line ;
2014-03-15 16:59:03 +00:00
2018-03-29 05:14:29 +00:00
if ( line > = NUMCHECKLIST )
2014-03-15 16:59:03 +00:00
break ;
}
}
2018-03-29 15:43:56 +00:00
# undef NUMCHECKLIST
2014-03-15 16:59:03 +00:00
# define NUMHINTS 5
static void M_EmblemHints ( INT32 choice )
{
( void ) choice ;
SR_EmblemHintMenu [ 0 ] . status = ( M_SecretUnlocked ( SECRET_ITEMFINDER ) ) ? ( IT_CVAR | IT_STRING ) : ( IT_SECRET ) ;
M_SetupNextMenu ( & SR_EmblemHintDef ) ;
itemOn = 1 ; // always start on back.
}
static void M_DrawEmblemHints ( void )
{
INT32 i , j = 0 ;
UINT32 collected = 0 ;
emblem_t * emblem ;
const char * hint ;
for ( i = 0 ; i < numemblems ; i + + )
{
emblem = & emblemlocations [ i ] ;
if ( emblem - > level ! = gamemap | | emblem - > type > ET_SKIN )
continue ;
if ( emblem - > collected )
{
2018-07-01 18:29:13 +00:00
collected = recommendedflags ;
2014-03-15 16:59:03 +00:00
V_DrawMappedPatch ( 12 , 12 + ( 28 * j ) , 0 , W_CachePatchName ( M_GetEmblemPatch ( emblem ) , PU_CACHE ) ,
R_GetTranslationColormap ( TC_DEFAULT , M_GetEmblemColor ( emblem ) , GTC_CACHE ) ) ;
}
else
{
collected = 0 ;
V_DrawScaledPatch ( 12 , 12 + ( 28 * j ) , 0 , W_CachePatchName ( " NEEDIT " , PU_CACHE ) ) ;
}
if ( emblem - > hint [ 0 ] )
hint = emblem - > hint ;
else
hint = M_GetText ( " No hints available. " ) ;
hint = V_WordWrap ( 40 , BASEVIDWIDTH - 12 , 0 , hint ) ;
V_DrawString ( 40 , 8 + ( 28 * j ) , V_RETURN8 | V_ALLOWLOWERCASE | collected , hint ) ;
if ( + + j > = NUMHINTS )
break ;
}
if ( ! j )
2018-07-01 18:29:13 +00:00
V_DrawCenteredString ( 160 , 48 , highlightflags , " No hidden emblems on this map. " ) ;
2014-03-15 16:59:03 +00:00
M_DrawGenericMenu ( ) ;
}
static void M_DrawSkyRoom ( void )
{
INT32 i , y = 0 ;
2018-06-30 22:18:13 +00:00
INT32 lengthstring = 0 ;
2014-03-15 16:59:03 +00:00
M_DrawGenericMenu ( ) ;
2018-06-30 22:18:13 +00:00
if ( currentMenu = = & OP_SoundOptionsDef )
{
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x ,
currentMenu - > y + currentMenu - > menuitems [ 0 ] . alphaKey ,
2018-07-01 18:29:13 +00:00
( nosound ? warningflags : highlightflags ) ,
2018-06-30 22:18:13 +00:00
( ( nosound | | sound_disabled ) ? " OFF " : " ON " ) ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x ,
currentMenu - > y + currentMenu - > menuitems [ 2 ] . alphaKey ,
2018-07-01 18:29:13 +00:00
( nodigimusic ? warningflags : highlightflags ) ,
2018-06-30 22:18:13 +00:00
( ( nodigimusic | | digital_disabled ) ? " OFF " : " ON " ) ) ;
/*V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x,
currentMenu - > y + currentMenu - > menuitems [ 5 ] . alphaKey ,
2018-07-01 18:29:13 +00:00
( nomidimusic ? warningflags : highlightflags ) ,
2018-06-30 22:18:13 +00:00
( ( nomidimusic | | music_disabled ) ? " OFF " : " ON " ) ) ; */
if ( itemOn = = 0 )
lengthstring = 8 * ( ( nosound | | sound_disabled ) ? 3 : 2 ) ;
else if ( itemOn = = 2 )
lengthstring = 8 * ( ( nodigimusic | | digital_disabled ) ? 3 : 2 ) ;
/*else if (itemOn == 5)
lengthstring = 8 * ( ( nomidimusic | | music_disabled ) ? 3 : 2 ) ; */
}
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < currentMenu - > numitems ; + + i )
{
2018-06-30 22:18:13 +00:00
if ( currentMenu - > menuitems [ i ] . itemaction = = M_HandleSoundTest )
2014-03-15 16:59:03 +00:00
{
y = currentMenu - > menuitems [ i ] . alphaKey ;
break ;
}
}
2018-07-29 17:35:56 +00:00
2018-06-30 22:18:13 +00:00
if ( y )
{
y + = currentMenu - > y ;
2018-07-01 18:29:13 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x , y , highlightflags , cv_soundtest . string ) ;
2018-06-30 22:18:13 +00:00
if ( cv_soundtest . value )
2018-07-01 18:29:13 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x , y + 8 , highlightflags , S_sfx [ cv_soundtest . value ] . name ) ;
2018-06-30 22:18:13 +00:00
if ( i = = itemOn )
lengthstring = V_StringWidth ( cv_soundtest . string , 0 ) ;
}
2014-03-15 16:59:03 +00:00
2018-06-30 22:18:13 +00:00
if ( lengthstring )
{
V_DrawCharacter ( BASEVIDWIDTH - currentMenu - > x - 10 - lengthstring - ( skullAnimCounter / 5 ) , currentMenu - > y + currentMenu - > menuitems [ itemOn ] . alphaKey ,
2018-07-29 17:35:56 +00:00
' \x1C ' | highlightflags , false ) ; // left arrow
2018-06-30 22:18:13 +00:00
V_DrawCharacter ( BASEVIDWIDTH - currentMenu - > x + 2 + ( skullAnimCounter / 5 ) , currentMenu - > y + currentMenu - > menuitems [ itemOn ] . alphaKey ,
2018-07-29 17:35:56 +00:00
' \x1D ' | highlightflags , false ) ; // right arrow
2018-06-30 22:18:13 +00:00
}
2014-03-15 16:59:03 +00:00
}
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 ) ;
}
}
// Entering secrets menu
2018-03-02 00:00:16 +00:00
/*static void M_SecretsMenu(INT32 choice)
2014-03-15 16:59:03 +00:00
{
INT32 i , j , ul ;
UINT8 done [ MAXUNLOCKABLES ] ;
UINT16 curheight ;
( void ) choice ;
// Clear all before starting
for ( i = 1 ; i < MAXUNLOCKABLES + 1 ; + + i )
SR_MainMenu [ i ] . status = IT_DISABLED ;
memset ( skyRoomMenuTranslations , 0 , sizeof ( skyRoomMenuTranslations ) ) ;
memset ( done , 0 , sizeof ( done ) ) ;
for ( i = 1 ; i < MAXUNLOCKABLES + 1 ; + + i )
{
curheight = UINT16_MAX ;
ul = - 1 ;
// Autosort unlockables
for ( j = 0 ; j < MAXUNLOCKABLES ; + + j )
{
if ( ! unlockables [ j ] . height | | done [ j ] | | unlockables [ j ] . type < 0 )
continue ;
if ( unlockables [ j ] . height < curheight )
{
curheight = unlockables [ j ] . height ;
ul = j ;
}
}
if ( ul < 0 )
break ;
done [ ul ] = true ;
skyRoomMenuTranslations [ i - 1 ] = ( UINT8 ) ul ;
SR_MainMenu [ i ] . text = unlockables [ ul ] . name ;
SR_MainMenu [ i ] . alphaKey = ( UINT8 ) unlockables [ ul ] . height ;
if ( unlockables [ ul ] . type = = SECRET_HEADER )
{
SR_MainMenu [ i ] . status = IT_HEADER ;
continue ;
}
SR_MainMenu [ i ] . status = IT_SECRET ;
if ( unlockables [ ul ] . unlocked )
{
switch ( unlockables [ ul ] . type )
{
case SECRET_LEVELSELECT :
SR_MainMenu [ i ] . status = IT_STRING | IT_CALL ;
SR_MainMenu [ i ] . itemaction = M_CustomLevelSelect ;
break ;
case SECRET_WARP :
SR_MainMenu [ i ] . status = IT_STRING | IT_CALL ;
SR_MainMenu [ i ] . itemaction = M_CustomWarp ;
break ;
case SECRET_CREDITS :
SR_MainMenu [ i ] . status = IT_STRING | IT_CALL ;
SR_MainMenu [ i ] . itemaction = M_Credits ;
break ;
case SECRET_SOUNDTEST :
SR_MainMenu [ i ] . status = IT_STRING | IT_KEYHANDLER ;
SR_MainMenu [ i ] . itemaction = M_HandleSoundTest ;
default :
break ;
}
}
}
M_SetupNextMenu ( & SR_MainDef ) ;
2018-03-02 00:00:16 +00:00
} */
2014-03-15 16:59:03 +00:00
// ==================
// NEW GAME FUNCTIONS
// ==================
INT32 ultimate_selectable = false ;
static void M_NewGame ( void )
{
fromlevelselect = false ;
startmap = spstage_start ;
2017-02-07 22:19:04 +00:00
CV_SetValue ( & cv_newgametype , GT_RACE ) ; // SRB2kart
2014-03-15 16:59:03 +00:00
M_SetupChoosePlayer ( 0 ) ;
}
2018-03-02 00:00:16 +00:00
/*static void M_CustomWarp(INT32 choice)
2014-03-15 16:59:03 +00:00
{
INT32 ul = skyRoomMenuTranslations [ choice - 1 ] ;
startmap = ( INT16 ) ( unlockables [ ul ] . variable ) ;
M_SetupChoosePlayer ( 0 ) ;
2018-03-02 00:00:16 +00:00
} */
2014-03-15 16:59:03 +00:00
static void M_Credits ( INT32 choice )
{
( void ) choice ;
cursaveslot = - 2 ;
M_ClearMenus ( true ) ;
F_StartCredits ( ) ;
}
2018-03-02 00:00:16 +00:00
/*static void M_CustomLevelSelect(INT32 choice)
2014-03-15 16:59:03 +00:00
{
INT32 ul = skyRoomMenuTranslations [ choice - 1 ] ;
SR_LevelSelectDef . prevMenu = currentMenu ;
levellistmode = LLM_LEVELSELECT ;
maplistoption = ( UINT8 ) ( unlockables [ ul ] . variable ) ;
if ( M_CountLevelsToShowInList ( ) = = 0 )
{
M_StartMessage ( M_GetText ( " No selectable levels found. \n " ) , NULL , MM_NOTHING ) ;
return ;
}
M_PrepareLevelSelect ( ) ;
M_SetupNextMenu ( & SR_LevelSelectDef ) ;
2018-03-02 00:00:16 +00:00
} */
2014-03-15 16:59:03 +00:00
// ==================
// SINGLE PLAYER MENU
// ==================
static void M_SinglePlayerMenu ( INT32 choice )
{
( void ) choice ;
SP_MainMenu [ sprecordattack ] . status =
2016-08-20 05:18:43 +00:00
( M_SecretUnlocked ( SECRET_RECORDATTACK ) ) ? IT_CALL | IT_STRING : IT_SECRET ;
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
/*SP_MainMenu[spnightsmode].status =
( M_SecretUnlocked ( SECRET_NIGHTSMODE ) ) ? IT_CALL | IT_STRING : IT_SECRET ; */
2014-03-15 16:59:03 +00:00
M_SetupNextMenu ( & SP_MainDef ) ;
}
static void M_LoadGameLevelSelect ( INT32 choice )
{
( void ) choice ;
levellistmode = LLM_LEVELSELECT ;
maplistoption = 1 ;
if ( M_CountLevelsToShowInList ( ) = = 0 )
{
M_StartMessage ( M_GetText ( " No selectable levels found. \n " ) , NULL , MM_NOTHING ) ;
return ;
}
SP_LevelSelectDef . prevMenu = currentMenu ;
M_PrepareLevelSelect ( ) ;
M_SetupNextMenu ( & SP_LevelSelectDef ) ;
}
// ==============
// LOAD GAME MENU
// ==============
static INT32 saveSlotSelected = 0 ;
static short menumovedir = 0 ;
static void M_DrawLoadGameData ( void )
{
INT32 ecks ;
INT32 i ;
ecks = SP_LoadDef . x + 24 ;
M_DrawTextBox ( SP_LoadDef . x - 12 , 144 , 24 , 4 ) ;
if ( saveSlotSelected = = NOSAVESLOT ) // last slot is play without saving
{
if ( ultimate_selectable )
{
V_DrawCenteredString ( ecks + 68 , 144 , V_ORANGEMAP , " ULTIMATE MODE " ) ;
V_DrawCenteredString ( ecks + 68 , 156 , 0 , " NO RINGS, NO ONE-UPS, " ) ;
V_DrawCenteredString ( ecks + 68 , 164 , 0 , " NO CONTINUES, ONE LIFE, " ) ;
V_DrawCenteredString ( ecks + 68 , 172 , 0 , " FINAL DESTINATION. " ) ;
}
else
{
V_DrawCenteredString ( ecks + 68 , 144 , V_ORANGEMAP , " PLAY WITHOUT SAVING " ) ;
V_DrawCenteredString ( ecks + 68 , 156 , 0 , " THIS GAME WILL NOT BE " ) ;
V_DrawCenteredString ( ecks + 68 , 164 , 0 , " SAVED, BUT YOU CAN STILL " ) ;
V_DrawCenteredString ( ecks + 68 , 172 , 0 , " GET EMBLEMS AND SECRETS. " ) ;
}
return ;
}
if ( savegameinfo [ saveSlotSelected ] . lives = = - 42 ) // Empty
{
V_DrawCenteredString ( ecks + 68 , 160 , 0 , " NO DATA " ) ;
return ;
}
if ( savegameinfo [ saveSlotSelected ] . lives = = - 666 ) // savegame is bad
{
2018-07-01 18:29:13 +00:00
V_DrawCenteredString ( ecks + 68 , 144 , warningflags , " CORRUPT SAVE FILE " ) ;
2014-03-15 16:59:03 +00:00
V_DrawCenteredString ( ecks + 68 , 156 , 0 , " THIS SAVE FILE " ) ;
V_DrawCenteredString ( ecks + 68 , 164 , 0 , " CAN NOT BE LOADED. " ) ;
V_DrawCenteredString ( ecks + 68 , 172 , 0 , " DELETE USING BACKSPACE. " ) ;
return ;
}
// Draw the back sprite, it looks ugly if we don't
V_DrawScaledPatch ( SP_LoadDef . x , 144 + 8 , 0 , livesback ) ;
if ( savegameinfo [ saveSlotSelected ] . skincolor = = 0 )
V_DrawScaledPatch ( SP_LoadDef . x , 144 + 8 , 0 , W_CachePatchName ( skins [ savegameinfo [ saveSlotSelected ] . skinnum ] . face , PU_CACHE ) ) ;
else
{
UINT8 * colormap = R_GetTranslationColormap ( savegameinfo [ saveSlotSelected ] . skinnum , savegameinfo [ saveSlotSelected ] . skincolor , 0 ) ;
V_DrawMappedPatch ( SP_LoadDef . x , 144 + 8 , 0 , W_CachePatchName ( skins [ savegameinfo [ saveSlotSelected ] . skinnum ] . face , PU_CACHE ) , colormap ) ;
}
V_DrawString ( ecks + 12 , 152 , 0 , savegameinfo [ saveSlotSelected ] . playername ) ;
# ifdef SAVEGAMES_OTHERVERSIONS
if ( savegameinfo [ saveSlotSelected ] . gamemap & 16384 )
2018-07-01 18:29:13 +00:00
V_DrawCenteredString ( ecks + 68 , 144 , warningflags , " OUTDATED SAVE FILE! " ) ;
2014-03-15 16:59:03 +00:00
# endif
if ( savegameinfo [ saveSlotSelected ] . gamemap & 8192 )
2018-07-01 18:29:13 +00:00
V_DrawString ( ecks + 12 , 160 , recommendedflags , " CLEAR! " ) ;
2014-03-15 16:59:03 +00:00
else
V_DrawString ( ecks + 12 , 160 , 0 , va ( " %s " , savegameinfo [ saveSlotSelected ] . levelname ) ) ;
// Use the big face pic for lives, duh. :3
V_DrawScaledPatch ( ecks + 12 , 175 , 0 , W_CachePatchName ( " STLIVEX " , PU_HUDGFX ) ) ;
V_DrawTallNum ( ecks + 40 , 172 , 0 , savegameinfo [ saveSlotSelected ] . lives ) ;
// Absolute ridiculousness, condensed into another function.
V_DrawContinueIcon ( ecks + 58 , 182 , 0 , savegameinfo [ saveSlotSelected ] . skinnum , savegameinfo [ saveSlotSelected ] . skincolor ) ;
V_DrawScaledPatch ( ecks + 68 , 175 , 0 , W_CachePatchName ( " STLIVEX " , PU_HUDGFX ) ) ;
V_DrawTallNum ( ecks + 96 , 172 , 0 , savegameinfo [ saveSlotSelected ] . continues ) ;
for ( i = 0 ; i < 7 ; + + i )
{
if ( savegameinfo [ saveSlotSelected ] . numemeralds & ( 1 < < i ) )
V_DrawScaledPatch ( ecks + 104 + ( i * 8 ) , 172 , 0 , tinyemeraldpics [ i ] ) ;
}
}
# define LOADBARHEIGHT SP_LoadDef.y + (LINEHEIGHT * (j+1)) + ymod
# define CURSORHEIGHT SP_LoadDef.y + (LINEHEIGHT*3) - 1
static void M_DrawLoad ( void )
{
INT32 i , j ;
INT32 ymod = 0 , offset = 0 ;
M_DrawMenuTitle ( ) ;
if ( menumovedir ! = 0 ) //movement illusion
{
ymod = ( - ( LINEHEIGHT / 4 ) ) * menumovedir ;
offset = ( ( menumovedir > 0 ) ? - 1 : 1 ) ;
}
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 40 , 0 , " Press backspace to delete a save. " ) ;
for ( i = MAXSAVEGAMES + saveSlotSelected - 2 + offset , j = 0 ; i < = MAXSAVEGAMES + saveSlotSelected + 2 + offset ; i + + , j + + )
{
if ( ( menumovedir < 0 & & j = = 4 ) | | ( menumovedir > 0 & & j = = 0 ) )
continue ; //this helps give the illusion of movement
M_DrawSaveLoadBorder ( SP_LoadDef . x , LOADBARHEIGHT ) ;
if ( ( i % MAXSAVEGAMES ) = = NOSAVESLOT ) // play without saving
{
if ( ultimate_selectable )
V_DrawCenteredString ( SP_LoadDef . x + 92 , LOADBARHEIGHT - 1 , V_ORANGEMAP , " ULTIMATE MODE " ) ;
else
V_DrawCenteredString ( SP_LoadDef . x + 92 , LOADBARHEIGHT - 1 , V_ORANGEMAP , " PLAY WITHOUT SAVING " ) ;
continue ;
}
if ( savegameinfo [ i % MAXSAVEGAMES ] . lives = = - 42 )
V_DrawString ( SP_LoadDef . x - 6 , LOADBARHEIGHT - 1 , V_TRANSLUCENT , " NO DATA " ) ;
else if ( savegameinfo [ i % MAXSAVEGAMES ] . lives = = - 666 )
2018-07-01 18:29:13 +00:00
V_DrawString ( SP_LoadDef . x - 6 , LOADBARHEIGHT - 1 , warningflags , " CORRUPT SAVE FILE " ) ;
2014-03-15 16:59:03 +00:00
else if ( savegameinfo [ i % MAXSAVEGAMES ] . gamemap & 8192 )
2018-07-01 18:29:13 +00:00
V_DrawString ( SP_LoadDef . x - 6 , LOADBARHEIGHT - 1 , recommendedflags , " CLEAR! " ) ;
2014-03-15 16:59:03 +00:00
else
V_DrawString ( SP_LoadDef . x - 6 , LOADBARHEIGHT - 1 , 0 , va ( " %s " , savegameinfo [ i % MAXSAVEGAMES ] . levelname ) ) ;
//Draw the save slot number on the right side
V_DrawRightAlignedString ( SP_LoadDef . x + 192 , LOADBARHEIGHT - 1 , 0 , va ( " %d " , ( i % MAXSAVEGAMES ) + 1 ) ) ;
}
//Draw cursors on both sides.
V_DrawScaledPatch ( 32 , CURSORHEIGHT , 0 , W_CachePatchName ( " M_CURSOR " , PU_CACHE ) ) ;
V_DrawScaledPatch ( 274 , CURSORHEIGHT , 0 , W_CachePatchName ( " M_CURSOR " , PU_CACHE ) ) ;
M_DrawLoadGameData ( ) ;
//finishing the movement illusion
if ( menumovedir )
menumovedir + = ( ( menumovedir > 0 ) ? 1 : - 1 ) ;
if ( abs ( menumovedir ) > 3 )
menumovedir = 0 ;
}
# undef LOADBARHEIGHT
# undef CURSORHEIGHT
//
// User wants to load this game
//
static void M_LoadSelect ( INT32 choice )
{
( void ) choice ;
if ( saveSlotSelected = = NOSAVESLOT ) //last slot is play without saving
{
M_NewGame ( ) ;
cursaveslot = - 1 ;
return ;
}
if ( ! FIL_ReadFileOK ( va ( savegamename , saveSlotSelected ) ) )
{
// This slot is empty, so start a new game here.
M_NewGame ( ) ;
}
else if ( savegameinfo [ saveSlotSelected ] . gamemap & 8192 ) // Completed
M_LoadGameLevelSelect ( saveSlotSelected + 1 ) ;
else
G_LoadGame ( ( UINT32 ) saveSlotSelected , 0 ) ;
cursaveslot = saveSlotSelected ;
}
# define VERSIONSIZE 16
# define BADSAVE { savegameinfo[slot].lives = -666; Z_Free(savebuffer); return; }
# define CHECKPOS if (save_p >= end_p) BADSAVE
// Reads the save file to list lives, level, player, etc.
// Tails 05-29-2003
static void M_ReadSavegameInfo ( UINT32 slot )
{
size_t length ;
char savename [ 255 ] ;
UINT8 * savebuffer ;
UINT8 * end_p ; // buffer end point, don't read past here
UINT8 * save_p ;
INT32 fake ; // Dummy variable
char temp [ sizeof ( timeattackfolder ) ] ;
char vcheck [ VERSIONSIZE ] ;
# ifdef SAVEGAMES_OTHERVERSIONS
boolean oldversion = false ;
# endif
sprintf ( savename , savegamename , slot ) ;
length = FIL_ReadFile ( savename , & savebuffer ) ;
if ( length = = 0 )
{
savegameinfo [ slot ] . lives = - 42 ;
return ;
}
end_p = savebuffer + length ;
// skip the description field
save_p = savebuffer ;
// Version check
memset ( vcheck , 0 , sizeof ( vcheck ) ) ;
sprintf ( vcheck , " version %d " , VERSION ) ;
if ( strcmp ( ( const char * ) save_p , ( const char * ) vcheck ) )
{
# ifdef SAVEGAMES_OTHERVERSIONS
oldversion = true ;
# else
BADSAVE // Incompatible versions?
# endif
}
save_p + = VERSIONSIZE ;
// dearchive all the modifications
// P_UnArchiveMisc()
CHECKPOS
fake = READINT16 ( save_p ) ;
if ( ( ( fake - 1 ) & 8191 ) > = NUMMAPS ) BADSAVE
if ( ! mapheaderinfo [ ( fake - 1 ) & 8191 ] )
{
savegameinfo [ slot ] . levelname [ 0 ] = ' \0 ' ;
savegameinfo [ slot ] . actnum = 0 ;
}
else
{
strcpy ( savegameinfo [ slot ] . levelname , mapheaderinfo [ ( fake - 1 ) & 8191 ] - > lvlttl ) ;
2018-06-05 05:34:05 +00:00
savegameinfo [ slot ] . actnum = 0 ; //mapheaderinfo[(fake-1) & 8191]->actnum
2014-03-15 16:59:03 +00:00
}
# ifdef SAVEGAMES_OTHERVERSIONS
if ( oldversion )
{
if ( fake = = 24 ) //meh, let's count old Clear! saves too
fake | = 8192 ;
fake | = 16384 ; // marker for outdated version
}
# endif
savegameinfo [ slot ] . gamemap = fake ;
CHECKPOS
fake = READUINT16 ( save_p ) - 357 ; // emeralds
savegameinfo [ slot ] . numemeralds = ( UINT8 ) fake ;
CHECKPOS
READSTRINGN ( save_p , temp , sizeof ( temp ) ) ; // mod it belongs to
if ( strcmp ( temp , timeattackfolder ) ) BADSAVE
// P_UnArchivePlayer()
CHECKPOS
savegameinfo [ slot ] . skincolor = READUINT8 ( save_p ) ;
CHECKPOS
savegameinfo [ slot ] . skinnum = READUINT8 ( save_p ) ;
CHECKPOS
( void ) READINT32 ( save_p ) ; // Score
CHECKPOS
savegameinfo [ slot ] . lives = READINT32 ( save_p ) ; // lives
CHECKPOS
savegameinfo [ slot ] . continues = READINT32 ( save_p ) ; // continues
2014-08-27 03:56:30 +00:00
if ( fake & ( 1 < < 10 ) )
{
2014-03-15 16:59:03 +00:00
CHECKPOS
savegameinfo [ slot ] . botskin = READUINT8 ( save_p ) ;
2014-08-27 03:56:30 +00:00
if ( savegameinfo [ slot ] . botskin - 1 > = numskins )
2014-03-15 16:59:03 +00:00
savegameinfo [ slot ] . botskin = 0 ;
CHECKPOS
savegameinfo [ slot ] . botcolor = READUINT8 ( save_p ) ; // because why not.
2014-08-27 03:56:30 +00:00
}
else
2014-03-15 16:59:03 +00:00
savegameinfo [ slot ] . botskin = 0 ;
2014-08-27 03:56:30 +00:00
if ( savegameinfo [ slot ] . botskin )
2017-09-28 20:54:26 +00:00
snprintf ( savegameinfo [ slot ] . playername , 36 , " %s & %s " ,
2014-08-27 03:56:30 +00:00
skins [ savegameinfo [ slot ] . skinnum ] . realname ,
skins [ savegameinfo [ slot ] . botskin - 1 ] . realname ) ;
else
strcpy ( savegameinfo [ slot ] . playername , skins [ savegameinfo [ slot ] . skinnum ] . realname ) ;
savegameinfo [ slot ] . playername [ 31 ] = 0 ;
2014-03-15 16:59:03 +00:00
// File end marker check
CHECKPOS
if ( READUINT8 ( save_p ) ! = 0x1d ) BADSAVE ;
// done
Z_Free ( savebuffer ) ;
}
# undef CHECKPOS
# undef BADSAVE
//
// M_ReadSaveStrings
// read the strings from the savegame files
// and put it in savegamestrings global variable
//
static void M_ReadSaveStrings ( void )
{
FILE * handle ;
UINT32 i ;
char name [ 256 ] ;
for ( i = 0 ; i < MAXSAVEGAMES ; i + + )
{
snprintf ( name , sizeof name , savegamename , i ) ;
name [ sizeof name - 1 ] = ' \0 ' ;
handle = fopen ( name , " rb " ) ;
if ( handle = = NULL )
{
savegameinfo [ i ] . lives = - 42 ;
continue ;
}
fclose ( handle ) ;
M_ReadSavegameInfo ( i ) ;
}
}
//
// User wants to delete this game
//
static void M_SaveGameDeleteResponse ( INT32 ch )
{
char name [ 256 ] ;
if ( ch ! = ' y ' & & ch ! = KEY_ENTER )
return ;
// delete savegame
snprintf ( name , sizeof name , savegamename , saveSlotSelected ) ;
name [ sizeof name - 1 ] = ' \0 ' ;
remove ( name ) ;
// Refresh savegame menu info
M_ReadSaveStrings ( ) ;
}
static void M_HandleLoadSave ( INT32 choice )
{
boolean exitmenu = false ; // exit to previous menu
switch ( choice )
{
case KEY_DOWNARROW :
S_StartSound ( NULL , sfx_menu1 ) ;
+ + saveSlotSelected ;
if ( saveSlotSelected > = MAXSAVEGAMES )
saveSlotSelected - = MAXSAVEGAMES ;
menumovedir = 1 ;
break ;
case KEY_UPARROW :
S_StartSound ( NULL , sfx_menu1 ) ;
- - saveSlotSelected ;
if ( saveSlotSelected < 0 )
saveSlotSelected + = MAXSAVEGAMES ;
menumovedir = - 1 ;
break ;
case KEY_ENTER :
S_StartSound ( NULL , sfx_menu1 ) ;
if ( savegameinfo [ saveSlotSelected ] . lives ! = - 666 ) // don't allow loading of "bad saves"
M_LoadSelect ( saveSlotSelected ) ;
break ;
case KEY_ESCAPE :
exitmenu = true ;
break ;
case KEY_BACKSPACE :
S_StartSound ( NULL , sfx_menu1 ) ;
// Don't allow people to 'delete' "Play without Saving."
// Nor allow people to 'delete' slots with no saves in them.
if ( saveSlotSelected ! = NOSAVESLOT & & savegameinfo [ saveSlotSelected ] . lives ! = - 42 )
M_StartMessage ( M_GetText ( " Are you sure you want to delete \n this save game? \n \n (Press 'Y' to confirm) \n " ) , M_SaveGameDeleteResponse , MM_YESNO ) ;
break ;
}
if ( exitmenu )
{
if ( currentMenu - > prevMenu )
M_SetupNextMenu ( currentMenu - > prevMenu ) ;
else
M_ClearMenus ( true ) ;
}
}
//
// Selected from SRB2 menu
//
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
/*static void M_LoadGame(INT32 choice)
2014-03-15 16:59:03 +00:00
{
( void ) choice ;
M_ReadSaveStrings ( ) ;
M_SetupNextMenu ( & SP_LoadDef ) ;
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
} */
2014-03-15 16:59:03 +00:00
//
// Used by cheats to force the save menu to a specific spot.
//
void M_ForceSaveSlotSelected ( INT32 sslot )
{
// Already there? Out of bounds? Whatever, then!
if ( sslot = = saveSlotSelected | | sslot > = MAXSAVEGAMES )
return ;
// Figure out whether to display up movement or down movement
menumovedir = ( saveSlotSelected - sslot ) > 0 ? - 1 : 1 ;
if ( abs ( saveSlotSelected - sslot ) > ( MAXSAVEGAMES > > 1 ) )
menumovedir * = - 1 ;
saveSlotSelected = sslot ;
}
// ================
// CHARACTER SELECT
// ================
static void M_SetupChoosePlayer ( INT32 choice )
{
( void ) choice ;
if ( mapheaderinfo [ startmap - 1 ] & & mapheaderinfo [ startmap - 1 ] - > forcecharacter [ 0 ] ! = ' \0 ' )
{
M_ChoosePlayer ( 0 ) ; //oh for crying out loud just get STARTED, it doesn't matter!
return ;
}
if ( Playing ( ) = = false )
{
S_StopMusic ( ) ;
2016-07-06 04:09:17 +00:00
S_ChangeMusicInternal ( " chrsel " , true ) ;
2014-03-15 16:59:03 +00:00
}
SP_PlayerDef . prevMenu = currentMenu ;
M_SetupNextMenu ( & SP_PlayerDef ) ;
char_scroll = itemOn * 128 * FRACUNIT ; // finish scrolling the menu
Z_Free ( char_notes ) ;
char_notes = NULL ;
}
// Draw the choose player setup menu, had some fun with player anim
static void M_DrawSetupChoosePlayerMenu ( void )
{
const INT32 my = 24 ;
patch_t * patch ;
INT32 i , o , j ;
char * picname ;
// Black BG
V_DrawFill ( 0 , 0 , BASEVIDWIDTH , BASEVIDHEIGHT , 31 ) ;
//V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE));
// Character select profile images!1
M_DrawTextBox ( 0 , my , 16 , 20 ) ;
if ( abs ( itemOn * 128 * FRACUNIT - char_scroll ) > 256 * FRACUNIT )
char_scroll = itemOn * 128 * FRACUNIT ;
else if ( itemOn * 128 * FRACUNIT - char_scroll > 128 * FRACUNIT )
char_scroll + = 48 * FRACUNIT ;
else if ( itemOn * 128 * FRACUNIT - char_scroll < - 128 * FRACUNIT )
char_scroll - = 48 * FRACUNIT ;
else if ( itemOn * 128 * FRACUNIT > char_scroll + 16 * FRACUNIT )
char_scroll + = 16 * FRACUNIT ;
else if ( itemOn * 128 * FRACUNIT < char_scroll - 16 * FRACUNIT )
char_scroll - = 16 * FRACUNIT ;
else // close enough.
char_scroll = itemOn * 128 * FRACUNIT ; // just be exact now.
i = ( char_scroll + 16 * FRACUNIT ) / ( 128 * FRACUNIT ) ;
o = ( ( char_scroll / FRACUNIT ) + 16 ) % 128 ;
// prev character
if ( i - 1 > = 0 & & PlayerMenu [ i - 1 ] . status ! = IT_DISABLED
& & o < 32 )
{
picname = description [ i - 1 ] . picname ;
if ( picname [ 0 ] = = ' \0 ' )
{
picname = strtok ( Z_StrDup ( description [ i - 1 ] . skinname ) , " & " ) ;
for ( j = 0 ; j < numskins ; j + + )
if ( stricmp ( skins [ j ] . name , picname ) = = 0 )
{
Z_Free ( picname ) ;
picname = skins [ j ] . charsel ;
break ;
}
if ( j = = numskins ) // AAAAAAAAAA
picname = skins [ 0 ] . charsel ;
}
patch = W_CachePatchName ( picname , PU_CACHE ) ;
if ( SHORT ( patch - > width ) > = 256 )
2014-03-21 18:42:55 +00:00
V_DrawCroppedPatch ( 8 < < FRACBITS , ( my + 8 ) < < FRACBITS , FRACUNIT / 2 , 0 , patch , 0 , SHORT ( patch - > height ) - 64 + o * 2 , SHORT ( patch - > width ) , SHORT ( patch - > height ) ) ;
2014-03-15 16:59:03 +00:00
else
2014-03-21 18:42:55 +00:00
V_DrawCroppedPatch ( 8 < < FRACBITS , ( my + 8 ) < < FRACBITS , FRACUNIT , 0 , patch , 0 , SHORT ( patch - > height ) - 32 + o , SHORT ( patch - > width ) , SHORT ( patch - > height ) ) ;
2014-03-15 16:59:03 +00:00
W_UnlockCachedPatch ( patch ) ;
}
// next character
if ( i + 1 < currentMenu - > numitems & & PlayerMenu [ i + 1 ] . status ! = IT_DISABLED
& & o < 128 )
{
picname = description [ i + 1 ] . picname ;
if ( picname [ 0 ] = = ' \0 ' )
{
picname = strtok ( Z_StrDup ( description [ i + 1 ] . skinname ) , " & " ) ;
for ( j = 0 ; j < numskins ; j + + )
if ( stricmp ( skins [ j ] . name , picname ) = = 0 )
{
Z_Free ( picname ) ;
picname = skins [ j ] . charsel ;
break ;
}
if ( j = = numskins ) // AAAAAAAAAA
picname = skins [ 0 ] . charsel ;
}
patch = W_CachePatchName ( picname , PU_CACHE ) ;
if ( SHORT ( patch - > width ) > = 256 )
2014-03-21 18:42:55 +00:00
V_DrawCroppedPatch ( 8 < < FRACBITS , ( my + 168 - o ) < < FRACBITS , FRACUNIT / 2 , 0 , patch , 0 , 0 , SHORT ( patch - > width ) , o * 2 ) ;
2014-03-15 16:59:03 +00:00
else
2014-03-21 18:42:55 +00:00
V_DrawCroppedPatch ( 8 < < FRACBITS , ( my + 168 - o ) < < FRACBITS , FRACUNIT , 0 , patch , 0 , 0 , SHORT ( patch - > width ) , o ) ;
2014-03-15 16:59:03 +00:00
W_UnlockCachedPatch ( patch ) ;
}
// current character
if ( i < currentMenu - > numitems & & PlayerMenu [ i ] . status ! = IT_DISABLED )
{
picname = description [ i ] . picname ;
if ( picname [ 0 ] = = ' \0 ' )
{
picname = strtok ( Z_StrDup ( description [ i ] . skinname ) , " & " ) ;
for ( j = 0 ; j < numskins ; j + + )
if ( stricmp ( skins [ j ] . name , picname ) = = 0 )
{
Z_Free ( picname ) ;
picname = skins [ j ] . charsel ;
break ;
}
if ( j = = numskins ) // AAAAAAAAAA
picname = skins [ 0 ] . charsel ;
}
patch = W_CachePatchName ( picname , PU_CACHE ) ;
if ( o > = 0 & & o < = 32 )
{
if ( SHORT ( patch - > width ) > = 256 )
V_DrawSmallScaledPatch ( 8 , my + 40 - o , 0 , patch ) ;
else
V_DrawScaledPatch ( 8 , my + 40 - o , 0 , patch ) ;
}
else
{
if ( SHORT ( patch - > width ) > = 256 )
2014-03-21 18:42:55 +00:00
V_DrawCroppedPatch ( 8 < < FRACBITS , ( my + 8 ) < < FRACBITS , FRACUNIT / 2 , 0 , patch , 0 , ( o - 32 ) * 2 , SHORT ( patch - > width ) , SHORT ( patch - > height ) ) ;
2014-03-15 16:59:03 +00:00
else
2014-03-21 18:42:55 +00:00
V_DrawCroppedPatch ( 8 < < FRACBITS , ( my + 8 ) < < FRACBITS , FRACUNIT , 0 , patch , 0 , o - 32 , SHORT ( patch - > width ) , SHORT ( patch - > height ) ) ;
2014-03-15 16:59:03 +00:00
}
W_UnlockCachedPatch ( patch ) ;
}
// draw title (or big pic)
M_DrawMenuTitle ( ) ;
// Character description
M_DrawTextBox ( 136 , my , 21 , 20 ) ;
if ( ! char_notes )
char_notes = V_WordWrap ( 0 , 21 * 8 , V_ALLOWLOWERCASE , description [ itemOn ] . notes ) ;
V_DrawString ( 146 , my + 9 , V_RETURN8 | V_ALLOWLOWERCASE , char_notes ) ;
}
// Chose the player you want to use Tails 03-02-2002
static void M_ChoosePlayer ( INT32 choice )
{
char * skin1 , * skin2 ;
INT32 skinnum ;
2018-08-11 21:23:40 +00:00
//boolean ultmode = (ultimate_selectable && SP_PlayerDef.prevMenu == &SP_LoadDef && saveSlotSelected == NOSAVESLOT);
2014-03-15 16:59:03 +00:00
// skip this if forcecharacter
if ( mapheaderinfo [ startmap - 1 ] & & mapheaderinfo [ startmap - 1 ] - > forcecharacter [ 0 ] = = ' \0 ' )
{
// M_SetupChoosePlayer didn't call us directly, that means we've been properly set up.
char_scroll = itemOn * 128 * FRACUNIT ; // finish scrolling the menu
M_DrawSetupChoosePlayerMenu ( ) ; // draw the finally selected character one last time for the fadeout
}
M_ClearMenus ( true ) ;
skin1 = strtok ( description [ choice ] . skinname , " & " ) ;
skin2 = strtok ( NULL , " & " ) ;
if ( skin2 ) {
// this character has a second skin
skinnum = R_SkinAvailable ( skin1 ) ;
botskin = ( UINT8 ) ( R_SkinAvailable ( skin2 ) + 1 ) ;
botingame = true ;
botcolor = skins [ botskin - 1 ] . prefcolor ;
// undo the strtok
description [ choice ] . skinname [ strlen ( skin1 ) ] = ' & ' ;
} else {
skinnum = R_SkinAvailable ( description [ choice ] . skinname ) ;
botingame = false ;
botskin = 0 ;
botcolor = 0 ;
}
if ( startmap ! = spstage_start )
cursaveslot = - 1 ;
lastmapsaved = 0 ;
gamecomplete = false ;
2018-08-11 21:23:40 +00:00
G_DeferedInitNew ( false , G_BuildMapName ( startmap ) , ( UINT8 ) skinnum , 0 , fromlevelselect ) ;
2014-03-15 16:59:03 +00:00
COM_BufAddText ( " dummyconsvar 1 \n " ) ; // G_DeferedInitNew doesn't do this
}
// ===============
// STATISTICS MENU
// ===============
2018-07-01 18:29:13 +00:00
// ===============
// STATISTICS MENU
// ===============
2014-03-15 16:59:03 +00:00
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 ;
2018-05-31 02:53:06 +00:00
if ( ! ( mapheaderinfo [ i ] - > typeoflevel & TOL_RACE ) // TOL_SP
2018-07-06 17:08:35 +00:00
| | ( mapheaderinfo [ i ] - > menuflags & ( LF2_HIDEINSTATS | LF2_HIDEINMENU ) ) )
2014-03-15 16:59:03 +00:00
continue ;
2018-05-31 02:53:06 +00:00
if ( M_MapLocked ( i + 1 ) ) // !mapvisited[i]
2014-03-15 16:59:03 +00:00
continue ;
statsMapList [ j + + ] = i ;
}
statsMapList [ j ] = - 1 ;
2018-07-01 18:29:13 +00:00
statsMax = j - 11 + numextraemblems ;
2014-03-15 16:59:03 +00:00
statsLocation = 0 ;
if ( statsMax < 0 )
statsMax = 0 ;
2018-07-01 18:29:13 +00:00
M_SetupNextMenu ( & SP_LevelStatsDef ) ;
2014-03-15 16:59:03 +00:00
}
static void M_DrawStatsMaps ( int location )
{
2018-07-01 18:29:13 +00:00
INT32 y = 80 , i = - 1 ;
2014-03-15 16:59:03 +00:00
INT16 mnum ;
extraemblem_t * exemblem ;
2018-07-01 18:29:13 +00:00
boolean dotopname = true , dobottomarrow = ( location < statsMax ) ;
2014-03-15 16:59:03 +00:00
2018-07-01 18:29:13 +00:00
if ( location )
2018-09-10 11:41:53 +00:00
V_DrawCharacter ( 10 , y - ( skullAnimCounter / 5 ) ,
' \x1A ' | highlightflags , false ) ; // up arrow
2014-03-15 16:59:03 +00:00
while ( statsMapList [ + + i ] ! = - 1 )
{
if ( location )
{
- - location ;
continue ;
}
2018-07-01 18:29:13 +00:00
else if ( dotopname )
{
V_DrawString ( 20 , y , highlightflags , " LEVEL NAME " ) ;
V_DrawString ( 248 , y , highlightflags , " EMBLEMS " ) ;
y + = 8 ;
dotopname = false ;
}
2014-03-15 16:59:03 +00:00
mnum = statsMapList [ i ] ;
M_DrawMapEmblems ( mnum + 1 , 292 , y ) ;
2018-07-01 18:29:13 +00:00
if ( mapheaderinfo [ mnum ] - > levelflags & LF_NOZONE )
V_DrawString ( 20 , y , 0 , va ( " %s %s " ,
mapheaderinfo [ mnum ] - > lvlttl ,
mapheaderinfo [ mnum ] - > actnum ) ) ;
2014-03-15 16:59:03 +00:00
else
2018-07-01 18:29:13 +00:00
V_DrawString ( 20 , y , 0 , va ( " %s %s %s " ,
mapheaderinfo [ mnum ] - > lvlttl ,
( mapheaderinfo [ mnum ] - > zonttl [ 0 ] ? mapheaderinfo [ mnum ] - > zonttl : " ZONE " ) ,
mapheaderinfo [ mnum ] - > actnum ) ) ;
2014-03-15 16:59:03 +00:00
y + = 8 ;
if ( y > = BASEVIDHEIGHT - 8 )
2018-07-01 18:29:13 +00:00
goto bottomarrow ;
}
if ( dotopname & & ! location )
{
V_DrawString ( 20 , y , highlightflags , " LEVEL NAME " ) ;
V_DrawString ( 248 , y , highlightflags , " EMBLEMS " ) ;
y + = 8 ;
2014-03-15 16:59:03 +00:00
}
2018-07-01 18:29:13 +00:00
else if ( location )
- - location ;
2014-03-15 16:59:03 +00:00
// Extra Emblems
for ( i = - 2 ; i < numextraemblems ; + + i )
{
2018-07-01 18:29:13 +00:00
if ( i = = - 1 )
{
V_DrawString ( 20 , y , highlightflags , " EXTRA EMBLEMS " ) ;
if ( location )
{
y + = 8 ;
location + + ;
}
}
2014-03-15 16:59:03 +00:00
if ( location )
{
- - location ;
continue ;
}
2018-07-01 18:29:13 +00:00
if ( i > = 0 )
2014-03-15 16:59:03 +00:00
{
exemblem = & extraemblems [ i ] ;
if ( exemblem - > collected )
V_DrawSmallMappedPatch ( 292 , y , 0 , W_CachePatchName ( M_GetExtraEmblemPatch ( exemblem ) , PU_CACHE ) ,
R_GetTranslationColormap ( TC_DEFAULT , M_GetExtraEmblemColor ( exemblem ) , GTC_CACHE ) ) ;
else
V_DrawSmallScaledPatch ( 292 , y , 0 , W_CachePatchName ( " NEEDIT " , PU_CACHE ) ) ;
2018-07-01 18:29:13 +00:00
V_DrawString ( 20 , y , 0 , va ( " %s " , exemblem - > description ) ) ;
2014-03-15 16:59:03 +00:00
}
y + = 8 ;
if ( y > = BASEVIDHEIGHT - 8 )
2018-07-01 18:29:13 +00:00
goto bottomarrow ;
2014-03-15 16:59:03 +00:00
}
2018-07-01 18:29:13 +00:00
bottomarrow :
if ( dobottomarrow )
2018-09-10 11:41:53 +00:00
V_DrawCharacter ( 10 , y - 8 + ( skullAnimCounter / 5 ) ,
' \x1B ' | highlightflags , false ) ; // up arrow
2014-03-15 16:59:03 +00:00
}
static void M_DrawLevelStats ( void )
{
char beststr [ 40 ] ;
tic_t besttime = 0 ;
INT32 i ;
2018-07-01 18:29:13 +00:00
INT32 mapsunfinished = 0 ;
2014-03-15 16:59:03 +00:00
M_DrawMenuTitle ( ) ;
2018-07-01 18:29:13 +00:00
V_DrawString ( 20 , 24 , highlightflags , " Total Play Time: " ) ;
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 32 , 0 , va ( " %i hours, %i minutes, %i seconds " ,
2014-03-15 16:59:03 +00:00
G_TicsToHours ( totalplaytime ) ,
G_TicsToMinutes ( totalplaytime , false ) ,
G_TicsToSeconds ( totalplaytime ) ) ) ;
2018-07-12 14:45:00 +00:00
V_DrawString ( 20 , 42 , highlightflags , " Total Matches: " ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH - 16 , 42 , 0 , va ( " %i played " , matchesplayed ) ) ;
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < NUMMAPS ; i + + )
{
if ( ! mapheaderinfo [ i ] | | ! ( mapheaderinfo [ i ] - > menuflags & LF2_RECORDATTACK ) )
continue ;
2018-07-01 18:29:13 +00:00
if ( ! mainrecords [ i ] | | mainrecords [ i ] - > time < = 0 )
2014-03-15 16:59:03 +00:00
{
2018-01-22 00:15:26 +00:00
mapsunfinished + + ;
2014-03-15 16:59:03 +00:00
continue ;
}
2018-07-01 18:29:13 +00:00
besttime + = mainrecords [ i ] - > time ;
2014-03-15 16:59:03 +00:00
}
2018-07-12 14:45:00 +00:00
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 ) ;
2018-07-01 18:29:13 +00:00
if ( mapsunfinished )
2018-07-12 14:45:00 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - 16 , 70 , warningflags , va ( " (%d unfinished) " , mapsunfinished ) ) ;
2018-07-01 18:29:13 +00:00
else
2018-07-12 14:45:00 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - 16 , 70 , recommendedflags , " (complete) " ) ;
2014-03-15 16:59:03 +00:00
2018-07-12 14:45:00 +00:00
V_DrawString ( 36 , 70 , 0 , va ( " x %d/%d " , M_CountEmblems ( ) , numemblems + numextraemblems ) ) ;
V_DrawSmallScaledPatch ( 20 , 70 , 0 , W_CachePatchName ( " EMBLICON " , PU_STATIC ) ) ;
2014-03-15 16:59:03 +00:00
2018-07-01 18:29:13 +00:00
M_DrawStatsMaps ( statsLocation ) ;
2014-03-15 16:59:03 +00:00
}
2018-07-01 18:29:13 +00:00
// Handle statistics.
static void M_HandleLevelStats ( INT32 choice )
2014-03-15 16:59:03 +00:00
{
boolean exitmenu = false ; // exit to previous menu
switch ( choice )
{
2018-07-01 18:29:13 +00:00
case KEY_DOWNARROW :
S_StartSound ( NULL , sfx_menu1 ) ;
if ( statsLocation < statsMax )
+ + statsLocation ;
2014-03-15 16:59:03 +00:00
break ;
2018-07-01 18:29:13 +00:00
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 :
2014-03-15 16:59:03 +00:00
S_StartSound ( NULL , sfx_menu1 ) ;
2018-07-01 18:29:13 +00:00
statsLocation - = ( statsLocation < 13 ) ? statsLocation : 13 ;
break ;
case KEY_ESCAPE :
exitmenu = true ;
2014-03-15 16:59:03 +00:00
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 ;
2018-07-02 00:55:01 +00:00
patch_t * PictureOfUrFace ;
2014-03-15 16:59:03 +00:00
2018-07-02 00:55:01 +00:00
//S_ChangeMusicInternal("racent", true); // Eww, but needed for when user hits escape during demo playback
2014-03-15 16:59:03 +00:00
V_DrawPatchFill ( W_CachePatchName ( " SRB2BACK " , PU_CACHE ) ) ;
M_DrawMenuTitle ( ) ;
2018-07-02 00:55:01 +00:00
if ( currentMenu = = & SP_TimeAttackDef )
2018-07-06 17:08:35 +00:00
M_DrawLevelSelectOnly ( true , false ) ;
2014-03-15 16:59:03 +00:00
// 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 ;
2018-07-02 00:55:01 +00:00
// Character face!
if ( W_CheckNumForName ( skins [ cv_chooseskin . value - 1 ] . face ) ! = LUMPERROR )
{
UINT8 * colormap = R_GetTranslationColormap ( cv_chooseskin . value - 1 , cv_playercolor . value , 0 ) ;
PictureOfUrFace = W_CachePatchName ( skins [ cv_chooseskin . value - 1 ] . face , PU_CACHE ) ;
V_DrawMappedPatch ( BASEVIDWIDTH - x - SHORT ( PictureOfUrFace - > width ) , y , 0 , PictureOfUrFace , colormap ) ;
}
2014-03-15 16:59:03 +00:00
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 ] . alphaKey ;
if ( i = = itemOn )
cursory = y ;
2018-07-01 18:29:13 +00:00
V_DrawString ( x , y , ( dispstatus = = IT_WHITESTRING ) ? highlightflags : 0 , currentMenu - > menuitems [ i ] . text ) ;
2014-03-15 16:59:03 +00:00
// Cvar specific handling
if ( ( currentMenu - > menuitems [ i ] . status & IT_TYPE ) = = IT_CVAR )
{
consvar_t * cv = ( consvar_t * ) currentMenu - > menuitems [ i ] . itemaction ;
2018-07-01 18:29:13 +00:00
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
{
2018-07-02 00:55:01 +00:00
const char * str = ( ( cv = = & cv_chooseskin ) ? skins [ cv_chooseskin . value - 1 ] . realname : cv - > string ) ;
INT32 soffset = 40 , strw = V_StringWidth ( str , 0 ) ;
2014-03-15 16:59:03 +00:00
2018-07-02 00:55:01 +00:00
// hack to keep the menu from overlapping the level icon
if ( currentMenu ! = & SP_TimeAttackDef | | cv = = & cv_nextmap )
soffset = 0 ;
2014-03-15 16:59:03 +00:00
2018-07-01 18:29:13 +00:00
// Should see nothing but strings
2018-07-02 00:55:01 +00:00
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
}
2018-07-01 18:29:13 +00:00
}
2014-03-15 16:59:03 +00:00
}
2017-10-21 02:01:07 +00:00
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
2018-07-01 18:29:13 +00:00
V_DrawString ( BASEVIDWIDTH - x - 80 - V_StringWidth ( cv_dummystaff . string , 0 ) , y , highlightflags , cv_dummystaff . string ) ;
2014-03-15 16:59:03 +00:00
}
2018-07-02 00:55:01 +00:00
x = currentMenu - > x ;
y = currentMenu - > y ;
2014-03-15 16:59:03 +00:00
2018-07-02 00:55:01 +00:00
// 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 ) ;
2014-03-15 16:59:03 +00:00
// Level record list
if ( cv_nextmap . value )
{
2018-08-29 20:37:47 +00:00
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 , 239 ) ;
V_DrawRightAlignedString ( 149 , 80 , highlightflags , " BEST LAP: " ) ;
K_drawKartTimestamp ( lap , 19 , 86 , 0 , false ) ;
V_DrawRightAlignedString ( 292 , 80 , highlightflags , " BEST TIME: " ) ;
K_drawKartTimestamp ( time , 162 , 86 , cv_nextmap . value , false ) ;
}
/*{
char beststr [ 40 ] ;
2014-03-15 16:59:03 +00:00
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 ) ) ;
2018-07-02 00:55:01 +00:00
V_DrawString ( 64 , y + 48 , highlightflags , " BEST TIME: " ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH - 64 - 24 - 8 , y + 48 , V_ALLOWLOWERCASE , beststr ) ;
2018-01-22 00:15:26 +00:00
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 ) ) ;
2018-07-02 00:55:01 +00:00
V_DrawString ( 64 , y + 56 , highlightflags , " BEST LAP: " ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH - 64 - 24 - 8 , y + 56 , V_ALLOWLOWERCASE , beststr ) ;
2014-03-15 16:59:03 +00:00
// Draw record emblems.
em = M_GetLevelEmblems ( cv_nextmap . value ) ;
while ( em )
{
switch ( em - > type )
{
2018-07-02 00:55:01 +00:00
case ET_TIME : break ;
2014-03-15 16:59:03 +00:00
default :
goto skipThisOne ;
}
if ( em - > collected )
2018-07-02 00:55:01 +00:00
V_DrawMappedPatch ( BASEVIDWIDTH - 64 - 24 , y + 48 , 0 , W_CachePatchName ( M_GetEmblemPatch ( em ) , PU_CACHE ) ,
2014-03-15 16:59:03 +00:00
R_GetTranslationColormap ( TC_DEFAULT , M_GetEmblemColor ( em ) , GTC_CACHE ) ) ;
else
2018-07-02 00:55:01 +00:00
V_DrawScaledPatch ( BASEVIDWIDTH - 64 - 24 , y + 48 , 0 , W_CachePatchName ( " NEEDIT " , PU_CACHE ) ) ;
2014-03-15 16:59:03 +00:00
skipThisOne :
em = M_GetLevelEmblems ( - 1 ) ;
}
2018-08-29 20:37:47 +00:00
} */
2014-03-15 16:59:03 +00:00
2018-07-02 00:55:01 +00:00
// ALWAYS DRAW player name, level name, skin and color even when not on this menu!
2014-03-15 16:59:03 +00:00
if ( currentMenu ! = & SP_TimeAttackDef )
{
consvar_t * ncv ;
2018-07-02 00:55:01 +00:00
for ( i = 0 ; i < 4 ; + + i )
2014-03-15 16:59:03 +00:00
{
2018-07-02 00:55:01 +00:00
y = currentMenu - > y + SP_TimeAttackMenu [ i ] . alphaKey ;
V_DrawString ( x , y , V_TRANSLUCENT , SP_TimeAttackMenu [ i ] . text ) ;
2014-03-15 16:59:03 +00:00
ncv = ( consvar_t * ) SP_TimeAttackMenu [ i ] . itemaction ;
2018-07-02 00:55:01 +00:00
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 ) ;
}
2017-10-21 17:22:54 +00:00
else
2018-07-02 00:55:01 +00:00
{
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 ) ;
}
2014-03-15 16:59:03 +00:00
}
}
}
// 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 ) ;
2018-08-15 15:12:36 +00:00
G_SetGamestate ( GS_TIMEATTACK ) ;
if ( cv_nextmap . value )
Nextmap_OnChange ( ) ;
else
CV_AddValue ( & cv_nextmap , 1 ) ;
2014-03-15 16:59:03 +00:00
itemOn = tastart ; // "Start" is selected.
2016-07-06 04:09:17 +00:00
S_ChangeMusicInternal ( " racent " , true ) ;
2014-03-15 16:59:03 +00:00
}
2018-07-04 21:57:50 +00:00
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 ;
}
2014-03-15 16:59:03 +00:00
// Drawing function for Nights Attack
2018-01-22 00:15:26 +00:00
/*void M_DrawNightsAttackMenu(void)
2014-03-15 16:59:03 +00:00
{
patch_t * PictureOfLevel ;
lumpnum_t lumpnum ;
char beststr [ 40 ] ;
2016-07-06 04:09:17 +00:00
S_ChangeMusicInternal ( " racent " , true ) ; // Eww, but needed for when user hits escape during demo playback
2014-03-15 16:59:03 +00:00
V_DrawPatchFill ( W_CachePatchName ( " SRB2BACK " , PU_CACHE ) ) ;
// draw menu (everything else goes on top of it)
M_DrawGenericMenu ( ) ;
// A 160x100 image of the level as entry MAPxxP
lumpnum = W_CheckNumForName ( va ( " %sP " , G_BuildMapName ( cv_nextmap . value ) ) ) ;
if ( lumpnum ! = LUMPERROR )
2018-07-01 18:29:13 +00:00
PictureOfLevel = W_CachePatchNum ( lumpnum , PU_CACHE ) ;
2014-03-15 16:59:03 +00:00
else
PictureOfLevel = W_CachePatchName ( " BLANKLVL " , PU_CACHE ) ;
V_DrawSmallScaledPatch ( 90 , 28 , 0 , PictureOfLevel ) ;
// Level record list
if ( cv_nextmap . value )
{
emblem_t * em ;
INT32 yHeight ;
UINT8 bestoverall = G_GetBestNightsGrade ( cv_nextmap . value , 0 ) ;
UINT8 bestgrade = G_GetBestNightsGrade ( cv_nextmap . value , cv_dummymares . value ) ;
UINT32 bestscore = G_GetBestNightsScore ( cv_nextmap . value , cv_dummymares . value ) ;
tic_t besttime = G_GetBestNightsTime ( cv_nextmap . value , cv_dummymares . value ) ;
if ( P_HasGrades ( cv_nextmap . value , 0 ) )
V_DrawScaledPatch ( 200 , 28 + 8 , 0 , ngradeletters [ bestoverall ] ) ;
2014-11-12 00:55:07 +00:00
if ( currentMenu = = & SP_NightsAttackDef )
2014-03-15 16:59:03 +00:00
{
2014-11-12 00:55:07 +00:00
if ( P_HasGrades ( cv_nextmap . value , cv_dummymares . value ) )
{
2018-07-01 18:29:13 +00:00
V_DrawString ( 160 - 88 , 112 , highlightflags , " BEST GRADE: " ) ;
2014-11-12 00:55:07 +00:00
V_DrawSmallScaledPatch ( 160 + 86 - ( ngradeletters [ bestgrade ] - > width / 2 ) ,
112 + 8 - ( ngradeletters [ bestgrade ] - > height / 2 ) ,
0 , ngradeletters [ bestgrade ] ) ;
}
2014-03-15 16:59:03 +00:00
2014-11-12 00:55:07 +00:00
if ( ! bestscore )
sprintf ( beststr , " (none) " ) ;
else
sprintf ( beststr , " %u " , bestscore ) ;
2014-03-15 16:59:03 +00:00
2018-07-01 18:29:13 +00:00
V_DrawString ( 160 - 88 , 122 , highlightflags , " BEST SCORE: " ) ;
2014-11-12 00:55:07 +00:00
V_DrawRightAlignedString ( 160 + 88 , 122 , V_ALLOWLOWERCASE , beststr ) ;
2014-03-15 16:59:03 +00:00
2014-11-12 00:55:07 +00:00
if ( besttime = = UINT32_MAX )
sprintf ( beststr , " (none) " ) ;
else
sprintf ( beststr , " %i:%02i.%02i " , G_TicsToMinutes ( besttime , true ) ,
G_TicsToSeconds ( besttime ) ,
G_TicsToCentiseconds ( besttime ) ) ;
2014-03-15 16:59:03 +00:00
2018-07-01 18:29:13 +00:00
V_DrawString ( 160 - 88 , 132 , highlightflags , " BEST TIME: " ) ;
2014-11-12 00:55:07 +00:00
V_DrawRightAlignedString ( 160 + 88 , 132 , V_ALLOWLOWERCASE , beststr ) ;
2014-03-15 16:59:03 +00:00
2014-11-12 00:55:07 +00:00
if ( cv_dummymares . value = = 0 ) {
// Draw record emblems.
em = M_GetLevelEmblems ( cv_nextmap . value ) ;
while ( em )
2014-03-15 16:59:03 +00:00
{
2014-11-12 00:55:07 +00:00
switch ( em - > type )
{
case ET_NGRADE : yHeight = 112 ; break ;
case ET_NTIME : yHeight = 132 ; break ;
default :
goto skipThisOne ;
}
2014-03-15 16:59:03 +00:00
2014-11-12 00:55:07 +00:00
if ( em - > collected )
V_DrawSmallMappedPatch ( 160 + 88 , yHeight , 0 , W_CachePatchName ( M_GetEmblemPatch ( em ) , PU_CACHE ) ,
R_GetTranslationColormap ( TC_DEFAULT , M_GetEmblemColor ( em ) , GTC_CACHE ) ) ;
else
V_DrawSmallScaledPatch ( 160 + 88 , yHeight , 0 , W_CachePatchName ( " NEEDIT " , PU_CACHE ) ) ;
2014-03-15 16:59:03 +00:00
2014-11-12 00:55:07 +00:00
skipThisOne :
em = M_GetLevelEmblems ( - 1 ) ;
}
2014-03-15 16:59:03 +00:00
}
}
2014-11-12 00:55:07 +00:00
// ALWAYS DRAW level name even when not on this menu!
else
{
consvar_t * ncv ;
INT32 x = SP_NightsAttackDef . x ;
INT32 y = SP_NightsAttackDef . y ;
ncv = ( consvar_t * ) SP_NightsAttackMenu [ 0 ] . itemaction ;
V_DrawString ( x , y + SP_NightsAttackMenu [ 0 ] . alphaKey , V_TRANSLUCENT , SP_NightsAttackMenu [ 0 ] . text ) ;
V_DrawString ( BASEVIDWIDTH - x - V_StringWidth ( ncv - > string , 0 ) ,
2018-07-01 18:29:13 +00:00
y + SP_NightsAttackMenu [ 0 ] . alphaKey , highlightflags | V_TRANSLUCENT , ncv - > string ) ;
2014-11-12 00:55:07 +00:00
}
2014-03-15 16:59:03 +00:00
}
2018-01-22 00:15:26 +00:00
} */
2014-03-15 16:59:03 +00:00
// Going to Nights Attack menu...
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
/*static void M_NightsAttack(INT32 choice)
2014-03-15 16:59:03 +00:00
{
( void ) choice ;
memset ( skins_cons_t , 0 , sizeof ( skins_cons_t ) ) ;
levellistmode = LLM_NIGHTSATTACK ; // Don't be dependent on cv_newgametype
if ( M_CountLevelsToShowInList ( ) = = 0 )
{
M_StartMessage ( M_GetText ( " No NiGHTS-attackable levels found. \n " ) , NULL , MM_NOTHING ) ;
return ;
}
// This is really just to make sure Sonic is the played character, just in case
M_PatchSkinNameTable ( ) ;
M_PrepareLevelSelect ( ) ;
M_SetupNextMenu ( & SP_NightsAttackDef ) ;
Nextmap_OnChange ( ) ;
itemOn = nastart ; // "Start" is selected.
G_SetGamestate ( GS_TIMEATTACK ) ;
2016-07-06 04:09:17 +00:00
S_ChangeMusicInternal ( " racent " , true ) ;
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
} */
2014-03-15 16:59:03 +00:00
// Player has selected the "START" from the nights attack screen
2018-01-22 00:15:26 +00:00
/*static void M_ChooseNightsAttack(INT32 choice)
2014-03-15 16:59:03 +00:00
{
2014-11-12 00:55:07 +00:00
char nameofdemo [ 256 ] ;
2014-03-15 16:59:03 +00:00
( void ) choice ;
emeralds = 0 ;
M_ClearMenus ( true ) ;
modeattacking = ATTACKING_NIGHTS ;
2014-11-12 00:55:07 +00:00
I_mkdir ( va ( " %s " PATHSEP " replay " , srb2home ) , 0755 ) ;
I_mkdir ( va ( " %s " PATHSEP " replay " PATHSEP " %s " , srb2home , timeattackfolder ) , 0755 ) ;
snprintf ( nameofdemo , sizeof nameofdemo , " replay " PATHSEP " %s " PATHSEP " %s-last " , timeattackfolder , G_BuildMapName ( cv_nextmap . value ) ) ;
if ( ! cv_autorecord . value )
remove ( va ( " %s " PATHSEP " %s.lmp " , srb2home , nameofdemo ) ) ;
else
G_RecordDemo ( nameofdemo ) ;
2017-12-19 06:55:33 +00:00
G_DeferedInitNew ( false , G_BuildMapName ( cv_nextmap . value ) , 0 , 0 , false ) ;
2018-01-22 00:15:26 +00:00
} */
2014-03-15 16:59:03 +00:00
// 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 ) ;
2017-12-19 06:55:33 +00:00
G_DeferedInitNew ( false , G_BuildMapName ( cv_nextmap . value ) , ( UINT8 ) ( cv_chooseskin . value - 1 ) , 0 , false ) ;
2014-03-15 16:59:03 +00:00
}
2017-10-21 02:01:07 +00:00
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 ( ) ;
2017-11-28 06:13:23 +00:00
S_StartSound ( NULL , sfx_menu1 ) ;
2017-10-21 02:01:07 +00:00
break ;
case KEY_UPARROW :
M_PrevOpt ( ) ;
2017-11-28 06:13:23 +00:00
S_StartSound ( NULL , sfx_menu1 ) ;
2017-10-21 02:01:07 +00:00
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 ;
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 ) ;
}
}
2014-03-15 16:59:03 +00:00
// 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
2014-11-12 00:55:07 +00:00
if ( currentMenu = = & SP_ReplayDef )
{
switch ( choice ) {
default :
2017-10-17 00:23:26 +00:00
case 0 : // best time
2014-11-12 00:55:07 +00:00
which = " time-best " ;
break ;
2018-01-22 00:15:26 +00:00
case 1 : // best lap
which = " lap-best " ;
break ;
case 2 : // last
2014-11-12 00:55:07 +00:00
which = " last " ;
break ;
2018-01-22 00:15:26 +00:00
case 3 : // best staff
2017-10-21 02:01:07 +00:00
return ; // M_HandleStaffReplay
2018-01-22 00:15:26 +00:00
case 4 : // guest
2014-11-12 00:55:07 +00:00
// 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 ) ) ;
}
2018-01-22 00:15:26 +00:00
/*else if (currentMenu == &SP_NightsReplayDef)
2014-11-12 00:55:07 +00:00
{
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 ;
2017-10-21 02:01:07 +00:00
case 3 : // staff
return ; // M_HandleStaffReplay
case 4 : // guest
2014-11-12 00:55:07 +00:00
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 ) ) ;
2018-01-22 00:15:26 +00:00
} */
2014-03-15 16:59:03 +00:00
}
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 ) ;
2018-01-22 00:15:26 +00:00
/*if (currentMenu == &SP_NightsGuestReplayDef)
2014-11-12 00:55:07 +00:00
M_SetupNextMenu ( & SP_NightsAttackDef ) ;
2018-01-22 00:15:26 +00:00
else */
2014-11-12 00:55:07 +00:00
M_SetupNextMenu ( & SP_TimeAttackDef ) ;
2014-03-15 16:59:03 +00:00
CV_AddValue ( & cv_nextmap , - 1 ) ;
CV_AddValue ( & cv_nextmap , 1 ) ;
M_StartMessage ( M_GetText ( " Guest replay data erased. \n " ) , NULL , MM_NOTHING ) ;
}
2018-01-22 00:15:26 +00:00
static void M_OverwriteGuest ( const char * which )
2014-03-15 16:59:03 +00:00
{
char * rguest = Z_StrDup ( va ( " %s " PATHSEP " replay " PATHSEP " %s " PATHSEP " %s-guest.lmp " , srb2home , timeattackfolder , G_BuildMapName ( cv_nextmap . value ) ) ) ;
UINT8 * buf ;
2014-11-12 00:55:07 +00:00
size_t len ;
2018-01-22 00:15:26 +00:00
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 ) ;
2014-03-15 16:59:03 +00:00
if ( ! len ) {
return ;
}
if ( FIL_FileExists ( rguest ) ) {
M_StopMessage ( 0 ) ;
remove ( rguest ) ;
}
FIL_WriteFile ( rguest , buf , len ) ;
Z_Free ( rguest ) ;
2018-01-22 00:15:26 +00:00
/*if (currentMenu == &SP_NightsGuestReplayDef)
2014-11-12 00:55:07 +00:00
M_SetupNextMenu ( & SP_NightsAttackDef ) ;
2018-01-22 00:15:26 +00:00
else */
2014-11-12 00:55:07 +00:00
M_SetupNextMenu ( & SP_TimeAttackDef ) ;
2014-03-15 16:59:03 +00:00
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 ;
2018-01-22 00:15:26 +00:00
M_OverwriteGuest ( " time-best " ) ;
}
static void M_OverwriteGuest_Lap ( INT32 choice )
{
( void ) choice ;
M_OverwriteGuest ( " lap-best " ) ;
2014-03-15 16:59:03 +00:00
}
2018-01-22 00:15:26 +00:00
/* SRB2Kart
2014-03-15 16:59:03 +00:00
static void M_OverwriteGuest_Score ( INT32 choice )
{
( void ) choice ;
2018-01-22 00:15:26 +00:00
M_OverwriteGuest ( " score-best " ) ;
2014-03-15 16:59:03 +00:00
}
static void M_OverwriteGuest_Rings ( INT32 choice )
{
( void ) choice ;
2018-01-22 00:15:26 +00:00
M_OverwriteGuest ( " rings-best " ) ;
2017-10-21 02:01:07 +00:00
} */
2014-03-15 16:59:03 +00:00
static void M_OverwriteGuest_Last ( INT32 choice )
{
( void ) choice ;
2018-01-22 00:15:26 +00:00
M_OverwriteGuest ( " last " ) ;
2014-03-15 16:59:03 +00:00
}
static void M_SetGuestReplay ( INT32 choice )
{
void ( * which ) ( INT32 ) ;
switch ( choice )
{
2018-01-22 00:15:26 +00:00
case 0 : // best time
2014-03-15 16:59:03 +00:00
which = M_OverwriteGuest_Time ;
break ;
2018-01-22 00:15:26 +00:00
case 1 : // best lap
which = M_OverwriteGuest_Lap ;
break ;
case 2 : // last
2014-03-15 16:59:03 +00:00
which = M_OverwriteGuest_Last ;
break ;
2018-01-22 00:15:26 +00:00
case 3 : // guest
2014-03-15 16:59:03 +00:00
default :
M_StartMessage ( M_GetText ( " Are you sure you want to \n delete 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 \n overwrite 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 ;
2014-11-12 00:55:07 +00:00
G_CheckDemoStatus ( ) ; // Cancel recording
if ( modeattacking = = ATTACKING_RECORD )
2014-03-15 16:59:03 +00:00
M_ChooseTimeAttack ( 0 ) ;
2018-01-22 00:15:26 +00:00
/*else if (modeattacking == ATTACKING_NIGHTS)
M_ChooseNightsAttack ( 0 ) ; */
2014-03-15 16:59:03 +00:00
}
static void M_ModeAttackEndGame ( INT32 choice )
{
( void ) choice ;
2014-11-12 00:55:07 +00:00
G_CheckDemoStatus ( ) ; // Cancel recording
2014-03-15 16:59:03 +00:00
2018-01-28 04:52:01 +00:00
if ( gamestate = = GS_LEVEL | | gamestate = = GS_INTERMISSION | | gamestate = = GS_VOTING )
2014-11-12 00:55:07 +00:00
Command_ExitGame_f ( ) ;
2014-03-15 16:59:03 +00:00
2014-11-12 00:55:07 +00:00
M_StartControlPanel ( ) ;
switch ( modeattacking )
2014-03-15 16:59:03 +00:00
{
2014-11-12 00:55:07 +00:00
default :
case ATTACKING_RECORD :
currentMenu = & SP_TimeAttackDef ;
break ;
2018-01-22 00:15:26 +00:00
/*case ATTACKING_NIGHTS:
2014-03-15 16:59:03 +00:00
currentMenu = & SP_NightsAttackDef ;
2018-01-22 00:15:26 +00:00
break ; */
2014-03-15 16:59:03 +00:00
}
2014-11-12 00:55:07 +00:00
itemOn = currentMenu - > lastOn ;
G_SetGamestate ( GS_TIMEATTACK ) ;
modeattacking = ATTACKING_NONE ;
2016-07-06 04:09:17 +00:00
S_ChangeMusicInternal ( " racent " , true ) ;
2014-11-12 00:55:07 +00:00
// Update replay availability.
CV_AddValue ( & cv_nextmap , 1 ) ;
CV_AddValue ( & cv_nextmap , - 1 ) ;
2014-03-15 16:59:03 +00:00
}
// ========
// 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 ( demoplayback | | demorecording )
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 ( ) ;
2018-07-01 18:29:13 +00:00
V_DrawString ( currentMenu - > x - 16 , currentMenu - > y , highlightflags , M_GetText ( " Select a room " ) ) ;
2014-03-15 16:59:03 +00:00
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 , j ;
const char * gt = " Unknown " ;
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 ] . alphaKey ,
2018-07-01 18:29:13 +00:00
highlightflags , ( itemOn = = mp_connect_room ) ? " <Select to change> " : " <Offline Mode> " ) ;
2014-03-15 16:59:03 +00:00
else
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x , currentMenu - > y + MP_ConnectMenu [ mp_connect_room ] . alphaKey ,
2018-07-01 18:29:13 +00:00
highlightflags , room_list [ menuRoomIndex ] . name ) ;
2014-03-15 16:59:03 +00:00
// Page num
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x , currentMenu - > y + MP_ConnectMenu [ mp_connect_page ] . alphaKey ,
2018-07-01 18:29:13 +00:00
highlightflags , va ( " %u of %d " , serverlistpage + 1 , numPages ) ) ;
2014-03-15 16:59:03 +00:00
// Horizontal line!
V_DrawFill ( 1 , currentMenu - > y + 40 , 318 , 1 , 0 ) ;
if ( serverlistcount < = 0 )
V_DrawString ( currentMenu - > x , currentMenu - > y + SERVERHEADERHEIGHT , 0 , " No servers found " ) ;
else
for ( i = 0 ; i < min ( serverlistcount - serverlistpage * SERVERS_PER_PAGE , SERVERS_PER_PAGE ) ; i + + )
{
INT32 slindex = i + serverlistpage * SERVERS_PER_PAGE ;
UINT32 globalflags = ( ( serverlist [ slindex ] . info . numberofplayer > = serverlist [ slindex ] . info . maxplayer ) ? V_TRANSLUCENT : 0 )
2018-07-01 18:29:13 +00:00
| ( ( itemOn = = FIRSTSERVERLINE + i ) ? highlightflags : 0 ) | V_ALLOWLOWERCASE ;
2014-03-15 16:59:03 +00:00
V_DrawString ( currentMenu - > x , S_LINEY ( i ) , globalflags , serverlist [ slindex ] . info . servername ) ;
// Don't use color flags intentionally, the global yellow color will auto override the text color code
if ( serverlist [ slindex ] . info . modifiedgame )
V_DrawSmallString ( currentMenu - > x + 202 , S_LINEY ( i ) + 8 , globalflags , " \x85 " " Mod " ) ;
if ( serverlist [ slindex ] . info . cheatsenabled )
V_DrawSmallString ( currentMenu - > x + 222 , S_LINEY ( i ) + 8 , globalflags , " \x83 " " Cheats " ) ;
V_DrawSmallString ( currentMenu - > x , S_LINEY ( i ) + 8 , globalflags ,
va ( " Ping: %u " , ( UINT32 ) LONG ( serverlist [ slindex ] . info . time ) ) ) ;
gt = " Unknown " ;
for ( j = 0 ; gametype_cons_t [ j ] . strvalue ; j + + )
{
if ( gametype_cons_t [ j ] . value = = serverlist [ slindex ] . info . gametype )
gt = gametype_cons_t [ j ] . strvalue ;
}
V_DrawSmallString ( currentMenu - > x + 46 , S_LINEY ( i ) + 8 , globalflags ,
va ( " Players: %02d/%02d " , serverlist [ slindex ] . info . numberofplayer , serverlist [ slindex ] . info . maxplayer ) ) ;
V_DrawSmallString ( currentMenu - > x + 112 , S_LINEY ( i ) + 8 , globalflags , va ( " Gametype: %s " , gt ) ) ;
MP_ConnectMenu [ i + FIRSTSERVERLINE ] . status = IT_STRING | IT_CALL ;
}
localservercount = serverlistcount ;
M_DrawGenericMenu ( ) ;
}
static boolean M_CancelConnect ( void )
{
D_CloseConnection ( ) ;
return true ;
}
// Ascending order, not descending.
// The casts are safe as long as the caller doesn't do anything stupid.
# define SERVER_LIST_ENTRY_COMPARATOR(key) \
static int ServerListEntryComparator_ # # key ( const void * entry1 , const void * entry2 ) \
{ \
2014-03-17 12:13:16 +00:00
const serverelem_t * sa = ( const serverelem_t * ) entry1 , * sb = ( const serverelem_t * ) entry2 ; \
if ( sa - > info . key ! = sb - > info . key ) \
return sa - > info . key - sb - > info . key ; \
return strcmp ( sa - > info . servername , sb - > info . servername ) ; \
}
// This does descending instead of ascending.
# define SERVER_LIST_ENTRY_COMPARATOR_REVERSE(key) \
static int ServerListEntryComparator_ # # key # # _reverse ( const void * entry1 , const void * entry2 ) \
{ \
const serverelem_t * sa = ( const serverelem_t * ) entry1 , * sb = ( const serverelem_t * ) entry2 ; \
if ( sb - > info . key ! = sa - > info . key ) \
return sb - > info . key - sa - > info . key ; \
return strcmp ( sb - > info . servername , sa - > info . servername ) ; \
2014-03-15 16:59:03 +00:00
}
SERVER_LIST_ENTRY_COMPARATOR ( time )
SERVER_LIST_ENTRY_COMPARATOR ( numberofplayer )
2014-03-17 12:13:16 +00:00
SERVER_LIST_ENTRY_COMPARATOR_REVERSE ( numberofplayer )
SERVER_LIST_ENTRY_COMPARATOR_REVERSE ( maxplayer )
2014-03-15 16:59:03 +00:00
SERVER_LIST_ENTRY_COMPARATOR ( gametype )
2014-03-17 12:13:16 +00:00
// Special one for modified state.
static int ServerListEntryComparator_modified ( const void * entry1 , const void * entry2 )
{
const serverelem_t * sa = ( const serverelem_t * ) entry1 , * sb = ( const serverelem_t * ) entry2 ;
// Modified acts as 2 points, cheats act as one point.
int modstate_a = ( sa - > info . cheatsenabled ? 1 : 0 ) | ( sa - > info . modifiedgame ? 2 : 0 ) ;
int modstate_b = ( sb - > info . cheatsenabled ? 1 : 0 ) | ( sb - > info . modifiedgame ? 2 : 0 ) ;
if ( modstate_a ! = modstate_b )
return modstate_a - modstate_b ;
// Default to strcmp.
return strcmp ( sa - > info . servername , sb - > info . servername ) ;
}
2014-03-15 16:59:03 +00:00
# endif
2014-03-17 12:13:16 +00:00
void M_SortServerList ( void )
2014-03-15 16:59:03 +00:00
{
# ifndef NONET
switch ( cv_serversort . value )
{
case 0 : // Ping.
qsort ( serverlist , serverlistcount , sizeof ( serverelem_t ) , ServerListEntryComparator_time ) ;
break ;
2014-03-17 12:13:16 +00:00
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.
2014-03-15 16:59:03 +00:00
qsort ( serverlist , serverlistcount , sizeof ( serverelem_t ) , ServerListEntryComparator_numberofplayer ) ;
break ;
2014-03-17 12:13:16 +00:00
case 4 : // Max players.
qsort ( serverlist , serverlistcount , sizeof ( serverelem_t ) , ServerListEntryComparator_maxplayer_reverse ) ;
break ;
case 5 : // Gametype.
2014-03-15 16:59:03 +00:00
qsort ( serverlist , serverlistcount , sizeof ( serverelem_t ) , ServerListEntryComparator_gametype ) ;
break ;
}
# endif
}
# ifndef NONET
# ifdef UPDATE_ALERT
static int M_CheckMODVersion ( void )
{
char updatestring [ 500 ] ;
const char * updatecheck = GetMODVersion ( ) ;
if ( updatecheck )
{
sprintf ( updatestring , UPDATE_ALERT_STRING , VERSIONSTRING , updatecheck ) ;
M_StartMessage ( updatestring , NULL , MM_NOTHING ) ;
return false ;
} else
return true ;
}
# endif
static void M_ConnectMenu ( INT32 choice )
{
( void ) choice ;
// modified game check: no longer handled
// we don't request a restart unless the filelist differs
// first page of servers
serverlistpage = 0 ;
M_SetupNextMenu ( & MP_ConnectDef ) ;
itemOn = 0 ;
M_Refresh ( 0 ) ;
}
static UINT32 roomIds [ NUM_LIST_ROOMS ] ;
static void M_RoomMenu ( INT32 choice )
{
INT32 i ;
( void ) choice ;
// Display a little "please wait" message.
M_DrawTextBox ( 52 , BASEVIDHEIGHT / 2 - 10 , 25 , 3 ) ;
V_DrawCenteredString ( BASEVIDWIDTH / 2 , BASEVIDHEIGHT / 2 , 0 , " Fetching room info... " ) ;
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
if ( GetRoomsList ( currentMenu = = & MP_ServerDef ) < 0 )
return ;
# ifdef UPDATE_ALERT
if ( ! M_CheckMODVersion ( ) )
return ;
# endif
for ( i = 1 ; i < NUM_LIST_ROOMS + 1 ; + + i )
MP_RoomMenu [ i ] . status = IT_DISABLED ;
memset ( roomIds , 0 , sizeof ( roomIds ) ) ;
for ( i = 0 ; room_list [ i ] . header . buffer [ 0 ] ; i + + )
{
2016-07-06 04:09:17 +00:00
if ( * room_list [ i ] . name ! = ' \0 ' )
2014-03-15 16:59:03 +00:00
{
MP_RoomMenu [ i + 1 ] . text = room_list [ i ] . name ;
roomIds [ i ] = room_list [ i ] . id ;
MP_RoomMenu [ i + 1 ] . status = IT_STRING | IT_CALL ;
}
}
MP_RoomDef . prevMenu = currentMenu ;
M_SetupNextMenu ( & MP_RoomDef ) ;
}
static void M_ChooseRoom ( INT32 choice )
{
if ( choice = = 0 )
ms_RoomId = - 1 ;
else
{
ms_RoomId = roomIds [ choice - 1 ] ;
menuRoomIndex = choice - 1 ;
}
serverlistpage = 0 ;
M_SetupNextMenu ( currentMenu - > prevMenu ) ;
if ( currentMenu = = & MP_ConnectDef )
M_Refresh ( 0 ) ;
}
# endif //NONET
//===========================================================================
// Start Server Menu
//===========================================================================
//
// FindFirstMap
//
2018-06-30 22:18:13 +00:00
// Finds the first map of a particular gametype (or returns the current map)
2014-03-15 16:59:03 +00:00
// Defaults to 1 if nothing found.
//
static INT32 M_FindFirstMap ( INT32 gtype )
{
INT32 i ;
2018-06-30 22:18:13 +00:00
if ( mapheaderinfo [ gamemap ] & & ( mapheaderinfo [ gamemap ] - > typeoflevel & gtype ) )
return gamemap ;
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < NUMMAPS ; i + + )
{
2018-08-15 15:12:36 +00:00
if ( ! mapheaderinfo [ i ] )
continue ;
if ( ! ( mapheaderinfo [ i ] - > typeoflevel & gtype ) )
continue ;
return i + 1 ;
2014-03-15 16:59:03 +00:00
}
return 1 ;
}
static void M_StartServer ( INT32 choice )
{
2017-12-19 01:59:04 +00:00
UINT8 ssplayers = 0 ;
2017-12-17 03:32:43 +00:00
2014-03-15 16:59:03 +00:00
( void ) choice ;
2018-06-30 15:01:03 +00:00
if ( currentMenu = = & MP_SplitServerDef )
ssplayers =
# ifdef NOFOURPLAYER
1 ;
# else
cv_dummysplitplayers . value - 1 ;
# endif
else
2014-03-15 16:59:03 +00:00
netgame = true ;
multiplayer = true ;
// Still need to reset devmode
cv_debug = 0 ;
2014-03-23 16:00:29 +00:00
if ( demoplayback )
2014-03-15 16:59:03 +00:00
G_StopDemo ( ) ;
2014-03-23 16:00:29 +00:00
if ( metalrecording )
G_StopMetalDemo ( ) ;
2014-03-15 16:59:03 +00:00
2018-08-15 15:12:36 +00:00
if ( ! cv_nextmap . value )
2018-08-15 15:59:28 +00:00
CV_SetValue ( & cv_nextmap , G_RandMap ( G_TOLFlag ( cv_newgametype . value ) , - 1 , false , false , 0 , false ) + 1 ) ;
2018-08-15 15:12:36 +00:00
2017-12-19 01:59:04 +00:00
if ( ssplayers < 1 )
2014-03-15 16:59:03 +00:00
{
2018-08-11 21:23:40 +00:00
D_MapChange ( cv_nextmap . value , cv_newgametype . value , ( boolean ) cv_kartencore . value , 1 , 1 , false , false ) ;
2014-03-15 16:59:03 +00:00
COM_BufAddText ( " dummyconsvar 1 \n " ) ;
}
else // split screen
{
paused = false ;
SV_StartSinglePlayerServer ( ) ;
2017-12-17 03:32:43 +00:00
2017-12-19 01:59:04 +00:00
if ( splitscreen ! = ssplayers )
2014-03-15 16:59:03 +00:00
{
2017-12-19 01:59:04 +00:00
splitscreen = ssplayers ;
2014-03-15 16:59:03 +00:00
SplitScreen_OnChange ( ) ;
}
2017-12-17 03:32:43 +00:00
2018-08-11 21:23:40 +00:00
D_MapChange ( cv_nextmap . value , cv_newgametype . value , ( boolean ) cv_kartencore . value , 1 , 1 , false , false ) ;
2014-03-15 16:59:03 +00:00
}
M_ClearMenus ( true ) ;
}
2018-07-02 00:55:01 +00:00
static void M_DrawLevelSelectOnly ( boolean leftfade , boolean rightfade )
2014-03-15 16:59:03 +00:00
{
lumpnum_t lumpnum ;
patch_t * PictureOfLevel ;
2018-07-02 12:20:04 +00:00
INT32 x , y , w , i , oldval , trans , dupadjust = ( ( vid . width / vid . dupx ) - BASEVIDWIDTH ) > > 1 ;
2017-02-07 22:19:04 +00:00
2014-03-15 16:59:03 +00:00
// A 160x100 image of the level as entry MAPxxP
2018-08-15 15:12:36 +00:00
if ( cv_nextmap . value )
{
lumpnum = W_CheckNumForName ( va ( " %sP " , G_BuildMapName ( cv_nextmap . value ) ) ) ;
if ( lumpnum ! = LUMPERROR )
PictureOfLevel = W_CachePatchNum ( lumpnum , PU_CACHE ) ;
else
PictureOfLevel = W_CachePatchName ( " BLANKLVL " , PU_CACHE ) ;
}
2014-03-15 16:59:03 +00:00
else
2018-08-15 15:12:36 +00:00
PictureOfLevel = W_CachePatchName ( " RANDOMLV " , PU_CACHE ) ;
2014-03-15 16:59:03 +00:00
2018-07-02 12:20:04 +00:00
w = SHORT ( PictureOfLevel - > width ) / 2 ;
i = SHORT ( PictureOfLevel - > height ) / 2 ;
x = BASEVIDWIDTH / 2 - w / 2 ;
y = currentMenu - > y + 130 + 8 - i ;
if ( currentMenu - > menuitems [ itemOn ] . itemaction = = & cv_nextmap & & skullAnimCounter < 4 )
trans = 120 ;
else
trans = G_GetGametypeColor ( cv_newgametype . value ) ;
V_DrawFill ( x - 1 , y - 1 , w + 2 , i + 2 , trans ) ; // variable reuse...
2018-06-30 22:18:13 +00:00
2018-08-29 21:02:42 +00:00
if ( ! cv_kartencore . value | | gamestate = = GS_TIMEATTACK | | cv_newgametype . value ! = GT_RACE )
2018-08-10 20:11:45 +00:00
V_DrawSmallScaledPatch ( x , y , 0 , PictureOfLevel ) ;
else
{
2018-08-11 21:23:40 +00:00
/*UINT8 *mappingforencore = NULL;
2018-08-10 20:11:45 +00:00
if ( ( lumpnum = W_CheckNumForName ( va ( " %sE " , mapname ) ) ) ! = LUMPERROR )
2018-08-11 21:23:40 +00:00
mappingforencore = W_CachePatchNum ( lumpnum , PU_CACHE ) ; */
2018-08-10 20:11:45 +00:00
2018-08-14 14:32:17 +00:00
V_DrawFixedPatch ( ( x + w ) < < FRACBITS , ( y ) < < FRACBITS , FRACUNIT / 2 , V_FLIP , PictureOfLevel , 0 ) ;
2018-08-11 21:23:40 +00:00
{
static angle_t rubyfloattime = 0 ;
const fixed_t rubyheight = FINESINE ( rubyfloattime > > ANGLETOFINESHIFT ) ;
V_DrawFixedPatch ( ( x + w / 2 ) < < FRACBITS , ( ( y + i / 2 ) < < FRACBITS ) - ( rubyheight < < 1 ) , FRACUNIT , 0 , W_CachePatchName ( " RUBYICON " , PU_CACHE ) , NULL ) ;
rubyfloattime + = ( ANGLE_MAX / NEWTICRATE ) ;
}
2018-08-10 20:11:45 +00:00
}
2018-07-01 18:29:13 +00:00
/*V_DrawDiag(x, y, 12, 31);
V_DrawDiag ( x , y , 10 , G_GetGametypeColor ( cv_newgametype . value ) ) ; */
2018-06-30 15:01:03 +00:00
2018-07-02 12:20:04 +00:00
y + = i / 4 ;
2018-07-01 18:29:13 +00:00
i = cv_nextmap . value - 1 ;
2018-07-02 00:55:01 +00:00
trans = ( leftfade ? V_TRANSLUCENT : 0 ) ;
2018-07-01 18:29:13 +00:00
# define horizspac 2
do
{
oldval = i ;
do
{
i - - ;
2018-08-15 15:12:36 +00:00
if ( i = = - 2 )
2018-07-01 18:29:13 +00:00
i = NUMMAPS - 1 ;
if ( i = = oldval )
2018-07-02 00:55:01 +00:00
return ;
2018-07-01 18:29:13 +00:00
if ( ! mapheaderinfo [ i ] )
continue ; // Don't allocate the header. That just makes memory usage skyrocket.
} while ( ! M_CanShowLevelInList ( i , cv_newgametype . value ) ) ;
// A 160x100 image of the level as entry MAPxxP
2018-08-15 15:12:36 +00:00
if ( i + 1 )
{
lumpnum = W_CheckNumForName ( va ( " %sP " , G_BuildMapName ( i + 1 ) ) ) ;
if ( lumpnum ! = LUMPERROR )
PictureOfLevel = W_CachePatchNum ( lumpnum , PU_CACHE ) ;
else
PictureOfLevel = W_CachePatchName ( " BLANKLVL " , PU_CACHE ) ;
}
2018-07-01 18:29:13 +00:00
else
2018-08-15 15:12:36 +00:00
PictureOfLevel = W_CachePatchName ( " RANDOMLV " , PU_CACHE ) ;
2018-07-01 18:29:13 +00:00
2018-08-10 20:11:45 +00:00
x - = horizspac + w / 2 ;
2018-07-01 18:29:13 +00:00
V_DrawTinyScaledPatch ( x , y , trans , PictureOfLevel ) ;
} while ( x > horizspac - dupadjust ) ;
2018-07-02 12:20:04 +00:00
x = ( BASEVIDWIDTH + w ) / 2 + horizspac ;
2018-07-01 18:29:13 +00:00
i = cv_nextmap . value - 1 ;
2018-07-02 00:55:01 +00:00
trans = ( rightfade ? V_TRANSLUCENT : 0 ) ;
2018-07-01 18:29:13 +00:00
while ( x < BASEVIDWIDTH + dupadjust - horizspac )
{
oldval = i ;
do
{
i + + ;
if ( i = = NUMMAPS )
2018-08-15 15:12:36 +00:00
i = - 1 ;
2018-07-01 18:29:13 +00:00
if ( i = = oldval )
2018-07-02 00:55:01 +00:00
return ;
2018-07-01 18:29:13 +00:00
if ( ! mapheaderinfo [ i ] )
continue ; // Don't allocate the header. That just makes memory usage skyrocket.
} while ( ! M_CanShowLevelInList ( i , cv_newgametype . value ) ) ;
// A 160x100 image of the level as entry MAPxxP
2018-08-15 15:12:36 +00:00
if ( i + 1 )
{
lumpnum = W_CheckNumForName ( va ( " %sP " , G_BuildMapName ( i + 1 ) ) ) ;
if ( lumpnum ! = LUMPERROR )
PictureOfLevel = W_CachePatchNum ( lumpnum , PU_CACHE ) ;
else
PictureOfLevel = W_CachePatchName ( " BLANKLVL " , PU_CACHE ) ;
}
2018-07-01 18:29:13 +00:00
else
2018-08-15 15:12:36 +00:00
PictureOfLevel = W_CachePatchName ( " RANDOMLV " , PU_CACHE ) ;
2018-07-01 18:29:13 +00:00
2018-07-02 00:55:01 +00:00
V_DrawTinyScaledPatch ( x , y , trans , PictureOfLevel ) ;
2018-08-10 20:11:45 +00:00
x + = horizspac + w / 2 ;
2018-07-01 18:29:13 +00:00
}
# undef horizspac
2018-07-02 00:55:01 +00:00
}
2018-07-01 18:29:13 +00:00
2018-07-02 00:55:01 +00:00
static void M_DrawServerMenu ( void )
{
M_DrawLevelSelectOnly ( ( currentMenu = = & MP_SplitServerDef ) , false ) ;
2018-07-01 18:29:13 +00:00
M_DrawGenericMenu ( ) ;
2018-07-02 00:55:01 +00:00
# ifndef NONET
// Room name
if ( currentMenu = = & MP_ServerDef )
{
# define mp_server_room 1
if ( ms_RoomId < 0 )
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x , currentMenu - > y + MP_ServerMenu [ mp_server_room ] . alphaKey ,
highlightflags , ( itemOn = = mp_server_room ) ? " <Select to change> " : " <Offline Mode> " ) ;
else
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x , currentMenu - > y + MP_ServerMenu [ mp_server_room ] . alphaKey ,
highlightflags , room_list [ menuRoomIndex ] . name ) ;
# undef mp_server_room
}
else
# endif
if ( currentMenu = = & MP_SplitServerDef )
2018-06-30 15:01:03 +00:00
// character bar, ripped off the color bar :V
2018-07-02 00:55:01 +00:00
{
2018-06-30 15:01:03 +00:00
# define iconwidth 32
# define spacingwidth 32
# define incrwidth (iconwidth + spacingwidth)
UINT8 i = 0 , pskin , pcol ;
2018-06-30 22:18:13 +00:00
// player arrangement width, but there's also a chance i'm a furry, shhhhhh
2018-06-30 15:01:03 +00:00
const INT32 paw = iconwidth +
# ifndef NOFOURPLAYER
3 *
# endif
incrwidth ;
2018-08-15 14:22:50 +00:00
INT32 x = BASEVIDWIDTH / 2 - paw / 2 , y = currentMenu - > y + 27 , trans = 0 ;
2018-06-30 15:01:03 +00:00
patch_t * face ;
while ( + + i < =
# ifdef NOFOURPLAYER
2
# else
4
# endif
)
{
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 ;
# ifndef NOFOURPLAYER
if ( ! trans & & i > cv_dummysplitplayers . value )
trans = V_TRANSLUCENT ;
# endif
face = W_CachePatchName ( skins [ pskin ] . face , PU_CACHE ) ;
V_DrawFixedPatch ( x < < FRACBITS , y < < FRACBITS , FRACUNIT , trans , face , R_GetTranslationColormap ( pskin , pcol , 0 ) ) ;
x + = incrwidth ;
}
# undef incrwidth
# undef spacingwidth
# undef iconwidth
2018-07-02 00:55:01 +00:00
}
2014-03-15 16:59:03 +00:00
}
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_StartSplitServerMenu ( INT32 choice )
{
( void ) choice ;
levellistmode = LLM_CREATESERVER ;
M_PrepareLevelSelect ( ) ;
M_SetupNextMenu ( & MP_SplitServerDef ) ;
}
# 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 [ 16 ] ;
// Draw the funky Connect IP menu. Tails 11-19-2002
// So much work for such a little thing!
2018-06-30 15:01:03 +00:00
static void M_DrawMPMainMenu ( void )
2014-03-15 16:59:03 +00:00
{
2018-06-30 15:01:03 +00:00
INT32 x = currentMenu - > x ;
INT32 y = currentMenu - > y ;
2014-03-15 16:59:03 +00:00
// use generic drawer for cursor, items and title
M_DrawGenericMenu ( ) ;
2018-06-30 15:01:03 +00:00
# if MAXPLAYERS == 16
2018-07-06 17:08:35 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - x , y + MP_MainMenu [ 1 ] . alphaKey ,
( ( itemOn = = 1 ) ? highlightflags : 0 ) , " (2-16 players) " ) ;
2018-06-30 15:01:03 +00:00
# else
Update the maxplayers label . . .
# endif
2018-07-06 17:08:35 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - x , y + MP_MainMenu [ 2 ] . alphaKey ,
( ( itemOn = = 2 ) ? highlightflags : 0 ) ,
2018-06-30 15:01:03 +00:00
# ifdef NOFOURPLAYER
" (2 players) "
# else
" (2-4 players) "
# endif
) ;
2018-07-06 17:08:35 +00:00
y + = MP_MainMenu [ 5 ] . alphaKey ;
2018-06-30 15:01:03 +00:00
V_DrawFill ( x + 5 , y + 4 + 5 , /*16*8 + 6,*/ BASEVIDWIDTH - 2 * ( x + 5 ) , 8 + 6 , 239 ) ;
2014-03-15 16:59:03 +00:00
// draw name string
2018-06-30 15:01:03 +00:00
V_DrawString ( x + 8 , y + 12 , V_MONOSPACE , setupm_ip ) ;
2014-03-15 16:59:03 +00:00
// draw text cursor for name
2018-07-06 17:08:35 +00:00
if ( itemOn = = 5
2018-06-30 15:01:03 +00:00
& & skullAnimCounter < 4 ) //blink cursor
V_DrawCharacter ( x + 8 + V_StringWidth ( setupm_ip , V_MONOSPACE ) , y + 12 , ' _ ' , false ) ;
2014-03-15 16:59:03 +00:00
}
// Tails 11-19-2002
static void M_ConnectIP ( INT32 choice )
{
( void ) choice ;
2018-01-12 01:35:39 +00:00
if ( * setupm_ip = = 0 )
{
M_StartMessage ( " You must specify an IP address. \n " , NULL , MM_NOTHING ) ;
return ;
}
2014-03-15 16:59:03 +00:00
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 )
{
2018-06-30 15:01:03 +00:00
size_t l ;
boolean exitmenu = false ; // exit to previous menu and send name change
2014-03-15 16:59:03 +00:00
switch ( choice )
{
2018-06-30 15:01:03 +00:00
case KEY_DOWNARROW :
M_NextOpt ( ) ;
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
break ;
case KEY_UPARROW :
M_PrevOpt ( ) ;
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
break ;
2014-03-15 16:59:03 +00:00
case KEY_ENTER :
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
M_ClearMenus ( true ) ;
M_ConnectIP ( 1 ) ;
break ;
case KEY_ESCAPE :
exitmenu = true ;
break ;
case KEY_BACKSPACE :
2018-06-30 15:01:03 +00:00
if ( ( l = strlen ( setupm_ip ) ) ! = 0 )
2014-03-15 16:59:03 +00:00
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
2018-06-30 15:01:03 +00:00
setupm_ip [ l - 1 ] = 0 ;
}
break ;
case KEY_DEL :
if ( setupm_ip [ 0 ] )
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
setupm_ip [ 0 ] = 0 ;
2014-03-15 16:59:03 +00:00
}
break ;
default :
l = strlen ( setupm_ip ) ;
2018-06-30 15:01:03 +00:00
if ( l > = 16 - 1 )
break ;
if ( choice = = 46 | | ( choice > = 48 & & choice < = 57 ) ) // Rudimentary number and period enforcing
2014-03-15 16:59:03 +00:00
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
2018-06-30 15:01:03 +00:00
setupm_ip [ l ] = ( char ) choice ;
setupm_ip [ l + 1 ] = 0 ;
2014-03-15 16:59:03 +00:00
}
2018-06-30 15:01:03 +00:00
else if ( choice > = 199 & & choice < = 211 & & choice ! = 202 & & choice ! = 206 ) //numpad too!
2014-03-15 16:59:03 +00:00
{
2018-06-30 15:01:03 +00:00
char keypad_translation [ ] = { ' 7 ' , ' 8 ' , ' 9 ' , ' - ' , ' 4 ' , ' 5 ' , ' 6 ' , ' + ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 0 ' , ' . ' } ;
2014-03-15 16:59:03 +00:00
choice = keypad_translation [ choice - 199 ] ;
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
2018-06-30 15:01:03 +00:00
setupm_ip [ l ] = ( char ) choice ;
setupm_ip [ l + 1 ] = 0 ;
2014-03-15 16:59:03 +00:00
}
2018-06-30 15:01:03 +00:00
2014-03-15 16:59:03 +00:00
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 ;
2017-11-28 06:13:23 +00:00
patch_t * statbg = W_CachePatchName ( " K_STATBG " , PU_CACHE ) ;
2018-09-03 04:06:17 +00:00
patch_t * statlr = W_CachePatchName ( " K_STATLR " , PU_CACHE ) ;
patch_t * statud = W_CachePatchName ( " K_STATUD " , PU_CACHE ) ;
2017-11-28 06:13:23 +00:00
patch_t * statdot = W_CachePatchName ( " K_SDOT0 " , PU_CACHE ) ;
2014-03-15 16:59:03 +00:00
patch_t * patch ;
UINT8 frame ;
2017-11-28 06:13:23 +00:00
UINT8 speed ;
UINT8 weight ;
UINT8 i ;
2018-07-01 18:29:13 +00:00
const UINT8 * flashcol = V_GetStringColormap ( highlightflags ) ;
2018-09-03 04:06:17 +00:00
INT32 statx , staty ;
2014-03-15 16:59:03 +00:00
mx = MP_PlayerSetupDef . x ;
my = MP_PlayerSetupDef . y ;
2018-09-03 04:06:17 +00:00
statx = ( BASEVIDWIDTH - mx - 118 ) ;
staty = ( my + 62 ) ;
2014-03-15 16:59:03 +00:00
// use generic drawer for cursor, items and title
M_DrawGenericMenu ( ) ;
// draw name string
2017-11-28 21:57:38 +00:00
M_DrawTextBox ( mx + 32 , my - 8 , MAXPLAYERNAME , 1 ) ;
V_DrawString ( mx + 40 , my , V_ALLOWLOWERCASE , setupm_name ) ;
2014-03-15 16:59:03 +00:00
2018-07-01 18:29:13 +00:00
// draw text cursor for name
if ( ! itemOn & & skullAnimCounter < 4 ) // blink cursor
V_DrawCharacter ( mx + 40 + V_StringWidth ( setupm_name , V_ALLOWLOWERCASE ) , my , ' _ ' , false ) ;
2014-03-15 16:59:03 +00:00
// draw skin string
2018-07-02 13:43:52 +00:00
st = V_StringWidth ( skins [ setupm_fakeskin ] . realname , 0 ) ;
V_DrawString ( BASEVIDWIDTH - mx - st , my + 16 ,
2018-07-01 18:29:13 +00:00
( ( MP_PlayerSetupMenu [ 2 ] . status & IT_TYPE ) = = IT_SPACE ? V_TRANSLUCENT : 0 ) | highlightflags | V_ALLOWLOWERCASE ,
2014-03-15 16:59:03 +00:00
skins [ setupm_fakeskin ] . realname ) ;
2018-07-02 13:43:52 +00:00
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
}
2014-03-15 16:59:03 +00:00
// draw the name of the color you have chosen
// Just so people don't go thinking that "Default" is Green.
2018-07-02 13:43:52 +00:00
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
}
2017-11-28 06:13:23 +00:00
// SRB2Kart: draw the stat backer
2018-09-03 04:06:17 +00:00
// 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 ) < < FRACBITS , staty < < FRACBITS , FRACUNIT , 0 , statlr , flashcol ) ;
V_DrawFixedPatch ( ( statx + 24 ) < < FRACBITS , ( staty + 22 ) < < FRACBITS , FRACUNIT , 0 , statud , flashcol ) ;
// bg
V_DrawFixedPatch ( ( statx + 34 ) < < FRACBITS , ( staty + 10 ) < < FRACBITS , FRACUNIT , 0 , statbg , 0 ) ;
2017-11-28 06:13:23 +00:00
2017-11-28 21:57:38 +00:00
for ( i = 0 ; i < numskins ; i + + ) // draw the stat dots
2017-11-28 06:13:23 +00:00
{
if ( i ! = setupm_fakeskin & & R_SkinAvailable ( skins [ i ] . name ) ! = - 1 )
{
speed = skins [ i ] . kartspeed ;
weight = skins [ i ] . kartweight ;
2018-07-02 13:43:52 +00:00
V_DrawFixedPatch ( ( ( BASEVIDWIDTH - mx - 80 ) + ( ( speed - 1 ) * 8 ) ) < < FRACBITS , ( ( my + 76 ) + ( ( weight - 1 ) * 8 ) ) < < FRACBITS , FRACUNIT , 0 , statdot , NULL ) ;
2017-11-28 06:13:23 +00:00
}
}
2014-03-15 16:59:03 +00:00
2018-07-01 18:29:13 +00:00
speed = skins [ setupm_fakeskin ] . kartspeed ;
weight = skins [ setupm_fakeskin ] . kartweight ;
statdot = W_CachePatchName ( " K_SDOT1 " , PU_CACHE ) ;
if ( skullAnimCounter < 4 ) // SRB2Kart: we draw this dot later so that it's not covered if there's multiple skins with the same stats
2018-07-02 13:43:52 +00:00
V_DrawFixedPatch ( ( ( BASEVIDWIDTH - mx - 80 ) + ( ( speed - 1 ) * 8 ) ) < < FRACBITS , ( ( my + 76 ) + ( ( weight - 1 ) * 8 ) ) < < FRACBITS , FRACUNIT , 0 , statdot , flashcol ) ;
2018-07-01 18:29:13 +00:00
else
2018-07-02 13:43:52 +00:00
V_DrawFixedPatch ( ( ( BASEVIDWIDTH - mx - 80 ) + ( ( speed - 1 ) * 8 ) ) < < FRACBITS , ( ( my + 76 ) + ( ( weight - 1 ) * 8 ) ) < < FRACBITS , FRACUNIT , 0 , statdot , NULL ) ;
2018-07-01 18:29:13 +00:00
statdot = W_CachePatchName ( " K_SDOT2 " , PU_CACHE ) ; // coloured center
2018-07-02 13:43:52 +00:00
if ( setupm_fakecolor )
V_DrawFixedPatch ( ( ( BASEVIDWIDTH - mx - 80 ) + ( ( speed - 1 ) * 8 ) ) < < FRACBITS , ( ( my + 76 ) + ( ( weight - 1 ) * 8 ) ) < < FRACBITS , FRACUNIT , 0 , statdot , R_GetTranslationColormap ( 0 , setupm_fakecolor , 0 ) ) ;
2018-07-01 18:29:13 +00:00
2017-11-28 21:57:38 +00:00
// 2.2 color bar backported with permission
2018-07-02 13:43:52 +00:00
# define charw 72
2017-11-28 21:57:38 +00:00
# define indexwidth 8
{
2018-07-02 13:43:52 +00:00
const INT32 colwidth = ( ( BASEVIDWIDTH - ( 2 * mx ) ) - charw ) / ( 2 * indexwidth ) ;
2017-12-04 01:00:31 +00:00
INT32 j = - colwidth ;
2017-11-28 21:57:38 +00:00
INT16 col = setupm_fakecolor - colwidth ;
2018-07-02 13:43:52 +00:00
INT32 x = mx ;
2017-11-28 21:57:38 +00:00
INT32 w = indexwidth ;
UINT8 h ;
while ( col < 1 )
col + = MAXSKINCOLORS - 1 ;
2017-12-04 01:00:31 +00:00
while ( j < = colwidth )
2017-11-28 21:57:38 +00:00
{
2017-12-04 01:00:31 +00:00
if ( ! ( j + + ) )
2017-11-28 21:57:38 +00:00
w = charw ;
else
w = indexwidth ;
for ( h = 0 ; h < 16 ; h + + )
2018-07-02 13:43:52 +00:00
V_DrawFill ( x , my + 162 + h , w , 1 , colortranslations [ col ] [ h ] ) ;
2017-11-28 21:57:38 +00:00
if ( + + col > = MAXSKINCOLORS )
col - = MAXSKINCOLORS - 1 ;
x + = w ;
}
}
# undef indexwidth
// character bar, ripped off the color bar :V
2018-07-02 13:43:52 +00:00
if ( setupm_fakecolor ) // inverse should never happen
2017-11-28 21:57:38 +00:00
# define iconwidth 32
{
const INT32 icons = 4 ;
2017-12-04 01:00:31 +00:00
INT32 k = - icons ;
2017-11-28 21:57:38 +00:00
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 = W_CachePatchName ( " K_CHRCUR " , PU_CACHE ) ;
patch_t * face ;
if ( col < 0 )
col + = numskins ;
2017-12-04 01:00:31 +00:00
while ( k < = icons )
2017-11-28 21:57:38 +00:00
{
2017-12-04 01:00:31 +00:00
if ( ! ( k + + ) )
2017-11-28 21:57:38 +00:00
{
scale = FRACUNIT ;
offx = 12 ;
offy = 0 ;
}
else
{
scale = FRACUNIT / 2 ;
offx = 8 ;
offy = 8 ;
}
face = W_CachePatchName ( skins [ col ] . face , PU_CACHE ) ;
V_DrawFixedPatch ( ( x + offx ) < < FRACBITS , ( my + 28 + offy ) < < FRACBITS , scale , 0 , face , R_GetTranslationColormap ( col , setupm_fakecolor , 0 ) ) ;
if ( scale = = FRACUNIT ) // bit of a hack
V_DrawFixedPatch ( ( x - 2 + offx ) < < FRACBITS , ( my + 26 + offy ) < < FRACBITS , scale , 0 , cursor , R_GetTranslationColormap ( col , setupm_fakecolor , 0 ) ) ;
if ( + + col > = numskins )
col - = numskins ;
x + = FixedMul ( iconwidth < < FRACBITS , 3 * scale / 2 ) / FRACUNIT ;
}
}
# undef iconwidth
2014-03-15 16:59:03 +00:00
// anim the player in the box
if ( - - multi_tics < = 0 )
{
st = multi_state - > 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 ] ;
2017-11-28 06:13:23 +00:00
patch = W_CachePatchNum ( sprframe - > lumppat [ 1 ] , PU_CACHE ) ;
2014-03-15 16:59:03 +00:00
if ( sprframe - > flip & 1 ) // Only for first sprite
flags | = V_FLIP ; // This sprite is left/right flipped!
// draw box around guy
2018-07-02 13:43:52 +00:00
V_DrawFill ( mx + 43 - ( charw / 2 ) , my + 65 , charw , 84 , 239 ) ;
2017-11-28 06:13:23 +00:00
2014-03-15 16:59:03 +00:00
// draw player sprite
2018-07-02 13:43:52 +00:00
if ( setupm_fakecolor ) // inverse should never happen
2014-03-15 16:59:03 +00:00
{
UINT8 * colormap = R_GetTranslationColormap ( setupm_fakeskin , setupm_fakecolor , 0 ) ;
2014-08-04 03:49:33 +00:00
if ( skins [ setupm_fakeskin ] . flags & SF_HIRES )
{
2018-07-02 13:43:52 +00:00
V_DrawFixedPatch ( ( mx + 43 ) < < FRACBITS ,
( my + 131 ) < < FRACBITS ,
2014-08-04 03:49:33 +00:00
skins [ setupm_fakeskin ] . highresscale ,
flags , patch , colormap ) ;
}
2014-03-15 16:59:03 +00:00
else
2018-07-02 13:43:52 +00:00
V_DrawMappedPatch ( mx + 43 , my + 131 , flags , patch , colormap ) ;
2014-03-15 16:59:03 +00:00
Z_Free ( colormap ) ;
}
2017-11-28 21:57:38 +00:00
# undef charw
2014-03-15 16:59:03 +00:00
}
// Handle 1P/2P MP Setup
static void M_HandleSetupMultiPlayer ( 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_LEFTARROW :
2017-11-28 06:13:23 +00:00
if ( itemOn = = 1 ) //player skin
2014-03-15 16:59:03 +00:00
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
setupm_fakeskin - - ;
}
2017-11-28 06:13:23 +00:00
else if ( itemOn = = 2 ) // player color
2014-03-15 16:59:03 +00:00
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
setupm_fakecolor - - ;
}
break ;
case KEY_RIGHTARROW :
2017-11-28 06:13:23 +00:00
if ( itemOn = = 1 ) //player skin
2014-03-15 16:59:03 +00:00
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
setupm_fakeskin + + ;
}
2017-11-28 06:13:23 +00:00
else if ( itemOn = = 2 ) // player color
2014-03-15 16:59:03 +00:00
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
setupm_fakecolor + + ;
}
break ;
case KEY_ESCAPE :
exitmenu = true ;
break ;
case KEY_BACKSPACE :
2018-07-06 17:08:35 +00:00
if ( itemOn = = 0 )
2014-03-15 16:59:03 +00:00
{
2018-07-06 17:08:35 +00:00
if ( ( l = strlen ( setupm_name ) ) ! = 0 )
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
setupm_name [ l - 1 ] = 0 ;
}
}
else if ( itemOn = = 2 )
{
UINT8 col = skins [ setupm_fakeskin ] . prefcolor ;
if ( setupm_fakecolor ! = col )
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
setupm_fakecolor = col ;
}
2014-03-15 16:59:03 +00:00
}
break ;
2018-06-30 22:18:13 +00:00
case KEY_DEL :
if ( itemOn = = 0 & & ( l = strlen ( setupm_name ) ) ! = 0 )
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
setupm_name [ 0 ] = 0 ;
}
break ;
2014-03-15 16:59:03 +00:00
default :
if ( choice < 32 | | choice > 127 | | itemOn ! = 0 )
break ;
l = strlen ( setupm_name ) ;
2018-06-26 16:46:04 +00:00
if ( l < MAXPLAYERNAME )
2014-03-15 16:59:03 +00:00
{
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 [ secondarydisplayplayer ] ;
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 ( secondarydisplayplayer ) )
MP_PlayerSetupMenu [ 2 ] . status = ( IT_GRAYEDOUT ) ;
else
MP_PlayerSetupMenu [ 2 ] . status = ( IT_KEYHANDLER | IT_STRING ) ;
MP_PlayerSetupDef . prevMenu = currentMenu ;
M_SetupNextMenu ( & MP_PlayerSetupDef ) ;
}
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2017-12-08 07:29:01 +00:00
// 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 [ thirddisplayplayer ] ;
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
2017-12-19 01:59:04 +00:00
if ( splitscreen > 1 & & ! CanChangeSkin ( thirddisplayplayer ) )
2017-12-08 07:29:01 +00:00
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 [ fourthdisplayplayer ] ;
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
2017-12-19 01:59:04 +00:00
if ( splitscreen > 2 & & ! CanChangeSkin ( fourthdisplayplayer ) )
2017-12-08 07:29:01 +00:00
MP_PlayerSetupMenu [ 2 ] . status = ( IT_GRAYEDOUT ) ;
else
MP_PlayerSetupMenu [ 2 ] . status = ( IT_KEYHANDLER | IT_STRING ) ;
MP_PlayerSetupDef . prevMenu = currentMenu ;
M_SetupNextMenu ( & MP_PlayerSetupDef ) ;
}
2018-01-01 18:11:24 +00:00
# endif
2017-12-08 07:29:01 +00:00
2014-03-15 16:59:03 +00:00
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 ;
// Delete the data
if ( erasecontext ! = 1 )
G_ClearRecords ( ) ;
if ( erasecontext ! = 0 )
M_ClearSecrets ( ) ;
if ( erasecontext = = 2 )
{
totalplaytime = 0 ;
Lots of changes
- Menus now have all of the Kart cvars
- Removed any cvars that aren't useful for Kart from the menu (they
still exist in the console, though)
- Removed SP and NiGHTS Mode options from the main menu
- "kartcc" is renamed "kartspeed", uses values 0-2 instead of multiples
of 50, or the terms "Relaxed", "Standard", and "Turbo"
- Many gametype options (game speed, frantic, mirror, & karma comeback)
are now changed on map load instead of instantly
- New cvar, "kartminimap", for disabling the minimap
- The maxplayers cvar now actually matches up with our 16 player limit
- Game now keeps track of matches played. Has a condition type
associated with it, as well.
- Game checks for unlocks and saves gamedata when finishing a match,
even in MP
- Removed most of the normal emblems, added a single emblem for Green
Hills. Didn't know what to do with extra emblems and such so I just left
them (FOR NOW c:<)
2018-01-16 03:31:14 +00:00
matchesplayed = 0 ;
2014-03-15 16:59:03 +00:00
F_StartIntro ( ) ;
}
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 ( " Secrets 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 ;
M_DrawGenericMenu ( ) ;
2018-07-03 20:18:17 +00:00
for ( i = 0 ; i < 8 ; i + + )
2014-03-15 16:59:03 +00:00
{
M_DrawSaveLoadBorder ( OP_JoystickSetDef . x , OP_JoystickSetDef . y + LINEHEIGHT * i ) ;
2017-12-17 03:32:43 +00:00
if ( ( setupcontrols_fourthplayer & & ( i = = cv_usejoystick4 . value ) )
| | ( setupcontrols_thirdplayer & & ( i = = cv_usejoystick3 . value ) )
| | ( setupcontrols_secondaryplayer & & ( i = = cv_usejoystick2 . value ) )
| | ( ! ( setupcontrols_secondaryplayer | | setupcontrols_thirdplayer | | setupcontrols_fourthplayer ) & & ( i = = cv_usejoystick . value ) ) )
2018-07-01 18:29:13 +00:00
V_DrawString ( OP_JoystickSetDef . x , OP_JoystickSetDef . y + LINEHEIGHT * i , recommendedflags , joystickInfo [ i ] ) ;
2014-03-15 16:59:03 +00:00
else
V_DrawString ( OP_JoystickSetDef . x , OP_JoystickSetDef . y + LINEHEIGHT * i , 0 , joystickInfo [ i ] ) ;
}
}
static void M_SetupJoystickMenu ( INT32 choice )
{
INT32 i = 0 ;
const char * joyname = " None " ;
const char * joyNA = " Unavailable " ;
INT32 n = I_NumJoys ( ) ;
( void ) choice ;
strcpy ( joystickInfo [ i ] , joyname ) ;
for ( i = 1 ; i < 8 ; i + + )
{
if ( i < = n & & ( joyname = I_GetJoyName ( i ) ) ! = NULL )
{
strncpy ( joystickInfo [ i ] , joyname , 24 ) ;
joystickInfo [ i ] [ 24 ] = ' \0 ' ;
}
else
strcpy ( joystickInfo [ i ] , joyNA ) ;
}
M_SetupNextMenu ( & OP_JoystickSetDef ) ;
}
static void M_Setup1PJoystickMenu ( INT32 choice )
{
2017-12-24 13:20:58 +00:00
setupcontrols_secondaryplayer = setupcontrols_thirdplayer = setupcontrols_fourthplayer = false ;
2014-03-15 16:59:03 +00:00
OP_JoystickSetDef . prevMenu = & OP_Joystick1Def ;
M_SetupJoystickMenu ( choice ) ;
}
static void M_Setup2PJoystickMenu ( INT32 choice )
{
setupcontrols_secondaryplayer = true ;
2017-12-24 13:20:58 +00:00
setupcontrols_thirdplayer = setupcontrols_fourthplayer = false ;
2014-03-15 16:59:03 +00:00
OP_JoystickSetDef . prevMenu = & OP_Joystick2Def ;
M_SetupJoystickMenu ( choice ) ;
}
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2017-12-08 07:29:01 +00:00
static void M_Setup3PJoystickMenu ( INT32 choice )
{
setupcontrols_thirdplayer = true ;
2017-12-24 13:20:58 +00:00
setupcontrols_secondaryplayer = setupcontrols_fourthplayer = false ;
2017-12-08 07:29:01 +00:00
OP_JoystickSetDef . prevMenu = & OP_Joystick3Def ;
M_SetupJoystickMenu ( choice ) ;
}
static void M_Setup4PJoystickMenu ( INT32 choice )
{
setupcontrols_fourthplayer = true ;
2017-12-24 13:20:58 +00:00
setupcontrols_secondaryplayer = setupcontrols_thirdplayer = false ;
2017-12-08 07:29:01 +00:00
OP_JoystickSetDef . prevMenu = & OP_Joystick4Def ;
M_SetupJoystickMenu ( choice ) ;
}
2018-01-01 18:11:24 +00:00
# endif
2017-12-08 07:29:01 +00:00
2014-03-15 16:59:03 +00:00
static void M_AssignJoystick ( INT32 choice )
{
2017-12-24 13:20:58 +00:00
if ( setupcontrols_fourthplayer )
CV_SetValue ( & cv_usejoystick4 , choice ) ;
else if ( setupcontrols_thirdplayer )
CV_SetValue ( & cv_usejoystick3 , choice ) ;
else if ( setupcontrols_secondaryplayer )
2014-03-15 16:59:03 +00:00
CV_SetValue ( & cv_usejoystick2 , choice ) ;
else
CV_SetValue ( & cv_usejoystick , choice ) ;
}
// =============
// CONTROLS MENU
// =============
static void M_Setup1PControlsMenu ( INT32 choice )
{
( void ) choice ;
2017-12-24 13:20:58 +00:00
setupcontrols_secondaryplayer = setupcontrols_thirdplayer = setupcontrols_fourthplayer = false ;
2014-03-15 16:59:03 +00:00
setupcontrols = gamecontrol ; // was called from main Options (for console player, then)
currentMenu - > lastOn = itemOn ;
2018-05-30 20:54:59 +00:00
// Unhide P1-only controls
2018-06-30 15:01:03 +00:00
OP_MoveControlsMenu [ 10 ] . status = IT_CONTROL ; // Talk
//OP_MoveControlsMenu[11].status = IT_CONTROL; // Team-talk
OP_MoveControlsMenu [ 11 ] . status = IT_CONTROL ; // Rankings
OP_MoveControlsMenu [ 12 ] . status = IT_CONTROL ; // Pause
OP_MoveControlsMenu [ 13 ] . status = IT_CONTROL ; // Console
OP_MoveControlsMenu [ 14 ] . itemaction = & OP_Joystick1Def ; // Gamepad
// Set cvars
OP_SpectateControlsMenu [ 6 ] . itemaction = & cv_chasecam ; // Chasecam
OP_SpectateControlsMenu [ 7 ] . itemaction = & cv_crosshair ; // Crosshair
2014-03-15 16:59:03 +00:00
2017-12-04 01:00:31 +00:00
M_SetupNextMenu ( & OP_MoveControlsDef ) ;
2014-03-15 16:59:03 +00:00
}
static void M_Setup2PControlsMenu ( INT32 choice )
{
( void ) choice ;
setupcontrols_secondaryplayer = true ;
2018-06-30 15:01:03 +00:00
setupcontrols_thirdplayer = setupcontrols_fourthplayer = false ;
2014-03-15 16:59:03 +00:00
setupcontrols = gamecontrolbis ;
currentMenu - > lastOn = itemOn ;
2018-05-30 20:54:59 +00:00
// Hide P1-only controls
2018-06-30 15:01:03 +00:00
OP_MoveControlsMenu [ 10 ] . status = IT_GRAYEDOUT2 ; // Talk
//OP_MoveControlsMenu[11].status = IT_GRAYEDOUT2; // Team-talk
2018-05-30 20:54:59 +00:00
OP_MoveControlsMenu [ 11 ] . status = IT_GRAYEDOUT2 ; // Rankings
OP_MoveControlsMenu [ 12 ] . status = IT_GRAYEDOUT2 ; // Pause
OP_MoveControlsMenu [ 13 ] . status = IT_GRAYEDOUT2 ; // Console
2018-06-30 15:01:03 +00:00
OP_MoveControlsMenu [ 14 ] . itemaction = & OP_Joystick2Def ; // Gamepad
// Set cvars
OP_SpectateControlsMenu [ 6 ] . itemaction = & cv_chasecam2 ; // Chasecam
OP_SpectateControlsMenu [ 7 ] . itemaction = & cv_crosshair2 ; // Crosshair
2014-03-15 16:59:03 +00:00
2017-12-04 01:00:31 +00:00
M_SetupNextMenu ( & OP_MoveControlsDef ) ;
2014-03-15 16:59:03 +00:00
}
2018-01-01 18:11:24 +00:00
# ifndef NOFOURPLAYER
2017-12-08 07:29:01 +00:00
static void M_Setup3PControlsMenu ( INT32 choice )
{
( void ) choice ;
setupcontrols_thirdplayer = true ;
2018-06-30 15:01:03 +00:00
setupcontrols_secondaryplayer = setupcontrols_fourthplayer = false ;
2017-12-11 06:12:38 +00:00
setupcontrols = gamecontrol3 ;
2017-12-08 07:29:01 +00:00
currentMenu - > lastOn = itemOn ;
2018-05-30 20:54:59 +00:00
// Hide P1-only controls
2018-06-30 15:01:03 +00:00
OP_MoveControlsMenu [ 10 ] . status = IT_GRAYEDOUT2 ; // Talk
//OP_MoveControlsMenu[11].status = IT_GRAYEDOUT2; // Team-talk
2018-05-30 20:54:59 +00:00
OP_MoveControlsMenu [ 11 ] . status = IT_GRAYEDOUT2 ; // Rankings
OP_MoveControlsMenu [ 12 ] . status = IT_GRAYEDOUT2 ; // Pause
OP_MoveControlsMenu [ 13 ] . status = IT_GRAYEDOUT2 ; // Console
2018-06-30 15:01:03 +00:00
OP_MoveControlsMenu [ 14 ] . itemaction = & OP_Joystick3Def ; // Gamepad
// Set cvars
OP_SpectateControlsMenu [ 6 ] . itemaction = & cv_chasecam3 ; // Chasecam
OP_SpectateControlsMenu [ 7 ] . itemaction = & cv_crosshair3 ; // Crosshair
2017-12-08 07:29:01 +00:00
M_SetupNextMenu ( & OP_MoveControlsDef ) ;
}
static void M_Setup4PControlsMenu ( INT32 choice )
{
( void ) choice ;
setupcontrols_fourthplayer = true ;
2018-06-30 15:01:03 +00:00
setupcontrols_secondaryplayer = setupcontrols_thirdplayer = false ;
2017-12-11 06:12:38 +00:00
setupcontrols = gamecontrol4 ;
2017-12-08 07:29:01 +00:00
currentMenu - > lastOn = itemOn ;
2018-05-30 20:54:59 +00:00
// Hide P1-only controls
2018-06-30 15:01:03 +00:00
OP_MoveControlsMenu [ 10 ] . status = IT_GRAYEDOUT2 ; // Talk
//OP_MoveControlsMenu[11].status = IT_GRAYEDOUT2; // Team-talk
2018-05-30 20:54:59 +00:00
OP_MoveControlsMenu [ 11 ] . status = IT_GRAYEDOUT2 ; // Rankings
OP_MoveControlsMenu [ 12 ] . status = IT_GRAYEDOUT2 ; // Pause
OP_MoveControlsMenu [ 13 ] . status = IT_GRAYEDOUT2 ; // Console
2018-06-30 15:01:03 +00:00
OP_MoveControlsMenu [ 14 ] . itemaction = & OP_Joystick4Def ; // Gamepad
// Set cvars
OP_SpectateControlsMenu [ 6 ] . itemaction = & cv_chasecam4 ; // Chasecam
OP_SpectateControlsMenu [ 7 ] . itemaction = & cv_crosshair4 ; // Crosshair
2017-12-08 07:29:01 +00:00
M_SetupNextMenu ( & OP_MoveControlsDef ) ;
}
2018-01-01 18:11:24 +00:00
# endif
2017-12-08 07:29:01 +00:00
2014-03-15 16:59:03 +00:00
// Draws the Customise Controls menu
static void M_DrawControl ( void )
{
char tmp [ 50 ] ;
2018-06-30 15:01:03 +00:00
INT32 i , y ;
2014-03-15 16:59:03 +00:00
INT32 keys [ 2 ] ;
2017-12-18 10:56:38 +00:00
const char * ctrl ;
2014-03-15 16:59:03 +00:00
// draw title, strings and submenu
M_DrawGenericMenu ( ) ;
2017-12-18 10:56:38 +00:00
if ( setupcontrols_secondaryplayer )
2018-06-30 15:01:03 +00:00
ctrl = " \x86 " " SET " " \x82 " " CONTROLS " " \x86 " " FOR " " \x82 " " SECONDARY PLAYER " ;
2017-12-18 10:56:38 +00:00
else if ( setupcontrols_thirdplayer )
2018-06-30 15:01:03 +00:00
ctrl = " \x86 " " SET " " \x82 " " CONTROLS " " \x86 " " FOR " " \x82 " " THIRD PLAYER " ;
2017-12-18 10:56:38 +00:00
else if ( setupcontrols_fourthplayer )
2018-06-30 15:01:03 +00:00
ctrl = " \x86 " " SET " " \x82 " " CONTROLS " " \x86 " " FOR " " \x82 " " FOURTH PLAYER " ;
2017-12-18 10:56:38 +00:00
else
2018-06-30 15:01:03 +00:00
ctrl = " \x86 " " PRESS " " \x82 " " ENTER " " \x86 " " TO CHANGE, " " \x82 " " BACKSPACE " " \x86 " " TO CLEAR " ;
M_CentreText ( 28 , ctrl ) ;
2017-12-18 10:56:38 +00:00
2018-06-30 15:01:03 +00:00
y = currentMenu - > y ;
2014-03-15 16:59:03 +00:00
2018-06-30 15:01:03 +00:00
for ( i = 0 ; i < currentMenu - > numitems ; i + + )
2014-03-15 16:59:03 +00:00
{
2018-06-30 15:01:03 +00:00
if ( currentMenu - > menuitems [ i ] . status ! = IT_CONTROL )
{
y = currentMenu - > y + currentMenu - > menuitems [ i ] . alphaKey ;
continue ;
}
2014-03-15 16:59:03 +00:00
if ( currentMenu - > menuitems [ i ] . status ! = IT_CONTROL )
continue ;
keys [ 0 ] = setupcontrols [ currentMenu - > menuitems [ i ] . alphaKey ] [ 0 ] ;
keys [ 1 ] = setupcontrols [ currentMenu - > menuitems [ i ] . alphaKey ] [ 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 , " or " ) ;
if ( keys [ 1 ] ! = KEY_NULL )
strcat ( tmp , G_KeynumToString ( keys [ 1 ] ) ) ;
}
2018-07-01 18:29:13 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x , y , highlightflags , tmp ) ;
2018-06-30 15:01:03 +00:00
y + = SMALLLINEHEIGHT ;
2014-03-15 16:59:03 +00:00
}
}
static INT32 controltochange ;
static void M_ChangecontrolResponse ( event_t * ev )
{
INT32 control ;
INT32 found ;
INT32 ch = ev - > data1 ;
// ESCAPE cancels
if ( ch ! = KEY_ESCAPE )
{
switch ( ev - > type )
{
// ignore mouse/joy movements, just get buttons
case ev_mouse :
case ev_mouse2 :
case ev_joystick :
case ev_joystick2 :
2017-12-24 13:20:58 +00:00
case ev_joystick3 :
case ev_joystick4 :
2014-03-15 16:59:03 +00:00
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 ;
2017-12-17 03:32:43 +00:00
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 ;
2014-03-15 16:59:03 +00:00
}
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
}
G_CheckDoubleUsage ( ch ) ;
setupcontrols [ control ] [ found ] = ch ;
}
}
M_StopMessage ( 0 ) ;
}
static void M_ChangeControl ( INT32 choice )
{
static char tmp [ 55 ] ;
controltochange = currentMenu - > menuitems [ choice ] . alphaKey ;
sprintf ( tmp , M_GetText ( " Hit the new key for \n %s \n ESC for Cancel " ) ,
currentMenu - > menuitems [ choice ] . text ) ;
M_StartMessage ( tmp , M_ChangecontrolResponse , MM_EVENTHANDLER ) ;
}
// =====
// SOUND
// =====
// Toggles sound systems in-game.
2018-06-30 22:18:13 +00:00
static void M_ToggleSFX ( INT32 choice )
2014-03-15 16:59:03 +00:00
{
2018-06-30 22:18:13 +00:00
switch ( choice )
{
case KEY_DOWNARROW :
S_StartSound ( NULL , sfx_menu1 ) ;
itemOn + + ;
return ;
case KEY_UPARROW :
S_StartSound ( NULL , sfx_menu1 ) ;
itemOn = currentMenu - > numitems - 1 ;
return ;
case KEY_ESCAPE :
currentMenu - > lastOn = itemOn ;
if ( currentMenu - > prevMenu )
M_SetupNextMenu ( currentMenu - > prevMenu ) ;
else
M_ClearMenus ( true ) ;
return ;
default :
break ;
}
2014-03-15 16:59:03 +00:00
if ( nosound )
{
nosound = false ;
I_StartupSound ( ) ;
if ( nosound ) return ;
2018-06-30 22:18:13 +00:00
S_Init ( cv_soundvolume . value , cv_digmusicvolume . value ) ; //, cv_midimusicvolume.value);
S_StartSound ( NULL , sfx_strpst ) ;
//M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING);
2014-03-15 16:59:03 +00:00
}
else
{
if ( sound_disabled )
{
sound_disabled = false ;
2018-06-30 22:18:13 +00:00
S_StartSound ( NULL , sfx_strpst ) ;
//M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING);
2014-03-15 16:59:03 +00:00
}
else
{
sound_disabled = true ;
S_StopSounds ( ) ;
2018-06-30 22:18:13 +00:00
//M_StartMessage(M_GetText("SFX Disabled\n"), NULL, MM_NOTHING);
2014-03-15 16:59:03 +00:00
}
}
}
2018-06-30 22:18:13 +00:00
static void M_ToggleDigital ( INT32 choice )
2014-03-15 16:59:03 +00:00
{
2018-06-30 22:18:13 +00:00
switch ( choice )
{
case KEY_DOWNARROW :
S_StartSound ( NULL , sfx_menu1 ) ;
itemOn + + ;
return ;
case KEY_UPARROW :
S_StartSound ( NULL , sfx_menu1 ) ;
itemOn - - ;
return ;
case KEY_ESCAPE :
currentMenu - > lastOn = itemOn ;
if ( currentMenu - > prevMenu )
M_SetupNextMenu ( currentMenu - > prevMenu ) ;
else
M_ClearMenus ( true ) ;
return ;
default :
break ;
}
2014-03-15 16:59:03 +00:00
if ( nodigimusic )
{
nodigimusic = false ;
I_InitDigMusic ( ) ;
if ( nodigimusic ) return ;
2018-06-30 22:18:13 +00:00
S_Init ( cv_soundvolume . value , cv_digmusicvolume . value ) ; //, cv_midimusicvolume.value);
2014-03-15 16:59:03 +00:00
S_StopMusic ( ) ;
2018-06-30 22:18:13 +00:00
if ( Playing ( ) )
P_RestoreMusic ( & players [ consoleplayer ] ) ;
else
S_ChangeMusicInternal ( " titles " , looptitle ) ;
//M_StartMessage(M_GetText("Digital Music Enabled\n"), NULL, MM_NOTHING);
2014-03-15 16:59:03 +00:00
}
else
{
if ( digital_disabled )
{
digital_disabled = false ;
2018-06-30 22:18:13 +00:00
if ( Playing ( ) )
P_RestoreMusic ( & players [ consoleplayer ] ) ;
else
S_ChangeMusicInternal ( " titles " , looptitle ) ;
//M_StartMessage(M_GetText("Digital Music Enabled\n"), NULL, MM_NOTHING);
2014-03-15 16:59:03 +00:00
}
else
{
digital_disabled = true ;
S_StopMusic ( ) ;
2018-06-30 22:18:13 +00:00
//M_StartMessage(M_GetText("Digital Music Disabled\n"), NULL, MM_NOTHING);
2014-03-15 16:59:03 +00:00
}
}
}
2018-06-30 22:18:13 +00:00
/*static void M_ToggleMIDI(INT32 choice)
2014-03-15 16:59:03 +00:00
{
2018-06-30 22:18:13 +00:00
switch ( choice )
{
case KEY_DOWNARROW :
S_StartSound ( NULL , sfx_menu1 ) ;
itemOn + + ;
return ;
case KEY_UPARROW :
S_StartSound ( NULL , sfx_menu1 ) ;
itemOn - - ;
return ;
case KEY_ESCAPE :
if ( currentMenu - > prevMenu )
M_SetupNextMenu ( currentMenu - > prevMenu ) ;
else
M_ClearMenus ( true ) ;
return ;
default :
break ;
}
2014-03-15 16:59:03 +00:00
if ( nomidimusic )
{
nomidimusic = false ;
I_InitMIDIMusic ( ) ;
if ( nomidimusic ) return ;
S_Init ( cv_soundvolume . value , cv_digmusicvolume . value , cv_midimusicvolume . value ) ;
2018-06-30 22:18:13 +00:00
if ( Playing ( ) )
P_RestoreMusic ( & players [ consoleplayer ] ) ;
else
S_ChangeMusicInternal ( " _clear " , false ) ;
//M_StartMessage(M_GetText("MIDI Music Enabled\n"), NULL, MM_NOTHING);
2014-03-15 16:59:03 +00:00
}
else
{
if ( music_disabled )
{
music_disabled = false ;
2018-06-30 22:18:13 +00:00
if ( Playing ( ) )
P_RestoreMusic ( & players [ consoleplayer ] ) ;
else
S_ChangeMusicInternal ( " _clear " , false ) ;
//M_StartMessage(M_GetText("MIDI Music Enabled\n"), NULL, MM_NOTHING);
2014-03-15 16:59:03 +00:00
}
else
{
music_disabled = true ;
S_StopMusic ( ) ;
2018-06-30 22:18:13 +00:00
//M_StartMessage(M_GetText("MIDI Music Disabled\n"), NULL, MM_NOTHING);
2014-03-15 16:59:03 +00:00
}
}
2018-06-30 22:18:13 +00:00
} */
2014-03-15 16:59:03 +00:00
2018-06-15 00:18:29 +00:00
static void M_RestartAudio ( void )
{
S_StopMusic ( ) ;
I_ShutdownMusic ( ) ;
I_ShutdownSound ( ) ;
I_StartupSound ( ) ;
I_InitMusic ( ) ;
I_SetSfxVolume ( cv_soundvolume . value ) ;
I_SetDigMusicVolume ( cv_digmusicvolume . value ) ;
2018-06-30 22:18:13 +00:00
//I_SetMIDIMusicVolume(cv_midimusicvolume.value);
S_StartSound ( NULL , sfx_strpst ) ;
2018-06-15 00:18:29 +00:00
if ( Playing ( ) ) // Gotta make sure the player is in a level
P_RestoreMusic ( & players [ consoleplayer ] ) ;
2018-06-30 22:18:13 +00:00
else
S_ChangeMusicInternal ( " titles " , looptitle ) ;
2018-06-15 00:18:29 +00:00
}
2014-03-15 16:59:03 +00:00
// ===============
// 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 ) ) ;
2014-07-25 23:10:24 +00:00
# if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
2014-03-15 16:59:03 +00:00
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 ) ;
}
2018-06-30 22:18:13 +00:00
static void M_DrawVideoMenu ( void )
2018-08-09 21:59:52 +00:00
{
M_DrawGenericMenu ( ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x , currentMenu - > y + OP_VideoOptionsMenu [ 0 ] . alphaKey ,
( SCR_IsAspectCorrect ( vid . width , vid . height ) ? recommendedflags : highlightflags ) ,
va ( " %dx%d " , vid . width , vid . height ) ) ;
}
static void M_DrawHUDOptions ( void )
2018-06-30 22:18:13 +00:00
{
2018-08-05 15:34:51 +00:00
const char * str0 = " ) " ;
const char * str1 = " Warning highlight " ;
const char * str2 = " , " ;
const char * str3 = " Good highlight " ;
2018-08-09 21:59:52 +00:00
INT32 x = BASEVIDWIDTH - currentMenu - > x + 2 , y = currentMenu - > y + 105 ;
2018-08-05 15:34:51 +00:00
INT32 w0 = V_StringWidth ( str0 , 0 ) , w1 = V_StringWidth ( str1 , 0 ) , w2 = V_StringWidth ( str2 , 0 ) , w3 = V_StringWidth ( str3 , 0 ) ;
2018-06-30 22:18:13 +00:00
M_DrawGenericMenu ( ) ;
2018-08-05 15:34:51 +00:00
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 , " ( " ) ;
2018-06-30 22:18:13 +00:00
}
2014-03-15 16:59:03 +00:00
// 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 ,
2018-07-01 18:29:13 +00:00
highlightflags , " Choose mode, reselect to change default " ) ;
2014-03-15 16:59:03 +00:00
row = 41 ;
col = OP_VideoModeDef . y + 14 ;
for ( i = 0 ; i < vidm_nummodes ; i + + )
{
if ( i = = vidm_selected )
2018-07-01 18:29:13 +00:00
V_DrawString ( row , col , highlightflags , modedescs [ i ] . desc ) ;
2014-03-15 16:59:03 +00:00
// Show multiples of 320x200 as green.
else
2018-07-01 18:29:13 +00:00
V_DrawString ( row , col , ( modedescs [ i ] . goodratio ) ? recommendedflags : 0 , modedescs [ i ] . desc ) ;
2014-03-15 16:59:03 +00:00
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 ,
2018-07-01 19:01:02 +00:00
recommendedflags , " Marked modes are recommended. " ) ;
2018-06-30 22:18:13 +00:00
V_DrawCenteredString ( BASEVIDWIDTH / 2 , OP_VideoModeDef . y + 146 ,
2018-07-01 18:29:13 +00:00
highlightflags , " Other modes may have visual errors. " ) ;
2014-03-15 16:59:03 +00:00
V_DrawCenteredString ( BASEVIDWIDTH / 2 , OP_VideoModeDef . y + 158 ,
2018-07-01 18:29:13 +00:00
highlightflags , " Larger modes may have performance issues. " ) ;
2014-03-15 16:59:03 +00:00
}
// 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
// ===============
2018-08-31 17:18:19 +00:00
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_kitchensink ,
& cv_triplesneaker ,
& cv_triplebanana ,
& cv_decabanana ,
& cv_tripleorbinaut ,
& cv_quadorbinaut ,
& cv_dualjawz
} ;
2018-09-20 16:45:09 +00:00
static tic_t shitsfree = 0 ;
2018-08-31 17:18:19 +00:00
static void M_DrawMonitorToggles ( void )
2014-03-15 16:59:03 +00:00
{
2018-08-31 17:18:19 +00:00
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 ) ;
2018-09-08 16:02:03 +00:00
INT32 onx = 0 , ony = 0 ;
2014-03-15 16:59:03 +00:00
consvar_t * cv ;
2018-09-08 16:02:03 +00:00
INT32 i , translucent , drawnum ;
2014-03-15 16:59:03 +00:00
2018-08-31 17:18:19 +00:00
M_DrawMenuTitle ( ) ;
2014-03-15 16:59:03 +00:00
2018-08-31 17:18:19 +00:00
// Find the available space around column
leftdraw = rightdraw = column ;
totaldraw = 0 ;
for ( i = 0 ; ( totaldraw < edges * 2 & & i < edges * 4 ) ; i + + )
2014-03-15 16:59:03 +00:00
{
2018-08-31 17:18:19 +00:00
if ( rightdraw + 1 < ( currentMenu - > numitems / height ) + 1 )
{
rightdraw + + ;
totaldraw + + ;
}
if ( leftdraw - 1 > = 0 )
{
leftdraw - - ;
totaldraw + + ;
}
2014-03-15 16:59:03 +00:00
}
2018-08-31 17:18:19 +00:00
for ( i = leftdraw ; i < = rightdraw ; i + + )
2014-03-15 16:59:03 +00:00
{
2018-08-31 17:18:19 +00:00
INT32 j ;
2014-03-15 16:59:03 +00:00
2018-08-31 17:18:19 +00:00
for ( j = 0 ; j < height ; j + + )
{
const INT32 thisitem = ( i * height ) + j ;
INT32 drawnum = 0 ;
2014-03-15 16:59:03 +00:00
2018-08-31 17:18:19 +00:00
if ( thisitem > = currentMenu - > numitems )
continue ;
2018-09-08 16:02:03 +00:00
if ( thisitem = = itemOn )
{
onx = x ;
ony = y ;
y + = spacing ;
continue ;
}
# ifdef ITEMTOGGLEBOTTOMRIGHT
if ( currentMenu - > menuitems [ thisitem ] . alphaKey = = 255 )
{
V_DrawScaledPatch ( x , y , V_TRANSLUCENT , W_CachePatchName ( " K_ISBG " , PU_CACHE ) ) ;
continue ;
}
# endif
2018-08-31 18:41:37 +00:00
if ( currentMenu - > menuitems [ thisitem ] . alphaKey = = 0 )
{
2018-09-08 16:02:03 +00:00
V_DrawScaledPatch ( x , y , 0 , W_CachePatchName ( " K_ISBG " , PU_CACHE ) ) ;
V_DrawScaledPatch ( x , y , 0 , W_CachePatchName ( " K_ISTOGL " , PU_CACHE ) ) ;
2018-08-31 18:41:37 +00:00
continue ;
}
2018-08-31 17:18:19 +00:00
cv = kartitemcvs [ currentMenu - > menuitems [ thisitem ] . alphaKey - 1 ] ;
translucent = ( cv - > value ? 0 : V_TRANSLUCENT ) ;
switch ( currentMenu - > menuitems [ thisitem ] . alphaKey )
{
case KRITEM_DUALJAWZ :
drawnum = 2 ;
break ;
case KRITEM_TRIPLESNEAKER :
case KRITEM_TRIPLEBANANA :
case KRITEM_TRIPLEORBINAUT :
2018-09-08 16:02:03 +00:00
drawnum = 3 ;
2018-08-31 17:18:19 +00:00
break ;
case KRITEM_QUADORBINAUT :
2018-09-08 16:02:03 +00:00
drawnum = 4 ;
2018-08-31 17:18:19 +00:00
break ;
case KRITEM_TENFOLDBANANA :
drawnum = 10 ;
break ;
default :
2018-09-08 16:02:03 +00:00
drawnum = 0 ;
2018-08-31 17:18:19 +00:00
break ;
}
2018-09-08 16:02:03 +00:00
if ( cv - > value )
V_DrawScaledPatch ( x , y , 0 , W_CachePatchName ( " K_ISBG " , PU_CACHE ) ) ;
2018-08-31 17:18:19 +00:00
else
2018-09-08 16:02:03 +00:00
V_DrawScaledPatch ( x , y , 0 , W_CachePatchName ( " K_ISBGD " , PU_CACHE ) ) ;
2018-08-31 17:18:19 +00:00
2018-09-08 16:02:03 +00:00
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 ] . alphaKey , true ) , PU_CACHE ) ) ;
V_DrawString ( x + 24 , y + 31 , V_ALLOWLOWERCASE | translucent , va ( " x%d " , drawnum ) ) ;
2018-08-31 17:18:19 +00:00
}
2018-09-08 16:02:03 +00:00
else
V_DrawScaledPatch ( x , y , translucent , W_CachePatchName ( K_GetItemPatch ( currentMenu - > menuitems [ thisitem ] . alphaKey , true ) , PU_CACHE ) ) ;
2014-03-15 16:59:03 +00:00
2018-08-31 17:18:19 +00:00
y + = spacing ;
}
x + = spacing ;
y = currentMenu - > y + ( spacing / 4 ) ;
2014-03-15 16:59:03 +00:00
}
2018-09-08 16:02:03 +00:00
{
# ifdef ITEMTOGGLEBOTTOMRIGHT
if ( currentMenu - > menuitems [ itemOn ] . alphaKey = = 255 )
2018-09-20 16:45:09 +00:00
{
2018-09-08 16:02:03 +00:00
V_DrawScaledPatch ( onx - 1 , ony - 2 , V_TRANSLUCENT , W_CachePatchName ( " K_ITBG " , PU_CACHE ) ) ;
2018-09-20 16:45:09 +00:00
if ( shitsfree )
{
INT32 trans = V_TRANSLUCENT ;
if ( shitsfree - 1 > TICRATE - 5 )
trans = ( ( 10 - TICRATE ) + shitsfree - 1 ) < < V_ALPHASHIFT ;
else if ( shitsfree < 5 )
trans = ( 10 - shitsfree ) < < V_ALPHASHIFT ;
V_DrawScaledPatch ( onx - 1 , ony - 2 , trans , W_CachePatchName ( " K_ITFREE " , PU_CACHE ) ) ;
}
}
2014-03-15 16:59:03 +00:00
else
2018-09-08 16:02:03 +00:00
# endif
if ( currentMenu - > menuitems [ itemOn ] . alphaKey = = 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 ] . alphaKey - 1 ] ;
translucent = ( cv - > value ? 0 : V_TRANSLUCENT ) ;
switch ( currentMenu - > menuitems [ itemOn ] . alphaKey )
{
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 ] . alphaKey , 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 ] . alphaKey , false ) , PU_CACHE ) ) ;
}
2014-03-15 16:59:03 +00:00
}
2018-09-20 16:45:09 +00:00
if ( shitsfree )
shitsfree - - ;
2018-08-31 17:18:19 +00:00
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 ;
2018-08-31 18:41:37 +00:00
UINT8 i ;
2018-09-08 16:02:03 +00:00
boolean exitmenu = false ;
2018-08-31 17:18:19 +00:00
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 :
2018-09-08 16:02:03 +00:00
# ifdef ITEMTOGGLEBOTTOMRIGHT
if ( currentMenu - > menuitems [ itemOn ] . alphaKey = = 255 )
2018-09-20 16:45:09 +00:00
{
//S_StartSound(NULL, sfx_lose);
if ( ! shitsfree )
{
shitsfree = TICRATE ;
S_StartSound ( NULL , sfx_itfree ) ;
}
}
2018-09-08 16:02:03 +00:00
else
# endif
2018-08-31 18:41:37 +00:00
if ( currentMenu - > menuitems [ itemOn ] . alphaKey = = 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 ] . alphaKey - 1 ] , 1 ) ;
}
2018-08-31 17:18:19 +00:00
break ;
case KEY_ESCAPE :
2018-09-08 16:02:03 +00:00
exitmenu = true ;
2018-08-31 17:18:19 +00:00
break ;
}
2018-09-08 16:02:03 +00:00
if ( exitmenu )
{
if ( currentMenu - > prevMenu )
M_SetupNextMenu ( currentMenu - > prevMenu ) ;
else
M_ClearMenus ( true ) ;
}
2018-08-31 17:18:19 +00:00
}
2014-03-15 16:59:03 +00:00
// =========
// Quit Game
// =========
static INT32 quitsounds [ ] =
{
// holy shit we're changing things up!
sfx_itemup , // Tails 11-09-99
sfx_jump , // Tails 11-09-99
sfx_skid , // Inu 04-03-13
sfx_spring , // Tails 11-09-99
sfx_pop ,
sfx_spdpad , // Inu 04-03-13
sfx_wdjump , // Inu 04-03-13
sfx_mswarp , // Inu 04-03-13
sfx_splash , // Tails 11-09-99
sfx_floush , // Tails 11-09-99
sfx_gloop , // Tails 11-09-99
sfx_s3k66 , // Inu 04-03-13
sfx_s3k6a , // Inu 04-03-13
sfx_s3k73 , // Inu 04-03-13
sfx_chchng // Tails 11-09-99
} ;
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 ( ) )
{
2018-01-15 21:02:33 +00:00
V_DrawSmallScaledPatch ( 0 , 0 , 0 , W_CachePatchName ( " GAMEQUIT " , PU_CACHE ) ) ; // Demo 3 Quit Screen Tails 06-16-2001
2014-03-15 16:59:03 +00:00
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 ) ,
2018-07-01 18:29:13 +00:00
my + currentMenu - > menuitems [ FOG_COLOR_ITEM ] . alphaKey , highlightflags , cv_grfogcolor . string ) ;
2014-03-15 16:59:03 +00:00
// 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 ] . alphaKey , ' _ ' | 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 ] . alphaKey - 10 ,
2018-07-01 18:29:13 +00:00
highlightflags , " Gamma correction " ) ;
2014-03-15 16:59:03 +00:00
}
//===================
// 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 ] ;
2016-07-06 04:09:17 +00:00
cv_grfogcolor . zstring [ 5 ] = ( char ) choice ;
2014-03-15 16:59:03 +00:00
}
break ;
}
if ( exitmenu )
{
if ( currentMenu - > prevMenu )
M_SetupNextMenu ( currentMenu - > prevMenu ) ;
else
M_ClearMenus ( true ) ;
}
}
# endif