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;
210 static boolean FileMenuKeySteal;
211 static boolean slottextloaded;
212 static char SlotText[6][SLOTTEXTLEN+2];
213 static char oldSlotText[SLOTTEXTLEN+2];
214 static int SlotStatus[6];
216 static int currentSlot;
217 static int quicksave;
218 static int quickload;
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 { ITT_SETKEY, "TURN RIGHT :", SCSetKey, 0, MENU_NONE },
386 { ITT_SETKEY, "TURN LEFT :", SCSetKey, 1, MENU_NONE },
387 { ITT_SETKEY, "MOVE FORWARD :", SCSetKey, 2, MENU_NONE },
388 { ITT_SETKEY, "MOVE BACK :" , SCSetKey, 3, MENU_NONE },
389 { ITT_SETKEY, "STRAFE LEFT :", SCSetKey, 4, MENU_NONE },
390 { ITT_SETKEY, "STRAFE RIGHT :", SCSetKey, 5, MENU_NONE },
391 { ITT_SETKEY, "FLY UP :", SCSetKey, 6, MENU_NONE },
392 { ITT_SETKEY, "FLY DOWN :", SCSetKey, 7, MENU_NONE },
393 { ITT_SETKEY, "FLY CENTER :", SCSetKey, 8, MENU_NONE },
394 { ITT_SETKEY, "JUMP :", SCSetKey, 9, MENU_NONE },
395 { ITT_SETKEY, "LOOK UP :", SCSetKey, 10, MENU_NONE },
396 { ITT_SETKEY, "LOOK DOWN :", SCSetKey, 11, MENU_NONE },
397 { ITT_SETKEY, "LOOK CENTER :", SCSetKey, 12, MENU_NONE },
398 { ITT_SETKEY, "INVETORY LEFT :", SCSetKey, 13, MENU_NONE },
399 { ITT_SETKEY, "INVENTORY RIGHT :", SCSetKey, 14, MENU_NONE },
400 { ITT_SETKEY, "USE ARTIFACT :", SCSetKey, 15, MENU_NONE },
401 { ITT_SETKEY, "FIRE :", SCSetKey, 16, MENU_NONE },
402 { ITT_SETKEY, "USE :", SCSetKey, 17, MENU_NONE },
403 { ITT_SETKEY, "STRAFE :", SCSetKey, 18, MENU_NONE },
404 { ITT_SETKEY, "SPEED :", SCSetKey, 19, MENU_NONE }
406 static Menu_t Options3Menu =
416 static Menu_t *Menus[] =
429 #if defined(__linux) || #defined(__FreeBSD__)
430 static char *GammaText[] =
440 // CODE --------------------------------------------------------------------
441 char *Key2String(int key)
445 return "RIGHT ARROW";
476 if(key >= 'a' && key <= 'z') return stupidtable[(key - 'a')];
481 void ClearControls(int key)
487 if(*defaults[i].location == key) *defaults[i].location = 0;
491 //---------------------------------------------------------------------------
495 //---------------------------------------------------------------------------
501 // messageson = true; // Set by defaults in .CFG
502 MauloBaseLump = W_GetNumForName("FBULA0"); // ("M_SKL00");
505 //---------------------------------------------------------------------------
509 //---------------------------------------------------------------------------
511 static void InitFonts(void)
513 FontABaseLump = W_GetNumForName("FONTA_S")+1;
514 FontAYellowBaseLump = W_GetNumForName("FONTAY_S")+1;
515 FontBBaseLump = W_GetNumForName("FONTB_S")+1;
518 //---------------------------------------------------------------------------
522 // Draw text using font A.
524 //---------------------------------------------------------------------------
526 void MN_DrTextA(char *text, int x, int y)
532 OGL_SetColorAndAlpha( 1, 1, 1, 1 );
535 while((c = *text++) != 0)
543 p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
545 OGL_DrawPatch_CS(x, y, FontABaseLump+c-33);
547 V_DrawPatch(x, y, p);
554 //==========================================================================
558 //==========================================================================
560 void MN_DrTextAYellow(char *text, int x, int y)
566 OGL_SetColorAndAlpha( 1, 1, 1, 1 );
569 while((c = *text++) != 0)
577 p = W_CacheLumpNum(FontAYellowBaseLump+c-33, PU_CACHE);
579 OGL_DrawPatch_CS(x, y, FontAYellowBaseLump+c-33);
581 V_DrawPatch(x, y, p);
588 //---------------------------------------------------------------------------
590 // FUNC MN_TextAWidth
592 // Returns the pixel width of a string using font A.
594 //---------------------------------------------------------------------------
596 int MN_TextAWidth(char *text)
603 while((c = *text++) != 0)
611 p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
618 //---------------------------------------------------------------------------
622 // Draw text using font B.
624 //---------------------------------------------------------------------------
626 void MN_DrTextB(char *text, int x, int y)
632 OGL_SetColorAndAlpha( 1, 1, 1, 1 );
635 while((c = *text++) != 0)
643 p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
645 OGL_DrawPatch_CS(x, y, FontBBaseLump+c-33);
647 V_DrawPatch(x, y, p);
654 //---------------------------------------------------------------------------
656 // FUNC MN_TextBWidth
658 // Returns the pixel width of a string using font B.
660 //---------------------------------------------------------------------------
662 int MN_TextBWidth(char *text)
669 while((c = *text++) != 0)
677 p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
684 //---------------------------------------------------------------------------
688 //---------------------------------------------------------------------------
692 if(MenuActive == false)
697 bgAlpha -= .5/(float)menuDarkTicks;
698 if(bgAlpha < 0) bgAlpha = 0;
702 outFade += 1/(float)slamInTicks;
703 if(outFade > 1) fadingOut = false;
713 void MN_OGL_SetupState(float time)
715 glMatrixMode(GL_MODELVIEW);
718 if(time > 1 && time <= 2)
721 glTranslatef(160, 100, 0);
722 glScalef(.9+time*.1, .9+time*.1, 1);
723 glTranslatef(-160, -100, 0);
724 glColor4f(1, 1, 1, time);
728 glTranslatef(160, 100, 0);
729 glScalef(2-time, 2-time, 1);
730 glTranslatef(-160, -100, 0);
731 glColor4f(1, 1, 1, time*time);
734 void MN_OGL_RestoreState()
736 glMatrixMode(GL_MODELVIEW);
742 //---------------------------------------------------------------------------
746 //---------------------------------------------------------------------------
750 "ARE YOU SURE YOU WANT TO QUIT?",
751 "ARE YOU SURE YOU WANT TO END THE GAME?",
752 "DO YOU WANT TO QUICKSAVE THE GAME NAMED",
753 "DO YOU WANT TO QUICKLOAD THE GAME NAMED",
754 "ARE YOU SURE YOU WANT TO SUICIDE?"
758 #define BETA_FLASH_TEXT "BETA"
769 if(MenuActive == false)
774 UpdateState |= I_FULLSCRN;
775 BorderNeedRefresh = true;
776 //OGL_SetNoTexture();
777 glDisable( GL_TEXTURE_2D );
778 OGL_DrawRect(0,0,320,200,0,0,0,bgAlpha);
779 glEnable( GL_TEXTURE_2D );
784 MN_DrTextA(QuitEndMsg[typeofask-1], 160-
785 MN_TextAWidth(QuitEndMsg[typeofask-1])/2, 80);
788 MN_DrTextA(SlotText[quicksave-1], 160-
789 MN_TextAWidth(SlotText[quicksave-1])/2, 90);
791 MN_TextAWidth(SlotText[quicksave-1])/2, 90);
795 MN_DrTextA(SlotText[quickload-1], 160-
796 MN_TextAWidth(SlotText[quickload-1])/2, 90);
798 MN_TextAWidth(SlotText[quicksave-1])/2, 90);
800 UpdateState |= I_FULLSCRN;
804 if( MenuActive || fadingOut )
806 int effTime = (MenuTime>menuDarkTicks)? menuDarkTicks : MenuTime;
807 float temp = .5 * effTime/(float)menuDarkTicks;
809 UpdateState |= I_FULLSCRN;
813 if(temp > bgAlpha) bgAlpha = temp;
814 effTime = (MenuTime>slamInTicks)? slamInTicks : MenuTime;
815 temp = effTime / (float)slamInTicks;
817 // Draw a dark background. It makes it easier to read the menus.
818 //OGL_SetNoTexture();
819 glDisable( GL_TEXTURE_2D );
820 OGL_DrawRect(0,0,320,200,0,0,0,bgAlpha);
821 glEnable( GL_TEXTURE_2D );
823 else temp = outFade+1;
824 MN_OGL_SetupState(temp);
829 MN_OGL_RestoreState();
832 //if(screenblocks < 10)
834 BorderNeedRefresh = true;
836 if(CurrentMenu->drawFunc != NULL)
838 CurrentMenu->drawFunc();
842 item = CurrentMenu->items;
843 if(item->type == ITT_SETKEY)
845 for(i = 0; i < CurrentMenu->itemCount; i++)
853 MN_DrTextA(item->text, x, y+6);
857 MN_DrTextB(item->text, x, y);
859 y += CurrentMenu->step;
862 y = CurrentMenu->y+(CurrentItPos*CurrentMenu->step)+SELECTOR_YOFFSET;
863 selName = MenuTime&16 ? "M_SLCTR1" : "M_SLCTR2";
864 OGL_DrawPatch_CS(x+SELECTOR_XOFFSET, y, W_GetNumForName(selName));
866 MN_OGL_RestoreState();
871 UpdateState |= I_FULLSCRN;
877 if(screenblocks < 10)
879 BorderNeedRefresh = true;
881 if(CurrentMenu->drawFunc != NULL)
883 CurrentMenu->drawFunc();
887 item = CurrentMenu->items;
888 if(item->type == ITT_SETKEY)
890 for(i = 0; i < CurrentMenu->itemCount; i++)
898 MN_DrTextA(item->text, x, y+6);
902 MN_DrTextB(item->text, x, y);
904 y += CurrentMenu->step;
907 y = CurrentMenu->y+(CurrentItPos*CurrentMenu->step)+SELECTOR_YOFFSET;
908 selName = MenuTime&16 ? "M_SLCTR1" : "M_SLCTR2";
909 V_DrawPatch(x+SELECTOR_XOFFSET, y,
910 W_CacheLumpName(selName, PU_CACHE));
915 //---------------------------------------------------------------------------
919 //---------------------------------------------------------------------------
921 static void DrawMainMenu(void)
925 frame = (MenuTime/5)%7;
928 OGL_DrawPatch_CS( 88, 0, W_GetNumForName("M_HTIC") );
929 OGL_DrawPatch_CS( 37, 80, MauloBaseLump+(frame+2)%7 );
930 OGL_DrawPatch_CS( 278, 80, MauloBaseLump+frame );
932 V_DrawPatch(88, 0, W_CacheLumpName("M_HTIC", PU_CACHE));
933 // Old Gold skull positions: (40, 10) and (232, 10)
934 V_DrawPatch(37, 80, W_CacheLumpNum(MauloBaseLump+(frame+2)%7,
936 V_DrawPatch(278, 80, W_CacheLumpNum(MauloBaseLump+frame, PU_CACHE));
940 //==========================================================================
944 //==========================================================================
946 static void DrawClassMenu(void)
949 static char *boxLumpName[4] =
956 static char *walkLumpName[4] =
964 MN_DrTextB("CHOOSE CLASS:", 34, 24);
965 class = (pclass_t)CurrentMenu->items[CurrentItPos].option;
967 OGL_DrawPatch_CS(174, 8, W_GetNumForName(boxLumpName[class]));
968 OGL_DrawPatch_CS(174+24, 8+12,
969 W_GetNumForName(walkLumpName[class])+((MenuTime>>3)&3));
971 V_DrawPatch(174, 8, W_CacheLumpName(boxLumpName[class], PU_CACHE));
972 V_DrawPatch(174+24, 8+12,
973 W_CacheLumpNum(W_GetNumForName(walkLumpName[class])
974 +((MenuTime>>3)&3), PU_CACHE));
978 //---------------------------------------------------------------------------
980 // PROC DrawSkillMenu
982 //---------------------------------------------------------------------------
984 static void DrawSkillMenu(void)
986 MN_DrTextB("CHOOSE SKILL LEVEL:", 74, 16);
989 //---------------------------------------------------------------------------
991 // PROC DrawFilesMenu
993 //---------------------------------------------------------------------------
995 static void DrawFilesMenu(void)
997 // clear out the quicksave/quickload stuff
1000 P_ClearMessage(&players[consoleplayer]);
1003 //---------------------------------------------------------------------------
1005 // PROC DrawLoadMenu
1007 //---------------------------------------------------------------------------
1009 static void DrawLoadMenu(void)
1011 MN_DrTextB("LOAD GAME", 160-MN_TextBWidth("LOAD GAME")/2, 10);
1016 DrawFileSlots(&LoadMenu);
1019 //---------------------------------------------------------------------------
1021 // PROC DrawSaveMenu
1023 //---------------------------------------------------------------------------
1025 static void DrawSaveMenu(void)
1027 MN_DrTextB("SAVE GAME", 160-MN_TextBWidth("SAVE GAME")/2, 10);
1032 DrawFileSlots(&SaveMenu);
1035 //===========================================================================
1039 // For each slot, looks for save games and reads the description field.
1041 //===========================================================================
1043 void MN_LoadSlotText(void)
1048 char versionText[HXS_VERSION_TEXT_LENGTH];
1049 char description[HXS_DESCRIPTION_LENGTH];
1052 for(slot = 0; slot < 6; slot++)
1055 snprintf(name, 100, "%shex%d.hxs", basePath, slot);
1056 fp = fopen(name, "rb");
1059 fread(description, HXS_DESCRIPTION_LENGTH, 1, fp);
1060 fread(versionText, HXS_VERSION_TEXT_LENGTH, 1, fp);
1062 if(!strcmp(versionText, HXS_VERSION_TEXT))
1069 memcpy(SlotText[slot], description, SLOTTEXTLEN);
1070 SlotStatus[slot] = 1;
1074 memset(SlotText[slot], 0, SLOTTEXTLEN);
1075 SlotStatus[slot] = 0;
1078 slottextloaded = true;
1081 //---------------------------------------------------------------------------
1083 // PROC DrawFileSlots
1085 //---------------------------------------------------------------------------
1087 static void DrawFileSlots(Menu_t *menu)
1095 for(i = 0; i < 6; i++)
1098 OGL_DrawPatch_CS(x, y, W_GetNumForName("M_FSLOT"));
1100 V_DrawPatch(x, y, W_CacheLumpName("M_FSLOT", PU_CACHE));
1104 MN_DrTextA(SlotText[i], x+5, y+5);
1110 //---------------------------------------------------------------------------
1112 // PROC DrawOptionsMenu
1114 //---------------------------------------------------------------------------
1116 static void DrawOptionsMenu(void)
1121 MN_DrTextB("ON", 196, 50);
1125 MN_DrTextB("OFF", 196, 50);
1127 MN_DrTextB(mlooktext[mouselook], 208, 110);
1129 sprintf(num,"%d",mouseSensitivity);
1130 MN_DrTextB(num,265, 71);
1134 MN_DrTextB("ON", 208, 130);
1138 MN_DrTextB("OFF", 208,130);
1142 //---------------------------------------------------------------------------
1144 // PROC DrawOptions2Menu
1146 //---------------------------------------------------------------------------
1148 static void DrawOptions2Menu(void)
1150 DrawSlider(&Options2Menu, 1, 9, screenblocks-3);
1151 DrawSlider(&Options2Menu, 3, 16, snd_MaxVolume);
1152 DrawSlider(&Options2Menu, 5, 16, snd_MusicVolume);
1155 MN_DrTextB("ON", 196, 140);
1159 MN_DrTextB("OFF", 196, 140);
1164 static void DrawOptions3Menu(void)
1170 if(askforkey && keyaskedfor == i) {
1171 MN_DrTextAYellow("???", 195, (i*SMALL_ITEM_HEIGHT+26));
1174 MN_DrTextA(Key2String(*defaults[i+FirstKey+3].location),
1175 195, (i*SMALL_ITEM_HEIGHT+26));
1181 //---------------------------------------------------------------------------
1185 //---------------------------------------------------------------------------
1187 static void SCQuitGame(int option)
1191 typeofask = 1; //quit game
1192 if(!netgame && !demoplayback)
1198 //---------------------------------------------------------------------------
1202 //---------------------------------------------------------------------------
1204 static void SCEndGame(int option)
1214 typeofask = 2; //endgame
1215 if(!netgame && !demoplayback)
1222 //---------------------------------------------------------------------------
1226 //---------------------------------------------------------------------------
1228 static void SCMessages(int option)
1233 P_SetMessage(&players[consoleplayer], "MESSAGES ON", true);
1237 P_SetMessage(&players[consoleplayer], "MESSAGES OFF", true);
1239 S_StartSound(NULL, SFX_CHAT);
1242 //===========================================================================
1246 //===========================================================================
1248 static boolean SCNetCheck(int option)
1257 P_SetMessage(&players[consoleplayer],
1258 "YOU CAN'T START A NEW GAME IN NETPLAY!", true);
1260 case 2: // load game
1261 P_SetMessage(&players[consoleplayer],
1262 "YOU CAN'T LOAD A GAME IN NETPLAY!", true);
1265 P_SetMessage(&players[consoleplayer],
1266 "YOU CAN'T END A GAME IN NETPLAY!", true);
1270 S_StartSound(NULL, SFX_CHAT);
1274 //===========================================================================
1278 //===========================================================================
1280 static void SCNetCheck2(int option)
1286 //---------------------------------------------------------------------------
1290 //---------------------------------------------------------------------------
1292 static void SCLoadGame(int option)
1294 if(!SlotStatus[option])
1295 { // Don't try to load from an empty slot
1299 MN_DeactivateMenu();
1300 BorderNeedRefresh = true;
1303 quickload = option+1;
1304 P_ClearMessage(&players[consoleplayer]);
1308 //---------------------------------------------------------------------------
1312 //---------------------------------------------------------------------------
1314 static void SCSaveGame(int option)
1318 if(!FileMenuKeySteal)
1320 FileMenuKeySteal = true;
1321 strcpy(oldSlotText, SlotText[option]);
1322 ptr = SlotText[option];
1329 SlotStatus[option]++;
1330 currentSlot = option;
1331 slotptr = ptr-SlotText[option];
1336 G_SaveGame(option, SlotText[option]);
1337 FileMenuKeySteal = false;
1338 MN_DeactivateMenu();
1340 BorderNeedRefresh = true;
1343 quicksave = option+1;
1344 P_ClearMessage(&players[consoleplayer]);
1348 //==========================================================================
1352 //==========================================================================
1354 static void SCClass(int option)
1358 P_SetMessage(&players[consoleplayer],
1359 "YOU CAN'T START A NEW GAME FROM WITHIN A NETGAME!", true);
1362 MenuPClass = option;
1365 case PCLASS_FIGHTER:
1367 SkillItems[0].text = "SQUIRE";
1368 SkillItems[1].text = "KNIGHT";
1369 SkillItems[2].text = "WARRIOR";
1370 SkillItems[3].text = "BERSERKER";
1371 SkillItems[4].text = "TITAN";
1375 SkillItems[0].text = "ALTAR BOY";
1376 SkillItems[1].text = "ACOLYTE";
1377 SkillItems[2].text = "PRIEST";
1378 SkillItems[3].text = "CARDINAL";
1379 SkillItems[4].text = "POPE";
1383 SkillItems[0].text = "APPRENTICE";
1384 SkillItems[1].text = "ENCHANTER";
1385 SkillItems[2].text = "SORCERER";
1386 SkillItems[3].text = "WARLOCK";
1387 SkillItems[4].text = "ARCHIMAGE";
1392 SkillItems[0].text = "KNAVE";
1393 SkillItems[1].text = "ROUGE";
1394 SkillItems[2].text = "CUTTHROAT";
1395 SkillItems[3].text = "EXECUTIONER";
1396 SkillItems[4].text = "WIDOW MAKER";
1400 SetMenu(MENU_SKILL);
1403 //---------------------------------------------------------------------------
1407 //---------------------------------------------------------------------------
1409 static void SCSkill(int option)
1411 extern int SB_state;
1413 PlayerClass[consoleplayer] = MenuPClass;
1414 G_DeferredNewGame(option);
1417 MN_DeactivateMenu();
1420 //---------------------------------------------------------------------------
1422 // PROC SCMouseSensi
1424 //---------------------------------------------------------------------------
1426 static void SCMouseSensi(int option)
1428 if(option == RIGHT_DIR)
1430 if(mouseSensitivity < MENU_MAX_MOUSE_SENS)
1435 else if(mouseSensitivity)
1441 //---------------------------------------------------------------------------
1445 //---------------------------------------------------------------------------
1447 static void SCSfxVolume(int option)
1449 if(option == RIGHT_DIR)
1451 if(snd_MaxVolume < 15)
1456 else if(snd_MaxVolume)
1460 soundchanged = true; // we'll set it when we leave the menu
1463 //---------------------------------------------------------------------------
1465 // PROC SCMusicVolume
1467 //---------------------------------------------------------------------------
1469 static void SCMusicVolume(int option)
1471 if(option == RIGHT_DIR)
1473 if(snd_MusicVolume < 15)
1478 else if(snd_MusicVolume)
1485 //---------------------------------------------------------------------------
1487 // PROC SCScreenSize
1489 //---------------------------------------------------------------------------
1491 static void SCScreenSize(int option)
1493 if(option == RIGHT_DIR)
1495 if(screenblocks < 11)
1500 else if(screenblocks > 3)
1504 R_SetViewSize(screenblocks, detailLevel);
1507 //---------------------------------------------------------------------------
1511 //---------------------------------------------------------------------------
1513 static void SCInfo(int option)
1516 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1517 if(!netgame && !demoplayback)
1523 //---------------------------------------------------------------------------
1527 //---------------------------------------------------------------------------
1528 static void SCSetKey(int option)
1531 keyaskedfor = option;
1532 if(!netgame && !demoplayback)
1538 //---------------------------------------------------------------------------
1540 // PROC SCMouslook(int option)
1542 //---------------------------------------------------------------------------
1543 static void SCMouselook(int option)
1545 if(option == RIGHT_DIR)
1547 if(mouselook < 2) mouselook++;
1550 else if(mouselook) mouselook--;
1553 static void SCAlwaysRun(int option)
1555 if(alwaysrun) alwaysrun=0;
1558 static void SCCDAudio(int option)
1569 ST_Message("Attempting to initialize CD Music: ");
1572 i_CDMusic = (I_CDMusInit() != -1);
1575 { // The user is trying to use the cdrom for both game and music
1580 ST_Message("initialized.\n");
1584 ST_Message("failed.\n");
1589 //---------------------------------------------------------------------------
1591 // FUNC MN_Responder
1593 //---------------------------------------------------------------------------
1595 boolean MN_Responder(event_t *event)
1600 extern boolean automapactive;
1601 static boolean shiftdown;
1602 extern void H2_StartTitle(void);
1603 extern void G_CheckDemoStatus(void);
1606 if(askforkey && event->type == ev_keydown)
1608 ClearControls(event->data1);
1609 *defaults[keyaskedfor+3+FirstKey].location = event->data1;
1613 if(askforkey && event->type == ev_mouse)
1616 mbone = defaults[keyaskedfor+3+FirstKey].location;
1618 mbtwo = defaults[keyaskedfor+3+FirstKey].location;
1620 mbthree = defaults[keyaskedfor+3+FirstKey].location;
1624 if(event->data1 == KEY_RSHIFT)
1626 shiftdown = (event->type == ev_keydown);
1628 if(event->type != ev_keydown)
1637 InfoType = (InfoType+1)%5;
1641 InfoType = (InfoType+1)%4;
1643 if(key == KEY_ESCAPE)
1649 if(!netgame && !demoplayback)
1653 MN_DeactivateMenu();
1654 SB_state = -1; //refresh the statbar
1655 BorderNeedRefresh = true;
1657 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1658 return(true); //make the info screen eat the keypress
1661 if(ravpic && key == KEY_F1)
1677 G_CheckDemoStatus();
1681 P_ClearMessage(&players[consoleplayer]);
1685 I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
1686 H2_StartTitle(); // go to intro/demo mode.
1689 P_SetMessage(&players[consoleplayer],
1690 "QUICKSAVING....", false);
1691 FileMenuKeySteal = true;
1692 SCSaveGame(quicksave-1);
1695 BorderNeedRefresh = true;
1698 P_SetMessage(&players[consoleplayer],
1699 "QUICKLOADING....", false);
1700 SCLoadGame(quickload-1);
1703 BorderNeedRefresh = true;
1708 BorderNeedRefresh = true;
1709 mn_SuicideConsole = true;
1713 return true; // eat the 'y' keypress
1721 players[consoleplayer].messageTics = 0;
1725 UpdateState |= I_FULLSCRN;
1726 BorderNeedRefresh = true;
1731 return false; // don't let the keys filter thru
1733 if(MenuActive == false && !chatmodeon)
1739 { // Don't screen size in automap
1742 SCScreenSize(LEFT_DIR);
1743 S_StartSound(NULL, SFX_PICKUP_KEY);
1744 BorderNeedRefresh = true;
1745 UpdateState |= I_FULLSCRN;
1749 { // Don't screen size in automap
1752 SCScreenSize(RIGHT_DIR);
1753 S_StartSound(NULL, SFX_PICKUP_KEY);
1754 BorderNeedRefresh = true;
1755 UpdateState |= I_FULLSCRN;
1761 typeofask = 5; // suicide
1765 case KEY_F1: // help screen
1766 SCInfo(0); // start up info screens
1769 case KEY_F2: // save game
1770 if(gamestate == GS_LEVEL && !demoplayback)
1773 FileMenuKeySteal = false;
1775 CurrentMenu = &SaveMenu;
1776 CurrentItPos = CurrentMenu->oldItPos;
1777 if(!netgame && !demoplayback)
1781 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1782 slottextloaded = false; //reload the slot text, when needed
1785 case KEY_F3: // load game
1789 FileMenuKeySteal = false;
1791 CurrentMenu = &LoadMenu;
1792 CurrentItPos = CurrentMenu->oldItPos;
1793 if(!netgame && !demoplayback)
1797 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1798 slottextloaded = false; //reload the slot text, when needed
1801 case KEY_F4: // volume
1803 FileMenuKeySteal = false;
1805 CurrentMenu = &Options2Menu;
1806 CurrentItPos = CurrentMenu->oldItPos;
1807 if(!netgame && !demoplayback)
1811 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1812 slottextloaded = false; //reload the slot text, when needed
1817 typeofask = 5; // suicide
1819 case KEY_F6: // quicksave
1820 if(gamestate == GS_LEVEL && !demoplayback)
1822 if(!quicksave || quicksave == -1)
1825 FileMenuKeySteal = false;
1827 CurrentMenu = &SaveMenu;
1828 CurrentItPos = CurrentMenu->oldItPos;
1829 if(!netgame && !demoplayback)
1833 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1834 slottextloaded = false; //reload the slot text
1836 P_SetMessage(&players[consoleplayer],
1837 "CHOOSE A QUICKSAVE SLOT", true);
1843 if(!netgame && !demoplayback)
1847 S_StartSound(NULL, SFX_CHAT);
1851 case KEY_F7: // endgame
1854 if(gamestate == GS_LEVEL && !demoplayback)
1856 S_StartSound(NULL, SFX_CHAT);
1861 case KEY_F8: // toggle messages
1864 case KEY_F9: // quickload
1867 if(!quickload || quickload == -1)
1870 FileMenuKeySteal = false;
1872 CurrentMenu = &LoadMenu;
1873 CurrentItPos = CurrentMenu->oldItPos;
1874 if(!netgame && !demoplayback)
1878 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1879 slottextloaded = false; // reload the slot text
1881 P_SetMessage(&players[consoleplayer],
1882 "CHOOSE A QUICKLOAD SLOT", true);
1887 if(!netgame && !demoplayback)
1892 S_StartSound(NULL, SFX_CHAT);
1896 case KEY_F10: // quit
1897 if(gamestate == GS_LEVEL || gamestate == GS_FINALE)
1900 S_StartSound(NULL, SFX_CHAT);
1903 case KEY_F11: // F11 - gamma mode correction
1909 SB_PaletteFlash(true); // force change
1910 P_SetMessage(&players[consoleplayer], GammaText[usegamma],
1913 case KEY_F12: // F12 - reload current map (devmaps mode)
1914 if(netgame || DevMaps == false)
1918 if(gamekeydown[key_speed])
1922 if(gamekeydown[key_strafe])
1926 G_DeferedInitNew(gameskill, gameepisode, gamemap);
1927 P_SetMessage(&players[consoleplayer], TXT_CHEATWARP,
1935 if(MenuActive == false)
1937 if(key == KEY_ESCAPE || gamestate == GS_DEMOSCREEN || demoplayback)
1944 if(!FileMenuKeySteal)
1946 item = &CurrentMenu->items[CurrentItPos];
1952 if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos+1 > CurrentMenu->itemCount-1)
1956 CurrentItPos = 0; //End of Key menu
1964 else if(CurrentItPos+1 > CurrentMenu->itemCount-1)
1972 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
1973 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
1979 if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos==0)
1983 CurrentItPos = 14; //End of Key menu
1991 else if(CurrentItPos == 0)
1993 CurrentItPos = CurrentMenu->itemCount-1;
1999 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
2000 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
2004 if(item->type == ITT_LRFUNC && item->func != NULL)
2006 item->func(LEFT_DIR);
2007 S_StartSound(NULL, SFX_PICKUP_KEY);
2011 case KEY_RIGHTARROW:
2012 if(item->type == ITT_LRFUNC && item->func != NULL)
2014 item->func(RIGHT_DIR);
2015 S_StartSound(NULL, SFX_PICKUP_KEY);
2020 if(item->type == ITT_SETMENU)
2022 if(item->func != NULL)
2024 item->func(item->option);
2026 SetMenu(item->menu);
2028 else if(item->func != NULL)
2030 CurrentMenu->oldItPos = CurrentItPos;
2031 if(item->type == ITT_LRFUNC)
2033 item->func(RIGHT_DIR);
2035 else if(item->type == ITT_EFUNC)
2037 item->func(item->option);
2039 else if(item->type == ITT_SETKEY)
2041 item->func(item->option);
2044 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
2048 MN_DeactivateMenu();
2051 S_StartSound(NULL, SFX_PICKUP_KEY);
2052 if(CurrentMenu->prevMenu == MENU_NONE)
2054 MN_DeactivateMenu();
2058 SetMenu(CurrentMenu->prevMenu);
2062 for(i = 0; i < CurrentMenu->itemCount; i++)
2064 if(CurrentMenu->items[i].text)
2067 == toupper(CurrentMenu->items[i].text[0]))
2079 { // Editing file names
2080 textBuffer = &SlotText[currentSlot][slotptr];
2081 if(key == KEY_BACKSPACE)
2086 *textBuffer = ASCII_CURSOR;
2091 if(key == KEY_ESCAPE)
2093 memset(SlotText[currentSlot], 0, SLOTTEXTLEN+2);
2094 strcpy(SlotText[currentSlot], oldSlotText);
2095 SlotStatus[currentSlot]--;
2096 MN_DeactivateMenu();
2099 if(key == KEY_ENTER)
2101 SlotText[currentSlot][slotptr] = 0; // clear the cursor
2102 item = &CurrentMenu->items[CurrentItPos];
2103 CurrentMenu->oldItPos = CurrentItPos;
2104 if(item->type == ITT_EFUNC)
2106 item->func(item->option);
2107 if(item->menu != MENU_NONE)
2109 SetMenu(item->menu);
2114 if(slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE)
2116 if((key >= 'a' && key <= 'z'))
2118 *textBuffer++ = key-32;
2119 *textBuffer = ASCII_CURSOR;
2123 if(((key >= '0' && key <= '9') || key == ' '
2124 || key == ',' || key == '.' || key == '-')
2127 *textBuffer++ = key;
2128 *textBuffer = ASCII_CURSOR;
2132 if(shiftdown && key == '1')
2134 *textBuffer++ = '!';
2135 *textBuffer = ASCII_CURSOR;
2145 //---------------------------------------------------------------------------
2147 // PROC MN_ActivateMenu
2149 //---------------------------------------------------------------------------
2151 void MN_ActivateMenu(void)
2162 FileMenuKeySteal = false;
2164 CurrentMenu = &MainMenu;
2165 CurrentItPos = CurrentMenu->oldItPos;
2166 if(!netgame && !demoplayback)
2170 S_StartSound(NULL, SFX_PLATFORM_STOP);
2171 slottextloaded = false; //reload the slot text, when needed
2174 //---------------------------------------------------------------------------
2176 // PROC MN_DeactivateMenu
2178 //---------------------------------------------------------------------------
2180 void MN_DeactivateMenu(void)
2182 CurrentMenu->oldItPos = CurrentItPos;
2188 S_StartSound(NULL, SFX_PLATFORM_STOP);
2189 P_ClearMessage(&players[consoleplayer]);
2192 //---------------------------------------------------------------------------
2196 //---------------------------------------------------------------------------
2198 void MN_DrawInfo(void)
2202 OGL_DrawRawScreen( W_GetNumForName("TITLE")+InfoType );
2204 I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
2205 memcpy(screen, (byte *)W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2206 PU_CACHE), SCREENWIDTH*SCREENHEIGHT);
2207 // V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2213 //---------------------------------------------------------------------------
2217 //---------------------------------------------------------------------------
2219 static void SetMenu(MenuType_t menu)
2221 CurrentMenu->oldItPos = CurrentItPos;
2222 CurrentMenu = Menus[menu];
2223 CurrentItPos = CurrentMenu->oldItPos;
2226 //---------------------------------------------------------------------------
2230 //---------------------------------------------------------------------------
2232 static void DrawSlider(Menu_t *menu, int item, int width, int slot)
2240 y = menu->y+2+(item*ITEM_HEIGHT);
2243 OGL_DrawPatch_CS(x-32, y, W_GetNumForName("M_SLDLT"));
2244 for(x2 = x, count = width; count--; x2 += 8)
2246 OGL_DrawPatch_CS( x2, y, W_GetNumForName(count&1 ? "M_SLDMD1" :
2249 OGL_DrawPatch_CS(x2, y, W_GetNumForName("M_SLDRT"));
2250 OGL_DrawPatch_CS(x+4+slot*8, y+7, W_GetNumForName("M_SLDKB"));
2252 V_DrawPatch(x-32, y, W_CacheLumpName("M_SLDLT", PU_CACHE));
2253 for(x2 = x, count = width; count--; x2 += 8)
2255 V_DrawPatch(x2, y, W_CacheLumpName(count&1 ? "M_SLDMD1"
2256 : "M_SLDMD2", PU_CACHE));
2258 V_DrawPatch(x2, y, W_CacheLumpName("M_SLDRT", PU_CACHE));
2259 V_DrawPatch(x+4+slot*8, y+7, W_CacheLumpName("M_SLDKB", PU_CACHE));