1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20 #include "quakedef.h"
21 #include "winquake.h"
22
23 void (*vid_menudrawfn)(void);
24 void (*vid_menukeyfn)(int key);
25
26 enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_slist} m_state;
27
28 void M_Menu_Main_f (void);
29 void M_Menu_SinglePlayer_f (void);
30 void M_Menu_Load_f (void);
31 void M_Menu_Save_f (void);
32 void M_Menu_MultiPlayer_f (void);
33 void M_Menu_Setup_f (void);
34 void M_Menu_Net_f (void);
35 void M_Menu_Options_f (void);
36 void M_Menu_Keys_f (void);
37 void M_Menu_Video_f (void);
38 void M_Menu_Help_f (void);
39 void M_Menu_Quit_f (void);
40 void M_Menu_SerialConfig_f (void);
41 void M_Menu_ModemConfig_f (void);
42 void M_Menu_LanConfig_f (void);
43 void M_Menu_GameOptions_f (void);
44 void M_Menu_Search_f (void);
45 void M_Menu_ServerList_f (void);
46
47 void M_Main_Draw (void);
48 void M_SinglePlayer_Draw (void);
49 void M_Load_Draw (void);
50 void M_Save_Draw (void);
51 void M_MultiPlayer_Draw (void);
52 void M_Setup_Draw (void);
53 void M_Net_Draw (void);
54 void M_Options_Draw (void);
55 void M_Keys_Draw (void);
56 void M_Video_Draw (void);
57 void M_Help_Draw (void);
58 void M_Quit_Draw (void);
59 void M_SerialConfig_Draw (void);
60 void M_ModemConfig_Draw (void);
61 void M_LanConfig_Draw (void);
62 void M_GameOptions_Draw (void);
63 void M_Search_Draw (void);
64 void M_ServerList_Draw (void);
65
66 void M_Main_Key (int key);
67 void M_SinglePlayer_Key (int key);
68 void M_Load_Key (int key);
69 void M_Save_Key (int key);
70 void M_MultiPlayer_Key (int key);
71 void M_Setup_Key (int key);
72 void M_Net_Key (int key);
73 void M_Options_Key (int key);
74 void M_Keys_Key (int key);
75 void M_Video_Key (int key);
76 void M_Help_Key (int key);
77 void M_Quit_Key (int key);
78 void M_SerialConfig_Key (int key);
79 void M_ModemConfig_Key (int key);
80 void M_LanConfig_Key (int key);
81 void M_GameOptions_Key (int key);
82 void M_Search_Key (int key);
83 void M_ServerList_Key (int key);
84
85 qboolean m_entersound; // play after drawing a frame, so caching
86 // won't disrupt the sound
87 qboolean m_recursiveDraw;
88
89 int m_return_state;
90 qboolean m_return_onerror;
91 char m_return_reason [32];
92
93 #define StartingGame (m_multiplayer_cursor == 1)
94 #define JoiningGame (m_multiplayer_cursor == 0)
95 #define SerialConfig (m_net_cursor == 0)
96 #define DirectConfig (m_net_cursor == 1)
97 #define IPXConfig (m_net_cursor == 2)
98 #define TCPIPConfig (m_net_cursor == 3)
99
100 void M_ConfigureNetSubsystem(void);
101
102 //=============================================================================
103 /* Support Routines */
104
105 /*
106 ================
107 M_DrawCharacter
108
109 Draws one solid graphics character
110 ================
111 */
M_DrawCharacter(int cx,int line,int num)112 void M_DrawCharacter (int cx, int line, int num)
113 {
114 Draw_Character ( cx + ((vid.width - 320)>>1), line, num);
115 }
116
M_Print(int cx,int cy,char * str)117 void M_Print (int cx, int cy, char *str)
118 {
119 while (*str)
120 {
121 M_DrawCharacter (cx, cy, (*str)+128);
122 str++;
123 cx += 8;
124 }
125 }
126
M_PrintWhite(int cx,int cy,char * str)127 void M_PrintWhite (int cx, int cy, char *str)
128 {
129 while (*str)
130 {
131 M_DrawCharacter (cx, cy, *str);
132 str++;
133 cx += 8;
134 }
135 }
136
M_DrawTransPic(int x,int y,qpic_t * pic)137 void M_DrawTransPic (int x, int y, qpic_t *pic)
138 {
139 Draw_TransPic (x + ((vid.width - 320)>>1), y, pic);
140 }
141
M_DrawPic(int x,int y,qpic_t * pic)142 void M_DrawPic (int x, int y, qpic_t *pic)
143 {
144 Draw_Pic (x + ((vid.width - 320)>>1), y, pic);
145 }
146
147 byte identityTable[256];
148 byte translationTable[256];
149
M_BuildTranslationTable(int top,int bottom)150 void M_BuildTranslationTable(int top, int bottom)
151 {
152 int j;
153 byte *dest, *source;
154
155 for (j = 0; j < 256; j++)
156 identityTable[j] = j;
157 dest = translationTable;
158 source = identityTable;
159 memcpy (dest, source, 256);
160
161 if (top < 128) // the artists made some backwards ranges. sigh.
162 memcpy (dest + TOP_RANGE, source + top, 16);
163 else
164 for (j=0 ; j<16 ; j++)
165 dest[TOP_RANGE+j] = source[top+15-j];
166
167 if (bottom < 128)
168 memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
169 else
170 for (j=0 ; j<16 ; j++)
171 dest[BOTTOM_RANGE+j] = source[bottom+15-j];
172 }
173
174
M_DrawTransPicTranslate(int x,int y,qpic_t * pic)175 void M_DrawTransPicTranslate (int x, int y, qpic_t *pic)
176 {
177 Draw_TransPicTranslate (x + ((vid.width - 320)>>1), y, pic, translationTable);
178 }
179
180
M_DrawTextBox(int x,int y,int width,int lines)181 void M_DrawTextBox (int x, int y, int width, int lines)
182 {
183 qpic_t *p;
184 int cx, cy;
185 int n;
186
187 // draw left side
188 cx = x;
189 cy = y;
190 p = Draw_CachePic ("gfx/box_tl.lmp");
191 M_DrawTransPic (cx, cy, p);
192 p = Draw_CachePic ("gfx/box_ml.lmp");
193 for (n = 0; n < lines; n++)
194 {
195 cy += 8;
196 M_DrawTransPic (cx, cy, p);
197 }
198 p = Draw_CachePic ("gfx/box_bl.lmp");
199 M_DrawTransPic (cx, cy+8, p);
200
201 // draw middle
202 cx += 8;
203 while (width > 0)
204 {
205 cy = y;
206 p = Draw_CachePic ("gfx/box_tm.lmp");
207 M_DrawTransPic (cx, cy, p);
208 p = Draw_CachePic ("gfx/box_mm.lmp");
209 for (n = 0; n < lines; n++)
210 {
211 cy += 8;
212 if (n == 1)
213 p = Draw_CachePic ("gfx/box_mm2.lmp");
214 M_DrawTransPic (cx, cy, p);
215 }
216 p = Draw_CachePic ("gfx/box_bm.lmp");
217 M_DrawTransPic (cx, cy+8, p);
218 width -= 2;
219 cx += 16;
220 }
221
222 // draw right side
223 cy = y;
224 p = Draw_CachePic ("gfx/box_tr.lmp");
225 M_DrawTransPic (cx, cy, p);
226 p = Draw_CachePic ("gfx/box_mr.lmp");
227 for (n = 0; n < lines; n++)
228 {
229 cy += 8;
230 M_DrawTransPic (cx, cy, p);
231 }
232 p = Draw_CachePic ("gfx/box_br.lmp");
233 M_DrawTransPic (cx, cy+8, p);
234 }
235
236 //=============================================================================
237
238 int m_save_demonum;
239
240 /*
241 ================
242 M_ToggleMenu_f
243 ================
244 */
M_ToggleMenu_f(void)245 void M_ToggleMenu_f (void)
246 {
247 m_entersound = true;
248
249 if (key_dest == key_menu)
250 {
251 if (m_state != m_main)
252 {
253 M_Menu_Main_f ();
254 return;
255 }
256 key_dest = key_game;
257 m_state = m_none;
258 return;
259 }
260 if (key_dest == key_console)
261 {
262 Con_ToggleConsole_f ();
263 }
264 else
265 {
266 M_Menu_Main_f ();
267 }
268 }
269
270
271 //=============================================================================
272 /* MAIN MENU */
273
274 int m_main_cursor;
275 #define MAIN_ITEMS 5
276
277
M_Menu_Main_f(void)278 void M_Menu_Main_f (void)
279 {
280 if (key_dest != key_menu)
281 {
282 m_save_demonum = cls.demonum;
283 cls.demonum = -1;
284 }
285 key_dest = key_menu;
286 m_state = m_main;
287 m_entersound = true;
288 }
289
290
M_Main_Draw(void)291 void M_Main_Draw (void)
292 {
293 int f;
294 qpic_t *p;
295
296 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
297 p = Draw_CachePic ("gfx/ttl_main.lmp");
298 M_DrawPic ( (320-p->width)/2, 4, p);
299 M_DrawTransPic (72, 32, Draw_CachePic ("gfx/mainmenu.lmp") );
300
301 f = (int)(realtime * 10)%6;
302
303 M_DrawTransPic (54, 32 + m_main_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
304 }
305
306
M_Main_Key(int key)307 void M_Main_Key (int key)
308 {
309 switch (key)
310 {
311 case K_ESCAPE:
312 key_dest = key_game;
313 m_state = m_none;
314 cls.demonum = m_save_demonum;
315 if (cls.demonum != -1 && !cls.demoplayback && cls.state == ca_disconnected)
316 CL_NextDemo ();
317 break;
318
319 case K_DOWNARROW:
320 S_LocalSound ("misc/menu1.wav");
321 if (++m_main_cursor >= MAIN_ITEMS)
322 m_main_cursor = 0;
323 break;
324
325 case K_UPARROW:
326 S_LocalSound ("misc/menu1.wav");
327 if (--m_main_cursor < 0)
328 m_main_cursor = MAIN_ITEMS - 1;
329 break;
330
331 case K_ENTER:
332 m_entersound = true;
333
334 switch (m_main_cursor)
335 {
336 case 0:
337 M_Menu_SinglePlayer_f ();
338 break;
339
340 case 1:
341 M_Menu_MultiPlayer_f ();
342 break;
343
344 case 2:
345 M_Menu_Options_f ();
346 break;
347
348 case 3:
349 M_Menu_Help_f ();
350 break;
351
352 case 4:
353 M_Menu_Quit_f ();
354 break;
355 }
356 }
357 }
358
359
360 //=============================================================================
361 /* OPTIONS MENU */
362
363 #define OPTIONS_ITEMS 16
364
365 #define SLIDER_RANGE 10
366
367 int options_cursor;
368
M_Menu_Options_f(void)369 void M_Menu_Options_f (void)
370 {
371 key_dest = key_menu;
372 m_state = m_options;
373 m_entersound = true;
374 }
375
376
M_AdjustSliders(int dir)377 void M_AdjustSliders (int dir)
378 {
379 S_LocalSound ("misc/menu3.wav");
380
381 switch (options_cursor)
382 {
383 case 3: // screen size
384 scr_viewsize.value += dir * 10;
385 if (scr_viewsize.value < 30)
386 scr_viewsize.value = 30;
387 if (scr_viewsize.value > 120)
388 scr_viewsize.value = 120;
389 Cvar_SetValue ("viewsize", scr_viewsize.value);
390 break;
391 case 4: // gamma
392 v_gamma.value -= dir * 0.05;
393 if (v_gamma.value < 0.5)
394 v_gamma.value = 0.5;
395 if (v_gamma.value > 1)
396 v_gamma.value = 1;
397 Cvar_SetValue ("gamma", v_gamma.value);
398 break;
399 case 5: // mouse speed
400 sensitivity.value += dir * 0.5;
401 if (sensitivity.value < 1)
402 sensitivity.value = 1;
403 if (sensitivity.value > 11)
404 sensitivity.value = 11;
405 Cvar_SetValue ("sensitivity", sensitivity.value);
406 break;
407 case 6: // music volume
408 #ifdef _WIN32
409 bgmvolume.value += dir * 1.0;
410 #else
411 bgmvolume.value += dir * 0.1;
412 #endif
413 if (bgmvolume.value < 0)
414 bgmvolume.value = 0;
415 if (bgmvolume.value > 1)
416 bgmvolume.value = 1;
417 Cvar_SetValue ("bgmvolume", bgmvolume.value);
418 break;
419 case 7: // sfx volume
420 volume.value += dir * 0.1;
421 if (volume.value < 0)
422 volume.value = 0;
423 if (volume.value > 1)
424 volume.value = 1;
425 Cvar_SetValue ("volume", volume.value);
426 break;
427
428 case 8: // allways run
429 if (cl_forwardspeed.value > 200)
430 {
431 Cvar_SetValue ("cl_forwardspeed", 200);
432 Cvar_SetValue ("cl_backspeed", 200);
433 }
434 else
435 {
436 Cvar_SetValue ("cl_forwardspeed", 400);
437 Cvar_SetValue ("cl_backspeed", 400);
438 }
439 break;
440
441 case 9: // invert mouse
442 Cvar_SetValue ("m_pitch", -m_pitch.value);
443 break;
444
445 case 10: // lookspring
446 Cvar_SetValue ("lookspring", !lookspring.value);
447 break;
448
449 case 11: // lookstrafe
450 Cvar_SetValue ("lookstrafe", !lookstrafe.value);
451 break;
452
453 case 12:
454 Cvar_SetValue ("cl_sbar", !cl_sbar.value);
455 break;
456
457 case 13:
458 Cvar_SetValue ("cl_hudswap", !cl_hudswap.value);
459
460 case 15: // _windowed_mouse
461 Cvar_SetValue ("_windowed_mouse", !_windowed_mouse.value);
462 break;
463 }
464 }
465
466
M_DrawSlider(int x,int y,float range)467 void M_DrawSlider (int x, int y, float range)
468 {
469 int i;
470
471 if (range < 0)
472 range = 0;
473 if (range > 1)
474 range = 1;
475 M_DrawCharacter (x-8, y, 128);
476 for (i=0 ; i<SLIDER_RANGE ; i++)
477 M_DrawCharacter (x + i*8, y, 129);
478 M_DrawCharacter (x+i*8, y, 130);
479 M_DrawCharacter (x + (SLIDER_RANGE-1)*8 * range, y, 131);
480 }
481
M_DrawCheckbox(int x,int y,int on)482 void M_DrawCheckbox (int x, int y, int on)
483 {
484 #if 0
485 if (on)
486 M_DrawCharacter (x, y, 131);
487 else
488 M_DrawCharacter (x, y, 129);
489 #endif
490 if (on)
491 M_Print (x, y, "on");
492 else
493 M_Print (x, y, "off");
494 }
495
M_Options_Draw(void)496 void M_Options_Draw (void)
497 {
498 float r;
499 qpic_t *p;
500
501 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
502 p = Draw_CachePic ("gfx/p_option.lmp");
503 M_DrawPic ( (320-p->width)/2, 4, p);
504
505 M_Print (16, 32, " Customize controls");
506 M_Print (16, 40, " Go to console");
507 M_Print (16, 48, " Reset to defaults");
508
509 M_Print (16, 56, " Screen size");
510 r = (scr_viewsize.value - 30) / (120 - 30);
511 M_DrawSlider (220, 56, r);
512
513 M_Print (16, 64, " Brightness");
514 r = (1.0 - v_gamma.value) / 0.5;
515 M_DrawSlider (220, 64, r);
516
517 M_Print (16, 72, " Mouse Speed");
518 r = (sensitivity.value - 1)/10;
519 M_DrawSlider (220, 72, r);
520
521 M_Print (16, 80, " CD Music Volume");
522 r = bgmvolume.value;
523 M_DrawSlider (220, 80, r);
524
525 M_Print (16, 88, " Sound Volume");
526 r = volume.value;
527 M_DrawSlider (220, 88, r);
528
529 M_Print (16, 96, " Always Run");
530 M_DrawCheckbox (220, 96, cl_forwardspeed.value > 200);
531
532 M_Print (16, 104, " Invert Mouse");
533 M_DrawCheckbox (220, 104, m_pitch.value < 0);
534
535 M_Print (16, 112, " Lookspring");
536 M_DrawCheckbox (220, 112, lookspring.value);
537
538 M_Print (16, 120, " Lookstrafe");
539 M_DrawCheckbox (220, 120, lookstrafe.value);
540
541 M_Print (16, 128, " Use old status bar");
542 M_DrawCheckbox (220, 128, cl_sbar.value);
543
544 M_Print (16, 136, " HUD on left side");
545 M_DrawCheckbox (220, 136, cl_hudswap.value);
546
547 if (vid_menudrawfn)
548 M_Print (16, 144, " Video Options");
549
550 #ifdef _WIN32
551 if (modestate == MS_WINDOWED)
552 {
553 #endif
554 M_Print (16, 152, " Use Mouse");
555 M_DrawCheckbox (220, 152, _windowed_mouse.value);
556 #ifdef _WIN32
557 }
558 #endif
559
560 // cursor
561 M_DrawCharacter (200, 32 + options_cursor*8, 12+((int)(realtime*4)&1));
562 }
563
564
M_Options_Key(int k)565 void M_Options_Key (int k)
566 {
567 switch (k)
568 {
569 case K_ESCAPE:
570 M_Menu_Main_f ();
571 break;
572
573 case K_ENTER:
574 m_entersound = true;
575 switch (options_cursor)
576 {
577 case 0:
578 M_Menu_Keys_f ();
579 break;
580 case 1:
581 m_state = m_none;
582 Con_ToggleConsole_f ();
583 break;
584 case 2:
585 Cbuf_AddText ("exec default.cfg\n");
586 break;
587 case 14:
588 M_Menu_Video_f ();
589 break;
590 default:
591 M_AdjustSliders (1);
592 break;
593 }
594 return;
595
596 case K_UPARROW:
597 S_LocalSound ("misc/menu1.wav");
598 options_cursor--;
599 if (options_cursor < 0)
600 options_cursor = OPTIONS_ITEMS-1;
601 break;
602
603 case K_DOWNARROW:
604 S_LocalSound ("misc/menu1.wav");
605 options_cursor++;
606 if (options_cursor >= OPTIONS_ITEMS)
607 options_cursor = 0;
608 break;
609
610 case K_LEFTARROW:
611 M_AdjustSliders (-1);
612 break;
613
614 case K_RIGHTARROW:
615 M_AdjustSliders (1);
616 break;
617 }
618
619 if (options_cursor == 14 && vid_menudrawfn == NULL)
620 {
621 if (k == K_UPARROW)
622 options_cursor = 13;
623 else
624 options_cursor = 0;
625 }
626
627 if ((options_cursor == 15)
628 #ifdef _WIN32
629 && (modestate != MS_WINDOWED)
630 #endif
631 )
632 {
633 if (k == K_UPARROW)
634 options_cursor = 14;
635 else
636 options_cursor = 0;
637 }
638 }
639
640
641 //=============================================================================
642 /* KEYS MENU */
643
644 char *bindnames[][2] =
645 {
646 {"+attack", "attack"},
647 {"impulse 10", "change weapon"},
648 {"+jump", "jump / swim up"},
649 {"+forward", "walk forward"},
650 {"+back", "backpedal"},
651 {"+left", "turn left"},
652 {"+right", "turn right"},
653 {"+speed", "run"},
654 {"+moveleft", "step left"},
655 {"+moveright", "step right"},
656 {"+strafe", "sidestep"},
657 {"+lookup", "look up"},
658 {"+lookdown", "look down"},
659 {"centerview", "center view"},
660 {"+mlook", "mouse look"},
661 {"+klook", "keyboard look"},
662 {"+moveup", "swim up"},
663 {"+movedown", "swim down"}
664 };
665
666 #define NUMCOMMANDS (sizeof(bindnames)/sizeof(bindnames[0]))
667
668 int keys_cursor;
669 int bind_grab;
670
M_Menu_Keys_f(void)671 void M_Menu_Keys_f (void)
672 {
673 key_dest = key_menu;
674 m_state = m_keys;
675 m_entersound = true;
676 }
677
678
M_FindKeysForCommand(char * command,int * twokeys)679 void M_FindKeysForCommand (char *command, int *twokeys)
680 {
681 int count;
682 int j;
683 int l;
684 char *b;
685
686 twokeys[0] = twokeys[1] = -1;
687 l = strlen(command);
688 count = 0;
689
690 for (j=0 ; j<256 ; j++)
691 {
692 b = keybindings[j];
693 if (!b)
694 continue;
695 if (!strncmp (b, command, l) )
696 {
697 twokeys[count] = j;
698 count++;
699 if (count == 2)
700 break;
701 }
702 }
703 }
704
M_UnbindCommand(char * command)705 void M_UnbindCommand (char *command)
706 {
707 int j;
708 int l;
709 char *b;
710
711 l = strlen(command);
712
713 for (j=0 ; j<256 ; j++)
714 {
715 b = keybindings[j];
716 if (!b)
717 continue;
718 if (!strncmp (b, command, l) )
719 Key_SetBinding (j, "");
720 }
721 }
722
723
M_Keys_Draw(void)724 void M_Keys_Draw (void)
725 {
726 int i, l;
727 int keys[2];
728 char *name;
729 int x, y;
730 qpic_t *p;
731
732 p = Draw_CachePic ("gfx/ttl_cstm.lmp");
733 M_DrawPic ( (320-p->width)/2, 4, p);
734
735 if (bind_grab)
736 M_Print (12, 32, "Press a key or button for this action");
737 else
738 M_Print (18, 32, "Enter to change, backspace to clear");
739
740 // search for known bindings
741 for (i=0 ; i< (int) NUMCOMMANDS ; i++)
742 {
743 y = 48 + 8*i;
744
745 M_Print (16, y, bindnames[i][1]);
746
747 l = strlen (bindnames[i][0]);
748
749 M_FindKeysForCommand (bindnames[i][0], keys);
750
751 if (keys[0] == -1)
752 {
753 M_Print (140, y, "???");
754 }
755 else
756 {
757 name = Key_KeynumToString (keys[0]);
758 M_Print (140, y, name);
759 x = strlen(name) * 8;
760 if (keys[1] != -1)
761 {
762 M_Print (140 + x + 8, y, "or");
763 M_Print (140 + x + 32, y, Key_KeynumToString (keys[1]));
764 }
765 }
766 }
767
768 if (bind_grab)
769 M_DrawCharacter (130, 48 + keys_cursor*8, '=');
770 else
771 M_DrawCharacter (130, 48 + keys_cursor*8, 12+((int)(realtime*4)&1));
772 }
773
774
M_Keys_Key(int k)775 void M_Keys_Key (int k)
776 {
777 char cmd[80];
778 int keys[2];
779
780 if (bind_grab)
781 { // defining a key
782 S_LocalSound ("misc/menu1.wav");
783 if (k == K_ESCAPE)
784 {
785 bind_grab = false;
786 }
787 else if (k != '`')
788 {
789 sprintf (cmd, "bind %s \"%s\"\n", Key_KeynumToString (k), bindnames[keys_cursor][0]);
790 Cbuf_InsertText (cmd);
791 }
792
793 bind_grab = false;
794 return;
795 }
796
797 switch (k)
798 {
799 case K_ESCAPE:
800 M_Menu_Options_f ();
801 break;
802
803 case K_LEFTARROW:
804 case K_UPARROW:
805 S_LocalSound ("misc/menu1.wav");
806 keys_cursor--;
807 if (keys_cursor < 0)
808 keys_cursor = NUMCOMMANDS-1;
809 break;
810
811 case K_DOWNARROW:
812 case K_RIGHTARROW:
813 S_LocalSound ("misc/menu1.wav");
814 keys_cursor++;
815 if (keys_cursor >= (int) NUMCOMMANDS)
816 keys_cursor = 0;
817 break;
818
819 case K_ENTER: // go into bind mode
820 M_FindKeysForCommand (bindnames[keys_cursor][0], keys);
821 S_LocalSound ("misc/menu2.wav");
822 if (keys[1] != -1)
823 M_UnbindCommand (bindnames[keys_cursor][0]);
824 bind_grab = true;
825 break;
826
827 case K_BACKSPACE: // delete bindings
828 case K_DEL: // delete bindings
829 S_LocalSound ("misc/menu2.wav");
830 M_UnbindCommand (bindnames[keys_cursor][0]);
831 break;
832 }
833 }
834
835 //=============================================================================
836 /* VIDEO MENU */
837
M_Menu_Video_f(void)838 void M_Menu_Video_f (void)
839 {
840 key_dest = key_menu;
841 m_state = m_video;
842 m_entersound = true;
843 }
844
845
M_Video_Draw(void)846 void M_Video_Draw (void)
847 {
848 (*vid_menudrawfn) ();
849 }
850
851
M_Video_Key(int key)852 void M_Video_Key (int key)
853 {
854 (*vid_menukeyfn) (key);
855 }
856
857 //=============================================================================
858 /* HELP MENU */
859
860 int help_page;
861 #define NUM_HELP_PAGES 6
862
863
M_Menu_Help_f(void)864 void M_Menu_Help_f (void)
865 {
866 key_dest = key_menu;
867 m_state = m_help;
868 m_entersound = true;
869 help_page = 0;
870 }
871
872
873
M_Help_Draw(void)874 void M_Help_Draw (void)
875 {
876 M_DrawPic (0, 0, Draw_CachePic ( va("gfx/help%i.lmp", help_page)) );
877 }
878
879
M_Help_Key(int key)880 void M_Help_Key (int key)
881 {
882 switch (key)
883 {
884 case K_ESCAPE:
885 M_Menu_Main_f ();
886 break;
887
888 case K_UPARROW:
889 case K_RIGHTARROW:
890 m_entersound = true;
891 if (++help_page >= NUM_HELP_PAGES)
892 help_page = 0;
893 break;
894
895 case K_DOWNARROW:
896 case K_LEFTARROW:
897 m_entersound = true;
898 if (--help_page < 0)
899 help_page = NUM_HELP_PAGES-1;
900 break;
901 }
902
903 }
904
905 //=============================================================================
906 /* QUIT MENU */
907
908 int msgNumber;
909 int m_quit_prevstate;
910 qboolean wasInMenus;
911
912 char *quitMessage [] =
913 {
914 /* .........1.........2.... */
915 " Are you gonna quit ",
916 " this game just like ",
917 " everything else? ",
918 " ",
919
920 " Milord, methinks that ",
921 " thou art a lowly ",
922 " quitter. Is this true? ",
923 " ",
924
925 " Do I need to bust your ",
926 " face open for trying ",
927 " to quit? ",
928 " ",
929
930 " Man, I oughta smack you",
931 " for trying to quit! ",
932 " Press Y to get ",
933 " smacked out. ",
934
935 " Press Y to quit like a ",
936 " big loser in life. ",
937 " Press N to stay proud ",
938 " and successful! ",
939
940 " If you press Y to ",
941 " quit, I will summon ",
942 " Satan all over your ",
943 " hard drive! ",
944
945 " Um, Asmodeus dislikes ",
946 " his children trying to ",
947 " quit. Press Y to return",
948 " to your Tinkertoys. ",
949
950 " If you quit now, I'll ",
951 " throw a blanket-party ",
952 " for you next time! ",
953 " "
954 };
955
M_Menu_Quit_f(void)956 void M_Menu_Quit_f (void)
957 {
958 if (m_state == m_quit)
959 return;
960 wasInMenus = (key_dest == key_menu);
961 key_dest = key_menu;
962 m_quit_prevstate = m_state;
963 m_state = m_quit;
964 m_entersound = true;
965 msgNumber = rand()&7;
966 }
967
968
M_Quit_Key(int key)969 void M_Quit_Key (int key)
970 {
971 switch (key)
972 {
973 case K_ESCAPE:
974 case 'n':
975 case 'N':
976 if (wasInMenus)
977 {
978 m_state = m_quit_prevstate;
979 m_entersound = true;
980 }
981 else
982 {
983 key_dest = key_game;
984 m_state = m_none;
985 }
986 break;
987
988 case 'Y':
989 case 'y':
990 key_dest = key_console;
991 CL_Disconnect ();
992 Sys_Quit ();
993 break;
994
995 default:
996 break;
997 }
998
999 }
1000
M_Menu_SinglePlayer_f(void)1001 void M_Menu_SinglePlayer_f (void) {
1002 m_state = m_singleplayer;
1003 }
1004
M_SinglePlayer_Draw(void)1005 void M_SinglePlayer_Draw (void) {
1006 qpic_t *p;
1007
1008 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
1009 // M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
1010 p = Draw_CachePic ("gfx/ttl_sgl.lmp");
1011 M_DrawPic ( (320-p->width)/2, 4, p);
1012 // M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") );
1013
1014 M_DrawTextBox (60, 10*8, 23, 4);
1015 M_PrintWhite (92, 12*8, "QuakeWorld is for");
1016 M_PrintWhite (88, 13*8, "Internet play only");
1017
1018 }
1019
M_SinglePlayer_Key(int key)1020 void M_SinglePlayer_Key (int key) {
1021 if (key == K_ESCAPE || key==K_ENTER)
1022 m_state = m_main;
1023 }
1024
M_Menu_MultiPlayer_f(void)1025 void M_Menu_MultiPlayer_f (void) {
1026 m_state = m_multiplayer;
1027 }
1028
M_MultiPlayer_Draw(void)1029 void M_MultiPlayer_Draw (void) {
1030 qpic_t *p;
1031
1032 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
1033 // M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
1034 p = Draw_CachePic ("gfx/p_multi.lmp");
1035 M_DrawPic ( (320-p->width)/2, 4, p);
1036 // M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") );
1037
1038 M_DrawTextBox (46, 8*8, 27, 9);
1039 M_PrintWhite (72, 10*8, "If you want to find QW ");
1040 M_PrintWhite (72, 11*8, "games, head on over to: ");
1041 M_Print (72, 12*8, " www.quakeworld.net ");
1042 M_PrintWhite (72, 13*8, " or ");
1043 M_Print (72, 14*8, " www.quakespy.com ");
1044 M_PrintWhite (72, 15*8, "For pointers on getting ");
1045 M_PrintWhite (72, 16*8, " started! ");
1046 }
1047
M_MultiPlayer_Key(int key)1048 void M_MultiPlayer_Key (int key) {
1049 if (key == K_ESCAPE || key==K_ENTER)
1050 m_state = m_main;
1051 }
1052
M_Quit_Draw(void)1053 void M_Quit_Draw (void)
1054 {
1055 #define VSTR(x) #x
1056 #define VSTR2(x) VSTR(x)
1057 char *cmsg[] = {
1058 // 0123456789012345678901234567890123456789
1059 "0 QuakeWorld",
1060 "1 version " VSTR2(VERSION) " by id Software",
1061 "0Programming",
1062 "1 John Carmack Michael Abrash",
1063 "1 John Cash Christian Antkow",
1064 "0Additional Programming",
1065 "1 Dave 'Zoid' Kirsch",
1066 "1 Jack 'morbid' Mathews",
1067 "0Id Software is not responsible for",
1068 "0providing technical support for",
1069 "0QUAKEWORLD(tm). (c)1996 Id Software,",
1070 "0Inc. All Rights Reserved.",
1071 "0QUAKEWORLD(tm) is a trademark of Id",
1072 "0Software, Inc.",
1073 "1NOTICE: THE COPYRIGHT AND TRADEMARK",
1074 "1NOTICES APPEARING IN YOUR COPY OF",
1075 "1QUAKE(r) ARE NOT MODIFIED BY THE USE",
1076 "1OF QUAKEWORLD(tm) AND REMAIN IN FULL",
1077 "1FORCE.",
1078 "0NIN(r) is a registered trademark",
1079 "0licensed to Nothing Interactive, Inc.",
1080 "0All rights reserved. Press y to exit",
1081 NULL };
1082 char **p;
1083 int y;
1084
1085 if (wasInMenus)
1086 {
1087 m_state = m_quit_prevstate;
1088 m_recursiveDraw = true;
1089 M_Draw ();
1090 m_state = m_quit;
1091 }
1092 #if 1
1093 M_DrawTextBox (0, 0, 38, 23);
1094 y = 12;
1095 for (p = cmsg; *p; p++, y += 8) {
1096 if (**p == '0')
1097 M_PrintWhite (16, y, *p + 1);
1098 else
1099 M_Print (16, y, *p + 1);
1100 }
1101 #else
1102 M_DrawTextBox (56, 76, 24, 4);
1103 M_Print (64, 84, quitMessage[msgNumber*4+0]);
1104 M_Print (64, 92, quitMessage[msgNumber*4+1]);
1105 M_Print (64, 100, quitMessage[msgNumber*4+2]);
1106 M_Print (64, 108, quitMessage[msgNumber*4+3]);
1107 #endif
1108 }
1109
1110
1111
1112 //=============================================================================
1113 /* Menu Subsystem */
1114
1115
M_Init(void)1116 void M_Init (void)
1117 {
1118 Cmd_AddCommand ("togglemenu", M_ToggleMenu_f);
1119
1120 Cmd_AddCommand ("menu_main", M_Menu_Main_f);
1121 Cmd_AddCommand ("menu_options", M_Menu_Options_f);
1122 Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
1123 Cmd_AddCommand ("menu_video", M_Menu_Video_f);
1124 Cmd_AddCommand ("help", M_Menu_Help_f);
1125 Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
1126 }
1127
1128
M_Draw(void)1129 void M_Draw (void)
1130 {
1131 if (m_state == m_none || key_dest != key_menu)
1132 return;
1133
1134 if (!m_recursiveDraw)
1135 {
1136 scr_copyeverything = 1;
1137
1138 if (scr_con_current)
1139 {
1140 Draw_ConsoleBackground (vid.height);
1141 VID_UnlockBuffer ();
1142 S_ExtraUpdate ();
1143 VID_LockBuffer ();
1144 }
1145 else
1146 Draw_FadeScreen ();
1147
1148 scr_fullupdate = 0;
1149 }
1150 else
1151 {
1152 m_recursiveDraw = false;
1153 }
1154
1155 switch (m_state)
1156 {
1157 case m_none:
1158 break;
1159
1160 case m_main:
1161 M_Main_Draw ();
1162 break;
1163
1164 case m_singleplayer:
1165 M_SinglePlayer_Draw ();
1166 break;
1167
1168 case m_load:
1169 // M_Load_Draw ();
1170 break;
1171
1172 case m_save:
1173 // M_Save_Draw ();
1174 break;
1175
1176 case m_multiplayer:
1177 M_MultiPlayer_Draw ();
1178 break;
1179
1180 case m_setup:
1181 // M_Setup_Draw ();
1182 break;
1183
1184 case m_net:
1185 // M_Net_Draw ();
1186 break;
1187
1188 case m_options:
1189 M_Options_Draw ();
1190 break;
1191
1192 case m_keys:
1193 M_Keys_Draw ();
1194 break;
1195
1196 case m_video:
1197 M_Video_Draw ();
1198 break;
1199
1200 case m_help:
1201 M_Help_Draw ();
1202 break;
1203
1204 case m_quit:
1205 M_Quit_Draw ();
1206 break;
1207
1208 case m_serialconfig:
1209 // M_SerialConfig_Draw ();
1210 break;
1211
1212 case m_modemconfig:
1213 // M_ModemConfig_Draw ();
1214 break;
1215
1216 case m_lanconfig:
1217 // M_LanConfig_Draw ();
1218 break;
1219
1220 case m_gameoptions:
1221 // M_GameOptions_Draw ();
1222 break;
1223
1224 case m_search:
1225 // M_Search_Draw ();
1226 break;
1227
1228 case m_slist:
1229 // M_ServerList_Draw ();
1230 break;
1231 }
1232
1233 if (m_entersound)
1234 {
1235 S_LocalSound ("misc/menu2.wav");
1236 m_entersound = false;
1237 }
1238
1239 VID_UnlockBuffer ();
1240 S_ExtraUpdate ();
1241 VID_LockBuffer ();
1242 }
1243
1244
M_Keydown(int key)1245 void M_Keydown (int key)
1246 {
1247 switch (m_state)
1248 {
1249 case m_none:
1250 return;
1251
1252 case m_main:
1253 M_Main_Key (key);
1254 return;
1255
1256 case m_singleplayer:
1257 M_SinglePlayer_Key (key);
1258 return;
1259
1260 case m_load:
1261 // M_Load_Key (key);
1262 return;
1263
1264 case m_save:
1265 // M_Save_Key (key);
1266 return;
1267
1268 case m_multiplayer:
1269 M_MultiPlayer_Key (key);
1270 return;
1271
1272 case m_setup:
1273 // M_Setup_Key (key);
1274 return;
1275
1276 case m_net:
1277 // M_Net_Key (key);
1278 return;
1279
1280 case m_options:
1281 M_Options_Key (key);
1282 return;
1283
1284 case m_keys:
1285 M_Keys_Key (key);
1286 return;
1287
1288 case m_video:
1289 M_Video_Key (key);
1290 return;
1291
1292 case m_help:
1293 M_Help_Key (key);
1294 return;
1295
1296 case m_quit:
1297 M_Quit_Key (key);
1298 return;
1299
1300 case m_serialconfig:
1301 // M_SerialConfig_Key (key);
1302 return;
1303
1304 case m_modemconfig:
1305 // M_ModemConfig_Key (key);
1306 return;
1307
1308 case m_lanconfig:
1309 // M_LanConfig_Key (key);
1310 return;
1311
1312 case m_gameoptions:
1313 // M_GameOptions_Key (key);
1314 return;
1315
1316 case m_search:
1317 // M_Search_Key (key);
1318 break;
1319
1320 case m_slist:
1321 // M_ServerList_Key (key);
1322 return;
1323 }
1324 }
1325
1326
1327