1 //**************************************************************************
3 //** mn_menu.c : Heretic 2 : Raven Software, Corp.
10 //**************************************************************************
12 // HEADER FILES ------------------------------------------------------------
24 // MACROS ------------------------------------------------------------------
28 #define ITEM_HEIGHT 20
29 #define SMALL_ITEM_HEIGHT 9
30 #define MENU_MAX_MOUSE_SENS 50
32 #define KEY_INS (0x80+0x52)
33 #define KEY_DEL (0x80+0x53)
34 #define KEY_PGUP (0x80+0x49)
35 #define KEY_PGDN (0x80+0x51)
36 #define KEY_HOME (0x80+0x47)
37 #define KEY_END (0x80+0x4f)
38 #define SELECTOR_XOFFSET (-28)
39 #define SELECTOR_YOFFSET (-1)
40 #define SLOTTEXTLEN 16
41 #define ASCII_CURSOR '['
43 // TYPES -------------------------------------------------------------------
73 void (*func)(int option);
82 void (*drawFunc)(void);
91 void (*textDrawer)(char*,int,int);
107 extern int alwaysrun;
108 extern boolean i_CDMusic;
109 extern int I_CDMusInit( void );
110 extern int I_CDMusStop( void );
112 extern int mouselook;
114 extern int key_right,key_left,key_up,key_down;
115 extern int key_straferight,key_strafeleft,key_jump;
116 extern int key_fire, key_use, key_strafe, key_speed;
117 extern int key_flyup, key_flydown, key_flycenter;
118 extern int key_lookup, key_lookdown, key_lookcenter;
119 extern int key_invleft, key_invright, key_useartifact;
121 char *stupidtable[] = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N",
122 "O","P","Q","R","S","T","U","V","W","X","Y","Z"};
124 extern default_t defaults[];
127 boolean askforkey = false;
129 int *mbone, *mbtwo, *mbthree;
131 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
133 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
135 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
137 char *Key2String(int key);
138 void ClearControls(int key);
139 static void InitFonts(void);
140 static void SetMenu(MenuType_t menu);
141 static void SCQuitGame(int option);
142 static void SCClass(int option);
143 static void SCSkill(int option);
144 static void SCMouseSensi(int option);
145 static void SCSfxVolume(int option);
146 static void SCMusicVolume(int option);
147 static void SCScreenSize(int option);
148 static boolean SCNetCheck(int option);
149 static void SCNetCheck2(int option);
150 static void SCLoadGame(int option);
151 static void SCSaveGame(int option);
152 static void SCMessages(int option);
153 static void SCEndGame(int option);
154 static void SCInfo(int option);
155 static void SCSetKey(int option);
156 static void SCMouselook(int option);
157 static void SCAlwaysRun(int option);
158 static void SCCDAudio(int option);
159 static void DrawMainMenu(void);
160 static void DrawClassMenu(void);
161 static void DrawSkillMenu(void);
162 static void DrawOptionsMenu(void);
163 static void DrawOptions2Menu(void);
164 static void DrawOptions3Menu(void);
165 static void DrawFileSlots(Menu_t *menu);
166 static void DrawFilesMenu(void);
167 static void MN_DrawInfo(void);
168 static void DrawLoadMenu(void);
169 static void DrawSaveMenu(void);
170 static void DrawSlider(Menu_t *menu, int item, int width, int slot);
171 void MN_LoadSlotText(void);
173 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
175 extern int detailLevel;
176 extern int screenblocks;
177 extern char *basePath;
178 extern int key_speed, key_strafe;
179 extern boolean gamekeydown[256]; // The NUMKEYS macro is local to g_game
181 // PUBLIC DATA DEFINITIONS -------------------------------------------------
186 boolean mn_SuicideConsole;
188 // PRIVATE DATA DEFINITIONS ------------------------------------------------
190 static int FontABaseLump;
191 static int FontAYellowBaseLump;
192 static int FontBBaseLump;
193 static int MauloBaseLump;
194 static Menu_t *CurrentMenu;
195 static int CurrentItPos;
196 static int MenuPClass;
198 static boolean soundchanged;
201 static float bgAlpha = 0;
202 static float outFade = 0;
203 static boolean fadingOut = false;
204 static int menuDarkTicks = 15;
205 static int slamInTicks = 9;
209 static boolean FileMenuKeySteal;
210 static boolean slottextloaded;
211 static char SlotText[6][SLOTTEXTLEN+2];
212 static char oldSlotText[SLOTTEXTLEN+2];
213 static int SlotStatus[6];
215 static int currentSlot;
216 static int quicksave;
217 static int quickload;
218 static int typeofask;
220 static MenuItem_t MainItems[] =
222 { ITT_SETMENU, "NEW GAME", SCNetCheck2, 1, MENU_CLASS },
223 { ITT_SETMENU, "OPTIONS", NULL, 0, MENU_OPTIONS },
224 { ITT_SETMENU, "GAME FILES", NULL, 0, MENU_FILES },
225 { ITT_EFUNC, "INFO", SCInfo, 0, MENU_NONE },
226 { ITT_EFUNC, "QUIT GAME", SCQuitGame, 0, MENU_NONE }
229 static Menu_t MainMenu =
239 static MenuItem_t ClassItems[] =
241 { ITT_EFUNC, "FIGHTER", SCClass, 0, MENU_NONE },
242 { ITT_EFUNC, "CLERIC", SCClass, 1, MENU_NONE },
243 { ITT_EFUNC, "MAGE", SCClass, 2, MENU_NONE }
245 ,{ ITT_EFUNC, "ASSASSIN", SCClass, 3, MENU_NONE }
249 static Menu_t ClassMenu =
264 static MenuItem_t FilesItems[] =
266 { ITT_SETMENU, "LOAD GAME", SCNetCheck2, 2, MENU_LOAD },
267 { ITT_SETMENU, "SAVE GAME", NULL, 0, MENU_SAVE }
270 static Menu_t FilesMenu =
280 static MenuItem_t LoadItems[] =
282 { ITT_EFUNC, NULL, SCLoadGame, 0, MENU_NONE },
283 { ITT_EFUNC, NULL, SCLoadGame, 1, MENU_NONE },
284 { ITT_EFUNC, NULL, SCLoadGame, 2, MENU_NONE },
285 { ITT_EFUNC, NULL, SCLoadGame, 3, MENU_NONE },
286 { ITT_EFUNC, NULL, SCLoadGame, 4, MENU_NONE },
287 { ITT_EFUNC, NULL, SCLoadGame, 5, MENU_NONE }
290 static Menu_t LoadMenu =
300 static MenuItem_t SaveItems[] =
302 { ITT_EFUNC, NULL, SCSaveGame, 0, MENU_NONE },
303 { ITT_EFUNC, NULL, SCSaveGame, 1, MENU_NONE },
304 { ITT_EFUNC, NULL, SCSaveGame, 2, MENU_NONE },
305 { ITT_EFUNC, NULL, SCSaveGame, 3, MENU_NONE },
306 { ITT_EFUNC, NULL, SCSaveGame, 4, MENU_NONE },
307 { ITT_EFUNC, NULL, SCSaveGame, 5, MENU_NONE }
310 static Menu_t SaveMenu =
320 static MenuItem_t SkillItems[] =
322 { ITT_EFUNC, NULL, SCSkill, sk_baby, MENU_NONE },
323 { ITT_EFUNC, NULL, SCSkill, sk_easy, MENU_NONE },
324 { ITT_EFUNC, NULL, SCSkill, sk_medium, MENU_NONE },
325 { ITT_EFUNC, NULL, SCSkill, sk_hard, MENU_NONE },
326 { ITT_EFUNC, NULL, SCSkill, sk_nightmare, MENU_NONE }
329 static Menu_t SkillMenu =
339 static MenuItem_t OptionsItems[] =
341 { ITT_EFUNC, "END GAME", SCEndGame, 0, MENU_NONE },
342 { ITT_EFUNC, "MESSAGES : ", SCMessages, 0, MENU_NONE },
343 { ITT_LRFUNC, "MOUSE SENSITIVITY :", SCMouseSensi, 0, MENU_NONE },
344 { ITT_SETMENU, "CONTROL SETUP", NULL, 0, MENU_OPTIONS3 },
345 { ITT_LRFUNC, "MOUSELOOK : ", SCMouselook, 0, MENU_NONE },
346 { ITT_EFUNC, "ALWAYS RUN : ", SCAlwaysRun, 0, MENU_NONE },
347 { ITT_SETMENU, "MORE...", NULL, 0, MENU_OPTIONS2 }
350 static Menu_t OptionsMenu =
361 static MenuItem_t Options2Items[] =
363 { ITT_LRFUNC, "SCREEN SIZE", SCScreenSize, 0, MENU_NONE },
364 { ITT_EMPTY, NULL, NULL, 0, MENU_NONE },
365 { ITT_LRFUNC, "SFX VOLUME", SCSfxVolume, 0, MENU_NONE },
366 { ITT_EMPTY, NULL, NULL, 0, MENU_NONE },
367 { ITT_LRFUNC, "MUSIC VOLUME", SCMusicVolume, 0, MENU_NONE },
368 { ITT_EMPTY, NULL, NULL, 0, MENU_NONE },
369 { ITT_EFUNC, "CD AUDIO :", SCCDAudio, 0, MENU_NONE }
372 static Menu_t Options2Menu =
383 static MenuItem_t Options3Items[] =
385 /* see defaults[] in m_misc.c for the correct option number:
386 * key_right corresponds to defaults[3], which means that we
387 * are using the (index_number - 3) here.
389 { ITT_SETKEY, "TURN RIGHT :", SCSetKey, 0, MENU_NONE },
390 { ITT_SETKEY, "TURN LEFT :", SCSetKey, 1, MENU_NONE },
391 { ITT_SETKEY, "MOVE FORWARD :", SCSetKey, 2, MENU_NONE },
392 { ITT_SETKEY, "MOVE BACK :" , SCSetKey, 3, MENU_NONE },
393 { ITT_SETKEY, "STRAFE LEFT :", SCSetKey, 4, MENU_NONE },
394 { ITT_SETKEY, "STRAFE RIGHT :", SCSetKey, 5, MENU_NONE },
395 { ITT_SETKEY, "JUMP :", SCSetKey, 6, MENU_NONE },
396 { ITT_SETKEY, "FLY UP :", SCSetKey, 7, MENU_NONE },
397 { ITT_SETKEY, "FLY DOWN :", SCSetKey, 8, MENU_NONE },
398 { ITT_SETKEY, "FLY CENTER :", SCSetKey, 9, MENU_NONE },
399 { ITT_SETKEY, "LOOK UP :", SCSetKey, 10, MENU_NONE },
400 { ITT_SETKEY, "LOOK DOWN :", SCSetKey, 11, MENU_NONE },
401 { ITT_SETKEY, "LOOK CENTER :", SCSetKey, 12, MENU_NONE },
402 { ITT_SETKEY, "INVETORY LEFT :", SCSetKey, 13, MENU_NONE },
403 { ITT_SETKEY, "INVENTORY RIGHT :", SCSetKey, 14, MENU_NONE },
404 { ITT_SETKEY, "USE ARTIFACT :", SCSetKey, 15, MENU_NONE },
405 { ITT_SETKEY, "FIRE :", SCSetKey, 16, MENU_NONE },
406 { ITT_SETKEY, "USE :", SCSetKey, 17, MENU_NONE },
407 { ITT_SETKEY, "STRAFE :", SCSetKey, 18, MENU_NONE },
408 { ITT_SETKEY, "SPEED :", SCSetKey, 19, MENU_NONE }
410 static Menu_t Options3Menu =
420 static Menu_t *Menus[] =
433 #if defined(__linux) || #defined(__FreeBSD__)
434 static char *GammaText[] =
444 // CODE --------------------------------------------------------------------
445 char *Key2String(int key)
449 return "RIGHT ARROW";
480 if(key >= 'a' && key <= 'z') return stupidtable[(key - 'a')];
485 void ClearControls(int key)
491 if(*defaults[i].location == key) *defaults[i].location = 0;
495 //---------------------------------------------------------------------------
499 //---------------------------------------------------------------------------
505 // messageson = true; // Set by defaults in .CFG
506 MauloBaseLump = W_GetNumForName("FBULA0"); // ("M_SKL00");
509 //---------------------------------------------------------------------------
513 //---------------------------------------------------------------------------
515 static void InitFonts(void)
517 FontABaseLump = W_GetNumForName("FONTA_S")+1;
518 FontAYellowBaseLump = W_GetNumForName("FONTAY_S")+1;
519 FontBBaseLump = W_GetNumForName("FONTB_S")+1;
522 //---------------------------------------------------------------------------
526 // Draw text using font A.
528 //---------------------------------------------------------------------------
530 void MN_DrTextA(char *text, int x, int y)
536 OGL_SetColorAndAlpha( 1, 1, 1, 1 );
539 while((c = *text++) != 0)
547 p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
549 OGL_DrawPatch_CS(x, y, FontABaseLump+c-33);
551 V_DrawPatch(x, y, p);
558 //==========================================================================
562 //==========================================================================
564 void MN_DrTextAYellow(char *text, int x, int y)
570 OGL_SetColorAndAlpha( 1, 1, 1, 1 );
573 while((c = *text++) != 0)
581 p = W_CacheLumpNum(FontAYellowBaseLump+c-33, PU_CACHE);
583 OGL_DrawPatch_CS(x, y, FontAYellowBaseLump+c-33);
585 V_DrawPatch(x, y, p);
592 //---------------------------------------------------------------------------
594 // FUNC MN_TextAWidth
596 // Returns the pixel width of a string using font A.
598 //---------------------------------------------------------------------------
600 int MN_TextAWidth(char *text)
607 while((c = *text++) != 0)
615 p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
622 //---------------------------------------------------------------------------
626 // Draw text using font B.
628 //---------------------------------------------------------------------------
630 void MN_DrTextB(char *text, int x, int y)
636 OGL_SetColorAndAlpha( 1, 1, 1, 1 );
639 while((c = *text++) != 0)
647 p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
649 OGL_DrawPatch_CS(x, y, FontBBaseLump+c-33);
651 V_DrawPatch(x, y, p);
658 //---------------------------------------------------------------------------
660 // FUNC MN_TextBWidth
662 // Returns the pixel width of a string using font B.
664 //---------------------------------------------------------------------------
666 int MN_TextBWidth(char *text)
673 while((c = *text++) != 0)
681 p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
688 //---------------------------------------------------------------------------
692 //---------------------------------------------------------------------------
696 if(MenuActive == false)
701 bgAlpha -= .5/(float)menuDarkTicks;
702 if(bgAlpha < 0) bgAlpha = 0;
706 outFade += 1/(float)slamInTicks;
707 if(outFade > 1) fadingOut = false;
717 void MN_OGL_SetupState(float time)
719 glMatrixMode(GL_MODELVIEW);
722 if(time > 1 && time <= 2)
725 glTranslatef(160, 100, 0);
726 glScalef(.9+time*.1, .9+time*.1, 1);
727 glTranslatef(-160, -100, 0);
728 glColor4f(1, 1, 1, time);
732 glTranslatef(160, 100, 0);
733 glScalef(2-time, 2-time, 1);
734 glTranslatef(-160, -100, 0);
735 glColor4f(1, 1, 1, time*time);
738 void MN_OGL_RestoreState()
740 glMatrixMode(GL_MODELVIEW);
746 //---------------------------------------------------------------------------
750 //---------------------------------------------------------------------------
754 "ARE YOU SURE YOU WANT TO QUIT?",
755 "ARE YOU SURE YOU WANT TO END THE GAME?",
756 "DO YOU WANT TO QUICKSAVE THE GAME NAMED",
757 "DO YOU WANT TO QUICKLOAD THE GAME NAMED",
758 "ARE YOU SURE YOU WANT TO SUICIDE?"
762 #define BETA_FLASH_TEXT "BETA"
773 if(MenuActive == false)
778 UpdateState |= I_FULLSCRN;
779 BorderNeedRefresh = true;
780 //OGL_SetNoTexture();
781 glDisable( GL_TEXTURE_2D );
782 OGL_DrawRect(0,0,320,200,0,0,0,bgAlpha);
783 glEnable( GL_TEXTURE_2D );
788 MN_DrTextA(QuitEndMsg[typeofask-1], 160-
789 MN_TextAWidth(QuitEndMsg[typeofask-1])/2, 80);
792 MN_DrTextA(SlotText[quicksave-1], 160-
793 MN_TextAWidth(SlotText[quicksave-1])/2, 90);
795 MN_TextAWidth(SlotText[quicksave-1])/2, 90);
799 MN_DrTextA(SlotText[quickload-1], 160-
800 MN_TextAWidth(SlotText[quickload-1])/2, 90);
802 MN_TextAWidth(SlotText[quicksave-1])/2, 90);
804 UpdateState |= I_FULLSCRN;
808 if( MenuActive || fadingOut )
810 int effTime = (MenuTime>menuDarkTicks)? menuDarkTicks : MenuTime;
811 float temp = .5 * effTime/(float)menuDarkTicks;
813 UpdateState |= I_FULLSCRN;
817 if(temp > bgAlpha) bgAlpha = temp;
818 effTime = (MenuTime>slamInTicks)? slamInTicks : MenuTime;
819 temp = effTime / (float)slamInTicks;
821 // Draw a dark background. It makes it easier to read the menus.
822 //OGL_SetNoTexture();
823 glDisable( GL_TEXTURE_2D );
824 OGL_DrawRect(0,0,320,200,0,0,0,bgAlpha);
825 glEnable( GL_TEXTURE_2D );
827 else temp = outFade+1;
828 MN_OGL_SetupState(temp);
833 MN_OGL_RestoreState();
836 //if(screenblocks < 10)
838 BorderNeedRefresh = true;
840 if(CurrentMenu->drawFunc != NULL)
842 CurrentMenu->drawFunc();
846 item = CurrentMenu->items;
847 if(item->type == ITT_SETKEY)
849 for(i = 0; i < CurrentMenu->itemCount; i++)
857 MN_DrTextA(item->text, x, y+6);
861 MN_DrTextB(item->text, x, y);
863 y += CurrentMenu->step;
866 y = CurrentMenu->y+(CurrentItPos*CurrentMenu->step)+SELECTOR_YOFFSET;
867 selName = MenuTime&16 ? "M_SLCTR1" : "M_SLCTR2";
868 OGL_DrawPatch_CS(x+SELECTOR_XOFFSET, y, W_GetNumForName(selName));
870 MN_OGL_RestoreState();
875 UpdateState |= I_FULLSCRN;
881 if(screenblocks < 10)
883 BorderNeedRefresh = true;
885 if(CurrentMenu->drawFunc != NULL)
887 CurrentMenu->drawFunc();
891 item = CurrentMenu->items;
892 if(item->type == ITT_SETKEY)
894 for(i = 0; i < CurrentMenu->itemCount; i++)
902 MN_DrTextA(item->text, x, y+6);
906 MN_DrTextB(item->text, x, y);
908 y += CurrentMenu->step;
911 y = CurrentMenu->y+(CurrentItPos*CurrentMenu->step)+SELECTOR_YOFFSET;
912 selName = MenuTime&16 ? "M_SLCTR1" : "M_SLCTR2";
913 V_DrawPatch(x+SELECTOR_XOFFSET, y,
914 W_CacheLumpName(selName, PU_CACHE));
919 //---------------------------------------------------------------------------
923 //---------------------------------------------------------------------------
925 static void DrawMainMenu(void)
929 frame = (MenuTime/5)%7;
932 OGL_DrawPatch_CS( 88, 0, W_GetNumForName("M_HTIC") );
933 OGL_DrawPatch_CS( 37, 80, MauloBaseLump+(frame+2)%7 );
934 OGL_DrawPatch_CS( 278, 80, MauloBaseLump+frame );
936 V_DrawPatch(88, 0, W_CacheLumpName("M_HTIC", PU_CACHE));
937 // Old Gold skull positions: (40, 10) and (232, 10)
938 V_DrawPatch(37, 80, W_CacheLumpNum(MauloBaseLump+(frame+2)%7,
940 V_DrawPatch(278, 80, W_CacheLumpNum(MauloBaseLump+frame, PU_CACHE));
944 //==========================================================================
948 //==========================================================================
950 static void DrawClassMenu(void)
953 static char *boxLumpName[4] =
960 static char *walkLumpName[4] =
968 MN_DrTextB("CHOOSE CLASS:", 34, 24);
969 class = (pclass_t)CurrentMenu->items[CurrentItPos].option;
971 OGL_DrawPatch_CS(174, 8, W_GetNumForName(boxLumpName[class]));
972 OGL_DrawPatch_CS(174+24, 8+12,
973 W_GetNumForName(walkLumpName[class])+((MenuTime>>3)&3));
975 V_DrawPatch(174, 8, W_CacheLumpName(boxLumpName[class], PU_CACHE));
976 V_DrawPatch(174+24, 8+12,
977 W_CacheLumpNum(W_GetNumForName(walkLumpName[class])
978 +((MenuTime>>3)&3), PU_CACHE));
982 //---------------------------------------------------------------------------
984 // PROC DrawSkillMenu
986 //---------------------------------------------------------------------------
988 static void DrawSkillMenu(void)
990 MN_DrTextB("CHOOSE SKILL LEVEL:", 74, 16);
993 //---------------------------------------------------------------------------
995 // PROC DrawFilesMenu
997 //---------------------------------------------------------------------------
999 static void DrawFilesMenu(void)
1001 // clear out the quicksave/quickload stuff
1004 P_ClearMessage(&players[consoleplayer]);
1007 //---------------------------------------------------------------------------
1009 // PROC DrawLoadMenu
1011 //---------------------------------------------------------------------------
1013 static void DrawLoadMenu(void)
1015 MN_DrTextB("LOAD GAME", 160-MN_TextBWidth("LOAD GAME")/2, 10);
1020 DrawFileSlots(&LoadMenu);
1023 //---------------------------------------------------------------------------
1025 // PROC DrawSaveMenu
1027 //---------------------------------------------------------------------------
1029 static void DrawSaveMenu(void)
1031 MN_DrTextB("SAVE GAME", 160-MN_TextBWidth("SAVE GAME")/2, 10);
1036 DrawFileSlots(&SaveMenu);
1039 //===========================================================================
1043 // For each slot, looks for save games and reads the description field.
1045 //===========================================================================
1047 void MN_LoadSlotText(void)
1052 char versionText[HXS_VERSION_TEXT_LENGTH];
1053 char description[HXS_DESCRIPTION_LENGTH];
1056 for(slot = 0; slot < 6; slot++)
1059 snprintf(name, 100, "%shex%d.hxs", basePath, slot);
1060 fp = fopen(name, "rb");
1063 fread(description, HXS_DESCRIPTION_LENGTH, 1, fp);
1064 fread(versionText, HXS_VERSION_TEXT_LENGTH, 1, fp);
1066 if(!strcmp(versionText, HXS_VERSION_TEXT))
1073 memcpy(SlotText[slot], description, SLOTTEXTLEN);
1074 SlotStatus[slot] = 1;
1078 memset(SlotText[slot], 0, SLOTTEXTLEN);
1079 SlotStatus[slot] = 0;
1082 slottextloaded = true;
1085 //---------------------------------------------------------------------------
1087 // PROC DrawFileSlots
1089 //---------------------------------------------------------------------------
1091 static void DrawFileSlots(Menu_t *menu)
1099 for(i = 0; i < 6; i++)
1102 OGL_DrawPatch_CS(x, y, W_GetNumForName("M_FSLOT"));
1104 V_DrawPatch(x, y, W_CacheLumpName("M_FSLOT", PU_CACHE));
1108 MN_DrTextA(SlotText[i], x+5, y+5);
1114 //---------------------------------------------------------------------------
1116 // PROC DrawOptionsMenu
1118 //---------------------------------------------------------------------------
1120 static void DrawOptionsMenu(void)
1125 MN_DrTextB("ON", 196, 50);
1129 MN_DrTextB("OFF", 196, 50);
1131 MN_DrTextB(mlooktext[mouselook], 208, 110);
1133 sprintf(num,"%d",mouseSensitivity);
1134 MN_DrTextB(num,265, 71);
1138 MN_DrTextB("ON", 208, 130);
1142 MN_DrTextB("OFF", 208,130);
1146 //---------------------------------------------------------------------------
1148 // PROC DrawOptions2Menu
1150 //---------------------------------------------------------------------------
1152 static void DrawOptions2Menu(void)
1154 DrawSlider(&Options2Menu, 1, 9, screenblocks-3);
1155 DrawSlider(&Options2Menu, 3, 16, snd_MaxVolume);
1156 DrawSlider(&Options2Menu, 5, 16, snd_MusicVolume);
1159 MN_DrTextB("ON", 196, 140);
1163 MN_DrTextB("OFF", 196, 140);
1168 static void DrawOptions3Menu(void)
1174 if(askforkey && keyaskedfor == i) {
1175 MN_DrTextAYellow("???", 195, (i*SMALL_ITEM_HEIGHT+26));
1178 MN_DrTextA(Key2String(*defaults[i+FirstKey+3].location),
1179 195, (i*SMALL_ITEM_HEIGHT+26));
1185 //---------------------------------------------------------------------------
1189 //---------------------------------------------------------------------------
1191 static void SCQuitGame(int option)
1195 typeofask = 1; //quit game
1196 if(!netgame && !demoplayback)
1202 //---------------------------------------------------------------------------
1206 //---------------------------------------------------------------------------
1208 static void SCEndGame(int option)
1218 typeofask = 2; //endgame
1219 if(!netgame && !demoplayback)
1226 //---------------------------------------------------------------------------
1230 //---------------------------------------------------------------------------
1232 static void SCMessages(int option)
1237 P_SetMessage(&players[consoleplayer], "MESSAGES ON", true);
1241 P_SetMessage(&players[consoleplayer], "MESSAGES OFF", true);
1243 S_StartSound(NULL, SFX_CHAT);
1246 //===========================================================================
1250 //===========================================================================
1252 static boolean SCNetCheck(int option)
1261 P_SetMessage(&players[consoleplayer],
1262 "YOU CAN'T START A NEW GAME IN NETPLAY!", true);
1264 case 2: // load game
1265 P_SetMessage(&players[consoleplayer],
1266 "YOU CAN'T LOAD A GAME IN NETPLAY!", true);
1269 P_SetMessage(&players[consoleplayer],
1270 "YOU CAN'T END A GAME IN NETPLAY!", true);
1274 S_StartSound(NULL, SFX_CHAT);
1278 //===========================================================================
1282 //===========================================================================
1284 static void SCNetCheck2(int option)
1290 //---------------------------------------------------------------------------
1294 //---------------------------------------------------------------------------
1296 static void SCLoadGame(int option)
1298 if(!SlotStatus[option])
1299 { // Don't try to load from an empty slot
1303 MN_DeactivateMenu();
1304 BorderNeedRefresh = true;
1307 quickload = option+1;
1308 P_ClearMessage(&players[consoleplayer]);
1312 //---------------------------------------------------------------------------
1316 //---------------------------------------------------------------------------
1318 static void SCSaveGame(int option)
1321 player_t *player = &players[consoleplayer];
1323 if(gamestate != GS_LEVEL || demoplayback
1324 || player->playerstate == PST_DEAD)
1326 FileMenuKeySteal = false;
1330 if(!FileMenuKeySteal)
1332 FileMenuKeySteal = true;
1333 strcpy(oldSlotText, SlotText[option]);
1334 ptr = SlotText[option];
1341 SlotStatus[option]++;
1342 currentSlot = option;
1343 slotptr = ptr-SlotText[option];
1348 G_SaveGame(option, SlotText[option]);
1349 FileMenuKeySteal = false;
1350 MN_DeactivateMenu();
1352 BorderNeedRefresh = true;
1355 quicksave = option+1;
1356 P_ClearMessage(&players[consoleplayer]);
1360 //==========================================================================
1364 //==========================================================================
1366 static void SCClass(int option)
1370 P_SetMessage(&players[consoleplayer],
1371 "YOU CAN'T START A NEW GAME FROM WITHIN A NETGAME!", true);
1374 MenuPClass = option;
1377 case PCLASS_FIGHTER:
1379 SkillItems[0].text = "SQUIRE";
1380 SkillItems[1].text = "KNIGHT";
1381 SkillItems[2].text = "WARRIOR";
1382 SkillItems[3].text = "BERSERKER";
1383 SkillItems[4].text = "TITAN";
1387 SkillItems[0].text = "ALTAR BOY";
1388 SkillItems[1].text = "ACOLYTE";
1389 SkillItems[2].text = "PRIEST";
1390 SkillItems[3].text = "CARDINAL";
1391 SkillItems[4].text = "POPE";
1395 SkillItems[0].text = "APPRENTICE";
1396 SkillItems[1].text = "ENCHANTER";
1397 SkillItems[2].text = "SORCERER";
1398 SkillItems[3].text = "WARLOCK";
1399 SkillItems[4].text = "ARCHIMAGE";
1404 SkillItems[0].text = "KNAVE";
1405 SkillItems[1].text = "ROUGE";
1406 SkillItems[2].text = "CUTTHROAT";
1407 SkillItems[3].text = "EXECUTIONER";
1408 SkillItems[4].text = "WIDOW MAKER";
1412 SetMenu(MENU_SKILL);
1415 //---------------------------------------------------------------------------
1419 //---------------------------------------------------------------------------
1421 static void SCSkill(int option)
1423 extern int SB_state;
1425 PlayerClass[consoleplayer] = MenuPClass;
1426 G_DeferredNewGame(option);
1429 MN_DeactivateMenu();
1432 //---------------------------------------------------------------------------
1434 // PROC SCMouseSensi
1436 //---------------------------------------------------------------------------
1438 static void SCMouseSensi(int option)
1440 if(option == RIGHT_DIR)
1442 if(mouseSensitivity < MENU_MAX_MOUSE_SENS)
1447 else if(mouseSensitivity)
1453 //---------------------------------------------------------------------------
1457 //---------------------------------------------------------------------------
1459 static void SCSfxVolume(int option)
1461 if(option == RIGHT_DIR)
1463 if(snd_MaxVolume < 15)
1468 else if(snd_MaxVolume)
1472 soundchanged = true; // we'll set it when we leave the menu
1475 //---------------------------------------------------------------------------
1477 // PROC SCMusicVolume
1479 //---------------------------------------------------------------------------
1481 static void SCMusicVolume(int option)
1483 if(option == RIGHT_DIR)
1485 if(snd_MusicVolume < 15)
1490 else if(snd_MusicVolume)
1497 //---------------------------------------------------------------------------
1499 // PROC SCScreenSize
1501 //---------------------------------------------------------------------------
1503 static void SCScreenSize(int option)
1505 if(option == RIGHT_DIR)
1507 if(screenblocks < 11)
1512 else if(screenblocks > 3)
1516 R_SetViewSize(screenblocks, detailLevel);
1519 //---------------------------------------------------------------------------
1523 //---------------------------------------------------------------------------
1525 static void SCInfo(int option)
1528 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1529 if(!netgame && !demoplayback)
1535 //---------------------------------------------------------------------------
1539 //---------------------------------------------------------------------------
1540 static void SCSetKey(int option)
1543 keyaskedfor = option;
1544 if(!netgame && !demoplayback)
1550 //---------------------------------------------------------------------------
1552 // PROC SCMouslook(int option)
1554 //---------------------------------------------------------------------------
1555 static void SCMouselook(int option)
1557 if(option == RIGHT_DIR)
1559 if(mouselook < 2) mouselook++;
1562 else if(mouselook) mouselook--;
1565 static void SCAlwaysRun(int option)
1567 if(alwaysrun) alwaysrun=0;
1570 static void SCCDAudio(int option)
1581 ST_Message("Attempting to initialize CD Music: ");
1584 i_CDMusic = (I_CDMusInit() != -1);
1587 { // The user is trying to use the cdrom for both game and music
1592 ST_Message("initialized.\n");
1596 ST_Message("failed.\n");
1601 //---------------------------------------------------------------------------
1603 // FUNC MN_Responder
1605 //---------------------------------------------------------------------------
1607 boolean MN_Responder(event_t *event)
1612 extern boolean automapactive;
1613 static boolean shiftdown;
1614 extern void H2_StartTitle(void);
1615 extern void G_CheckDemoStatus(void);
1618 if(askforkey && event->type == ev_keydown)
1620 ClearControls(event->data1);
1621 *defaults[keyaskedfor+3+FirstKey].location = event->data1;
1625 if(askforkey && event->type == ev_mouse)
1628 mbone = defaults[keyaskedfor+3+FirstKey].location;
1630 mbtwo = defaults[keyaskedfor+3+FirstKey].location;
1632 mbthree = defaults[keyaskedfor+3+FirstKey].location;
1636 if(event->data1 == KEY_RSHIFT)
1638 shiftdown = (event->type == ev_keydown);
1640 if(event->type != ev_keydown)
1649 InfoType = (InfoType+1)%5;
1653 InfoType = (InfoType+1)%4;
1655 if(key == KEY_ESCAPE)
1661 if(!netgame && !demoplayback)
1665 MN_DeactivateMenu();
1666 SB_state = -1; //refresh the statbar
1667 BorderNeedRefresh = true;
1669 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1670 return(true); //make the info screen eat the keypress
1673 if(ravpic && key == KEY_F1)
1689 G_CheckDemoStatus();
1693 P_ClearMessage(&players[consoleplayer]);
1697 I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
1698 H2_StartTitle(); // go to intro/demo mode.
1701 P_SetMessage(&players[consoleplayer],
1702 "QUICKSAVING....", false);
1703 FileMenuKeySteal = true;
1704 SCSaveGame(quicksave-1);
1707 BorderNeedRefresh = true;
1710 P_SetMessage(&players[consoleplayer],
1711 "QUICKLOADING....", false);
1712 SCLoadGame(quickload-1);
1715 BorderNeedRefresh = true;
1720 BorderNeedRefresh = true;
1721 mn_SuicideConsole = true;
1725 return true; // eat the 'y' keypress
1733 players[consoleplayer].messageTics = 0;
1737 UpdateState |= I_FULLSCRN;
1738 BorderNeedRefresh = true;
1743 return false; // don't let the keys filter thru
1745 if(MenuActive == false && !chatmodeon)
1751 { // Don't screen size in automap
1754 SCScreenSize(LEFT_DIR);
1755 S_StartSound(NULL, SFX_PICKUP_KEY);
1756 BorderNeedRefresh = true;
1757 UpdateState |= I_FULLSCRN;
1761 { // Don't screen size in automap
1764 SCScreenSize(RIGHT_DIR);
1765 S_StartSound(NULL, SFX_PICKUP_KEY);
1766 BorderNeedRefresh = true;
1767 UpdateState |= I_FULLSCRN;
1773 typeofask = 5; // suicide
1777 case KEY_F1: // help screen
1778 SCInfo(0); // start up info screens
1781 case KEY_F2: // save game
1782 if(gamestate == GS_LEVEL && !demoplayback)
1785 FileMenuKeySteal = false;
1787 CurrentMenu = &SaveMenu;
1788 CurrentItPos = CurrentMenu->oldItPos;
1789 if(!netgame && !demoplayback)
1793 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1794 slottextloaded = false; //reload the slot text, when needed
1797 case KEY_F3: // load game
1801 FileMenuKeySteal = false;
1803 CurrentMenu = &LoadMenu;
1804 CurrentItPos = CurrentMenu->oldItPos;
1805 if(!netgame && !demoplayback)
1809 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1810 slottextloaded = false; //reload the slot text, when needed
1813 case KEY_F4: // volume
1815 FileMenuKeySteal = false;
1817 CurrentMenu = &Options2Menu;
1818 CurrentItPos = CurrentMenu->oldItPos;
1819 if(!netgame && !demoplayback)
1823 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1824 slottextloaded = false; //reload the slot text, when needed
1829 typeofask = 5; // suicide
1831 case KEY_F6: // quicksave
1832 if(gamestate == GS_LEVEL && !demoplayback)
1834 if(!quicksave || quicksave == -1)
1837 FileMenuKeySteal = false;
1839 CurrentMenu = &SaveMenu;
1840 CurrentItPos = CurrentMenu->oldItPos;
1841 if(!netgame && !demoplayback)
1845 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1846 slottextloaded = false; //reload the slot text
1848 P_SetMessage(&players[consoleplayer],
1849 "CHOOSE A QUICKSAVE SLOT", true);
1855 if(!netgame && !demoplayback)
1859 S_StartSound(NULL, SFX_CHAT);
1863 case KEY_F7: // endgame
1866 if(gamestate == GS_LEVEL && !demoplayback)
1868 S_StartSound(NULL, SFX_CHAT);
1873 case KEY_F8: // toggle messages
1876 case KEY_F9: // quickload
1879 if(!quickload || quickload == -1)
1882 FileMenuKeySteal = false;
1884 CurrentMenu = &LoadMenu;
1885 CurrentItPos = CurrentMenu->oldItPos;
1886 if(!netgame && !demoplayback)
1890 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1891 slottextloaded = false; // reload the slot text
1893 P_SetMessage(&players[consoleplayer],
1894 "CHOOSE A QUICKLOAD SLOT", true);
1899 if(!netgame && !demoplayback)
1904 S_StartSound(NULL, SFX_CHAT);
1908 case KEY_F10: // quit
1909 if(gamestate == GS_LEVEL || gamestate == GS_FINALE)
1912 S_StartSound(NULL, SFX_CHAT);
1915 case KEY_F11: // F11 - gamma mode correction
1921 SB_PaletteFlash(true); // force change
1922 P_SetMessage(&players[consoleplayer], GammaText[usegamma],
1925 case KEY_F12: // F12 - reload current map (devmaps mode)
1926 if(netgame || DevMaps == false)
1930 if(gamekeydown[key_speed])
1934 if(gamekeydown[key_strafe])
1938 G_DeferedInitNew(gameskill, gameepisode, gamemap);
1939 P_SetMessage(&players[consoleplayer], TXT_CHEATWARP,
1947 if(MenuActive == false)
1949 if(key == KEY_ESCAPE || gamestate == GS_DEMOSCREEN || demoplayback)
1956 if(!FileMenuKeySteal)
1958 item = &CurrentMenu->items[CurrentItPos];
1964 if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos+1 > CurrentMenu->itemCount-1)
1968 CurrentItPos = 0; //End of Key menu
1976 else if(CurrentItPos+1 > CurrentMenu->itemCount-1)
1984 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
1985 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
1991 if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos==0)
1995 CurrentItPos = 14; //End of Key menu
2003 else if(CurrentItPos == 0)
2005 CurrentItPos = CurrentMenu->itemCount-1;
2011 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
2012 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
2016 if(item->type == ITT_LRFUNC && item->func != NULL)
2018 item->func(LEFT_DIR);
2019 S_StartSound(NULL, SFX_PICKUP_KEY);
2023 case KEY_RIGHTARROW:
2024 if(item->type == ITT_LRFUNC && item->func != NULL)
2026 item->func(RIGHT_DIR);
2027 S_StartSound(NULL, SFX_PICKUP_KEY);
2032 if(item->type == ITT_SETMENU)
2034 if(item->func != NULL)
2036 item->func(item->option);
2038 SetMenu(item->menu);
2040 else if(item->func != NULL)
2042 CurrentMenu->oldItPos = CurrentItPos;
2043 if(item->type == ITT_LRFUNC)
2045 item->func(RIGHT_DIR);
2047 else if(item->type == ITT_EFUNC)
2049 item->func(item->option);
2051 else if(item->type == ITT_SETKEY)
2053 item->func(item->option);
2056 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
2060 MN_DeactivateMenu();
2063 S_StartSound(NULL, SFX_PICKUP_KEY);
2064 if(CurrentMenu->prevMenu == MENU_NONE)
2066 MN_DeactivateMenu();
2070 SetMenu(CurrentMenu->prevMenu);
2074 for(i = 0; i < CurrentMenu->itemCount; i++)
2076 if(CurrentMenu->items[i].text)
2079 == toupper(CurrentMenu->items[i].text[0]))
2091 { // Editing file names
2092 textBuffer = &SlotText[currentSlot][slotptr];
2093 if(key == KEY_BACKSPACE)
2098 *textBuffer = ASCII_CURSOR;
2103 if(key == KEY_ESCAPE)
2105 memset(SlotText[currentSlot], 0, SLOTTEXTLEN+2);
2106 strcpy(SlotText[currentSlot], oldSlotText);
2107 SlotStatus[currentSlot]--;
2108 MN_DeactivateMenu();
2111 if(key == KEY_ENTER)
2113 SlotText[currentSlot][slotptr] = 0; // clear the cursor
2114 item = &CurrentMenu->items[CurrentItPos];
2115 CurrentMenu->oldItPos = CurrentItPos;
2116 if(item->type == ITT_EFUNC)
2118 item->func(item->option);
2119 if(item->menu != MENU_NONE)
2121 SetMenu(item->menu);
2126 if(slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE)
2128 if((key >= 'a' && key <= 'z'))
2130 *textBuffer++ = key-32;
2131 *textBuffer = ASCII_CURSOR;
2135 if(((key >= '0' && key <= '9') || key == ' '
2136 || key == ',' || key == '.' || key == '-')
2139 *textBuffer++ = key;
2140 *textBuffer = ASCII_CURSOR;
2144 if(shiftdown && key == '1')
2146 *textBuffer++ = '!';
2147 *textBuffer = ASCII_CURSOR;
2157 //---------------------------------------------------------------------------
2159 // PROC MN_ActivateMenu
2161 //---------------------------------------------------------------------------
2163 void MN_ActivateMenu(void)
2174 FileMenuKeySteal = false;
2176 CurrentMenu = &MainMenu;
2177 CurrentItPos = CurrentMenu->oldItPos;
2178 if(!netgame && !demoplayback)
2182 S_StartSound(NULL, SFX_PLATFORM_STOP);
2183 slottextloaded = false; //reload the slot text, when needed
2186 //---------------------------------------------------------------------------
2188 // PROC MN_DeactivateMenu
2190 //---------------------------------------------------------------------------
2192 void MN_DeactivateMenu(void)
2194 CurrentMenu->oldItPos = CurrentItPos;
2200 S_StartSound(NULL, SFX_PLATFORM_STOP);
2201 P_ClearMessage(&players[consoleplayer]);
2204 //---------------------------------------------------------------------------
2208 //---------------------------------------------------------------------------
2210 void MN_DrawInfo(void)
2214 OGL_DrawRawScreen( W_GetNumForName("TITLE")+InfoType );
2216 I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
2217 memcpy(screen, (byte *)W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2218 PU_CACHE), SCREENWIDTH*SCREENHEIGHT);
2219 // V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2225 //---------------------------------------------------------------------------
2229 //---------------------------------------------------------------------------
2231 static void SetMenu(MenuType_t menu)
2233 CurrentMenu->oldItPos = CurrentItPos;
2234 CurrentMenu = Menus[menu];
2235 CurrentItPos = CurrentMenu->oldItPos;
2238 //---------------------------------------------------------------------------
2242 //---------------------------------------------------------------------------
2244 static void DrawSlider(Menu_t *menu, int item, int width, int slot)
2252 y = menu->y+2+(item*ITEM_HEIGHT);
2255 OGL_DrawPatch_CS(x-32, y, W_GetNumForName("M_SLDLT"));
2256 for(x2 = x, count = width; count--; x2 += 8)
2258 OGL_DrawPatch_CS( x2, y, W_GetNumForName(count&1 ? "M_SLDMD1" :
2261 OGL_DrawPatch_CS(x2, y, W_GetNumForName("M_SLDRT"));
2262 OGL_DrawPatch_CS(x+4+slot*8, y+7, W_GetNumForName("M_SLDKB"));
2264 V_DrawPatch(x-32, y, W_CacheLumpName("M_SLDLT", PU_CACHE));
2265 for(x2 = x, count = width; count--; x2 += 8)
2267 V_DrawPatch(x2, y, W_CacheLumpName(count&1 ? "M_SLDMD1"
2268 : "M_SLDMD2", PU_CACHE));
2270 V_DrawPatch(x2, y, W_CacheLumpName("M_SLDRT", PU_CACHE));
2271 V_DrawPatch(x+4+slot*8, y+7, W_CacheLumpName("M_SLDKB", PU_CACHE));