summaryrefslogtreecommitdiff
path: root/src/heretic/mn_menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/heretic/mn_menu.c')
-rw-r--r--src/heretic/mn_menu.c1674
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));
+}