osezer patch 012
[theoddone33/hhexen.git] / base / mn_menu.c
1 //**************************************************************************
2 //**
3 //** mn_menu.c : Heretic 2 : Raven Software, Corp.
4 //**
5 //** $RCSfile$
6 //** $Revision$
7 //** $Date$
8 //** $Author$
9 //**
10 //**************************************************************************
11
12 // HEADER FILES ------------------------------------------------------------
13
14 #include <ctype.h>
15 #include "h2def.h"
16 #include "p_local.h"
17 #include "r_local.h"
18 #include "soundst.h"
19
20 #ifdef RENDER3D
21 #include "ogl_def.h"
22 #endif
23
24 // MACROS ------------------------------------------------------------------
25
26 #define LEFT_DIR 0
27 #define RIGHT_DIR 1
28 #define ITEM_HEIGHT 20
29 #define SMALL_ITEM_HEIGHT 9
30 #define MENU_MAX_MOUSE_SENS 50
31
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 '['
42
43 // TYPES -------------------------------------------------------------------
44
45 typedef enum
46 {
47         ITT_EMPTY,
48         ITT_EFUNC,
49         ITT_LRFUNC,
50         ITT_SETMENU,
51         ITT_INERT,
52         ITT_SETKEY
53 } ItemType_t;
54
55 typedef enum
56 {
57         MENU_MAIN,
58         MENU_CLASS,
59         MENU_SKILL,
60         MENU_OPTIONS,
61         MENU_OPTIONS2,
62         MENU_OPTIONS3,
63         MENU_FILES,
64         MENU_LOAD,
65         MENU_SAVE,
66         MENU_NONE
67 } MenuType_t;
68
69 typedef struct
70 {
71         ItemType_t type;
72         char *text;
73         void (*func)(int option);
74         int option;
75         MenuType_t menu;
76 } MenuItem_t;
77
78 typedef struct
79 {
80         int x;
81         int y;
82         void (*drawFunc)(void);
83         int itemCount;
84         MenuItem_t *items;
85         int oldItPos;
86         int step;
87         MenuType_t prevMenu;
88
89 #ifdef RENDER3D
90 #if 0
91     void (*textDrawer)(char*,int,int);
92     int itemHeight;
93 #endif
94 #endif
95
96 } Menu_t;
97
98 char *mlooktext[] =
99 {
100         "OFF",
101         "NORMAL",
102         "INVERSE"
103 };
104
105 boolean cdaudio;
106
107 extern int alwaysrun;
108 extern boolean i_CDMusic;
109 extern int I_CDMusInit( void );
110 extern int I_CDMusStop( void );
111
112 extern int mouselook;
113
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;
120
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"};
123
124 extern default_t defaults[];
125 int FirstKey = 0;
126
127 boolean askforkey = false;
128 int keyaskedfor;
129 int *mbone, *mbtwo, *mbthree;
130
131 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
132
133 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
134
135 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
136
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);
172
173 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
174
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
180
181 // PUBLIC DATA DEFINITIONS -------------------------------------------------
182
183 boolean MenuActive;
184 int InfoType;
185 boolean messageson;
186 boolean mn_SuicideConsole;
187
188 // PRIVATE DATA DEFINITIONS ------------------------------------------------
189
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;
197 static int MenuTime;
198 static boolean soundchanged;
199
200 #ifdef RENDER3D
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;
206 #endif
207
208 boolean askforquit;
209 static boolean FileMenuKeySteal;
210 static boolean slottextloaded;
211 static char SlotText[6][SLOTTEXTLEN+2];
212 static char oldSlotText[SLOTTEXTLEN+2];
213 static int SlotStatus[6];
214 static int slotptr;
215 static int currentSlot;
216 static int quicksave;
217 static int quickload;
218 static int typeofask;
219
220 static MenuItem_t MainItems[] =
221 {
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 }
227 };
228
229 static Menu_t MainMenu =
230 {
231         110, 56,
232         DrawMainMenu,
233         5, MainItems,
234         0,
235         ITEM_HEIGHT,
236         MENU_NONE
237 };
238
239 static MenuItem_t ClassItems[] =
240 {
241         { ITT_EFUNC, "FIGHTER", SCClass, 0, MENU_NONE },
242         { ITT_EFUNC, "CLERIC", SCClass, 1, MENU_NONE },
243         { ITT_EFUNC, "MAGE", SCClass, 2, MENU_NONE }
244 #ifdef ASSASSIN 
245         ,{ ITT_EFUNC, "ASSASSIN", SCClass, 3, MENU_NONE }
246 #endif
247 };
248
249 static Menu_t ClassMenu =
250 {
251         66, 66,
252         DrawClassMenu,
253 #ifdef ASSASSIN 
254         4
255 #else 
256         3
257 #endif
258         , ClassItems,
259         0,
260         ITEM_HEIGHT,
261         MENU_MAIN
262 };
263
264 static MenuItem_t FilesItems[] =
265 {
266         { ITT_SETMENU, "LOAD GAME", SCNetCheck2, 2, MENU_LOAD },
267         { ITT_SETMENU, "SAVE GAME", NULL, 0, MENU_SAVE }
268 };
269
270 static Menu_t FilesMenu =
271 {
272         110, 60,
273         DrawFilesMenu,
274         2, FilesItems,
275         0,
276         ITEM_HEIGHT,
277         MENU_MAIN
278 };
279
280 static MenuItem_t LoadItems[] =
281 {
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 }
288 };
289
290 static Menu_t LoadMenu =
291 {
292         70, 30,
293         DrawLoadMenu,
294         6, LoadItems,
295         0,
296         ITEM_HEIGHT,
297         MENU_FILES
298 };
299
300 static MenuItem_t SaveItems[] =
301 {
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 }
308 };
309
310 static Menu_t SaveMenu =
311 {
312         70, 30,
313         DrawSaveMenu,
314         6, SaveItems,
315         0,
316         ITEM_HEIGHT,
317         MENU_FILES
318 };
319
320 static MenuItem_t SkillItems[] =
321 {
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 }
327 };
328
329 static Menu_t SkillMenu =
330 {
331         120, 44,
332         DrawSkillMenu,
333         5, SkillItems,
334         2,
335         ITEM_HEIGHT,
336         MENU_CLASS
337 };
338
339 static MenuItem_t OptionsItems[] =
340 {
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 }
348 };
349
350 static Menu_t OptionsMenu =
351 {
352         88, 30,
353         DrawOptionsMenu,
354         7,
355         OptionsItems,
356         0,
357         ITEM_HEIGHT,
358         MENU_MAIN
359 };
360
361 static MenuItem_t Options2Items[] =
362 {
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 }
370 };
371
372 static Menu_t Options2Menu =
373 {
374         90, 20,
375         DrawOptions2Menu,
376         7,
377         Options2Items,
378         0,
379         ITEM_HEIGHT,
380         MENU_OPTIONS
381 };
382
383 static MenuItem_t Options3Items[] =
384 {
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.
388  */
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 }
409 };
410 static Menu_t Options3Menu = 
411 {
412         70,20,
413         DrawOptions3Menu,
414         15, Options3Items,
415         0,
416         SMALL_ITEM_HEIGHT,
417         MENU_OPTIONS
418 };
419
420 static Menu_t *Menus[] =
421 {
422         &MainMenu,
423         &ClassMenu,
424         &SkillMenu,
425         &OptionsMenu,
426         &Options2Menu,
427         &Options3Menu,
428         &FilesMenu,
429         &LoadMenu,
430         &SaveMenu
431 };
432
433 #if defined(__linux) || #defined(__FreeBSD__)
434 static char *GammaText[] = 
435 {
436         TXT_GAMMA_LEVEL_OFF,
437         TXT_GAMMA_LEVEL_1,
438         TXT_GAMMA_LEVEL_2,
439         TXT_GAMMA_LEVEL_3,
440         TXT_GAMMA_LEVEL_4
441 };
442 #endif
443         
444 // CODE --------------------------------------------------------------------
445 char *Key2String(int key)
446 {
447   switch(key) {
448         case KEY_RIGHTARROW:
449         return "RIGHT ARROW";
450         case KEY_LEFTARROW:
451         return "LEFT ARROW";
452         case KEY_DOWNARROW:
453         return "DOWN ARROW";
454         case KEY_UPARROW:
455         return "UP ARROW";
456         case KEY_ENTER:
457         return "ENTER";
458         case KEY_PGUP:
459         return "PAGE UP";
460         case KEY_PGDN:
461         return "PAGE DOWN";
462         case KEY_INS:
463         return "INSERT";
464         case KEY_HOME:
465         return "HOME";
466         case KEY_END:
467         return "END";
468         case KEY_DEL:
469         return "DELETE";
470         case ' ':
471         return "SPACE";
472         case KEY_RSHIFT:
473         return "SHIFT";
474         case KEY_RALT:
475         return "ALT";
476         case KEY_RCTRL:
477         return "CTRL";
478   }
479   //Handle letter keys
480   if(key >= 'a' && key <= 'z') return stupidtable[(key - 'a')];
481   //Everything else
482   return " ";
483 }
484
485 void ClearControls(int key)
486 {
487         int i;
488
489         for(i=3;i<24;i++)
490         {
491                 if(*defaults[i].location == key) *defaults[i].location = 0;
492         }
493 }
494
495 //---------------------------------------------------------------------------
496 //
497 // PROC MN_Init
498 //
499 //---------------------------------------------------------------------------
500
501 void MN_Init(void)
502 {
503         InitFonts();
504         MenuActive = false;
505 //      messageson = true;              // Set by defaults in .CFG
506         MauloBaseLump = W_GetNumForName("FBULA0"); // ("M_SKL00");
507 }
508
509 //---------------------------------------------------------------------------
510 //
511 // PROC InitFonts
512 //
513 //---------------------------------------------------------------------------
514
515 static void InitFonts(void)
516 {
517         FontABaseLump = W_GetNumForName("FONTA_S")+1;
518         FontAYellowBaseLump = W_GetNumForName("FONTAY_S")+1;
519         FontBBaseLump = W_GetNumForName("FONTB_S")+1;
520 }
521
522 //---------------------------------------------------------------------------
523 //
524 // PROC MN_DrTextA
525 //
526 // Draw text using font A.
527 //
528 //---------------------------------------------------------------------------
529
530 void MN_DrTextA(char *text, int x, int y)
531 {
532         char c;
533         patch_t *p;
534
535 #ifdef RENDER3D
536     OGL_SetColorAndAlpha( 1, 1, 1, 1 );
537 #endif
538
539         while((c = *text++) != 0)
540         {
541                 if(c < 33)
542                 {
543                         x += 5;
544                 }
545                 else
546                 {
547                         p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
548 #ifdef RENDER3D
549             OGL_DrawPatch_CS(x, y, FontABaseLump+c-33);
550 #else
551                         V_DrawPatch(x, y, p);
552 #endif
553                         x += p->width-1;
554                 }
555         }
556 }
557
558 //==========================================================================
559 //
560 // MN_DrTextAYellow
561 //
562 //==========================================================================
563
564 void MN_DrTextAYellow(char *text, int x, int y)
565 {
566         char c;
567         patch_t *p;
568
569 #ifdef RENDER3D
570     OGL_SetColorAndAlpha( 1, 1, 1, 1 );
571 #endif
572
573         while((c = *text++) != 0)
574         {
575                 if(c < 33)
576                 {
577                         x += 5;
578                 }
579                 else
580                 {
581                         p = W_CacheLumpNum(FontAYellowBaseLump+c-33, PU_CACHE);
582 #ifdef RENDER3D
583             OGL_DrawPatch_CS(x, y, FontAYellowBaseLump+c-33);
584 #else
585                         V_DrawPatch(x, y, p);
586 #endif
587                         x += p->width-1;
588                 }
589         }
590 }
591
592 //---------------------------------------------------------------------------
593 //
594 // FUNC MN_TextAWidth
595 //
596 // Returns the pixel width of a string using font A.
597 //
598 //---------------------------------------------------------------------------
599
600 int MN_TextAWidth(char *text)
601 {
602         char c;
603         int width;
604         patch_t *p;
605
606         width = 0;
607         while((c = *text++) != 0)
608         {
609                 if(c < 33)
610                 {
611                         width += 5;
612                 }
613                 else
614                 {
615                         p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
616                         width += p->width-1;
617                 }
618         }
619         return(width);
620 }
621
622 //---------------------------------------------------------------------------
623 //
624 // PROC MN_DrTextB
625 //
626 // Draw text using font B.
627 //
628 //---------------------------------------------------------------------------
629
630 void MN_DrTextB(char *text, int x, int y)
631 {
632         char c;
633         patch_t *p;
634
635 #ifdef RENDER3D
636     OGL_SetColorAndAlpha( 1, 1, 1, 1 );
637 #endif
638
639         while((c = *text++) != 0)
640         {
641                 if(c < 33)
642                 {
643                         x += 8;
644                 }
645                 else
646                 {
647                         p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
648 #ifdef RENDER3D
649             OGL_DrawPatch_CS(x, y, FontBBaseLump+c-33);
650 #else
651                         V_DrawPatch(x, y, p);
652 #endif
653                         x += p->width-1;
654                 }
655         }
656 }
657
658 //---------------------------------------------------------------------------
659 //
660 // FUNC MN_TextBWidth
661 //
662 // Returns the pixel width of a string using font B.
663 //
664 //---------------------------------------------------------------------------
665
666 int MN_TextBWidth(char *text)
667 {
668         char c;
669         int width;
670         patch_t *p;
671
672         width = 0;
673         while((c = *text++) != 0)
674         {
675                 if(c < 33)
676                 {
677                         width += 5;
678                 }
679                 else
680                 {
681                         p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
682                         width += p->width-1;
683                 }
684         }
685         return(width);
686 }
687
688 //---------------------------------------------------------------------------
689 //
690 // PROC MN_Ticker
691 //
692 //---------------------------------------------------------------------------
693
694 void MN_Ticker(void)
695 {
696         if(MenuActive == false)
697         {
698 #ifdef RENDER3D
699         if(bgAlpha > 0)
700         {
701             bgAlpha -= .5/(float)menuDarkTicks;
702             if(bgAlpha < 0) bgAlpha = 0;
703         }
704         if(fadingOut)
705         {
706             outFade += 1/(float)slamInTicks;
707             if(outFade > 1) fadingOut = false;
708         }
709 #endif
710                 return;
711         }
712         MenuTime++;
713 }
714
715
716 #ifdef RENDER3D
717 void MN_OGL_SetupState(float time)
718 {
719     glMatrixMode(GL_MODELVIEW);
720     glPushMatrix();
721  
722     if(time > 1 && time <= 2)
723     {
724         time = 2-time;
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);
729         return;
730     }
731  
732     glTranslatef(160, 100, 0);
733     glScalef(2-time, 2-time, 1);
734     glTranslatef(-160, -100, 0);
735     glColor4f(1, 1, 1, time*time);
736 }
737  
738 void MN_OGL_RestoreState()
739 {
740     glMatrixMode(GL_MODELVIEW);
741     glPopMatrix();                                                              
742 }
743 #endif
744
745
746 //---------------------------------------------------------------------------
747 //
748 // PROC MN_Drawer
749 //
750 //---------------------------------------------------------------------------
751
752 char *QuitEndMsg[] =
753 {
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?"
759 };
760
761
762 #define BETA_FLASH_TEXT "BETA"
763
764 void MN_Drawer(void)
765 {
766         int i;
767         int x;
768         int y;
769         MenuItem_t *item;
770         char *selName;
771
772
773         if(MenuActive == false)
774         {
775 #ifdef RENDER3D
776         if(bgAlpha > 0)
777         {
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 );
784         }
785 #endif
786                 if(askforquit)
787                 {
788                         MN_DrTextA(QuitEndMsg[typeofask-1], 160-
789                                 MN_TextAWidth(QuitEndMsg[typeofask-1])/2, 80);
790                         if(typeofask == 3)
791                         {
792                                 MN_DrTextA(SlotText[quicksave-1], 160-
793                                         MN_TextAWidth(SlotText[quicksave-1])/2, 90);
794                                 MN_DrTextA("?", 160+
795                                         MN_TextAWidth(SlotText[quicksave-1])/2, 90);
796                         }
797                         if(typeofask == 4)
798                         {
799                                 MN_DrTextA(SlotText[quickload-1], 160-
800                                         MN_TextAWidth(SlotText[quickload-1])/2, 90);
801                                 MN_DrTextA("?", 160+
802                                         MN_TextAWidth(SlotText[quicksave-1])/2, 90);
803                         }
804                         UpdateState |= I_FULLSCRN;
805                 }
806         }
807 #ifdef RENDER3D
808     if( MenuActive || fadingOut )
809     {
810         int effTime = (MenuTime>menuDarkTicks)? menuDarkTicks : MenuTime;
811         float temp = .5 * effTime/(float)menuDarkTicks;
812  
813         UpdateState |= I_FULLSCRN;
814  
815         if(!fadingOut)
816         {
817             if(temp > bgAlpha) bgAlpha = temp;
818             effTime = (MenuTime>slamInTicks)? slamInTicks : MenuTime;
819             temp = effTime / (float)slamInTicks;
820  
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 );
826         }
827         else temp = outFade+1;
828         MN_OGL_SetupState(temp);
829  
830         if(InfoType)
831         {
832             MN_DrawInfo();
833             MN_OGL_RestoreState();
834             return;
835         }
836         //if(screenblocks < 10)
837         //{
838         BorderNeedRefresh = true;
839         //}
840         if(CurrentMenu->drawFunc != NULL)
841         {
842             CurrentMenu->drawFunc();
843         }
844         x = CurrentMenu->x;
845         y = CurrentMenu->y;
846         item = CurrentMenu->items;
847         if(item->type == ITT_SETKEY)
848                 item += FirstKey;
849         for(i = 0; i < CurrentMenu->itemCount; i++)
850         {
851                         switch(item->type)
852                         {
853                                 case (ITT_EMPTY):
854                                         break;
855                                 case (ITT_SETKEY):
856                                         if(item->text) 
857                                                 MN_DrTextA(item->text, x, y+6);
858                                         break;
859                                 default:
860                                         if(item->text)
861                                                 MN_DrTextB(item->text, x, y);
862                         }
863                         y += CurrentMenu->step;
864             item++;
865         }
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));
869  
870         MN_OGL_RestoreState();
871     }
872 #else
873         else
874         {
875                 UpdateState |= I_FULLSCRN;
876                 if(InfoType)
877                 {
878                         MN_DrawInfo();
879                         return;
880                 }
881                 if(screenblocks < 10)
882                 {
883                         BorderNeedRefresh = true;
884                 }
885                 if(CurrentMenu->drawFunc != NULL)
886                 {
887                         CurrentMenu->drawFunc();
888                 }
889                 x = CurrentMenu->x;
890                 y = CurrentMenu->y;
891                 item = CurrentMenu->items;
892                 if(item->type == ITT_SETKEY)
893                         item += FirstKey;
894                 for(i = 0; i < CurrentMenu->itemCount; i++)
895                 {
896                         switch(item->type)
897                         {
898                                 case (ITT_EMPTY):
899                                         break;
900                                 case (ITT_SETKEY):
901                                         if(item->text) 
902                                                 MN_DrTextA(item->text, x, y+6);
903                                         break;
904                                 default:
905                                         if(item->text)
906                                                 MN_DrTextB(item->text, x, y);
907                         }
908                         y += CurrentMenu->step;
909                         item++;
910                 }
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));
915         }
916 #endif
917 }
918
919 //---------------------------------------------------------------------------
920 //
921 // PROC DrawMainMenu
922 //
923 //---------------------------------------------------------------------------
924
925 static void DrawMainMenu(void)
926 {
927         int frame;
928
929         frame = (MenuTime/5)%7;
930
931 #ifdef RENDER3D
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 );
935 #else
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, 
939                 PU_CACHE));
940         V_DrawPatch(278, 80, W_CacheLumpNum(MauloBaseLump+frame, PU_CACHE));
941 #endif
942 }
943
944 //==========================================================================
945 //
946 // DrawClassMenu
947 //
948 //==========================================================================
949
950 static void DrawClassMenu(void)
951 {
952         pclass_t class;
953         static char *boxLumpName[4] =
954         {
955                 "m_fbox",
956                 "m_cbox",
957                 "m_mbox",
958                 "m_abox"
959         };
960         static char *walkLumpName[4] =
961         {
962                 "m_fwalk1",
963                 "m_cwalk1",
964                 "m_mwalk1",
965                 "m_awalk1"
966         };
967
968         MN_DrTextB("CHOOSE CLASS:", 34, 24);
969         class = (pclass_t)CurrentMenu->items[CurrentItPos].option;
970 #ifdef RENDER3D
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));
974 #else
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));
979 #endif
980 }
981
982 //---------------------------------------------------------------------------
983 //
984 // PROC DrawSkillMenu
985 //
986 //---------------------------------------------------------------------------
987
988 static void DrawSkillMenu(void)
989 {
990         MN_DrTextB("CHOOSE SKILL LEVEL:", 74, 16);
991 }
992
993 //---------------------------------------------------------------------------
994 //
995 // PROC DrawFilesMenu
996 //
997 //---------------------------------------------------------------------------
998
999 static void DrawFilesMenu(void)
1000 {
1001 // clear out the quicksave/quickload stuff
1002         quicksave = 0;
1003         quickload = 0;
1004         P_ClearMessage(&players[consoleplayer]);
1005 }
1006
1007 //---------------------------------------------------------------------------
1008 //
1009 // PROC DrawLoadMenu
1010 //
1011 //---------------------------------------------------------------------------
1012
1013 static void DrawLoadMenu(void)
1014 {
1015         MN_DrTextB("LOAD GAME", 160-MN_TextBWidth("LOAD GAME")/2, 10);
1016         if(!slottextloaded)
1017         {
1018                 MN_LoadSlotText();
1019         }
1020         DrawFileSlots(&LoadMenu);
1021 }
1022
1023 //---------------------------------------------------------------------------
1024 //
1025 // PROC DrawSaveMenu
1026 //
1027 //---------------------------------------------------------------------------
1028
1029 static void DrawSaveMenu(void)
1030 {
1031         MN_DrTextB("SAVE GAME", 160-MN_TextBWidth("SAVE GAME")/2, 10);
1032         if(!slottextloaded)
1033         {
1034                 MN_LoadSlotText();
1035         }
1036         DrawFileSlots(&SaveMenu);
1037 }
1038
1039 //===========================================================================
1040 //
1041 // MN_LoadSlotText
1042 //
1043 // For each slot, looks for save games and reads the description field.
1044 //
1045 //===========================================================================
1046
1047 void MN_LoadSlotText(void)
1048 {
1049         int slot;
1050         FILE *fp;
1051         char name[100];
1052         char versionText[HXS_VERSION_TEXT_LENGTH];
1053         char description[HXS_DESCRIPTION_LENGTH];
1054         boolean found;
1055
1056         for(slot = 0; slot < 6; slot++)
1057         {
1058                 found = false;
1059                 snprintf(name, 100, "%shex%d.hxs", basePath, slot);
1060                 fp = fopen(name, "rb");
1061                 if(fp)
1062                 {
1063                         fread(description, HXS_DESCRIPTION_LENGTH, 1, fp);
1064                         fread(versionText, HXS_VERSION_TEXT_LENGTH, 1, fp);
1065                         fclose(fp);
1066                         if(!strcmp(versionText, HXS_VERSION_TEXT))
1067                         {
1068                                 found = true;
1069                         }
1070                 }
1071                 if(found)
1072                 {
1073                         memcpy(SlotText[slot], description, SLOTTEXTLEN);
1074                         SlotStatus[slot] = 1;
1075                 }
1076                 else
1077                 {
1078                         memset(SlotText[slot], 0, SLOTTEXTLEN);
1079                         SlotStatus[slot] = 0;
1080                 }
1081         }
1082         slottextloaded = true;
1083 }
1084
1085 //---------------------------------------------------------------------------
1086 //
1087 // PROC DrawFileSlots
1088 //
1089 //---------------------------------------------------------------------------
1090
1091 static void DrawFileSlots(Menu_t *menu)
1092 {
1093         int i;
1094         int x;
1095         int y;
1096
1097         x = menu->x;
1098         y = menu->y;
1099         for(i = 0; i < 6; i++)
1100         {
1101 #ifdef RENDER3D
1102         OGL_DrawPatch_CS(x, y, W_GetNumForName("M_FSLOT"));
1103 #else
1104                 V_DrawPatch(x, y, W_CacheLumpName("M_FSLOT", PU_CACHE));
1105 #endif
1106                 if(SlotStatus[i])
1107                 {
1108                         MN_DrTextA(SlotText[i], x+5, y+5);
1109                 }
1110                 y += ITEM_HEIGHT;
1111         }
1112 }
1113
1114 //---------------------------------------------------------------------------
1115 //
1116 // PROC DrawOptionsMenu
1117 //
1118 //---------------------------------------------------------------------------
1119
1120 static void DrawOptionsMenu(void)
1121 {
1122 char num[5];
1123         if(messageson)
1124         {
1125                 MN_DrTextB("ON", 196, 50);
1126         }
1127         else
1128         {
1129                 MN_DrTextB("OFF", 196, 50);
1130         }
1131         MN_DrTextB(mlooktext[mouselook], 208, 110);
1132
1133         sprintf(num,"%d",mouseSensitivity);
1134         MN_DrTextB(num,265, 71); 
1135
1136         if(alwaysrun)
1137         {
1138                 MN_DrTextB("ON", 208, 130);
1139         }
1140         else
1141         {
1142                 MN_DrTextB("OFF", 208,130);
1143         }
1144 }
1145
1146 //---------------------------------------------------------------------------
1147 //
1148 // PROC DrawOptions2Menu
1149 //
1150 //---------------------------------------------------------------------------
1151
1152 static void DrawOptions2Menu(void)
1153 {
1154         DrawSlider(&Options2Menu, 1, 9, screenblocks-3);
1155         DrawSlider(&Options2Menu, 3, 16, snd_MaxVolume);
1156         DrawSlider(&Options2Menu, 5, 16, snd_MusicVolume);
1157         if(cdaudio == true)
1158         {
1159                 MN_DrTextB("ON", 196, 140);
1160         }
1161         else
1162         {
1163                 MN_DrTextB("OFF", 196, 140);
1164         }
1165 }
1166
1167
1168 static void DrawOptions3Menu(void)
1169 {
1170         int i;
1171
1172         for(i=0;i<15;i++)
1173         {
1174                 if(askforkey && keyaskedfor == i) {
1175                         MN_DrTextAYellow("???", 195, (i*SMALL_ITEM_HEIGHT+26));
1176                 }
1177                 else {
1178                         MN_DrTextA(Key2String(*defaults[i+FirstKey+3].location),
1179                                 195, (i*SMALL_ITEM_HEIGHT+26));
1180                 }
1181         }
1182
1183 }
1184
1185 //---------------------------------------------------------------------------
1186 //
1187 // PROC SCQuitGame
1188 //
1189 //---------------------------------------------------------------------------
1190
1191 static void SCQuitGame(int option)
1192 {
1193         MenuActive = false;
1194         askforquit = true;
1195         typeofask = 1; //quit game
1196         if(!netgame && !demoplayback)
1197         {
1198                 paused = true;
1199         }
1200 }
1201
1202 //---------------------------------------------------------------------------
1203 //
1204 // PROC SCEndGame
1205 //
1206 //---------------------------------------------------------------------------
1207
1208 static void SCEndGame(int option)
1209 {
1210         if(demoplayback)
1211         {
1212                 return;
1213         }
1214         if(SCNetCheck(3))
1215         {
1216                 MenuActive = false;
1217                 askforquit = true;
1218                 typeofask = 2; //endgame
1219                 if(!netgame && !demoplayback)
1220                 {
1221                         paused = true;
1222                 }
1223         }
1224 }
1225
1226 //---------------------------------------------------------------------------
1227 //
1228 // PROC SCMessages
1229 //
1230 //---------------------------------------------------------------------------
1231
1232 static void SCMessages(int option)
1233 {
1234         messageson ^= 1;
1235         if(messageson)
1236         {
1237                 P_SetMessage(&players[consoleplayer], "MESSAGES ON", true);
1238         }
1239         else
1240         {
1241                 P_SetMessage(&players[consoleplayer], "MESSAGES OFF", true);
1242         }
1243         S_StartSound(NULL, SFX_CHAT);
1244 }
1245
1246 //===========================================================================
1247 //
1248 // SCNetCheck
1249 //
1250 //===========================================================================
1251
1252 static boolean SCNetCheck(int option)
1253 {
1254         if(!netgame)
1255         {
1256                 return true;
1257         }
1258         switch(option)
1259         {
1260                 case 1: // new game
1261                         P_SetMessage(&players[consoleplayer],
1262                                 "YOU CAN'T START A NEW GAME IN NETPLAY!", true);
1263                         break;
1264                 case 2: // load game
1265                         P_SetMessage(&players[consoleplayer],
1266                                 "YOU CAN'T LOAD A GAME IN NETPLAY!", true);
1267                         break;
1268                 case 3: // end game
1269                         P_SetMessage(&players[consoleplayer],
1270                                 "YOU CAN'T END A GAME IN NETPLAY!", true);
1271                         break;
1272         }
1273         MenuActive = false;
1274         S_StartSound(NULL, SFX_CHAT);
1275         return false;
1276 }
1277
1278 //===========================================================================
1279 //
1280 // SCNetCheck2
1281 //
1282 //===========================================================================
1283
1284 static void SCNetCheck2(int option)
1285 {
1286         SCNetCheck(option);
1287         return;
1288 }
1289
1290 //---------------------------------------------------------------------------
1291 //
1292 // PROC SCLoadGame
1293 //
1294 //---------------------------------------------------------------------------
1295
1296 static void SCLoadGame(int option)
1297 {
1298         if(!SlotStatus[option])
1299         { // Don't try to load from an empty slot
1300                 return;
1301         }
1302         G_LoadGame(option);
1303         MN_DeactivateMenu();
1304         BorderNeedRefresh = true;
1305         if(quickload == -1)
1306         {
1307                 quickload = option+1;
1308                 P_ClearMessage(&players[consoleplayer]);
1309         }
1310 }
1311
1312 //---------------------------------------------------------------------------
1313 //
1314 // PROC SCSaveGame
1315 //
1316 //---------------------------------------------------------------------------
1317
1318 static void SCSaveGame(int option)
1319 {
1320         char *ptr;
1321         player_t *player = &players[consoleplayer];
1322
1323         if(gamestate != GS_LEVEL || demoplayback
1324                 || player->playerstate == PST_DEAD)
1325         {
1326                 FileMenuKeySteal = false;
1327                 return;
1328         }
1329
1330         if(!FileMenuKeySteal)
1331         {
1332                 FileMenuKeySteal = true;
1333                 strcpy(oldSlotText, SlotText[option]);
1334                 ptr = SlotText[option];
1335                 while(*ptr)
1336                 {
1337                         ptr++;
1338                 }
1339                 *ptr = '[';
1340                 *(ptr+1) = 0;
1341                 SlotStatus[option]++;
1342                 currentSlot = option;
1343                 slotptr = ptr-SlotText[option];
1344                 return;
1345         }
1346         else
1347         {
1348                 G_SaveGame(option, SlotText[option]);
1349                 FileMenuKeySteal = false;
1350                 MN_DeactivateMenu();
1351         }
1352         BorderNeedRefresh = true;
1353         if(quicksave == -1)
1354         {
1355                 quicksave = option+1;
1356                 P_ClearMessage(&players[consoleplayer]);
1357         }
1358 }
1359
1360 //==========================================================================
1361 //
1362 // SCClass
1363 //
1364 //==========================================================================
1365
1366 static void SCClass(int option)
1367 {
1368         if(netgame)
1369         {
1370                 P_SetMessage(&players[consoleplayer],
1371                         "YOU CAN'T START A NEW GAME FROM WITHIN A NETGAME!", true);
1372                 return;
1373         }
1374         MenuPClass = option;
1375         switch(MenuPClass)
1376         {
1377                 case PCLASS_FIGHTER:
1378                         SkillMenu.x = 120;
1379                         SkillItems[0].text = "SQUIRE";
1380                         SkillItems[1].text = "KNIGHT";
1381                         SkillItems[2].text = "WARRIOR";
1382                         SkillItems[3].text = "BERSERKER";
1383                         SkillItems[4].text = "TITAN";
1384                         break;
1385                 case PCLASS_CLERIC:
1386                         SkillMenu.x = 116;
1387                         SkillItems[0].text = "ALTAR BOY";
1388                         SkillItems[1].text = "ACOLYTE";
1389                         SkillItems[2].text = "PRIEST";
1390                         SkillItems[3].text = "CARDINAL";
1391                         SkillItems[4].text = "POPE";
1392                         break;
1393                 case PCLASS_MAGE:
1394                         SkillMenu.x = 112;
1395                         SkillItems[0].text = "APPRENTICE";
1396                         SkillItems[1].text = "ENCHANTER";
1397                         SkillItems[2].text = "SORCERER";
1398                         SkillItems[3].text = "WARLOCK";
1399                         SkillItems[4].text = "ARCHIMAGE";
1400                         break;
1401 #ifdef ASSASSIN
1402                 case PCLASS_ASS:
1403                         SkillMenu.x = 116;
1404                         SkillItems[0].text = "KNAVE";
1405                         SkillItems[1].text = "ROUGE";
1406                         SkillItems[2].text = "CUTTHROAT";
1407                         SkillItems[3].text = "EXECUTIONER";
1408                         SkillItems[4].text = "WIDOW MAKER";
1409                         break;
1410 #endif
1411         }
1412         SetMenu(MENU_SKILL);
1413 }
1414
1415 //---------------------------------------------------------------------------
1416 //
1417 // PROC SCSkill
1418 //
1419 //---------------------------------------------------------------------------
1420
1421 static void SCSkill(int option)
1422 {
1423         extern int SB_state;
1424
1425         PlayerClass[consoleplayer] = MenuPClass;
1426         G_DeferredNewGame(option);
1427         SB_SetClassData();
1428         SB_state = -1;
1429         MN_DeactivateMenu();
1430 }
1431
1432 //---------------------------------------------------------------------------
1433 //
1434 // PROC SCMouseSensi
1435 //
1436 //---------------------------------------------------------------------------
1437
1438 static void SCMouseSensi(int option)
1439 {
1440         if(option == RIGHT_DIR)
1441         {
1442                 if(mouseSensitivity < MENU_MAX_MOUSE_SENS)
1443                 {
1444                         mouseSensitivity++;
1445                 }
1446         }
1447         else if(mouseSensitivity)
1448         {
1449                 mouseSensitivity--;
1450         }
1451 }
1452
1453 //---------------------------------------------------------------------------
1454 //
1455 // PROC SCSfxVolume
1456 //
1457 //---------------------------------------------------------------------------
1458
1459 static void SCSfxVolume(int option)
1460 {
1461         if(option == RIGHT_DIR)
1462         {
1463                 if(snd_MaxVolume < 15)
1464                 {
1465                         snd_MaxVolume++;
1466                 }
1467         }
1468         else if(snd_MaxVolume)
1469         {
1470                 snd_MaxVolume--;
1471         }
1472         soundchanged = true; // we'll set it when we leave the menu
1473 }
1474
1475 //---------------------------------------------------------------------------
1476 //
1477 // PROC SCMusicVolume
1478 //
1479 //---------------------------------------------------------------------------
1480
1481 static void SCMusicVolume(int option)
1482 {
1483         if(option == RIGHT_DIR)
1484         {
1485                 if(snd_MusicVolume < 15)
1486                 {
1487                         snd_MusicVolume++;
1488                 }
1489         }
1490         else if(snd_MusicVolume)
1491         {
1492                 snd_MusicVolume--;
1493         }
1494         S_SetMusicVolume();
1495 }
1496
1497 //---------------------------------------------------------------------------
1498 //
1499 // PROC SCScreenSize
1500 //
1501 //---------------------------------------------------------------------------
1502
1503 static void SCScreenSize(int option)
1504 {
1505         if(option == RIGHT_DIR)
1506         {
1507                 if(screenblocks < 11)
1508                 {
1509                         screenblocks++;
1510                 }
1511         }
1512         else if(screenblocks > 3)
1513         {
1514                 screenblocks--;
1515         }
1516         R_SetViewSize(screenblocks, detailLevel);
1517 }
1518
1519 //---------------------------------------------------------------------------
1520 //
1521 // PROC SCInfo
1522 //
1523 //---------------------------------------------------------------------------
1524
1525 static void SCInfo(int option)
1526 {
1527         InfoType = 1;
1528         S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1529         if(!netgame && !demoplayback)
1530         {
1531                 paused = true;
1532         }
1533 }
1534
1535 //---------------------------------------------------------------------------
1536 //
1537 // PROC SCSetKey
1538 //
1539 //---------------------------------------------------------------------------
1540 static void SCSetKey(int option)
1541 {
1542         askforkey = true;
1543         keyaskedfor = option;
1544         if(!netgame && !demoplayback)
1545         {
1546                 paused = true;
1547         }
1548 }
1549
1550 //---------------------------------------------------------------------------
1551 //
1552 // PROC SCMouslook(int option)
1553 //
1554 //---------------------------------------------------------------------------
1555 static void SCMouselook(int option)
1556 {
1557         if(option == RIGHT_DIR)
1558         {
1559                 if(mouselook < 2) mouselook++;
1560                 
1561         }
1562         else if(mouselook) mouselook--;
1563 }
1564
1565 static void SCAlwaysRun(int option)
1566 {
1567         if(alwaysrun) alwaysrun=0;
1568         else alwaysrun=1;
1569 }
1570 static void SCCDAudio(int option)
1571 {
1572         if(cdaudio == true)
1573         {
1574                 cdaudio = false;
1575                 I_CDMusStop();
1576                 i_CDMusic = false;
1577         }
1578         else
1579         {
1580                 cdaudio = true;
1581                 ST_Message("Attempting to initialize CD Music: ");
1582                 if(!cdrom)
1583                 {
1584                         i_CDMusic = (I_CDMusInit() != -1);
1585                 }
1586                 else
1587                 { // The user is trying to use the cdrom for both game and music
1588                         i_CDMusic = false;
1589                 }
1590                 if(i_CDMusic)
1591                 {
1592                         ST_Message("initialized.\n");
1593                 }
1594                 else
1595                 {
1596                         ST_Message("failed.\n");
1597                 }
1598         }
1599 }
1600
1601 //---------------------------------------------------------------------------
1602 //
1603 // FUNC MN_Responder
1604 //
1605 //---------------------------------------------------------------------------
1606
1607 boolean MN_Responder(event_t *event)
1608 {
1609         int key;
1610         int i;
1611         MenuItem_t *item;
1612         extern boolean automapactive;
1613         static boolean shiftdown;
1614         extern void H2_StartTitle(void);
1615         extern void G_CheckDemoStatus(void);
1616         char *textBuffer;
1617
1618         if(askforkey && event->type == ev_keydown)
1619         {
1620                 ClearControls(event->data1);
1621                 *defaults[keyaskedfor+3+FirstKey].location = event->data1;
1622                 askforkey = false;
1623                 return(true);
1624         }
1625         if(askforkey && event->type == ev_mouse)
1626         {
1627                 if(event->data1&1)
1628                         mbone = defaults[keyaskedfor+3+FirstKey].location;
1629                 if(event->data1&2)
1630                         mbtwo = defaults[keyaskedfor+3+FirstKey].location;
1631                 if(event->data1&4)
1632                         mbthree = defaults[keyaskedfor+3+FirstKey].location;
1633                 else return(false);
1634                 return(true);
1635         }
1636         if(event->data1 == KEY_RSHIFT)
1637         {
1638                 shiftdown = (event->type == ev_keydown);
1639         }
1640         if(event->type != ev_keydown)
1641         {
1642                 return(false);
1643         }
1644         key = event->data1;
1645         if(InfoType)
1646         {
1647                 if(shareware)
1648                 {
1649                         InfoType = (InfoType+1)%5;
1650                 }
1651                 else
1652                 {
1653                         InfoType = (InfoType+1)%4;
1654                 }
1655                 if(key == KEY_ESCAPE)
1656                 {
1657                         InfoType = 0;
1658                 }
1659                 if(!InfoType)
1660                 {
1661                         if(!netgame && !demoplayback)
1662                         {
1663                                 paused = false;
1664                         }
1665                         MN_DeactivateMenu();
1666                         SB_state = -1; //refresh the statbar
1667                         BorderNeedRefresh = true;
1668                 }
1669                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1670                 return(true); //make the info screen eat the keypress
1671         }
1672
1673         if(ravpic && key == KEY_F1)
1674         {
1675                 G_ScreenShot();
1676                 return(true);
1677         }
1678
1679         if(askforquit)
1680         {
1681                 switch(key)
1682                 {
1683                         case 'y':
1684                                 if(askforquit)
1685                                 {
1686                                         switch(typeofask)
1687                                         {
1688                                                 case 1:
1689                                                         G_CheckDemoStatus(); 
1690                                                         I_Quit();
1691                                                         break;
1692                                                 case 2:
1693                                                         P_ClearMessage(&players[consoleplayer]);
1694                                                         typeofask = 0;
1695                                                         askforquit = false;
1696                                                         paused = false;
1697                                                         I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
1698                                                         H2_StartTitle(); // go to intro/demo mode.
1699                                                         break;
1700                                                 case 3:
1701                                                         P_SetMessage(&players[consoleplayer], 
1702                                                                 "QUICKSAVING....", false);
1703                                                         FileMenuKeySteal = true;
1704                                                         SCSaveGame(quicksave-1);
1705                                                         askforquit = false;
1706                                                         typeofask = 0;
1707                                                         BorderNeedRefresh = true;
1708                                                         return true;
1709                                                 case 4:
1710                                                         P_SetMessage(&players[consoleplayer], 
1711                                                                 "QUICKLOADING....", false);
1712                                                         SCLoadGame(quickload-1);
1713                                                         askforquit = false;
1714                                                         typeofask = 0;
1715                                                         BorderNeedRefresh = true;
1716                                                         return true;
1717                                                 case 5:
1718                                                         askforquit = false;
1719                                                         typeofask = 0;  
1720                                                         BorderNeedRefresh = true;
1721                                                         mn_SuicideConsole = true;
1722                                                         return true;
1723                                                         break;
1724                                                 default:
1725                                                         return true; // eat the 'y' keypress
1726                                         }
1727                                 }
1728                                 return false;
1729                         case 'n':
1730                         case KEY_ESCAPE:
1731                                 if(askforquit)
1732                                 {
1733                                         players[consoleplayer].messageTics = 0;
1734                                         askforquit = false;
1735                                         typeofask = 0;
1736                                         paused = false;
1737                                         UpdateState |= I_FULLSCRN;
1738                                         BorderNeedRefresh = true;
1739                                         return true;
1740                                 }
1741                                 return false;
1742                 }
1743                 return false; // don't let the keys filter thru
1744         }
1745         if(MenuActive == false && !chatmodeon)
1746         {
1747                 switch(key)
1748                 {
1749                         case KEY_MINUS:
1750                                 if(automapactive)
1751                                 { // Don't screen size in automap
1752                                         return(false);
1753                                 }
1754                                 SCScreenSize(LEFT_DIR);
1755                                 S_StartSound(NULL, SFX_PICKUP_KEY);
1756                                 BorderNeedRefresh = true;
1757                                 UpdateState |= I_FULLSCRN;
1758                                 return(true);
1759                         case KEY_EQUALS:
1760                                 if(automapactive)
1761                                 { // Don't screen size in automap
1762                                         return(false);
1763                                 }
1764                                 SCScreenSize(RIGHT_DIR);
1765                                 S_StartSound(NULL, SFX_PICKUP_KEY);
1766                                 BorderNeedRefresh = true;
1767                                 UpdateState |= I_FULLSCRN;
1768                                 return(true);
1769 #ifdef __NeXT__
1770                         case 'q':
1771                                 MenuActive = false;
1772                                 askforquit = true;
1773                                 typeofask = 5; // suicide
1774                                 return true;
1775 #endif
1776 #ifndef __NeXT__
1777                         case KEY_F1: // help screen
1778                                 SCInfo(0); // start up info screens
1779                                 MenuActive = true;
1780                                 return(true);
1781                         case KEY_F2: // save game
1782                                 if(gamestate == GS_LEVEL && !demoplayback)
1783                                 {
1784                                         MenuActive = true;
1785                                         FileMenuKeySteal = false;
1786                                         MenuTime = 0;
1787                                         CurrentMenu = &SaveMenu;
1788                                         CurrentItPos = CurrentMenu->oldItPos;
1789                                         if(!netgame && !demoplayback)
1790                                         {
1791                                                 paused = true;
1792                                         }
1793                                         S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1794                                         slottextloaded = false; //reload the slot text, when needed
1795                                 }
1796                                 return true;
1797                         case KEY_F3: // load game
1798                                 if(SCNetCheck(2))
1799                                 {
1800                                         MenuActive = true;
1801                                         FileMenuKeySteal = false;
1802                                         MenuTime = 0;
1803                                         CurrentMenu = &LoadMenu;
1804                                         CurrentItPos = CurrentMenu->oldItPos;
1805                                         if(!netgame && !demoplayback)
1806                                         {
1807                                                 paused = true;
1808                                         }
1809                                         S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1810                                         slottextloaded = false; //reload the slot text, when needed
1811                                 }
1812                                 return true;
1813                         case KEY_F4: // volume
1814                                 MenuActive = true;
1815                                 FileMenuKeySteal = false;
1816                                 MenuTime = 0;
1817                                 CurrentMenu = &Options2Menu;
1818                                 CurrentItPos = CurrentMenu->oldItPos;
1819                                 if(!netgame && !demoplayback)
1820                                 {
1821                                         paused = true;
1822                                 }
1823                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1824                                 slottextloaded = false; //reload the slot text, when needed
1825                                 return true;
1826                         case KEY_F5:
1827                                 MenuActive = false;
1828                                 askforquit = true;
1829                                 typeofask = 5; // suicide
1830                                 return true;
1831                         case KEY_F6: // quicksave
1832                                 if(gamestate == GS_LEVEL && !demoplayback)
1833                                 {
1834                                         if(!quicksave || quicksave == -1)
1835                                         {
1836                                                 MenuActive = true;
1837                                                 FileMenuKeySteal = false;
1838                                                 MenuTime = 0;
1839                                                 CurrentMenu = &SaveMenu;
1840                                                 CurrentItPos = CurrentMenu->oldItPos;
1841                                                 if(!netgame && !demoplayback)
1842                                                 {
1843                                                         paused = true;
1844                                                 }
1845                                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1846                                                 slottextloaded = false; //reload the slot text
1847                                                 quicksave = -1;
1848                                                 P_SetMessage(&players[consoleplayer],
1849                                                         "CHOOSE A QUICKSAVE SLOT", true);
1850                                         }
1851                                         else
1852                                         {
1853                                                 askforquit = true;
1854                                                 typeofask = 3;
1855                                                 if(!netgame && !demoplayback)
1856                                                 {
1857                                                         paused = true;
1858                                                 }
1859                                                 S_StartSound(NULL, SFX_CHAT);
1860                                         }
1861                                 }
1862                                 return true;
1863                         case KEY_F7: // endgame
1864                                 if(SCNetCheck(3))
1865                                 {
1866                                         if(gamestate == GS_LEVEL && !demoplayback)
1867                                         {
1868                                                 S_StartSound(NULL, SFX_CHAT);
1869                                                 SCEndGame(0);
1870                                         }
1871                                 }
1872                                 return true;
1873                         case KEY_F8: // toggle messages
1874                                 SCMessages(0);
1875                                 return true;
1876                         case KEY_F9: // quickload
1877                                 if(SCNetCheck(2))
1878                                 {
1879                                         if(!quickload || quickload == -1)
1880                                         {
1881                                                 MenuActive = true;
1882                                                 FileMenuKeySteal = false;
1883                                                 MenuTime = 0;
1884                                                 CurrentMenu = &LoadMenu;
1885                                                 CurrentItPos = CurrentMenu->oldItPos;
1886                                                 if(!netgame && !demoplayback)
1887                                                 {
1888                                                         paused = true;
1889                                                 }
1890                                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1891                                                 slottextloaded = false; // reload the slot text
1892                                                 quickload = -1;
1893                                                 P_SetMessage(&players[consoleplayer],
1894                                                         "CHOOSE A QUICKLOAD SLOT", true);
1895                                         }
1896                                         else
1897                                         {
1898                                                 askforquit = true;
1899                                                 if(!netgame && !demoplayback)
1900                                                 {
1901                                                         paused = true;
1902                                                 }
1903                                                 typeofask = 4;
1904                                                 S_StartSound(NULL, SFX_CHAT);
1905                                         }
1906                                 }
1907                                 return true;
1908                         case KEY_F10: // quit
1909                                 if(gamestate == GS_LEVEL || gamestate == GS_FINALE)
1910                                 {
1911                                         SCQuitGame(0);
1912                                         S_StartSound(NULL, SFX_CHAT);
1913                                 }
1914                                 return true;
1915                         case KEY_F11: // F11 - gamma mode correction
1916                                 usegamma++;
1917                                 if(usegamma > 4)
1918                                 {
1919                                         usegamma = 0;
1920                                 }
1921                                 SB_PaletteFlash(true); // force change
1922                                 P_SetMessage(&players[consoleplayer], GammaText[usegamma],
1923                                         false);
1924                                 return true;
1925                         case KEY_F12: // F12 - reload current map (devmaps mode)
1926                                 if(netgame || DevMaps == false)
1927                                 {
1928                                         return false;
1929                                 }
1930                                 if(gamekeydown[key_speed])
1931                                 { // Monsters ON
1932                                         nomonsters = false;
1933                                 }
1934                                 if(gamekeydown[key_strafe])
1935                                 { // Monsters OFF
1936                                         nomonsters = true;
1937                                 }
1938                                 G_DeferedInitNew(gameskill, gameepisode, gamemap);
1939                                 P_SetMessage(&players[consoleplayer], TXT_CHEATWARP,
1940                                         false);
1941                                 return true;
1942 #endif
1943                 }
1944
1945         }
1946
1947         if(MenuActive == false)
1948         {
1949                 if(key == KEY_ESCAPE || gamestate == GS_DEMOSCREEN || demoplayback)
1950                 {
1951                         MN_ActivateMenu();
1952                         return(true);
1953                 }
1954                 return(false);
1955         }
1956         if(!FileMenuKeySteal)
1957         {
1958                 item = &CurrentMenu->items[CurrentItPos];
1959                 switch(key)
1960                 {
1961                         case KEY_DOWNARROW:
1962                                 do
1963                                 {
1964 if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos+1 > CurrentMenu->itemCount-1)
1965         {
1966                 if(FirstKey == 5) 
1967                 {
1968                         CurrentItPos = 0;  //End of Key menu
1969                         FirstKey = 0;
1970                 }
1971                 else
1972                 {
1973                         FirstKey++;
1974                 }       
1975         }
1976         else if(CurrentItPos+1 > CurrentMenu->itemCount-1)
1977         {
1978                 CurrentItPos = 0;
1979         }
1980         else
1981         {
1982                 CurrentItPos++;
1983         }
1984 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
1985 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
1986 return(true);
1987 break;
1988 case KEY_UPARROW:
1989         do
1990         {
1991         if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos==0)
1992         {
1993                 if(FirstKey == 0) 
1994                 {
1995                         CurrentItPos = 14;  //End of Key menu
1996                         FirstKey = 5;
1997                 }
1998                 else
1999                 {
2000                         FirstKey--;
2001                 }       
2002         }
2003         else if(CurrentItPos == 0)
2004                                         {
2005                                                 CurrentItPos = CurrentMenu->itemCount-1;
2006                                         }
2007                                         else
2008                                         {
2009                                                 CurrentItPos--;
2010                                         }
2011                                 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
2012                                 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
2013                                 return(true);
2014                                 break;
2015                         case KEY_LEFTARROW:
2016                                 if(item->type == ITT_LRFUNC && item->func != NULL)
2017                                 {
2018                                         item->func(LEFT_DIR);
2019                                         S_StartSound(NULL, SFX_PICKUP_KEY);
2020                                 }
2021                                 return(true);
2022                                 break;
2023                         case KEY_RIGHTARROW:
2024                                 if(item->type == ITT_LRFUNC && item->func != NULL)
2025                                 {
2026                                         item->func(RIGHT_DIR);
2027                                         S_StartSound(NULL, SFX_PICKUP_KEY);
2028                                 }
2029                                 return(true);
2030                                 break;
2031                         case KEY_ENTER:
2032                                 if(item->type == ITT_SETMENU)
2033                                 {
2034                                         if(item->func != NULL)  
2035                                         {
2036                                                 item->func(item->option);
2037                                         }
2038                                         SetMenu(item->menu);
2039                                 }
2040                                 else if(item->func != NULL)
2041                                 {
2042                                         CurrentMenu->oldItPos = CurrentItPos;
2043                                         if(item->type == ITT_LRFUNC)
2044                                         {
2045                                                 item->func(RIGHT_DIR);
2046                                         }
2047                                         else if(item->type == ITT_EFUNC)
2048                                         {
2049                                                 item->func(item->option);
2050                                         }
2051                                         else if(item->type == ITT_SETKEY)
2052                                         {
2053                                                 item->func(item->option);
2054                                         }
2055                                 }
2056                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
2057                                 return(true);
2058                                 break;
2059                         case KEY_ESCAPE:
2060                                 MN_DeactivateMenu();
2061                                 return(true);
2062                         case KEY_BACKSPACE:
2063                                 S_StartSound(NULL, SFX_PICKUP_KEY);
2064                                 if(CurrentMenu->prevMenu == MENU_NONE)
2065                                 {
2066                                         MN_DeactivateMenu();
2067                                 }
2068                                 else
2069                                 {
2070                                         SetMenu(CurrentMenu->prevMenu);
2071                                 }
2072                                 return(true);
2073                         default:
2074                                 for(i = 0; i < CurrentMenu->itemCount; i++)
2075                                 {
2076                                         if(CurrentMenu->items[i].text)
2077                                         {
2078                                                 if(toupper(key)
2079                                                         == toupper(CurrentMenu->items[i].text[0]))
2080                                                 {
2081                                                         CurrentItPos = i;
2082                                                         return(true);
2083                                                 }
2084                                         }
2085                                 }
2086                                 break;
2087                 }
2088                 return(false);
2089         }
2090         else
2091         { // Editing file names
2092                 textBuffer = &SlotText[currentSlot][slotptr];
2093                 if(key == KEY_BACKSPACE)
2094                 {
2095                         if(slotptr)
2096                         {
2097                                 *textBuffer-- = 0;
2098                                 *textBuffer = ASCII_CURSOR;
2099                                 slotptr--;
2100                         }
2101                         return(true);
2102                 }
2103                 if(key == KEY_ESCAPE)
2104                 {
2105                         memset(SlotText[currentSlot], 0, SLOTTEXTLEN+2);
2106                         strcpy(SlotText[currentSlot], oldSlotText);
2107                         SlotStatus[currentSlot]--;
2108                         MN_DeactivateMenu();
2109                         return(true);
2110                 }
2111                 if(key == KEY_ENTER)
2112                 {
2113                         SlotText[currentSlot][slotptr] = 0; // clear the cursor
2114                         item = &CurrentMenu->items[CurrentItPos];
2115                         CurrentMenu->oldItPos = CurrentItPos;
2116                         if(item->type == ITT_EFUNC)
2117                         {
2118                                 item->func(item->option);
2119                                 if(item->menu != MENU_NONE)
2120                                 {
2121                                         SetMenu(item->menu);
2122                                 }
2123                         }
2124                         return(true);
2125                 }
2126                 if(slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE)
2127                 {
2128                         if((key >= 'a' && key <= 'z'))
2129                         {
2130                                 *textBuffer++ = key-32;
2131                                 *textBuffer = ASCII_CURSOR;
2132                                 slotptr++;
2133                                 return(true);
2134                         }
2135                         if(((key >= '0' && key <= '9') || key == ' '
2136                                 || key == ',' || key == '.' || key == '-')
2137                                 && !shiftdown)
2138                         {
2139                                 *textBuffer++ = key;
2140                                 *textBuffer = ASCII_CURSOR;
2141                                 slotptr++;
2142                                 return(true);
2143                         }
2144                         if(shiftdown && key == '1')
2145                         {
2146                                 *textBuffer++ = '!';
2147                                 *textBuffer = ASCII_CURSOR;
2148                                 slotptr++;
2149                                 return(true);
2150                         }
2151                 }
2152                 return(true);
2153         }
2154         return(false);
2155 }
2156
2157 //---------------------------------------------------------------------------
2158 //
2159 // PROC MN_ActivateMenu
2160 //
2161 //---------------------------------------------------------------------------
2162
2163 void MN_ActivateMenu(void)
2164 {
2165         if(MenuActive)
2166         {
2167                 return;
2168         }
2169         if(paused)
2170         {
2171                 S_ResumeSound();
2172         }
2173         MenuActive = true;
2174         FileMenuKeySteal = false;
2175         MenuTime = 0;
2176         CurrentMenu = &MainMenu;
2177         CurrentItPos = CurrentMenu->oldItPos;
2178         if(!netgame && !demoplayback)
2179         {
2180                 paused = true;
2181         }
2182         S_StartSound(NULL, SFX_PLATFORM_STOP);
2183         slottextloaded = false; //reload the slot text, when needed
2184 }
2185
2186 //---------------------------------------------------------------------------
2187 //
2188 // PROC MN_DeactivateMenu
2189 //
2190 //---------------------------------------------------------------------------
2191
2192 void MN_DeactivateMenu(void)
2193 {
2194         CurrentMenu->oldItPos = CurrentItPos;
2195         MenuActive = false;
2196         if(!netgame)
2197         {
2198                 paused = false;
2199         }
2200         S_StartSound(NULL, SFX_PLATFORM_STOP);
2201         P_ClearMessage(&players[consoleplayer]);
2202 }
2203
2204 //---------------------------------------------------------------------------
2205 //
2206 // PROC MN_DrawInfo
2207 //
2208 //---------------------------------------------------------------------------
2209
2210 void MN_DrawInfo(void)
2211 {
2212 #ifdef RENDER3D
2213     OGL_SetFilter( 0 );
2214     OGL_DrawRawScreen( W_GetNumForName("TITLE")+InfoType );
2215 #else
2216         I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
2217         memcpy(screen, (byte *)W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2218                 PU_CACHE), SCREENWIDTH*SCREENHEIGHT);
2219 //      V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2220 //              PU_CACHE));
2221 #endif
2222 }
2223
2224
2225 //---------------------------------------------------------------------------
2226 //
2227 // PROC SetMenu
2228 //
2229 //---------------------------------------------------------------------------
2230
2231 static void SetMenu(MenuType_t menu)
2232 {
2233         CurrentMenu->oldItPos = CurrentItPos;
2234         CurrentMenu = Menus[menu];
2235         CurrentItPos = CurrentMenu->oldItPos;
2236 }
2237
2238 //---------------------------------------------------------------------------
2239 //
2240 // PROC DrawSlider
2241 //
2242 //---------------------------------------------------------------------------
2243
2244 static void DrawSlider(Menu_t *menu, int item, int width, int slot)
2245 {
2246         int x;
2247         int y;
2248         int x2;
2249         int count;
2250
2251         x = menu->x+24;
2252         y = menu->y+2+(item*ITEM_HEIGHT);
2253
2254 #ifdef RENDER3D
2255     OGL_DrawPatch_CS(x-32, y, W_GetNumForName("M_SLDLT"));
2256     for(x2 = x, count = width; count--; x2 += 8)
2257     {
2258         OGL_DrawPatch_CS( x2, y, W_GetNumForName(count&1 ? "M_SLDMD1" :
2259                           "M_SLDMD2") );
2260     }
2261     OGL_DrawPatch_CS(x2, y, W_GetNumForName("M_SLDRT"));
2262     OGL_DrawPatch_CS(x+4+slot*8, y+7, W_GetNumForName("M_SLDKB"));
2263 #else
2264         V_DrawPatch(x-32, y, W_CacheLumpName("M_SLDLT", PU_CACHE));
2265         for(x2 = x, count = width; count--; x2 += 8)
2266         {
2267                 V_DrawPatch(x2, y, W_CacheLumpName(count&1 ? "M_SLDMD1"
2268                         : "M_SLDMD2", PU_CACHE));
2269         }
2270         V_DrawPatch(x2, y, W_CacheLumpName("M_SLDRT", PU_CACHE));
2271         V_DrawPatch(x+4+slot*8, y+7, W_CacheLumpName("M_SLDKB", PU_CACHE));
2272 #endif
2273 }
2274