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";
1391 SkillItems[0].text = "KNAVE";
1392 SkillItems[1].text = "ROUGE";
1393 SkillItems[2].text = "CUTTHROAT";
1394 SkillItems[3].text = "EXECUTIONER";
1395 SkillItems[4].text = "WIDOW MAKER";
1398 SetMenu(MENU_SKILL);
1401 //---------------------------------------------------------------------------
1405 //---------------------------------------------------------------------------
1407 static void SCSkill(int option)
1409 extern int SB_state;
1411 PlayerClass[consoleplayer] = MenuPClass;
1412 G_DeferredNewGame(option);
1415 MN_DeactivateMenu();
1418 //---------------------------------------------------------------------------
1420 // PROC SCMouseSensi
1422 //---------------------------------------------------------------------------
1424 static void SCMouseSensi(int option)
1426 if(option == RIGHT_DIR)
1428 if(mouseSensitivity < MENU_MAX_MOUSE_SENS)
1433 else if(mouseSensitivity)
1439 //---------------------------------------------------------------------------
1443 //---------------------------------------------------------------------------
1445 static void SCSfxVolume(int option)
1447 if(option == RIGHT_DIR)
1449 if(snd_MaxVolume < 15)
1454 else if(snd_MaxVolume)
1458 soundchanged = true; // we'll set it when we leave the menu
1461 //---------------------------------------------------------------------------
1463 // PROC SCMusicVolume
1465 //---------------------------------------------------------------------------
1467 static void SCMusicVolume(int option)
1469 if(option == RIGHT_DIR)
1471 if(snd_MusicVolume < 15)
1476 else if(snd_MusicVolume)
1483 //---------------------------------------------------------------------------
1485 // PROC SCScreenSize
1487 //---------------------------------------------------------------------------
1489 static void SCScreenSize(int option)
1491 if(option == RIGHT_DIR)
1493 if(screenblocks < 11)
1498 else if(screenblocks > 3)
1502 R_SetViewSize(screenblocks, detailLevel);
1505 //---------------------------------------------------------------------------
1509 //---------------------------------------------------------------------------
1511 static void SCInfo(int option)
1514 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1515 if(!netgame && !demoplayback)
1521 //---------------------------------------------------------------------------
1525 //---------------------------------------------------------------------------
1526 static void SCSetKey(int option)
1529 keyaskedfor = option;
1530 if(!netgame && !demoplayback)
1536 //---------------------------------------------------------------------------
1538 // PROC SCMouslook(int option)
1540 //---------------------------------------------------------------------------
1541 static void SCMouselook(int option)
1543 if(option == RIGHT_DIR)
1545 if(mouselook < 2) mouselook++;
1548 else if(mouselook) mouselook--;
1551 static void SCAlwaysRun(int option)
1553 if(alwaysrun) alwaysrun=0;
1556 static void SCCDAudio(int option)
1567 ST_Message("Attempting to initialize CD Music: ");
1570 i_CDMusic = (I_CDMusInit() != -1);
1573 { // The user is trying to use the cdrom for both game and music
1578 ST_Message("initialized.\n");
1582 ST_Message("failed.\n");
1587 //---------------------------------------------------------------------------
1589 // FUNC MN_Responder
1591 //---------------------------------------------------------------------------
1593 boolean MN_Responder(event_t *event)
1598 extern boolean automapactive;
1599 static boolean shiftdown;
1600 extern void H2_StartTitle(void);
1601 extern void G_CheckDemoStatus(void);
1604 if(askforkey && event->type == ev_keydown)
1606 ClearControls(event->data1);
1607 *defaults[keyaskedfor+3+FirstKey].location = event->data1;
1611 if(askforkey && event->type == ev_mouse)
1614 mbone = defaults[keyaskedfor+3+FirstKey].location;
1616 mbtwo = defaults[keyaskedfor+3+FirstKey].location;
1618 mbthree = defaults[keyaskedfor+3+FirstKey].location;
1622 if(event->data1 == KEY_RSHIFT)
1624 shiftdown = (event->type == ev_keydown);
1626 if(event->type != ev_keydown)
1635 InfoType = (InfoType+1)%5;
1639 InfoType = (InfoType+1)%4;
1641 if(key == KEY_ESCAPE)
1647 if(!netgame && !demoplayback)
1651 MN_DeactivateMenu();
1652 SB_state = -1; //refresh the statbar
1653 BorderNeedRefresh = true;
1655 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1656 return(true); //make the info screen eat the keypress
1659 if(ravpic && key == KEY_F1)
1675 G_CheckDemoStatus();
1679 P_ClearMessage(&players[consoleplayer]);
1683 I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
1684 H2_StartTitle(); // go to intro/demo mode.
1687 P_SetMessage(&players[consoleplayer],
1688 "QUICKSAVING....", false);
1689 FileMenuKeySteal = true;
1690 SCSaveGame(quicksave-1);
1693 BorderNeedRefresh = true;
1696 P_SetMessage(&players[consoleplayer],
1697 "QUICKLOADING....", false);
1698 SCLoadGame(quickload-1);
1701 BorderNeedRefresh = true;
1706 BorderNeedRefresh = true;
1707 mn_SuicideConsole = true;
1711 return true; // eat the 'y' keypress
1719 players[consoleplayer].messageTics = 0;
1723 UpdateState |= I_FULLSCRN;
1724 BorderNeedRefresh = true;
1729 return false; // don't let the keys filter thru
1731 if(MenuActive == false && !chatmodeon)
1737 { // Don't screen size in automap
1740 SCScreenSize(LEFT_DIR);
1741 S_StartSound(NULL, SFX_PICKUP_KEY);
1742 BorderNeedRefresh = true;
1743 UpdateState |= I_FULLSCRN;
1747 { // Don't screen size in automap
1750 SCScreenSize(RIGHT_DIR);
1751 S_StartSound(NULL, SFX_PICKUP_KEY);
1752 BorderNeedRefresh = true;
1753 UpdateState |= I_FULLSCRN;
1759 typeofask = 5; // suicide
1763 case KEY_F1: // help screen
1764 SCInfo(0); // start up info screens
1767 case KEY_F2: // save game
1768 if(gamestate == GS_LEVEL && !demoplayback)
1771 FileMenuKeySteal = false;
1773 CurrentMenu = &SaveMenu;
1774 CurrentItPos = CurrentMenu->oldItPos;
1775 if(!netgame && !demoplayback)
1779 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1780 slottextloaded = false; //reload the slot text, when needed
1783 case KEY_F3: // load game
1787 FileMenuKeySteal = false;
1789 CurrentMenu = &LoadMenu;
1790 CurrentItPos = CurrentMenu->oldItPos;
1791 if(!netgame && !demoplayback)
1795 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1796 slottextloaded = false; //reload the slot text, when needed
1799 case KEY_F4: // volume
1801 FileMenuKeySteal = false;
1803 CurrentMenu = &Options2Menu;
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
1815 typeofask = 5; // suicide
1817 case KEY_F6: // quicksave
1818 if(gamestate == GS_LEVEL && !demoplayback)
1820 if(!quicksave || quicksave == -1)
1823 FileMenuKeySteal = false;
1825 CurrentMenu = &SaveMenu;
1826 CurrentItPos = CurrentMenu->oldItPos;
1827 if(!netgame && !demoplayback)
1831 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1832 slottextloaded = false; //reload the slot text
1834 P_SetMessage(&players[consoleplayer],
1835 "CHOOSE A QUICKSAVE SLOT", true);
1841 if(!netgame && !demoplayback)
1845 S_StartSound(NULL, SFX_CHAT);
1849 case KEY_F7: // endgame
1852 if(gamestate == GS_LEVEL && !demoplayback)
1854 S_StartSound(NULL, SFX_CHAT);
1859 case KEY_F8: // toggle messages
1862 case KEY_F9: // quickload
1865 if(!quickload || quickload == -1)
1868 FileMenuKeySteal = false;
1870 CurrentMenu = &LoadMenu;
1871 CurrentItPos = CurrentMenu->oldItPos;
1872 if(!netgame && !demoplayback)
1876 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1877 slottextloaded = false; // reload the slot text
1879 P_SetMessage(&players[consoleplayer],
1880 "CHOOSE A QUICKLOAD SLOT", true);
1885 if(!netgame && !demoplayback)
1890 S_StartSound(NULL, SFX_CHAT);
1894 case KEY_F10: // quit
1895 if(gamestate == GS_LEVEL || gamestate == GS_FINALE)
1898 S_StartSound(NULL, SFX_CHAT);
1901 case KEY_F11: // F11 - gamma mode correction
1907 SB_PaletteFlash(true); // force change
1908 P_SetMessage(&players[consoleplayer], GammaText[usegamma],
1911 case KEY_F12: // F12 - reload current map (devmaps mode)
1912 if(netgame || DevMaps == false)
1916 if(gamekeydown[key_speed])
1920 if(gamekeydown[key_strafe])
1924 G_DeferedInitNew(gameskill, gameepisode, gamemap);
1925 P_SetMessage(&players[consoleplayer], TXT_CHEATWARP,
1933 if(MenuActive == false)
1935 if(key == KEY_ESCAPE || gamestate == GS_DEMOSCREEN || demoplayback)
1942 if(!FileMenuKeySteal)
1944 item = &CurrentMenu->items[CurrentItPos];
1950 if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos+1 > CurrentMenu->itemCount-1)
1954 CurrentItPos = 0; //End of Key menu
1962 else if(CurrentItPos+1 > CurrentMenu->itemCount-1)
1970 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
1971 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
1977 if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos==0)
1981 CurrentItPos = 14; //End of Key menu
1989 else if(CurrentItPos == 0)
1991 CurrentItPos = CurrentMenu->itemCount-1;
1997 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
1998 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
2002 if(item->type == ITT_LRFUNC && item->func != NULL)
2004 item->func(LEFT_DIR);
2005 S_StartSound(NULL, SFX_PICKUP_KEY);
2009 case KEY_RIGHTARROW:
2010 if(item->type == ITT_LRFUNC && item->func != NULL)
2012 item->func(RIGHT_DIR);
2013 S_StartSound(NULL, SFX_PICKUP_KEY);
2018 if(item->type == ITT_SETMENU)
2020 if(item->func != NULL)
2022 item->func(item->option);
2024 SetMenu(item->menu);
2026 else if(item->func != NULL)
2028 CurrentMenu->oldItPos = CurrentItPos;
2029 if(item->type == ITT_LRFUNC)
2031 item->func(RIGHT_DIR);
2033 else if(item->type == ITT_EFUNC)
2035 item->func(item->option);
2037 else if(item->type == ITT_SETKEY)
2039 item->func(item->option);
2042 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
2046 MN_DeactivateMenu();
2049 S_StartSound(NULL, SFX_PICKUP_KEY);
2050 if(CurrentMenu->prevMenu == MENU_NONE)
2052 MN_DeactivateMenu();
2056 SetMenu(CurrentMenu->prevMenu);
2060 for(i = 0; i < CurrentMenu->itemCount; i++)
2062 if(CurrentMenu->items[i].text)
2065 == toupper(CurrentMenu->items[i].text[0]))
2077 { // Editing file names
2078 textBuffer = &SlotText[currentSlot][slotptr];
2079 if(key == KEY_BACKSPACE)
2084 *textBuffer = ASCII_CURSOR;
2089 if(key == KEY_ESCAPE)
2091 memset(SlotText[currentSlot], 0, SLOTTEXTLEN+2);
2092 strcpy(SlotText[currentSlot], oldSlotText);
2093 SlotStatus[currentSlot]--;
2094 MN_DeactivateMenu();
2097 if(key == KEY_ENTER)
2099 SlotText[currentSlot][slotptr] = 0; // clear the cursor
2100 item = &CurrentMenu->items[CurrentItPos];
2101 CurrentMenu->oldItPos = CurrentItPos;
2102 if(item->type == ITT_EFUNC)
2104 item->func(item->option);
2105 if(item->menu != MENU_NONE)
2107 SetMenu(item->menu);
2112 if(slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE)
2114 if((key >= 'a' && key <= 'z'))
2116 *textBuffer++ = key-32;
2117 *textBuffer = ASCII_CURSOR;
2121 if(((key >= '0' && key <= '9') || key == ' '
2122 || key == ',' || key == '.' || key == '-')
2125 *textBuffer++ = key;
2126 *textBuffer = ASCII_CURSOR;
2130 if(shiftdown && key == '1')
2132 *textBuffer++ = '!';
2133 *textBuffer = ASCII_CURSOR;
2143 //---------------------------------------------------------------------------
2145 // PROC MN_ActivateMenu
2147 //---------------------------------------------------------------------------
2149 void MN_ActivateMenu(void)
2160 FileMenuKeySteal = false;
2162 CurrentMenu = &MainMenu;
2163 CurrentItPos = CurrentMenu->oldItPos;
2164 if(!netgame && !demoplayback)
2168 S_StartSound(NULL, SFX_PLATFORM_STOP);
2169 slottextloaded = false; //reload the slot text, when needed
2172 //---------------------------------------------------------------------------
2174 // PROC MN_DeactivateMenu
2176 //---------------------------------------------------------------------------
2178 void MN_DeactivateMenu(void)
2180 CurrentMenu->oldItPos = CurrentItPos;
2186 S_StartSound(NULL, SFX_PLATFORM_STOP);
2187 P_ClearMessage(&players[consoleplayer]);
2190 //---------------------------------------------------------------------------
2194 //---------------------------------------------------------------------------
2196 void MN_DrawInfo(void)
2200 OGL_DrawRawScreen( W_GetNumForName("TITLE")+InfoType );
2202 I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
2203 memcpy(screen, (byte *)W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2204 PU_CACHE), SCREENWIDTH*SCREENHEIGHT);
2205 // V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2211 //---------------------------------------------------------------------------
2215 //---------------------------------------------------------------------------
2217 static void SetMenu(MenuType_t menu)
2219 CurrentMenu->oldItPos = CurrentItPos;
2220 CurrentMenu = Menus[menu];
2221 CurrentItPos = CurrentMenu->oldItPos;
2224 //---------------------------------------------------------------------------
2228 //---------------------------------------------------------------------------
2230 static void DrawSlider(Menu_t *menu, int item, int width, int slot)
2238 y = menu->y+2+(item*ITEM_HEIGHT);
2241 OGL_DrawPatch_CS(x-32, y, W_GetNumForName("M_SLDLT"));
2242 for(x2 = x, count = width; count--; x2 += 8)
2244 OGL_DrawPatch_CS( x2, y, W_GetNumForName(count&1 ? "M_SLDMD1" :
2247 OGL_DrawPatch_CS(x2, y, W_GetNumForName("M_SLDRT"));
2248 OGL_DrawPatch_CS(x+4+slot*8, y+7, W_GetNumForName("M_SLDKB"));
2250 V_DrawPatch(x-32, y, W_CacheLumpName("M_SLDLT", PU_CACHE));
2251 for(x2 = x, count = width; count--; x2 += 8)
2253 V_DrawPatch(x2, y, W_CacheLumpName(count&1 ? "M_SLDMD1"
2254 : "M_SLDMD2", PU_CACHE));
2256 V_DrawPatch(x2, y, W_CacheLumpName("M_SLDRT", PU_CACHE));
2257 V_DrawPatch(x+4+slot*8, y+7, W_CacheLumpName("M_SLDKB", PU_CACHE));