18 #define ITEM_HEIGHT 20
19 #define SELECTOR_XOFFSET (-28)
20 #define SELECTOR_YOFFSET (-1)
21 #define SLOTTEXTLEN 16
22 #define ASCII_CURSOR '['
52 boolean (*func)(int option);
61 void (*drawFunc)(void);
70 static void InitFonts(void);
71 static void SetMenu(MenuType_t menu);
72 static boolean SCNetCheck(int option);
73 static boolean SCQuitGame(int option);
74 static boolean SCEpisode(int option);
75 static boolean SCSkill(int option);
76 static boolean SCMouseSensi(int option);
77 static boolean SCSfxVolume(int option);
78 static boolean SCMusicVolume(int option);
79 static boolean SCScreenSize(int option);
80 static boolean SCLoadGame(int option);
81 static boolean SCSaveGame(int option);
82 static boolean SCMessages(int option);
83 static boolean SCEndGame(int option);
84 static boolean SCInfo(int option);
85 static void DrawMainMenu(void);
86 static void DrawEpisodeMenu(void);
87 static void DrawSkillMenu(void);
88 static void DrawOptionsMenu(void);
89 static void DrawOptions2Menu(void);
90 static void DrawFileSlots(Menu_t *menu);
91 static void DrawFilesMenu(void);
92 static void MN_DrawInfo(void);
93 static void DrawLoadMenu(void);
94 static void DrawSaveMenu(void);
95 static void DrawSlider(Menu_t *menu, int item, int width, int slot);
96 void MN_LoadSlotText(void);
100 extern int detailLevel;
101 extern int screenblocks;
111 static int FontABaseLump;
112 static int FontBBaseLump;
113 static int SkullBaseLump;
114 static Menu_t *CurrentMenu;
115 static int CurrentItPos;
116 static int MenuEpisode;
118 static boolean soundchanged;
121 static float bgAlpha = 0;
122 static float outFade = 0;
123 static boolean fadingOut = false;
124 static int menuDarkTicks = 15;
125 static int slamInTicks = 9;
130 static boolean FileMenuKeySteal;
131 static boolean slottextloaded;
132 static char SlotText[6][SLOTTEXTLEN+2];
133 static char oldSlotText[SLOTTEXTLEN+2];
134 static int SlotStatus[6];
136 static int currentSlot;
137 static int quicksave;
138 static int quickload;
140 static MenuItem_t MainItems[] =
142 { ITT_EFUNC, "NEW GAME", SCNetCheck, 1, MENU_EPISODE },
143 { ITT_SETMENU, "OPTIONS", NULL, 0, MENU_OPTIONS },
144 { ITT_SETMENU, "GAME FILES", NULL, 0, MENU_FILES },
145 { ITT_EFUNC, "INFO", SCInfo, 0, MENU_NONE },
146 { ITT_EFUNC, "QUIT GAME", SCQuitGame, 0, MENU_NONE }
149 static Menu_t MainMenu =
158 static MenuItem_t EpisodeItems[] =
160 { ITT_EFUNC, "CITY OF THE DAMNED", SCEpisode, 1, MENU_NONE },
161 { ITT_EFUNC, "HELL'S MAW", SCEpisode, 2, MENU_NONE },
162 { ITT_EFUNC, "THE DOME OF D'SPARIL", SCEpisode, 3, MENU_NONE },
163 { ITT_EFUNC, "THE OSSUARY", SCEpisode, 4, MENU_NONE },
164 { ITT_EFUNC, "THE STAGNANT DEMESNE", SCEpisode, 5, MENU_NONE }
167 static Menu_t EpisodeMenu =
176 static MenuItem_t FilesItems[] =
178 { ITT_EFUNC, "LOAD GAME", SCNetCheck, 2, MENU_LOAD },
179 { ITT_SETMENU, "SAVE GAME", NULL, 0, MENU_SAVE }
182 static Menu_t FilesMenu =
191 static MenuItem_t LoadItems[] =
193 { ITT_EFUNC, NULL, SCLoadGame, 0, MENU_NONE },
194 { ITT_EFUNC, NULL, SCLoadGame, 1, MENU_NONE },
195 { ITT_EFUNC, NULL, SCLoadGame, 2, MENU_NONE },
196 { ITT_EFUNC, NULL, SCLoadGame, 3, MENU_NONE },
197 { ITT_EFUNC, NULL, SCLoadGame, 4, MENU_NONE },
198 { ITT_EFUNC, NULL, SCLoadGame, 5, MENU_NONE }
201 static Menu_t LoadMenu =
210 static MenuItem_t SaveItems[] =
212 { ITT_EFUNC, NULL, SCSaveGame, 0, MENU_NONE },
213 { ITT_EFUNC, NULL, SCSaveGame, 1, MENU_NONE },
214 { ITT_EFUNC, NULL, SCSaveGame, 2, MENU_NONE },
215 { ITT_EFUNC, NULL, SCSaveGame, 3, MENU_NONE },
216 { ITT_EFUNC, NULL, SCSaveGame, 4, MENU_NONE },
217 { ITT_EFUNC, NULL, SCSaveGame, 5, MENU_NONE }
220 static Menu_t SaveMenu =
229 static MenuItem_t SkillItems[] =
231 { ITT_EFUNC, "THOU NEEDETH A WET-NURSE", SCSkill, sk_baby, MENU_NONE },
232 { ITT_EFUNC, "YELLOWBELLIES-R-US", SCSkill, sk_easy, MENU_NONE },
233 { ITT_EFUNC, "BRINGEST THEM ONETH", SCSkill, sk_medium, MENU_NONE },
234 { ITT_EFUNC, "THOU ART A SMITE-MEISTER", SCSkill, sk_hard, MENU_NONE },
235 { ITT_EFUNC, "BLACK PLAGUE POSSESSES THEE",
236 SCSkill, sk_nightmare, MENU_NONE }
239 static Menu_t SkillMenu =
248 static MenuItem_t OptionsItems[] =
250 { ITT_EFUNC, "END GAME", SCEndGame, 0, MENU_NONE },
251 { ITT_EFUNC, "MESSAGES : ", SCMessages, 0, MENU_NONE },
252 { ITT_LRFUNC, "MOUSE SENSITIVITY", SCMouseSensi, 0, MENU_NONE },
253 { ITT_EMPTY, NULL, NULL, 0, MENU_NONE },
254 { ITT_SETMENU, "MORE...", NULL, 0, MENU_OPTIONS2 }
257 static Menu_t OptionsMenu =
266 static MenuItem_t Options2Items[] =
268 { ITT_LRFUNC, "SCREEN SIZE", SCScreenSize, 0, MENU_NONE },
269 { ITT_EMPTY, NULL, NULL, 0, MENU_NONE },
270 { ITT_LRFUNC, "SFX VOLUME", SCSfxVolume, 0, MENU_NONE },
271 { ITT_EMPTY, NULL, NULL, 0, MENU_NONE },
272 { ITT_LRFUNC, "MUSIC VOLUME", SCMusicVolume, 0, MENU_NONE },
273 { ITT_EMPTY, NULL, NULL, 0, MENU_NONE }
276 static Menu_t Options2Menu =
285 static Menu_t *Menus[] =
297 //---------------------------------------------------------------------------
301 //---------------------------------------------------------------------------
308 SkullBaseLump = W_GetNumForName("M_SKL00");
310 { // Add episodes 4 and 5 to the menu
311 EpisodeMenu.itemCount = 5;
312 EpisodeMenu.y -= ITEM_HEIGHT;
316 //---------------------------------------------------------------------------
320 //---------------------------------------------------------------------------
322 static void InitFonts(void)
324 FontABaseLump = W_GetNumForName("FONTA_S")+1;
325 FontBBaseLump = W_GetNumForName("FONTB_S")+1;
328 //---------------------------------------------------------------------------
332 // Draw text using font A.
334 //---------------------------------------------------------------------------
336 void MN_DrTextA(char *text, int x, int y)
342 OGL_SetColorAndAlpha( 1, 1, 1, 1 );
345 while((c = *text++) != 0)
353 p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
355 OGL_DrawPatch_CS(x, y, FontABaseLump+c-33);
357 V_DrawPatch(x, y, p);
364 //---------------------------------------------------------------------------
366 // FUNC MN_TextAWidth
368 // Returns the pixel width of a string using font A.
370 //---------------------------------------------------------------------------
372 int MN_TextAWidth(char *text)
379 while((c = *text++) != 0)
387 p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
394 //---------------------------------------------------------------------------
398 // Draw text using font B.
400 //---------------------------------------------------------------------------
402 void MN_DrTextB(char *text, int x, int y)
408 OGL_SetColorAndAlpha( 1, 1, 1, 1 );
411 while((c = *text++) != 0)
419 p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
421 OGL_DrawPatch_CS(x, y, FontBBaseLump+c-33);
423 V_DrawPatch(x, y, p);
430 //---------------------------------------------------------------------------
432 // FUNC MN_TextBWidth
434 // Returns the pixel width of a string using font B.
436 //---------------------------------------------------------------------------
438 int MN_TextBWidth(char *text)
445 while((c = *text++) != 0)
453 p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
460 //---------------------------------------------------------------------------
464 //---------------------------------------------------------------------------
468 if(MenuActive == false)
473 bgAlpha -= .5/(float)menuDarkTicks;
474 if(bgAlpha < 0) bgAlpha = 0;
478 outFade += 1/(float)slamInTicks;
479 if(outFade > 1) fadingOut = false;
488 void MN_OGL_SetupState(float time)
490 glMatrixMode(GL_MODELVIEW);
493 if(time > 1 && time <= 2)
496 glTranslatef(160, 100, 0);
497 glScalef(.9+time*.1, .9+time*.1, 1);
498 glTranslatef(-160, -100, 0);
499 glColor4f(1, 1, 1, time);
503 glTranslatef(160, 100, 0);
504 glScalef(2-time, 2-time, 1);
505 glTranslatef(-160, -100, 0);
506 glColor4f(1, 1, 1, time*time);
509 void MN_OGL_RestoreState()
511 glMatrixMode(GL_MODELVIEW);
516 //---------------------------------------------------------------------------
520 //---------------------------------------------------------------------------
524 "ARE YOU SURE YOU WANT TO QUIT?",
525 "ARE YOU SURE YOU WANT TO END THE GAME?",
526 "DO YOU WANT TO QUICKSAVE THE GAME NAMED",
527 "DO YOU WANT TO QUICKLOAD THE GAME NAMED"
538 if(MenuActive == false)
543 UpdateState |= I_FULLSCRN;
544 BorderNeedRefresh = true;
545 //OGL_SetNoTexture();
546 glDisable( GL_TEXTURE_2D );
547 OGL_DrawRect(0,0,320,200,0,0,0,bgAlpha);
548 glEnable( GL_TEXTURE_2D );
553 MN_DrTextA(QuitEndMsg[typeofask-1], 160-
554 MN_TextAWidth(QuitEndMsg[typeofask-1])/2, 80);
557 MN_DrTextA(SlotText[quicksave-1], 160-
558 MN_TextAWidth(SlotText[quicksave-1])/2, 90);
560 MN_TextAWidth(SlotText[quicksave-1])/2, 90);
564 MN_DrTextA(SlotText[quickload-1], 160-
565 MN_TextAWidth(SlotText[quickload-1])/2, 90);
567 MN_TextAWidth(SlotText[quickload-1])/2, 90);
569 UpdateState |= I_FULLSCRN;
574 if( MenuActive || fadingOut )
576 int effTime = (MenuTime>menuDarkTicks)? menuDarkTicks : MenuTime;
577 float temp = .5 * effTime/(float)menuDarkTicks;
579 UpdateState |= I_FULLSCRN;
583 if(temp > bgAlpha) bgAlpha = temp;
584 effTime = (MenuTime>slamInTicks)? slamInTicks : MenuTime;
585 temp = effTime / (float)slamInTicks;
587 // Draw a dark background. It makes it easier to read the menus.
588 //OGL_SetNoTexture();
589 glDisable( GL_TEXTURE_2D );
590 OGL_DrawRect(0,0,320,200,0,0,0,bgAlpha);
591 glEnable( GL_TEXTURE_2D );
593 else temp = outFade+1;
594 MN_OGL_SetupState(temp);
599 MN_OGL_RestoreState();
602 //if(screenblocks < 10)
604 BorderNeedRefresh = true;
606 if(CurrentMenu->drawFunc != NULL)
608 CurrentMenu->drawFunc();
612 item = CurrentMenu->items;
613 for(i = 0; i < CurrentMenu->itemCount; i++)
621 MN_DrTextB(item->text, x, y);
626 y = CurrentMenu->y+(CurrentItPos*ITEM_HEIGHT)+SELECTOR_YOFFSET;
627 selName = MenuTime&16 ? "M_SLCTR1" : "M_SLCTR2";
628 OGL_DrawPatch_CS(x+SELECTOR_XOFFSET, y, W_GetNumForName(selName));
630 MN_OGL_RestoreState();
635 UpdateState |= I_FULLSCRN;
641 if(screenblocks < 10)
643 BorderNeedRefresh = true;
645 if(CurrentMenu->drawFunc != NULL)
647 CurrentMenu->drawFunc();
651 item = CurrentMenu->items;
652 for(i = 0; i < CurrentMenu->itemCount; i++)
654 if(item->type != ITT_EMPTY && item->text)
656 MN_DrTextB(item->text, x, y);
661 y = CurrentMenu->y+(CurrentItPos*ITEM_HEIGHT)+SELECTOR_YOFFSET;
662 selName = MenuTime&16 ? "M_SLCTR1" : "M_SLCTR2";
663 V_DrawPatch(x+SELECTOR_XOFFSET, y,
664 W_CacheLumpName(selName, PU_CACHE));
669 //---------------------------------------------------------------------------
673 //---------------------------------------------------------------------------
675 static void DrawMainMenu(void)
679 frame = (MenuTime/3)%18;
681 OGL_DrawPatch_CS( 88, 0, W_GetNumForName("M_HTIC") );
682 OGL_DrawPatch_CS( 40, 10, SkullBaseLump+(17-frame) );
683 OGL_DrawPatch_CS( 232, 10, SkullBaseLump+frame );
685 V_DrawPatch(88, 0, W_CacheLumpName("M_HTIC", PU_CACHE));
686 V_DrawPatch(40, 10, W_CacheLumpNum(SkullBaseLump+(17-frame),
688 V_DrawPatch(232, 10, W_CacheLumpNum(SkullBaseLump+frame, PU_CACHE));
692 //---------------------------------------------------------------------------
694 // PROC DrawEpisodeMenu
696 //---------------------------------------------------------------------------
698 static void DrawEpisodeMenu(void)
702 //---------------------------------------------------------------------------
704 // PROC DrawSkillMenu
706 //---------------------------------------------------------------------------
708 static void DrawSkillMenu(void)
712 //---------------------------------------------------------------------------
714 // PROC DrawFilesMenu
716 //---------------------------------------------------------------------------
718 static void DrawFilesMenu(void)
720 // clear out the quicksave/quickload stuff
723 players[consoleplayer].message = NULL;
724 players[consoleplayer].messageTics = 1;
727 //---------------------------------------------------------------------------
731 //---------------------------------------------------------------------------
733 static void DrawLoadMenu(void)
735 MN_DrTextB("LOAD GAME", 160-MN_TextBWidth("LOAD GAME")/2, 10);
740 DrawFileSlots(&LoadMenu);
743 //---------------------------------------------------------------------------
747 //---------------------------------------------------------------------------
749 static void DrawSaveMenu(void)
751 MN_DrTextB("SAVE GAME", 160-MN_TextBWidth("SAVE GAME")/2, 10);
756 DrawFileSlots(&SaveMenu);
759 //===========================================================================
763 // Loads in the text message for each slot
764 //===========================================================================
766 void MN_LoadSlotText(void)
773 for (i = 0; i < 6; i++)
777 sprintf(name, SAVEGAMENAMECD"%d.hsg", i);
781 sprintf(name, SAVEGAMENAME"%d.hsg", i);
783 fp = fopen(name, "rb+");
786 SlotText[i][0] = 0; // empty the string
790 count = fread(&SlotText[i], SLOTTEXTLEN, 1, fp);
794 slottextloaded = true;
797 //---------------------------------------------------------------------------
799 // PROC DrawFileSlots
801 //---------------------------------------------------------------------------
803 static void DrawFileSlots(Menu_t *menu)
811 for(i = 0; i < 6; i++)
814 OGL_DrawPatch_CS(x, y, W_GetNumForName("M_FSLOT"));
816 V_DrawPatch(x, y, W_CacheLumpName("M_FSLOT", PU_CACHE));
820 MN_DrTextA(SlotText[i], x+5, y+5);
826 //---------------------------------------------------------------------------
828 // PROC DrawOptionsMenu
830 //---------------------------------------------------------------------------
832 static void DrawOptionsMenu(void)
836 MN_DrTextB("ON", 196, 50);
840 MN_DrTextB("OFF", 196, 50);
842 DrawSlider(&OptionsMenu, 3, 10, mouseSensitivity);
845 //---------------------------------------------------------------------------
847 // PROC DrawOptions2Menu
849 //---------------------------------------------------------------------------
851 static void DrawOptions2Menu(void)
853 DrawSlider(&Options2Menu, 1, 9, screenblocks-3);
854 DrawSlider(&Options2Menu, 3, 16, snd_MaxVolume);
855 DrawSlider(&Options2Menu, 5, 16, snd_MusicVolume);
858 //---------------------------------------------------------------------------
862 //---------------------------------------------------------------------------
864 static boolean SCNetCheck(int option)
867 { // okay to go into the menu
873 P_SetMessage(&players[consoleplayer],
874 "YOU CAN'T START A NEW GAME IN NETPLAY!", true);
877 P_SetMessage(&players[consoleplayer],
878 "YOU CAN'T LOAD A GAME IN NETPLAY!", true);
887 //---------------------------------------------------------------------------
891 //---------------------------------------------------------------------------
893 static boolean SCQuitGame(int option)
897 typeofask = 1; //quit game
898 if(!netgame && !demoplayback)
905 //---------------------------------------------------------------------------
909 //---------------------------------------------------------------------------
911 static boolean SCEndGame(int option)
913 if(demoplayback || netgame)
919 typeofask = 2; //endgame
920 if(!netgame && !demoplayback)
927 //---------------------------------------------------------------------------
931 //---------------------------------------------------------------------------
933 static boolean SCMessages(int option)
938 P_SetMessage(&players[consoleplayer], "MESSAGES ON", true);
942 P_SetMessage(&players[consoleplayer], "MESSAGES OFF", true);
944 S_StartSound(NULL, sfx_chat);
948 //---------------------------------------------------------------------------
952 //---------------------------------------------------------------------------
954 static boolean SCLoadGame(int option)
958 if(!SlotStatus[option])
959 { // slot's empty...don't try and load
964 sprintf(name, SAVEGAMENAMECD"%d.hsg", option);
968 sprintf(name, SAVEGAMENAME"%d.hsg", option);
972 BorderNeedRefresh = true;
975 quickload = option+1;
976 players[consoleplayer].message = NULL;
977 players[consoleplayer].messageTics = 1;
982 //---------------------------------------------------------------------------
986 //---------------------------------------------------------------------------
988 static boolean SCSaveGame(int option)
992 if(!FileMenuKeySteal)
994 FileMenuKeySteal = true;
995 strcpy(oldSlotText, SlotText[option]);
996 ptr = SlotText[option];
1003 SlotStatus[option]++;
1004 currentSlot = option;
1005 slotptr = ptr-SlotText[option];
1010 G_SaveGame(option, SlotText[option]);
1011 FileMenuKeySteal = false;
1012 MN_DeactivateMenu();
1014 BorderNeedRefresh = true;
1017 quicksave = option+1;
1018 players[consoleplayer].message = NULL;
1019 players[consoleplayer].messageTics = 1;
1024 //---------------------------------------------------------------------------
1028 //---------------------------------------------------------------------------
1030 static boolean SCEpisode(int option)
1032 if(shareware && option > 1)
1034 P_SetMessage(&players[consoleplayer],
1035 "ONLY AVAILABLE IN THE REGISTERED VERSION", true);
1039 MenuEpisode = option;
1040 SetMenu(MENU_SKILL);
1045 //---------------------------------------------------------------------------
1049 //---------------------------------------------------------------------------
1051 static boolean SCSkill(int option)
1053 G_DeferedInitNew(option, MenuEpisode, 1);
1054 MN_DeactivateMenu();
1058 //---------------------------------------------------------------------------
1060 // PROC SCMouseSensi
1062 //---------------------------------------------------------------------------
1064 static boolean SCMouseSensi(int option)
1066 if(option == RIGHT_DIR)
1068 if(mouseSensitivity < 9)
1073 else if(mouseSensitivity)
1080 //---------------------------------------------------------------------------
1084 //---------------------------------------------------------------------------
1086 static boolean SCSfxVolume(int option)
1088 if(option == RIGHT_DIR)
1090 if(snd_MaxVolume < 15)
1095 else if(snd_MaxVolume)
1099 S_SetMaxVolume(false); // don't recalc the sound curve, yet
1100 soundchanged = true; // we'll set it when we leave the menu
1104 //---------------------------------------------------------------------------
1106 // PROC SCMusicVolume
1108 //---------------------------------------------------------------------------
1110 static boolean SCMusicVolume(int option)
1112 if(option == RIGHT_DIR)
1114 if(snd_MusicVolume < 15)
1119 else if(snd_MusicVolume)
1127 //---------------------------------------------------------------------------
1129 // PROC SCScreenSize
1131 //---------------------------------------------------------------------------
1133 static boolean SCScreenSize(int option)
1135 if(option == RIGHT_DIR)
1137 if(screenblocks < 11)
1142 else if(screenblocks > 3)
1146 R_SetViewSize(screenblocks, detailLevel);
1150 //---------------------------------------------------------------------------
1154 //---------------------------------------------------------------------------
1156 static boolean SCInfo(int option)
1159 S_StartSound(NULL, sfx_dorcls);
1160 if(!netgame && !demoplayback)
1167 //---------------------------------------------------------------------------
1169 // FUNC MN_Responder
1171 //---------------------------------------------------------------------------
1173 boolean MN_Responder(event_t *event)
1178 extern boolean automapactive;
1179 static boolean shiftdown;
1180 extern void D_StartTitle(void);
1181 extern void G_CheckDemoStatus(void);
1184 if(event->data1 == KEY_RSHIFT)
1186 shiftdown = (event->type == ev_keydown);
1188 if(event->type != ev_keydown)
1197 InfoType = (InfoType+1)%5;
1201 InfoType = (InfoType+1)%4;
1203 if(key == KEY_ESCAPE)
1210 MN_DeactivateMenu();
1211 SB_state = -1; //refresh the statbar
1212 BorderNeedRefresh = true;
1214 S_StartSound(NULL, sfx_dorcls);
1215 return(true); //make the info screen eat the keypress
1218 if(ravpic && key == KEY_F1)
1234 G_CheckDemoStatus();
1238 players[consoleplayer].messageTics = 0;
1239 //set the msg to be cleared
1240 players[consoleplayer].message = NULL;
1244 I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
1245 D_StartTitle(); // go to intro/demo mode.
1248 P_SetMessage(&players[consoleplayer], "QUICKSAVING....", false);
1249 FileMenuKeySteal = true;
1250 SCSaveGame(quicksave-1);
1253 BorderNeedRefresh = true;
1256 P_SetMessage(&players[consoleplayer], "QUICKLOADING....", false);
1257 SCLoadGame(quickload-1);
1260 BorderNeedRefresh = true;
1263 return true; // eat the 'y' keypress
1271 players[consoleplayer].messageTics = 1; //set the msg to be cleared
1275 UpdateState |= I_FULLSCRN;
1276 BorderNeedRefresh = true;
1281 return false; // don't let the keys filter thru
1283 if(MenuActive == false && !chatmodeon)
1289 { // Don't screen size in automap
1292 SCScreenSize(LEFT_DIR);
1293 S_StartSound(NULL, sfx_keyup);
1294 BorderNeedRefresh = true;
1295 UpdateState |= I_FULLSCRN;
1299 { // Don't screen size in automap
1302 SCScreenSize(RIGHT_DIR);
1303 S_StartSound(NULL, sfx_keyup);
1304 BorderNeedRefresh = true;
1305 UpdateState |= I_FULLSCRN;
1308 case KEY_F1: // help screen
1309 SCInfo(0); // start up info screens
1312 case KEY_F2: // save game
1313 if(gamestate == GS_LEVEL && !demoplayback)
1316 FileMenuKeySteal = false;
1318 CurrentMenu = &SaveMenu;
1319 CurrentItPos = CurrentMenu->oldItPos;
1320 if(!netgame && !demoplayback)
1324 S_StartSound(NULL, sfx_dorcls);
1325 slottextloaded = false; //reload the slot text, when needed
1328 case KEY_F3: // load game
1332 FileMenuKeySteal = false;
1334 CurrentMenu = &LoadMenu;
1335 CurrentItPos = CurrentMenu->oldItPos;
1336 if(!netgame && !demoplayback)
1340 S_StartSound(NULL, sfx_dorcls);
1341 slottextloaded = false; //reload the slot text, when needed
1344 case KEY_F4: // volume
1346 FileMenuKeySteal = false;
1348 CurrentMenu = &Options2Menu;
1349 CurrentItPos = CurrentMenu->oldItPos;
1350 if(!netgame && !demoplayback)
1354 S_StartSound(NULL, sfx_dorcls);
1355 slottextloaded = false; //reload the slot text, when needed
1357 case KEY_F5: // F5 isn't used in Heretic. (detail level)
1359 case KEY_F6: // quicksave
1360 if(gamestate == GS_LEVEL && !demoplayback)
1362 if(!quicksave || quicksave == -1)
1365 FileMenuKeySteal = false;
1367 CurrentMenu = &SaveMenu;
1368 CurrentItPos = CurrentMenu->oldItPos;
1369 if(!netgame && !demoplayback)
1373 S_StartSound(NULL, sfx_dorcls);
1374 slottextloaded = false; //reload the slot text, when needed
1376 P_SetMessage(&players[consoleplayer],
1377 "CHOOSE A QUICKSAVE SLOT", true);
1383 if(!netgame && !demoplayback)
1387 S_StartSound(NULL, sfx_chat);
1391 case KEY_F7: // endgame
1392 if(gamestate == GS_LEVEL && !demoplayback)
1394 S_StartSound(NULL, sfx_chat);
1398 case KEY_F8: // toggle messages
1401 case KEY_F9: // quickload
1402 if(!quickload || quickload == -1)
1405 FileMenuKeySteal = false;
1407 CurrentMenu = &LoadMenu;
1408 CurrentItPos = CurrentMenu->oldItPos;
1409 if(!netgame && !demoplayback)
1413 S_StartSound(NULL, sfx_dorcls);
1414 slottextloaded = false; //reload the slot text, when needed
1416 P_SetMessage(&players[consoleplayer],
1417 "CHOOSE A QUICKLOAD SLOT", true);
1422 if(!netgame && !demoplayback)
1427 S_StartSound(NULL, sfx_chat);
1430 case KEY_F10: // quit
1431 if(gamestate == GS_LEVEL)
1434 S_StartSound(NULL, sfx_chat);
1437 case KEY_F11: // F11 - gamma mode correction
1446 I_SetPalette((byte *)W_CacheLumpName("PLAYPAL", PU_CACHE));
1454 if(MenuActive == false)
1456 if(key == KEY_ESCAPE || gamestate == GS_DEMOSCREEN || demoplayback)
1463 if(!FileMenuKeySteal)
1465 item = &CurrentMenu->items[CurrentItPos];
1471 if(CurrentItPos+1 > CurrentMenu->itemCount-1)
1479 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
1480 S_StartSound(NULL, sfx_switch);
1486 if(CurrentItPos == 0)
1488 CurrentItPos = CurrentMenu->itemCount-1;
1494 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
1495 S_StartSound(NULL, sfx_switch);
1499 if(item->type == ITT_LRFUNC && item->func != NULL)
1501 item->func(LEFT_DIR);
1502 S_StartSound(NULL, sfx_keyup);
1506 case KEY_RIGHTARROW:
1507 if(item->type == ITT_LRFUNC && item->func != NULL)
1509 item->func(RIGHT_DIR);
1510 S_StartSound(NULL, sfx_keyup);
1515 if(item->type == ITT_SETMENU)
1517 SetMenu(item->menu);
1519 else if(item->func != NULL)
1521 CurrentMenu->oldItPos = CurrentItPos;
1522 if(item->type == ITT_LRFUNC)
1524 item->func(RIGHT_DIR);
1526 else if(item->type == ITT_EFUNC)
1528 if(item->func(item->option))
1530 if(item->menu != MENU_NONE)
1532 SetMenu(item->menu);
1537 S_StartSound(NULL, sfx_dorcls);
1541 MN_DeactivateMenu();
1544 S_StartSound(NULL, sfx_switch);
1545 if(CurrentMenu->prevMenu == MENU_NONE)
1547 MN_DeactivateMenu();
1551 SetMenu(CurrentMenu->prevMenu);
1555 for(i = 0; i < CurrentMenu->itemCount; i++)
1557 if(CurrentMenu->items[i].text)
1560 == toupper(CurrentMenu->items[i].text[0]))
1572 { // Editing file names
1573 textBuffer = &SlotText[currentSlot][slotptr];
1574 if(key == KEY_BACKSPACE)
1579 *textBuffer = ASCII_CURSOR;
1584 if(key == KEY_ESCAPE)
1586 memset(SlotText[currentSlot], 0, SLOTTEXTLEN+2);
1587 strcpy(SlotText[currentSlot], oldSlotText);
1588 SlotStatus[currentSlot]--;
1589 MN_DeactivateMenu();
1592 if(key == KEY_ENTER)
1594 SlotText[currentSlot][slotptr] = 0; // clear the cursor
1595 item = &CurrentMenu->items[CurrentItPos];
1596 CurrentMenu->oldItPos = CurrentItPos;
1597 if(item->type == ITT_EFUNC)
1599 item->func(item->option);
1600 if(item->menu != MENU_NONE)
1602 SetMenu(item->menu);
1607 if(slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE)
1609 if((key >= 'a' && key <= 'z'))
1611 *textBuffer++ = key-32;
1612 *textBuffer = ASCII_CURSOR;
1616 if(((key >= '0' && key <= '9') || key == ' '
1617 || key == ',' || key == '.' || key == '-')
1620 *textBuffer++ = key;
1621 *textBuffer = ASCII_CURSOR;
1625 if(shiftdown && key == '1')
1627 *textBuffer++ = '!';
1628 *textBuffer = ASCII_CURSOR;
1638 //---------------------------------------------------------------------------
1640 // PROC MN_ActivateMenu
1642 //---------------------------------------------------------------------------
1644 void MN_ActivateMenu(void)
1655 FileMenuKeySteal = false;
1657 CurrentMenu = &MainMenu;
1658 CurrentItPos = CurrentMenu->oldItPos;
1659 if(!netgame && !demoplayback)
1663 S_StartSound(NULL, sfx_dorcls);
1664 slottextloaded = false; //reload the slot text, when needed
1667 //---------------------------------------------------------------------------
1669 // PROC MN_DeactivateMenu
1671 //---------------------------------------------------------------------------
1673 void MN_DeactivateMenu(void)
1675 CurrentMenu->oldItPos = CurrentItPos;
1681 S_StartSound(NULL, sfx_dorcls);
1684 S_SetMaxVolume(true); //recalc the sound curve
1685 soundchanged = false;
1687 players[consoleplayer].message = NULL;
1688 players[consoleplayer].messageTics = 1;
1691 //---------------------------------------------------------------------------
1695 //---------------------------------------------------------------------------
1697 void MN_DrawInfo(void)
1701 OGL_DrawRawScreen( W_GetNumForName("TITLE")+InfoType );
1703 I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
1704 memcpy(screen, (byte *)W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
1705 PU_CACHE), SCREENWIDTH*SCREENHEIGHT);
1706 // V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
1712 //---------------------------------------------------------------------------
1716 //---------------------------------------------------------------------------
1718 static void SetMenu(MenuType_t menu)
1720 CurrentMenu->oldItPos = CurrentItPos;
1721 CurrentMenu = Menus[menu];
1722 CurrentItPos = CurrentMenu->oldItPos;
1725 //---------------------------------------------------------------------------
1729 //---------------------------------------------------------------------------
1731 static void DrawSlider(Menu_t *menu, int item, int width, int slot)
1739 y = menu->y+2+(item*ITEM_HEIGHT);
1741 OGL_DrawPatch_CS(x-32, y, W_GetNumForName("M_SLDLT"));
1742 for(x2 = x, count = width; count--; x2 += 8)
1744 OGL_DrawPatch_CS( x2, y, W_GetNumForName(count&1 ? "M_SLDMD1" :
1747 OGL_DrawPatch_CS(x2, y, W_GetNumForName("M_SLDRT"));
1748 OGL_DrawPatch_CS(x+4+slot*8, y+7, W_GetNumForName("M_SLDKB"));
1750 V_DrawPatch(x-32, y, W_CacheLumpName("M_SLDLT", PU_CACHE));
1751 for(x2 = x, count = width; count--; x2 += 8)
1753 V_DrawPatch(x2, y, W_CacheLumpName(count&1 ? "M_SLDMD1"
1754 : "M_SLDMD2", PU_CACHE));
1756 V_DrawPatch(x2, y, W_CacheLumpName("M_SLDRT", PU_CACHE));
1757 V_DrawPatch(x+4+slot*8, y+7, W_CacheLumpName("M_SLDKB", PU_CACHE));