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 /* see defaults[] in m_misc.c for the correct option number:
386 * key_right corresponds to defaults[3], which means that we
387 * are using the (index_number - 3) here.
389 { ITT_SETKEY, "TURN RIGHT :", SCSetKey, 0, MENU_NONE },
390 { ITT_SETKEY, "TURN LEFT :", SCSetKey, 1, MENU_NONE },
391 { ITT_SETKEY, "MOVE FORWARD :", SCSetKey, 2, MENU_NONE },
392 { ITT_SETKEY, "MOVE BACK :" , SCSetKey, 3, MENU_NONE },
393 { ITT_SETKEY, "STRAFE LEFT :", SCSetKey, 4, MENU_NONE },
394 { ITT_SETKEY, "STRAFE RIGHT :", SCSetKey, 5, MENU_NONE },
395 { ITT_SETKEY, "JUMP :", SCSetKey, 6, MENU_NONE },
396 { ITT_SETKEY, "FLY UP :", SCSetKey, 7, MENU_NONE },
397 { ITT_SETKEY, "FLY DOWN :", SCSetKey, 8, MENU_NONE },
398 { ITT_SETKEY, "FLY CENTER :", SCSetKey, 9, MENU_NONE },
399 { ITT_SETKEY, "LOOK UP :", SCSetKey, 10, MENU_NONE },
400 { ITT_SETKEY, "LOOK DOWN :", SCSetKey, 11, MENU_NONE },
401 { ITT_SETKEY, "LOOK CENTER :", SCSetKey, 12, MENU_NONE },
402 { ITT_SETKEY, "INVETORY LEFT :", SCSetKey, 13, MENU_NONE },
403 { ITT_SETKEY, "INVENTORY RIGHT :", SCSetKey, 14, MENU_NONE },
404 { ITT_SETKEY, "USE ARTIFACT :", SCSetKey, 15, MENU_NONE },
405 { ITT_SETKEY, "FIRE :", SCSetKey, 16, MENU_NONE },
406 { ITT_SETKEY, "USE :", SCSetKey, 17, MENU_NONE },
407 { ITT_SETKEY, "STRAFE :", SCSetKey, 18, MENU_NONE },
408 { ITT_SETKEY, "SPEED :", SCSetKey, 19, MENU_NONE }
410 static Menu_t Options3Menu =
420 static Menu_t *Menus[] =
433 #if defined(__linux) || #defined(__FreeBSD__)
434 static char *GammaText[] =
444 // CODE --------------------------------------------------------------------
445 char *Key2String(int key)
449 return "RIGHT ARROW";
480 if(key >= 'a' && key <= 'z') return stupidtable[(key - 'a')];
485 void ClearControls(int key)
491 if(*defaults[i].location == key) *defaults[i].location = 0;
495 //---------------------------------------------------------------------------
499 //---------------------------------------------------------------------------
505 // messageson = true; // Set by defaults in .CFG
506 MauloBaseLump = W_GetNumForName("FBULA0"); // ("M_SKL00");
509 //---------------------------------------------------------------------------
513 //---------------------------------------------------------------------------
515 static void InitFonts(void)
517 FontABaseLump = W_GetNumForName("FONTA_S")+1;
518 FontAYellowBaseLump = W_GetNumForName("FONTAY_S")+1;
519 FontBBaseLump = W_GetNumForName("FONTB_S")+1;
522 //---------------------------------------------------------------------------
526 // Draw text using font A.
528 //---------------------------------------------------------------------------
530 void MN_DrTextA(char *text, int x, int y)
536 OGL_SetColorAndAlpha( 1, 1, 1, 1 );
539 while((c = *text++) != 0)
547 p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
549 OGL_DrawPatch_CS(x, y, FontABaseLump+c-33);
551 V_DrawPatch(x, y, p);
558 //==========================================================================
562 //==========================================================================
564 void MN_DrTextAYellow(char *text, int x, int y)
570 OGL_SetColorAndAlpha( 1, 1, 1, 1 );
573 while((c = *text++) != 0)
581 p = W_CacheLumpNum(FontAYellowBaseLump+c-33, PU_CACHE);
583 OGL_DrawPatch_CS(x, y, FontAYellowBaseLump+c-33);
585 V_DrawPatch(x, y, p);
592 //---------------------------------------------------------------------------
594 // FUNC MN_TextAWidth
596 // Returns the pixel width of a string using font A.
598 //---------------------------------------------------------------------------
600 int MN_TextAWidth(char *text)
607 while((c = *text++) != 0)
615 p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
622 //---------------------------------------------------------------------------
626 // Draw text using font B.
628 //---------------------------------------------------------------------------
630 void MN_DrTextB(char *text, int x, int y)
636 OGL_SetColorAndAlpha( 1, 1, 1, 1 );
639 while((c = *text++) != 0)
647 p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
649 OGL_DrawPatch_CS(x, y, FontBBaseLump+c-33);
651 V_DrawPatch(x, y, p);
658 //---------------------------------------------------------------------------
660 // FUNC MN_TextBWidth
662 // Returns the pixel width of a string using font B.
664 //---------------------------------------------------------------------------
666 int MN_TextBWidth(char *text)
673 while((c = *text++) != 0)
681 p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
688 //---------------------------------------------------------------------------
692 //---------------------------------------------------------------------------
696 if(MenuActive == false)
701 bgAlpha -= .5/(float)menuDarkTicks;
702 if(bgAlpha < 0) bgAlpha = 0;
706 outFade += 1/(float)slamInTicks;
707 if(outFade > 1) fadingOut = false;
717 void MN_OGL_SetupState(float time)
719 glMatrixMode(GL_MODELVIEW);
722 if(time > 1 && time <= 2)
725 glTranslatef(160, 100, 0);
726 glScalef(.9+time*.1, .9+time*.1, 1);
727 glTranslatef(-160, -100, 0);
728 glColor4f(1, 1, 1, time);
732 glTranslatef(160, 100, 0);
733 glScalef(2-time, 2-time, 1);
734 glTranslatef(-160, -100, 0);
735 glColor4f(1, 1, 1, time*time);
738 void MN_OGL_RestoreState()
740 glMatrixMode(GL_MODELVIEW);
746 //---------------------------------------------------------------------------
750 //---------------------------------------------------------------------------
754 "ARE YOU SURE YOU WANT TO QUIT?",
755 "ARE YOU SURE YOU WANT TO END THE GAME?",
756 "DO YOU WANT TO QUICKSAVE THE GAME NAMED",
757 "DO YOU WANT TO QUICKLOAD THE GAME NAMED",
758 "ARE YOU SURE YOU WANT TO SUICIDE?"
762 #define BETA_FLASH_TEXT "BETA"
773 if(MenuActive == false)
778 UpdateState |= I_FULLSCRN;
779 BorderNeedRefresh = true;
780 //OGL_SetNoTexture();
781 glDisable( GL_TEXTURE_2D );
782 OGL_DrawRect(0,0,320,200,0,0,0,bgAlpha);
783 glEnable( GL_TEXTURE_2D );
788 MN_DrTextA(QuitEndMsg[typeofask-1], 160-
789 MN_TextAWidth(QuitEndMsg[typeofask-1])/2, 80);
792 MN_DrTextA(SlotText[quicksave-1], 160-
793 MN_TextAWidth(SlotText[quicksave-1])/2, 90);
795 MN_TextAWidth(SlotText[quicksave-1])/2, 90);
799 MN_DrTextA(SlotText[quickload-1], 160-
800 MN_TextAWidth(SlotText[quickload-1])/2, 90);
802 MN_TextAWidth(SlotText[quicksave-1])/2, 90);
804 UpdateState |= I_FULLSCRN;
808 if( MenuActive || fadingOut )
810 int effTime = (MenuTime>menuDarkTicks)? menuDarkTicks : MenuTime;
811 float temp = .5 * effTime/(float)menuDarkTicks;
813 UpdateState |= I_FULLSCRN;
817 if(temp > bgAlpha) bgAlpha = temp;
818 effTime = (MenuTime>slamInTicks)? slamInTicks : MenuTime;
819 temp = effTime / (float)slamInTicks;
821 // Draw a dark background. It makes it easier to read the menus.
822 //OGL_SetNoTexture();
823 glDisable( GL_TEXTURE_2D );
824 OGL_DrawRect(0,0,320,200,0,0,0,bgAlpha);
825 glEnable( GL_TEXTURE_2D );
827 else temp = outFade+1;
828 MN_OGL_SetupState(temp);
833 MN_OGL_RestoreState();
836 //if(screenblocks < 10)
838 BorderNeedRefresh = true;
840 if(CurrentMenu->drawFunc != NULL)
842 CurrentMenu->drawFunc();
846 item = CurrentMenu->items;
847 if(item->type == ITT_SETKEY)
849 for(i = 0; i < CurrentMenu->itemCount; i++)
857 MN_DrTextA(item->text, x, y+6);
861 MN_DrTextB(item->text, x, y);
863 y += CurrentMenu->step;
866 y = CurrentMenu->y+(CurrentItPos*CurrentMenu->step)+SELECTOR_YOFFSET;
867 selName = MenuTime&16 ? "M_SLCTR1" : "M_SLCTR2";
868 OGL_DrawPatch_CS(x+SELECTOR_XOFFSET, y, W_GetNumForName(selName));
870 MN_OGL_RestoreState();
875 UpdateState |= I_FULLSCRN;
881 if(screenblocks < 10)
883 BorderNeedRefresh = true;
885 if(CurrentMenu->drawFunc != NULL)
887 CurrentMenu->drawFunc();
891 item = CurrentMenu->items;
892 if(item->type == ITT_SETKEY)
894 for(i = 0; i < CurrentMenu->itemCount; i++)
902 MN_DrTextA(item->text, x, y+6);
906 MN_DrTextB(item->text, x, y);
908 y += CurrentMenu->step;
911 y = CurrentMenu->y+(CurrentItPos*CurrentMenu->step)+SELECTOR_YOFFSET;
912 selName = MenuTime&16 ? "M_SLCTR1" : "M_SLCTR2";
913 V_DrawPatch(x+SELECTOR_XOFFSET, y,
914 W_CacheLumpName(selName, PU_CACHE));
919 //---------------------------------------------------------------------------
923 //---------------------------------------------------------------------------
925 static void DrawMainMenu(void)
929 frame = (MenuTime/5)%7;
932 OGL_DrawPatch_CS( 88, 0, W_GetNumForName("M_HTIC") );
933 OGL_DrawPatch_CS( 37, 80, MauloBaseLump+(frame+2)%7 );
934 OGL_DrawPatch_CS( 278, 80, MauloBaseLump+frame );
936 V_DrawPatch(88, 0, W_CacheLumpName("M_HTIC", PU_CACHE));
937 // Old Gold skull positions: (40, 10) and (232, 10)
938 V_DrawPatch(37, 80, W_CacheLumpNum(MauloBaseLump+(frame+2)%7,
940 V_DrawPatch(278, 80, W_CacheLumpNum(MauloBaseLump+frame, PU_CACHE));
944 //==========================================================================
948 //==========================================================================
950 static void DrawClassMenu(void)
953 static char *boxLumpName[4] =
960 static char *walkLumpName[4] =
968 MN_DrTextB("CHOOSE CLASS:", 34, 24);
969 class = (pclass_t)CurrentMenu->items[CurrentItPos].option;
971 OGL_DrawPatch_CS(174, 8, W_GetNumForName(boxLumpName[class]));
972 OGL_DrawPatch_CS(174+24, 8+12,
973 W_GetNumForName(walkLumpName[class])+((MenuTime>>3)&3));
975 V_DrawPatch(174, 8, W_CacheLumpName(boxLumpName[class], PU_CACHE));
976 V_DrawPatch(174+24, 8+12,
977 W_CacheLumpNum(W_GetNumForName(walkLumpName[class])
978 +((MenuTime>>3)&3), PU_CACHE));
982 //---------------------------------------------------------------------------
984 // PROC DrawSkillMenu
986 //---------------------------------------------------------------------------
988 static void DrawSkillMenu(void)
990 MN_DrTextB("CHOOSE SKILL LEVEL:", 74, 16);
993 //---------------------------------------------------------------------------
995 // PROC DrawFilesMenu
997 //---------------------------------------------------------------------------
999 static void DrawFilesMenu(void)
1001 // clear out the quicksave/quickload stuff
1004 P_ClearMessage(&players[consoleplayer]);
1007 //---------------------------------------------------------------------------
1009 // PROC DrawLoadMenu
1011 //---------------------------------------------------------------------------
1013 static void DrawLoadMenu(void)
1015 MN_DrTextB("LOAD GAME", 160-MN_TextBWidth("LOAD GAME")/2, 10);
1020 DrawFileSlots(&LoadMenu);
1023 //---------------------------------------------------------------------------
1025 // PROC DrawSaveMenu
1027 //---------------------------------------------------------------------------
1029 static void DrawSaveMenu(void)
1031 MN_DrTextB("SAVE GAME", 160-MN_TextBWidth("SAVE GAME")/2, 10);
1036 DrawFileSlots(&SaveMenu);
1039 //===========================================================================
1043 // For each slot, looks for save games and reads the description field.
1045 //===========================================================================
1047 void MN_LoadSlotText(void)
1052 char versionText[HXS_VERSION_TEXT_LENGTH];
1053 char description[HXS_DESCRIPTION_LENGTH];
1056 for(slot = 0; slot < 6; slot++)
1059 snprintf(name, 100, "%shex%d.hxs", basePath, slot);
1060 fp = fopen(name, "rb");
1063 fread(description, HXS_DESCRIPTION_LENGTH, 1, fp);
1064 fread(versionText, HXS_VERSION_TEXT_LENGTH, 1, fp);
1066 if(!strcmp(versionText, HXS_VERSION_TEXT))
1073 memcpy(SlotText[slot], description, SLOTTEXTLEN);
1074 SlotStatus[slot] = 1;
1078 memset(SlotText[slot], 0, SLOTTEXTLEN);
1079 SlotStatus[slot] = 0;
1082 slottextloaded = true;
1085 //---------------------------------------------------------------------------
1087 // PROC DrawFileSlots
1089 //---------------------------------------------------------------------------
1091 static void DrawFileSlots(Menu_t *menu)
1099 for(i = 0; i < 6; i++)
1102 OGL_DrawPatch_CS(x, y, W_GetNumForName("M_FSLOT"));
1104 V_DrawPatch(x, y, W_CacheLumpName("M_FSLOT", PU_CACHE));
1108 MN_DrTextA(SlotText[i], x+5, y+5);
1114 //---------------------------------------------------------------------------
1116 // PROC DrawOptionsMenu
1118 //---------------------------------------------------------------------------
1120 static void DrawOptionsMenu(void)
1125 MN_DrTextB("ON", 196, 50);
1129 MN_DrTextB("OFF", 196, 50);
1131 MN_DrTextB(mlooktext[mouselook], 208, 110);
1133 sprintf(num,"%d",mouseSensitivity);
1134 MN_DrTextB(num,265, 71);
1138 MN_DrTextB("ON", 208, 130);
1142 MN_DrTextB("OFF", 208,130);
1146 //---------------------------------------------------------------------------
1148 // PROC DrawOptions2Menu
1150 //---------------------------------------------------------------------------
1152 static void DrawOptions2Menu(void)
1154 DrawSlider(&Options2Menu, 1, 9, screenblocks-3);
1155 DrawSlider(&Options2Menu, 3, 16, snd_MaxVolume);
1156 DrawSlider(&Options2Menu, 5, 16, snd_MusicVolume);
1159 MN_DrTextB("ON", 196, 140);
1163 MN_DrTextB("OFF", 196, 140);
1168 static void DrawOptions3Menu(void)
1174 if(askforkey && keyaskedfor == i) {
1175 MN_DrTextAYellow("???", 195, (i*SMALL_ITEM_HEIGHT+26));
1178 MN_DrTextA(Key2String(*defaults[i+FirstKey+3].location),
1179 195, (i*SMALL_ITEM_HEIGHT+26));
1185 //---------------------------------------------------------------------------
1189 //---------------------------------------------------------------------------
1191 static void SCQuitGame(int option)
1195 typeofask = 1; //quit game
1196 if(!netgame && !demoplayback)
1202 //---------------------------------------------------------------------------
1206 //---------------------------------------------------------------------------
1208 static void SCEndGame(int option)
1218 typeofask = 2; //endgame
1219 if(!netgame && !demoplayback)
1226 //---------------------------------------------------------------------------
1230 //---------------------------------------------------------------------------
1232 static void SCMessages(int option)
1237 P_SetMessage(&players[consoleplayer], "MESSAGES ON", true);
1241 P_SetMessage(&players[consoleplayer], "MESSAGES OFF", true);
1243 S_StartSound(NULL, SFX_CHAT);
1246 //===========================================================================
1250 //===========================================================================
1252 static boolean SCNetCheck(int option)
1261 P_SetMessage(&players[consoleplayer],
1262 "YOU CAN'T START A NEW GAME IN NETPLAY!", true);
1264 case 2: // load game
1265 P_SetMessage(&players[consoleplayer],
1266 "YOU CAN'T LOAD A GAME IN NETPLAY!", true);
1269 P_SetMessage(&players[consoleplayer],
1270 "YOU CAN'T END A GAME IN NETPLAY!", true);
1274 S_StartSound(NULL, SFX_CHAT);
1278 //===========================================================================
1282 //===========================================================================
1284 static void SCNetCheck2(int option)
1290 //---------------------------------------------------------------------------
1294 //---------------------------------------------------------------------------
1296 static void SCLoadGame(int option)
1298 if(!SlotStatus[option])
1299 { // Don't try to load from an empty slot
1303 MN_DeactivateMenu();
1304 BorderNeedRefresh = true;
1307 quickload = option+1;
1308 P_ClearMessage(&players[consoleplayer]);
1312 //---------------------------------------------------------------------------
1316 //---------------------------------------------------------------------------
1318 static void SCSaveGame(int option)
1322 if(!FileMenuKeySteal)
1324 FileMenuKeySteal = true;
1325 strcpy(oldSlotText, SlotText[option]);
1326 ptr = SlotText[option];
1333 SlotStatus[option]++;
1334 currentSlot = option;
1335 slotptr = ptr-SlotText[option];
1340 G_SaveGame(option, SlotText[option]);
1341 FileMenuKeySteal = false;
1342 MN_DeactivateMenu();
1344 BorderNeedRefresh = true;
1347 quicksave = option+1;
1348 P_ClearMessage(&players[consoleplayer]);
1352 //==========================================================================
1356 //==========================================================================
1358 static void SCClass(int option)
1362 P_SetMessage(&players[consoleplayer],
1363 "YOU CAN'T START A NEW GAME FROM WITHIN A NETGAME!", true);
1366 MenuPClass = option;
1369 case PCLASS_FIGHTER:
1371 SkillItems[0].text = "SQUIRE";
1372 SkillItems[1].text = "KNIGHT";
1373 SkillItems[2].text = "WARRIOR";
1374 SkillItems[3].text = "BERSERKER";
1375 SkillItems[4].text = "TITAN";
1379 SkillItems[0].text = "ALTAR BOY";
1380 SkillItems[1].text = "ACOLYTE";
1381 SkillItems[2].text = "PRIEST";
1382 SkillItems[3].text = "CARDINAL";
1383 SkillItems[4].text = "POPE";
1387 SkillItems[0].text = "APPRENTICE";
1388 SkillItems[1].text = "ENCHANTER";
1389 SkillItems[2].text = "SORCERER";
1390 SkillItems[3].text = "WARLOCK";
1391 SkillItems[4].text = "ARCHIMAGE";
1396 SkillItems[0].text = "KNAVE";
1397 SkillItems[1].text = "ROUGE";
1398 SkillItems[2].text = "CUTTHROAT";
1399 SkillItems[3].text = "EXECUTIONER";
1400 SkillItems[4].text = "WIDOW MAKER";
1404 SetMenu(MENU_SKILL);
1407 //---------------------------------------------------------------------------
1411 //---------------------------------------------------------------------------
1413 static void SCSkill(int option)
1415 extern int SB_state;
1417 PlayerClass[consoleplayer] = MenuPClass;
1418 G_DeferredNewGame(option);
1421 MN_DeactivateMenu();
1424 //---------------------------------------------------------------------------
1426 // PROC SCMouseSensi
1428 //---------------------------------------------------------------------------
1430 static void SCMouseSensi(int option)
1432 if(option == RIGHT_DIR)
1434 if(mouseSensitivity < MENU_MAX_MOUSE_SENS)
1439 else if(mouseSensitivity)
1445 //---------------------------------------------------------------------------
1449 //---------------------------------------------------------------------------
1451 static void SCSfxVolume(int option)
1453 if(option == RIGHT_DIR)
1455 if(snd_MaxVolume < 15)
1460 else if(snd_MaxVolume)
1464 soundchanged = true; // we'll set it when we leave the menu
1467 //---------------------------------------------------------------------------
1469 // PROC SCMusicVolume
1471 //---------------------------------------------------------------------------
1473 static void SCMusicVolume(int option)
1475 if(option == RIGHT_DIR)
1477 if(snd_MusicVolume < 15)
1482 else if(snd_MusicVolume)
1489 //---------------------------------------------------------------------------
1491 // PROC SCScreenSize
1493 //---------------------------------------------------------------------------
1495 static void SCScreenSize(int option)
1497 if(option == RIGHT_DIR)
1499 if(screenblocks < 11)
1504 else if(screenblocks > 3)
1508 R_SetViewSize(screenblocks, detailLevel);
1511 //---------------------------------------------------------------------------
1515 //---------------------------------------------------------------------------
1517 static void SCInfo(int option)
1520 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1521 if(!netgame && !demoplayback)
1527 //---------------------------------------------------------------------------
1531 //---------------------------------------------------------------------------
1532 static void SCSetKey(int option)
1535 keyaskedfor = option;
1536 if(!netgame && !demoplayback)
1542 //---------------------------------------------------------------------------
1544 // PROC SCMouslook(int option)
1546 //---------------------------------------------------------------------------
1547 static void SCMouselook(int option)
1549 if(option == RIGHT_DIR)
1551 if(mouselook < 2) mouselook++;
1554 else if(mouselook) mouselook--;
1557 static void SCAlwaysRun(int option)
1559 if(alwaysrun) alwaysrun=0;
1562 static void SCCDAudio(int option)
1573 ST_Message("Attempting to initialize CD Music: ");
1576 i_CDMusic = (I_CDMusInit() != -1);
1579 { // The user is trying to use the cdrom for both game and music
1584 ST_Message("initialized.\n");
1588 ST_Message("failed.\n");
1593 //---------------------------------------------------------------------------
1595 // FUNC MN_Responder
1597 //---------------------------------------------------------------------------
1599 boolean MN_Responder(event_t *event)
1604 extern boolean automapactive;
1605 static boolean shiftdown;
1606 extern void H2_StartTitle(void);
1607 extern void G_CheckDemoStatus(void);
1610 if(askforkey && event->type == ev_keydown)
1612 ClearControls(event->data1);
1613 *defaults[keyaskedfor+3+FirstKey].location = event->data1;
1617 if(askforkey && event->type == ev_mouse)
1620 mbone = defaults[keyaskedfor+3+FirstKey].location;
1622 mbtwo = defaults[keyaskedfor+3+FirstKey].location;
1624 mbthree = defaults[keyaskedfor+3+FirstKey].location;
1628 if(event->data1 == KEY_RSHIFT)
1630 shiftdown = (event->type == ev_keydown);
1632 if(event->type != ev_keydown)
1641 InfoType = (InfoType+1)%5;
1645 InfoType = (InfoType+1)%4;
1647 if(key == KEY_ESCAPE)
1653 if(!netgame && !demoplayback)
1657 MN_DeactivateMenu();
1658 SB_state = -1; //refresh the statbar
1659 BorderNeedRefresh = true;
1661 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1662 return(true); //make the info screen eat the keypress
1665 if(ravpic && key == KEY_F1)
1681 G_CheckDemoStatus();
1685 P_ClearMessage(&players[consoleplayer]);
1689 I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
1690 H2_StartTitle(); // go to intro/demo mode.
1693 P_SetMessage(&players[consoleplayer],
1694 "QUICKSAVING....", false);
1695 FileMenuKeySteal = true;
1696 SCSaveGame(quicksave-1);
1699 BorderNeedRefresh = true;
1702 P_SetMessage(&players[consoleplayer],
1703 "QUICKLOADING....", false);
1704 SCLoadGame(quickload-1);
1707 BorderNeedRefresh = true;
1712 BorderNeedRefresh = true;
1713 mn_SuicideConsole = true;
1717 return true; // eat the 'y' keypress
1725 players[consoleplayer].messageTics = 0;
1729 UpdateState |= I_FULLSCRN;
1730 BorderNeedRefresh = true;
1735 return false; // don't let the keys filter thru
1737 if(MenuActive == false && !chatmodeon)
1743 { // Don't screen size in automap
1746 SCScreenSize(LEFT_DIR);
1747 S_StartSound(NULL, SFX_PICKUP_KEY);
1748 BorderNeedRefresh = true;
1749 UpdateState |= I_FULLSCRN;
1753 { // Don't screen size in automap
1756 SCScreenSize(RIGHT_DIR);
1757 S_StartSound(NULL, SFX_PICKUP_KEY);
1758 BorderNeedRefresh = true;
1759 UpdateState |= I_FULLSCRN;
1765 typeofask = 5; // suicide
1769 case KEY_F1: // help screen
1770 SCInfo(0); // start up info screens
1773 case KEY_F2: // save game
1774 if(gamestate == GS_LEVEL && !demoplayback)
1777 FileMenuKeySteal = false;
1779 CurrentMenu = &SaveMenu;
1780 CurrentItPos = CurrentMenu->oldItPos;
1781 if(!netgame && !demoplayback)
1785 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1786 slottextloaded = false; //reload the slot text, when needed
1789 case KEY_F3: // load game
1793 FileMenuKeySteal = false;
1795 CurrentMenu = &LoadMenu;
1796 CurrentItPos = CurrentMenu->oldItPos;
1797 if(!netgame && !demoplayback)
1801 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1802 slottextloaded = false; //reload the slot text, when needed
1805 case KEY_F4: // volume
1807 FileMenuKeySteal = false;
1809 CurrentMenu = &Options2Menu;
1810 CurrentItPos = CurrentMenu->oldItPos;
1811 if(!netgame && !demoplayback)
1815 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1816 slottextloaded = false; //reload the slot text, when needed
1821 typeofask = 5; // suicide
1823 case KEY_F6: // quicksave
1824 if(gamestate == GS_LEVEL && !demoplayback)
1826 if(!quicksave || quicksave == -1)
1829 FileMenuKeySteal = false;
1831 CurrentMenu = &SaveMenu;
1832 CurrentItPos = CurrentMenu->oldItPos;
1833 if(!netgame && !demoplayback)
1837 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1838 slottextloaded = false; //reload the slot text
1840 P_SetMessage(&players[consoleplayer],
1841 "CHOOSE A QUICKSAVE SLOT", true);
1847 if(!netgame && !demoplayback)
1851 S_StartSound(NULL, SFX_CHAT);
1855 case KEY_F7: // endgame
1858 if(gamestate == GS_LEVEL && !demoplayback)
1860 S_StartSound(NULL, SFX_CHAT);
1865 case KEY_F8: // toggle messages
1868 case KEY_F9: // quickload
1871 if(!quickload || quickload == -1)
1874 FileMenuKeySteal = false;
1876 CurrentMenu = &LoadMenu;
1877 CurrentItPos = CurrentMenu->oldItPos;
1878 if(!netgame && !demoplayback)
1882 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1883 slottextloaded = false; // reload the slot text
1885 P_SetMessage(&players[consoleplayer],
1886 "CHOOSE A QUICKLOAD SLOT", true);
1891 if(!netgame && !demoplayback)
1896 S_StartSound(NULL, SFX_CHAT);
1900 case KEY_F10: // quit
1901 if(gamestate == GS_LEVEL || gamestate == GS_FINALE)
1904 S_StartSound(NULL, SFX_CHAT);
1907 case KEY_F11: // F11 - gamma mode correction
1913 SB_PaletteFlash(true); // force change
1914 P_SetMessage(&players[consoleplayer], GammaText[usegamma],
1917 case KEY_F12: // F12 - reload current map (devmaps mode)
1918 if(netgame || DevMaps == false)
1922 if(gamekeydown[key_speed])
1926 if(gamekeydown[key_strafe])
1930 G_DeferedInitNew(gameskill, gameepisode, gamemap);
1931 P_SetMessage(&players[consoleplayer], TXT_CHEATWARP,
1939 if(MenuActive == false)
1941 if(key == KEY_ESCAPE || gamestate == GS_DEMOSCREEN || demoplayback)
1948 if(!FileMenuKeySteal)
1950 item = &CurrentMenu->items[CurrentItPos];
1956 if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos+1 > CurrentMenu->itemCount-1)
1960 CurrentItPos = 0; //End of Key menu
1968 else if(CurrentItPos+1 > CurrentMenu->itemCount-1)
1976 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
1977 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
1983 if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos==0)
1987 CurrentItPos = 14; //End of Key menu
1995 else if(CurrentItPos == 0)
1997 CurrentItPos = CurrentMenu->itemCount-1;
2003 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
2004 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
2008 if(item->type == ITT_LRFUNC && item->func != NULL)
2010 item->func(LEFT_DIR);
2011 S_StartSound(NULL, SFX_PICKUP_KEY);
2015 case KEY_RIGHTARROW:
2016 if(item->type == ITT_LRFUNC && item->func != NULL)
2018 item->func(RIGHT_DIR);
2019 S_StartSound(NULL, SFX_PICKUP_KEY);
2024 if(item->type == ITT_SETMENU)
2026 if(item->func != NULL)
2028 item->func(item->option);
2030 SetMenu(item->menu);
2032 else if(item->func != NULL)
2034 CurrentMenu->oldItPos = CurrentItPos;
2035 if(item->type == ITT_LRFUNC)
2037 item->func(RIGHT_DIR);
2039 else if(item->type == ITT_EFUNC)
2041 item->func(item->option);
2043 else if(item->type == ITT_SETKEY)
2045 item->func(item->option);
2048 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
2052 MN_DeactivateMenu();
2055 S_StartSound(NULL, SFX_PICKUP_KEY);
2056 if(CurrentMenu->prevMenu == MENU_NONE)
2058 MN_DeactivateMenu();
2062 SetMenu(CurrentMenu->prevMenu);
2066 for(i = 0; i < CurrentMenu->itemCount; i++)
2068 if(CurrentMenu->items[i].text)
2071 == toupper(CurrentMenu->items[i].text[0]))
2083 { // Editing file names
2084 textBuffer = &SlotText[currentSlot][slotptr];
2085 if(key == KEY_BACKSPACE)
2090 *textBuffer = ASCII_CURSOR;
2095 if(key == KEY_ESCAPE)
2097 memset(SlotText[currentSlot], 0, SLOTTEXTLEN+2);
2098 strcpy(SlotText[currentSlot], oldSlotText);
2099 SlotStatus[currentSlot]--;
2100 MN_DeactivateMenu();
2103 if(key == KEY_ENTER)
2105 SlotText[currentSlot][slotptr] = 0; // clear the cursor
2106 item = &CurrentMenu->items[CurrentItPos];
2107 CurrentMenu->oldItPos = CurrentItPos;
2108 if(item->type == ITT_EFUNC)
2110 item->func(item->option);
2111 if(item->menu != MENU_NONE)
2113 SetMenu(item->menu);
2118 if(slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE)
2120 if((key >= 'a' && key <= 'z'))
2122 *textBuffer++ = key-32;
2123 *textBuffer = ASCII_CURSOR;
2127 if(((key >= '0' && key <= '9') || key == ' '
2128 || key == ',' || key == '.' || key == '-')
2131 *textBuffer++ = key;
2132 *textBuffer = ASCII_CURSOR;
2136 if(shiftdown && key == '1')
2138 *textBuffer++ = '!';
2139 *textBuffer = ASCII_CURSOR;
2149 //---------------------------------------------------------------------------
2151 // PROC MN_ActivateMenu
2153 //---------------------------------------------------------------------------
2155 void MN_ActivateMenu(void)
2166 FileMenuKeySteal = false;
2168 CurrentMenu = &MainMenu;
2169 CurrentItPos = CurrentMenu->oldItPos;
2170 if(!netgame && !demoplayback)
2174 S_StartSound(NULL, SFX_PLATFORM_STOP);
2175 slottextloaded = false; //reload the slot text, when needed
2178 //---------------------------------------------------------------------------
2180 // PROC MN_DeactivateMenu
2182 //---------------------------------------------------------------------------
2184 void MN_DeactivateMenu(void)
2186 CurrentMenu->oldItPos = CurrentItPos;
2192 S_StartSound(NULL, SFX_PLATFORM_STOP);
2193 P_ClearMessage(&players[consoleplayer]);
2196 //---------------------------------------------------------------------------
2200 //---------------------------------------------------------------------------
2202 void MN_DrawInfo(void)
2206 OGL_DrawRawScreen( W_GetNumForName("TITLE")+InfoType );
2208 I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
2209 memcpy(screen, (byte *)W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2210 PU_CACHE), SCREENWIDTH*SCREENHEIGHT);
2211 // V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2217 //---------------------------------------------------------------------------
2221 //---------------------------------------------------------------------------
2223 static void SetMenu(MenuType_t menu)
2225 CurrentMenu->oldItPos = CurrentItPos;
2226 CurrentMenu = Menus[menu];
2227 CurrentItPos = CurrentMenu->oldItPos;
2230 //---------------------------------------------------------------------------
2234 //---------------------------------------------------------------------------
2236 static void DrawSlider(Menu_t *menu, int item, int width, int slot)
2244 y = menu->y+2+(item*ITEM_HEIGHT);
2247 OGL_DrawPatch_CS(x-32, y, W_GetNumForName("M_SLDLT"));
2248 for(x2 = x, count = width; count--; x2 += 8)
2250 OGL_DrawPatch_CS( x2, y, W_GetNumForName(count&1 ? "M_SLDMD1" :
2253 OGL_DrawPatch_CS(x2, y, W_GetNumForName("M_SLDRT"));
2254 OGL_DrawPatch_CS(x+4+slot*8, y+7, W_GetNumForName("M_SLDKB"));
2256 V_DrawPatch(x-32, y, W_CacheLumpName("M_SLDLT", PU_CACHE));
2257 for(x2 = x, count = width; count--; x2 += 8)
2259 V_DrawPatch(x2, y, W_CacheLumpName(count&1 ? "M_SLDMD1"
2260 : "M_SLDMD2", PU_CACHE));
2262 V_DrawPatch(x2, y, W_CacheLumpName("M_SLDRT", PU_CACHE));
2263 V_DrawPatch(x+4+slot*8, y+7, W_CacheLumpName("M_SLDKB", PU_CACHE));