diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2cd9bb662b..028b5bd3bc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -954,6 +954,7 @@ set (PCH_SOURCES maploader/renderinfo.cpp maploader/compatibility.cpp maploader/postprocessor.cpp + menu/doommenu.cpp menu/joystickmenu.cpp menu/loadsavemenu.cpp menu/menu.cpp diff --git a/src/common/engine/i_interface.h b/src/common/engine/i_interface.h index 5bd03dd0b6..f5fed4531d 100644 --- a/src/common/engine/i_interface.h +++ b/src/common/engine/i_interface.h @@ -17,6 +17,7 @@ struct SystemCallbacks void (*OnScreenSizeChanged)(); IntRect(*GetSceneRect)(); FString(*GetLocationDescription)(); + void (*MenuDim)(); }; extern SystemCallbacks *sysCallbacks; diff --git a/src/console/c_cmds.cpp b/src/console/c_cmds.cpp index a4b868963a..3f697465f6 100644 --- a/src/console/c_cmds.cpp +++ b/src/console/c_cmds.cpp @@ -77,6 +77,11 @@ CVAR (Bool, sv_cheats, false, CVAR_SERVERINFO | CVAR_LATCH) CVAR (Bool, sv_unlimited_pickup, false, CVAR_SERVERINFO) CVAR (Int, cl_blockcheats, 0, 0) +CVAR(Float, mouse_sensitivity, 1.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Bool, show_messages, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Bool, show_obituaries, true, CVAR_ARCHIVE) + + CCMD (toggleconsole) { C_ToggleConsole(); diff --git a/src/d_main.cpp b/src/d_main.cpp index 3ff6d9f6b0..622b9ccdcc 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -189,9 +189,10 @@ EXTERN_CVAR(Bool, ticker) extern bool setmodeneeded; extern bool demorecording; -extern bool M_DemoNoPlay; // [RH] if true, then skip any demos in the loop +bool M_DemoNoPlay; // [RH] if true, then skip any demos in the loop extern bool insave; extern TDeletingArray LightDefaults; +extern FName MessageBoxClass; const char* iwad_folders[13] = { "flats/", "textures/", "hires/", "sprites/", "voxels/", "colormaps/", "acs/", "maps/", "voices/", "patches/", "graphics/", "sounds/", "music/" }; const char* iwad_reserved[12] = { "mapinfo", "zmapinfo", "gameinfo", "sndinfo", "sbarinfo", "menudef", "gldefs", "animdefs", "decorate", "zscript", "iwadinfo", "maps/" }; @@ -2875,6 +2876,7 @@ void System_CrashInfo(char* buffer, size_t bufflen, const char *lfstr) *buffer = 0; } +void System_M_Dim(); static void PatchTextures() @@ -3032,6 +3034,7 @@ static int D_DoomMain_Internal (void) System_OnScreenSizeChanged, System_GetSceneRect, System_GetLocationDescription, + System_M_Dim, }; sysCallbacks = &syscb; @@ -3328,6 +3331,7 @@ static int D_DoomMain_Internal (void) // [RH] Parse through all loaded mapinfo lumps if (!batchrun) Printf ("G_ParseMapInfo: Load map definitions.\n"); G_ParseMapInfo (iwad_info->MapInfo); + MessageBoxClass = gameinfo.MessageBoxClass; ReadStatistics(); // MUSINFO must be parsed after MAPINFO diff --git a/src/g_game.cpp b/src/g_game.cpp index aa15419c5c..b65b95f637 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -83,6 +83,7 @@ #include "c_buttons.h" #include "d_buttons.h" #include "hwrenderer/scene/hw_drawinfo.h" +#include "doommenu.h" static FRandom pr_dmspawn ("DMSpawn"); diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 08c43a9e74..bbb4511caa 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -54,6 +54,7 @@ #include "s_music.h" #include "texturemanager.h" #include "v_draw.h" +#include "doommenu.h" FIntermissionDescriptorList IntermissionDescriptors; diff --git a/src/menu/doommenu.cpp b/src/menu/doommenu.cpp new file mode 100644 index 0000000000..86c0ff512a --- /dev/null +++ b/src/menu/doommenu.cpp @@ -0,0 +1,499 @@ +/* +** menu.cpp +** Menu base class and global interface +** +**--------------------------------------------------------------------------- +** Copyright 2010 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "c_dispatch.h" +#include "d_gui.h" +#include "c_buttons.h" +#include "c_console.h" +#include "c_bind.h" +#include "d_eventbase.h" +#include "g_input.h" +#include "configfile.h" +#include "gstrings.h" +#include "menu.h" +#include "vm.h" +#include "v_video.h" +#include "i_system.h" +#include "types.h" +#include "texturemanager.h" +#include "v_draw.h" +#include "vm.h" +#include "gamestate.h" +#include "i_interface.h" +#include "gi.h" +#include "g_game.h" +#include "g_level.h" +#include "d_event.h" +#include "p_tick.h" +#include "st_start.h" +#include "d_main.h" +#include "i_system.h" +#include "doommenu.h" +#include "r_utility.h" +#include "gameconfigfile.h" + +EXTERN_CVAR(Int, cl_gfxlocalization) +EXTERN_CVAR(Bool, m_quickexit) +EXTERN_CVAR(Bool, saveloadconfirmation) // [mxd] +EXTERN_CVAR(Bool, quicksaverotation) +EXTERN_CVAR(Bool, show_messages) + +typedef void(*hfunc)(); +DMenu* CreateMessageBoxMenu(DMenu* parent, const char* message, int messagemode, bool playsound, FName action = NAME_None, hfunc handler = nullptr); +bool OkForLocalization(FTextureID texnum, const char* substitute); +void D_ToggleHud(); +void I_WaitVBL(int count); + +extern bool hud_toggled; + + +FNewGameStartup NewGameStartupInfo; + + +bool M_SetSpecialMenu(FName menu, int param) +{ + // some menus need some special treatment + switch (menu.GetIndex()) + { + case NAME_Mainmenu: + if (gameinfo.gametype & GAME_DoomStrifeChex) // Raven's games always used text based menus + { + if (gameinfo.forcetextinmenus) // If text is forced, this overrides any check. + { + menu = NAME_MainmenuTextOnly; + } + else if (cl_gfxlocalization != 0 && !gameinfo.forcenogfxsubstitution) + { + // For these games we must check up-front if they get localized because in that case another template must be used. + DMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_Mainmenu); + if (desc != nullptr) + { + if ((*desc)->IsKindOf(RUNTIME_CLASS(DListMenuDescriptor))) + { + DListMenuDescriptor *ld = static_cast(*desc); + if (ld->mFromEngine) + { + // This assumes that replacing one graphic will replace all of them. + // So this only checks the "New game" entry for localization capability. + FTextureID texid = TexMan.CheckForTexture("M_NGAME", ETextureType::MiscPatch); + if (!OkForLocalization(texid, "$MNU_NEWGAME")) + { + menu = NAME_MainmenuTextOnly; + } + } + } + } + } + } + break; + case NAME_Episodemenu: + // sent from the player class menu + NewGameStartupInfo.Skill = -1; + NewGameStartupInfo.Episode = -1; + NewGameStartupInfo.PlayerClass = + param == -1000? nullptr : + param == -1? "Random" : GetPrintableDisplayName(PlayerClasses[param].Type).GetChars(); + M_StartupEpisodeMenu(&NewGameStartupInfo); // needs player class name from class menu (later) + break; + + case NAME_Skillmenu: + // sent from the episode menu + + if ((gameinfo.flags & GI_SHAREWARE) && param > 0) + { + // Only Doom and Heretic have multi-episode shareware versions. + M_StartMessage(GStrings("SWSTRING"), 1); + return false; + } + + NewGameStartupInfo.Episode = param; + M_StartupSkillMenu(&NewGameStartupInfo); // needs player class name from class menu (later) + break; + + case NAME_StartgameConfirm: + { + // sent from the skill menu for a skill that needs to be confirmed + NewGameStartupInfo.Skill = param; + + const char *msg = AllSkills[param].MustConfirmText; + if (*msg==0) msg = GStrings("NIGHTMARE"); + M_StartMessage (msg, 0, NAME_StartgameConfirmed); + return false; + } + + case NAME_Startgame: + // sent either from skill menu or confirmation screen. Skill gets only set if sent from skill menu + // Now we can finally start the game. Ugh... + NewGameStartupInfo.Skill = param; + case NAME_StartgameConfirmed: + + G_DeferedInitNew (&NewGameStartupInfo); + if (gamestate == GS_FULLCONSOLE) + { + gamestate = GS_HIDECONSOLE; + gameaction = ga_newgame; + } + M_ClearMenus (); + return false; + + case NAME_Savegamemenu: + if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer) || gamestate != GS_LEVEL) + { + // cannot save outside the game. + M_StartMessage (GStrings("SAVEDEAD"), 1); + return false; + } + + case NAME_Quitmenu: + // The separate menu class no longer exists but the name still needs support for existing mods. + C_DoCommand("menu_quit"); + return false; + + case NAME_EndGameMenu: + // The separate menu class no longer exists but the name still needs support for existing mods. + void ActivateEndGameMenu(); + ActivateEndGameMenu(); + return false; + + case NAME_Playermenu: + menu = NAME_NewPlayerMenu; // redirect the old player menu to the new one. + break; + } + + // End of special checks + return true; +} + +//============================================================================= +// +// +// +//============================================================================= + +void M_StartControlPanel(bool makeSound, bool scaleoverride) +{ + if (hud_toggled) + D_ToggleHud(); + + // intro might call this repeatedly + if (CurrentMenu != nullptr) + return; + + P_CheckTickerPaused(); + + if (makeSound) + { + S_Sound(CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE); + } + M_DoStartControlPanel(scaleoverride); +} + + +//========================================================================== +// +// M_Dim +// +// Applies a colored overlay to the entire screen, with the opacity +// determined by the dimamount cvar. +// +//========================================================================== + +CUSTOM_CVAR(Float, dimamount, -1.f, CVAR_ARCHIVE) +{ + if (self < 0.f && self != -1.f) + { + self = -1.f; + } + else if (self > 1.f) + { + self = 1.f; + } +} +CVAR(Color, dimcolor, 0xffd700, CVAR_ARCHIVE) + +void System_M_Dim() +{ + PalEntry dimmer; + float amount; + + if (dimamount >= 0) + { + dimmer = PalEntry(dimcolor); + amount = dimamount; + } + else + { + dimmer = gameinfo.dimcolor; + amount = gameinfo.dimamount; + } + + Dim(twod, dimmer, amount, 0, 0, twod->GetWidth(), twod->GetHeight()); +} + + +//============================================================================= +// +// +// +//============================================================================= + +CCMD (menu_quit) +{ // F10 + if (m_quickexit) + { + ST_Endoom(); + } + + M_StartControlPanel (true); + + const size_t messageindex = static_cast(gametic) % gameinfo.quitmessages.Size(); + FString EndString; + const char *msg = gameinfo.quitmessages[messageindex]; + if (msg[0] == '$') + { + if (msg[1] == '*') + { + EndString = GStrings(msg + 2); + } + else + { + EndString.Format("%s\n\n%s", GStrings(msg + 1), GStrings("DOSY")); + } + } + else EndString = gameinfo.quitmessages[messageindex]; + + DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, EndString, 0, false, NAME_None, []() + { + if (!netgame) + { + if (gameinfo.quitSound.IsNotEmpty()) + { + S_Sound(CHAN_VOICE, CHANF_UI, gameinfo.quitSound, snd_menuvolume, ATTN_NONE); + I_WaitVBL(105); + } + } + ST_Endoom(); + }); + + + M_ActivateMenu(newmenu); +} + + + +//============================================================================= +// +// +// +//============================================================================= + +void ActivateEndGameMenu() +{ + FString tempstring = GStrings(netgame ? "NETEND" : "ENDGAME"); + DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []() + { + M_ClearMenus(); + if (!netgame) + { + if (demorecording) + G_CheckDemoStatus(); + D_StartTitle(); + } + }); + + M_ActivateMenu(newmenu); +} + +CCMD (menu_endgame) +{ // F7 + if (!usergame) + { + S_Sound (CHAN_VOICE, CHANF_UI, "menu/invalid", snd_menuvolume, ATTN_NONE); + return; + } + + //M_StartControlPanel (true); + S_Sound (CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE); + + ActivateEndGameMenu(); +} + +//============================================================================= +// +// +// +//============================================================================= + +CCMD (quicksave) +{ // F6 + if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer)) + { + S_Sound (CHAN_VOICE, CHANF_UI, "menu/invalid", snd_menuvolume, ATTN_NONE); + return; + } + + if (gamestate != GS_LEVEL) + return; + + // If the quick save rotation is enabled, it handles the save slot. + if (quicksaverotation) + { + G_DoQuickSave(); + return; + } + + if (savegameManager.quickSaveSlot == NULL || savegameManager.quickSaveSlot == (FSaveGameNode*)1) + { + S_Sound(CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE); + M_StartControlPanel(false); + M_SetMenu(NAME_Savegamemenu); + return; + } + + // [mxd]. Just save the game, no questions asked. + if (!saveloadconfirmation) + { + G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->SaveTitle.GetChars()); + return; + } + + S_Sound(CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE); + + FString tempstring = GStrings("QSPROMPT"); + tempstring.Substitute("%s", savegameManager.quickSaveSlot->SaveTitle.GetChars()); + + DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []() + { + G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->SaveTitle.GetChars()); + S_Sound(CHAN_VOICE, CHANF_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE); + M_ClearMenus(); + }); + + M_ActivateMenu(newmenu); +} + +//============================================================================= +// +// +// +//============================================================================= + +CCMD (quickload) +{ // F9 + if (netgame) + { + M_StartControlPanel(true); + M_StartMessage (GStrings("QLOADNET"), 1); + return; + } + + if (savegameManager.quickSaveSlot == NULL || savegameManager.quickSaveSlot == (FSaveGameNode*)1) + { + M_StartControlPanel(true); + // signal that whatever gets loaded should be the new quicksave + savegameManager.quickSaveSlot = (FSaveGameNode *)1; + M_SetMenu(NAME_Loadgamemenu); + return; + } + + // [mxd]. Just load the game, no questions asked. + if (!saveloadconfirmation) + { + G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars()); + return; + } + FString tempstring = GStrings("QLPROMPT"); + tempstring.Substitute("%s", savegameManager.quickSaveSlot->SaveTitle.GetChars()); + + M_StartControlPanel(true); + + DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []() + { + G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars()); + S_Sound(CHAN_VOICE, CHANF_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE); + M_ClearMenus(); + }); + M_ActivateMenu(newmenu); +} + + + + +// +// Toggle messages on/off +// +CCMD (togglemessages) +{ + if (show_messages) + { + Printf (128, "%s\n", GStrings("MSGOFF")); + show_messages = false; + } + else + { + Printf (128, "%s\n", GStrings("MSGON")); + show_messages = true; + } +} + +EXTERN_CVAR (Int, screenblocks) + +CCMD (sizedown) +{ + screenblocks = screenblocks - 1; + S_Sound (CHAN_VOICE, CHANF_UI, "menu/change", snd_menuvolume, ATTN_NONE); +} + +CCMD (sizeup) +{ + screenblocks = screenblocks + 1; + S_Sound (CHAN_VOICE, CHANF_UI, "menu/change", snd_menuvolume, ATTN_NONE); +} + +CCMD(reset2defaults) +{ + C_SetDefaultBindings (); + C_SetCVarsToDefaults (); + R_SetViewSize (screenblocks); +} + +CCMD(reset2saved) +{ + GameConfig->DoGlobalSetup (); + GameConfig->DoGameSetup (gameinfo.ConfigName); + GameConfig->DoModSetup (gameinfo.ConfigName); + R_SetViewSize (screenblocks); +} + + diff --git a/src/menu/doommenu.h b/src/menu/doommenu.h new file mode 100644 index 0000000000..3d6d45254e --- /dev/null +++ b/src/menu/doommenu.h @@ -0,0 +1,4 @@ +#pragma once +#include "menu.h" + +void M_StartControlPanel (bool makeSound, bool scaleoverride = false); diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index c9cacb718a..0ab3efa363 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -32,40 +32,34 @@ ** */ -#include "doomdef.h" -#include "doomstat.h" #include "c_dispatch.h" #include "d_gui.h" -#include "d_player.h" +#include "c_buttons.h" #include "c_console.h" #include "c_bind.h" -#include "p_tick.h" -#include "g_game.h" -#include "d_event.h" -#include "hu_stuff.h" -#include "gi.h" +#include "d_eventbase.h" #include "g_input.h" -#include "gameconfigfile.h" +#include "configfile.h" #include "gstrings.h" -#include "r_utility.h" -#include "menu/menu.h" +#include "menu.h" #include "vm.h" -#include "events.h" #include "v_video.h" #include "i_system.h" -#include "c_buttons.h" #include "types.h" #include "texturemanager.h" #include "v_draw.h" +#include "vm.h" +#include "gamestate.h" +#include "i_interface.h" + +void M_StartControlPanel(bool makeSound, bool scaleoverride = false); int DMenu::InMenu; static ScaleOverrider *CurrentScaleOverrider; +extern int chatmodeon; // // Todo: Move these elsewhere // -CVAR (Float, mouse_sensitivity, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -CVAR (Bool, show_messages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -CVAR (Bool, show_obituaries, true, CVAR_ARCHIVE) CVAR (Int, m_showinputgrid, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, m_blockcontrollers, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -73,21 +67,6 @@ CVAR (Float, snd_menuvolume, 0.6f, CVAR_ARCHIVE) CVAR(Int, m_use_mouse, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Int, m_show_backbutton, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -CUSTOM_CVAR(Float, dimamount, -1.f, CVAR_ARCHIVE) -{ - if (self < 0.f && self != -1.f) - { - self = -1.f; - } - else if (self > 1.f) - { - self = 1.f; - } -} -CVAR(Color, dimcolor, 0xffd700, CVAR_ARCHIVE) - - - static DMenu *GetCurrentMenu() { return CurrentMenu; @@ -108,9 +87,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DMenu, MenuTime, GetMenuTime) ACTION_RETURN_INT(MenuTime); } -FNewGameStartup NewGameStartupInfo; EMenuState menuactive; -bool M_DemoNoPlay; FButtonStatus MenuButtons[NUM_MKEYS]; int MenuButtonTickers[NUM_MKEYS]; bool MenuButtonOrigin[NUM_MKEYS]; @@ -122,8 +99,6 @@ int MenuTime; extern PClass *DefaultListMenuClass; extern PClass *DefaultOptionMenuClass; -extern bool hud_toggled; -void D_ToggleHud(); #define KEY_REPEAT_DELAY (TICRATE*5/12) @@ -355,11 +330,8 @@ bool DMenu::TranslateKeyboardEvents() // //============================================================================= -void M_StartControlPanel (bool makeSound, bool scaleoverride) +void M_DoStartControlPanel (bool scaleoverride) { - if (hud_toggled) - D_ToggleHud(); - // intro might call this repeatedly if (CurrentMenu != nullptr) return; @@ -372,14 +344,6 @@ void M_StartControlPanel (bool makeSound, bool scaleoverride) C_HideConsole (); // [RH] Make sure console goes bye bye. menuactive = MENU_On; - // Pause sound effects before we play the menu switch sound. - // That way, it won't be paused. - P_CheckTickerPaused (); - - if (makeSound) - { - S_Sound (CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE); - } BackbuttonTime = 0; BackbuttonAlpha = 0; if (scaleoverride && !CurrentScaleOverrider) CurrentScaleOverrider = new ScaleOverrider(twod); @@ -421,123 +385,11 @@ DEFINE_ACTION_FUNCTION(DMenu, ActivateMenu) // //============================================================================= -EXTERN_CVAR(Int, cl_gfxlocalization) - +bool M_SetSpecialMenu(FName menu, int param); // game specific checks void M_SetMenu(FName menu, int param) { - // some menus need some special treatment - switch (menu.GetIndex()) - { - case NAME_Mainmenu: - if (gameinfo.gametype & GAME_DoomStrifeChex) // Raven's games always used text based menus - { - if (gameinfo.forcetextinmenus) // If text is forced, this overrides any check. - { - menu = NAME_MainmenuTextOnly; - } - else if (cl_gfxlocalization != 0 && !gameinfo.forcenogfxsubstitution) - { - // For these games we must check up-front if they get localized because in that case another template must be used. - DMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_Mainmenu); - if (desc != nullptr) - { - if ((*desc)->IsKindOf(RUNTIME_CLASS(DListMenuDescriptor))) - { - DListMenuDescriptor *ld = static_cast(*desc); - if (ld->mFromEngine) - { - // This assumes that replacing one graphic will replace all of them. - // So this only checks the "New game" entry for localization capability. - FTextureID texid = TexMan.CheckForTexture("M_NGAME", ETextureType::MiscPatch); - if (!OkForLocalization(texid, "$MNU_NEWGAME")) - { - menu = NAME_MainmenuTextOnly; - } - } - } - } - } - } - break; - case NAME_Episodemenu: - // sent from the player class menu - NewGameStartupInfo.Skill = -1; - NewGameStartupInfo.Episode = -1; - NewGameStartupInfo.PlayerClass = - param == -1000? nullptr : - param == -1? "Random" : GetPrintableDisplayName(PlayerClasses[param].Type).GetChars(); - M_StartupEpisodeMenu(&NewGameStartupInfo); // needs player class name from class menu (later) - break; - - case NAME_Skillmenu: - // sent from the episode menu - - if ((gameinfo.flags & GI_SHAREWARE) && param > 0) - { - // Only Doom and Heretic have multi-episode shareware versions. - M_StartMessage(GStrings("SWSTRING"), 1); - return; - } - - NewGameStartupInfo.Episode = param; - M_StartupSkillMenu(&NewGameStartupInfo); // needs player class name from class menu (later) - break; - - case NAME_StartgameConfirm: - { - // sent from the skill menu for a skill that needs to be confirmed - NewGameStartupInfo.Skill = param; - - const char *msg = AllSkills[param].MustConfirmText; - if (*msg==0) msg = GStrings("NIGHTMARE"); - M_StartMessage (msg, 0, NAME_StartgameConfirmed); - return; - } - - case NAME_Startgame: - // sent either from skill menu or confirmation screen. Skill gets only set if sent from skill menu - // Now we can finally start the game. Ugh... - NewGameStartupInfo.Skill = param; - case NAME_StartgameConfirmed: - - G_DeferedInitNew (&NewGameStartupInfo); - if (gamestate == GS_FULLCONSOLE) - { - gamestate = GS_HIDECONSOLE; - gameaction = ga_newgame; - } - M_ClearMenus (); - return; - - case NAME_Savegamemenu: - if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer) || gamestate != GS_LEVEL) - { - // cannot save outside the game. - M_StartMessage (GStrings("SAVEDEAD"), 1); - return; - } - - case NAME_VideoModeMenu: - break; - - case NAME_Quitmenu: - // The separate menu class no longer exists but the name still needs support for existing mods. - C_DoCommand("menu_quit"); - return; - - case NAME_EndGameMenu: - // The separate menu class no longer exists but the name still needs support for existing mods. - void ActivateEndGameMenu(); - ActivateEndGameMenu(); - return; - - case NAME_Playermenu: - menu = NAME_NewPlayerMenu; // redirect the old player menu to the new one. - break; - } - - // End of special checks + if (!M_SetSpecialMenu(menu, param)) return; DMenuDescriptor **desc = MenuDescriptors.CheckKey(menu); if (desc != nullptr) @@ -796,13 +648,6 @@ bool M_Responder (event_t *ev) M_SetMenu(NAME_Mainmenu, -1); return true; } - // If devparm is set, pressing F1 always takes a screenshot no matter - // what it's bound to. (for those who don't bother to read the docs) - if (devparm && ev->data1 == KEY_F1) - { - G_ScreenShot(nullptr); - return true; - } return false; } else if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_LButtonDown && @@ -858,35 +703,6 @@ void M_Ticker (void) } } -//========================================================================== -// -// M_Dim -// -// Applies a colored overlay to the entire screen, with the opacity -// determined by the dimamount cvar. -// -//========================================================================== - -static void M_Dim() -{ - PalEntry dimmer; - float amount; - - if (dimamount >= 0) - { - dimmer = PalEntry(dimcolor); - amount = dimamount; - } - else - { - dimmer = gameinfo.dimcolor; - amount = gameinfo.dimamount; - } - - Dim(twod, dimmer, amount, 0, 0, twod->GetWidth(), twod->GetHeight()); -} - - //============================================================================= // // @@ -901,10 +717,10 @@ void M_Drawer (void) if (CurrentMenu != nullptr && menuactive != MENU_Off) { - if (!CurrentMenu->DontBlur) screen->BlurScene(gameinfo.bluramount); + if (!CurrentMenu->DontBlur) screen->BlurScene(0); if (!CurrentMenu->DontDim) { - M_Dim(); + if (sysCallbacks && sysCallbacks->MenuDim) sysCallbacks->MenuDim(); } CurrentMenu->CallDrawer(); } @@ -918,7 +734,6 @@ void M_Drawer (void) void M_ClearMenus() { - M_DemoNoPlay = false; while (CurrentMenu != nullptr) { DMenu* parent = CurrentMenu->mParentMenu; @@ -1137,59 +952,12 @@ CCMD (prevmenu) M_PreviousMenu(); } -// -// Toggle messages on/off -// -CCMD (togglemessages) -{ - if (show_messages) - { - Printf (128, "%s\n", GStrings("MSGOFF")); - show_messages = false; - } - else - { - Printf (128, "%s\n", GStrings("MSGON")); - show_messages = true; - } -} - -EXTERN_CVAR (Int, screenblocks) - -CCMD (sizedown) -{ - screenblocks = screenblocks - 1; - S_Sound (CHAN_VOICE, CHANF_UI, "menu/change", snd_menuvolume, ATTN_NONE); -} - -CCMD (sizeup) -{ - screenblocks = screenblocks + 1; - S_Sound (CHAN_VOICE, CHANF_UI, "menu/change", snd_menuvolume, ATTN_NONE); -} - CCMD(menuconsole) { M_ClearMenus(); C_ToggleConsole(); } -CCMD(reset2defaults) -{ - C_SetDefaultBindings (); - C_SetCVarsToDefaults (); - R_SetViewSize (screenblocks); -} - -CCMD(reset2saved) -{ - GameConfig->DoGlobalSetup (); - GameConfig->DoGameSetup (gameinfo.ConfigName); - GameConfig->DoModSetup (gameinfo.ConfigName); - R_SetViewSize (screenblocks); -} - - // This really should be in the script but we can't do scripted CCMDs yet. CCMD(undocolorpic) { diff --git a/src/menu/menu.h b/src/menu/menu.h index f6f4fe9e0b..a2b6a91f7f 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -6,10 +6,8 @@ #include "dobject.h" #include "d_player.h" -#include "r_data/r_translate.h" #include "c_cvars.h" #include "v_font.h" -#include "gi.h" #include "textures.h" EXTERN_CVAR(Float, snd_menuvolume) @@ -207,7 +205,7 @@ public: mScrollTop = 0; mIndent = 0; mDontDim = 0; - mFont = gameinfo.gametype == GAME_Doom ? BigUpper : BigFont; + mFont = BigUpper; } size_t PropagateMark() override; @@ -347,7 +345,7 @@ void M_PreviousMenu (); void M_ParseMenuDefs(); void M_StartupEpisodeMenu(FNewGameStartup *gs); void M_StartupSkillMenu(FNewGameStartup *gs); -void M_StartControlPanel (bool makeSound, bool scaleoverride = false); +void M_DoStartControlPanel(bool scaleoverride); void M_SetMenu(FName menu, int param = -1); void M_StartMessage(const char *message, int messagemode, FName action = NAME_None); DMenu *StartPickerMenu(DMenu *parent, const char *name, FColorCVar *cvar); diff --git a/src/menu/messagebox.cpp b/src/menu/messagebox.cpp index 75685678b8..a38e8dbdce 100644 --- a/src/menu/messagebox.cpp +++ b/src/menu/messagebox.cpp @@ -33,18 +33,14 @@ */ #include -#include "menu/menu.h" -#include "d_main.h" +#include "menu.h" #include "gstrings.h" -#include "gi.h" #include "i_video.h" -#include "st_start.h" #include "c_dispatch.h" -#include "g_game.h" #include "vm.h" -EXTERN_CVAR (Bool, saveloadconfirmation) // [mxd] -EXTERN_CVAR (Bool, quicksaverotation) +void M_StartControlPanel(bool makeSound, bool scaleoverride = false); +FName MessageBoxClass = NAME_MessageBoxMenu; CVAR(Bool, m_quickexit, false, CVAR_ARCHIVE) @@ -65,7 +61,7 @@ DEFINE_ACTION_FUNCTION(DMessageBoxMenu, CallHandler) DMenu *CreateMessageBoxMenu(DMenu *parent, const char *message, int messagemode, bool playsound, FName action = NAME_None, hfunc handler = nullptr) { - auto c = PClass::FindClass(gameinfo.MessageBoxClass); + auto c = PClass::FindClass(MessageBoxClass); if (!c->IsDescendantOf(NAME_MessageBoxMenu)) c = PClass::FindClass(NAME_MessageBoxMenu); auto p = c->CreateNew(); FString namestr = message; @@ -85,191 +81,6 @@ DMenu *CreateMessageBoxMenu(DMenu *parent, const char *message, int messagemode, // //============================================================================= -CCMD (menu_quit) -{ // F10 - if (m_quickexit) - { - ST_Endoom(); - } - - M_StartControlPanel (true); - - const size_t messageindex = static_cast(gametic) % gameinfo.quitmessages.Size(); - FString EndString; - const char *msg = gameinfo.quitmessages[messageindex]; - if (msg[0] == '$') - { - if (msg[1] == '*') - { - EndString = GStrings(msg + 2); - } - else - { - EndString.Format("%s\n\n%s", GStrings(msg + 1), GStrings("DOSY")); - } - } - else EndString = gameinfo.quitmessages[messageindex]; - - DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, EndString, 0, false, NAME_None, []() - { - if (!netgame) - { - if (gameinfo.quitSound.IsNotEmpty()) - { - S_Sound(CHAN_VOICE, CHANF_UI, gameinfo.quitSound, snd_menuvolume, ATTN_NONE); - I_WaitVBL(105); - } - } - ST_Endoom(); - }); - - - M_ActivateMenu(newmenu); -} - - - -//============================================================================= -// -// -// -//============================================================================= - -void ActivateEndGameMenu() -{ - FString tempstring = GStrings(netgame ? "NETEND" : "ENDGAME"); - DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []() - { - M_ClearMenus(); - if (!netgame) - { - if (demorecording) - G_CheckDemoStatus(); - D_StartTitle(); - } - }); - - M_ActivateMenu(newmenu); -} - -CCMD (menu_endgame) -{ // F7 - if (!usergame) - { - S_Sound (CHAN_VOICE, CHANF_UI, "menu/invalid", snd_menuvolume, ATTN_NONE); - return; - } - - //M_StartControlPanel (true); - S_Sound (CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE); - - ActivateEndGameMenu(); -} - -//============================================================================= -// -// -// -//============================================================================= - -CCMD (quicksave) -{ // F6 - if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer)) - { - S_Sound (CHAN_VOICE, CHANF_UI, "menu/invalid", snd_menuvolume, ATTN_NONE); - return; - } - - if (gamestate != GS_LEVEL) - return; - - // If the quick save rotation is enabled, it handles the save slot. - if (quicksaverotation) - { - G_DoQuickSave(); - return; - } - - if (savegameManager.quickSaveSlot == NULL || savegameManager.quickSaveSlot == (FSaveGameNode*)1) - { - S_Sound(CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE); - M_StartControlPanel(false); - M_SetMenu(NAME_Savegamemenu); - return; - } - - // [mxd]. Just save the game, no questions asked. - if (!saveloadconfirmation) - { - G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->SaveTitle.GetChars()); - return; - } - - S_Sound(CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE); - - FString tempstring = GStrings("QSPROMPT"); - tempstring.Substitute("%s", savegameManager.quickSaveSlot->SaveTitle.GetChars()); - - DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []() - { - G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->SaveTitle.GetChars()); - S_Sound(CHAN_VOICE, CHANF_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE); - M_ClearMenus(); - }); - - M_ActivateMenu(newmenu); -} - -//============================================================================= -// -// -// -//============================================================================= - -CCMD (quickload) -{ // F9 - if (netgame) - { - M_StartControlPanel(true); - M_StartMessage (GStrings("QLOADNET"), 1); - return; - } - - if (savegameManager.quickSaveSlot == NULL || savegameManager.quickSaveSlot == (FSaveGameNode*)1) - { - M_StartControlPanel(true); - // signal that whatever gets loaded should be the new quicksave - savegameManager.quickSaveSlot = (FSaveGameNode *)1; - M_SetMenu(NAME_Loadgamemenu); - return; - } - - // [mxd]. Just load the game, no questions asked. - if (!saveloadconfirmation) - { - G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars()); - return; - } - FString tempstring = GStrings("QLPROMPT"); - tempstring.Substitute("%s", savegameManager.quickSaveSlot->SaveTitle.GetChars()); - - M_StartControlPanel(true); - - DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []() - { - G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars()); - S_Sound(CHAN_VOICE, CHANF_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE); - M_ClearMenus(); - }); - M_ActivateMenu(newmenu); -} - -//============================================================================= -// -// -// -//============================================================================= - void M_StartMessage(const char *message, int messagemode, FName action) { if (CurrentMenu == NULL) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index d270af0d41..19d9a81cca 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -58,6 +58,7 @@ #include "v_video.h" #include "actorinlines.h" #include "v_draw.h" +#include "doommenu.h" static FRandom pr_randomspeech("RandomSpeech"); diff --git a/wadsrc/static/zscript/ui/menu/colorpickermenu.zs b/wadsrc/static/zscript/ui/menu/colorpickermenu.zs index 188d9f2722..f8ce518746 100644 --- a/wadsrc/static/zscript/ui/menu/colorpickermenu.zs +++ b/wadsrc/static/zscript/ui/menu/colorpickermenu.zs @@ -241,7 +241,6 @@ class ColorpickerMenu : OptionMenu { mGridPosX = cell_x; mGridPosY = cell_y; - //S_Sound (CHAN_VOICE, CHANF_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); } mDesc.mSelectedItem = mStartItem+7; if (type == MOUSE_Release) diff --git a/wadsrc/static/zscript/ui/menu/conversationmenu.zs b/wadsrc/static/zscript/ui/menu/conversationmenu.zs index 70a114c9b2..52d106c57d 100644 --- a/wadsrc/static/zscript/ui/menu/conversationmenu.zs +++ b/wadsrc/static/zscript/ui/menu/conversationmenu.zs @@ -375,10 +375,6 @@ class ConversationMenu : Menu } } } - if (sel != -1 && sel != mSelection) - { - //S_Sound (CHAN_VOICE, CHANF_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); - } mSelection = sel; if (type == MOUSE_Release) { diff --git a/wadsrc/static/zscript/ui/menu/messagebox.zs b/wadsrc/static/zscript/ui/menu/messagebox.zs index 68e8119253..e8a97bf672 100644 --- a/wadsrc/static/zscript/ui/menu/messagebox.zs +++ b/wadsrc/static/zscript/ui/menu/messagebox.zs @@ -302,10 +302,6 @@ class MessageBoxMenu : Menu { sel = y >= mMouseY + fh; } - if (sel != -1 && sel != messageSelection) - { - //S_Sound (CHAN_VOICE, CHANF_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); - } messageSelection = sel; if (type == MOUSE_Release) { diff --git a/wadsrc/static/zscript/ui/menu/optionmenu.zs b/wadsrc/static/zscript/ui/menu/optionmenu.zs index 1a27b82651..20ae748ae8 100644 --- a/wadsrc/static/zscript/ui/menu/optionmenu.zs +++ b/wadsrc/static/zscript/ui/menu/optionmenu.zs @@ -393,7 +393,6 @@ class OptionMenu : Menu if (yline != mDesc.mSelectedItem) { mDesc.mSelectedItem = yline; - //S_Sound (CHAN_VOICE, CHANF_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); } mDesc.mItems[yline].MouseEvent(type, x, y); return true;