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.
2018-11-25 12:35:38 +00:00
// Copyright (C) 1999-2018 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
2018-12-02 21:52:30 +00:00
# include "i_joy.h" // for joystick menu controls
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"
2018-12-14 08:58:07 +00:00
# if defined(HAVE_SDL)
# include "SDL.h"
# if SDL_VERSION_ATLEAST(2,0,0)
# include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG
# endif
# endif
2014-03-15 16:59:03 +00:00
# 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
# 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
2019-01-16 01:09:55 +00:00
description_t description [ MAXSKINS ] ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//static char *char_notes = NULL;
//static fixed_t char_scroll = 0;
2014-03-15 16:59:03 +00:00
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 ;
2018-12-02 01:13:14 +00:00
static char joystickInfo [ 8 ] [ 29 ] ;
2014-03-15 16:59:03 +00:00
# ifndef NONET
static UINT32 serverlistpage ;
# endif
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//static saveinfo_t savegameinfo[MAXSAVEGAMES]; // Extra info about the save games.
2014-03-15 16:59:03 +00:00
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
2018-11-23 03:50:40 +00:00
static UINT8 setupcontrolplayer ;
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 ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//static void M_LoadGameLevelSelect(INT32 choice);
2014-03-15 16:59:03 +00:00
static void M_GetAllEmeralds ( INT32 choice ) ;
static void M_DestroyRobots ( INT32 choice ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//static void M_LevelSelectWarp(INT32 choice);
2014-03-15 16:59:03 +00:00
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
2019-03-30 22:25:54 +00:00
#if 0 // Bring this back when we have actual single-player
2014-03-15 16:59:03 +00:00
static void M_SinglePlayerMenu ( INT32 choice ) ;
2019-03-30 22:25:54 +00:00
# endif
2014-03-15 16:59:03 +00:00
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-10-16 00:28:35 +00:00
static void M_ConfirmSpectateChange ( INT32 choice ) ;
2018-03-02 00:00:16 +00:00
//static void M_SecretsMenu(INT32 choice);
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//static void M_SetupChoosePlayer(INT32 choice);
2014-03-15 16:59:03 +00:00
static void M_QuitSRB2 ( INT32 choice ) ;
menu_t SP_MainDef , MP_MainDef , OP_MainDef ;
2018-10-16 00:28:35 +00:00
menu_t MISC_ScrambleTeamDef , MISC_ChangeTeamDef , MISC_ChangeSpectateDef ;
2014-03-15 16:59:03 +00:00
// 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 ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//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 ) ;
2019-01-18 13:04:12 +00:00
static void M_ConnectMenuModChecks ( INT32 choice ) ;
2014-03-15 16:59:03 +00:00
static void M_Refresh ( INT32 choice ) ;
static void M_Connect ( INT32 choice ) ;
static void M_ChooseRoom ( INT32 choice ) ;
# endif
2019-01-18 13:04:12 +00:00
static void M_StartOfflineServerMenu ( INT32 choice ) ;
static void M_StartServer ( INT32 choice ) ;
2014-03-15 16:59:03 +00:00
static void M_SetupMultiPlayer ( INT32 choice ) ;
static void M_SetupMultiPlayer2 ( INT32 choice ) ;
2017-12-08 07:29:01 +00:00
static void M_SetupMultiPlayer3 ( INT32 choice ) ;
static void M_SetupMultiPlayer4 ( INT32 choice ) ;
2018-10-16 21:11:47 +00:00
static void M_SetupMultiHandler ( INT32 choice ) ;
2014-03-15 16:59:03 +00:00
// Options
// Split into multiple parts due to size
// Controls
2018-09-27 20:55:21 +00:00
menu_t OP_ControlsDef , OP_AllControlsDef ;
2018-01-01 18:11:24 +00:00
menu_t OP_MouseOptionsDef , OP_Mouse2OptionsDef ;
2018-10-16 21:11:47 +00:00
menu_t OP_Joystick1Def , OP_Joystick2Def , OP_Joystick3Def , OP_Joystick4Def ;
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 ) ;
2017-12-08 07:29:01 +00:00
static void M_Setup3PControlsMenu ( INT32 choice ) ;
static void M_Setup4PControlsMenu ( INT32 choice ) ;
2018-10-16 21:11:47 +00:00
2014-03-15 16:59:03 +00:00
static void M_Setup1PJoystickMenu ( INT32 choice ) ;
static void M_Setup2PJoystickMenu ( INT32 choice ) ;
2017-12-08 07:29:01 +00:00
static void M_Setup3PJoystickMenu ( INT32 choice ) ;
static void M_Setup4PJoystickMenu ( INT32 choice ) ;
2018-10-16 21:11:47 +00:00
2014-03-15 16:59:03 +00:00
static void M_AssignJoystick ( INT32 choice ) ;
static void M_ChangeControl ( INT32 choice ) ;
2018-11-23 03:50:40 +00:00
static void M_ResetControls ( INT32 choice ) ;
2014-03-15 16:59:03 +00:00
// Video & Sound
menu_t OP_VideoOptionsDef , OP_VideoModeDef ;
# ifdef HWRENDER
menu_t OP_OpenGLOptionsDef , OP_OpenGLFogDef , OP_OpenGLColorDef ;
# endif
menu_t OP_SoundOptionsDef ;
2018-10-22 21:24:58 +00:00
//static void M_RestartAudio(void);
2014-03-15 16:59:03 +00:00
//Misc
2019-05-02 05:33:11 +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-11-27 17:10:46 +00:00
# ifndef NONET
menu_t OP_AdvServerOptionsDef ;
# endif
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
2019-03-31 01:57:53 +00:00
// Replay hut
2019-03-31 22:29:41 +00:00
menu_t MISC_ReplayHutDef ;
2019-05-02 05:33:11 +00:00
menu_t MISC_ReplayOptionsDef ;
2019-03-31 06:22:41 +00:00
static void M_HandleReplayHutList ( INT32 choice ) ;
2019-03-31 01:57:53 +00:00
static void M_DrawReplayHut ( void ) ;
2019-03-31 22:29:41 +00:00
static void M_DrawReplayStartMenu ( void ) ;
2019-03-31 18:50:20 +00:00
static boolean M_QuitReplayHut ( void ) ;
2019-03-31 22:29:41 +00:00
static void M_HutStartReplay ( INT32 choice ) ;
2019-03-31 01:57:53 +00:00
2019-04-05 07:38:48 +00:00
static void M_DrawPlaybackMenu ( void ) ;
2019-04-06 19:51:00 +00:00
static void M_PlaybackRewind ( INT32 choice ) ;
2019-04-05 07:38:48 +00:00
static void M_PlaybackPause ( INT32 choice ) ;
static void M_PlaybackFastForward ( INT32 choice ) ;
static void M_PlaybackAdvance ( INT32 choice ) ;
static void M_PlaybackSetViews ( INT32 choice ) ;
static void M_PlaybackAdjustView ( INT32 choice ) ;
2019-04-06 23:17:56 +00:00
static void M_PlaybackQuit ( INT32 choice ) ;
2019-04-05 07:38:48 +00:00
2019-05-02 16:00:51 +00:00
static UINT8 playback_enterheld = 0 ; // horrid hack to prevent holding the button from being extremely fucked
2014-03-15 16:59:03 +00:00
// Drawing functions
static void M_DrawGenericMenu ( void ) ;
2019-03-31 18:50:29 +00:00
static void M_DrawGenericBackgroundMenu ( void ) ;
2014-03-15 16:59:03 +00:00
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 ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//static void M_DrawLoad(void);
2014-03-15 16:59:03 +00:00
static void M_DrawLevelStats ( void ) ;
static void M_DrawTimeAttackMenu ( void ) ;
2018-01-22 00:15:26 +00:00
//static void M_DrawNightsAttackMenu(void);
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//static void M_DrawSetupChoosePlayerMenu(void);
2014-03-15 16:59:03 +00:00
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
2018-10-16 21:11:47 +00:00
static void M_DrawMPMainMenu ( void ) ;
2014-03-15 16:59:03 +00:00
# ifndef NONET
static void M_DrawConnectMenu ( void ) ;
static void M_DrawRoomMenu ( void ) ;
# endif
static void M_DrawJoystick ( void ) ;
static void M_DrawSetupMultiPlayerMenu ( void ) ;
// Handling functions
# ifndef NONET
static boolean M_CancelConnect ( void ) ;
# endif
static boolean M_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 ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//static void M_HandleLoadSave(INT32 choice);
2014-03-15 16:59:03 +00:00
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-10-16 00:28:35 +00:00
static void Dummymenuplayer_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.
// ==========================================================================
2019-03-11 19:50:01 +00:00
consvar_t cv_showfocuslost = { " showfocuslost " , " Yes " , CV_SAVE , CV_YesNo , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2014-03-15 16:59:03 +00:00
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.
2019-03-18 22:00:23 +00:00
// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h!
CV_PossibleValue_t gametype_cons_t [ NUMGAMETYPES + 1 ] ;
2014-03-15 16:59:03 +00:00
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 " } ,
2019-02-10 02:10:54 +00:00
{ 4 , " Max Player Slots " } ,
2014-03-17 12:13:16 +00:00
{ 5 , " Gametype " } ,
2014-03-15 16:59:03 +00:00
{ 0 , NULL }
} ;
2019-01-29 18:27:43 +00:00
consvar_t cv_serversort = { " serversort " , " Ping " , CV_CALL , serversort_cons_t , M_SortServerList , 0 , NULL , NULL , 0 , 0 , NULL } ;
2014-03-15 16:59:03 +00:00
// 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-09-30 22:07:05 +00:00
static void Splitplayers_OnChange ( void ) ;
CV_PossibleValue_t splitplayers_cons_t [ ] = { { 1 , " One " } , { 2 , " Two " } , { 3 , " Three " } , { 4 , " Four " } , { 0 , NULL } } ;
consvar_t cv_splitplayers = { " splitplayers " , " One " , CV_CALL , splitplayers_cons_t , Splitplayers_OnChange , 0 , NULL , NULL , 0 , 0 , NULL } ;
2018-06-30 22:18:13 +00:00
2018-10-16 00:28:35 +00:00
static CV_PossibleValue_t dummymenuplayer_cons_t [ ] = { { 0 , " NOPE " } , { 1 , " P1 " } , { 2 , " P2 " } , { 3 , " P3 " } , { 4 , " P4 " } , { 0 , NULL } } ;
2014-03-15 16:59:03 +00:00
static CV_PossibleValue_t dummyteam_cons_t [ ] = { { 0 , " Spectator " } , { 1 , " Red " } , { 2 , " Blue " } , { 0 , NULL } } ;
2018-10-16 00:28:35 +00:00
static CV_PossibleValue_t dummyspectate_cons_t [ ] = { { 0 , " Spectator " } , { 1 , " Playing " } , { 0 , NULL } } ;
2014-03-15 16:59:03 +00:00
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
2018-10-16 00:28:35 +00:00
static consvar_t cv_dummymenuplayer = { " dummymenuplayer " , " P1 " , CV_HIDEN | CV_CALL , dummymenuplayer_cons_t , Dummymenuplayer_OnChange , 0 , NULL , NULL , 0 , 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 } ;
2018-10-16 00:28:35 +00:00
static consvar_t cv_dummyspectate = { " dummyspectate " , " Spectator " , CV_HIDEN , dummyspectate_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2014-03-15 16:59:03 +00:00
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 [ ] =
{
2019-03-30 22:25:54 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Extras " , & SR_MainDef , 76 } ,
//{IT_CALL |IT_STRING, NULL, "1 Player", M_SinglePlayerMenu, 84},
{ IT_CALL | IT_STRING , NULL , " Time Attack " , M_TimeAttack , 84 } ,
{ IT_SUBMENU | IT_STRING , NULL , " Multiplayer " , & MP_MainDef , 92 } ,
{ IT_CALL | IT_STRING , NULL , " Options " , M_Options , 100 } ,
{ IT_CALL | IT_STRING , NULL , " Addons " , M_Addons , 108 } ,
{ 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
} ;
2019-03-31 01:57:53 +00:00
static menuitem_t MISC_ReplayHutMenu [ ] =
{
2019-05-02 05:33:11 +00:00
{ IT_KEYHANDLER | IT_NOTHING , NULL , " " , M_HandleReplayHutList , 0 } , // Dummy menuitem for the replay list
{ IT_NOTHING , NULL , " " , NULL , 0 } , // Dummy for handling wrapping to the top of the menu..
2019-03-31 01:57:53 +00:00
} ;
2019-03-31 22:29:41 +00:00
static menuitem_t MISC_ReplayStartMenu [ ] =
{
{ IT_CALL | IT_STRING , NULL , " Load Addons and Watch " , M_HutStartReplay , 0 } ,
{ IT_CALL | IT_STRING , NULL , " Watch Without Addons " , M_HutStartReplay , 10 } ,
{ IT_CALL | IT_STRING , NULL , " Watch Replay " , M_HutStartReplay , 10 } ,
{ IT_SUBMENU | IT_STRING , NULL , " Back " , & MISC_ReplayHutDef , 30 } ,
} ;
2019-03-31 18:50:29 +00:00
static menuitem_t MISC_ReplayOptionsMenu [ ] =
{
{ IT_CVAR | IT_STRING , NULL , " Record Replays " , & cv_recordmultiplayerdemos , 0 } ,
{ IT_CVAR | IT_STRING , NULL , " Sync Check Interval " , & cv_netdemosyncquality , 10 } ,
} ;
2019-04-05 07:38:48 +00:00
static menuitem_t PlaybackMenu [ ] =
{
2019-04-06 07:17:30 +00:00
{ IT_CALL | IT_STRING , " M_PHIDE " , " Hide Menu " , M_SelectableClearMenus , 0 } ,
2019-04-06 23:59:11 +00:00
{ IT_CALL | IT_STRING , " M_PREW " , " Rewind " , M_PlaybackRewind , 20 } ,
{ IT_CALL | IT_STRING , " M_PPAUSE " , " Pause " , M_PlaybackPause , 36 } ,
2019-06-23 04:39:31 +00:00
{ IT_CALL | IT_STRING , " M_PFFWD " , " Fast-Forward " , M_PlaybackFastForward , 52 } ,
2019-04-13 19:42:15 +00:00
{ IT_CALL | IT_STRING , " M_PSTEPB " , " Backup Frame " , M_PlaybackRewind , 20 } ,
{ IT_CALL | IT_STRING , " M_PRESUM " , " Resume " , M_PlaybackPause , 36 } ,
2019-04-06 23:59:11 +00:00
{ IT_CALL | IT_STRING , " M_PFADV " , " Advance Frame " , M_PlaybackAdvance , 52 } ,
{ IT_ARROWS | IT_STRING , " M_PVIEWS " , " View Count " , M_PlaybackSetViews , 72 } ,
{ IT_ARROWS | IT_STRING , " M_PNVIEW " , " Viewpoint " , M_PlaybackAdjustView , 88 } ,
{ IT_ARROWS | IT_STRING , " M_PNVIEW " , " Viewpoint 2 " , M_PlaybackAdjustView , 104 } ,
{ IT_ARROWS | IT_STRING , " M_PNVIEW " , " Viewpoint 3 " , M_PlaybackAdjustView , 120 } ,
{ IT_ARROWS | IT_STRING , " M_PNVIEW " , " Viewpoint 4 " , M_PlaybackAdjustView , 136 } ,
2019-04-13 20:23:31 +00:00
//{IT_CALL | IT_STRING, "M_POPTS", "More Options...", M_ReplayHut, 156},
//{IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 172},
{ IT_CALL | IT_STRING , " M_PEXIT " , " Stop Playback " , M_PlaybackQuit , 156 } ,
2019-04-05 07:38:48 +00:00
} ;
typedef enum
{
playback_hide ,
playback_rewind ,
playback_pause ,
playback_fastforward ,
2019-04-13 19:42:15 +00:00
playback_backframe ,
playback_resume ,
2019-04-05 07:38:48 +00:00
playback_advanceframe ,
playback_viewcount ,
playback_view1 ,
playback_view2 ,
playback_view3 ,
playback_view4 ,
2019-04-13 20:23:31 +00:00
//playback_moreoptions,
2019-04-05 07:38:48 +00:00
playback_quit
} playback_e ;
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 [ ] =
{
2019-01-05 20:59:23 +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 } ,
{ IT_CALL | IT_STRING , NULL , " Continue " , M_SelectableClearMenus , 40 } ,
{ IT_CALL | IT_STRING , NULL , " P1 Setup... " , M_SetupMultiPlayer , 48 } , // splitscreen
{ IT_CALL | IT_STRING , NULL , " P2 Setup... " , M_SetupMultiPlayer2 , 56 } , // splitscreen
{ IT_CALL | IT_STRING , NULL , " P3 Setup... " , M_SetupMultiPlayer3 , 64 } , // splitscreen
{ IT_CALL | IT_STRING , NULL , " P4 Setup... " , M_SetupMultiPlayer4 , 72 } , // splitscreen
{ IT_STRING | IT_CALL , NULL , " Spectate " , M_ConfirmSpectate , 48 } , // alone
{ IT_STRING | IT_CALL , NULL , " Enter Game " , M_ConfirmEnterGame , 48 } , // alone
{ IT_STRING | IT_CALL , NULL , " Cancel Join " , M_ConfirmSpectate , 48 } , // alone
{ IT_STRING | IT_SUBMENU , NULL , " Switch Team... " , & MISC_ChangeTeamDef , 48 } ,
{ IT_STRING | IT_SUBMENU , NULL , " Enter/Spectate... " , & MISC_ChangeSpectateDef , 48 } ,
{ IT_CALL | IT_STRING , NULL , " Player Setup... " , M_SetupMultiPlayer , 56 } , // alone
{ IT_CALL | IT_STRING , NULL , " Options " , M_Options , 64 } ,
{ IT_CALL | IT_STRING , NULL , " Return to Title " , M_EndGame , 80 } ,
{ IT_CALL | IT_STRING , NULL , " Quit Game " , M_QuitSRB2 , 88 } ,
2014-03-15 16:59:03 +00:00
} ;
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 ,
2017-12-18 10:56:38 +00:00
mpause_psetupsplit3 ,
mpause_psetupsplit4 ,
2018-10-16 21:11:47 +00:00
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 ,
2018-10-16 00:28:35 +00:00
mpause_switchspectate ,
2014-03-15 16:59:03 +00:00
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 } ,
2018-11-07 18:01:50 +00:00
{ IT_CALL | IT_STRING , NULL , " Medal Hints... " , M_EmblemHints , 24 } ,
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//{IT_CALL | IT_STRING, NULL, "Level Select...", M_LoadGameLevelSelect, 32},
2014-03-15 16:59:03 +00:00
{ 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 ,
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//spause_levelselect,
2014-03-15 16:59:03 +00:00
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 [ ] =
{
2018-10-16 00:28:35 +00:00
{ IT_STRING | IT_CVAR , NULL , " Player " , & cv_dummymenuplayer , 30 } ,
{ IT_STRING | IT_CVAR , NULL , " Team " , & cv_dummyteam , 40 } ,
2014-03-15 16:59:03 +00:00
{ IT_WHITESTRING | IT_CALL , NULL , " Confirm " , M_ConfirmTeamChange , 90 } ,
} ;
2018-10-16 00:28:35 +00:00
static menuitem_t MISC_ChangeSpectateMenu [ ] =
{
{ IT_STRING | IT_CVAR , NULL , " Player " , & cv_dummymenuplayer , 30 } ,
{ IT_STRING | IT_CVAR , NULL , " Status " , & cv_dummyspectate , 40 } ,
{ IT_WHITESTRING | IT_CALL , NULL , " Confirm " , M_ConfirmSpectateChange , 90 } ,
} ;
2014-03-15 16:59:03 +00:00
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 [ ] =
{
2019-05-02 05:33:11 +00:00
{ IT_STRING | IT_SUBMENU , NULL , " Unlockables " , & SR_UnlockChecklistDef , 100 } ,
{ IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED , NULL , " Statistics " , M_Statistics , 108 } ,
{ IT_CALL | IT_STRING , NULL , " Replay Hut " , M_ReplayHut , 116 } ,
2014-03-15 16:59:03 +00:00
{ 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
} ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
/*static menuitem_t SR_LevelSelectMenu[] =
2014-03-15 16:59:03 +00:00
{
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 } ,
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
} ; */
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 [ ] =
{
2018-11-07 18:01:50 +00:00
{ IT_STRING | IT_CVAR , NULL , " Medal Radar " , & cv_itemfinder , 10 } ,
2014-03-15 16:59:03 +00:00
{ 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
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
/*static menuitem_t SP_LoadGameMenu[] =
2014-03-15 16:59:03 +00:00
{
{ 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 } ,
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
} ; */
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!
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
# define M_ChoosePlayer NULL
2019-01-16 01:09:55 +00:00
menuitem_t PlayerMenu [ MAXSKINS ] ;
2014-03-15 16:59:03 +00:00
// -----------------------------------
// Multiplayer and all of its submenus
// -----------------------------------
// Prefix: MP_
2018-01-01 18:11:24 +00:00
2018-10-16 21:11:47 +00:00
static menuitem_t MP_MainMenu [ ] =
2018-09-30 21:09:59 +00:00
{
2018-10-16 21:11:47 +00:00
{ IT_HEADER , NULL , " Players " , NULL , 0 } ,
{ IT_STRING | IT_CVAR , NULL , " Number of local players " , & cv_splitplayers , 10 } ,
2018-09-30 21:09:59 +00:00
2018-10-16 21:11:47 +00:00
{ IT_STRING | IT_KEYHANDLER , NULL , " Player setup... " , M_SetupMultiHandler , 18 } ,
{ IT_HEADER , NULL , " Host a game " , NULL , 100 - 24 } ,
# ifndef NONET
{ IT_STRING | IT_CALL , NULL , " Internet/LAN... " , M_StartServerMenu , 110 - 24 } ,
2018-09-30 21:09:59 +00:00
# else
2018-10-16 21:11:47 +00:00
{ IT_GRAYEDOUT , NULL , " Internet/LAN... " , NULL , 110 - 24 } ,
2018-09-30 21:09:59 +00:00
# endif
2018-10-16 21:11:47 +00:00
{ IT_STRING | IT_CALL , NULL , " Offline... " , M_StartOfflineServerMenu , 118 - 24 } ,
2018-09-30 21:09:59 +00:00
2018-10-16 21:11:47 +00:00
{ IT_HEADER , NULL , " Join a game " , NULL , 132 - 24 } ,
# ifndef NONET
2019-01-18 13:04:12 +00:00
{ IT_STRING | IT_CALL , NULL , " Internet server browser... " , M_ConnectMenuModChecks , 142 - 24 } ,
2018-10-16 21:11:47 +00:00
{ IT_STRING | IT_KEYHANDLER , NULL , " Specify IPv4 address: " , M_HandleConnectIP , 150 - 24 } ,
# else
2019-01-18 13:04:12 +00:00
{ IT_GRAYEDOUT , NULL , " Internet server browser... " , NULL , 142 - 24 } ,
{ IT_GRAYEDOUT , NULL , " Specify IPv4 address: " , NULL , 150 - 24 } ,
2018-10-16 21:11:47 +00:00
# endif
2018-09-30 21:09:59 +00:00
//{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-10-16 21:11:47 +00:00
# ifndef NONET
2018-06-30 15:01:03 +00:00
2014-03-15 16:59:03 +00:00
static menuitem_t MP_ServerMenu [ ] =
{
2019-03-09 21:00:48 +00:00
{ IT_STRING | IT_CVAR , NULL , " Max. Player Count " , & cv_maxplayers , 0 } ,
{ IT_STRING | IT_CALL , NULL , " Room... " , M_RoomMenu , 10 } ,
{ IT_STRING | IT_CVAR | IT_CV_STRING , NULL , " Server Name " , & cv_servername , 20 } ,
{ IT_STRING | IT_CVAR | IT_CV_PASSWORD , NULL , " Password " , & cv_dummyjoinpassword , 44 } ,
2014-03-15 16:59:03 +00:00
2019-03-09 21:00:48 +00:00
{ IT_STRING | IT_CVAR , NULL , " Game Type " , & cv_newgametype , 68 } ,
{ IT_STRING | IT_CVAR , NULL , " Level " , & cv_nextmap , 78 } ,
2014-03-15 16:59:03 +00:00
2019-03-09 21:00:48 +00:00
{ IT_WHITESTRING | IT_CALL , NULL , " Start " , M_StartServer , 130 } ,
2014-03-15 16:59:03 +00:00
} ;
2018-10-16 21:11:47 +00:00
# endif
2018-09-30 21:09:59 +00:00
// Separated offline and normal servers.
static menuitem_t MP_OfflineServerMenu [ ] =
2014-03-15 16:59:03 +00:00
{
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-09-30 21:09:59 +00:00
2018-06-30 15:01:03 +00:00
{ IT_WHITESTRING | IT_CALL , NULL , " Start " , M_StartServer , 130 } ,
} ;
static menuitem_t MP_PlayerSetupMenu [ ] =
{
{ IT_KEYHANDLER | IT_STRING , NULL , " Name " , M_HandleSetupMultiPlayer , 0 } ,
{ IT_KEYHANDLER | IT_STRING , NULL , " Character " , M_HandleSetupMultiPlayer , 16 } , // Tails 01-18-2001
{ IT_KEYHANDLER | IT_STRING , NULL , " Color " , M_HandleSetupMultiPlayer , 152 } ,
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 } ,
2019-05-02 05:33:11 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Gameplay Options... " , & OP_GameOptionsDef , 70 } ,
{ IT_SUBMENU | IT_STRING , NULL , " Server Options... " , & OP_ServerOptionsDef , 80 } ,
2018-03-02 00:00:16 +00:00
2019-05-02 05:33:11 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Data Options... " , & OP_DataOptionsDef , 100 } ,
2018-06-15 00:18:29 +00:00
2019-05-02 05:33:11 +00:00
{ IT_CALL | IT_STRING , NULL , " Tricks & Secrets (F1) " , M_Manual , 120 } ,
{ IT_CALL | IT_STRING , NULL , " Play Credits " , M_Credits , 130 } ,
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
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
2018-11-23 03:50:40 +00:00
{ IT_STRING | IT_CVAR , NULL , " Controls per key " , & cv_controlperkey , 60 } ,
2014-03-15 16:59:03 +00:00
} ;
2018-09-27 20:55:21 +00:00
static menuitem_t OP_AllControlsMenu [ ] =
{
2018-11-26 08:12:22 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Gamepad Options... " , & OP_Joystick1Def , 0 } ,
{ IT_CALL | IT_STRING , NULL , " Reset to defaults " , M_ResetControls , 8 } ,
2018-09-27 20:55:21 +00:00
//{IT_SPACE, NULL, NULL, NULL, 0},
{ IT_HEADER , NULL , " Gameplay Controls " , NULL , 0 } ,
{ IT_SPACE , NULL , NULL , NULL , 0 } ,
{ IT_CONTROL , NULL , " Accelerate " , M_ChangeControl , gc_accelerate } ,
{ IT_CONTROL , NULL , " Turn Left " , M_ChangeControl , gc_turnleft } ,
{ IT_CONTROL , NULL , " Turn Right " , M_ChangeControl , gc_turnright } ,
{ IT_CONTROL , NULL , " Drift " , M_ChangeControl , gc_drift } ,
{ IT_CONTROL , NULL , " Brake " , M_ChangeControl , gc_brake } ,
{ IT_CONTROL , NULL , " Use/Throw Item " , M_ChangeControl , gc_fire } ,
{ IT_CONTROL , NULL , " Aim Forward " , M_ChangeControl , gc_aimforward } ,
{ IT_CONTROL , NULL , " Aim Backward " , M_ChangeControl , gc_aimbackward } ,
{ IT_CONTROL , NULL , " Look Backward " , M_ChangeControl , gc_lookback } ,
{ IT_HEADER , NULL , " Miscelleanous Controls " , NULL , 0 } ,
{ IT_SPACE , NULL , NULL , NULL , 0 } ,
{ IT_CONTROL , NULL , " Chat " , M_ChangeControl , gc_talkkey } ,
//{IT_CONTROL, NULL, "Team Chat", M_ChangeControl, gc_teamkey },
{ IT_CONTROL , NULL , " Show Rankings " , M_ChangeControl , gc_scores } ,
{ IT_CONTROL , NULL , " Change Viewpoint " , M_ChangeControl , gc_viewpoint } ,
{ IT_CONTROL , NULL , " Reset Camera " , M_ChangeControl , gc_camreset } ,
{ IT_CONTROL , NULL , " Toggle First-Person " , M_ChangeControl , gc_camtoggle } ,
{ IT_CONTROL , NULL , " Pause " , M_ChangeControl , gc_pause } ,
{ IT_CONTROL , NULL , " Screenshot " , M_ChangeControl , gc_screenshot } ,
{ IT_CONTROL , NULL , " Toggle GIF Recording " , M_ChangeControl , gc_recordgif } ,
{ IT_CONTROL , NULL , " Open/Close Menu (ESC) " , M_ChangeControl , gc_systemmenu } ,
{ IT_CONTROL , NULL , " Developer Console " , M_ChangeControl , gc_console } ,
{ IT_HEADER , NULL , " Spectator Controls " , NULL , 0 } ,
{ IT_SPACE , NULL , NULL , NULL , 0 } ,
{ IT_CONTROL , NULL , " Become Spectator " , M_ChangeControl , gc_spectate } ,
{ IT_CONTROL , NULL , " Look Up " , M_ChangeControl , gc_lookup } ,
{ IT_CONTROL , NULL , " Look Down " , M_ChangeControl , gc_lookdown } ,
{ IT_CONTROL , NULL , " Center View " , M_ChangeControl , gc_centerview } ,
{ IT_HEADER , NULL , " Custom Lua Actions " , NULL , 0 } ,
{ IT_SPACE , NULL , NULL , NULL , 0 } ,
{ IT_CONTROL , NULL , " Custom Action 1 " , M_ChangeControl , gc_custom1 } ,
{ IT_CONTROL , NULL , " Custom Action 2 " , M_ChangeControl , gc_custom2 } ,
{ IT_CONTROL , NULL , " Custom Action 3 " , M_ChangeControl , gc_custom3 } ,
2018-01-24 21:53:20 +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
} ;
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
} ;
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 } ,
2018-11-22 22:32:03 +00:00
{ IT_STRING | IT_CVAR , NULL , " First-Person MouseLook " , & cv_alwaysfreelook , 30 } ,
{ IT_STRING | IT_CVAR , NULL , " Third-Person MouseLook " , & cv_chasefreelook , 40 } ,
{ IT_STRING | IT_CVAR , NULL , " Mouse Move " , & cv_mousemove , 50 } ,
{ IT_STRING | IT_CVAR , NULL , " Invert Mouse " , & cv_invertmouse , 60 } ,
2014-03-15 16:59:03 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-11-22 22:32:03 +00:00
NULL , " Mouse X Speed " , & cv_mousesens , 70 } ,
2015-01-01 19:50:31 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-11-22 22:32:03 +00:00
NULL , " Mouse Y Speed " , & cv_mouseysens , 80 } ,
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 } ,
2018-11-22 22:32:03 +00:00
{ IT_STRING | IT_CVAR , NULL , " First-Person MouseLook " , & cv_alwaysfreelook2 , 30 } ,
{ IT_STRING | IT_CVAR , NULL , " Third-Person MouseLook " , & cv_chasefreelook2 , 40 } ,
{ IT_STRING | IT_CVAR , NULL , " Mouse Move " , & cv_mousemove2 , 50 } ,
{ IT_STRING | IT_CVAR , NULL , " Invert Mouse " , & cv_invertmouse2 , 60 } ,
2014-03-15 16:59:03 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-11-22 22:32:03 +00:00
NULL , " Mouse X Speed " , & cv_mousesens2 , 70 } ,
2015-01-01 19:50:31 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-11-22 22:32:03 +00:00
NULL , " Mouse Y Speed " , & cv_mouseysens2 , 80 } ,
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 } ,
2018-10-14 21:32:34 +00:00
//{IT_STRING | IT_CVAR, NULL, "Weather Density", &cv_precipdensity, 65},
{ IT_STRING | IT_CVAR , NULL , " Skyboxes " , & cv_skybox , 65 } ,
2019-05-23 06:16:20 +00:00
{ IT_STRING | IT_CVAR , NULL , " Field of View " , & cv_fov , 75 } ,
2018-06-15 00:18:29 +00:00
2019-05-23 06:16:20 +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
2019-05-23 06:16:20 +00:00
{ IT_STRING | IT_CVAR , NULL , " 3D models " , & cv_grmdls , 115 } ,
{ IT_STRING | IT_CVAR , NULL , " Fallback Player 3D Model " , & cv_grfallbackplayermodel , 125 } ,
{ IT_SUBMENU | IT_STRING , NULL , " OpenGL Options... " , & OP_OpenGLOptionsDef , 135 } ,
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 ,
2018-10-14 21:32:34 +00:00
//op_video_wd,
2018-08-05 15:34:51 +00:00
op_video_skybox ,
2019-05-23 06:16:20 +00:00
op_video_fov ,
2018-08-05 15:34:51 +00:00
op_video_fps ,
op_video_vsync ,
# ifdef HWRENDER
2018-11-04 14:41:24 +00:00
op_video_md2 ,
2019-05-23 05:45:32 +00:00
op_video_kartman ,
2018-08-05 15:34:51 +00:00
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-10-27 20:16:19 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Fog... " , & OP_OpenGLFogDef , 10 } ,
{ IT_SUBMENU | IT_STRING , NULL , " Gamma... " , & OP_OpenGLColorDef , 20 } ,
2019-05-23 06:16:20 +00:00
{ IT_STRING | IT_CVAR , NULL , " Quality " , & cv_scr_depth , 35 } ,
{ IT_STRING | IT_CVAR , NULL , " Texture Filter " , & cv_grfiltermode , 45 } ,
{ IT_STRING | IT_CVAR , NULL , " Anisotropic " , & cv_granisotropicmode , 55 } ,
2018-10-27 20:16:19 +00:00
/*#ifdef _WINDOWS
2014-03-15 16:59:03 +00:00
{ IT_STRING | IT_CVAR , NULL , " Fullscreen " , & cv_fullscreen , 50 } ,
# endif
# ifdef ALAM_LIGHTING
{ IT_SUBMENU | IT_STRING , NULL , " Lighting... " , & OP_OpenGLLightingDef , 70 } ,
2018-10-27 20:16:19 +00:00
# endif* /
2014-03-15 16:59:03 +00:00
} ;
# 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-11-29 13:49:50 +00:00
{ IT_STRING | IT_CVAR , NULL , " SFX " , & cv_gamesounds , 10 } ,
2018-06-15 00:18:29 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2018-11-29 13:49:50 +00:00
NULL , " SFX Volume " , & cv_soundvolume , 18 } ,
2018-06-30 22:18:13 +00:00
2018-11-29 13:49:50 +00:00
{ IT_STRING | IT_CVAR , NULL , " Music " , & cv_gamedigimusic , 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:
2018-11-29 13:49:50 +00:00
{ IT_STRING | IT_CVAR , NULL , " MIDI " , & cv_gamemidimusic , 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* /
2018-10-22 21:03:02 +00:00
//{IT_STRING|IT_CALL, NULL, "Restart Audio System", M_RestartAudio, 50},
2018-06-30 22:18:13 +00:00
2018-10-22 21:03:02 +00:00
{ IT_STRING | IT_CVAR , NULL , " Reverse L/R Channels " , & stereoreverse , 50 } ,
{ IT_STRING | IT_CVAR , NULL , " Surround Sound " , & surround , 60 } ,
2018-06-15 00:18:29 +00:00
2019-01-05 20:59:23 +00:00
{ IT_STRING | IT_CVAR , NULL , " Chat Notifications " , & cv_chatnotifications , 75 } ,
2018-10-22 21:03:02 +00:00
{ IT_STRING | IT_CVAR , NULL , " Character voices " , & cv_kartvoices , 85 } ,
{ IT_STRING | IT_CVAR , NULL , " Powerup Warning " , & cv_kartinvinsfx , 95 } ,
2014-03-15 16:59:03 +00:00
2018-11-29 13:49:50 +00:00
{ IT_KEYHANDLER | IT_STRING , NULL , " Sound Test " , M_HandleSoundTest , 110 } ,
2019-03-11 21:57:11 +00:00
{ IT_STRING | IT_CVAR , NULL , " Play Music While Unfocused " , & cv_playmusicifunfocused , 125 } ,
{ IT_STRING | IT_CVAR , NULL , " Play SFX While Unfocused " , & cv_playsoundifunfocused , 135 } ,
2014-03-15 16:59:03 +00:00
} ;
2019-05-02 05:33:11 +00:00
static menuitem_t OP_DataOptionsMenu [ ] =
2014-03-15 16:59:03 +00:00
{
2019-05-02 05:33:11 +00:00
{ IT_STRING | IT_CALL , NULL , " Screenshot Options... " , M_ScreenshotOptions , 10 } ,
{ IT_STRING | IT_CALL , NULL , " Add-on Options... " , M_AddonsOptions , 20 } ,
{ IT_STRING | IT_SUBMENU , NULL , " Replay Options... " , & MISC_ReplayOptionsDef , 30 } ,
2014-03-15 16:59:03 +00:00
2019-05-02 05:33:11 +00:00
{ IT_STRING | IT_SUBMENU , NULL , " Erase Data... " , & OP_EraseDataDef , 50 } ,
} ;
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
2019-02-16 02:51:44 +00:00
{ IT_STRING | IT_SUBMENU , NULL , " Online HUD options... " , & OP_ChatOptionsDef , 35 } ,
2018-08-09 21:59:52 +00:00
{ 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 } ,
2019-03-11 19:50:01 +00:00
{ IT_STRING | IT_CVAR , NULL , " Show \" FOCUS LOST \" " , & cv_showfocuslost , 135 } ,
2018-08-09 21:59:52 +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
2019-02-16 02:51:44 +00:00
// Ok it's still called chatoptions but we'll put ping display in here to be clean
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?
2019-01-05 20:59:23 +00:00
{ 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 ,
2019-01-05 20:59:23 +00:00
NULL , " Chat Box Width " , & cv_chatwidth , 25 } ,
2018-08-02 22:52:07 +00:00
{ IT_STRING | IT_CVAR | IT_CV_SLIDER ,
2019-01-05 20:59:23 +00:00
NULL , " Chat Box Height " , & cv_chatheight , 35 } ,
{ IT_STRING | IT_CVAR , NULL , " Chat Background Tint " , & cv_chatbacktint , 50 } ,
{ IT_STRING | IT_CVAR , NULL , " Message Fadeout Time " , & cv_chattime , 60 } ,
{ IT_STRING | IT_CVAR , NULL , " Spam Protection " , & cv_chatspamprotection , 70 } ,
2019-02-16 02:51:44 +00:00
{ IT_STRING | IT_CVAR , NULL , " Local ping display " , & cv_showping , 90 } , // shows ping next to framerate if we want to.
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
2019-01-05 20:59:23 +00:00
{ IT_STRING | IT_CVAR , NULL , " Time Limit " , & cv_timelimit , 100 } ,
{ IT_STRING | IT_CVAR , NULL , " Starting Bumpers " , & cv_kartbumpers , 110 } ,
{ IT_STRING | IT_CVAR , NULL , " Karma Comeback " , & cv_kartcomeback , 120 } ,
2018-06-15 00:18:29 +00:00
2019-01-05 20:59:23 +00:00
{ IT_STRING | IT_CVAR , NULL , " Force Character " , & cv_forceskin , 140 } ,
{ IT_STRING | IT_CVAR , NULL , " Restrict Character Changes " , & cv_restrictskinchange , 150 } ,
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 } ,
2018-11-04 01:00:17 +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 } ,
2018-11-27 17:10:46 +00:00
{ IT_STRING | IT_CVAR , NULL , " Allow Add-on Downloading " , & cv_downloading , 110 } ,
{ IT_STRING | IT_CVAR , NULL , " Pause Permission " , & cv_pause , 120 } ,
{ IT_STRING | IT_CVAR , NULL , " Mute All Chat " , & cv_mute , 130 } ,
2018-06-15 00:18:29 +00:00
2018-11-27 17:10:46 +00:00
{ IT_SUBMENU | IT_STRING , NULL , " Advanced Options... " , & OP_AdvServerOptionsDef , 150 } ,
2014-03-15 16:59:03 +00:00
# endif
} ;
2018-11-27 17:10:46 +00:00
# ifndef NONET
static menuitem_t OP_AdvServerOptionsMenu [ ] =
{
{ IT_STRING | IT_CVAR | IT_CV_STRING ,
NULL , " Server Browser Address " , & cv_masterserver , 10 } ,
{ IT_STRING | IT_CVAR , NULL , " Attempts to resynchronise " , & cv_resynchattempts , 40 } ,
{ IT_STRING | IT_CVAR , NULL , " Ping limit (ms) " , & cv_maxping , 50 } ,
2019-02-16 02:51:44 +00:00
{ IT_STRING | IT_CVAR , NULL , " Ping timeout (s) " , & cv_pingtimeout , 60 } ,
{ IT_STRING | IT_CVAR , NULL , " Connection timeout (tics) " , & cv_nettimeout , 70 } ,
{ IT_STRING | IT_CVAR , NULL , " Join timeout (tics) " , & cv_jointimeout , 80 } ,
2018-11-27 17:10:46 +00:00
2019-02-16 02:51:44 +00:00
{ IT_STRING | IT_CVAR , NULL , " Max. file transfer send (KB) " , & cv_maxsend , 100 } ,
{ IT_STRING | IT_CVAR , NULL , " File transfer packet rate " , & cv_downloadspeed , 110 } ,
2018-11-27 17:10:46 +00:00
2019-02-16 02:51:44 +00:00
{ IT_STRING | IT_CVAR , NULL , " Log join addresses " , & cv_showjoinaddress , 130 } ,
{ IT_STRING | IT_CVAR , NULL , " Log resyncs " , & cv_blamecfail , 140 } ,
{ IT_STRING | IT_CVAR , NULL , " Log file transfers " , & cv_noticedownload , 150 } ,
2018-11-27 17:10:46 +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 ) ,
2019-05-02 05:33:11 +00:00
& OP_DataOptionsDef ,
2018-08-28 20:08:47 +00:00
MISC_AddonsMenu ,
M_DrawAddons ,
50 , 28 ,
0 ,
NULL
} ;
2019-03-31 01:57:53 +00:00
menu_t MISC_ReplayHutDef =
{
2019-03-31 18:50:20 +00:00
NULL ,
2019-03-31 01:57:53 +00:00
sizeof ( MISC_ReplayHutMenu ) / sizeof ( menuitem_t ) ,
2019-03-31 18:50:20 +00:00
NULL ,
2019-03-31 01:57:53 +00:00
MISC_ReplayHutMenu ,
M_DrawReplayHut ,
30 , 80 ,
2019-05-02 05:33:11 +00:00
0 ,
2019-03-31 18:50:20 +00:00
M_QuitReplayHut
2019-03-31 01:57:53 +00:00
} ;
2019-03-31 22:29:41 +00:00
2019-03-31 18:50:29 +00:00
menu_t MISC_ReplayOptionsDef =
{
2019-04-06 07:17:30 +00:00
" M_REPOPT " ,
2019-03-31 18:50:29 +00:00
sizeof ( MISC_ReplayOptionsMenu ) / sizeof ( menuitem_t ) ,
2019-05-02 05:33:11 +00:00
& OP_DataOptionsDef ,
2019-03-31 18:50:29 +00:00
MISC_ReplayOptionsMenu ,
2019-05-02 05:33:11 +00:00
M_DrawGenericMenu ,
2019-03-31 18:50:29 +00:00
27 , 40 ,
0 ,
NULL
} ;
2019-03-31 01:57:53 +00:00
2019-03-31 22:29:41 +00:00
menu_t MISC_ReplayStartDef =
{
NULL ,
sizeof ( MISC_ReplayStartMenu ) / sizeof ( menuitem_t ) ,
& MISC_ReplayHutDef ,
MISC_ReplayStartMenu ,
M_DrawReplayStartMenu ,
30 , 90 ,
0 ,
NULL
} ;
2019-04-05 07:38:48 +00:00
menu_t PlaybackMenuDef = {
NULL ,
sizeof ( PlaybackMenu ) / sizeof ( menuitem_t ) ,
NULL ,
PlaybackMenu ,
M_DrawPlaybackMenu ,
2019-04-13 20:23:31 +00:00
//BASEVIDWIDTH/2 - 94, 2,
BASEVIDWIDTH / 2 - 88 , 2 ,
2019-04-05 07:38:48 +00:00
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 ) ;
2018-10-16 00:28:35 +00:00
menu_t MISC_ChangeSpectateDef = DEFAULTMENUSTYLE ( NULL , MISC_ChangeSpectateMenu , & MPauseDef , 27 , 40 ) ;
2014-03-15 16:59:03 +00:00
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.
//
2018-10-25 17:41:14 +00:00
static INT32 highlightflags , recommendedflags , warningflags ;
2018-07-01 18:29:13 +00:00
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
}
2018-10-25 17:41:14 +00:00
// excuse me but I'm extremely lazy:
INT32 HU_GetHighlightColor ( void )
{
M_GetGametypeColor ( ) ; // update flag colour reguardless of the menu being opened or not.
return highlightflags ;
}
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
} ;
2019-05-02 05:33:11 +00:00
menu_t SR_MainDef = CENTERMENUSTYLE ( NULL , SR_MainMenu , & MainDef , 72 ) ;
2018-06-30 15:01:03 +00:00
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//menu_t SR_LevelSelectDef = MAPICONMENUSTYLE(NULL, SR_LevelSelectMenu, &SR_MainDef);
2018-06-30 15:01:03 +00:00
2014-03-15 16:59:03 +00:00
menu_t SR_UnlockChecklistDef =
{
NULL ,
1 ,
2019-03-30 22:25:54 +00:00
& 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 ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
/*menu_t SP_LoadDef =
2014-03-15 16:59:03 +00:00
{
" M_PICKG " ,
1 ,
& SP_MainDef ,
SP_LoadGameMenu ,
M_DrawLoad ,
68 , 46 ,
0 ,
NULL
} ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
menu_t SP_LevelSelectDef = MAPICONMENUSTYLE ( NULL , SP_LevelSelectMenu , & SP_LoadDef ) ; */
2014-03-15 16:59:03 +00:00
menu_t SP_LevelStatsDef =
{
" M_STATS " ,
1 ,
2019-03-30 22:25:54 +00:00
& SR_MainDef ,
2014-03-15 16:59:03 +00:00
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
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
/*menu_t SP_PlayerDef =
2014-03-15 16:59:03 +00:00
{
" M_PICKP " ,
sizeof ( PlayerMenu ) / sizeof ( menuitem_t ) , //player_end,
& SP_MainDef ,
PlayerMenu ,
M_DrawSetupChoosePlayerMenu ,
24 , 32 ,
0 ,
NULL
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
} ; */
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 ) ,
2018-10-16 21:11:47 +00:00
& MainDef ,
2018-06-30 15:01:03 +00:00
MP_MainMenu ,
M_DrawMPMainMenu ,
2018-10-16 21:11:47 +00:00
42 , 30 ,
2018-06-30 15:01:03 +00:00
0 ,
2019-02-09 09:58:48 +00:00
# ifndef NONET
2018-06-30 15:01:03 +00:00
M_CancelConnect
2019-02-09 09:58:48 +00:00
# else
NULL
2018-07-06 17:08:35 +00:00
# endif
2019-02-09 09:58:48 +00:00
} ;
2018-09-30 21:09:59 +00:00
menu_t MP_OfflineServerDef = MAPICONMENUSTYLE ( " M_MULTI " , MP_OfflineServerMenu , & MP_MainDef ) ;
2019-02-09 09:58:48 +00:00
2014-03-15 16:59:03 +00:00
# ifndef NONET
2019-02-09 09:58:48 +00:00
menu_t MP_ServerDef = MAPICONMENUSTYLE ( " M_MULTI " , MP_ServerMenu , & MP_MainDef ) ;
2014-03-15 16:59:03 +00:00
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 ) ;
2018-09-27 20:55:21 +00:00
menu_t OP_AllControlsDef = CONTROLMENUSTYLE ( OP_AllControlsMenu , & OP_ControlsDef ) ;
menu_t OP_Joystick1Def = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_Joystick1Menu , & OP_AllControlsDef , 60 , 30 ) ;
menu_t OP_Joystick2Def = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_Joystick2Menu , & OP_AllControlsDef , 60 , 30 ) ;
menu_t OP_Joystick3Def = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_Joystick3Menu , & OP_AllControlsDef , 60 , 30 ) ;
menu_t OP_Joystick4Def = DEFAULTMENUSTYLE ( " M_CONTRO " , OP_Joystick4Menu , & OP_AllControlsDef , 60 , 30 ) ;
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 ) ;
2018-11-27 17:10:46 +00:00
# ifndef NONET
menu_t OP_AdvServerOptionsDef = DEFAULTMENUSTYLE ( " M_SERVER " , OP_AdvServerOptionsMenu , & OP_ServerOptionsDef , 24 , 30 ) ;
# endif
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);
2019-01-05 20:59:23 +00:00
//menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE("M_GAME", OP_ChatOptionsMenu, &OP_GameOptionsDef, 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
2019-05-02 05:33:11 +00:00
menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE ( " M_DATA " , OP_DataOptionsMenu , & OP_MainDef , 60 , 30 ) ;
menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE ( " M_SCSHOT " , OP_ScreenshotOptionsMenu , & OP_DataOptionsDef , 30 , 30 ) ;
menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE ( " M_ADDONS " , OP_AddonsOptionsMenu , & OP_DataOptionsDef , 30 , 30 ) ;
menu_t OP_EraseDataDef = DEFAULTMENUSTYLE ( " M_DATA " , OP_EraseDataMenu , & OP_DataOptionsDef , 30 , 30 ) ;
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 ;
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-11-07 21:42:10 +00:00
CV_SetValue ( & cv_dummystaff , 1 ) ;
if ( cv_dummystaff . value )
2018-07-06 17:08:35 +00:00
{
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-10-16 00:28:35 +00:00
static void Dummymenuplayer_OnChange ( void )
{
if ( cv_dummymenuplayer . value < 1 )
CV_StealthSetValue ( & cv_dummymenuplayer , splitscreen + 1 ) ;
else if ( cv_dummymenuplayer . value > splitscreen + 1 )
CV_StealthSetValue ( & cv_dummymenuplayer , 1 ) ;
}
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
2018-11-07 21:42:10 +00:00
char dummystaffname [ 22 ] ;
2018-11-04 01:00:17 +00:00
2017-10-21 02:01:07 +00:00
static void Dummystaff_OnChange ( void )
{
lumpnum_t l ;
2018-11-04 01:00:17 +00:00
dummystaffname [ 0 ] = ' \0 ' ;
2017-10-21 02:01:07 +00:00
if ( ( l = W_CheckNumForName ( va ( " %sS01 " , G_BuildMapName ( cv_nextmap . value ) ) ) ) = = LUMPERROR )
{
CV_StealthSetValue ( & cv_dummystaff , 0 ) ;
return ;
}
else
{
2018-11-07 21:42:10 +00:00
char * temp = dummystaffname ;
2017-10-21 02:01:07 +00:00
UINT8 numstaff = 1 ;
2018-11-07 21:42:10 +00:00
while ( numstaff < 99 & & ( l = W_CheckNumForName ( va ( " %sS%02u " , G_BuildMapName ( cv_nextmap . value ) , numstaff + 1 ) ) ) ! = LUMPERROR )
2017-10-21 02:01:07 +00:00
numstaff + + ;
if ( cv_dummystaff . value < 1 )
CV_StealthSetValue ( & cv_dummystaff , numstaff ) ;
else if ( cv_dummystaff . value > numstaff )
CV_StealthSetValue ( & cv_dummystaff , 1 ) ;
2018-11-04 01:00:17 +00:00
if ( ( l = W_CheckNumForName ( va ( " %sS%02u " , G_BuildMapName ( cv_nextmap . value ) , cv_dummystaff . value ) ) ) = = LUMPERROR )
return ; // shouldn't happen but might as well check...
G_UpdateStaffGhostName ( l ) ;
2018-11-07 21:42:10 +00:00
while ( * temp )
temp + + ;
sprintf ( temp , " - %d " , cv_dummystaff . value ) ;
2017-10-21 02:01:07 +00:00
}
}
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-11-27 17:10:46 +00:00
{
# ifndef NONET
if ( cv = = & cv_nettimeout | | cv = = & cv_jointimeout )
choice * = ( TICRATE / 7 ) ;
else if ( cv = = & cv_maxsend )
choice * = 512 ;
else if ( cv = = & cv_maxping )
choice * = 50 ;
# endif
2018-07-29 17:35:56 +00:00
CV_AddValue ( cv , choice ) ;
2018-11-27 17:10:46 +00:00
}
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
2019-03-09 21:14:08 +00:00
if ( ( currentMenu - > menuitems [ itemOn ] . status & IT_CVARTYPE ) = = IT_CV_PASSWORD )
( ( consvar_t * ) currentMenu - > menuitems [ itemOn ] . itemaction ) - > value = 0 ;
2014-03-15 16:59:03 +00:00
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
2019-03-09 21:14:08 +00:00
if ( ( currentMenu - > menuitems [ itemOn ] . status & IT_CVARTYPE ) = = IT_CV_PASSWORD )
( ( consvar_t * ) currentMenu - > menuitems [ itemOn ] . itemaction ) - > value = 0 ;
2014-03-15 16:59:03 +00:00
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 ;
2018-11-05 19:02:34 +00:00
static void Command_Manual_f ( void )
{
if ( modeattacking )
return ;
M_StartControlPanel ( ) ;
M_Manual ( INT32_MAX ) ;
itemOn = 0 ;
}
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 ;
2018-12-02 21:52:30 +00:00
static INT32 pjoyx = 0 , pjoyy = 0 ;
2014-03-15 16:59:03 +00:00
static INT32 pmousex = 0 , pmousey = 0 ;
static INT32 lastx = 0 , lasty = 0 ;
void ( * routine ) ( INT32 choice ) ; // for some casting problem
2019-03-25 02:32:15 +00:00
if ( dedicated | | ( demo . playback & & demo . title )
2014-03-15 16:59:03 +00:00
| | 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 ;
}
2018-12-10 15:00:15 +00:00
else if ( ev - > type = = ev_keydown )
2014-03-15 16:59:03 +00:00
{
2018-12-10 15:00:15 +00:00
ch = ev - > data1 ;
2018-12-03 08:33:12 +00:00
2018-12-10 15:00:15 +00:00
// added 5-2-98 remap virtual keys (mouse & joystick buttons)
switch ( ch )
{
case KEY_MOUSE1 :
//case KEY_JOY1:
//case KEY_JOY1 + 2:
ch = KEY_ENTER ;
break ;
/*case KEY_JOY1 + 3: // Brake can function as 'n' for message boxes now.
2018-12-03 08:33:12 +00:00
ch = ' n ' ;
2018-12-10 15:00:15 +00:00
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 ;
2014-03-15 16:59:03 +00:00
}
2018-12-10 15:00:15 +00:00
}
else if ( menuactive )
{
if ( ev - > type = = ev_joystick & & ev - > data1 = = 0 & & joywait < I_GetTime ( ) )
2014-03-15 16:59:03 +00:00
{
2019-05-02 03:30:53 +00:00
const INT32 jdeadzone = ( ( JOYAXISRANGE - 1 ) * cv_deadzone . value ) > > FRACBITS ;
2018-12-02 21:18:28 +00:00
if ( ev - > data3 ! = INT32_MAX )
2014-03-15 16:59:03 +00:00
{
2018-12-02 21:52:30 +00:00
if ( Joystick . bGamepadStyle | | abs ( ev - > data3 ) > jdeadzone )
2018-12-02 21:18:28 +00:00
{
2018-12-02 21:52:30 +00:00
if ( ev - > data3 < 0 & & pjoyy > = 0 )
{
ch = KEY_UPARROW ;
joywait = I_GetTime ( ) + NEWTICRATE / 7 ;
}
else if ( ev - > data3 > 0 & & pjoyy < = 0 )
{
ch = KEY_DOWNARROW ;
joywait = I_GetTime ( ) + NEWTICRATE / 7 ;
}
pjoyy = ev - > data3 ;
2018-12-02 21:18:28 +00:00
}
2018-12-02 21:52:30 +00:00
else
pjoyy = 0 ;
2014-03-15 16:59:03 +00:00
}
2018-12-02 21:18:28 +00:00
if ( ev - > data2 ! = INT32_MAX )
2014-03-15 16:59:03 +00:00
{
2018-12-02 21:52:30 +00:00
if ( Joystick . bGamepadStyle | | abs ( ev - > data2 ) > jdeadzone )
2018-12-02 21:18:28 +00:00
{
2018-12-02 21:52:30 +00:00
if ( ev - > data2 < 0 & & pjoyx > = 0 )
{
ch = KEY_LEFTARROW ;
joywait = I_GetTime ( ) + NEWTICRATE / 17 ;
}
else if ( ev - > data2 > 0 & & pjoyx < = 0 )
{
ch = KEY_RIGHTARROW ;
joywait = I_GetTime ( ) + NEWTICRATE / 17 ;
}
pjoyx = ev - > data2 ;
2018-12-02 21:18:28 +00:00
}
2018-12-02 21:52:30 +00:00
else
pjoyx = 0 ;
2014-03-15 16:59:03 +00:00
}
}
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 ;
2018-09-27 00:51:25 +00:00
else if ( ch = = gamecontrol [ gc_systemmenu ] [ 0 ] | | ch = = gamecontrol [ gc_systemmenu ] [ 1 ] ) // allow remappable ESC key
2017-12-25 07:09:06 +00:00
ch = KEY_ESCAPE ;
2019-01-15 09:02:52 +00:00
else if ( ( ch = = gamecontrol [ gc_accelerate ] [ 0 ] | | ch = = gamecontrol [ gc_accelerate ] [ 1 ] ) & & ch > = KEY_MOUSE1 )
2018-12-10 15:00:15 +00:00
ch = KEY_ENTER ;
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
2018-11-05 19:02:34 +00:00
Command_Manual_f ( ) ;
2014-03-15 16:59:03 +00:00
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 ;
}
2019-01-15 09:02:52 +00:00
if ( ( ch = = gamecontrol [ gc_brake ] [ 0 ] | | ch = = gamecontrol [ gc_brake ] [ 1 ] ) & & ch > = KEY_MOUSE1 ) // do this here, otherwise brake opens the menu mid-game
2018-12-10 15:00:15 +00:00
ch = KEY_ESCAPE ;
2014-03-15 16:59:03 +00:00
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 )
{
2019-03-09 21:00:48 +00:00
if ( ( currentMenu - > menuitems [ itemOn ] . status & IT_CVARTYPE ) = = IT_CV_STRING | | ( currentMenu - > menuitems [ itemOn ] . status & IT_CVARTYPE ) = = IT_CV_PASSWORD )
2014-03-15 16:59:03 +00:00
{
2019-03-09 23:03:52 +00:00
if ( ch = = KEY_TAB & & ( currentMenu - > menuitems [ itemOn ] . status & IT_CVARTYPE ) = = IT_CV_PASSWORD )
2019-03-09 21:14:08 +00:00
( ( consvar_t * ) currentMenu - > menuitems [ itemOn ] . itemaction ) - > value ^ = 1 ;
2014-03-15 16:59:03 +00:00
if ( shiftdown & & ch > = 32 & & ch < = 127 )
ch = shiftxform [ ch ] ;
if ( M_ChangeStringCvar ( ch ) )
return true ;
else
routine = NULL ;
}
else
routine = M_ChangeCvar ;
}
2019-04-05 07:38:48 +00:00
if ( currentMenu = = & PlaybackMenuDef )
{
// Flip left/right with up/down for the playback menu, since it's a horizontal icon row.
switch ( ch )
{
2019-05-02 16:00:51 +00:00
case KEY_LEFTARROW : ch = KEY_UPARROW ; break ;
case KEY_UPARROW : ch = KEY_RIGHTARROW ; break ;
case KEY_RIGHTARROW : ch = KEY_DOWNARROW ; break ;
case KEY_DOWNARROW : ch = KEY_LEFTARROW ; break ;
default : break ;
2019-04-05 07:38:48 +00:00
}
}
2014-03-15 16:59:03 +00:00
// Keys usable within menu
switch ( ch )
{
case KEY_DOWNARROW :
M_NextOpt ( ) ;
S_StartSound ( NULL , sfx_menu1 ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
/*if (currentMenu == &SP_PlayerDef)
2014-03-15 16:59:03 +00:00
{
Z_Free ( char_notes ) ;
char_notes = NULL ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
} */
2014-03-15 16:59:03 +00:00
return true ;
case KEY_UPARROW :
M_PrevOpt ( ) ;
S_StartSound ( NULL , sfx_menu1 ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
/*if (currentMenu == &SP_PlayerDef)
2014-03-15 16:59:03 +00:00
{
Z_Free ( char_notes ) ;
char_notes = NULL ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
} */
2014-03-15 16:59:03 +00:00
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 ;
2019-05-02 16:00:51 +00:00
if ( currentMenu = = & PlaybackMenuDef )
{
boolean held = ( boolean ) playback_enterheld ;
playback_enterheld = TICRATE / 7 ;
if ( held )
return true ;
}
2014-03-15 16:59:03 +00:00
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 ) )
{
2019-01-26 16:58:45 +00:00
if ( ( ( currentMenu - > menuitems [ itemOn ] . status & IT_CALLTYPE ) & IT_CALL_NOTMODIFIED ) & & majormods )
2014-03-15 16:59:03 +00:00
{
S_StartSound ( NULL , sfx_menu1 ) ;
2019-01-15 19:01:55 +00:00
M_StartMessage ( M_GetText ( " This cannot be done with complex add-ons \n or in a cheated game. \n \n (Press a key) \n " ) , NULL , MM_NOTHING ) ;
2014-03-15 16:59:03 +00:00
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 :
2018-12-10 15:00:15 +00:00
//case KEY_JOY1 + 2:
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 )
{
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 ) ;
2018-09-29 15:18:16 +00:00
S_StartSound ( NULL , sfx_shldls ) ;
2014-03-15 16:59:03 +00:00
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...)
2019-04-05 07:38:48 +00:00
if ( ! WipeInAction & & currentMenu ! = & PlaybackMenuDef ) // Replay playback has its own background
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-11-03 07:38:41 +00:00
V_DrawThinString ( vid . dupx , vid . height - 20 * vid . dupy , V_NOSCALESTART | V_TRANSLUCENT | V_ALLOWLOWERCASE , compbranch ) ;
V_DrawThinString ( vid . dupx , vid . height - 10 * vid . dupy , V_NOSCALESTART | V_TRANSLUCENT | V_ALLOWLOWERCASE , comprevision ) ;
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
2019-03-11 19:50:01 +00:00
if ( window_notinfocus & & cv_showfocuslost . value )
2016-07-06 04:09:17 +00:00
{
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 )
{
// intro might call this repeatedly
if ( menuactive )
{
CON_ToggleOff ( ) ; // move away console
return ;
}
menuactive = true ;
2019-04-05 07:38:48 +00:00
if ( demo . playback )
{
currentMenu = & PlaybackMenuDef ;
}
else if ( ! Playing ( ) )
2014-03-15 16:59:03 +00:00
{
// 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
{
2018-10-17 12:40:17 +00:00
if ( gamestate ! = GS_LEVEL /*|| ultimatemode*/ ) // intermission, so gray out stuff.
2014-03-15 16:59:03 +00:00
{
SPauseMenu [ spause_pandora ] . status = ( M_SecretUnlocked ( SECRET_PANDORA ) ) ? ( IT_GRAYEDOUT ) : ( IT_DISABLED ) ;
SPauseMenu [ spause_retry ] . status = IT_GRAYEDOUT ;
}
else
{
2018-10-17 12:40:17 +00:00
//INT32 numlives = 2;
2014-03-15 16:59:03 +00:00
SPauseMenu [ spause_pandora ] . status = ( M_SecretUnlocked ( SECRET_PANDORA ) ) ? ( IT_STRING | IT_CALL ) : ( IT_DISABLED ) ;
2018-10-17 12:40:17 +00:00
/*if (&players[consoleplayer])
2014-03-15 16:59:03 +00:00
{
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 ) ;
2018-10-17 12:40:17 +00:00
else */
2014-03-15 16:59:03 +00:00
SPauseMenu [ spause_retry ] . status = ( IT_STRING | IT_CALL ) ;
}
// We can always use level select though. :33
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
//SPauseMenu[spause_levelselect].status = (gamecomplete) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
2014-03-15 16:59:03 +00:00
// 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 ;
2017-12-18 10:56:38 +00:00
MPauseMenu [ mpause_psetupsplit3 ] . status = IT_DISABLED ;
MPauseMenu [ mpause_psetupsplit4 ] . status = IT_DISABLED ;
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 ;
2018-10-16 00:28:35 +00:00
MPauseMenu [ mpause_switchspectate ] . status = IT_DISABLED ;
2014-03-15 16:59:03 +00:00
MPauseMenu [ mpause_psetup ] . status = IT_DISABLED ;
2018-10-16 00:28:35 +00:00
MISC_ChangeTeamMenu [ 0 ] . status = IT_DISABLED ;
MISC_ChangeSpectateMenu [ 0 ] . status = IT_DISABLED ;
2017-12-18 10:56:38 +00:00
// Reset these in case splitscreen messes things up
2018-10-16 00:28:35 +00:00
MPauseMenu [ mpause_switchteam ] . alphaKey = 48 ;
MPauseMenu [ mpause_switchspectate ] . alphaKey = 48 ;
2017-12-18 10:56:38 +00:00
MPauseMenu [ mpause_options ] . alphaKey = 64 ;
MPauseMenu [ mpause_title ] . alphaKey = 80 ;
MPauseMenu [ mpause_quit ] . alphaKey = 88 ;
2018-10-16 00:28:35 +00:00
Dummymenuplayer_OnChange ( ) ;
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 ;
2018-10-16 00:28:35 +00:00
MISC_ChangeTeamMenu [ 0 ] . status = MISC_ChangeSpectateMenu [ 0 ] . status = IT_STRING | IT_CVAR ;
if ( netgame )
{
if ( G_GametypeHasTeams ( ) )
{
MPauseMenu [ mpause_switchteam ] . status = IT_STRING | IT_SUBMENU ;
MPauseMenu [ mpause_switchteam ] . alphaKey + = ( ( splitscreen + 1 ) * 8 ) ;
MPauseMenu [ mpause_options ] . alphaKey + = 8 ;
MPauseMenu [ mpause_title ] . alphaKey + = 8 ;
MPauseMenu [ mpause_quit ] . alphaKey + = 8 ;
}
else if ( G_GametypeHasSpectators ( ) )
{
MPauseMenu [ mpause_switchspectate ] . status = IT_STRING | IT_SUBMENU ;
MPauseMenu [ mpause_switchspectate ] . alphaKey + = ( ( splitscreen + 1 ) * 8 ) ;
MPauseMenu [ mpause_options ] . alphaKey + = 8 ;
MPauseMenu [ mpause_title ] . alphaKey + = 8 ;
MPauseMenu [ mpause_quit ] . alphaKey + = 8 ;
}
}
2017-12-18 10:56:38 +00:00
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 ;
2018-10-16 00:28:35 +00:00
MPauseMenu [ mpause_options ] . alphaKey + = 8 ;
MPauseMenu [ mpause_title ] . alphaKey + = 8 ;
MPauseMenu [ mpause_quit ] . alphaKey + = 8 ;
2017-12-18 10:56:38 +00:00
2018-10-16 00:28:35 +00:00
if ( splitscreen > 2 )
2017-12-18 10:56:38 +00:00
{
MPauseMenu [ mpause_psetupsplit4 ] . status = IT_STRING | IT_CALL ;
2018-10-16 00:28:35 +00:00
MPauseMenu [ mpause_options ] . alphaKey + = 8 ;
MPauseMenu [ mpause_title ] . alphaKey + = 8 ;
MPauseMenu [ mpause_quit ] . alphaKey + = 8 ;
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 ;
2019-05-02 16:00:51 +00:00
if ( currentMenu = = & PlaybackMenuDef )
{
if ( playback_enterheld > 0 )
playback_enterheld - - ;
}
else
playback_enterheld = 0 ;
2014-03-15 16:59:03 +00:00
//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 )
{
2019-01-16 01:09:55 +00:00
UINT8 i ;
2018-11-05 19:02:34 +00:00
COM_AddCommand ( " manual " , Command_Manual_f ) ;
2014-03-15 16:59:03 +00:00
CV_RegisterVar ( & cv_nextmap ) ;
CV_RegisterVar ( & cv_newgametype ) ;
CV_RegisterVar ( & cv_chooseskin ) ;
CV_RegisterVar ( & cv_autorecord ) ;
if ( dedicated )
return ;
// Menu hacks
2018-10-16 00:28:35 +00:00
CV_RegisterVar ( & cv_dummymenuplayer ) ;
2014-03-15 16:59:03 +00:00
CV_RegisterVar ( & cv_dummyteam ) ;
2018-10-16 00:28:35 +00:00
CV_RegisterVar ( & cv_dummyspectate ) ;
2014-03-15 16:59:03 +00:00
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
2019-01-16 01:09:55 +00:00
// Setup PlayerMenu table
for ( i = 0 ; i < MAXSKINS ; i + + )
{
PlayerMenu [ i ] . status = ( i = = 0 ? IT_CALL : IT_DISABLED ) ;
PlayerMenu [ i ] . patch = PlayerMenu [ i ] . text = NULL ;
PlayerMenu [ i ] . itemaction = M_ChoosePlayer ;
PlayerMenu [ i ] . alphaKey = 0 ;
}
2014-03-15 16:59:03 +00:00
# ifdef HWRENDER
// Permanently hide some options based on render mode
if ( rendermode = = render_soft )
2019-05-23 05:45:32 +00:00
OP_VideoOptionsMenu [ op_video_ogl ] . status =
OP_VideoOptionsMenu [ op_video_kartman ] . status =
OP_VideoOptionsMenu [ op_video_md2 ] . 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 ) ;
}
2019-01-27 04:16:49 +00:00
void M_InitCharacterTables ( void )
{
UINT8 i ;
2019-01-16 01:09:55 +00:00
// Setup PlayerMenu table
for ( i = 0 ; i < MAXSKINS ; i + + )
{
PlayerMenu [ i ] . status = ( i < 4 ? IT_CALL : IT_DISABLED ) ;
PlayerMenu [ i ] . patch = PlayerMenu [ i ] . text = NULL ;
PlayerMenu [ i ] . itemaction = M_ChoosePlayer ;
PlayerMenu [ i ] . alphaKey = 0 ;
}
// Setup description table
for ( i = 0 ; i < MAXSKINS ; i + + )
{
if ( i = = 0 )
{
strcpy ( description [ i ] . notes , " \x82 Sonic \x80 is the fastest of the three, but also the hardest to control. Beginners beware, but experts will find Sonic very powerful. \n \n \x82 " " Ability: \x80 Speed Thok \n Double jump to zoom forward with a huge burst of speed. \n \n \x82 Tip: \x80 Simply letting go of forward does not slow down in SRB2. To slow down, hold the opposite direction. " ) ;
strcpy ( description [ i ] . picname , " " ) ;
strcpy ( description [ i ] . skinname , " sonic " ) ;
}
else if ( i = = 1 )
{
strcpy ( description [ i ] . notes , " \x82 Tails \x80 is the most mobile of the three, but has the slowest speed. Because of his mobility, he's well- \n suited to beginners. \n \n \x82 " " Ability: \x80 Fly \n Double jump to start flying for a limited time. Repetitively hit the jump button to ascend. \n \n \x82 Tip: \x80 To quickly descend while flying, hit the spin button. " ) ;
strcpy ( description [ i ] . picname , " " ) ;
strcpy ( description [ i ] . skinname , " tails " ) ;
}
else if ( i = = 2 )
{
strcpy ( description [ i ] . notes , " \x82 Knuckles \x80 is well- \n rounded and can destroy breakable walls simply by touching them, but he can't jump as high as the other two. \n \n \x82 " " Ability: \x80 Glide & Climb \n Double jump to glide in the air as long as jump is held. Glide into a wall to climb it. \n \n \x82 Tip: \x80 Press spin while climbing to jump off the wall; press jump instead to jump off \n and face away from \n the wall. " ) ;
strcpy ( description [ i ] . picname , " " ) ;
strcpy ( description [ i ] . skinname , " knuckles " ) ;
}
else if ( i = = 3 )
{
strcpy ( description [ i ] . notes , " \x82 Sonic & Tails \x80 team up to take on Dr. Eggman! \n Control Sonic while Tails desperately struggles to keep up. \n \n Player 2 can control Tails directly by setting the controls in the options menu. \n Tails's directional controls are relative to Player 1's camera. \n \n Tails can pick up Sonic while flying and carry him around. " ) ;
strcpy ( description [ i ] . picname , " CHRS&T " ) ;
strcpy ( description [ i ] . skinname , " sonic&tails " ) ;
}
else
{
strcpy ( description [ i ] . notes , " ??? " ) ;
strcpy ( description [ i ] . picname , " " ) ;
strcpy ( description [ i ] . skinname , " " ) ;
}
}
2014-03-15 16:59:03 +00:00
}
// ==========================================================================
// 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
//
2018-12-06 02:27:51 +00:00
/*static void M_DrawSaveLoadBorder(INT32 x,INT32 y)
2014-03-15 16:59:03 +00:00
{
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 ) ) ;
2018-12-06 02:27:51 +00:00
} */
2014-03-15 16:59:03 +00:00
// 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 ) ,
2019-03-16 05:39:52 +00:00
R_GetTranslationColormap ( TC_DEFAULT , M_GetEmblemColor ( emblem ) , GTC_MENUCACHE ) ) ;
2014-03-15 16:59:03 +00:00
else
V_DrawSmallScaledPatch ( x , y , 0 , W_CachePatchName ( " NEEDIT " , PU_CACHE ) ) ;
emblem = M_GetLevelEmblems ( - 1 ) ;
2018-11-01 00:10:34 +00:00
x - = 8 ;
2014-03-15 16:59:03 +00:00
}
}
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 ;
2019-03-09 21:00:48 +00:00
char asterisks [ MAXSTRINGLENGTH + 1 ] ;
size_t sl ;
2014-03-15 16:59:03 +00:00
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 ;
2019-03-09 21:14:08 +00:00
case IT_CV_PASSWORD :
if ( i = = itemOn )
{
V_DrawRightAlignedThinString ( x + MAXSTRINGLENGTH * 8 + 10 , y , V_ALLOWLOWERCASE , va ( M_GetText ( " Tab: %s password " ) , cv - > value ? " hide " : " show " ) ) ;
}
if ( ! cv - > value | | i ! = itemOn )
{
sl = strlen ( cv - > string ) ;
memset ( asterisks , ' * ' , sl ) ;
memset ( asterisks + sl , 0 , MAXSTRINGLENGTH + 1 - sl ) ;
M_DrawTextBox ( x , y + 4 , MAXSTRINGLENGTH , 1 ) ;
V_DrawString ( x + 8 , y + 12 , V_ALLOWLOWERCASE , asterisks ) ;
if ( skullAnimCounter < 4 & & i = = itemOn )
V_DrawCharacter ( x + 8 + V_StringWidth ( asterisks , 0 ) , y + 12 ,
' _ ' | 0x80 , false ) ;
y + = 16 ;
break ;
}
/* fallthru */
2014-03-15 16:59:03 +00:00
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
}
}
2019-03-31 18:50:29 +00:00
static void M_DrawGenericBackgroundMenu ( void )
{
V_DrawPatchFill ( W_CachePatchName ( " SRB2BACK " , PU_CACHE ) ) ;
M_DrawGenericMenu ( ) ;
}
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 ) ,
2019-03-16 05:39:52 +00:00
R_GetTranslationColormap ( TC_DEFAULT , M_GetEmblemColor ( emblem ) , GTC_MENUCACHE ) ) ;
2014-03-15 16:59:03 +00:00
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
2018-10-06 20:08:09 +00:00
/*if (gt == GT_COOP && (mapheaderinfo[mapnum]->typeoflevel & TOL_COOP))
2014-03-15 16:59:03 +00:00
return true ;
if ( gt = = GT_COMPETITION & & ( mapheaderinfo [ mapnum ] - > typeoflevel & TOL_COMPETITION ) )
return true ;
if ( gt = = GT_CTF & & ( mapheaderinfo [ mapnum ] - > typeoflevel & TOL_CTF ) )
return true ;
if ( ( gt = = GT_TAG | | gt = = GT_HIDEANDSEEK ) & & ( mapheaderinfo [ mapnum ] - > typeoflevel & TOL_TAG ) )
2018-10-06 20:08:09 +00:00
return true ; */
if ( ( gt = = GT_MATCH | | gt = = GT_TEAMMATCH ) & & ( mapheaderinfo [ mapnum ] - > typeoflevel & TOL_MATCH ) )
2014-03-15 16:59:03 +00:00
return true ;
if ( gt = = GT_RACE & & ( mapheaderinfo [ mapnum ] - > typeoflevel & TOL_RACE ) )
return true ;
return false ;
2018-10-06 20:08:09 +00:00
/*case LLM_LEVELSELECT:
2014-03-15 16:59:03 +00:00
if ( mapheaderinfo [ mapnum ] - > levelselect ! = maplistoption )
return false ;
if ( M_MapLocked ( mapnum + 1 ) )
return false ; // not unlocked
2018-10-06 20:08:09 +00:00
return true ; */
2014-03-15 16:59:03 +00:00
case LLM_RECORDATTACK :
2018-10-06 20:08:09 +00:00
/*if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK))
return false ; */
if ( ! ( mapheaderinfo [ mapnum ] - > typeoflevel & TOL_RACE ) )
2014-03-15 16:59:03 +00:00
return false ;
if ( M_MapLocked ( mapnum + 1 ) )
return false ; // not unlocked
2018-10-06 20:08:09 +00:00
if ( M_SecretUnlocked ( SECRET_HELLATTACK ) )
return true ; // now you're in hell
if ( mapheaderinfo [ mapnum ] - > menuflags & LF2_HIDEINMENU )
return false ; // map hell
/*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED)
2014-03-15 16:59:03 +00:00
return true ;
if ( ! mapvisited [ mapnum ] )
2018-10-06 20:08:09 +00:00
return false ; */
2014-03-15 16:59:03 +00:00
return true ;
2018-10-06 20:08:09 +00:00
/*case LLM_NIGHTSATTACK:
2014-03-15 16:59:03 +00:00
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 ;
2018-10-06 20:08:09 +00:00
return true ; */
default :
return false ;
2014-03-15 16:59:03 +00:00
}
// 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
2019-05-02 16:03:50 +00:00
MessageDef . prevMenu = ( ( demo . playback ) ? & PlaybackMenuDef : & MainDef ) ;
2014-03-15 16:59:03 +00:00
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
{
2018-11-14 01:27:01 +00:00
INT32 x = BASEVIDWIDTH > > 1 , y = ( BASEVIDHEIGHT > > 1 ) - 4 ;
x + = ( itemOn ? 1 : - 1 ) * ( ( BASEVIDWIDTH > > 2 ) + 10 ) ;
2018-09-10 11:39:59 +00:00
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 ] ;
2019-03-31 01:57:53 +00:00
if ( ! preparefilemenu ( false , false ) )
2018-08-28 20:08:47 +00:00
{
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-12-16 21:07:47 +00:00
# ifdef USE_KART
2018-08-29 13:19:08 +00:00
addonsp [ EXT_KART ] = W_CachePatchName ( " M_FKART " , PU_STATIC ) ;
2018-12-16 21:07:47 +00:00
# endif
2018-11-29 15:07:53 +00:00
addonsp [ EXT_PK3 ] = W_CachePatchName ( " M_FPK3 " , PU_STATIC ) ;
2018-08-28 20:08:47 +00:00
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 ;
}
2018-11-14 01:27:01 +00:00
# define UNEXIST S_StartSound(NULL, sfx_s26d);\
2018-08-28 20:08:47 +00:00
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
2019-01-17 20:51:41 +00:00
static boolean prevmajormods = false ;
2018-08-28 20:08:47 +00:00
static void M_AddonsClearName ( INT32 choice )
{
2019-01-17 22:01:28 +00:00
if ( ! majormods | | prevmajormods )
2019-01-17 20:51:41 +00:00
{
CLEARNAME ;
}
2018-08-28 20:08:47 +00:00
M_StopMessage ( choice ) ;
}
// returns whether to do message draw
static boolean M_AddonsRefresh ( void )
{
2019-03-31 01:57:53 +00:00
if ( ( refreshdirmenu & REFRESHDIR_NORMAL ) & & ! preparefilemenu ( true , false ) )
2018-08-28 20:08:47 +00:00
{
UNEXIST ;
2019-01-28 16:32:07 +00:00
if ( refreshdirname )
{
CLEARNAME ;
}
2018-08-28 20:08:47 +00:00
return true ;
}
2019-01-17 22:01:28 +00:00
if ( ! majormods & & prevmajormods )
prevmajormods = false ;
if ( ( refreshdirmenu & REFRESHDIR_ADDFILE ) | | ( majormods & & ! prevmajormods ) )
2018-08-28 20:08:47 +00:00
{
char * message = NULL ;
if ( refreshdirmenu & REFRESHDIR_NOTLOADED )
{
2018-11-14 01:27:01 +00:00
S_StartSound ( NULL , sfx_s26d ) ;
2018-08-28 20:08:47 +00:00
if ( refreshdirmenu & REFRESHDIR_MAX )
2019-02-01 23:51:15 +00:00
message = va ( " %c%s \x80 \n Maximum number of add-ons reached. \n A file could not be loaded. \n If you wish to play with this add-on, restart the game to clear existing ones. \n \n (Press a key) \n " , ( ' \x80 ' + ( highlightflags > > V_CHARCOLORSHIFT ) ) , refreshdirname ) ;
2018-08-28 20:08:47 +00:00
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 ) )
{
2018-11-14 01:27:01 +00:00
S_StartSound ( NULL , sfx_s224 ) ;
2018-08-28 20:08:47 +00:00
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 " ) ) ;
}
2019-01-26 16:58:45 +00:00
else if ( majormods & & ! prevmajormods )
2019-01-17 20:51:41 +00:00
{
S_StartSound ( NULL , sfx_s221 ) ;
2019-02-01 23:51:15 +00:00
message = va ( " %c%s \x80 \n Gameplay has now been modified. \n If you wish to play Record Attack mode, restart the game to clear existing add-ons. \n \n (Press a key) \n " , ( ' \x80 ' + ( highlightflags > > V_CHARCOLORSHIFT ) ) , refreshdirname ) ;
2019-01-17 20:51:41 +00:00
prevmajormods = majormods ;
}
2018-08-28 20:08:47 +00:00
if ( message )
{
M_StartMessage ( message , M_AddonsClearName , MM_EVENTHANDLER ) ;
return true ;
}
2018-11-14 01:27:01 +00:00
S_StartSound ( NULL , sfx_s221 ) ;
2018-08-28 20:08:47 +00:00
CLEARNAME ;
}
return false ;
}
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
{
2019-04-18 04:09:10 +00:00
y = FixedDiv ( ( ( ssize_t ) ( numwadfiles ) - ( ssize_t ) ( mainwads + 1 ) ) < < FRACBITS , ( ( ssize_t ) MAX_WADFILES - ( ssize_t ) ( mainwads + 1 ) ) < < FRACBITS ) ;
2018-08-28 20:08:47 +00:00
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
2019-01-03 00:58:21 +00:00
// then compute top and adjust bottom if needed!
if ( m < ( 2 * numaddonsshown + 1 ) )
2018-08-28 20:08:47 +00:00
{
2019-01-03 00:58:21 +00:00
m = min ( sizedirmenu , 2 * numaddonsshown + 1 ) ;
2018-08-28 20:08:47 +00:00
i = 0 ;
}
2019-01-03 00:58:21 +00:00
else
i = m - ( 2 * numaddonsshown + 1 ) ;
2018-08-28 20:08:47 +00:00
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 ;
2019-01-28 16:32:07 +00:00
V_DrawSmallScaledPatch ( x , y + 4 , ( ( ! majormods ) ? 0 : V_TRANSLUCENT ) , addonsp [ NUM_EXT + 4 ] ) ;
2018-08-28 20:08:47 +00:00
if ( modifiedgame )
V_DrawSmallScaledPatch ( x , y + 4 , 0 , addonsp [ NUM_EXT + 2 ] ) ;
}
static void M_AddonExec ( INT32 ch )
{
if ( ch ! = ' y ' & & ch ! = KEY_ENTER )
return ;
S_StartSound ( NULL , sfx_zoom ) ;
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
2019-03-31 01:57:53 +00:00
if ( ! preparefilemenu ( true , false ) )
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 ] ] )
2018-11-14 01:27:01 +00:00
S_StartSound ( NULL , sfx_s26d ) ;
2018-08-28 20:08:47 +00:00
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 ;
2019-03-31 01:57:53 +00:00
if ( ! preparefilemenu ( false , false ) )
2018-08-28 20:08:47 +00:00
{
2018-11-14 01:27:01 +00:00
S_StartSound ( NULL , sfx_s224 ) ;
2018-08-28 20:08:47 +00:00
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 ;
2019-03-31 01:57:53 +00:00
if ( ! preparefilemenu ( true , false ) )
2018-08-28 20:08:47 +00:00
{
UNEXIST ;
return ;
}
}
else
{
S_StartSound ( NULL , sfx_menu1 ) ;
dir_on [ menudepthleft ] = 1 ;
}
refresh = false ;
}
else
{
2018-11-14 01:27:01 +00:00
S_StartSound ( NULL , sfx_s26d ) ;
2018-08-28 20:08:47 +00:00
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 ;
2019-03-31 01:57:53 +00:00
if ( ! preparefilemenu ( false , false ) )
2018-08-28 20:08:47 +00:00
{
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
2018-11-14 01:27:01 +00:00
S_StartSound ( NULL , sfx_s26d ) ;
2019-01-05 20:59:23 +00:00
M_StartMessage ( va ( " %c%s \x80 \n This version of SRB2Kart does not \n have support for .lua files. \n \n (Press a key) \n " , ( ' \x80 ' + ( highlightflags > > V_CHARCOLORSHIFT ) ) , dirmenu [ dir_on [ menudepthleft ] ] + DIR_STRING ) , NULL , MM_NOTHING ) ;
2018-08-28 20:08:47 +00:00
break ;
# endif
// else intentional fallthrough
case EXT_SOC :
case EXT_WAD :
2018-12-16 21:07:47 +00:00
# ifdef USE_KART
2018-08-29 13:19:08 +00:00
case EXT_KART :
2018-12-16 21:07:47 +00:00
# endif
2018-11-29 15:07:53 +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 :
2018-11-14 01:27:01 +00:00
S_StartSound ( NULL , sfx_s26d ) ;
2018-08-28 20:08:47 +00:00
}
}
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 ) ;
}
}
2019-03-31 01:57:53 +00:00
// ---- REPLAY HUT -----
2019-03-31 06:22:41 +00:00
menudemo_t * demolist ;
2019-03-31 01:57:53 +00:00
2019-03-31 07:54:09 +00:00
# define DF_ENCORE 0x40
static INT16 replayScrollTitle = 0 ;
2019-04-09 18:34:34 +00:00
static SINT8 replayScrollDelay = TICRATE , replayScrollDir = 1 ;
2019-03-31 01:57:53 +00:00
2019-03-31 06:22:41 +00:00
static void PrepReplayList ( void )
{
size_t i ;
if ( demolist )
Z_Free ( demolist ) ;
demolist = Z_Calloc ( sizeof ( menudemo_t ) * sizedirmenu , PU_STATIC , NULL ) ;
for ( i = 0 ; i < sizedirmenu ; i + + )
{
2019-03-31 21:28:18 +00:00
if ( dirmenu [ i ] [ DIR_TYPE ] = = EXT_UP )
{
demolist [ i ] . type = MD_SUBDIR ;
sprintf ( demolist [ i ] . title , " UP " ) ;
}
else if ( dirmenu [ i ] [ DIR_TYPE ] = = EXT_FOLDER )
2019-03-31 06:22:41 +00:00
{
demolist [ i ] . type = MD_SUBDIR ;
strncpy ( demolist [ i ] . title , dirmenu [ i ] + DIR_STRING , 64 ) ;
}
else
{
demolist [ i ] . type = MD_NOTLOADED ;
snprintf ( demolist [ i ] . filepath , 255 , " %s%s " , menupath , dirmenu [ i ] + DIR_STRING ) ;
sprintf ( demolist [ i ] . title , " ..... " ) ;
}
}
}
2019-04-01 00:26:53 +00:00
void M_ReplayHut ( INT32 choice )
2019-03-31 01:57:53 +00:00
{
( void ) choice ;
2019-04-01 00:26:53 +00:00
if ( ! demo . inreplayhut )
2019-03-31 18:50:20 +00:00
{
snprintf ( menupath , 1024 , " %s " PATHSEP " replay " PATHSEP " online " PATHSEP , srb2home ) ;
menupathindex [ ( menudepthleft = menudepth - 1 ) ] = strlen ( menupath ) ;
}
2019-03-31 01:57:53 +00:00
if ( ! preparefilemenu ( false , true ) )
{
M_StartMessage ( " No replays found. \n \n (Press a key) \n " , NULL , MM_NOTHING ) ;
return ;
}
2019-04-01 00:26:53 +00:00
else if ( ! demo . inreplayhut )
2019-03-31 01:57:53 +00:00
dir_on [ menudepthleft ] = 0 ;
2019-04-01 00:26:53 +00:00
demo . inreplayhut = true ;
2019-03-31 01:57:53 +00:00
2019-04-01 20:07:27 +00:00
replayScrollTitle = 0 ; replayScrollDelay = TICRATE ; replayScrollDir = 1 ;
2019-03-31 06:22:41 +00:00
PrepReplayList ( ) ;
2019-04-01 00:26:53 +00:00
menuactive = true ;
2019-03-31 01:57:53 +00:00
M_SetupNextMenu ( & MISC_ReplayHutDef ) ;
G_SetGamestate ( GS_TIMEATTACK ) ;
2019-04-13 19:22:48 +00:00
demo . rewinding = false ;
2019-03-31 01:57:53 +00:00
S_ChangeMusicInternal ( " replst " , true ) ;
}
2019-03-31 06:22:41 +00:00
static void M_HandleReplayHutList ( INT32 choice )
{
switch ( choice )
{
case KEY_UPARROW :
2019-03-31 21:28:18 +00:00
if ( dir_on [ menudepthleft ] )
dir_on [ menudepthleft ] - - ;
2019-03-31 06:22:41 +00:00
else
M_PrevOpt ( ) ;
S_StartSound ( NULL , sfx_menu1 ) ;
2019-03-31 07:54:09 +00:00
replayScrollTitle = 0 ; replayScrollDelay = TICRATE ; replayScrollDir = 1 ;
2019-03-31 06:22:41 +00:00
break ;
case KEY_DOWNARROW :
2019-03-31 21:28:18 +00:00
if ( dir_on [ menudepthleft ] < sizedirmenu - 1 )
dir_on [ menudepthleft ] + + ;
2019-03-31 06:22:41 +00:00
else
itemOn = 0 ; // Not M_NextOpt because that would take us to the extra dummy item
S_StartSound ( NULL , sfx_menu1 ) ;
2019-03-31 07:54:09 +00:00
replayScrollTitle = 0 ; replayScrollDelay = TICRATE ; replayScrollDir = 1 ;
2019-03-31 06:22:41 +00:00
break ;
2019-03-31 18:50:20 +00:00
case KEY_ESCAPE :
M_QuitReplayHut ( ) ;
break ;
case KEY_ENTER :
2019-03-31 21:28:18 +00:00
switch ( dirmenu [ dir_on [ menudepthleft ] ] [ DIR_TYPE ] )
{
case EXT_FOLDER :
strcpy ( & menupath [ menupathindex [ menudepthleft ] ] , dirmenu [ dir_on [ menudepthleft ] ] + DIR_STRING ) ;
if ( menudepthleft )
{
menupathindex [ - - menudepthleft ] = strlen ( menupath ) ;
menupath [ menupathindex [ menudepthleft ] ] = 0 ;
if ( ! preparefilemenu ( false , true ) )
{
S_StartSound ( NULL , sfx_s224 ) ;
M_StartMessage ( va ( " %c%s \x80 \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 , true ) )
{
M_QuitReplayHut ( ) ;
return ;
}
}
else
{
S_StartSound ( NULL , sfx_menu1 ) ;
dir_on [ menudepthleft ] = 1 ;
PrepReplayList ( ) ;
}
}
else
{
S_StartSound ( NULL , sfx_s26d ) ;
M_StartMessage ( va ( " %c%s \x80 \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 , true ) )
{
M_QuitReplayHut ( ) ;
return ;
}
PrepReplayList ( ) ;
break ;
default :
2019-03-31 22:29:41 +00:00
// We can't just use M_SetupNextMenu because that'll run ReplayDef's quitroutine and boot us back to the title screen!
2019-03-31 21:28:18 +00:00
currentMenu - > lastOn = itemOn ;
2019-03-31 22:29:41 +00:00
currentMenu = & MISC_ReplayStartDef ;
2019-03-31 21:28:18 +00:00
2019-04-01 20:07:27 +00:00
replayScrollTitle = 0 ; replayScrollDelay = TICRATE ; replayScrollDir = 1 ;
2019-03-31 22:29:41 +00:00
switch ( demolist [ dir_on [ menudepthleft ] ] . addonstatus )
{
case DFILE_ERROR_CANNOTLOAD :
// Only show "Watch Replay Without Addons"
MISC_ReplayStartMenu [ 0 ] . status = IT_DISABLED ;
MISC_ReplayStartMenu [ 1 ] . status = IT_CALL | IT_STRING ;
//MISC_ReplayStartMenu[1].alphaKey = 0;
MISC_ReplayStartMenu [ 2 ] . status = IT_DISABLED ;
itemOn = 1 ;
break ;
case DFILE_ERROR_NOTLOADED :
case DFILE_ERROR_INCOMPLETEOUTOFORDER :
// Show "Load Addons and Watch Replay" and "Watch Replay Without Addons"
MISC_ReplayStartMenu [ 0 ] . status = IT_CALL | IT_STRING ;
MISC_ReplayStartMenu [ 1 ] . status = IT_CALL | IT_STRING ;
//MISC_ReplayStartMenu[1].alphaKey = 10;
MISC_ReplayStartMenu [ 2 ] . status = IT_DISABLED ;
itemOn = 0 ;
break ;
case DFILE_ERROR_EXTRAFILES :
case DFILE_ERROR_OUTOFORDER :
default :
// Show "Watch Replay"
MISC_ReplayStartMenu [ 0 ] . status = IT_DISABLED ;
MISC_ReplayStartMenu [ 1 ] . status = IT_DISABLED ;
MISC_ReplayStartMenu [ 2 ] . status = IT_CALL | IT_STRING ;
//MISC_ReplayStartMenu[2].alphaKey = 0;
itemOn = 2 ;
break ;
}
}
break ;
}
}
2019-04-06 16:16:19 +00:00
# define SCALEDVIEWWIDTH (vid.width / vid.dupx)
# define SCALEDVIEWHEIGHT (vid.height / vid.dupy)
2019-03-31 22:29:41 +00:00
static void DrawReplayHutReplayInfo ( void )
{
lumpnum_t lumpnum ;
2019-04-02 04:34:53 +00:00
patch_t * patch ;
UINT8 * colormap ;
2019-03-31 22:29:41 +00:00
INT32 x , y , w , h ;
switch ( demolist [ dir_on [ menudepthleft ] ] . type )
{
case MD_NOTLOADED :
2019-04-06 16:16:19 +00:00
V_DrawCenteredString ( 160 , 40 , V_SNAPTOTOP , " Loading replay information... " ) ;
2019-03-31 22:29:41 +00:00
break ;
case MD_INVALID :
2019-04-06 16:16:19 +00:00
V_DrawCenteredString ( 160 , 40 , V_SNAPTOTOP | warningflags , " This replay cannot be played. " ) ;
2019-03-31 22:29:41 +00:00
break ;
case MD_SUBDIR :
break ; // Can't think of anything to draw here right now
case MD_OUTDATED :
2019-04-06 16:16:19 +00:00
V_DrawThinString ( 17 , 64 , V_SNAPTOTOP | V_ALLOWLOWERCASE | V_TRANSLUCENT | highlightflags , " Recorded on an outdated version. " ) ;
2019-03-31 22:29:41 +00:00
/*fallthru*/
default :
// Draw level stuff
x = 15 ; y = 15 ;
// A 160x100 image of the level as entry MAPxxP
//CONS_Printf("%d %s\n", demolist[dir_on[menudepthleft]].map, G_BuildMapName(demolist[dir_on[menudepthleft]].map));
lumpnum = W_CheckNumForName ( va ( " %sP " , G_BuildMapName ( demolist [ dir_on [ menudepthleft ] ] . map ) ) ) ;
if ( lumpnum ! = LUMPERROR )
2019-04-02 04:34:53 +00:00
patch = W_CachePatchNum ( lumpnum , PU_CACHE ) ;
2019-03-31 22:29:41 +00:00
else
2019-04-06 07:17:30 +00:00
patch = W_CachePatchName ( " M_NOLVL " , PU_CACHE ) ;
2019-03-31 22:29:41 +00:00
if ( ! ( demolist [ dir_on [ menudepthleft ] ] . kartspeed & DF_ENCORE ) )
2019-04-06 16:16:19 +00:00
V_DrawSmallScaledPatch ( x , y , V_SNAPTOTOP , patch ) ;
2019-03-31 22:29:41 +00:00
else
{
2019-04-02 04:34:53 +00:00
w = SHORT ( patch - > width ) ;
h = SHORT ( patch - > height ) ;
2019-04-06 16:16:19 +00:00
V_DrawSmallScaledPatch ( x + ( w > > 1 ) , y , V_SNAPTOTOP | V_FLIP , patch ) ;
2019-03-31 22:29:41 +00:00
{
static angle_t rubyfloattime = 0 ;
const fixed_t rubyheight = FINESINE ( rubyfloattime > > ANGLETOFINESHIFT ) ;
2019-04-06 16:16:19 +00:00
V_DrawFixedPatch ( ( x + ( w > > 2 ) ) < < FRACBITS , ( ( y + ( h > > 2 ) ) < < FRACBITS ) - ( rubyheight < < 1 ) , FRACUNIT , V_SNAPTOTOP , W_CachePatchName ( " RUBYICON " , PU_CACHE ) , NULL ) ;
2019-03-31 22:29:41 +00:00
rubyfloattime + = ( ANGLE_MAX / NEWTICRATE ) ;
}
}
x + = 85 ;
if ( mapheaderinfo [ demolist [ dir_on [ menudepthleft ] ] . map - 1 ] )
2019-04-06 16:16:19 +00:00
V_DrawString ( x , y , V_SNAPTOTOP , G_BuildMapTitle ( demolist [ dir_on [ menudepthleft ] ] . map ) ) ;
2019-03-31 22:29:41 +00:00
else
2019-04-06 16:16:19 +00:00
V_DrawString ( x , y , V_SNAPTOTOP | V_ALLOWLOWERCASE | V_TRANSLUCENT , " Level is not loaded. " ) ;
2019-03-31 22:29:41 +00:00
2019-04-01 17:56:23 +00:00
if ( demolist [ dir_on [ menudepthleft ] ] . numlaps )
2019-04-06 16:16:19 +00:00
V_DrawThinString ( x , y + 9 , V_SNAPTOTOP | V_ALLOWLOWERCASE , va ( " (%d laps) " , demolist [ dir_on [ menudepthleft ] ] . numlaps ) ) ;
2019-04-01 17:56:23 +00:00
2019-04-06 16:16:19 +00:00
V_DrawString ( x , y + 20 , V_SNAPTOTOP | V_ALLOWLOWERCASE , demolist [ dir_on [ menudepthleft ] ] . gametype = = GT_RACE ?
2019-03-31 22:29:41 +00:00
va ( " Race (%s speed) " , kartspeed_cons_t [ demolist [ dir_on [ menudepthleft ] ] . kartspeed & ~ DF_ENCORE ] . strvalue ) :
" Battle Mode " ) ;
2019-04-02 01:30:24 +00:00
if ( ! demolist [ dir_on [ menudepthleft ] ] . standings [ 0 ] . ranking )
{
// No standings were loaded!
2019-04-06 16:16:19 +00:00
V_DrawString ( x , y + 39 , V_SNAPTOTOP | V_ALLOWLOWERCASE | V_TRANSLUCENT , " No standings available. " ) ;
2019-04-02 01:30:24 +00:00
break ;
}
2019-04-06 16:16:19 +00:00
V_DrawThinString ( x , y + 29 , V_SNAPTOTOP | highlightflags , " WINNER " ) ;
V_DrawString ( x + 38 , y + 30 , V_SNAPTOTOP | V_ALLOWLOWERCASE , demolist [ dir_on [ menudepthleft ] ] . standings [ 0 ] . name ) ;
2019-03-31 22:29:41 +00:00
2019-04-01 20:07:27 +00:00
if ( demolist [ dir_on [ menudepthleft ] ] . gametype = = GT_RACE )
{
2019-04-06 16:16:19 +00:00
V_DrawThinString ( x , y + 39 , V_SNAPTOTOP | highlightflags , " TIME " ) ;
V_DrawRightAlignedString ( x + 84 , y + 40 , V_SNAPTOTOP , va ( " %d'%02d \" %02d " ,
2019-04-01 20:07:27 +00:00
G_TicsToMinutes ( demolist [ dir_on [ menudepthleft ] ] . standings [ 0 ] . timeorscore , true ) ,
G_TicsToSeconds ( demolist [ dir_on [ menudepthleft ] ] . standings [ 0 ] . timeorscore ) ,
G_TicsToCentiseconds ( demolist [ dir_on [ menudepthleft ] ] . standings [ 0 ] . timeorscore )
) ) ;
}
else
{
2019-04-06 16:16:19 +00:00
V_DrawThinString ( x , y + 39 , V_SNAPTOTOP | highlightflags , " SCORE " ) ;
V_DrawString ( x + 32 , y + 40 , V_SNAPTOTOP , va ( " %d " , demolist [ dir_on [ menudepthleft ] ] . standings [ 0 ] . timeorscore ) ) ;
2019-04-01 20:07:27 +00:00
}
2019-03-31 22:29:41 +00:00
// Character face!
2019-04-01 20:07:27 +00:00
if ( W_CheckNumForName ( skins [ demolist [ dir_on [ menudepthleft ] ] . standings [ 0 ] . skin ] . facewant ) ! = LUMPERROR )
2019-03-31 22:29:41 +00:00
{
2019-04-02 04:34:53 +00:00
patch = facewantprefix [ demolist [ dir_on [ menudepthleft ] ] . standings [ 0 ] . skin ] ;
colormap = R_GetTranslationColormap (
2019-04-01 20:07:27 +00:00
demolist [ dir_on [ menudepthleft ] ] . standings [ 0 ] . skin ,
demolist [ dir_on [ menudepthleft ] ] . standings [ 0 ] . color ,
2019-03-31 22:29:41 +00:00
GTC_MENUCACHE ) ;
2019-03-31 21:28:18 +00:00
}
2019-04-02 04:34:53 +00:00
else
{
2019-04-06 07:17:30 +00:00
patch = W_CachePatchName ( " M_NOWANT " , PU_CACHE ) ;
2019-04-02 04:34:53 +00:00
colormap = R_GetTranslationColormap (
TC_RAINBOW ,
demolist [ dir_on [ menudepthleft ] ] . standings [ 0 ] . color ,
GTC_MENUCACHE ) ;
}
2019-04-06 16:16:19 +00:00
V_DrawMappedPatch ( BASEVIDWIDTH - 15 - SHORT ( patch - > width ) , y + 20 , V_SNAPTOTOP , patch , colormap ) ;
2019-03-31 18:50:20 +00:00
break ;
2019-03-31 06:22:41 +00:00
}
}
2019-03-31 01:57:53 +00:00
static void M_DrawReplayHut ( void )
{
INT32 x , y , cursory = 0 ;
INT16 i ;
2019-03-31 06:22:41 +00:00
INT16 replaylistitem = currentMenu - > numitems - 2 ;
boolean processed_one_this_frame = false ;
2019-03-31 01:57:53 +00:00
2019-03-31 06:22:41 +00:00
static UINT16 replayhutmenuy = 0 ;
2019-03-31 01:57:53 +00:00
V_DrawPatchFill ( W_CachePatchName ( " SRB2BACK " , PU_CACHE ) ) ;
2019-04-10 14:10:09 +00:00
if ( cv_vhseffect . value )
V_DrawVhsEffect ( false ) ;
2019-03-31 01:57:53 +00:00
// Draw menu choices
x = currentMenu - > x ;
y = currentMenu - > y ;
2019-03-31 06:22:41 +00:00
if ( itemOn > replaylistitem )
{
itemOn = replaylistitem ;
2019-03-31 21:28:18 +00:00
dir_on [ menudepthleft ] = sizedirmenu - 1 ;
2019-03-31 07:54:09 +00:00
replayScrollTitle = 0 ; replayScrollDelay = TICRATE ; replayScrollDir = 1 ;
2019-03-31 06:22:41 +00:00
}
else if ( itemOn < replaylistitem )
{
2019-03-31 21:28:18 +00:00
dir_on [ menudepthleft ] = 0 ;
2019-03-31 07:54:09 +00:00
replayScrollTitle = 0 ; replayScrollDelay = TICRATE ; replayScrollDir = 1 ;
2019-03-31 06:22:41 +00:00
}
if ( itemOn = = replaylistitem )
2019-03-31 01:57:53 +00:00
{
INT32 maxy ;
// Scroll menu items if needed
2019-03-31 21:28:18 +00:00
cursory = y + currentMenu - > menuitems [ replaylistitem ] . alphaKey + dir_on [ menudepthleft ] * 10 ;
2019-03-31 06:22:41 +00:00
maxy = y + currentMenu - > menuitems [ replaylistitem ] . alphaKey + sizedirmenu * 10 ;
2019-03-31 01:57:53 +00:00
2019-03-31 06:22:41 +00:00
if ( cursory > maxy - 20 )
cursory = maxy - 20 ;
2019-03-31 01:57:53 +00:00
2019-04-06 16:16:19 +00:00
if ( cursory - replayhutmenuy > SCALEDVIEWHEIGHT - 50 )
replayhutmenuy + = ( cursory - SCALEDVIEWHEIGHT - replayhutmenuy + 51 ) / 2 ;
2019-03-31 06:22:41 +00:00
else if ( cursory - replayhutmenuy < 110 )
2019-03-31 07:54:09 +00:00
replayhutmenuy + = ( max ( 0 , cursory - 110 ) - replayhutmenuy - 1 ) / 2 ;
2019-03-31 01:57:53 +00:00
}
2019-03-31 06:22:41 +00:00
else
replayhutmenuy / = 2 ;
y - = replayhutmenuy ;
2019-03-31 01:57:53 +00:00
// Draw static menu items
2019-03-31 06:22:41 +00:00
for ( i = 0 ; i < replaylistitem ; i + + )
2019-03-31 01:57:53 +00:00
{
2019-04-01 00:29:05 +00:00
INT32 localy = y + currentMenu - > menuitems [ i ] . alphaKey ;
if ( localy < 65 )
continue ;
2019-03-31 01:57:53 +00:00
if ( i = = itemOn )
2019-04-01 00:29:05 +00:00
cursory = localy ;
2019-03-31 01:57:53 +00:00
if ( ( currentMenu - > menuitems [ i ] . status & IT_DISPLAY ) = = IT_STRING )
2019-04-06 16:16:19 +00:00
V_DrawString ( x , localy , V_SNAPTOTOP | V_SNAPTOLEFT , currentMenu - > menuitems [ i ] . text ) ;
2019-03-31 01:57:53 +00:00
else
2019-04-06 16:16:19 +00:00
V_DrawString ( x , localy , V_SNAPTOTOP | V_SNAPTOLEFT | highlightflags , currentMenu - > menuitems [ i ] . text ) ;
2019-03-31 01:57:53 +00:00
}
2019-04-15 04:17:12 +00:00
y + = currentMenu - > menuitems [ replaylistitem ] . alphaKey ;
2019-03-31 01:57:53 +00:00
for ( i = 0 ; i < ( INT16 ) sizedirmenu ; i + + )
{
2019-03-31 06:22:41 +00:00
INT32 localy = y + i * 10 ;
2019-04-01 17:25:12 +00:00
INT32 localx = x ;
2019-03-31 07:54:09 +00:00
if ( localy < 65 )
continue ;
2019-04-06 16:16:19 +00:00
if ( localy > = SCALEDVIEWHEIGHT )
2019-03-31 07:54:09 +00:00
break ;
if ( demolist [ i ] . type = = MD_NOTLOADED & & ! processed_one_this_frame )
2019-03-31 06:22:41 +00:00
{
processed_one_this_frame = true ;
G_LoadDemoInfo ( & demolist [ i ] ) ;
}
2019-04-01 17:25:12 +00:00
if ( demolist [ i ] . type = = MD_SUBDIR )
{
localx + = 8 ;
2019-04-06 16:16:19 +00:00
V_DrawScaledPatch ( x - 4 , localy , V_SNAPTOTOP | V_SNAPTOLEFT , W_CachePatchName ( dirmenu [ i ] [ DIR_TYPE ] = = EXT_UP ? " M_RBACK " : " M_RFLDR " , PU_CACHE ) ) ;
2019-04-01 17:25:12 +00:00
}
2019-03-31 21:28:18 +00:00
if ( itemOn = = replaylistitem & & i = = ( INT16 ) dir_on [ menudepthleft ] )
2019-03-31 06:22:41 +00:00
{
cursory = localy ;
2019-03-31 07:54:09 +00:00
if ( replayScrollDelay )
replayScrollDelay - - ;
else if ( replayScrollDir > 0 )
{
2019-04-06 16:16:19 +00:00
if ( replayScrollTitle < ( V_StringWidth ( demolist [ i ] . title , 0 ) - ( SCALEDVIEWWIDTH - ( x < < 1 ) ) ) < < 1 )
2019-03-31 07:54:09 +00:00
replayScrollTitle + + ;
else
{
replayScrollDelay = TICRATE ;
replayScrollDir = - 1 ;
}
}
else
{
if ( replayScrollTitle > 0 )
replayScrollTitle - - ;
else
{
replayScrollDelay = TICRATE ;
replayScrollDir = 1 ;
}
}
2019-04-06 16:16:19 +00:00
V_DrawString ( localx - ( replayScrollTitle > > 1 ) , localy , V_SNAPTOTOP | V_SNAPTOLEFT | highlightflags | V_ALLOWLOWERCASE , demolist [ i ] . title ) ;
2019-03-31 06:22:41 +00:00
}
else
2019-04-06 16:16:19 +00:00
V_DrawString ( localx , localy , V_SNAPTOTOP | V_SNAPTOLEFT | V_ALLOWLOWERCASE , demolist [ i ] . title ) ;
2019-03-31 01:57:53 +00:00
}
2019-04-15 04:17:12 +00:00
// Draw scrollbar
y = sizedirmenu * 10 + currentMenu - > menuitems [ replaylistitem ] . alphaKey + 30 ;
if ( y > SCALEDVIEWHEIGHT - 80 )
{
V_DrawFill ( BASEVIDWIDTH - 4 , 75 , 4 , SCALEDVIEWHEIGHT - 80 , V_SNAPTOTOP | V_SNAPTORIGHT | 239 ) ;
V_DrawFill ( BASEVIDWIDTH - 3 , 76 + ( SCALEDVIEWHEIGHT - 80 ) * replayhutmenuy / y , 2 , ( ( ( SCALEDVIEWHEIGHT - 80 ) * ( SCALEDVIEWHEIGHT - 80 ) ) - 1 ) / y - 1 , V_SNAPTOTOP | V_SNAPTORIGHT | 229 ) ;
}
2019-03-31 01:57:53 +00:00
// Draw the cursor
2019-04-06 16:16:19 +00:00
V_DrawScaledPatch ( currentMenu - > x - 24 , cursory , V_SNAPTOTOP | V_SNAPTOLEFT ,
2019-03-31 01:57:53 +00:00
W_CachePatchName ( " M_CURSOR " , PU_CACHE ) ) ;
2019-04-06 16:16:19 +00:00
V_DrawString ( currentMenu - > x , cursory , V_SNAPTOTOP | V_SNAPTOLEFT | highlightflags , currentMenu - > menuitems [ itemOn ] . text ) ;
2019-03-31 07:54:09 +00:00
// Now draw some replay info!
2019-04-06 16:16:19 +00:00
V_DrawFill ( 10 , 10 , 300 , 60 , V_SNAPTOTOP | 239 ) ;
2019-03-31 07:54:09 +00:00
if ( itemOn = = replaylistitem )
{
2019-03-31 22:29:41 +00:00
DrawReplayHutReplayInfo ( ) ;
}
}
2019-03-31 07:54:09 +00:00
2019-03-31 22:29:41 +00:00
static void M_DrawReplayStartMenu ( void )
{
const char * warning ;
2019-04-01 20:07:27 +00:00
UINT8 i ;
2019-03-31 07:54:09 +00:00
2019-03-31 22:29:41 +00:00
M_DrawGenericBackgroundMenu ( ) ;
2019-04-01 20:07:27 +00:00
# define STARTY 62-(replayScrollTitle>>1)
// Draw rankings beyond first
for ( i = 1 ; i < MAXPLAYERS & & demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . ranking ; i + + )
{
2019-04-02 04:34:53 +00:00
patch_t * patch ;
UINT8 * colormap ;
2019-04-06 16:16:19 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - 100 , STARTY + i * 20 , V_SNAPTOTOP | highlightflags , va ( " %2d " , demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . ranking ) ) ;
V_DrawThinString ( BASEVIDWIDTH - 96 , STARTY + i * 20 , V_SNAPTOTOP | V_ALLOWLOWERCASE , demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . name ) ;
2019-04-01 20:07:27 +00:00
if ( demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . timeorscore = = UINT32_MAX - 1 )
2019-04-06 16:16:19 +00:00
V_DrawThinString ( BASEVIDWIDTH - 92 , STARTY + i * 20 + 9 , V_SNAPTOTOP , " NO CONTEST " ) ;
2019-04-01 20:07:27 +00:00
else if ( demolist [ dir_on [ menudepthleft ] ] . gametype = = GT_RACE )
2019-04-06 16:16:19 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - 40 , STARTY + i * 20 + 9 , V_SNAPTOTOP , va ( " %d'%02d \" %02d " ,
2019-04-01 20:07:27 +00:00
G_TicsToMinutes ( demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . timeorscore , true ) ,
G_TicsToSeconds ( demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . timeorscore ) ,
G_TicsToCentiseconds ( demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . timeorscore )
) ) ;
else
2019-04-06 16:16:19 +00:00
V_DrawString ( BASEVIDWIDTH - 92 , STARTY + i * 20 + 9 , V_SNAPTOTOP , va ( " %d " , demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . timeorscore ) ) ;
2019-04-02 04:34:53 +00:00
2019-04-01 20:07:27 +00:00
// Character face!
if ( W_CheckNumForName ( skins [ demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . skin ] . facerank ) ! = LUMPERROR )
{
2019-04-02 04:34:53 +00:00
patch = facerankprefix [ demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . skin ] ;
colormap = R_GetTranslationColormap (
2019-04-01 20:07:27 +00:00
demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . skin ,
demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . color ,
GTC_MENUCACHE ) ;
}
2019-04-02 04:34:53 +00:00
else
{
2019-04-06 07:17:30 +00:00
patch = W_CachePatchName ( " M_NORANK " , PU_CACHE ) ;
2019-04-02 04:34:53 +00:00
colormap = R_GetTranslationColormap (
TC_RAINBOW ,
demolist [ dir_on [ menudepthleft ] ] . standings [ i ] . color ,
GTC_MENUCACHE ) ;
}
2019-04-06 16:16:19 +00:00
V_DrawMappedPatch ( BASEVIDWIDTH - 5 - SHORT ( patch - > width ) , STARTY + i * 20 , V_SNAPTOTOP , patch , colormap ) ;
2019-04-01 20:07:27 +00:00
}
# undef STARTY
// Handle scrolling rankings
if ( replayScrollDelay )
replayScrollDelay - - ;
else if ( replayScrollDir > 0 )
{
2019-04-06 16:16:19 +00:00
if ( replayScrollTitle < ( i * 20 - SCALEDVIEWHEIGHT + 100 ) < < 1 )
2019-04-01 20:07:27 +00:00
replayScrollTitle + + ;
else
{
replayScrollDelay = TICRATE ;
replayScrollDir = - 1 ;
}
}
else
{
if ( replayScrollTitle > 0 )
replayScrollTitle - - ;
else
{
replayScrollDelay = TICRATE ;
replayScrollDir = 1 ;
}
}
2019-04-06 16:16:19 +00:00
V_DrawFill ( 10 , 10 , 300 , 60 , V_SNAPTOTOP | 239 ) ;
2019-03-31 22:29:41 +00:00
DrawReplayHutReplayInfo ( ) ;
2019-03-31 07:54:09 +00:00
2019-04-06 16:16:19 +00:00
V_DrawString ( 10 , 72 , V_SNAPTOTOP | highlightflags | V_ALLOWLOWERCASE , demolist [ dir_on [ menudepthleft ] ] . title ) ;
2019-03-31 07:54:09 +00:00
2019-03-31 22:29:41 +00:00
// Draw a warning prompt if needed
switch ( demolist [ dir_on [ menudepthleft ] ] . addonstatus )
{
case DFILE_ERROR_CANNOTLOAD :
warning = " Some addons in this replay cannot be loaded. \n You can watch anyway, but desyncs may occur. " ;
break ;
2019-03-31 07:54:09 +00:00
2019-03-31 22:29:41 +00:00
case DFILE_ERROR_NOTLOADED :
case DFILE_ERROR_INCOMPLETEOUTOFORDER :
warning = " Loading addons will mark your game as modified, and record attack may be unavailable. \n You can watch without loading addons, but desyncs may occur. " ;
break ;
2019-03-31 07:54:09 +00:00
2019-03-31 22:29:41 +00:00
case DFILE_ERROR_EXTRAFILES :
warning = " You have addons loaded that were not present in this replay. \n You can watch anyway, but desyncs may occur. " ;
break ;
2019-03-31 07:54:09 +00:00
2019-03-31 22:29:41 +00:00
case DFILE_ERROR_OUTOFORDER :
warning = " You have this replay's addons loaded, but they are out of order. \n You can watch anyway, but desyncs may occur. " ;
break ;
2019-03-31 07:54:09 +00:00
2019-03-31 22:29:41 +00:00
default :
return ;
2019-03-31 07:54:09 +00:00
}
2019-03-31 22:29:41 +00:00
2019-04-06 16:16:19 +00:00
V_DrawSmallString ( 4 , BASEVIDHEIGHT - 14 , V_SNAPTOBOTTOM | V_SNAPTOLEFT | V_ALLOWLOWERCASE , warning ) ;
2019-03-31 01:57:53 +00:00
}
2019-03-31 18:50:20 +00:00
static boolean M_QuitReplayHut ( void )
{
// D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate.
menuactive = false ;
D_StartTitle ( ) ;
if ( demolist )
Z_Free ( demolist ) ;
demolist = NULL ;
2019-04-01 00:26:53 +00:00
demo . inreplayhut = false ;
2019-03-31 18:50:20 +00:00
return true ;
}
2019-03-31 22:29:41 +00:00
static void M_HutStartReplay ( INT32 choice )
{
( void ) choice ;
M_ClearMenus ( false ) ;
demo . loadfiles = ( itemOn = = 0 ) ;
demo . ignorefiles = ( itemOn ! = 0 ) ;
G_DoPlayDemo ( demolist [ dir_on [ menudepthleft ] ] . filepath ) ;
}
2019-04-06 23:59:11 +00:00
void M_SetPlaybackMenuPointer ( void )
{
itemOn = playback_pause ;
}
2019-04-05 07:38:48 +00:00
static void M_DrawPlaybackMenu ( void )
{
INT16 i ;
patch_t * icon ;
UINT8 * activemap = R_GetTranslationColormap ( TC_RAINBOW , SKINCOLOR_GOLD , GTC_MENUCACHE ) ;
// Toggle items
2019-04-06 19:51:00 +00:00
if ( paused & & ! demo . rewinding )
2019-04-05 07:38:48 +00:00
{
2019-04-13 19:42:15 +00:00
PlaybackMenu [ playback_pause ] . status = PlaybackMenu [ playback_fastforward ] . status = PlaybackMenu [ playback_rewind ] . status = IT_DISABLED ;
PlaybackMenu [ playback_resume ] . status = PlaybackMenu [ playback_advanceframe ] . status = PlaybackMenu [ playback_backframe ] . status = IT_CALL | IT_STRING ;
if ( itemOn > = playback_rewind & & itemOn < = playback_fastforward )
itemOn + = playback_backframe - playback_rewind ;
2019-04-05 07:38:48 +00:00
}
else
{
2019-04-13 19:42:15 +00:00
PlaybackMenu [ playback_pause ] . status = PlaybackMenu [ playback_fastforward ] . status = PlaybackMenu [ playback_rewind ] . status = IT_CALL | IT_STRING ;
PlaybackMenu [ playback_resume ] . status = PlaybackMenu [ playback_advanceframe ] . status = PlaybackMenu [ playback_backframe ] . status = IT_DISABLED ;
if ( itemOn > = playback_backframe & & itemOn < = playback_advanceframe )
itemOn - = playback_backframe - playback_rewind ;
2019-04-05 07:38:48 +00:00
}
2019-04-06 23:59:11 +00:00
if ( modeattacking )
{
for ( i = playback_viewcount ; i < = playback_view4 ; i + + )
PlaybackMenu [ i ] . status = IT_DISABLED ;
2019-04-13 20:23:31 +00:00
//PlaybackMenu[playback_moreoptions].alphaKey = 72;
//PlaybackMenu[playback_quit].alphaKey = 88;
PlaybackMenu [ playback_quit ] . alphaKey = 72 ;
2019-04-06 23:59:11 +00:00
2019-04-13 20:23:31 +00:00
//currentMenu->x = BASEVIDWIDTH/2 - 52;
currentMenu - > x = BASEVIDWIDTH / 2 - 44 ;
2019-04-06 23:59:11 +00:00
}
else
{
2019-05-02 16:42:29 +00:00
PlaybackMenu [ playback_viewcount ] . status = IT_ARROWS | IT_STRING ;
2019-04-06 23:59:11 +00:00
for ( i = 0 ; i < = splitscreen ; i + + )
PlaybackMenu [ playback_view1 + i ] . status = IT_ARROWS | IT_STRING ;
for ( i = splitscreen + 1 ; i < 4 ; i + + )
PlaybackMenu [ playback_view1 + i ] . status = IT_DISABLED ;
2019-04-13 20:23:31 +00:00
//PlaybackMenu[playback_moreoptions].alphaKey = 156;
//PlaybackMenu[playback_quit].alphaKey = 172;
PlaybackMenu [ playback_quit ] . alphaKey = 156 ;
2019-04-06 23:59:11 +00:00
2019-04-13 20:23:31 +00:00
//currentMenu->x = BASEVIDWIDTH/2 - 94;
currentMenu - > x = BASEVIDWIDTH / 2 - 88 ;
2019-04-06 23:59:11 +00:00
}
2019-04-05 07:38:48 +00:00
// wip
//M_DrawTextBox(currentMenu->x-68, currentMenu->y-7, 15, 15);
//M_DrawCenteredMenu();
for ( i = 0 ; i < currentMenu - > numitems ; i + + )
{
UINT8 * inactivemap = NULL ;
if ( i > = playback_view1 & & i < = playback_view4 )
{
2019-04-06 23:59:11 +00:00
if ( modeattacking ) continue ;
2019-04-05 07:38:48 +00:00
if ( splitscreen > = i - playback_view1 )
{
2019-05-02 04:49:05 +00:00
INT32 ply = displayplayers [ i - playback_view1 ] ;
2019-04-05 07:38:48 +00:00
icon = facerankprefix [ players [ ply ] . skin ] ;
if ( i ! = itemOn )
inactivemap = R_GetTranslationColormap ( players [ ply ] . skin , players [ ply ] . skincolor , GTC_MENUCACHE ) ;
}
2019-04-06 07:17:30 +00:00
else if ( currentMenu - > menuitems [ i ] . patch & & W_CheckNumForName ( currentMenu - > menuitems [ i ] . patch ) ! = LUMPERROR )
2019-04-05 07:38:48 +00:00
icon = W_CachePatchName ( currentMenu - > menuitems [ i ] . patch , PU_CACHE ) ;
else
icon = W_CachePatchName ( " PLAYRANK " , PU_CACHE ) ; // temp
}
else if ( currentMenu - > menuitems [ i ] . status = = IT_DISABLED )
continue ;
2019-04-06 07:17:30 +00:00
else if ( currentMenu - > menuitems [ i ] . patch & & W_CheckNumForName ( currentMenu - > menuitems [ i ] . patch ) ! = LUMPERROR )
2019-04-05 07:38:48 +00:00
icon = W_CachePatchName ( currentMenu - > menuitems [ i ] . patch , PU_CACHE ) ;
else
icon = W_CachePatchName ( " PLAYRANK " , PU_CACHE ) ; // temp
2019-04-06 23:06:02 +00:00
if ( ( i = = playback_fastforward & & cv_playbackspeed . value > 1 ) | | ( i = = playback_rewind & & demo . rewinding ) )
2019-04-15 04:22:24 +00:00
V_DrawMappedPatch ( currentMenu - > x + currentMenu - > menuitems [ i ] . alphaKey , currentMenu - > y , V_SNAPTOTOP , icon , R_GetTranslationColormap ( TC_RAINBOW , SKINCOLOR_JAWZ , GTC_MENUCACHE ) ) ;
2019-04-05 07:38:48 +00:00
else
2019-04-15 04:22:24 +00:00
V_DrawMappedPatch ( currentMenu - > x + currentMenu - > menuitems [ i ] . alphaKey , currentMenu - > y , V_SNAPTOTOP , icon , ( i = = itemOn ) ? activemap : inactivemap ) ;
2019-04-05 07:38:48 +00:00
if ( i = = itemOn )
2019-04-13 19:42:15 +00:00
{
2019-04-13 20:23:23 +00:00
V_DrawCharacter ( currentMenu - > x + currentMenu - > menuitems [ i ] . alphaKey + 4 , currentMenu - > y + 14 ,
2019-04-15 04:22:24 +00:00
' \x1A ' | V_SNAPTOTOP | highlightflags , false ) ;
2019-04-13 20:23:23 +00:00
2019-04-15 04:22:24 +00:00
V_DrawCenteredString ( BASEVIDWIDTH / 2 , currentMenu - > y + 18 , V_SNAPTOTOP | V_ALLOWLOWERCASE , currentMenu - > menuitems [ i ] . text ) ;
2019-04-13 19:42:15 +00:00
if ( ( currentMenu - > menuitems [ i ] . status & IT_TYPE ) = = IT_ARROWS )
{
char * str ;
if ( ! ( i = = playback_viewcount & & splitscreen = = 3 ) )
V_DrawCharacter ( BASEVIDWIDTH / 2 - 4 , currentMenu - > y + 28 - ( skullAnimCounter / 5 ) ,
2019-04-15 04:22:24 +00:00
' \x1A ' | V_SNAPTOTOP | highlightflags , false ) ; // up arrow
2019-04-13 19:42:15 +00:00
if ( ! ( i = = playback_viewcount & & splitscreen = = 0 ) )
V_DrawCharacter ( BASEVIDWIDTH / 2 - 4 , currentMenu - > y + 48 + ( skullAnimCounter / 5 ) ,
2019-04-15 04:22:24 +00:00
' \x1B ' | V_SNAPTOTOP | highlightflags , false ) ; // down arrow
2019-04-13 19:42:15 +00:00
switch ( i )
{
case playback_viewcount :
str = va ( " %d " , splitscreen + 1 ) ;
break ;
case playback_view1 :
case playback_view2 :
case playback_view3 :
case playback_view4 :
2019-04-18 07:08:11 +00:00
str = player_names [ displayplayers [ i - playback_view1 ] ] ; // 0 to 3
2019-04-13 19:42:15 +00:00
break ;
default : // shouldn't ever be reached but whatever
continue ;
}
2019-04-15 04:22:24 +00:00
V_DrawCenteredString ( BASEVIDWIDTH / 2 , currentMenu - > y + 38 , V_SNAPTOTOP | V_ALLOWLOWERCASE | highlightflags , str ) ;
2019-04-13 19:42:15 +00:00
}
}
2019-04-05 07:38:48 +00:00
}
}
2019-04-06 19:51:00 +00:00
static void M_PlaybackRewind ( INT32 choice )
{
2019-04-06 23:06:02 +00:00
static tic_t lastconfirmtime ;
2019-04-06 19:51:00 +00:00
( void ) choice ;
if ( ! demo . rewinding )
2019-04-06 20:36:53 +00:00
{
if ( paused )
{
G_ConfirmRewind ( leveltime - 1 ) ;
paused = true ;
S_PauseAudio ( ) ;
}
else
demo . rewinding = paused = true ;
}
2019-04-06 23:06:02 +00:00
else if ( lastconfirmtime + TICRATE / 2 < I_GetTime ( ) )
{
lastconfirmtime = I_GetTime ( ) ;
2019-04-06 19:51:00 +00:00
G_ConfirmRewind ( leveltime ) ;
2019-04-06 23:06:02 +00:00
}
2019-04-06 19:51:00 +00:00
2019-04-06 23:06:02 +00:00
CV_SetValue ( & cv_playbackspeed , 1 ) ;
2019-04-06 19:51:00 +00:00
}
2019-04-05 07:38:48 +00:00
static void M_PlaybackPause ( INT32 choice )
{
( void ) choice ;
paused = ! paused ;
2019-04-06 19:51:00 +00:00
if ( demo . rewinding )
{
G_ConfirmRewind ( leveltime ) ;
paused = true ;
S_PauseAudio ( ) ;
}
else if ( paused )
2019-04-05 07:38:48 +00:00
S_PauseAudio ( ) ;
else
S_ResumeAudio ( ) ;
CV_SetValue ( & cv_playbackspeed , 1 ) ;
}
static void M_PlaybackFastForward ( INT32 choice )
{
( void ) choice ;
2019-04-06 19:51:00 +00:00
if ( demo . rewinding )
{
G_ConfirmRewind ( leveltime ) ;
paused = false ;
S_ResumeAudio ( ) ;
}
2019-04-05 07:38:48 +00:00
CV_SetValue ( & cv_playbackspeed , cv_playbackspeed . value = = 1 ? 4 : 1 ) ;
}
static void M_PlaybackAdvance ( INT32 choice )
{
( void ) choice ;
paused = false ;
TryRunTics ( 1 ) ;
paused = true ;
}
static void M_PlaybackSetViews ( INT32 choice )
{
if ( choice > 0 )
{
if ( splitscreen < 3 )
G_AdjustView ( splitscreen + 2 , 0 , true ) ;
}
else if ( splitscreen )
{
splitscreen - - ;
R_ExecuteSetViewSize ( ) ;
}
}
static void M_PlaybackAdjustView ( INT32 choice )
{
G_AdjustView ( itemOn - playback_viewcount , ( choice > 0 ) ? 1 : - 1 , true ) ;
}
2019-03-31 22:29:41 +00:00
2019-04-06 23:17:56 +00:00
static void M_PlaybackQuit ( INT32 choice )
{
( void ) choice ;
G_StopDemo ( ) ;
if ( demo . inreplayhut )
M_ReplayHut ( choice ) ;
else if ( modeattacking )
2019-04-06 23:59:11 +00:00
{
M_EndModeAttackRun ( ) ;
S_ChangeMusicInternal ( " racent " , true ) ;
}
2019-04-06 23:17:56 +00:00
else
D_StartTitle ( ) ;
}
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-10-16 00:28:35 +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-10-16 00:28:35 +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 ) ;
2018-10-16 00:28:35 +00:00
COM_ImmedExecute ( va ( " teamscramble %d " , cv_dummyscramble . value + 1 ) ) ;
}
static void M_ConfirmTeamChange ( INT32 choice )
{
( void ) choice ;
if ( cv_dummymenuplayer . value > splitscreen + 1 )
return ;
if ( ! cv_allowteamchange . value & & cv_dummyteam . value )
{
M_StartMessage ( M_GetText ( " The server is not allowing \n team changes at this time. \n Press a key. \n " ) , NULL , MM_NOTHING ) ;
return ;
}
M_ClearMenus ( true ) ;
switch ( cv_dummymenuplayer . value )
2014-03-15 16:59:03 +00:00
{
case 1 :
2018-10-16 00:28:35 +00:00
default :
COM_ImmedExecute ( va ( " changeteam %s " , cv_dummyteam . string ) ) ;
break ;
case 2 :
COM_ImmedExecute ( va ( " changeteam2 %s " , cv_dummyteam . string ) ) ;
break ;
case 3 :
COM_ImmedExecute ( va ( " changeteam3 %s " , cv_dummyteam . string ) ) ;
break ;
case 4 :
COM_ImmedExecute ( va ( " changeteam4 %s " , cv_dummyteam . string ) ) ;
2014-03-15 16:59:03 +00:00
break ;
}
}
2018-10-16 00:28:35 +00:00
static void M_ConfirmSpectateChange ( INT32 choice )
2014-03-15 16:59:03 +00:00
{
( void ) choice ;
2018-10-16 00:28:35 +00:00
if ( cv_dummymenuplayer . value > splitscreen + 1 )
return ;
if ( ! cv_allowteamchange . value & & cv_dummyspectate . value )
2014-03-15 16:59:03 +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 ;
}
M_ClearMenus ( true ) ;
2018-10-16 00:28:35 +00:00
switch ( cv_dummymenuplayer . value )
2014-03-15 16:59:03 +00:00
{
case 1 :
2018-10-16 00:28:35 +00:00
default :
COM_ImmedExecute ( va ( " changeteam %s " , cv_dummyspectate . string ) ) ;
2014-03-15 16:59:03 +00:00
break ;
case 2 :
2018-10-16 00:28:35 +00:00
COM_ImmedExecute ( va ( " changeteam2 %s " , cv_dummyspectate . string ) ) ;
break ;
case 3 :
COM_ImmedExecute ( va ( " changeteam3 %s " , cv_dummyspectate . string ) ) ;
break ;
case 4 :
COM_ImmedExecute ( va ( " changeteam4 %s " , cv_dummyspectate . string ) ) ;
2014-03-15 16:59:03 +00:00
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
2019-05-02 05:33:11 +00:00
OP_MainMenu [ 4 ] . status = OP_MainMenu [ 5 ] . status = ( Playing ( ) & & ! ( server | | IsPlayerAdmin ( consoleplayer ) ) ) ? ( IT_GRAYEDOUT ) : ( IT_STRING | IT_SUBMENU ) ;
2014-03-15 16:59:03 +00:00
2019-05-02 05:33:11 +00:00
OP_MainMenu [ 8 ] . status = ( Playing ( ) ) ? ( IT_GRAYEDOUT ) : ( IT_STRING | IT_CALL ) ; // Play credits
OP_DataOptionsMenu [ 3 ] . status = ( Playing ( ) ) ? ( IT_GRAYEDOUT ) : ( IT_STRING | IT_SUBMENU ) ; // Erase data
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 ;
2018-10-17 12:40:17 +00:00
M_StartMessage ( M_GetText ( " Start this race over? \n \n (Press 'Y' to confirm) \n " ) , M_RetryResponse , MM_YESNO ) ;
2014-03-15 16:59:03 +00:00
}
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 ) ;
2019-01-17 22:01:28 +00:00
G_SetGameModified ( multiplayer , true ) ;
2014-03-15 16:59:03 +00:00
}
static void M_DestroyRobotsResponse ( INT32 ch )
{
if ( ch ! = ' y ' & & ch ! = KEY_ENTER )
return ;
// Destroy all robots
P_DestroyRobots ( ) ;
2019-01-17 22:01:28 +00:00
G_SetGameModified ( multiplayer , true ) ;
2014-03-15 16:59:03 +00:00
}
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 ) ;
}
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
/*static void M_LevelSelectWarp(INT32 choice)
2014-03-15 16:59:03 +00:00
{
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 ) ;
}
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
} */
2014-03-15 16:59:03 +00:00
// ========
// 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-11-07 18:01:50 +00:00
return va ( " Get %d medals " , cond . requirement ) ;
2018-03-29 05:14:29 +00:00
case UC_EXTRAEMBLEM :
2018-11-07 18:01:50 +00:00
return va ( " Get \" %s \" medal " , 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 ;
2018-11-14 19:39:37 +00:00
boolean secret = false ;
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < MAXUNLOCKABLES ; i + + )
{
2018-11-14 19:15:24 +00:00
const char * secretname ;
2018-11-14 19:39:37 +00:00
secret = ( ! M_Achieved ( unlockables [ i ] . showconditionset - 1 ) & & ! unlockables [ i ] . unlocked ) ;
2018-11-14 19:15:24 +00:00
2014-03-15 16:59:03 +00:00
if ( unlockables [ i ] . name [ 0 ] = = 0 | | unlockables [ i ] . nochecklist
2018-08-08 19:48:29 +00:00
| | ! unlockables [ i ] . conditionset | | unlockables [ i ] . conditionset > MAXCONDITIONSETS
2018-11-14 19:39:37 +00:00
| | ( unlockables [ i ] . type = = SECRET_HELLATTACK & & secret ) ) // TODO: turn this into an unlockable setting instead of tying it to Hell Attack
2014-03-15 16:59:03 +00:00
continue ;
2018-03-29 05:14:29 +00:00
+ + line ;
2018-11-14 19:15:24 +00:00
secretname = M_CreateSecretMenuOption ( unlockables [ i ] . name ) ;
V_DrawString ( 8 , ( line * 8 ) , V_RETURN8 | ( unlockables [ i ] . unlocked ? recommendedflags : warningflags ) , ( secret ? secretname : 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-11-14 19:15:24 +00:00
const char * secretstr = M_CreateSecretMenuOption ( str ) ;
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 ) , " * " ) ;
2018-11-14 19:15:24 +00:00
V_DrawString ( 32 , ( line * 8 ) , V_MONOSPACE | V_ALLOWLOWERCASE | ( achieved ? highlightflags : 0 ) , ( secret ? secretstr : str ) ) ;
2018-03-29 15:43:56 +00:00
}
else
{
2018-11-14 19:15:24 +00:00
V_DrawString ( 32 , ( line * 8 ) , V_MONOSPACE | V_ALLOWLOWERCASE | ( achieved ? highlightflags : 0 ) , ( secret ? " ? " : " & " ) ) ;
V_DrawString ( 48 , ( line * 8 ) , V_MONOSPACE | V_ALLOWLOWERCASE | ( achieved ? highlightflags : 0 ) , ( secret ? secretstr : str ) ) ;
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 ) ,
2019-03-16 05:39:52 +00:00
R_GetTranslationColormap ( TC_DEFAULT , M_GetEmblemColor ( emblem ) , GTC_MENUCACHE ) ) ;
2014-03-15 16:59:03 +00:00
}
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-11-07 18:01:50 +00:00
V_DrawCenteredString ( 160 , 48 , highlightflags , " No hidden medals 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-11-07 21:15:14 +00:00
( sound_disabled ? warningflags : highlightflags ) ,
( sound_disabled ? " OFF " : " ON " ) ) ;
2018-06-30 22:18:13 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x ,
currentMenu - > y + currentMenu - > menuitems [ 2 ] . alphaKey ,
2018-11-07 21:15:14 +00:00
( digital_disabled ? warningflags : highlightflags ) ,
( digital_disabled ? " OFF " : " ON " ) ) ;
2018-06-30 22:18:13 +00:00
/*V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x,
currentMenu - > y + currentMenu - > menuitems [ 5 ] . alphaKey ,
2018-11-07 21:15:14 +00:00
( midi_disabled ? warningflags : highlightflags ) ,
( midi_disabled ? " OFF " : " ON " ) ) ; */
2018-06-30 22:18:13 +00:00
if ( itemOn = = 0 )
2018-11-07 21:15:14 +00:00
lengthstring = 8 * ( sound_disabled ? 3 : 2 ) ;
2018-06-30 22:18:13 +00:00
else if ( itemOn = = 2 )
2018-11-07 21:15:14 +00:00
lengthstring = 8 * ( digital_disabled ? 3 : 2 ) ;
2018-06-30 22:18:13 +00:00
/*else if (itemOn == 5)
2018-11-07 21:15:14 +00:00
lengthstring = 8 * ( midi_disabled ? 3 : 2 ) ; */
2018-06-30 22:18:13 +00:00
}
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
// ==================
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
/*INT32 ultimate_selectable = false;
2014-03-15 16:59:03 +00:00
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 ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
} */
2014-03-15 16:59:03 +00:00
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
// ==================
2019-03-30 22:25:54 +00:00
#if 0 // Bring this back when we have actual single-player
2014-03-15 16:59:03 +00:00
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 ) ;
}
2019-03-30 22:25:54 +00:00
# endif
2014-03-15 16:59:03 +00:00
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
/*static void M_LoadGameLevelSelect(INT32 choice)
2014-03-15 16:59:03 +00:00
{
( 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 ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
} */
2014-03-15 16:59:03 +00:00
// ==============
// LOAD GAME MENU
// ==============
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
/*static INT32 saveSlotSelected = 0;
2014-03-15 16:59:03 +00:00
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 " ) ;
2018-11-07 18:01:50 +00:00
V_DrawCenteredString ( ecks + 68 , 172 , 0 , " GET MEDALS AND SECRETS. " ) ;
2014-03-15 16:59:03 +00:00
}
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
{
2019-03-16 05:39:52 +00:00
UINT8 * colormap = R_GetTranslationColormap ( savegameinfo [ saveSlotSelected ] . skinnum , savegameinfo [ saveSlotSelected ] . skincolor , GTC_MENUCACHE ) ;
2014-03-15 16:59:03 +00:00
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
//
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
static void M_LoadGame ( INT32 choice )
2014-03-15 16:59:03 +00:00
{
( void ) choice ;
M_ReadSaveStrings ( ) ;
M_SetupNextMenu ( & SP_LoadDef ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +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
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
} */
2014-03-15 16:59:03 +00:00
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 " ) ;
2018-11-07 18:01:50 +00:00
V_DrawString ( 256 , y , highlightflags , " MEDALS " ) ;
2018-07-01 18:29:13 +00:00
y + = 8 ;
dotopname = false ;
}
2014-03-15 16:59:03 +00:00
mnum = statsMapList [ i ] ;
2018-11-01 00:10:34 +00:00
M_DrawMapEmblems ( mnum + 1 , 295 , y ) ;
2014-03-15 16:59:03 +00:00
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 " ) ;
2018-11-07 18:01:50 +00:00
V_DrawString ( 256 , y , highlightflags , " MEDALS " ) ;
2018-07-01 18:29:13 +00:00
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 )
{
2018-11-07 18:01:50 +00:00
V_DrawString ( 20 , y , highlightflags , " EXTRA MEDALS " ) ;
2018-07-01 18:29:13 +00:00
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 )
2018-11-01 00:10:34 +00:00
V_DrawSmallMappedPatch ( 295 , y , 0 , W_CachePatchName ( M_GetExtraEmblemPatch ( exemblem ) , PU_CACHE ) ,
2019-03-16 05:39:52 +00:00
R_GetTranslationColormap ( TC_DEFAULT , M_GetExtraEmblemColor ( exemblem ) , GTC_MENUCACHE ) ) ;
2014-03-15 16:59:03 +00:00
else
2018-11-01 00:10:34 +00:00
V_DrawSmallScaledPatch ( 295 , y , 0 , W_CachePatchName ( " NEEDIT " , PU_CACHE ) ) ;
2014-03-15 16:59:03 +00:00
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 ) ,
2018-10-16 21:11:47 +00:00
' \x1B ' | highlightflags , false ) ; // down 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-11-01 00:10:34 +00:00
V_DrawString ( 32 , 70 , 0 , va ( " x %d/%d " , M_CountEmblems ( ) , numemblems + numextraemblems ) ) ;
V_DrawSmallScaledPatch ( 20 , 70 , 0 , W_CachePatchName ( " GOTITA " , 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
//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!
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
if ( W_CheckNumForName ( skins [ cv_chooseskin . value - 1 ] . facewant ) ! = LUMPERROR )
2018-07-02 00:55:01 +00:00
{
2019-03-16 05:39:52 +00:00
UINT8 * colormap = R_GetTranslationColormap ( cv_chooseskin . value - 1 , cv_playercolor . value , GTC_MENUCACHE ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
V_DrawMappedPatch ( BASEVIDWIDTH - x - SHORT ( facewantprefix [ cv_chooseskin . value - 1 ] - > width ) , y , 0 , facewantprefix [ cv_chooseskin . value - 1 ] , colormap ) ;
2018-07-02 00:55:01 +00:00
}
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-11-04 01:00:17 +00:00
{
INT32 strw = V_StringWidth ( dummystaffname , V_ALLOWLOWERCASE ) ;
V_DrawString ( BASEVIDWIDTH - x - strw , y , highlightflags | V_ALLOWLOWERCASE , dummystaffname ) ;
if ( i = = itemOn )
{
V_DrawCharacter ( BASEVIDWIDTH - x - 10 - strw - ( skullAnimCounter / 5 ) , y ,
' \x1C ' | highlightflags , false ) ; // left arrow
V_DrawCharacter ( BASEVIDWIDTH - x + 2 + ( skullAnimCounter / 5 ) , y ,
' \x1D ' | highlightflags , false ) ; // right arrow
}
}
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: " ) ;
2018-11-04 12:15:13 +00:00
K_drawKartTimestamp ( lap , 19 , 86 , 0 , 2 ) ;
2018-08-29 20:37:47 +00:00
V_DrawRightAlignedString ( 292 , 80 , highlightflags , " BEST TIME: " ) ;
2018-11-04 12:15:13 +00:00
K_drawKartTimestamp ( time , 162 , 86 , cv_nextmap . value , 1 ) ;
2018-08-29 20:37:47 +00:00
}
/*{
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 ) ,
2019-03-16 05:39:52 +00:00
R_GetTranslationColormap ( TC_DEFAULT , M_GetEmblemColor ( em ) , GTC_MENUCACHE ) ) ;
2014-03-15 16:59:03 +00:00
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 ) ,
2019-03-16 05:39:52 +00:00
R_GetTranslationColormap ( TC_DEFAULT , M_GetEmblemColor ( em ) , GTC_MENUCACHE ) ) ;
2014-11-12 00:55:07 +00:00
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 ;
2019-03-25 02:32:15 +00:00
demo . loadfiles = false ; demo . ignorefiles = true ; // Just assume that record attack replays have the files needed
2017-10-21 02:01:07 +00:00
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
2019-03-25 02:32:15 +00:00
demo . loadfiles = false ; demo . ignorefiles = true ; // Just assume that record attack replays have the files needed
2014-03-15 16:59:03 +00:00
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-11-06 13:38:53 +00:00
case 3 : // 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 ;
2019-03-25 02:32:15 +00:00
if ( demo . playback )
2014-03-15 16:59:03 +00:00
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 )
{
2019-03-18 22:00:23 +00:00
UINT16 i ;
2014-03-15 16:59:03 +00:00
const char * gt = " Unknown " ;
2019-03-09 20:30:04 +00:00
const char * spd = " " ;
2014-03-15 16:59:03 +00:00
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 " ;
2019-03-18 22:00:23 +00:00
if ( serverlist [ slindex ] . info . gametype < NUMGAMETYPES )
gt = Gametype_Names [ serverlist [ slindex ] . info . gametype ] ;
2014-03-15 16:59:03 +00:00
V_DrawSmallString ( currentMenu - > x + 46 , S_LINEY ( i ) + 8 , globalflags ,
va ( " Players: %02d/%02d " , serverlist [ slindex ] . info . numberofplayer , serverlist [ slindex ] . info . maxplayer ) ) ;
2019-03-09 20:30:04 +00:00
V_DrawSmallString ( currentMenu - > x + 112 , S_LINEY ( i ) + 8 , globalflags , gt ) ;
if ( serverlist [ slindex ] . info . gametype = = GT_RACE )
{
spd = kartspeed_cons_t [ serverlist [ slindex ] . info . kartvars & SV_SPEEDMASK ] . strvalue ;
V_DrawSmallString ( currentMenu - > x + 132 , S_LINEY ( i ) + 8 , globalflags , va ( " (%s Speed) " , spd ) ) ;
}
if ( serverlist [ slindex ] . info . kartvars & SV_PASSWORD )
2019-03-09 21:27:23 +00:00
V_DrawFixedPatch ( ( currentMenu - > x - 9 ) < < FRACBITS , ( S_LINEY ( i ) ) < < FRACBITS , FRACUNIT , globalflags & ( ~ V_ALLOWLOWERCASE ) , W_CachePatchName ( " SERVLOCK " , PU_CACHE ) , NULL ) ;
2014-03-15 16:59:03 +00:00
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
2018-11-19 17:47:23 +00:00
static boolean M_CheckMODVersion ( void )
2014-03-15 16:59:03 +00:00
{
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 ;
2019-04-19 05:41:50 +00:00
if ( ms_RoomId < 0 )
2019-06-19 21:32:11 +00:00
{
2019-04-19 05:41:50 +00:00
M_RoomMenu ( 0 ) ; // Select a room instead of staring at an empty list
2019-06-19 21:32:11 +00:00
// This prevents us from returning to the modified game alert.
currentMenu - > prevMenu = & MP_MainDef ;
}
2019-04-19 05:41:50 +00:00
else
M_SetupNextMenu ( & MP_ConnectDef ) ;
2014-03-15 16:59:03 +00:00
itemOn = 0 ;
M_Refresh ( 0 ) ;
}
2019-01-18 13:04:12 +00:00
static void M_ConnectMenuModChecks ( INT32 choice )
{
( void ) choice ;
// okay never mind we want to COMMUNICATE to the player pre-emptively instead of letting them try and then get confused when it doesn't work
if ( modifiedgame )
{
2019-01-18 14:11:59 +00:00
M_StartMessage ( M_GetText ( " Add-ons are currently loaded. \n \n You will only be able to join a server if \n it has the same ones loaded in the same order, which may be unlikely. \n \n If you wish to play on other servers, \n restart the game to clear existing add-ons. \n \n (Press a key) \n " ) , M_ConnectMenu , MM_EVENTHANDLER ) ;
2019-01-18 13:04:12 +00:00
return ;
}
M_ConnectMenu ( - 1 ) ;
}
2014-03-15 16:59:03 +00:00
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 ;
2019-04-19 05:41:50 +00:00
/*
We were on the Multiplayer menu ? That means that we must have been trying to
view the server browser , but we hadn ' t selected a room yet . So we need to go
to the browser next , not back there .
*/
if ( currentMenu - > prevMenu = = & MP_MainDef )
M_SetupNextMenu ( & MP_ConnectDef ) ;
else
M_SetupNextMenu ( currentMenu - > prevMenu ) ;
2014-03-15 16:59:03 +00:00
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 )
{
2018-10-16 21:11:47 +00:00
UINT8 ssplayers = cv_splitplayers . value - 1 ;
2018-09-30 21:09:59 +00:00
( void ) choice ;
if ( currentMenu = = & MP_OfflineServerDef )
netgame = false ;
2018-06-30 15:01:03 +00:00
else
2014-03-15 16:59:03 +00:00
netgame = true ;
multiplayer = true ;
2019-03-25 01:36:22 +00:00
strncpy ( connectedservername , cv_servername . string , MAXSERVERNAME ) ;
2014-03-15 16:59:03 +00:00
// Still need to reset devmode
cv_debug = 0 ;
2019-03-09 21:00:48 +00:00
if ( strlen ( cv_dummyjoinpassword . string ) > 0 )
D_SetJoinPassword ( cv_dummyjoinpassword . string ) ;
else
joinpasswordset = false ;
2019-03-25 02:32:15 +00:00
if ( demo . playback )
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-11-26 09:27:31 +00:00
CV_SetValue ( & cv_nextmap , G_RandMap ( G_TOLFlag ( cv_newgametype . value ) , - 1 , false , 0 , false , NULL ) + 1 ) ;
2018-08-15 15:12:36 +00:00
2018-09-30 21:17:33 +00:00
if ( cv_maxplayers . value < ssplayers + 1 )
CV_SetValue ( & cv_maxplayers , ssplayers + 1 ) ;
2018-10-25 11:21:44 +00:00
2018-09-30 21:09:59 +00:00
if ( splitscreen ! = ssplayers )
2014-03-15 16:59:03 +00:00
{
2018-09-30 21:09:59 +00:00
splitscreen = ssplayers ;
SplitScreen_OnChange ( ) ;
2014-03-15 16:59:03 +00:00
}
2018-09-30 21:09:59 +00:00
if ( currentMenu = = & MP_OfflineServerDef ) // offline server
2014-03-15 16:59:03 +00:00
{
paused = false ;
SV_StartSinglePlayerServer ( ) ;
2018-10-21 11:51:18 +00:00
multiplayer = true ; // yeah, SV_StartSinglePlayerServer clobbers this...
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
}
2018-09-30 21:09:59 +00:00
else
{
D_MapChange ( cv_nextmap . value , cv_newgametype . value , ( boolean ) cv_kartencore . value , 1 , 1 , false , false ) ;
COM_BufAddText ( " dummyconsvar 1 \n " ) ;
}
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 )
{
2018-10-16 21:11:47 +00:00
M_DrawLevelSelectOnly ( false , 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 ,
2018-09-30 21:09:59 +00:00
highlightflags , ( itemOn = = mp_server_room ) ? " <Select to change> " : " <LAN Mode> " ) ;
2018-07-02 00:55:01 +00:00
else
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x , currentMenu - > y + MP_ServerMenu [ mp_server_room ] . alphaKey ,
highlightflags , room_list [ menuRoomIndex ] . name ) ;
# undef mp_server_room
}
# endif
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 ) ;
}
2018-09-30 21:09:59 +00:00
static void M_StartOfflineServerMenu ( INT32 choice )
2014-03-15 16:59:03 +00:00
{
( void ) choice ;
levellistmode = LLM_CREATESERVER ;
M_PrepareLevelSelect ( ) ;
2018-09-30 21:09:59 +00:00
M_SetupNextMenu ( & MP_OfflineServerDef ) ;
2014-03-15 16:59:03 +00:00
}
# 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
// ==============
2019-01-26 04:50:58 +00:00
static char setupm_ip [ 28 ] ;
2018-10-16 21:11:47 +00:00
# endif
static UINT8 setupm_pselect = 1 ;
2014-03-15 16:59:03 +00:00
// 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-10-16 21:11:47 +00:00
# ifndef NONET
# if MAXPLAYERS != 16
2018-06-30 15:01:03 +00:00
Update the maxplayers label . . .
2018-10-16 21:11:47 +00:00
# endif
V_DrawRightAlignedString ( BASEVIDWIDTH - x , y + MP_MainMenu [ 4 ] . alphaKey ,
( ( itemOn = = 4 ) ? highlightflags : 0 ) , " (2-16 players) " ) ;
2018-06-30 15:01:03 +00:00
# endif
2018-10-16 21:11:47 +00:00
V_DrawRightAlignedString ( BASEVIDWIDTH - x , y + MP_MainMenu [ 5 ] . alphaKey ,
( ( itemOn = = 5 ) ? highlightflags : 0 ) ,
2018-06-30 15:01:03 +00:00
" (2-4 players) "
) ;
2018-10-16 21:11:47 +00:00
# ifndef NONET
y + = MP_MainMenu [ 8 ] . 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
2019-01-26 04:50:58 +00:00
V_DrawString ( x + 8 , y + 12 , V_ALLOWLOWERCASE , setupm_ip ) ;
2014-03-15 16:59:03 +00:00
// draw text cursor for name
2018-10-16 21:11:47 +00:00
if ( itemOn = = 8
2018-06-30 15:01:03 +00:00
& & skullAnimCounter < 4 ) //blink cursor
2019-01-26 04:50:58 +00:00
V_DrawCharacter ( x + 8 + V_StringWidth ( setupm_ip , V_ALLOWLOWERCASE ) , y + 12 , ' _ ' , false ) ;
2018-10-16 21:11:47 +00:00
# endif
// character bar, ripped off the color bar :V
{
# define iconwidth 32
# define spacingwidth 32
# define incrwidth (iconwidth + spacingwidth)
UINT8 i = 0 , pskin , pcol ;
// player arrangement width, but there's also a chance i'm a furry, shhhhhh
const INT32 paw = iconwidth + 3 * incrwidth ;
INT32 trans = 0 ;
UINT8 * colmap ;
x = BASEVIDWIDTH / 2 - paw / 2 ;
y = currentMenu - > y + 32 ;
while ( + + i < = 4 )
{
switch ( i )
{
default :
pskin = R_SkinAvailable ( cv_skin . string ) ;
pcol = cv_playercolor . value ;
break ;
case 2 :
pskin = R_SkinAvailable ( cv_skin2 . string ) ;
pcol = cv_playercolor2 . value ;
break ;
case 3 :
pskin = R_SkinAvailable ( cv_skin3 . string ) ;
pcol = cv_playercolor3 . value ;
break ;
case 4 :
pskin = R_SkinAvailable ( cv_skin4 . string ) ;
pcol = cv_playercolor4 . value ;
break ;
}
if ( pskin > = MAXSKINS )
pskin = 0 ;
if ( ! trans & & i > cv_splitplayers . value )
trans = V_TRANSLUCENT ;
2019-03-16 05:39:52 +00:00
colmap = R_GetTranslationColormap ( pskin , pcol , GTC_MENUCACHE ) ;
2018-10-16 21:11:47 +00:00
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
V_DrawFixedPatch ( x < < FRACBITS , y < < FRACBITS , FRACUNIT , trans , facewantprefix [ pskin ] , colmap ) ;
2018-10-16 21:11:47 +00:00
if ( itemOn = = 2 & & i = = setupm_pselect )
{
2018-11-14 21:53:57 +00:00
static UINT8 cursorframe = 0 ;
2018-11-10 05:01:44 +00:00
if ( skullAnimCounter % 4 = = 0 )
cursorframe + + ;
if ( cursorframe > 7 )
cursorframe = 0 ;
V_DrawFixedPatch ( x < < FRACBITS , y < < FRACBITS , FRACUNIT , 0 , W_CachePatchName ( va ( " K_BHILI%d " , cursorframe + 1 ) , PU_CACHE ) , NULL ) ;
2018-10-16 21:11:47 +00:00
}
x + = incrwidth ;
}
# undef incrwidth
# undef spacingwidth
# undef iconwidth
}
2014-03-15 16:59:03 +00:00
}
2018-10-16 21:11:47 +00:00
static void Splitplayers_OnChange ( void )
{
if ( cv_splitplayers . value < setupm_pselect )
setupm_pselect = 1 ;
}
static void M_SetupMultiHandler ( INT32 choice )
{
boolean exitmenu = false ; // exit to previous menu and send name change
switch ( choice )
{
case KEY_LEFTARROW :
if ( cv_splitplayers . value > 1 )
{
if ( - - setupm_pselect < 1 )
setupm_pselect = cv_splitplayers . value ;
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
}
break ;
case KEY_RIGHTARROW :
if ( cv_splitplayers . value > 1 )
{
if ( + + setupm_pselect > cv_splitplayers . value )
setupm_pselect = 1 ;
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
}
break ;
case KEY_DOWNARROW :
M_NextOpt ( ) ;
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
break ;
case KEY_UPARROW :
M_PrevOpt ( ) ;
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
break ;
case KEY_ENTER :
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
currentMenu - > lastOn = itemOn ;
switch ( setupm_pselect )
{
case 2 :
M_SetupMultiPlayer2 ( 0 ) ;
return ;
case 3 :
M_SetupMultiPlayer3 ( 0 ) ;
return ;
case 4 :
M_SetupMultiPlayer4 ( 0 ) ;
return ;
default :
M_SetupMultiPlayer ( 0 ) ;
return ;
}
break ;
}
case KEY_ESCAPE :
exitmenu = true ;
break ;
}
if ( exitmenu )
{
if ( currentMenu - > prevMenu )
M_SetupNextMenu ( currentMenu - > prevMenu ) ;
else
M_ClearMenus ( true ) ;
}
}
# ifndef NONET
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 ;
}
2018-10-27 19:44:18 +00:00
M_ClearMenus ( true ) ;
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
2018-11-14 15:28:17 +00:00
currentMenu - > lastOn = itemOn ;
2014-03-15 16:59:03 +00:00
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 :
2019-01-26 09:41:05 +00:00
l = strlen ( setupm_ip ) ;
if ( l > = 28 - 1 )
2018-06-30 15:01:03 +00:00
break ;
2019-01-26 09:41:05 +00:00
// Rudimentary number and period enforcing - also allows letters so hostnames can be used instead
2019-01-26 21:15:37 +00:00
if ( ( choice > = ' - ' & & choice < = ' : ' ) | | ( choice > = ' A ' & & choice < = ' Z ' ) | | ( choice > = ' a ' & & choice < = ' z ' ) )
2019-01-26 09:41:05 +00:00
{
S_StartSound ( NULL , sfx_menu1 ) ; // Tails
setupm_ip [ l ] = ( char ) choice ;
setupm_ip [ l + 1 ] = 0 ;
}
else if ( choice > = 199 & & choice < = 211 & & choice ! = 202 & & choice ! = 206 ) //numpad too!
2014-03-15 16:59:03 +00:00
{
2019-01-26 09:41:05 +00:00
char keypad_translation [ ] = { ' 7 ' , ' 8 ' , ' 9 ' , ' - ' , ' 4 ' , ' 5 ' , ' 6 ' , ' + ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 0 ' , ' . ' } ;
choice = keypad_translation [ choice - 199 ] ;
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
}
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 )
2019-03-16 05:39:52 +00:00
V_DrawFixedPatch ( ( ( BASEVIDWIDTH - mx - 80 ) + ( ( speed - 1 ) * 8 ) ) < < FRACBITS , ( ( my + 76 ) + ( ( weight - 1 ) * 8 ) ) < < FRACBITS , FRACUNIT , 0 , statdot , R_GetTranslationColormap ( 0 , setupm_fakecolor , GTC_MENUCACHE ) ) ;
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 ;
2018-11-10 05:01:44 +00:00
patch_t * cursor ;
static UINT8 cursorframe = 0 ;
2017-11-28 21:57:38 +00:00
patch_t * face ;
2018-10-16 21:11:47 +00:00
UINT8 * colmap ;
2017-11-28 21:57:38 +00:00
2018-11-10 05:01:44 +00:00
if ( skullAnimCounter % 4 = = 0 )
cursorframe + + ;
if ( cursorframe > 7 )
cursorframe = 0 ;
cursor = W_CachePatchName ( va ( " K_BHILI%d " , cursorframe + 1 ) , PU_CACHE ) ;
2017-11-28 21:57:38 +00:00
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 ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
face = facewantprefix [ col ] ;
2017-11-28 21:57:38 +00:00
offx = 12 ;
offy = 0 ;
}
else
{
scale = FRACUNIT / 2 ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
face = facerankprefix [ col ] ;
2017-11-28 21:57:38 +00:00
offx = 8 ;
offy = 8 ;
}
2019-03-16 05:39:52 +00:00
colmap = R_GetTranslationColormap ( col , setupm_fakecolor , GTC_MENUCACHE ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
V_DrawFixedPatch ( ( x + offx ) < < FRACBITS , ( my + 28 + offy ) < < FRACBITS , FRACUNIT , 0 , face , colmap ) ;
2017-11-28 21:57:38 +00:00
if ( scale = = FRACUNIT ) // bit of a hack
2018-11-10 05:01:44 +00:00
V_DrawFixedPatch ( ( x + offx ) < < FRACBITS , ( my + 28 + offy ) < < FRACBITS , FRACUNIT , 0 , cursor , colmap ) ;
2017-11-28 21:57:38 +00:00
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
{
2019-03-16 05:39:52 +00:00
UINT8 * colormap = R_GetTranslationColormap ( setupm_fakeskin , setupm_fakecolor , GTC_MENUCACHE ) ;
2014-03-15 16:59:03 +00:00
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
}
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
2019-05-12 09:22:34 +00:00
if ( ( choice = = gamecontrol [ gc_fire ] [ 0 ] | | choice = = gamecontrol [ gc_fire ] [ 1 ] ) & & itemOn = = 2 )
choice = KEY_BACKSPACE ; // Hack to allow resetting prefcolor on controllers
2019-05-12 08:21:46 +00:00
2014-03-15 16:59:03 +00:00
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
2019-04-18 07:08:11 +00:00
setupm_player = & players [ displayplayers [ 1 ] ] ;
2014-03-15 16:59:03 +00:00
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
2019-04-18 07:08:11 +00:00
if ( splitscreen & & ! CanChangeSkin ( displayplayers [ 1 ] ) )
2014-03-15 16:59:03 +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 ) ;
}
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
2019-04-18 07:08:11 +00:00
setupm_player = & players [ displayplayers [ 2 ] ] ;
2017-12-08 07:29:01 +00:00
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
2019-04-18 07:08:11 +00:00
if ( splitscreen > 1 & & ! CanChangeSkin ( displayplayers [ 2 ] ) )
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
2019-04-18 07:08:11 +00:00
setupm_player = & players [ displayplayers [ 3 ] ] ;
2017-12-08 07:29:01 +00:00
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
2019-04-18 07:08:11 +00:00
if ( splitscreen > 2 & & ! CanChangeSkin ( displayplayers [ 3 ] ) )
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 ) ;
}
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 ;
2018-11-14 01:27:01 +00:00
S_StartSound ( NULL , sfx_itrole ) ; // bweh heh heh
2014-03-15 16:59:03 +00:00
// Delete the data
if ( erasecontext = = 2 )
{
2018-11-12 22:09:37 +00:00
// SRB2Kart: This actually needs to be done FIRST, so that you don't immediately regain playtime/matches secrets
2014-03-15 16:59:03 +00:00
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 ( ) ;
}
2018-11-12 22:09:37 +00:00
if ( erasecontext ! = 1 )
G_ClearRecords ( ) ;
if ( erasecontext ! = 0 )
M_ClearSecrets ( ) ;
2014-03-15 16:59:03 +00:00
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 )
{
2018-12-27 22:21:51 +00:00
INT32 i , compareval4 , compareval3 , compareval2 , compareval ;
2014-03-15 16:59:03 +00:00
M_DrawGenericMenu ( ) ;
2018-07-03 20:18:17 +00:00
for ( i = 0 ; i < 8 ; i + + )
2014-03-15 16:59:03 +00:00
{
2018-12-02 01:13:14 +00:00
M_DrawTextBox ( OP_JoystickSetDef . x - 8 , OP_JoystickSetDef . y + LINEHEIGHT * i - 12 , 28 , 1 ) ;
//M_DrawSaveLoadBorder(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i);
2014-03-15 16:59:03 +00:00
2018-12-14 10:31:47 +00:00
# ifdef JOYSTICK_HOTPLUG
2018-12-27 22:21:51 +00:00
if ( atoi ( cv_usejoystick4 . string ) > I_NumJoys ( ) )
compareval4 = atoi ( cv_usejoystick4 . string ) ;
else
compareval4 = cv_usejoystick4 . value ;
if ( atoi ( cv_usejoystick3 . string ) > I_NumJoys ( ) )
compareval3 = atoi ( cv_usejoystick3 . string ) ;
else
compareval3 = cv_usejoystick3 . value ;
2018-12-14 10:31:47 +00:00
if ( atoi ( cv_usejoystick2 . string ) > I_NumJoys ( ) )
compareval2 = atoi ( cv_usejoystick2 . string ) ;
else
compareval2 = cv_usejoystick2 . value ;
if ( atoi ( cv_usejoystick . string ) > I_NumJoys ( ) )
compareval = atoi ( cv_usejoystick . string ) ;
else
compareval = cv_usejoystick . value ;
# else
2018-12-27 22:21:51 +00:00
compareval4 = cv_usejoystick4 . value ;
compareval3 = cv_usejoystick3 . value ;
2018-12-14 10:31:47 +00:00
compareval2 = cv_usejoystick2 . value ;
compareval = cv_usejoystick . value
# endif
2018-12-27 22:21:51 +00:00
if ( ( setupcontrolplayer = = 4 & & ( i = = compareval4 ) )
| | ( setupcontrolplayer = = 3 & & ( i = = compareval3 ) )
| | ( setupcontrolplayer = = 2 & & ( i = = compareval2 ) )
| | ( setupcontrolplayer = = 1 & & ( i = = compareval ) ) )
2018-12-02 01:13:14 +00:00
V_DrawString ( OP_JoystickSetDef . x , OP_JoystickSetDef . y + LINEHEIGHT * i - 4 , V_GREENMAP , joystickInfo [ i ] ) ;
2014-03-15 16:59:03 +00:00
else
2018-12-02 01:13:14 +00:00
V_DrawString ( OP_JoystickSetDef . x , OP_JoystickSetDef . y + LINEHEIGHT * i - 4 , 0 , joystickInfo [ i ] ) ;
2014-03-15 16:59:03 +00:00
}
}
2018-12-06 15:54:58 +00:00
void M_SetupJoystickMenu ( INT32 choice )
2014-03-15 16:59:03 +00:00
{
INT32 i = 0 ;
const char * joyNA = " Unavailable " ;
INT32 n = I_NumJoys ( ) ;
( void ) choice ;
2018-12-03 18:32:24 +00:00
strcpy ( joystickInfo [ i ] , " None " ) ;
2014-03-15 16:59:03 +00:00
for ( i = 1 ; i < 8 ; i + + )
{
2018-12-02 01:13:14 +00:00
if ( i < = n & & ( I_GetJoyName ( i ) ) ! = NULL )
strncpy ( joystickInfo [ i ] , I_GetJoyName ( i ) , 28 ) ;
2014-03-15 16:59:03 +00:00
else
strcpy ( joystickInfo [ i ] , joyNA ) ;
2018-12-14 08:58:07 +00:00
# ifdef JOYSTICK_HOTPLUG
// We use cv_usejoystick.string as the USER-SET var
// and cv_usejoystick.value as the INTERNAL var
//
// In practice, if cv_usejoystick.string == 0, this overrides
// cv_usejoystick.value and always disables
//
// Update cv_usejoystick.string here so that the user can
// properly change this value.
if ( i = = cv_usejoystick . value )
CV_SetValue ( & cv_usejoystick , i ) ;
if ( i = = cv_usejoystick2 . value )
CV_SetValue ( & cv_usejoystick2 , i ) ;
2018-12-27 22:21:51 +00:00
if ( i = = cv_usejoystick3 . value )
CV_SetValue ( & cv_usejoystick3 , i ) ;
if ( i = = cv_usejoystick4 . value )
CV_SetValue ( & cv_usejoystick4 , i ) ;
2018-12-14 08:58:07 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
M_SetupNextMenu ( & OP_JoystickSetDef ) ;
}
static void M_Setup1PJoystickMenu ( INT32 choice )
{
2018-11-23 03:50:40 +00:00
setupcontrolplayer = 1 ;
2014-03-15 16:59:03 +00:00
OP_JoystickSetDef . prevMenu = & OP_Joystick1Def ;
M_SetupJoystickMenu ( choice ) ;
}
static void M_Setup2PJoystickMenu ( INT32 choice )
{
2018-11-23 03:50:40 +00:00
setupcontrolplayer = 2 ;
2014-03-15 16:59:03 +00:00
OP_JoystickSetDef . prevMenu = & OP_Joystick2Def ;
M_SetupJoystickMenu ( choice ) ;
}
2017-12-08 07:29:01 +00:00
static void M_Setup3PJoystickMenu ( INT32 choice )
{
2018-11-23 03:50:40 +00:00
setupcontrolplayer = 3 ;
2017-12-08 07:29:01 +00:00
OP_JoystickSetDef . prevMenu = & OP_Joystick3Def ;
M_SetupJoystickMenu ( choice ) ;
}
static void M_Setup4PJoystickMenu ( INT32 choice )
{
2018-12-28 00:13:13 +00:00
setupcontrolplayer = 4 ;
2017-12-08 07:29:01 +00:00
OP_JoystickSetDef . prevMenu = & OP_Joystick4Def ;
M_SetupJoystickMenu ( choice ) ;
}
2014-03-15 16:59:03 +00:00
static void M_AssignJoystick ( INT32 choice )
{
2018-12-14 10:02:41 +00:00
# ifdef JOYSTICK_HOTPLUG
2018-12-14 11:05:31 +00:00
INT32 oldchoice , oldstringchoice ;
2018-12-14 10:57:10 +00:00
INT32 numjoys = I_NumJoys ( ) ;
2018-12-14 10:02:41 +00:00
2018-11-23 03:50:40 +00:00
if ( setupcontrolplayer = = 4 )
2018-12-27 22:21:51 +00:00
{
oldchoice = oldstringchoice = atoi ( cv_usejoystick4 . string ) > numjoys ? atoi ( cv_usejoystick4 . string ) : cv_usejoystick4 . value ;
2017-12-24 13:20:58 +00:00
CV_SetValue ( & cv_usejoystick4 , choice ) ;
2018-12-27 22:21:51 +00:00
// Just in case last-minute changes were made to cv_usejoystick.value,
// update the string too
// But don't do this if we're intentionally setting higher than numjoys
if ( choice < = numjoys )
{
CV_SetValue ( & cv_usejoystick4 , cv_usejoystick4 . value ) ;
// reset this so the comparison is valid
if ( oldchoice > numjoys )
oldchoice = cv_usejoystick4 . value ;
if ( oldchoice ! = choice )
{
if ( choice & & oldstringchoice > numjoys ) // if we did not select "None", we likely selected a used device
CV_SetValue ( & cv_usejoystick4 , ( oldstringchoice > numjoys ? oldstringchoice : oldchoice ) ) ;
if ( oldstringchoice = =
( atoi ( cv_usejoystick4 . string ) > numjoys ? atoi ( cv_usejoystick4 . string ) : cv_usejoystick4 . value ) )
M_StartMessage ( " This joystick is used by another \n "
" player. Reset the joystick \n "
" for that player first. \n \n "
" (Press a key) \n " , NULL , MM_NOTHING ) ;
}
}
}
2018-11-23 03:50:40 +00:00
else if ( setupcontrolplayer = = 3 )
2018-12-27 22:21:51 +00:00
{
oldchoice = oldstringchoice = atoi ( cv_usejoystick3 . string ) > numjoys ? atoi ( cv_usejoystick3 . string ) : cv_usejoystick3 . value ;
2017-12-24 13:20:58 +00:00
CV_SetValue ( & cv_usejoystick3 , choice ) ;
2018-12-27 22:21:51 +00:00
// Just in case last-minute changes were made to cv_usejoystick.value,
// update the string too
// But don't do this if we're intentionally setting higher than numjoys
if ( choice < = numjoys )
{
CV_SetValue ( & cv_usejoystick3 , cv_usejoystick3 . value ) ;
// reset this so the comparison is valid
if ( oldchoice > numjoys )
oldchoice = cv_usejoystick3 . value ;
if ( oldchoice ! = choice )
{
if ( choice & & oldstringchoice > numjoys ) // if we did not select "None", we likely selected a used device
CV_SetValue ( & cv_usejoystick3 , ( oldstringchoice > numjoys ? oldstringchoice : oldchoice ) ) ;
if ( oldstringchoice = =
( atoi ( cv_usejoystick3 . string ) > numjoys ? atoi ( cv_usejoystick3 . string ) : cv_usejoystick3 . value ) )
M_StartMessage ( " This joystick is used by another \n "
" player. Reset the joystick \n "
" for that player first. \n \n "
" (Press a key) \n " , NULL , MM_NOTHING ) ;
}
}
}
2018-11-23 03:50:40 +00:00
else if ( setupcontrolplayer = = 2 )
2018-12-14 10:02:41 +00:00
{
2018-12-14 11:05:31 +00:00
oldchoice = oldstringchoice = atoi ( cv_usejoystick2 . string ) > numjoys ? atoi ( cv_usejoystick2 . string ) : cv_usejoystick2 . value ;
2014-03-15 16:59:03 +00:00
CV_SetValue ( & cv_usejoystick2 , choice ) ;
2018-12-14 10:02:41 +00:00
// Just in case last-minute changes were made to cv_usejoystick.value,
// update the string too
2018-12-14 10:57:10 +00:00
// But don't do this if we're intentionally setting higher than numjoys
if ( choice < = numjoys )
2018-12-14 10:02:41 +00:00
{
2018-12-14 10:57:10 +00:00
CV_SetValue ( & cv_usejoystick2 , cv_usejoystick2 . value ) ;
// reset this so the comparison is valid
if ( oldchoice > numjoys )
oldchoice = cv_usejoystick2 . value ;
if ( oldchoice ! = choice )
{
2018-12-14 11:05:31 +00:00
if ( choice & & oldstringchoice > numjoys ) // if we did not select "None", we likely selected a used device
CV_SetValue ( & cv_usejoystick2 , ( oldstringchoice > numjoys ? oldstringchoice : oldchoice ) ) ;
2018-12-14 10:57:10 +00:00
2018-12-14 11:05:31 +00:00
if ( oldstringchoice = =
2018-12-14 10:57:10 +00:00
( atoi ( cv_usejoystick2 . string ) > numjoys ? atoi ( cv_usejoystick2 . string ) : cv_usejoystick2 . value ) )
M_StartMessage ( " This joystick is used by another \n "
" player. Reset the joystick \n "
" for that player first. \n \n "
" (Press a key) \n " , NULL , MM_NOTHING ) ;
}
2018-12-14 10:02:41 +00:00
}
}
2018-12-27 22:21:51 +00:00
else if ( setupcontrolplayer = = 1 )
2018-12-14 10:02:41 +00:00
{
2018-12-14 11:05:31 +00:00
oldchoice = oldstringchoice = atoi ( cv_usejoystick . string ) > numjoys ? atoi ( cv_usejoystick . string ) : cv_usejoystick . value ;
2014-03-15 16:59:03 +00:00
CV_SetValue ( & cv_usejoystick , choice ) ;
2018-12-14 10:02:41 +00:00
// Just in case last-minute changes were made to cv_usejoystick.value,
// update the string too
2018-12-14 10:57:10 +00:00
// But don't do this if we're intentionally setting higher than numjoys
if ( choice < = numjoys )
2018-12-14 10:02:41 +00:00
{
2018-12-14 10:57:10 +00:00
CV_SetValue ( & cv_usejoystick , cv_usejoystick . value ) ;
// reset this so the comparison is valid
if ( oldchoice > numjoys )
oldchoice = cv_usejoystick . value ;
if ( oldchoice ! = choice )
{
2018-12-14 11:05:31 +00:00
if ( choice & & oldstringchoice > numjoys ) // if we did not select "None", we likely selected a used device
CV_SetValue ( & cv_usejoystick , ( oldstringchoice > numjoys ? oldstringchoice : oldchoice ) ) ;
2018-12-14 10:57:10 +00:00
2018-12-14 11:05:31 +00:00
if ( oldstringchoice = =
2018-12-14 10:57:10 +00:00
( atoi ( cv_usejoystick . string ) > numjoys ? atoi ( cv_usejoystick . string ) : cv_usejoystick . value ) )
M_StartMessage ( " This joystick is used by another \n "
" player. Reset the joystick \n "
" for that player first. \n \n "
" (Press a key) \n " , NULL , MM_NOTHING ) ;
}
2018-12-14 10:02:41 +00:00
}
}
# else
2018-12-27 22:21:51 +00:00
if ( setupcontrolplayer = = 4 )
CV_SetValue ( & cv_usejoystick4 , choice ) ;
else if ( setupcontrolplayer = = 3 )
CV_SetValue ( & cv_usejoystick3 , choice ) ;
else if ( setupcontrolplayer = = 2 )
2018-12-14 10:02:41 +00:00
CV_SetValue ( & cv_usejoystick2 , choice ) ;
2018-12-27 22:21:51 +00:00
else if ( setupcontrolplayer = = 1 )
2018-12-14 10:02:41 +00:00
CV_SetValue ( & cv_usejoystick , choice ) ;
# endif
2014-03-15 16:59:03 +00:00
}
// =============
// CONTROLS MENU
// =============
static void M_Setup1PControlsMenu ( INT32 choice )
{
( void ) choice ;
2018-11-23 03:50:40 +00:00
setupcontrolplayer = 1 ;
2014-03-15 16:59:03 +00:00
setupcontrols = gamecontrol ; // was called from main Options (for console player, then)
currentMenu - > lastOn = itemOn ;
2018-09-27 20:55:21 +00:00
// Set proper gamepad options
2018-11-26 08:12:22 +00:00
OP_AllControlsMenu [ 0 ] . itemaction = & OP_Joystick1Def ;
2018-06-30 15:01:03 +00:00
2018-09-27 20:55:21 +00:00
// Unhide P1-only controls
2018-11-23 03:50:40 +00:00
OP_AllControlsMenu [ 15 ] . status = IT_CONTROL ; // Chat
//OP_AllControlsMenu[16].status = IT_CONTROL; // Team-chat
OP_AllControlsMenu [ 16 ] . status = IT_CONTROL ; // Rankings
2019-02-02 01:53:52 +00:00
//OP_AllControlsMenu[17].status = IT_CONTROL; // Viewpoint
2018-11-23 03:50:40 +00:00
// 18 is Reset Camera, 19 is Toggle Chasecam
OP_AllControlsMenu [ 20 ] . status = IT_CONTROL ; // Pause
OP_AllControlsMenu [ 21 ] . status = IT_CONTROL ; // Screenshot
OP_AllControlsMenu [ 22 ] . status = IT_CONTROL ; // GIF
OP_AllControlsMenu [ 23 ] . status = IT_CONTROL ; // System Menu
OP_AllControlsMenu [ 24 ] . status = IT_CONTROL ; // Console
/*OP_AllControlsMenu[25].status = IT_HEADER; // Spectator Controls header
OP_AllControlsMenu [ 26 ] . status = IT_SPACE ; // Spectator Controls space
OP_AllControlsMenu [ 27 ] . status = IT_CONTROL ; // Spectate
OP_AllControlsMenu [ 28 ] . status = IT_CONTROL ; // Look Up
OP_AllControlsMenu [ 29 ] . status = IT_CONTROL ; // Look Down
OP_AllControlsMenu [ 30 ] . status = IT_CONTROL ; // Center View
2018-10-16 00:31:26 +00:00
*/
2018-09-27 20:55:21 +00:00
M_SetupNextMenu ( & OP_AllControlsDef ) ;
2014-03-15 16:59:03 +00:00
}
static void M_Setup2PControlsMenu ( INT32 choice )
{
( void ) choice ;
2018-11-23 03:50:40 +00:00
setupcontrolplayer = 2 ;
2014-03-15 16:59:03 +00:00
setupcontrols = gamecontrolbis ;
currentMenu - > lastOn = itemOn ;
2018-09-27 20:55:21 +00:00
// Set proper gamepad options
2018-11-26 08:12:22 +00:00
OP_AllControlsMenu [ 0 ] . itemaction = & OP_Joystick2Def ;
2014-03-15 16:59:03 +00:00
2018-09-27 20:55:21 +00:00
// Hide P1-only controls
2018-11-23 03:50:40 +00:00
OP_AllControlsMenu [ 15 ] . status = IT_GRAYEDOUT2 ; // Chat
//OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat
OP_AllControlsMenu [ 16 ] . status = IT_GRAYEDOUT2 ; // Rankings
2019-02-02 01:53:52 +00:00
//OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint
2018-11-23 03:50:40 +00:00
// 18 is Reset Camera, 19 is Toggle Chasecam
OP_AllControlsMenu [ 20 ] . status = IT_GRAYEDOUT2 ; // Pause
OP_AllControlsMenu [ 21 ] . status = IT_GRAYEDOUT2 ; // Screenshot
OP_AllControlsMenu [ 22 ] . status = IT_GRAYEDOUT2 ; // GIF
OP_AllControlsMenu [ 23 ] . status = IT_GRAYEDOUT2 ; // System Menu
OP_AllControlsMenu [ 24 ] . status = IT_GRAYEDOUT2 ; // Console
/*OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Spectator Controls header
OP_AllControlsMenu [ 26 ] . status = IT_GRAYEDOUT2 ; // Spectator Controls space
OP_AllControlsMenu [ 27 ] . status = IT_GRAYEDOUT2 ; // Spectate
OP_AllControlsMenu [ 28 ] . status = IT_GRAYEDOUT2 ; // Look Up
OP_AllControlsMenu [ 29 ] . status = IT_GRAYEDOUT2 ; // Look Down
OP_AllControlsMenu [ 30 ] . status = IT_GRAYEDOUT2 ; // Center View
2018-10-16 00:31:26 +00:00
*/
2018-09-27 20:55:21 +00:00
M_SetupNextMenu ( & OP_AllControlsDef ) ;
2014-03-15 16:59:03 +00:00
}
2017-12-08 07:29:01 +00:00
static void M_Setup3PControlsMenu ( INT32 choice )
{
( void ) choice ;
2018-11-23 03:50:40 +00:00
setupcontrolplayer = 3 ;
2017-12-11 06:12:38 +00:00
setupcontrols = gamecontrol3 ;
2017-12-08 07:29:01 +00:00
currentMenu - > lastOn = itemOn ;
2018-09-27 20:55:21 +00:00
// Set proper gamepad options
2018-11-26 08:12:22 +00:00
OP_AllControlsMenu [ 0 ] . itemaction = & OP_Joystick3Def ;
2017-12-08 07:29:01 +00:00
2018-09-27 20:55:21 +00:00
// Hide P1-only controls
2018-11-23 03:50:40 +00:00
OP_AllControlsMenu [ 15 ] . status = IT_GRAYEDOUT2 ; // Chat
//OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat
OP_AllControlsMenu [ 16 ] . status = IT_GRAYEDOUT2 ; // Rankings
2019-02-02 01:53:52 +00:00
//OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint
2018-11-23 03:50:40 +00:00
// 18 is Reset Camera, 19 is Toggle Chasecam
OP_AllControlsMenu [ 20 ] . status = IT_GRAYEDOUT2 ; // Pause
OP_AllControlsMenu [ 21 ] . status = IT_GRAYEDOUT2 ; // Screenshot
OP_AllControlsMenu [ 22 ] . status = IT_GRAYEDOUT2 ; // GIF
OP_AllControlsMenu [ 23 ] . status = IT_GRAYEDOUT2 ; // System Menu
OP_AllControlsMenu [ 24 ] . status = IT_GRAYEDOUT2 ; // Console
/*OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Spectator Controls header
OP_AllControlsMenu [ 26 ] . status = IT_GRAYEDOUT2 ; // Spectator Controls space
OP_AllControlsMenu [ 27 ] . status = IT_GRAYEDOUT2 ; // Spectate
OP_AllControlsMenu [ 28 ] . status = IT_GRAYEDOUT2 ; // Look Up
OP_AllControlsMenu [ 29 ] . status = IT_GRAYEDOUT2 ; // Look Down
OP_AllControlsMenu [ 30 ] . status = IT_GRAYEDOUT2 ; // Center View
2018-10-16 00:31:26 +00:00
*/
2018-09-27 20:55:21 +00:00
M_SetupNextMenu ( & OP_AllControlsDef ) ;
2017-12-08 07:29:01 +00:00
}
static void M_Setup4PControlsMenu ( INT32 choice )
{
( void ) choice ;
2018-11-23 03:50:40 +00:00
setupcontrolplayer = 4 ;
2017-12-11 06:12:38 +00:00
setupcontrols = gamecontrol4 ;
2017-12-08 07:29:01 +00:00
currentMenu - > lastOn = itemOn ;
2018-09-27 20:55:21 +00:00
// Set proper gamepad options
2018-11-26 08:12:22 +00:00
OP_AllControlsMenu [ 0 ] . itemaction = & OP_Joystick4Def ;
2018-06-30 15:01:03 +00:00
2018-09-27 20:55:21 +00:00
// Hide P1-only controls
2018-11-23 03:50:40 +00:00
OP_AllControlsMenu [ 15 ] . status = IT_GRAYEDOUT2 ; // Chat
//OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat
OP_AllControlsMenu [ 16 ] . status = IT_GRAYEDOUT2 ; // Rankings
2019-02-02 01:53:52 +00:00
//OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint
2018-11-23 03:50:40 +00:00
// 18 is Reset Camera, 19 is Toggle Chasecam
OP_AllControlsMenu [ 20 ] . status = IT_GRAYEDOUT2 ; // Pause
OP_AllControlsMenu [ 21 ] . status = IT_GRAYEDOUT2 ; // Screenshot
OP_AllControlsMenu [ 22 ] . status = IT_GRAYEDOUT2 ; // GIF
OP_AllControlsMenu [ 23 ] . status = IT_GRAYEDOUT2 ; // System Menu
OP_AllControlsMenu [ 24 ] . status = IT_GRAYEDOUT2 ; // Console
/*OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Spectator Controls header
OP_AllControlsMenu [ 26 ] . status = IT_GRAYEDOUT2 ; // Spectator Controls space
OP_AllControlsMenu [ 27 ] . status = IT_GRAYEDOUT2 ; // Spectate
OP_AllControlsMenu [ 28 ] . status = IT_GRAYEDOUT2 ; // Look Up
OP_AllControlsMenu [ 29 ] . status = IT_GRAYEDOUT2 ; // Look Down
OP_AllControlsMenu [ 30 ] . status = IT_GRAYEDOUT2 ; // Center View
2018-10-16 00:31:26 +00:00
*/
2018-09-27 20:55:21 +00:00
M_SetupNextMenu ( & OP_AllControlsDef ) ;
2017-12-08 07:29:01 +00:00
}
2018-09-27 20:55:21 +00:00
# define controlheight 18
2014-03-15 16:59:03 +00:00
// Draws the Customise Controls menu
static void M_DrawControl ( void )
{
2018-10-09 19:28:52 +00:00
char tmp [ 50 ] ;
INT32 x , y , i , max , cursory = 0 , iter ;
INT32 keys [ 2 ] ;
2014-03-15 16:59:03 +00:00
2018-10-09 19:28:52 +00:00
x = currentMenu - > x ;
y = currentMenu - > y ;
2014-03-15 16:59:03 +00:00
2018-10-09 19:28:52 +00:00
/*i = itemOn - (controlheight/2);
if ( i < 0 )
i = 0 ;
*/
2018-06-30 15:01:03 +00:00
2018-10-09 19:28:52 +00:00
iter = ( controlheight / 2 ) ;
for ( i = itemOn ; ( ( iter | | currentMenu - > menuitems [ i ] . status = = IT_GRAYEDOUT2 ) & & i > 0 ) ; i - - )
{
if ( currentMenu - > menuitems [ i ] . status ! = IT_GRAYEDOUT2 )
iter - - ;
}
if ( currentMenu - > menuitems [ i ] . status = = IT_GRAYEDOUT2 )
i - - ;
2017-12-18 10:56:38 +00:00
2018-10-09 19:28:52 +00:00
iter + = ( controlheight / 2 ) ;
for ( max = itemOn ; ( iter & & max < currentMenu - > numitems ) ; max + + )
{
if ( currentMenu - > menuitems [ max ] . status ! = IT_GRAYEDOUT2 )
iter - - ;
}
2014-03-15 16:59:03 +00:00
2018-10-09 19:28:52 +00:00
if ( iter )
2014-03-15 16:59:03 +00:00
{
2018-10-09 19:28:52 +00:00
iter + = ( controlheight / 2 ) ;
for ( i = itemOn ; ( ( iter | | currentMenu - > menuitems [ i ] . status = = IT_GRAYEDOUT2 ) & & i > 0 ) ; i - - )
2018-06-30 15:01:03 +00:00
{
2018-10-09 19:28:52 +00:00
if ( currentMenu - > menuitems [ i ] . status ! = IT_GRAYEDOUT2 )
iter - - ;
2018-06-30 15:01:03 +00:00
}
2018-10-09 19:28:52 +00:00
}
/*max = i + controlheight;
if ( max > currentMenu - > numitems )
{
max = currentMenu - > numitems ;
if ( max < controlheight )
i = 0 ;
else
i = max - controlheight ;
} */
// draw title (or big pic)
M_DrawMenuTitle ( ) ;
M_CentreText ( 28 ,
2018-11-26 08:12:22 +00:00
( setupcontrolplayer > 1 ? va ( " \x86 " " Set controls for " " \x82 " " Player %d " , setupcontrolplayer ) :
" \x86 " " Press " " \x82 " " ENTER " " \x86 " " to change, " " \x82 " " BACKSPACE " " \x86 " " to clear " ) ) ;
2018-10-09 19:28:52 +00:00
if ( i )
2018-10-16 21:11:47 +00:00
V_DrawCharacter ( currentMenu - > x - 16 , y - ( skullAnimCounter / 5 ) ,
' \x1A ' | highlightflags , false ) ; // up arrow
2018-10-09 19:28:52 +00:00
if ( max ! = currentMenu - > numitems )
2018-10-16 21:11:47 +00:00
V_DrawCharacter ( currentMenu - > x - 16 , y + ( SMALLLINEHEIGHT * ( controlheight - 1 ) ) + ( skullAnimCounter / 5 ) + ( skullAnimCounter / 5 ) ,
' \x1B ' | highlightflags , false ) ; // down arrow
2018-10-09 19:28:52 +00:00
for ( ; i < max ; i + + )
{
if ( currentMenu - > menuitems [ i ] . status = = IT_GRAYEDOUT2 )
2014-03-15 16:59:03 +00:00
continue ;
2018-10-09 19:28:52 +00:00
if ( i = = itemOn )
cursory = y ;
2014-03-15 16:59:03 +00:00
2018-10-09 19:28:52 +00:00
if ( currentMenu - > menuitems [ i ] . status = = IT_CONTROL )
2014-03-15 16:59:03 +00:00
{
2018-10-09 19:28:52 +00:00
V_DrawString ( x , y , ( ( i = = itemOn ) ? highlightflags : 0 ) , currentMenu - > menuitems [ i ] . text ) ;
keys [ 0 ] = setupcontrols [ currentMenu - > menuitems [ i ] . alphaKey ] [ 0 ] ;
keys [ 1 ] = setupcontrols [ currentMenu - > menuitems [ i ] . alphaKey ] [ 1 ] ;
2014-03-15 16:59:03 +00:00
2018-10-09 19:28:52 +00:00
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 ] ) ) ;
2014-03-15 16:59:03 +00:00
2018-10-09 19:28:52 +00:00
if ( keys [ 0 ] ! = KEY_NULL & & keys [ 1 ] ! = KEY_NULL )
strcat ( tmp , " , " ) ;
2014-03-15 16:59:03 +00:00
2018-10-09 19:28:52 +00:00
if ( keys [ 1 ] ! = KEY_NULL )
strcat ( tmp , G_KeynumToString ( keys [ 1 ] ) ) ;
2014-03-15 16:59:03 +00:00
2018-10-09 19:28:52 +00:00
}
V_DrawRightAlignedString ( BASEVIDWIDTH - currentMenu - > x , y , highlightflags , tmp ) ;
2014-03-15 16:59:03 +00:00
}
2018-10-09 19:28:52 +00:00
/*else if (currentMenu->menuitems[i].status == IT_GRAYEDOUT2)
V_DrawString ( x , y , V_TRANSLUCENT , currentMenu - > menuitems [ i ] . text ) ; */
else if ( ( currentMenu - > menuitems [ i ] . status = = IT_HEADER ) & & ( i ! = max - 1 ) )
2018-09-27 20:55:21 +00:00
V_DrawString ( 19 , y + 6 , highlightflags , currentMenu - > menuitems [ i ] . text ) ;
else if ( currentMenu - > menuitems [ i ] . status & IT_STRING )
V_DrawString ( x , y , ( ( i = = itemOn ) ? highlightflags : 0 ) , currentMenu - > menuitems [ i ] . text ) ;
2018-06-30 15:01:03 +00:00
y + = SMALLLINEHEIGHT ;
2014-03-15 16:59:03 +00:00
}
2018-09-27 20:55:21 +00:00
2018-10-09 19:28:52 +00:00
V_DrawScaledPatch ( currentMenu - > x - 20 , cursory , 0 ,
W_CachePatchName ( " M_CURSOR " , PU_CACHE ) ) ;
2014-03-15 16:59:03 +00:00
}
2018-09-27 21:17:04 +00:00
# undef controlheight
2014-03-15 16:59:03 +00:00
static INT32 controltochange ;
2018-12-31 06:26:25 +00:00
static char controltochangetext [ 33 ] ;
2014-03-15 16:59:03 +00:00
static void M_ChangecontrolResponse ( event_t * ev )
{
INT32 control ;
INT32 found ;
INT32 ch = ev - > data1 ;
2018-11-21 04:43:05 +00:00
// ESCAPE cancels; dummy out PAUSE
if ( ch ! = KEY_ESCAPE & & ch ! = KEY_PAUSE )
2014-03-15 16:59:03 +00:00
{
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
}
2018-12-20 09:04:49 +00:00
( void ) G_CheckDoubleUsage ( ch , true ) ;
2014-03-15 16:59:03 +00:00
setupcontrols [ control ] [ found ] = ch ;
}
2018-11-14 01:27:01 +00:00
S_StartSound ( NULL , sfx_s221 ) ;
2014-03-15 16:59:03 +00:00
}
2018-11-21 04:43:05 +00:00
else if ( ch = = KEY_PAUSE )
{
2019-01-05 00:38:36 +00:00
// This buffer assumes a 125-character message plus a 32-character control name (per controltochangetext buffer size)
static char tmp [ 158 ] ;
2018-11-21 04:43:05 +00:00
menu_t * prev = currentMenu - > prevMenu ;
if ( controltochange = = gc_pause )
sprintf ( tmp , M_GetText ( " The \x82 Pause Key \x80 is enabled, but \n you may select another key. \n \n Hit another key for \n %s \n ESC for Cancel " ) ,
controltochangetext ) ;
else
sprintf ( tmp , M_GetText ( " The \x82 Pause Key \x80 is enabled, but \n it is not configurable. \n \n Hit another key for \n %s \n ESC for Cancel " ) ,
controltochangetext ) ;
2014-03-15 16:59:03 +00:00
2018-11-21 04:43:05 +00:00
M_StartMessage ( tmp , M_ChangecontrolResponse , MM_EVENTHANDLER ) ;
currentMenu - > prevMenu = prev ;
2014-03-15 16:59:03 +00:00
2018-11-21 04:43:05 +00:00
S_StartSound ( NULL , sfx_s3k42 ) ;
return ;
2014-03-15 16:59:03 +00:00
}
2018-09-29 15:18:16 +00:00
else
2018-11-14 01:27:01 +00:00
S_StartSound ( NULL , sfx_s224 ) ;
2014-03-15 16:59:03 +00:00
M_StopMessage ( 0 ) ;
}
static void M_ChangeControl ( INT32 choice )
{
2018-12-31 06:26:25 +00:00
// This buffer assumes a 35-character message (per below) plus a max control name limit of 32 chars (per controltochangetext)
// If you change the below message, then change the size of this buffer!
static char tmp [ 68 ] ;
2014-03-15 16:59:03 +00:00
controltochange = currentMenu - > menuitems [ choice ] . alphaKey ;
sprintf ( tmp , M_GetText ( " Hit the new key for \n %s \n ESC for Cancel " ) ,
currentMenu - > menuitems [ choice ] . text ) ;
2018-12-31 06:26:25 +00:00
strlcpy ( controltochangetext , currentMenu - > menuitems [ choice ] . text , 33 ) ;
2014-03-15 16:59:03 +00:00
M_StartMessage ( tmp , M_ChangecontrolResponse , MM_EVENTHANDLER ) ;
}
2018-11-26 08:12:22 +00:00
static void M_ResetControlsResponse ( INT32 ch )
2018-11-23 03:50:40 +00:00
{
INT32 i ;
2018-11-26 08:12:22 +00:00
if ( ch ! = ' y ' & & ch ! = KEY_ENTER )
return ;
2018-11-23 03:50:40 +00:00
// clear all controls
for ( i = 0 ; i < num_gamecontrols ; i + + )
{
switch ( setupcontrolplayer )
{
case 4 :
G_ClearControlKeys ( gamecontrol4 , i ) ;
break ;
case 3 :
G_ClearControlKeys ( gamecontrol3 , i ) ;
break ;
case 2 :
G_ClearControlKeys ( gamecontrolbis , i ) ;
break ;
case 1 :
default :
G_ClearControlKeys ( gamecontrol , i ) ;
break ;
}
}
// Setup original defaults
G_Controldefault ( setupcontrolplayer ) ;
// Setup gamepad option defaults (yucky)
switch ( setupcontrolplayer )
{
case 4 :
CV_StealthSet ( & cv_usejoystick4 , cv_usejoystick4 . defaultvalue ) ;
CV_StealthSet ( & cv_turnaxis4 , cv_turnaxis4 . defaultvalue ) ;
CV_StealthSet ( & cv_moveaxis4 , cv_moveaxis4 . defaultvalue ) ;
CV_StealthSet ( & cv_brakeaxis4 , cv_brakeaxis4 . defaultvalue ) ;
CV_StealthSet ( & cv_aimaxis4 , cv_aimaxis4 . defaultvalue ) ;
CV_StealthSet ( & cv_lookaxis4 , cv_lookaxis4 . defaultvalue ) ;
CV_StealthSet ( & cv_fireaxis4 , cv_fireaxis4 . defaultvalue ) ;
CV_StealthSet ( & cv_driftaxis4 , cv_driftaxis4 . defaultvalue ) ;
break ;
case 3 :
CV_StealthSet ( & cv_usejoystick3 , cv_usejoystick3 . defaultvalue ) ;
CV_StealthSet ( & cv_turnaxis3 , cv_turnaxis3 . defaultvalue ) ;
CV_StealthSet ( & cv_moveaxis3 , cv_moveaxis3 . defaultvalue ) ;
CV_StealthSet ( & cv_brakeaxis3 , cv_brakeaxis3 . defaultvalue ) ;
CV_StealthSet ( & cv_aimaxis3 , cv_aimaxis3 . defaultvalue ) ;
CV_StealthSet ( & cv_lookaxis3 , cv_lookaxis3 . defaultvalue ) ;
CV_StealthSet ( & cv_fireaxis3 , cv_fireaxis3 . defaultvalue ) ;
CV_StealthSet ( & cv_driftaxis3 , cv_driftaxis3 . defaultvalue ) ;
break ;
case 2 :
CV_StealthSet ( & cv_usejoystick2 , cv_usejoystick2 . defaultvalue ) ;
CV_StealthSet ( & cv_turnaxis2 , cv_turnaxis2 . defaultvalue ) ;
CV_StealthSet ( & cv_moveaxis2 , cv_moveaxis2 . defaultvalue ) ;
CV_StealthSet ( & cv_brakeaxis2 , cv_brakeaxis2 . defaultvalue ) ;
CV_StealthSet ( & cv_aimaxis2 , cv_aimaxis2 . defaultvalue ) ;
CV_StealthSet ( & cv_lookaxis2 , cv_lookaxis2 . defaultvalue ) ;
CV_StealthSet ( & cv_fireaxis2 , cv_fireaxis2 . defaultvalue ) ;
CV_StealthSet ( & cv_driftaxis2 , cv_driftaxis2 . defaultvalue ) ;
break ;
case 1 :
default :
CV_StealthSet ( & cv_usejoystick , cv_usejoystick . defaultvalue ) ;
CV_StealthSet ( & cv_turnaxis , cv_turnaxis . defaultvalue ) ;
CV_StealthSet ( & cv_moveaxis , cv_moveaxis . defaultvalue ) ;
CV_StealthSet ( & cv_brakeaxis , cv_brakeaxis . defaultvalue ) ;
CV_StealthSet ( & cv_aimaxis , cv_aimaxis . defaultvalue ) ;
CV_StealthSet ( & cv_lookaxis , cv_lookaxis . defaultvalue ) ;
CV_StealthSet ( & cv_fireaxis , cv_fireaxis . defaultvalue ) ;
CV_StealthSet ( & cv_driftaxis , cv_driftaxis . defaultvalue ) ;
break ;
}
S_StartSound ( NULL , sfx_s224 ) ;
}
2018-11-26 08:12:22 +00:00
static void M_ResetControls ( INT32 choice )
{
( void ) choice ;
M_StartMessage ( va ( M_GetText ( " Reset Player %d's controls to defaults? \n \n (Press 'Y' to confirm) \n " ) , setupcontrolplayer ) , M_ResetControlsResponse , MM_YESNO ) ;
}
2014-03-15 16:59:03 +00:00
// =====
// SOUND
// =====
2018-10-22 21:24:58 +00:00
/*static void M_RestartAudio(void)
2018-06-15 00:18:29 +00:00
{
2018-10-22 20:32:06 +00:00
COM_ImmedExecute ( " restartaudio " ) ;
2018-10-22 21:24:58 +00:00
} */
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 ;
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
{
2018-11-14 01:27:01 +00:00
//S_StartSound(NULL, sfx_s26d);
2018-09-20 16:45:09 +00:00
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!
2018-11-14 01:30:26 +00:00
// srb2kart: you ain't seen nothing yet
sfx_kc2e ,
sfx_kc2f ,
sfx_cdfm01 ,
sfx_ddash ,
sfx_s3ka2 ,
sfx_s3k49 ,
sfx_slip ,
sfx_tossed ,
sfx_s3k7b ,
sfx_itrolf ,
sfx_itrole ,
sfx_cdpcm9 ,
sfx_s3k4e ,
sfx_s259 ,
sfx_3db06 ,
sfx_s3k3a ,
sfx_peel ,
sfx_cdfm28 ,
sfx_s3k96 ,
sfx_s3kc0s ,
sfx_cdfm39 ,
sfx_hogbom ,
sfx_kc5a ,
sfx_kc46 ,
sfx_s3k92 ,
sfx_s3k42 ,
sfx_kpogos ,
sfx_screec
2014-03-15 16:59:03 +00:00
} ;
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-11-05 12:52:15 +00:00
V_DrawFill ( 0 , 0 , BASEVIDWIDTH , BASEVIDHEIGHT , 31 ) ;
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