diff options
Diffstat (limited to 'src/heretic/mn_menu.c')
-rw-r--r-- | src/heretic/mn_menu.c | 1674 |
1 files changed, 1674 insertions, 0 deletions
diff --git a/src/heretic/mn_menu.c b/src/heretic/mn_menu.c new file mode 100644 index 00000000..75728427 --- /dev/null +++ b/src/heretic/mn_menu.c @@ -0,0 +1,1674 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2008 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// +//----------------------------------------------------------------------------- + +// MN_menu.c + +#include <ctype.h> + +#include "deh_str.h" +#include "doomdef.h" +#include "doomkeys.h" +#include "i_system.h" +#include "i_swap.h" +#include "m_controls.h" +#include "p_local.h" +#include "r_local.h" +#include "s_sound.h" +#include "v_video.h" + +// Macros + +#define LEFT_DIR 0 +#define RIGHT_DIR 1 +#define ITEM_HEIGHT 20 +#define SELECTOR_XOFFSET (-28) +#define SELECTOR_YOFFSET (-1) +#define SLOTTEXTLEN 16 +#define ASCII_CURSOR '[' + +// Types + +typedef enum +{ + ITT_EMPTY, + ITT_EFUNC, + ITT_LRFUNC, + ITT_SETMENU, + ITT_INERT +} ItemType_t; + +typedef enum +{ + MENU_MAIN, + MENU_EPISODE, + MENU_SKILL, + MENU_OPTIONS, + MENU_OPTIONS2, + MENU_FILES, + MENU_LOAD, + MENU_SAVE, + MENU_NONE +} MenuType_t; + +typedef struct +{ + ItemType_t type; + char *text; + boolean(*func) (int option); + int option; + MenuType_t menu; +} MenuItem_t; + +typedef struct +{ + int x; + int y; + void (*drawFunc) (void); + int itemCount; + MenuItem_t *items; + int oldItPos; + MenuType_t prevMenu; +} Menu_t; + +// Private Functions + +static void InitFonts(void); +static void SetMenu(MenuType_t menu); +static boolean SCNetCheck(int option); +static boolean SCQuitGame(int option); +static boolean SCEpisode(int option); +static boolean SCSkill(int option); +static boolean SCMouseSensi(int option); +static boolean SCSfxVolume(int option); +static boolean SCMusicVolume(int option); +static boolean SCScreenSize(int option); +static boolean SCLoadGame(int option); +static boolean SCSaveGame(int option); +static boolean SCMessages(int option); +static boolean SCEndGame(int option); +static boolean SCInfo(int option); +static void DrawMainMenu(void); +static void DrawEpisodeMenu(void); +static void DrawSkillMenu(void); +static void DrawOptionsMenu(void); +static void DrawOptions2Menu(void); +static void DrawFileSlots(Menu_t * menu); +static void DrawFilesMenu(void); +static void MN_DrawInfo(void); +static void DrawLoadMenu(void); +static void DrawSaveMenu(void); +static void DrawSlider(Menu_t * menu, int item, int width, int slot); +void MN_LoadSlotText(void); + +// External Data + +extern int usegamma; +extern int detailLevel; +extern int screenblocks; + +// Public Data + +boolean MenuActive; +int InfoType; +boolean messageson; + +// Private Data + +static int FontABaseLump; +static int FontBBaseLump; +static int SkullBaseLump; +static Menu_t *CurrentMenu; +static int CurrentItPos; +static int MenuEpisode; +static int MenuTime; +static boolean soundchanged; + +boolean askforquit; +boolean typeofask; +static boolean FileMenuKeySteal; +static boolean slottextloaded; +static char SlotText[6][SLOTTEXTLEN + 2]; +static char oldSlotText[SLOTTEXTLEN + 2]; +static int SlotStatus[6]; +static int slotptr; +static int currentSlot; +static int quicksave; +static int quickload; + +static MenuItem_t MainItems[] = { + {ITT_EFUNC, "NEW GAME", SCNetCheck, 1, MENU_EPISODE}, + {ITT_SETMENU, "OPTIONS", NULL, 0, MENU_OPTIONS}, + {ITT_SETMENU, "GAME FILES", NULL, 0, MENU_FILES}, + {ITT_EFUNC, "INFO", SCInfo, 0, MENU_NONE}, + {ITT_EFUNC, "QUIT GAME", SCQuitGame, 0, MENU_NONE} +}; + +static Menu_t MainMenu = { + 110, 56, + DrawMainMenu, + 5, MainItems, + 0, + MENU_NONE +}; + +static MenuItem_t EpisodeItems[] = { + {ITT_EFUNC, "CITY OF THE DAMNED", SCEpisode, 1, MENU_NONE}, + {ITT_EFUNC, "HELL'S MAW", SCEpisode, 2, MENU_NONE}, + {ITT_EFUNC, "THE DOME OF D'SPARIL", SCEpisode, 3, MENU_NONE}, + {ITT_EFUNC, "THE OSSUARY", SCEpisode, 4, MENU_NONE}, + {ITT_EFUNC, "THE STAGNANT DEMESNE", SCEpisode, 5, MENU_NONE} +}; + +static Menu_t EpisodeMenu = { + 80, 50, + DrawEpisodeMenu, + 3, EpisodeItems, + 0, + MENU_MAIN +}; + +static MenuItem_t FilesItems[] = { + {ITT_EFUNC, "LOAD GAME", SCNetCheck, 2, MENU_LOAD}, + {ITT_SETMENU, "SAVE GAME", NULL, 0, MENU_SAVE} +}; + +static Menu_t FilesMenu = { + 110, 60, + DrawFilesMenu, + 2, FilesItems, + 0, + MENU_MAIN +}; + +static MenuItem_t LoadItems[] = { + {ITT_EFUNC, NULL, SCLoadGame, 0, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 1, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 2, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 3, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 4, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 5, MENU_NONE} +}; + +static Menu_t LoadMenu = { + 70, 30, + DrawLoadMenu, + 6, LoadItems, + 0, + MENU_FILES +}; + +static MenuItem_t SaveItems[] = { + {ITT_EFUNC, NULL, SCSaveGame, 0, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 1, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 2, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 3, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 4, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 5, MENU_NONE} +}; + +static Menu_t SaveMenu = { + 70, 30, + DrawSaveMenu, + 6, SaveItems, + 0, + MENU_FILES +}; + +static MenuItem_t SkillItems[] = { + {ITT_EFUNC, "THOU NEEDETH A WET-NURSE", SCSkill, sk_baby, MENU_NONE}, + {ITT_EFUNC, "YELLOWBELLIES-R-US", SCSkill, sk_easy, MENU_NONE}, + {ITT_EFUNC, "BRINGEST THEM ONETH", SCSkill, sk_medium, MENU_NONE}, + {ITT_EFUNC, "THOU ART A SMITE-MEISTER", SCSkill, sk_hard, MENU_NONE}, + {ITT_EFUNC, "BLACK PLAGUE POSSESSES THEE", + SCSkill, sk_nightmare, MENU_NONE} +}; + +static Menu_t SkillMenu = { + 38, 30, + DrawSkillMenu, + 5, SkillItems, + 2, + MENU_EPISODE +}; + +static MenuItem_t OptionsItems[] = { + {ITT_EFUNC, "END GAME", SCEndGame, 0, MENU_NONE}, + {ITT_EFUNC, "MESSAGES : ", SCMessages, 0, MENU_NONE}, + {ITT_LRFUNC, "MOUSE SENSITIVITY", SCMouseSensi, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, + {ITT_SETMENU, "MORE...", NULL, 0, MENU_OPTIONS2} +}; + +static Menu_t OptionsMenu = { + 88, 30, + DrawOptionsMenu, + 5, OptionsItems, + 0, + MENU_MAIN +}; + +static MenuItem_t Options2Items[] = { + {ITT_LRFUNC, "SCREEN SIZE", SCScreenSize, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, + {ITT_LRFUNC, "SFX VOLUME", SCSfxVolume, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, + {ITT_LRFUNC, "MUSIC VOLUME", SCMusicVolume, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE} +}; + +static Menu_t Options2Menu = { + 90, 20, + DrawOptions2Menu, + 6, Options2Items, + 0, + MENU_OPTIONS +}; + +static Menu_t *Menus[] = { + &MainMenu, + &EpisodeMenu, + &SkillMenu, + &OptionsMenu, + &Options2Menu, + &FilesMenu, + &LoadMenu, + &SaveMenu +}; + +//--------------------------------------------------------------------------- +// +// PROC MN_Init +// +//--------------------------------------------------------------------------- + +void MN_Init(void) +{ + InitFonts(); + MenuActive = false; + messageson = true; + SkullBaseLump = W_GetNumForName(DEH_String("M_SKL00")); + + if (gamemode == retail) + { // Add episodes 4 and 5 to the menu + EpisodeMenu.itemCount = 5; + EpisodeMenu.y -= ITEM_HEIGHT; + } +} + +//--------------------------------------------------------------------------- +// +// PROC InitFonts +// +//--------------------------------------------------------------------------- + +static void InitFonts(void) +{ + FontABaseLump = W_GetNumForName(DEH_String("FONTA_S")) + 1; + FontBBaseLump = W_GetNumForName(DEH_String("FONTB_S")) + 1; +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DrTextA +// +// Draw text using font A. +// +//--------------------------------------------------------------------------- + +void MN_DrTextA(char *text, int x, int y) +{ + char c; + patch_t *p; + + while ((c = *text++) != 0) + { + if (c < 33) + { + x += 5; + } + else + { + p = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + V_DrawPatch(x, y, p); + x += SHORT(p->width) - 1; + } + } +} + +//--------------------------------------------------------------------------- +// +// FUNC MN_TextAWidth +// +// Returns the pixel width of a string using font A. +// +//--------------------------------------------------------------------------- + +int MN_TextAWidth(char *text) +{ + char c; + int width; + patch_t *p; + + width = 0; + while ((c = *text++) != 0) + { + if (c < 33) + { + width += 5; + } + else + { + p = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + width += SHORT(p->width) - 1; + } + } + return (width); +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DrTextB +// +// Draw text using font B. +// +//--------------------------------------------------------------------------- + +void MN_DrTextB(char *text, int x, int y) +{ + char c; + patch_t *p; + + while ((c = *text++) != 0) + { + if (c < 33) + { + x += 8; + } + else + { + p = W_CacheLumpNum(FontBBaseLump + c - 33, PU_CACHE); + V_DrawPatch(x, y, p); + x += SHORT(p->width) - 1; + } + } +} + +//--------------------------------------------------------------------------- +// +// FUNC MN_TextBWidth +// +// Returns the pixel width of a string using font B. +// +//--------------------------------------------------------------------------- + +int MN_TextBWidth(char *text) +{ + char c; + int width; + patch_t *p; + + width = 0; + while ((c = *text++) != 0) + { + if (c < 33) + { + width += 5; + } + else + { + p = W_CacheLumpNum(FontBBaseLump + c - 33, PU_CACHE); + width += SHORT(p->width) - 1; + } + } + return (width); +} + +//--------------------------------------------------------------------------- +// +// PROC MN_Ticker +// +//--------------------------------------------------------------------------- + +void MN_Ticker(void) +{ + if (MenuActive == false) + { + return; + } + MenuTime++; +} + +//--------------------------------------------------------------------------- +// +// PROC MN_Drawer +// +//--------------------------------------------------------------------------- + +char *QuitEndMsg[] = { + "ARE YOU SURE YOU WANT TO QUIT?", + "ARE YOU SURE YOU WANT TO END THE GAME?", + "DO YOU WANT TO QUICKSAVE THE GAME NAMED", + "DO YOU WANT TO QUICKLOAD THE GAME NAMED" +}; + +void MN_Drawer(void) +{ + int i; + int x; + int y; + MenuItem_t *item; + char *message; + char *selName; + + if (MenuActive == false) + { + if (askforquit) + { + message = DEH_String(QuitEndMsg[typeofask - 1]); + + MN_DrTextA(message, 160 - MN_TextAWidth(message) / 2, 80); + if (typeofask == 3) + { + MN_DrTextA(SlotText[quicksave - 1], 160 - + MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); + MN_DrTextA(DEH_String("?"), 160 + + MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); + } + if (typeofask == 4) + { + MN_DrTextA(SlotText[quickload - 1], 160 - + MN_TextAWidth(SlotText[quickload - 1]) / 2, 90); + MN_DrTextA(DEH_String("?"), 160 + + MN_TextAWidth(SlotText[quickload - 1]) / 2, 90); + } + UpdateState |= I_FULLSCRN; + } + return; + } + else + { + UpdateState |= I_FULLSCRN; + if (InfoType) + { + MN_DrawInfo(); + return; + } + if (screenblocks < 10) + { + BorderNeedRefresh = true; + } + if (CurrentMenu->drawFunc != NULL) + { + CurrentMenu->drawFunc(); + } + x = CurrentMenu->x; + y = CurrentMenu->y; + item = CurrentMenu->items; + for (i = 0; i < CurrentMenu->itemCount; i++) + { + if (item->type != ITT_EMPTY && item->text) + { + MN_DrTextB(DEH_String(item->text), x, y); + } + y += ITEM_HEIGHT; + item++; + } + y = CurrentMenu->y + (CurrentItPos * ITEM_HEIGHT) + SELECTOR_YOFFSET; + selName = DEH_String(MenuTime & 16 ? "M_SLCTR1" : "M_SLCTR2"); + V_DrawPatch(x + SELECTOR_XOFFSET, y, + W_CacheLumpName(selName, PU_CACHE)); + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawMainMenu +// +//--------------------------------------------------------------------------- + +static void DrawMainMenu(void) +{ + int frame; + + frame = (MenuTime / 3) % 18; + V_DrawPatch(88, 0, W_CacheLumpName(DEH_String("M_HTIC"), PU_CACHE)); + V_DrawPatch(40, 10, W_CacheLumpNum(SkullBaseLump + (17 - frame), + PU_CACHE)); + V_DrawPatch(232, 10, W_CacheLumpNum(SkullBaseLump + frame, PU_CACHE)); +} + +//--------------------------------------------------------------------------- +// +// PROC DrawEpisodeMenu +// +//--------------------------------------------------------------------------- + +static void DrawEpisodeMenu(void) +{ +} + +//--------------------------------------------------------------------------- +// +// PROC DrawSkillMenu +// +//--------------------------------------------------------------------------- + +static void DrawSkillMenu(void) +{ +} + +//--------------------------------------------------------------------------- +// +// PROC DrawFilesMenu +// +//--------------------------------------------------------------------------- + +static void DrawFilesMenu(void) +{ +// clear out the quicksave/quickload stuff + quicksave = 0; + quickload = 0; + players[consoleplayer].message = NULL; + players[consoleplayer].messageTics = 1; +} + +//--------------------------------------------------------------------------- +// +// PROC DrawLoadMenu +// +//--------------------------------------------------------------------------- + +static void DrawLoadMenu(void) +{ + char *title; + + title = DEH_String("LOAD GAME"); + + MN_DrTextB(title, 160 - MN_TextBWidth(title) / 2, 10); + if (!slottextloaded) + { + MN_LoadSlotText(); + } + DrawFileSlots(&LoadMenu); +} + +//--------------------------------------------------------------------------- +// +// PROC DrawSaveMenu +// +//--------------------------------------------------------------------------- + +static void DrawSaveMenu(void) +{ + char *title; + + title = DEH_String("SAVE GAME"); + + MN_DrTextB(title, 160 - MN_TextBWidth(title) / 2, 10); + if (!slottextloaded) + { + MN_LoadSlotText(); + } + DrawFileSlots(&SaveMenu); +} + +//=========================================================================== +// +// MN_LoadSlotText +// +// Loads in the text message for each slot +//=========================================================================== + +void MN_LoadSlotText(void) +{ + FILE *fp; + int count; + int i; + char *filename; + + for (i = 0; i < 6; i++) + { + filename = SV_Filename(i); + fp = fopen(filename, "rb+"); + free(filename); + + if (!fp) + { + SlotText[i][0] = 0; // empty the string + SlotStatus[i] = 0; + continue; + } + count = fread(&SlotText[i], SLOTTEXTLEN, 1, fp); + fclose(fp); + SlotStatus[i] = 1; + } + slottextloaded = true; +} + +//--------------------------------------------------------------------------- +// +// PROC DrawFileSlots +// +//--------------------------------------------------------------------------- + +static void DrawFileSlots(Menu_t * menu) +{ + int i; + int x; + int y; + + x = menu->x; + y = menu->y; + for (i = 0; i < 6; i++) + { + V_DrawPatch(x, y, W_CacheLumpName(DEH_String("M_FSLOT"), PU_CACHE)); + if (SlotStatus[i]) + { + MN_DrTextA(SlotText[i], x + 5, y + 5); + } + y += ITEM_HEIGHT; + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawOptionsMenu +// +//--------------------------------------------------------------------------- + +static void DrawOptionsMenu(void) +{ + if (messageson) + { + MN_DrTextB(DEH_String("ON"), 196, 50); + } + else + { + MN_DrTextB(DEH_String("OFF"), 196, 50); + } + DrawSlider(&OptionsMenu, 3, 10, mouseSensitivity); +} + +//--------------------------------------------------------------------------- +// +// PROC DrawOptions2Menu +// +//--------------------------------------------------------------------------- + +static void DrawOptions2Menu(void) +{ + DrawSlider(&Options2Menu, 1, 9, screenblocks - 3); + DrawSlider(&Options2Menu, 3, 16, snd_MaxVolume); + DrawSlider(&Options2Menu, 5, 16, snd_MusicVolume); +} + +//--------------------------------------------------------------------------- +// +// PROC SCNetCheck +// +//--------------------------------------------------------------------------- + +static boolean SCNetCheck(int option) +{ + if (!netgame) + { // okay to go into the menu + return true; + } + switch (option) + { + case 1: + P_SetMessage(&players[consoleplayer], + "YOU CAN'T START A NEW GAME IN NETPLAY!", true); + break; + case 2: + P_SetMessage(&players[consoleplayer], + "YOU CAN'T LOAD A GAME IN NETPLAY!", true); + break; + default: + break; + } + MenuActive = false; + return false; +} + +//--------------------------------------------------------------------------- +// +// PROC SCQuitGame +// +//--------------------------------------------------------------------------- + +static boolean SCQuitGame(int option) +{ + MenuActive = false; + askforquit = true; + typeofask = 1; //quit game + if (!netgame && !demoplayback) + { + paused = true; + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCEndGame +// +//--------------------------------------------------------------------------- + +static boolean SCEndGame(int option) +{ + if (demoplayback || netgame) + { + return false; + } + MenuActive = false; + askforquit = true; + typeofask = 2; //endgame + if (!netgame && !demoplayback) + { + paused = true; + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCMessages +// +//--------------------------------------------------------------------------- + +static boolean SCMessages(int option) +{ + messageson ^= 1; + if (messageson) + { + P_SetMessage(&players[consoleplayer], DEH_String("MESSAGES ON"), true); + } + else + { + P_SetMessage(&players[consoleplayer], DEH_String("MESSAGES OFF"), true); + } + S_StartSound(NULL, sfx_chat); + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCLoadGame +// +//--------------------------------------------------------------------------- + +static boolean SCLoadGame(int option) +{ + char *filename; + + if (!SlotStatus[option]) + { // slot's empty...don't try and load + return false; + } + + filename = SV_Filename(option); + G_LoadGame(filename); + free(filename); + + MN_DeactivateMenu(); + BorderNeedRefresh = true; + if (quickload == -1) + { + quickload = option + 1; + players[consoleplayer].message = NULL; + players[consoleplayer].messageTics = 1; + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCSaveGame +// +//--------------------------------------------------------------------------- + +static boolean SCSaveGame(int option) +{ + char *ptr; + + if (!FileMenuKeySteal) + { + FileMenuKeySteal = true; + strcpy(oldSlotText, SlotText[option]); + ptr = SlotText[option]; + while (*ptr) + { + ptr++; + } + *ptr = '['; + *(ptr + 1) = 0; + SlotStatus[option]++; + currentSlot = option; + slotptr = ptr - SlotText[option]; + return false; + } + else + { + G_SaveGame(option, SlotText[option]); + FileMenuKeySteal = false; + MN_DeactivateMenu(); + } + BorderNeedRefresh = true; + if (quicksave == -1) + { + quicksave = option + 1; + players[consoleplayer].message = NULL; + players[consoleplayer].messageTics = 1; + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCEpisode +// +//--------------------------------------------------------------------------- + +static boolean SCEpisode(int option) +{ + if (gamemode == shareware && option > 1) + { + P_SetMessage(&players[consoleplayer], + "ONLY AVAILABLE IN THE REGISTERED VERSION", true); + } + else + { + MenuEpisode = option; + SetMenu(MENU_SKILL); + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCSkill +// +//--------------------------------------------------------------------------- + +static boolean SCSkill(int option) +{ + G_DeferedInitNew(option, MenuEpisode, 1); + MN_DeactivateMenu(); + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCMouseSensi +// +//--------------------------------------------------------------------------- + +static boolean SCMouseSensi(int option) +{ + if (option == RIGHT_DIR) + { + if (mouseSensitivity < 9) + { + mouseSensitivity++; + } + } + else if (mouseSensitivity) + { + mouseSensitivity--; + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCSfxVolume +// +//--------------------------------------------------------------------------- + +static boolean SCSfxVolume(int option) +{ + if (option == RIGHT_DIR) + { + if (snd_MaxVolume < 15) + { + snd_MaxVolume++; + } + } + else if (snd_MaxVolume) + { + snd_MaxVolume--; + } + S_SetMaxVolume(false); // don't recalc the sound curve, yet + soundchanged = true; // we'll set it when we leave the menu + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCMusicVolume +// +//--------------------------------------------------------------------------- + +static boolean SCMusicVolume(int option) +{ + if (option == RIGHT_DIR) + { + if (snd_MusicVolume < 15) + { + snd_MusicVolume++; + } + } + else if (snd_MusicVolume) + { + snd_MusicVolume--; + } + S_SetMusicVolume(); + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCScreenSize +// +//--------------------------------------------------------------------------- + +static boolean SCScreenSize(int option) +{ + if (option == RIGHT_DIR) + { + if (screenblocks < 11) + { + screenblocks++; + } + } + else if (screenblocks > 3) + { + screenblocks--; + } + R_SetViewSize(screenblocks, detailLevel); + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCInfo +// +//--------------------------------------------------------------------------- + +static boolean SCInfo(int option) +{ + InfoType = 1; + S_StartSound(NULL, sfx_dorcls); + if (!netgame && !demoplayback) + { + paused = true; + } + return true; +} + +//--------------------------------------------------------------------------- +// +// FUNC MN_Responder +// +//--------------------------------------------------------------------------- + +boolean MN_Responder(event_t * event) +{ + int charTyped; + int key; + int i; + MenuItem_t *item; + extern boolean automapactive; + static boolean shiftdown; + extern void D_StartTitle(void); + extern void G_CheckDemoStatus(void); + char *textBuffer; + + // In testcontrols mode, none of the function keys should do anything + // - the only key is escape to quit. + + if (testcontrols) + { + if (event->type == ev_quit + || (event->type == ev_keydown + && (event->data1 == key_menu_activate + || event->data1 == key_menu_quit))) + { + I_Quit(); + return true; + } + + return false; + } + + // "close" button pressed on window? + if (event->type == ev_quit) + { + // First click on close = bring up quit confirm message. + // Second click = confirm quit. + + if (!MenuActive && askforquit && typeofask == 1) + { + G_CheckDemoStatus(); + I_Quit(); + } + else + { + SCQuitGame(0); + S_StartSound(NULL, sfx_chat); + } + return true; + } + + if (event->data1 == KEY_RSHIFT) + { + shiftdown = (event->type == ev_keydown); + } + if (event->type != ev_keydown) + { + return (false); + } + key = event->data1; + charTyped = event->data2; + + if (InfoType) + { + if (gamemode == shareware) + { + InfoType = (InfoType + 1) % 5; + } + else + { + InfoType = (InfoType + 1) % 4; + } + if (key == KEY_ESCAPE) + { + InfoType = 0; + } + if (!InfoType) + { + paused = false; + MN_DeactivateMenu(); + SB_state = -1; //refresh the statbar + BorderNeedRefresh = true; + } + S_StartSound(NULL, sfx_dorcls); + return (true); //make the info screen eat the keypress + } + + if (ravpic && key == KEY_F1) + { + G_ScreenShot(); + return (true); + } + + if (askforquit) + { + if (key == key_menu_confirm) + { + switch (typeofask) + { + case 1: + G_CheckDemoStatus(); + I_Quit(); + return false; + + case 2: + players[consoleplayer].messageTics = 0; + //set the msg to be cleared + players[consoleplayer].message = NULL; + paused = false; + I_SetPalette(W_CacheLumpName + ("PLAYPAL", PU_CACHE)); + D_StartTitle(); // go to intro/demo mode. + break; + + case 3: + P_SetMessage(&players[consoleplayer], + "QUICKSAVING....", false); + FileMenuKeySteal = true; + SCSaveGame(quicksave - 1); + BorderNeedRefresh = true; + break; + + case 4: + P_SetMessage(&players[consoleplayer], + "QUICKLOADING....", false); + SCLoadGame(quickload - 1); + BorderNeedRefresh = true; + break; + + default: + break; + } + + askforquit = false; + typeofask = 0; + + return true; + } + else if (key == key_menu_abort || key == KEY_ESCAPE) + { + players[consoleplayer].messageTics = 1; //set the msg to be cleared + askforquit = false; + typeofask = 0; + paused = false; + UpdateState |= I_FULLSCRN; + BorderNeedRefresh = true; + return true; + } + + return false; // don't let the keys filter thru + } + + if (!MenuActive && !chatmodeon) + { + if (key == key_menu_decscreen) + { + if (automapactive) + { // Don't screen size in automap + return (false); + } + SCScreenSize(LEFT_DIR); + S_StartSound(NULL, sfx_keyup); + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + return (true); + } + else if (key == key_menu_incscreen) + { + if (automapactive) + { // Don't screen size in automap + return (false); + } + SCScreenSize(RIGHT_DIR); + S_StartSound(NULL, sfx_keyup); + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + return (true); + } + else if (key == key_menu_help) // F1 + { + SCInfo(0); // start up info screens + MenuActive = true; + return (true); + } + else if (key == key_menu_save) // F2 (save game) + { + if (gamestate == GS_LEVEL && !demoplayback) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &SaveMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed + } + return true; + } + else if (key == key_menu_load) // F3 (load game) + { + if (SCNetCheck(2)) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &LoadMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed + } + return true; + } + else if (key == key_menu_volume) // F4 (volume) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &Options2Menu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed + return true; + } + else if (key == key_menu_detail) // F5 (detail) + { + // F5 isn't used in Heretic. (detail level) + return true; + } + else if (key == key_menu_qsave) // F6 (quicksave) + { + if (gamestate == GS_LEVEL && !demoplayback) + { + if (!quicksave || quicksave == -1) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &SaveMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed + quicksave = -1; + P_SetMessage(&players[consoleplayer], + "CHOOSE A QUICKSAVE SLOT", true); + } + else + { + askforquit = true; + typeofask = 3; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_chat); + } + } + return true; + } + else if (key == key_menu_endgame) // F7 (end game) + { + if (gamestate == GS_LEVEL && !demoplayback) + { + S_StartSound(NULL, sfx_chat); + SCEndGame(0); + } + return true; + } + else if (key == key_menu_messages) // F8 (toggle messages) + { + SCMessages(0); + return true; + } + else if (key == key_menu_qload) // F9 (quickload) + { + if (!quickload || quickload == -1) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &LoadMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed + quickload = -1; + P_SetMessage(&players[consoleplayer], + "CHOOSE A QUICKLOAD SLOT", true); + } + else + { + askforquit = true; + if (!netgame && !demoplayback) + { + paused = true; + } + typeofask = 4; + S_StartSound(NULL, sfx_chat); + } + return true; + } + else if (key == key_menu_quit) // F10 (quit) + { + if (gamestate == GS_LEVEL) + { + SCQuitGame(0); + S_StartSound(NULL, sfx_chat); + } + return true; + } + else if (key == key_menu_gamma) // F11 (gamma correction) + { + usegamma++; + if (usegamma > 4) + { + usegamma = 0; + } + I_SetPalette((byte *) W_CacheLumpName("PLAYPAL", PU_CACHE)); + return true; + } + + } + + if (!MenuActive) + { + if (key == key_menu_activate || gamestate == GS_DEMOSCREEN || demoplayback) + { + MN_ActivateMenu(); + return (true); + } + return (false); + } + if (!FileMenuKeySteal) + { + item = &CurrentMenu->items[CurrentItPos]; + + if (key == key_menu_down) // Next menu item + { + do + { + if (CurrentItPos + 1 > CurrentMenu->itemCount - 1) + { + CurrentItPos = 0; + } + else + { + CurrentItPos++; + } + } + while (CurrentMenu->items[CurrentItPos].type == ITT_EMPTY); + S_StartSound(NULL, sfx_switch); + return (true); + } + else if (key == key_menu_up) // Previous menu item + { + do + { + if (CurrentItPos == 0) + { + CurrentItPos = CurrentMenu->itemCount - 1; + } + else + { + CurrentItPos--; + } + } + while (CurrentMenu->items[CurrentItPos].type == ITT_EMPTY); + S_StartSound(NULL, sfx_switch); + return (true); + } + else if (key == key_menu_left) // Slider left + { + if (item->type == ITT_LRFUNC && item->func != NULL) + { + item->func(LEFT_DIR); + S_StartSound(NULL, sfx_keyup); + } + return (true); + } + else if (key == key_menu_right) // Slider right + { + if (item->type == ITT_LRFUNC && item->func != NULL) + { + item->func(RIGHT_DIR); + S_StartSound(NULL, sfx_keyup); + } + return (true); + } + else if (key == key_menu_forward) // Activate item (enter) + { + if (item->type == ITT_SETMENU) + { + SetMenu(item->menu); + } + else if (item->func != NULL) + { + CurrentMenu->oldItPos = CurrentItPos; + if (item->type == ITT_LRFUNC) + { + item->func(RIGHT_DIR); + } + else if (item->type == ITT_EFUNC) + { + if (item->func(item->option)) + { + if (item->menu != MENU_NONE) + { + SetMenu(item->menu); + } + } + } + } + S_StartSound(NULL, sfx_dorcls); + return (true); + } + else if (key == key_menu_activate) // Toggle menu + { + MN_DeactivateMenu(); + return (true); + } + else if (key == key_menu_back) // Go back to previous menu + { + S_StartSound(NULL, sfx_switch); + if (CurrentMenu->prevMenu == MENU_NONE) + { + MN_DeactivateMenu(); + } + else + { + SetMenu(CurrentMenu->prevMenu); + } + return (true); + } + else if (charTyped != 0) + { + // Jump to menu item based on first letter: + + for (i = 0; i < CurrentMenu->itemCount; i++) + { + if (CurrentMenu->items[i].text) + { + if (toupper(charTyped) + == toupper(DEH_String(CurrentMenu->items[i].text)[0])) + { + CurrentItPos = i; + return (true); + } + } + } + } + + return (false); + } + else + { // Editing file names + textBuffer = &SlotText[currentSlot][slotptr]; + if (key == KEY_BACKSPACE) + { + if (slotptr) + { + *textBuffer-- = 0; + *textBuffer = ASCII_CURSOR; + slotptr--; + } + return (true); + } + if (key == KEY_ESCAPE) + { + memset(SlotText[currentSlot], 0, SLOTTEXTLEN + 2); + strcpy(SlotText[currentSlot], oldSlotText); + SlotStatus[currentSlot]--; + MN_DeactivateMenu(); + return (true); + } + if (key == KEY_ENTER) + { + SlotText[currentSlot][slotptr] = 0; // clear the cursor + item = &CurrentMenu->items[CurrentItPos]; + CurrentMenu->oldItPos = CurrentItPos; + if (item->type == ITT_EFUNC) + { + item->func(item->option); + if (item->menu != MENU_NONE) + { + SetMenu(item->menu); + } + } + return (true); + } + if (slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE) + { + if (isalpha(charTyped)) + { + *textBuffer++ = toupper(charTyped); + *textBuffer = ASCII_CURSOR; + slotptr++; + return (true); + } + if (isdigit(charTyped) || charTyped == ' ' + || charTyped == ',' || charTyped == '.' || charTyped == '-' + || charTyped == '!') + { + *textBuffer++ = charTyped; + *textBuffer = ASCII_CURSOR; + slotptr++; + return (true); + } + } + return (true); + } + return (false); +} + +//--------------------------------------------------------------------------- +// +// PROC MN_ActivateMenu +// +//--------------------------------------------------------------------------- + +void MN_ActivateMenu(void) +{ + if (MenuActive) + { + return; + } + if (paused) + { + S_ResumeSound(); + } + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &MainMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DeactivateMenu +// +//--------------------------------------------------------------------------- + +void MN_DeactivateMenu(void) +{ + if (CurrentMenu != NULL) + { + CurrentMenu->oldItPos = CurrentItPos; + } + MenuActive = false; + if (!netgame) + { + paused = false; + } + S_StartSound(NULL, sfx_dorcls); + if (soundchanged) + { + S_SetMaxVolume(true); //recalc the sound curve + soundchanged = false; + } + players[consoleplayer].message = NULL; + players[consoleplayer].messageTics = 1; +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DrawInfo +// +//--------------------------------------------------------------------------- + +void MN_DrawInfo(void) +{ + I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); + V_DrawRawScreen(W_CacheLumpNum(W_GetNumForName("TITLE") + InfoType, + PU_CACHE)); +// V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType, +// PU_CACHE)); +} + + +//--------------------------------------------------------------------------- +// +// PROC SetMenu +// +//--------------------------------------------------------------------------- + +static void SetMenu(MenuType_t menu) +{ + CurrentMenu->oldItPos = CurrentItPos; + CurrentMenu = Menus[menu]; + CurrentItPos = CurrentMenu->oldItPos; +} + +//--------------------------------------------------------------------------- +// +// PROC DrawSlider +// +//--------------------------------------------------------------------------- + +static void DrawSlider(Menu_t * menu, int item, int width, int slot) +{ + int x; + int y; + int x2; + int count; + + x = menu->x + 24; + y = menu->y + 2 + (item * ITEM_HEIGHT); + V_DrawPatch(x - 32, y, W_CacheLumpName(DEH_String("M_SLDLT"), PU_CACHE)); + for (x2 = x, count = width; count--; x2 += 8) + { + V_DrawPatch(x2, y, W_CacheLumpName(DEH_String(count & 1 ? "M_SLDMD1" + : "M_SLDMD2"), PU_CACHE)); + } + V_DrawPatch(x2, y, W_CacheLumpName(DEH_String("M_SLDRT"), PU_CACHE)); + V_DrawPatch(x + 4 + slot * 8, y + 7, + W_CacheLumpName(DEH_String("M_SLDKB"), PU_CACHE)); +} |