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
22 #ifdef _WIN32
23 #include "winquake.h"
24 #endif
25
26 void (*vid_menudrawfn)(void);
27 void (*vid_menukeyfn)(int key);
28
29 enum m_state_t {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;
30
31 void M_Menu_Main_f (void);
32 void M_Menu_SinglePlayer_f (void);
33 void M_Menu_Load_f (void);
34 void M_Menu_Save_f (void);
35 void M_Menu_MultiPlayer_f (void);
36 void M_Menu_Setup_f (void);
37 void M_Menu_Net_f (void);
38 void M_Menu_Options_f (void);
39 void M_Menu_Keys_f (void);
40 void M_Menu_Video_f (void);
41 void M_Menu_Help_f (void);
42 void M_Menu_Quit_f (void);
43 void M_Menu_SerialConfig_f (void);
44 void M_Menu_ModemConfig_f (void);
45 void M_Menu_LanConfig_f (void);
46 void M_Menu_GameOptions_f (void);
47 void M_Menu_Search_f (void);
48 void M_Menu_ServerList_f (void);
49
50 void M_Main_Draw (void);
51 void M_SinglePlayer_Draw (void);
52 void M_Load_Draw (void);
53 void M_Save_Draw (void);
54 void M_MultiPlayer_Draw (void);
55 void M_Setup_Draw (void);
56 void M_Net_Draw (void);
57 void M_Options_Draw (void);
58 void M_Keys_Draw (void);
59 void M_Video_Draw (void);
60 void M_Help_Draw (void);
61 void M_Quit_Draw (void);
62 void M_SerialConfig_Draw (void);
63 void M_ModemConfig_Draw (void);
64 void M_LanConfig_Draw (void);
65 void M_GameOptions_Draw (void);
66 void M_Search_Draw (void);
67 void M_ServerList_Draw (void);
68
69 void M_Main_Key (int key);
70 void M_SinglePlayer_Key (int key);
71 void M_Load_Key (int key);
72 void M_Save_Key (int key);
73 void M_MultiPlayer_Key (int key);
74 void M_Setup_Key (int key);
75 void M_Net_Key (int key);
76 void M_Options_Key (int key);
77 void M_Keys_Key (int key);
78 void M_Video_Key (int key);
79 void M_Help_Key (int key);
80 void M_Quit_Key (int key);
81 void M_SerialConfig_Key (int key);
82 void M_ModemConfig_Key (int key);
83 void M_LanConfig_Key (int key);
84 void M_GameOptions_Key (int key);
85 void M_Search_Key (int key);
86 void M_ServerList_Key (int key);
87
88 qboolean m_entersound; // play after drawing a frame, so caching
89 // won't disrupt the sound
90 qboolean m_recursiveDraw;
91
92 int m_return_state;
93 qboolean m_return_onerror;
94 char m_return_reason [32];
95
96 #define StartingGame (m_multiplayer_cursor == 1)
97 #define JoiningGame (m_multiplayer_cursor == 0)
98 #define SerialConfig (m_net_cursor == 0)
99 #define DirectConfig (m_net_cursor == 1)
100 #define IPXConfig (m_net_cursor == 2)
101 #define TCPIPConfig (m_net_cursor == 3)
102
103 void M_ConfigureNetSubsystem(void);
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,const char * str)117 void M_Print (int cx, int cy, const 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,const char * str)127 void M_PrintWhite (int cx, int cy, const 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)(host_time * 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_connected)
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 /* SINGLE PLAYER MENU */
361
362 int m_singleplayer_cursor;
363 #define SINGLEPLAYER_ITEMS 3
364
365
M_Menu_SinglePlayer_f(void)366 void M_Menu_SinglePlayer_f (void)
367 {
368 key_dest = key_menu;
369 m_state = m_singleplayer;
370 m_entersound = true;
371 }
372
373
M_SinglePlayer_Draw(void)374 void M_SinglePlayer_Draw (void)
375 {
376 int f;
377 qpic_t *p;
378
379 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
380 p = Draw_CachePic ("gfx/ttl_sgl.lmp");
381 M_DrawPic ( (320-p->width)/2, 4, p);
382 M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") );
383
384 f = (int)(host_time * 10)%6;
385
386 M_DrawTransPic (54, 32 + m_singleplayer_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
387 }
388
389
M_SinglePlayer_Key(int key)390 void M_SinglePlayer_Key (int key)
391 {
392 switch (key)
393 {
394 case K_ESCAPE:
395 M_Menu_Main_f ();
396 break;
397
398 case K_DOWNARROW:
399 S_LocalSound ("misc/menu1.wav");
400 if (++m_singleplayer_cursor >= SINGLEPLAYER_ITEMS)
401 m_singleplayer_cursor = 0;
402 break;
403
404 case K_UPARROW:
405 S_LocalSound ("misc/menu1.wav");
406 if (--m_singleplayer_cursor < 0)
407 m_singleplayer_cursor = SINGLEPLAYER_ITEMS - 1;
408 break;
409
410 case K_ENTER:
411 m_entersound = true;
412
413 switch (m_singleplayer_cursor)
414 {
415 case 0:
416 if (sv.active)
417 if (!SCR_ModalMessage("Are you sure you want to\nstart a new game?\n"))
418 break;
419 key_dest = key_game;
420 if (sv.active)
421 Cbuf_AddText ("disconnect\n");
422 Cbuf_AddText ("maxplayers 1\n");
423 Cbuf_AddText ("map start\n");
424 break;
425
426 case 1:
427 M_Menu_Load_f ();
428 break;
429
430 case 2:
431 M_Menu_Save_f ();
432 break;
433 }
434 }
435 }
436
437 //=============================================================================
438 /* LOAD/SAVE MENU */
439
440 int load_cursor; // 0 < load_cursor < MAX_SAVEGAMES
441
442 #define MAX_SAVEGAMES 12
443 char m_filenames[MAX_SAVEGAMES][SAVEGAME_COMMENT_LENGTH+1];
444 int loadable[MAX_SAVEGAMES];
445
M_ScanSaves(void)446 void M_ScanSaves (void)
447 {
448 int i, j;
449 char name[MAX_OSPATH];
450 FILE *f;
451 int version;
452
453 for (i=0 ; i<MAX_SAVEGAMES ; i++)
454 {
455 strcpy (m_filenames[i], "--- UNUSED SLOT ---");
456 loadable[i] = false;
457 sprintf (name, "%s/s%i.sav", com_gamedir, i);
458 f = fopen (name, "r");
459 if (!f)
460 continue;
461 fscanf (f, "%i\n", &version);
462 fscanf (f, "%79s\n", name);
463 strncpy (m_filenames[i], name, sizeof(m_filenames[i])-1);
464
465 // change _ back to space
466 for (j=0 ; j<SAVEGAME_COMMENT_LENGTH ; j++)
467 if (m_filenames[i][j] == '_')
468 m_filenames[i][j] = ' ';
469 loadable[i] = true;
470 fclose (f);
471 }
472 }
473
M_Menu_Load_f(void)474 void M_Menu_Load_f (void)
475 {
476 m_entersound = true;
477 m_state = m_load;
478 key_dest = key_menu;
479 M_ScanSaves ();
480 }
481
482
M_Menu_Save_f(void)483 void M_Menu_Save_f (void)
484 {
485 if (!sv.active)
486 return;
487 if (cl.intermission)
488 return;
489 if (svs.maxclients != 1)
490 return;
491 m_entersound = true;
492 m_state = m_save;
493 key_dest = key_menu;
494 M_ScanSaves ();
495 }
496
497
M_Load_Draw(void)498 void M_Load_Draw (void)
499 {
500 int i;
501 qpic_t *p;
502
503 p = Draw_CachePic ("gfx/p_load.lmp");
504 M_DrawPic ( (320-p->width)/2, 4, p);
505
506 for (i=0 ; i< MAX_SAVEGAMES; i++)
507 M_Print (16, 32 + 8*i, m_filenames[i]);
508
509 // line cursor
510 M_DrawCharacter (8, 32 + load_cursor*8, 12+((int)(realtime*4)&1));
511 }
512
513
M_Save_Draw(void)514 void M_Save_Draw (void)
515 {
516 int i;
517 qpic_t *p;
518
519 p = Draw_CachePic ("gfx/p_save.lmp");
520 M_DrawPic ( (320-p->width)/2, 4, p);
521
522 for (i=0 ; i<MAX_SAVEGAMES ; i++)
523 M_Print (16, 32 + 8*i, m_filenames[i]);
524
525 // line cursor
526 M_DrawCharacter (8, 32 + load_cursor*8, 12+((int)(realtime*4)&1));
527 }
528
529
M_Load_Key(int k)530 void M_Load_Key (int k)
531 {
532 switch (k)
533 {
534 case K_ESCAPE:
535 M_Menu_SinglePlayer_f ();
536 break;
537
538 case K_ENTER:
539 S_LocalSound ("misc/menu2.wav");
540 if (!loadable[load_cursor])
541 return;
542 m_state = m_none;
543 key_dest = key_game;
544
545 // Host_Loadgame_f can't bring up the loading plaque because too much
546 // stack space has been used, so do it now
547 SCR_BeginLoadingPlaque ();
548
549 // issue the load command
550 Cbuf_AddText (va ("load s%i\n", load_cursor) );
551 return;
552
553 case K_UPARROW:
554 case K_LEFTARROW:
555 S_LocalSound ("misc/menu1.wav");
556 load_cursor--;
557 if (load_cursor < 0)
558 load_cursor = MAX_SAVEGAMES-1;
559 break;
560
561 case K_DOWNARROW:
562 case K_RIGHTARROW:
563 S_LocalSound ("misc/menu1.wav");
564 load_cursor++;
565 if (load_cursor >= MAX_SAVEGAMES)
566 load_cursor = 0;
567 break;
568 }
569 }
570
571
M_Save_Key(int k)572 void M_Save_Key (int k)
573 {
574 switch (k)
575 {
576 case K_ESCAPE:
577 M_Menu_SinglePlayer_f ();
578 break;
579
580 case K_ENTER:
581 m_state = m_none;
582 key_dest = key_game;
583 Cbuf_AddText (va("save s%i\n", load_cursor));
584 return;
585
586 case K_UPARROW:
587 case K_LEFTARROW:
588 S_LocalSound ("misc/menu1.wav");
589 load_cursor--;
590 if (load_cursor < 0)
591 load_cursor = MAX_SAVEGAMES-1;
592 break;
593
594 case K_DOWNARROW:
595 case K_RIGHTARROW:
596 S_LocalSound ("misc/menu1.wav");
597 load_cursor++;
598 if (load_cursor >= MAX_SAVEGAMES)
599 load_cursor = 0;
600 break;
601 }
602 }
603
604 //=============================================================================
605 /* MULTIPLAYER MENU */
606
607 int m_multiplayer_cursor;
608 #define MULTIPLAYER_ITEMS 3
609
610
M_Menu_MultiPlayer_f(void)611 void M_Menu_MultiPlayer_f (void)
612 {
613 key_dest = key_menu;
614 m_state = m_multiplayer;
615 m_entersound = true;
616 }
617
618
M_MultiPlayer_Draw(void)619 void M_MultiPlayer_Draw (void)
620 {
621 int f;
622 qpic_t *p;
623
624 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
625 p = Draw_CachePic ("gfx/p_multi.lmp");
626 M_DrawPic ( (320-p->width)/2, 4, p);
627 M_DrawTransPic (72, 32, Draw_CachePic ("gfx/mp_menu.lmp") );
628
629 f = (int)(host_time * 10)%6;
630
631 M_DrawTransPic (54, 32 + m_multiplayer_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
632
633 if (serialAvailable || ipxAvailable || tcpipAvailable)
634 return;
635 M_PrintWhite ((320/2) - ((27*8)/2), 148, "No Communications Available");
636 }
637
638
M_MultiPlayer_Key(int key)639 void M_MultiPlayer_Key (int key)
640 {
641 switch (key)
642 {
643 case K_ESCAPE:
644 M_Menu_Main_f ();
645 break;
646
647 case K_DOWNARROW:
648 S_LocalSound ("misc/menu1.wav");
649 if (++m_multiplayer_cursor >= MULTIPLAYER_ITEMS)
650 m_multiplayer_cursor = 0;
651 break;
652
653 case K_UPARROW:
654 S_LocalSound ("misc/menu1.wav");
655 if (--m_multiplayer_cursor < 0)
656 m_multiplayer_cursor = MULTIPLAYER_ITEMS - 1;
657 break;
658
659 case K_ENTER:
660 m_entersound = true;
661 switch (m_multiplayer_cursor)
662 {
663 case 0:
664 if (serialAvailable || ipxAvailable || tcpipAvailable)
665 M_Menu_Net_f ();
666 break;
667
668 case 1:
669 if (serialAvailable || ipxAvailable || tcpipAvailable)
670 M_Menu_Net_f ();
671 break;
672
673 case 2:
674 M_Menu_Setup_f ();
675 break;
676 }
677 }
678 }
679
680 //=============================================================================
681 /* SETUP MENU */
682
683 int setup_cursor = 4;
684 int setup_cursor_table[] = {40, 56, 80, 104, 140};
685
686 char setup_hostname[16];
687 char setup_myname[16];
688 int setup_oldtop;
689 int setup_oldbottom;
690 int setup_top;
691 int setup_bottom;
692
693 #define NUM_SETUP_CMDS 5
694
M_Menu_Setup_f(void)695 void M_Menu_Setup_f (void)
696 {
697 key_dest = key_menu;
698 m_state = m_setup;
699 m_entersound = true;
700 Q_strcpy(setup_myname, cl_name.string);
701 Q_strcpy(setup_hostname, hostname.string);
702 setup_top = setup_oldtop = ((int)cl_color.value) >> 4;
703 setup_bottom = setup_oldbottom = ((int)cl_color.value) & 15;
704 }
705
706
M_Setup_Draw(void)707 void M_Setup_Draw (void)
708 {
709 qpic_t *p;
710
711 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
712 p = Draw_CachePic ("gfx/p_multi.lmp");
713 M_DrawPic ( (320-p->width)/2, 4, p);
714
715 M_Print (64, 40, "Hostname");
716 M_DrawTextBox (160, 32, 16, 1);
717 M_Print (168, 40, setup_hostname);
718
719 M_Print (64, 56, "Your name");
720 M_DrawTextBox (160, 48, 16, 1);
721 M_Print (168, 56, setup_myname);
722
723 M_Print (64, 80, "Shirt color");
724 M_Print (64, 104, "Pants color");
725
726 M_DrawTextBox (64, 140-8, 14, 1);
727 M_Print (72, 140, "Accept Changes");
728
729 p = Draw_CachePic ("gfx/bigbox.lmp");
730 M_DrawTransPic (160, 64, p);
731 p = Draw_CachePic ("gfx/menuplyr.lmp");
732 M_BuildTranslationTable(setup_top*16, setup_bottom*16);
733 M_DrawTransPicTranslate (172, 72, p);
734
735 M_DrawCharacter (56, setup_cursor_table [setup_cursor], 12+((int)(realtime*4)&1));
736
737 if (setup_cursor == 0)
738 M_DrawCharacter (168 + 8*strlen(setup_hostname), setup_cursor_table [setup_cursor], 10+((int)(realtime*4)&1));
739
740 if (setup_cursor == 1)
741 M_DrawCharacter (168 + 8*strlen(setup_myname), setup_cursor_table [setup_cursor], 10+((int)(realtime*4)&1));
742 }
743
744
M_Setup_Key(int k)745 void M_Setup_Key (int k)
746 {
747 int l;
748
749 switch (k)
750 {
751 case K_ESCAPE:
752 M_Menu_MultiPlayer_f ();
753 break;
754
755 case K_UPARROW:
756 S_LocalSound ("misc/menu1.wav");
757 setup_cursor--;
758 if (setup_cursor < 0)
759 setup_cursor = NUM_SETUP_CMDS-1;
760 break;
761
762 case K_DOWNARROW:
763 S_LocalSound ("misc/menu1.wav");
764 setup_cursor++;
765 if (setup_cursor >= NUM_SETUP_CMDS)
766 setup_cursor = 0;
767 break;
768
769 case K_LEFTARROW:
770 if (setup_cursor < 2)
771 return;
772 S_LocalSound ("misc/menu3.wav");
773 if (setup_cursor == 2)
774 setup_top = setup_top - 1;
775 if (setup_cursor == 3)
776 setup_bottom = setup_bottom - 1;
777 break;
778 case K_RIGHTARROW:
779 if (setup_cursor < 2)
780 return;
781 forward:
782 S_LocalSound ("misc/menu3.wav");
783 if (setup_cursor == 2)
784 setup_top = setup_top + 1;
785 if (setup_cursor == 3)
786 setup_bottom = setup_bottom + 1;
787 break;
788
789 case K_ENTER:
790 if (setup_cursor == 0 || setup_cursor == 1)
791 return;
792
793 if (setup_cursor == 2 || setup_cursor == 3)
794 goto forward;
795
796 // setup_cursor == 4 (OK)
797 if (Q_strcmp(cl_name.string, setup_myname) != 0)
798 Cbuf_AddText ( va ("name \"%s\"\n", setup_myname) );
799 if (Q_strcmp(hostname.string, setup_hostname) != 0)
800 Cvar_Set("hostname", setup_hostname);
801 if (setup_top != setup_oldtop || setup_bottom != setup_oldbottom)
802 Cbuf_AddText( va ("color %i %i\n", setup_top, setup_bottom) );
803 m_entersound = true;
804 M_Menu_MultiPlayer_f ();
805 break;
806
807 case K_BACKSPACE:
808 if (setup_cursor == 0)
809 {
810 if (strlen(setup_hostname))
811 setup_hostname[strlen(setup_hostname)-1] = 0;
812 }
813
814 if (setup_cursor == 1)
815 {
816 if (strlen(setup_myname))
817 setup_myname[strlen(setup_myname)-1] = 0;
818 }
819 break;
820
821 default:
822 if (k < 32 || k > 127)
823 break;
824 if (setup_cursor == 0)
825 {
826 l = strlen(setup_hostname);
827 if (l < 15)
828 {
829 setup_hostname[l+1] = 0;
830 setup_hostname[l] = k;
831 }
832 }
833 if (setup_cursor == 1)
834 {
835 l = strlen(setup_myname);
836 if (l < 15)
837 {
838 setup_myname[l+1] = 0;
839 setup_myname[l] = k;
840 }
841 }
842 }
843
844 if (setup_top > 13)
845 setup_top = 0;
846 if (setup_top < 0)
847 setup_top = 13;
848 if (setup_bottom > 13)
849 setup_bottom = 0;
850 if (setup_bottom < 0)
851 setup_bottom = 13;
852 }
853
854 //=============================================================================
855 /* NET MENU */
856
857 int m_net_cursor;
858 int m_net_items;
859 int m_net_saveHeight;
860
861 const char *net_helpMessage [] =
862 {
863 /* .........1.........2.... */
864 " ",
865 " Two computers connected",
866 " through two modems. ",
867 " ",
868
869 " ",
870 " Two computers connected",
871 " by a null-modem cable. ",
872 " ",
873
874 " Novell network LANs ",
875 " or Windows 95 DOS-box. ",
876 " ",
877 "(LAN=Local Area Network)",
878
879 " Commonly used to play ",
880 " over the Internet, but ",
881 " also used on a Local ",
882 " Area Network. "
883 };
884
M_Menu_Net_f(void)885 void M_Menu_Net_f (void)
886 {
887 key_dest = key_menu;
888 m_state = m_net;
889 m_entersound = true;
890 m_net_items = 4;
891
892 if (m_net_cursor >= m_net_items)
893 m_net_cursor = 0;
894 m_net_cursor--;
895 M_Net_Key (K_DOWNARROW);
896 }
897
898
M_Net_Draw(void)899 void M_Net_Draw (void)
900 {
901 int f;
902 qpic_t *p;
903
904 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
905 p = Draw_CachePic ("gfx/p_multi.lmp");
906 M_DrawPic ( (320-p->width)/2, 4, p);
907
908 f = 32;
909
910 if (serialAvailable)
911 {
912 p = Draw_CachePic ("gfx/netmen1.lmp");
913 }
914 else
915 {
916 #ifdef _WIN32
917 p = NULL;
918 #else
919 p = Draw_CachePic ("gfx/dim_modm.lmp");
920 #endif
921 }
922
923 if (p)
924 M_DrawTransPic (72, f, p);
925
926 f += 19;
927
928 if (serialAvailable)
929 {
930 p = Draw_CachePic ("gfx/netmen2.lmp");
931 }
932 else
933 {
934 #ifdef _WIN32
935 p = NULL;
936 #else
937 p = Draw_CachePic ("gfx/dim_drct.lmp");
938 #endif
939 }
940
941 if (p)
942 M_DrawTransPic (72, f, p);
943
944 f += 19;
945 if (ipxAvailable)
946 p = Draw_CachePic ("gfx/netmen3.lmp");
947 else
948 p = Draw_CachePic ("gfx/dim_ipx.lmp");
949 M_DrawTransPic (72, f, p);
950
951 f += 19;
952 if (tcpipAvailable)
953 p = Draw_CachePic ("gfx/netmen4.lmp");
954 else
955 p = Draw_CachePic ("gfx/dim_tcp.lmp");
956 M_DrawTransPic (72, f, p);
957
958 if (m_net_items == 5) // JDC, could just be removed
959 {
960 f += 19;
961 p = Draw_CachePic ("gfx/netmen5.lmp");
962 M_DrawTransPic (72, f, p);
963 }
964
965 f = (320-26*8)/2;
966 M_DrawTextBox (f, 134, 24, 4);
967 f += 8;
968 M_Print (f, 142, net_helpMessage[m_net_cursor*4+0]);
969 M_Print (f, 150, net_helpMessage[m_net_cursor*4+1]);
970 M_Print (f, 158, net_helpMessage[m_net_cursor*4+2]);
971 M_Print (f, 166, net_helpMessage[m_net_cursor*4+3]);
972
973 f = (int)(host_time * 10)%6;
974 M_DrawTransPic (54, 32 + m_net_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
975 }
976
977
M_Net_Key(int k)978 void M_Net_Key (int k)
979 {
980 again:
981 switch (k)
982 {
983 case K_ESCAPE:
984 M_Menu_MultiPlayer_f ();
985 break;
986
987 case K_DOWNARROW:
988 S_LocalSound ("misc/menu1.wav");
989 if (++m_net_cursor >= m_net_items)
990 m_net_cursor = 0;
991 break;
992
993 case K_UPARROW:
994 S_LocalSound ("misc/menu1.wav");
995 if (--m_net_cursor < 0)
996 m_net_cursor = m_net_items - 1;
997 break;
998
999 case K_ENTER:
1000 m_entersound = true;
1001
1002 switch (m_net_cursor)
1003 {
1004 case 0:
1005 M_Menu_SerialConfig_f ();
1006 break;
1007
1008 case 1:
1009 M_Menu_SerialConfig_f ();
1010 break;
1011
1012 case 2:
1013 M_Menu_LanConfig_f ();
1014 break;
1015
1016 case 3:
1017 M_Menu_LanConfig_f ();
1018 break;
1019
1020 case 4:
1021 // multiprotocol
1022 break;
1023 }
1024 }
1025
1026 if (m_net_cursor == 0 && !serialAvailable)
1027 goto again;
1028 if (m_net_cursor == 1 && !serialAvailable)
1029 goto again;
1030 if (m_net_cursor == 2 && !ipxAvailable)
1031 goto again;
1032 if (m_net_cursor == 3 && !tcpipAvailable)
1033 goto again;
1034 }
1035
1036 //=============================================================================
1037 /* OPTIONS MENU */
1038
1039 #ifdef _WIN32
1040 #define OPTIONS_ITEMS 14
1041 #else
1042 #define OPTIONS_ITEMS 13
1043 #endif
1044
1045 #define SLIDER_RANGE 10
1046
1047 int options_cursor;
1048
M_Menu_Options_f(void)1049 void M_Menu_Options_f (void)
1050 {
1051 key_dest = key_menu;
1052 m_state = m_options;
1053 m_entersound = true;
1054
1055 #ifdef _WIN32
1056 if ((options_cursor == 13) && (modestate != MS_WINDOWED))
1057 {
1058 options_cursor = 0;
1059 }
1060 #endif
1061 }
1062
1063
M_AdjustSliders(int dir)1064 void M_AdjustSliders (int dir)
1065 {
1066 S_LocalSound ("misc/menu3.wav");
1067
1068 switch (options_cursor)
1069 {
1070 case 3: // screen size
1071 scr_viewsize.value += dir * 10;
1072 if (scr_viewsize.value < 30)
1073 scr_viewsize.value = 30;
1074 if (scr_viewsize.value > 120)
1075 scr_viewsize.value = 120;
1076 Cvar_SetValue ("viewsize", scr_viewsize.value);
1077 break;
1078 case 4: // gamma
1079 v_gamma.value -= dir * 0.05;
1080 if (v_gamma.value < 0.5)
1081 v_gamma.value = 0.5;
1082 if (v_gamma.value > 1)
1083 v_gamma.value = 1;
1084 Cvar_SetValue ("gamma", v_gamma.value);
1085 break;
1086 case 5: // mouse speed
1087 sensitivity.value += dir * 0.5;
1088 if (sensitivity.value < 1)
1089 sensitivity.value = 1;
1090 if (sensitivity.value > 11)
1091 sensitivity.value = 11;
1092 Cvar_SetValue ("sensitivity", sensitivity.value);
1093 break;
1094 case 6: // music volume
1095 #ifdef _WIN32
1096 bgmvolume.value += dir * 1.0;
1097 #else
1098 bgmvolume.value += dir * 0.1;
1099 #endif
1100 if (bgmvolume.value < 0)
1101 bgmvolume.value = 0;
1102 if (bgmvolume.value > 1)
1103 bgmvolume.value = 1;
1104 Cvar_SetValue ("bgmvolume", bgmvolume.value);
1105 break;
1106 case 7: // sfx volume
1107 volume.value += dir * 0.1;
1108 if (volume.value < 0)
1109 volume.value = 0;
1110 if (volume.value > 1)
1111 volume.value = 1;
1112 Cvar_SetValue ("volume", volume.value);
1113 break;
1114
1115 case 8: // allways run
1116 if (cl_forwardspeed.value > 200)
1117 {
1118 Cvar_SetValue ("cl_forwardspeed", 200);
1119 Cvar_SetValue ("cl_backspeed", 200);
1120 }
1121 else
1122 {
1123 Cvar_SetValue ("cl_forwardspeed", 400);
1124 Cvar_SetValue ("cl_backspeed", 400);
1125 }
1126 break;
1127
1128 case 9: // invert mouse
1129 Cvar_SetValue ("m_pitch", -m_pitch.value);
1130 break;
1131
1132 case 10: // lookspring
1133 Cvar_SetValue ("lookspring", !lookspring.value);
1134 break;
1135
1136 case 11: // lookstrafe
1137 Cvar_SetValue ("lookstrafe", !lookstrafe.value);
1138 break;
1139
1140 #ifdef _WIN32
1141 case 13: // _windowed_mouse
1142 Cvar_SetValue ("_windowed_mouse", !_windowed_mouse.value);
1143 break;
1144 #endif
1145 }
1146 }
1147
1148
M_DrawSlider(int x,int y,float range)1149 void M_DrawSlider (int x, int y, float range)
1150 {
1151 int i;
1152
1153 if (range < 0)
1154 range = 0;
1155 if (range > 1)
1156 range = 1;
1157 M_DrawCharacter (x-8, y, 128);
1158 for (i=0 ; i<SLIDER_RANGE ; i++)
1159 M_DrawCharacter (x + i*8, y, 129);
1160 M_DrawCharacter (x+i*8, y, 130);
1161 M_DrawCharacter ((int) (x + (SLIDER_RANGE-1)*8 * range), y, 131);
1162 }
1163
M_DrawCheckbox(int x,int y,int on)1164 void M_DrawCheckbox (int x, int y, int on)
1165 {
1166 #if 0
1167 if (on)
1168 M_DrawCharacter (x, y, 131);
1169 else
1170 M_DrawCharacter (x, y, 129);
1171 #endif
1172 if (on)
1173 M_Print (x, y, "on");
1174 else
1175 M_Print (x, y, "off");
1176 }
1177
M_Options_Draw(void)1178 void M_Options_Draw (void)
1179 {
1180 float r;
1181 qpic_t *p;
1182
1183 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
1184 p = Draw_CachePic ("gfx/p_option.lmp");
1185 M_DrawPic ( (320-p->width)/2, 4, p);
1186
1187 M_Print (16, 32, " Customize controls");
1188 M_Print (16, 40, " Go to console");
1189 M_Print (16, 48, " Reset to defaults");
1190
1191 M_Print (16, 56, " Screen size");
1192 r = (scr_viewsize.value - 30) / (120 - 30);
1193 M_DrawSlider (220, 56, r);
1194
1195 M_Print (16, 64, " Brightness");
1196 r = (1.0 - v_gamma.value) / 0.5;
1197 M_DrawSlider (220, 64, r);
1198
1199 M_Print (16, 72, " Mouse Speed");
1200 r = (sensitivity.value - 1)/10;
1201 M_DrawSlider (220, 72, r);
1202
1203 M_Print (16, 80, " CD Music Volume");
1204 r = bgmvolume.value;
1205 M_DrawSlider (220, 80, r);
1206
1207 M_Print (16, 88, " Sound Volume");
1208 r = volume.value;
1209 M_DrawSlider (220, 88, r);
1210
1211 M_Print (16, 96, " Always Run");
1212 M_DrawCheckbox (220, 96, cl_forwardspeed.value > 200);
1213
1214 M_Print (16, 104, " Invert Mouse");
1215 M_DrawCheckbox (220, 104, m_pitch.value < 0);
1216
1217 M_Print (16, 112, " Lookspring");
1218 M_DrawCheckbox (220, 112, (int) lookspring.value);
1219
1220 M_Print (16, 120, " Lookstrafe");
1221 M_DrawCheckbox (220, 120, (int) lookstrafe.value);
1222
1223 if (vid_menudrawfn)
1224 M_Print (16, 128, " Video Options");
1225
1226 #ifdef _WIN32
1227 if (modestate == MS_WINDOWED)
1228 {
1229 M_Print (16, 136, " Use Mouse");
1230 M_DrawCheckbox (220, 136, _windowed_mouse.value);
1231 }
1232 #endif
1233
1234 // cursor
1235 M_DrawCharacter (200, 32 + options_cursor*8, 12+((int)(realtime*4)&1));
1236 }
1237
1238
M_Options_Key(int k)1239 void M_Options_Key (int k)
1240 {
1241 switch (k)
1242 {
1243 case K_ESCAPE:
1244 M_Menu_Main_f ();
1245 break;
1246
1247 case K_ENTER:
1248 m_entersound = true;
1249 switch (options_cursor)
1250 {
1251 case 0:
1252 M_Menu_Keys_f ();
1253 break;
1254 case 1:
1255 m_state = m_none;
1256 Con_ToggleConsole_f ();
1257 break;
1258 case 2:
1259 Cbuf_AddText ("exec default.cfg\n");
1260 break;
1261 case 12:
1262 M_Menu_Video_f ();
1263 break;
1264 default:
1265 M_AdjustSliders (1);
1266 break;
1267 }
1268 return;
1269
1270 case K_UPARROW:
1271 S_LocalSound ("misc/menu1.wav");
1272 options_cursor--;
1273 if (options_cursor < 0)
1274 options_cursor = OPTIONS_ITEMS-1;
1275 break;
1276
1277 case K_DOWNARROW:
1278 S_LocalSound ("misc/menu1.wav");
1279 options_cursor++;
1280 if (options_cursor >= OPTIONS_ITEMS)
1281 options_cursor = 0;
1282 break;
1283
1284 case K_LEFTARROW:
1285 M_AdjustSliders (-1);
1286 break;
1287
1288 case K_RIGHTARROW:
1289 M_AdjustSliders (1);
1290 break;
1291 }
1292
1293 if (options_cursor == 12 && vid_menudrawfn == NULL)
1294 {
1295 if (k == K_UPARROW)
1296 options_cursor = 11;
1297 else
1298 options_cursor = 0;
1299 }
1300
1301 #ifdef _WIN32
1302 if ((options_cursor == 13) && (modestate != MS_WINDOWED))
1303 {
1304 if (k == K_UPARROW)
1305 options_cursor = 12;
1306 else
1307 options_cursor = 0;
1308 }
1309 #endif
1310 }
1311
1312 //=============================================================================
1313 /* KEYS MENU */
1314
1315 const char *bindnames[][2] =
1316 {
1317 {"+attack", "attack"},
1318 {"impulse 10", "change weapon"},
1319 {"+jump", "jump / swim up"},
1320 {"+forward", "walk forward"},
1321 {"+back", "backpedal"},
1322 {"+left", "turn left"},
1323 {"+right", "turn right"},
1324 {"+speed", "run"},
1325 {"+moveleft", "step left"},
1326 {"+moveright", "step right"},
1327 {"+strafe", "sidestep"},
1328 {"+lookup", "look up"},
1329 {"+lookdown", "look down"},
1330 {"centerview", "center view"},
1331 {"+mlook", "mouse look"},
1332 {"+klook", "keyboard look"},
1333 {"+moveup", "swim up"},
1334 {"+movedown", "swim down"}
1335 };
1336
1337 #define NUMCOMMANDS (sizeof(bindnames)/sizeof(bindnames[0]))
1338
1339 int keys_cursor;
1340 int bind_grab;
1341
M_Menu_Keys_f(void)1342 void M_Menu_Keys_f (void)
1343 {
1344 key_dest = key_menu;
1345 m_state = m_keys;
1346 m_entersound = true;
1347 }
1348
1349
M_FindKeysForCommand(const char * command,int * twokeys)1350 void M_FindKeysForCommand (const char *command, int *twokeys)
1351 {
1352 int count;
1353 int j;
1354 int l;
1355 char *b;
1356
1357 twokeys[0] = twokeys[1] = -1;
1358 l = strlen(command);
1359 count = 0;
1360
1361 for (j=0 ; j<256 ; j++)
1362 {
1363 b = keybindings[j];
1364 if (!b)
1365 continue;
1366 if (!strncmp (b, command, l) )
1367 {
1368 twokeys[count] = j;
1369 count++;
1370 if (count == 2)
1371 break;
1372 }
1373 }
1374 }
1375
M_UnbindCommand(const char * command)1376 void M_UnbindCommand (const char *command)
1377 {
1378 int j;
1379 int l;
1380 char *b;
1381
1382 l = strlen(command);
1383
1384 for (j=0 ; j<256 ; j++)
1385 {
1386 b = keybindings[j];
1387 if (!b)
1388 continue;
1389 if (!strncmp (b, command, l) )
1390 Key_SetBinding (j, "");
1391 }
1392 }
1393
1394
M_Keys_Draw(void)1395 void M_Keys_Draw (void)
1396 {
1397 int i, l;
1398 int keys[2];
1399 const char *name;
1400 int x, y;
1401 qpic_t *p;
1402
1403 p = Draw_CachePic ("gfx/ttl_cstm.lmp");
1404 M_DrawPic ( (320-p->width)/2, 4, p);
1405
1406 if (bind_grab)
1407 M_Print (12, 32, "Press a key or button for this action");
1408 else
1409 M_Print (18, 32, "Enter to change, backspace to clear");
1410
1411 // search for known bindings
1412 for (i=0 ; i< (int) (NUMCOMMANDS) ; i++)
1413 {
1414 y = 48 + 8*i;
1415
1416 M_Print (16, y, bindnames[i][1]);
1417
1418 l = strlen (bindnames[i][0]);
1419
1420 M_FindKeysForCommand (bindnames[i][0], keys);
1421
1422 if (keys[0] == -1)
1423 {
1424 M_Print (140, y, "???");
1425 }
1426 else
1427 {
1428 name = Key_KeynumToString (keys[0]);
1429 M_Print (140, y, name);
1430 x = strlen(name) * 8;
1431 if (keys[1] != -1)
1432 {
1433 M_Print (140 + x + 8, y, "or");
1434 M_Print (140 + x + 32, y, Key_KeynumToString (keys[1]));
1435 }
1436 }
1437 }
1438
1439 if (bind_grab)
1440 M_DrawCharacter (130, 48 + keys_cursor*8, '=');
1441 else
1442 M_DrawCharacter (130, 48 + keys_cursor*8, 12+((int)(realtime*4)&1));
1443 }
1444
1445
M_Keys_Key(int k)1446 void M_Keys_Key (int k)
1447 {
1448 char cmd[80];
1449 int keys[2];
1450
1451 if (bind_grab)
1452 { // defining a key
1453 S_LocalSound ("misc/menu1.wav");
1454 if (k == K_ESCAPE)
1455 {
1456 bind_grab = false;
1457 }
1458 else if (k != '`')
1459 {
1460 sprintf (cmd, "bind \"%s\" \"%s\"\n", Key_KeynumToString (k), bindnames[keys_cursor][0]);
1461 Cbuf_InsertText (cmd);
1462 }
1463
1464 bind_grab = false;
1465 return;
1466 }
1467
1468 switch (k)
1469 {
1470 case K_ESCAPE:
1471 M_Menu_Options_f ();
1472 break;
1473
1474 case K_LEFTARROW:
1475 case K_UPARROW:
1476 S_LocalSound ("misc/menu1.wav");
1477 keys_cursor--;
1478 if (keys_cursor < 0)
1479 keys_cursor = NUMCOMMANDS-1;
1480 break;
1481
1482 case K_DOWNARROW:
1483 case K_RIGHTARROW:
1484 S_LocalSound ("misc/menu1.wav");
1485 keys_cursor++;
1486 if (keys_cursor >= (int)(NUMCOMMANDS))
1487 keys_cursor = 0;
1488 break;
1489
1490 case K_ENTER: // go into bind mode
1491 M_FindKeysForCommand (bindnames[keys_cursor][0], keys);
1492 S_LocalSound ("misc/menu2.wav");
1493 if (keys[1] != -1)
1494 M_UnbindCommand (bindnames[keys_cursor][0]);
1495 bind_grab = true;
1496 break;
1497
1498 case K_BACKSPACE: // delete bindings
1499 case K_DEL: // delete bindings
1500 S_LocalSound ("misc/menu2.wav");
1501 M_UnbindCommand (bindnames[keys_cursor][0]);
1502 break;
1503 }
1504 }
1505
1506 //=============================================================================
1507 /* VIDEO MENU */
1508
M_Menu_Video_f(void)1509 void M_Menu_Video_f (void)
1510 {
1511 key_dest = key_menu;
1512 m_state = m_video;
1513 m_entersound = true;
1514 }
1515
1516
M_Video_Draw(void)1517 void M_Video_Draw (void)
1518 {
1519 (*vid_menudrawfn) ();
1520 }
1521
1522
M_Video_Key(int key)1523 void M_Video_Key (int key)
1524 {
1525 (*vid_menukeyfn) (key);
1526 }
1527
1528 //=============================================================================
1529 /* HELP MENU */
1530
1531 int help_page;
1532 #define NUM_HELP_PAGES 6
1533
1534
M_Menu_Help_f(void)1535 void M_Menu_Help_f (void)
1536 {
1537 #if 1 // Hijack menu for timedemo
1538 key_dest = key_menu;
1539 m_state = m_none;
1540 char buf[50];
1541 strcpy(buf, "timedemo demo1");
1542 Cmd_TokenizeString(buf);
1543 CL_TimeDemo_f();
1544 #else
1545 key_dest = key_menu;
1546 m_state = m_help;
1547 m_entersound = true;
1548 help_page = 0;
1549 #endif
1550 }
1551
1552
1553
M_Help_Draw(void)1554 void M_Help_Draw (void)
1555 {
1556 M_DrawPic (0, 0, Draw_CachePic ( va("gfx/help%i.lmp", help_page)) );
1557 }
1558
1559
M_Help_Key(int key)1560 void M_Help_Key (int key)
1561 {
1562 switch (key)
1563 {
1564 case K_ESCAPE:
1565 M_Menu_Main_f ();
1566 break;
1567
1568 case K_UPARROW:
1569 case K_RIGHTARROW:
1570 m_entersound = true;
1571 if (++help_page >= NUM_HELP_PAGES)
1572 help_page = 0;
1573 break;
1574
1575 case K_DOWNARROW:
1576 case K_LEFTARROW:
1577 m_entersound = true;
1578 if (--help_page < 0)
1579 help_page = NUM_HELP_PAGES-1;
1580 break;
1581 }
1582
1583 }
1584
1585 //=============================================================================
1586 /* QUIT MENU */
1587
1588 int msgNumber;
1589 int m_quit_prevstate;
1590 qboolean wasInMenus;
1591
1592 #ifndef _WIN32
1593 const char *quitMessage [] =
1594 {
1595 /* .........1.........2.... */
1596 " Are you gonna quit ",
1597 " this game just like ",
1598 " everything else? ",
1599 " ",
1600
1601 " Milord, methinks that ",
1602 " thou art a lowly ",
1603 " quitter. Is this true? ",
1604 " ",
1605
1606 " Do I need to bust your ",
1607 " face open for trying ",
1608 " to quit? ",
1609 " ",
1610
1611 " Man, I oughta smack you",
1612 " for trying to quit! ",
1613 " Press Y to get ",
1614 " smacked out. ",
1615
1616 " Press Y to quit like a ",
1617 " big loser in life. ",
1618 " Press N to stay proud ",
1619 " and successful! ",
1620
1621 " If you press Y to ",
1622 " quit, I will summon ",
1623 " Satan all over your ",
1624 " hard drive! ",
1625
1626 " Um, Asmodeus dislikes ",
1627 " his children trying to ",
1628 " quit. Press Y to return",
1629 " to your Tinkertoys. ",
1630
1631 " If you quit now, I'll ",
1632 " throw a blanket-party ",
1633 " for you next time! ",
1634 " "
1635 };
1636 #endif
1637
M_Menu_Quit_f(void)1638 void M_Menu_Quit_f (void)
1639 {
1640 if (m_state == m_quit)
1641 return;
1642 wasInMenus = (key_dest == key_menu);
1643 key_dest = key_menu;
1644 m_quit_prevstate = m_state;
1645 m_state = m_quit;
1646 m_entersound = true;
1647 msgNumber = rand()&7;
1648 }
1649
1650
M_Quit_Key(int key)1651 void M_Quit_Key (int key)
1652 {
1653 switch (key)
1654 {
1655 case K_ESCAPE:
1656 case 'n':
1657 case 'N':
1658 if (wasInMenus)
1659 {
1660 m_state = (m_state_t) m_quit_prevstate;
1661 m_entersound = true;
1662 }
1663 else
1664 {
1665 key_dest = key_game;
1666 m_state = (m_state_t) m_none;
1667 }
1668 break;
1669
1670 case 'Y':
1671 case 'y':
1672 case K_ENTER:
1673 key_dest = key_console;
1674 Host_Quit_f ();
1675 break;
1676
1677 default:
1678 break;
1679 }
1680
1681 }
1682
1683
M_Quit_Draw(void)1684 void M_Quit_Draw (void)
1685 {
1686 if (wasInMenus)
1687 {
1688 m_state = (m_state_t) m_quit_prevstate;
1689 m_recursiveDraw = true;
1690 M_Draw ();
1691 m_state = m_quit;
1692 }
1693
1694 #ifdef _WIN32
1695 M_DrawTextBox (0, 0, 38, 23);
1696 M_PrintWhite (16, 12, " Quake version 1.09 by id Software\n\n");
1697 M_PrintWhite (16, 28, "Programming Art \n");
1698 M_Print (16, 36, " John Carmack Adrian Carmack\n");
1699 M_Print (16, 44, " Michael Abrash Kevin Cloud\n");
1700 M_Print (16, 52, " John Cash Paul Steed\n");
1701 M_Print (16, 60, " Dave 'Zoid' Kirsch\n");
1702 M_PrintWhite (16, 68, "Design Biz\n");
1703 M_Print (16, 76, " John Romero Jay Wilbur\n");
1704 M_Print (16, 84, " Sandy Petersen Mike Wilson\n");
1705 M_Print (16, 92, " American McGee Donna Jackson\n");
1706 M_Print (16, 100, " Tim Willits Todd Hollenshead\n");
1707 M_PrintWhite (16, 108, "Support Projects\n");
1708 M_Print (16, 116, " Barrett Alexander Shawn Green\n");
1709 M_PrintWhite (16, 124, "Sound Effects\n");
1710 M_Print (16, 132, " Trent Reznor and Nine Inch Nails\n\n");
1711 M_PrintWhite (16, 140, "Quake is a trademark of Id Software,\n");
1712 M_PrintWhite (16, 148, "inc., (c)1996 Id Software, inc. All\n");
1713 M_PrintWhite (16, 156, "rights reserved. NIN logo is a\n");
1714 M_PrintWhite (16, 164, "registered trademark licensed to\n");
1715 M_PrintWhite (16, 172, "Nothing Interactive, Inc. All rights\n");
1716 M_PrintWhite (16, 180, "reserved. Press y to exit\n");
1717 #else
1718 M_DrawTextBox (56, 76, 24, 4);
1719 #if 0
1720 M_Print (64, 84, quitMessage[msgNumber*4+0]);
1721 M_Print (64, 92, quitMessage[msgNumber*4+1]);
1722 M_Print (64, 100, quitMessage[msgNumber*4+2]);
1723 M_Print (64, 108, quitMessage[msgNumber*4+3]);
1724 #else
1725 M_PrintWhite(64, 92, "Click Trackball to Quit");
1726 #endif
1727 #endif
1728 }
1729
1730 //=============================================================================
1731
1732 /* SERIAL CONFIG MENU */
1733
1734 int serialConfig_cursor;
1735 int serialConfig_cursor_table[] = {48, 64, 80, 96, 112, 132};
1736 #define NUM_SERIALCONFIG_CMDS 6
1737
1738 static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8};
1739 static int ISA_IRQs[] = {4,3,4,3};
1740 int serialConfig_baudrate[] = {9600,14400,19200,28800,38400,57600};
1741
1742 int serialConfig_comport;
1743 int serialConfig_irq ;
1744 int serialConfig_baud;
1745 char serialConfig_phone[16];
1746
M_Menu_SerialConfig_f(void)1747 void M_Menu_SerialConfig_f (void)
1748 {
1749 int n;
1750 int port;
1751 int baudrate;
1752 qboolean useModem;
1753
1754 key_dest = key_menu;
1755 m_state = m_serialconfig;
1756 m_entersound = true;
1757 if (JoiningGame && SerialConfig)
1758 serialConfig_cursor = 4;
1759 else
1760 serialConfig_cursor = 5;
1761
1762 (*GetComPortConfig) (0, &port, &serialConfig_irq, &baudrate, &useModem);
1763
1764 // map uart's port to COMx
1765 for (n = 0; n < 4; n++)
1766 if (ISA_uarts[n] == port)
1767 break;
1768 if (n == 4)
1769 {
1770 n = 0;
1771 serialConfig_irq = 4;
1772 }
1773 serialConfig_comport = n + 1;
1774
1775 // map baudrate to index
1776 for (n = 0; n < 6; n++)
1777 if (serialConfig_baudrate[n] == baudrate)
1778 break;
1779 if (n == 6)
1780 n = 5;
1781 serialConfig_baud = n;
1782
1783 m_return_onerror = false;
1784 m_return_reason[0] = 0;
1785 }
1786
1787
M_SerialConfig_Draw(void)1788 void M_SerialConfig_Draw (void)
1789 {
1790 qpic_t *p;
1791 int basex;
1792 const char *startJoin;
1793 const char *directModem;
1794
1795 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
1796 p = Draw_CachePic ("gfx/p_multi.lmp");
1797 basex = (320-p->width)/2;
1798 M_DrawPic (basex, 4, p);
1799
1800 if (StartingGame)
1801 startJoin = "New Game";
1802 else
1803 startJoin = "Join Game";
1804 if (SerialConfig)
1805 directModem = "Modem";
1806 else
1807 directModem = "Direct Connect";
1808 M_Print (basex, 32, va ("%s - %s", startJoin, directModem));
1809 basex += 8;
1810
1811 M_Print (basex, serialConfig_cursor_table[0], "Port");
1812 M_DrawTextBox (160, 40, 4, 1);
1813 M_Print (168, serialConfig_cursor_table[0], va("COM%u", serialConfig_comport));
1814
1815 M_Print (basex, serialConfig_cursor_table[1], "IRQ");
1816 M_DrawTextBox (160, serialConfig_cursor_table[1]-8, 1, 1);
1817 M_Print (168, serialConfig_cursor_table[1], va("%u", serialConfig_irq));
1818
1819 M_Print (basex, serialConfig_cursor_table[2], "Baud");
1820 M_DrawTextBox (160, serialConfig_cursor_table[2]-8, 5, 1);
1821 M_Print (168, serialConfig_cursor_table[2], va("%u", serialConfig_baudrate[serialConfig_baud]));
1822
1823 if (SerialConfig)
1824 {
1825 M_Print (basex, serialConfig_cursor_table[3], "Modem Setup...");
1826 if (JoiningGame)
1827 {
1828 M_Print (basex, serialConfig_cursor_table[4], "Phone number");
1829 M_DrawTextBox (160, serialConfig_cursor_table[4]-8, 16, 1);
1830 M_Print (168, serialConfig_cursor_table[4], serialConfig_phone);
1831 }
1832 }
1833
1834 if (JoiningGame)
1835 {
1836 M_DrawTextBox (basex, serialConfig_cursor_table[5]-8, 7, 1);
1837 M_Print (basex+8, serialConfig_cursor_table[5], "Connect");
1838 }
1839 else
1840 {
1841 M_DrawTextBox (basex, serialConfig_cursor_table[5]-8, 2, 1);
1842 M_Print (basex+8, serialConfig_cursor_table[5], "OK");
1843 }
1844
1845 M_DrawCharacter (basex-8, serialConfig_cursor_table [serialConfig_cursor], 12+((int)(realtime*4)&1));
1846
1847 if (serialConfig_cursor == 4)
1848 M_DrawCharacter (168 + 8*strlen(serialConfig_phone), serialConfig_cursor_table [serialConfig_cursor], 10+((int)(realtime*4)&1));
1849
1850 if (*m_return_reason)
1851 M_PrintWhite (basex, 148, m_return_reason);
1852 }
1853
1854
M_SerialConfig_Key(int key)1855 void M_SerialConfig_Key (int key)
1856 {
1857 int l;
1858
1859 switch (key)
1860 {
1861 case K_ESCAPE:
1862 M_Menu_Net_f ();
1863 break;
1864
1865 case K_UPARROW:
1866 S_LocalSound ("misc/menu1.wav");
1867 serialConfig_cursor--;
1868 if (serialConfig_cursor < 0)
1869 serialConfig_cursor = NUM_SERIALCONFIG_CMDS-1;
1870 break;
1871
1872 case K_DOWNARROW:
1873 S_LocalSound ("misc/menu1.wav");
1874 serialConfig_cursor++;
1875 if (serialConfig_cursor >= NUM_SERIALCONFIG_CMDS)
1876 serialConfig_cursor = 0;
1877 break;
1878
1879 case K_LEFTARROW:
1880 if (serialConfig_cursor > 2)
1881 break;
1882 S_LocalSound ("misc/menu3.wav");
1883
1884 if (serialConfig_cursor == 0)
1885 {
1886 serialConfig_comport--;
1887 if (serialConfig_comport == 0)
1888 serialConfig_comport = 4;
1889 serialConfig_irq = ISA_IRQs[serialConfig_comport-1];
1890 }
1891
1892 if (serialConfig_cursor == 1)
1893 {
1894 serialConfig_irq--;
1895 if (serialConfig_irq == 6)
1896 serialConfig_irq = 5;
1897 if (serialConfig_irq == 1)
1898 serialConfig_irq = 7;
1899 }
1900
1901 if (serialConfig_cursor == 2)
1902 {
1903 serialConfig_baud--;
1904 if (serialConfig_baud < 0)
1905 serialConfig_baud = 5;
1906 }
1907
1908 break;
1909
1910 case K_RIGHTARROW:
1911 if (serialConfig_cursor > 2)
1912 break;
1913 forward:
1914 S_LocalSound ("misc/menu3.wav");
1915
1916 if (serialConfig_cursor == 0)
1917 {
1918 serialConfig_comport++;
1919 if (serialConfig_comport > 4)
1920 serialConfig_comport = 1;
1921 serialConfig_irq = ISA_IRQs[serialConfig_comport-1];
1922 }
1923
1924 if (serialConfig_cursor == 1)
1925 {
1926 serialConfig_irq++;
1927 if (serialConfig_irq == 6)
1928 serialConfig_irq = 7;
1929 if (serialConfig_irq == 8)
1930 serialConfig_irq = 2;
1931 }
1932
1933 if (serialConfig_cursor == 2)
1934 {
1935 serialConfig_baud++;
1936 if (serialConfig_baud > 5)
1937 serialConfig_baud = 0;
1938 }
1939
1940 break;
1941
1942 case K_ENTER:
1943 if (serialConfig_cursor < 3)
1944 goto forward;
1945
1946 m_entersound = true;
1947
1948 if (serialConfig_cursor == 3)
1949 {
1950 (*SetComPortConfig) (0, ISA_uarts[serialConfig_comport-1], serialConfig_irq, serialConfig_baudrate[serialConfig_baud], SerialConfig);
1951
1952 M_Menu_ModemConfig_f ();
1953 break;
1954 }
1955
1956 if (serialConfig_cursor == 4)
1957 {
1958 serialConfig_cursor = 5;
1959 break;
1960 }
1961
1962 // serialConfig_cursor == 5 (OK/CONNECT)
1963 (*SetComPortConfig) (0, ISA_uarts[serialConfig_comport-1], serialConfig_irq, serialConfig_baudrate[serialConfig_baud], SerialConfig);
1964
1965 M_ConfigureNetSubsystem ();
1966
1967 if (StartingGame)
1968 {
1969 M_Menu_GameOptions_f ();
1970 break;
1971 }
1972
1973 m_return_state = m_state;
1974 m_return_onerror = true;
1975 key_dest = key_game;
1976 m_state = m_none;
1977
1978 if (SerialConfig)
1979 Cbuf_AddText (va ("connect \"%s\"\n", serialConfig_phone));
1980 else
1981 Cbuf_AddText ("connect\n");
1982 break;
1983
1984 case K_BACKSPACE:
1985 if (serialConfig_cursor == 4)
1986 {
1987 if (strlen(serialConfig_phone))
1988 serialConfig_phone[strlen(serialConfig_phone)-1] = 0;
1989 }
1990 break;
1991
1992 default:
1993 if (key < 32 || key > 127)
1994 break;
1995 if (serialConfig_cursor == 4)
1996 {
1997 l = strlen(serialConfig_phone);
1998 if (l < 15)
1999 {
2000 serialConfig_phone[l+1] = 0;
2001 serialConfig_phone[l] = key;
2002 }
2003 }
2004 }
2005
2006 if (DirectConfig && (serialConfig_cursor == 3 || serialConfig_cursor == 4))
2007 {
2008 if (key == K_UPARROW)
2009 serialConfig_cursor = 2;
2010 else
2011 serialConfig_cursor = 5;
2012 }
2013 if (SerialConfig && StartingGame && serialConfig_cursor == 4)
2014 {
2015 if (key == K_UPARROW)
2016 serialConfig_cursor = 3;
2017 else
2018 serialConfig_cursor = 5;
2019 }
2020 }
2021
2022 //=============================================================================
2023 /* MODEM CONFIG MENU */
2024
2025 int modemConfig_cursor;
2026 int modemConfig_cursor_table [] = {40, 56, 88, 120, 156};
2027 #define NUM_MODEMCONFIG_CMDS 5
2028
2029 char modemConfig_dialing;
2030 char modemConfig_clear [16];
2031 char modemConfig_init [32];
2032 char modemConfig_hangup [16];
2033
M_Menu_ModemConfig_f(void)2034 void M_Menu_ModemConfig_f (void)
2035 {
2036 key_dest = key_menu;
2037 m_state = m_modemconfig;
2038 m_entersound = true;
2039 (*GetModemConfig) (0, &modemConfig_dialing, modemConfig_clear, modemConfig_init, modemConfig_hangup);
2040 }
2041
2042
M_ModemConfig_Draw(void)2043 void M_ModemConfig_Draw (void)
2044 {
2045 qpic_t *p;
2046 int basex;
2047
2048 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
2049 p = Draw_CachePic ("gfx/p_multi.lmp");
2050 basex = (320-p->width)/2;
2051 M_DrawPic (basex, 4, p);
2052 basex += 8;
2053
2054 if (modemConfig_dialing == 'P')
2055 M_Print (basex, modemConfig_cursor_table[0], "Pulse Dialing");
2056 else
2057 M_Print (basex, modemConfig_cursor_table[0], "Touch Tone Dialing");
2058
2059 M_Print (basex, modemConfig_cursor_table[1], "Clear");
2060 M_DrawTextBox (basex, modemConfig_cursor_table[1]+4, 16, 1);
2061 M_Print (basex+8, modemConfig_cursor_table[1]+12, modemConfig_clear);
2062 if (modemConfig_cursor == 1)
2063 M_DrawCharacter (basex+8 + 8*strlen(modemConfig_clear), modemConfig_cursor_table[1]+12, 10+((int)(realtime*4)&1));
2064
2065 M_Print (basex, modemConfig_cursor_table[2], "Init");
2066 M_DrawTextBox (basex, modemConfig_cursor_table[2]+4, 30, 1);
2067 M_Print (basex+8, modemConfig_cursor_table[2]+12, modemConfig_init);
2068 if (modemConfig_cursor == 2)
2069 M_DrawCharacter (basex+8 + 8*strlen(modemConfig_init), modemConfig_cursor_table[2]+12, 10+((int)(realtime*4)&1));
2070
2071 M_Print (basex, modemConfig_cursor_table[3], "Hangup");
2072 M_DrawTextBox (basex, modemConfig_cursor_table[3]+4, 16, 1);
2073 M_Print (basex+8, modemConfig_cursor_table[3]+12, modemConfig_hangup);
2074 if (modemConfig_cursor == 3)
2075 M_DrawCharacter (basex+8 + 8*strlen(modemConfig_hangup), modemConfig_cursor_table[3]+12, 10+((int)(realtime*4)&1));
2076
2077 M_DrawTextBox (basex, modemConfig_cursor_table[4]-8, 2, 1);
2078 M_Print (basex+8, modemConfig_cursor_table[4], "OK");
2079
2080 M_DrawCharacter (basex-8, modemConfig_cursor_table [modemConfig_cursor], 12+((int)(realtime*4)&1));
2081 }
2082
2083
M_ModemConfig_Key(int key)2084 void M_ModemConfig_Key (int key)
2085 {
2086 int l;
2087
2088 switch (key)
2089 {
2090 case K_ESCAPE:
2091 M_Menu_SerialConfig_f ();
2092 break;
2093
2094 case K_UPARROW:
2095 S_LocalSound ("misc/menu1.wav");
2096 modemConfig_cursor--;
2097 if (modemConfig_cursor < 0)
2098 modemConfig_cursor = NUM_MODEMCONFIG_CMDS-1;
2099 break;
2100
2101 case K_DOWNARROW:
2102 S_LocalSound ("misc/menu1.wav");
2103 modemConfig_cursor++;
2104 if (modemConfig_cursor >= NUM_MODEMCONFIG_CMDS)
2105 modemConfig_cursor = 0;
2106 break;
2107
2108 case K_LEFTARROW:
2109 case K_RIGHTARROW:
2110 if (modemConfig_cursor == 0)
2111 {
2112 if (modemConfig_dialing == 'P')
2113 modemConfig_dialing = 'T';
2114 else
2115 modemConfig_dialing = 'P';
2116 S_LocalSound ("misc/menu1.wav");
2117 }
2118 break;
2119
2120 case K_ENTER:
2121 if (modemConfig_cursor == 0)
2122 {
2123 if (modemConfig_dialing == 'P')
2124 modemConfig_dialing = 'T';
2125 else
2126 modemConfig_dialing = 'P';
2127 m_entersound = true;
2128 }
2129
2130 if (modemConfig_cursor == 4)
2131 {
2132 (*SetModemConfig) (0, va ("%c", modemConfig_dialing), modemConfig_clear, modemConfig_init, modemConfig_hangup);
2133 m_entersound = true;
2134 M_Menu_SerialConfig_f ();
2135 }
2136 break;
2137
2138 case K_BACKSPACE:
2139 if (modemConfig_cursor == 1)
2140 {
2141 if (strlen(modemConfig_clear))
2142 modemConfig_clear[strlen(modemConfig_clear)-1] = 0;
2143 }
2144
2145 if (modemConfig_cursor == 2)
2146 {
2147 if (strlen(modemConfig_init))
2148 modemConfig_init[strlen(modemConfig_init)-1] = 0;
2149 }
2150
2151 if (modemConfig_cursor == 3)
2152 {
2153 if (strlen(modemConfig_hangup))
2154 modemConfig_hangup[strlen(modemConfig_hangup)-1] = 0;
2155 }
2156 break;
2157
2158 default:
2159 if (key < 32 || key > 127)
2160 break;
2161
2162 if (modemConfig_cursor == 1)
2163 {
2164 l = strlen(modemConfig_clear);
2165 if (l < 15)
2166 {
2167 modemConfig_clear[l+1] = 0;
2168 modemConfig_clear[l] = key;
2169 }
2170 }
2171
2172 if (modemConfig_cursor == 2)
2173 {
2174 l = strlen(modemConfig_init);
2175 if (l < 29)
2176 {
2177 modemConfig_init[l+1] = 0;
2178 modemConfig_init[l] = key;
2179 }
2180 }
2181
2182 if (modemConfig_cursor == 3)
2183 {
2184 l = strlen(modemConfig_hangup);
2185 if (l < 15)
2186 {
2187 modemConfig_hangup[l+1] = 0;
2188 modemConfig_hangup[l] = key;
2189 }
2190 }
2191 }
2192 }
2193
2194 //=============================================================================
2195 /* LAN CONFIG MENU */
2196
2197 int lanConfig_cursor = -1;
2198 int lanConfig_cursor_table [] = {72, 92, 124};
2199 #define NUM_LANCONFIG_CMDS 3
2200
2201 int lanConfig_port;
2202 char lanConfig_portname[6];
2203 char lanConfig_joinname[22];
2204
M_Menu_LanConfig_f(void)2205 void M_Menu_LanConfig_f (void)
2206 {
2207 key_dest = key_menu;
2208 m_state = m_lanconfig;
2209 m_entersound = true;
2210 if (lanConfig_cursor == -1)
2211 {
2212 if (JoiningGame && TCPIPConfig)
2213 lanConfig_cursor = 2;
2214 else
2215 lanConfig_cursor = 1;
2216 }
2217 if (StartingGame && lanConfig_cursor == 2)
2218 lanConfig_cursor = 1;
2219 lanConfig_port = DEFAULTnet_hostport;
2220 sprintf(lanConfig_portname, "%u", lanConfig_port);
2221
2222 m_return_onerror = false;
2223 m_return_reason[0] = 0;
2224 }
2225
2226
M_LanConfig_Draw(void)2227 void M_LanConfig_Draw (void)
2228 {
2229 qpic_t *p;
2230 int basex;
2231 const char *startJoin;
2232 const char *protocol;
2233
2234 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
2235 p = Draw_CachePic ("gfx/p_multi.lmp");
2236 basex = (320-p->width)/2;
2237 M_DrawPic (basex, 4, p);
2238
2239 if (StartingGame)
2240 startJoin = "New Game";
2241 else
2242 startJoin = "Join Game";
2243 if (IPXConfig)
2244 protocol = "IPX";
2245 else
2246 protocol = "TCP/IP";
2247 M_Print (basex, 32, va ("%s - %s", startJoin, protocol));
2248 basex += 8;
2249
2250 M_Print (basex, 52, "Address:");
2251 if (IPXConfig)
2252 M_Print (basex+9*8, 52, my_ipx_address);
2253 else
2254 M_Print (basex+9*8, 52, my_tcpip_address);
2255
2256 M_Print (basex, lanConfig_cursor_table[0], "Port");
2257 M_DrawTextBox (basex+8*8, lanConfig_cursor_table[0]-8, 6, 1);
2258 M_Print (basex+9*8, lanConfig_cursor_table[0], lanConfig_portname);
2259
2260 if (JoiningGame)
2261 {
2262 M_Print (basex, lanConfig_cursor_table[1], "Search for local games...");
2263 M_Print (basex, 108, "Join game at:");
2264 M_DrawTextBox (basex+8, lanConfig_cursor_table[2]-8, 22, 1);
2265 M_Print (basex+16, lanConfig_cursor_table[2], lanConfig_joinname);
2266 }
2267 else
2268 {
2269 M_DrawTextBox (basex, lanConfig_cursor_table[1]-8, 2, 1);
2270 M_Print (basex+8, lanConfig_cursor_table[1], "OK");
2271 }
2272
2273 M_DrawCharacter (basex-8, lanConfig_cursor_table [lanConfig_cursor], 12+((int)(realtime*4)&1));
2274
2275 if (lanConfig_cursor == 0)
2276 M_DrawCharacter (basex+9*8 + 8*strlen(lanConfig_portname), lanConfig_cursor_table [0], 10+((int)(realtime*4)&1));
2277
2278 if (lanConfig_cursor == 2)
2279 M_DrawCharacter (basex+16 + 8*strlen(lanConfig_joinname), lanConfig_cursor_table [2], 10+((int)(realtime*4)&1));
2280
2281 if (*m_return_reason)
2282 M_PrintWhite (basex, 148, m_return_reason);
2283 }
2284
2285
M_LanConfig_Key(int key)2286 void M_LanConfig_Key (int key)
2287 {
2288 int l;
2289
2290 switch (key)
2291 {
2292 case K_ESCAPE:
2293 M_Menu_Net_f ();
2294 break;
2295
2296 case K_UPARROW:
2297 S_LocalSound ("misc/menu1.wav");
2298 lanConfig_cursor--;
2299 if (lanConfig_cursor < 0)
2300 lanConfig_cursor = NUM_LANCONFIG_CMDS-1;
2301 break;
2302
2303 case K_DOWNARROW:
2304 S_LocalSound ("misc/menu1.wav");
2305 lanConfig_cursor++;
2306 if (lanConfig_cursor >= NUM_LANCONFIG_CMDS)
2307 lanConfig_cursor = 0;
2308 break;
2309
2310 case K_ENTER:
2311 if (lanConfig_cursor == 0)
2312 break;
2313
2314 m_entersound = true;
2315
2316 M_ConfigureNetSubsystem ();
2317
2318 if (lanConfig_cursor == 1)
2319 {
2320 if (StartingGame)
2321 {
2322 M_Menu_GameOptions_f ();
2323 break;
2324 }
2325 M_Menu_Search_f();
2326 break;
2327 }
2328
2329 if (lanConfig_cursor == 2)
2330 {
2331 m_return_state = m_state;
2332 m_return_onerror = true;
2333 key_dest = key_game;
2334 m_state = m_none;
2335 Cbuf_AddText ( va ("connect \"%s\"\n", lanConfig_joinname) );
2336 break;
2337 }
2338
2339 break;
2340
2341 case K_BACKSPACE:
2342 if (lanConfig_cursor == 0)
2343 {
2344 if (strlen(lanConfig_portname))
2345 lanConfig_portname[strlen(lanConfig_portname)-1] = 0;
2346 }
2347
2348 if (lanConfig_cursor == 2)
2349 {
2350 if (strlen(lanConfig_joinname))
2351 lanConfig_joinname[strlen(lanConfig_joinname)-1] = 0;
2352 }
2353 break;
2354
2355 default:
2356 if (key < 32 || key > 127)
2357 break;
2358
2359 if (lanConfig_cursor == 2)
2360 {
2361 l = strlen(lanConfig_joinname);
2362 if (l < 21)
2363 {
2364 lanConfig_joinname[l+1] = 0;
2365 lanConfig_joinname[l] = key;
2366 }
2367 }
2368
2369 if (key < '0' || key > '9')
2370 break;
2371 if (lanConfig_cursor == 0)
2372 {
2373 l = strlen(lanConfig_portname);
2374 if (l < 5)
2375 {
2376 lanConfig_portname[l+1] = 0;
2377 lanConfig_portname[l] = key;
2378 }
2379 }
2380 }
2381
2382 if (StartingGame && lanConfig_cursor == 2)
2383 {
2384 if (key == K_UPARROW)
2385 lanConfig_cursor = 1;
2386 else
2387 lanConfig_cursor = 0;
2388 }
2389
2390 l = Q_atoi(lanConfig_portname);
2391 if (l > 65535)
2392 l = lanConfig_port;
2393 else
2394 lanConfig_port = l;
2395 sprintf(lanConfig_portname, "%u", lanConfig_port);
2396 }
2397
2398 //=============================================================================
2399 /* GAME OPTIONS MENU */
2400
2401 typedef struct
2402 {
2403 const char *name;
2404 const char *description;
2405 } level_t;
2406
2407 level_t levels[] =
2408 {
2409 {"start", "Entrance"}, // 0
2410
2411 {"e1m1", "Slipgate Complex"}, // 1
2412 {"e1m2", "Castle of the Damned"},
2413 {"e1m3", "The Necropolis"},
2414 {"e1m4", "The Grisly Grotto"},
2415 {"e1m5", "Gloom Keep"},
2416 {"e1m6", "The Door To Chthon"},
2417 {"e1m7", "The House of Chthon"},
2418 {"e1m8", "Ziggurat Vertigo"},
2419
2420 {"e2m1", "The Installation"}, // 9
2421 {"e2m2", "Ogre Citadel"},
2422 {"e2m3", "Crypt of Decay"},
2423 {"e2m4", "The Ebon Fortress"},
2424 {"e2m5", "The Wizard's Manse"},
2425 {"e2m6", "The Dismal Oubliette"},
2426 {"e2m7", "Underearth"},
2427
2428 {"e3m1", "Termination Central"}, // 16
2429 {"e3m2", "The Vaults of Zin"},
2430 {"e3m3", "The Tomb of Terror"},
2431 {"e3m4", "Satan's Dark Delight"},
2432 {"e3m5", "Wind Tunnels"},
2433 {"e3m6", "Chambers of Torment"},
2434 {"e3m7", "The Haunted Halls"},
2435
2436 {"e4m1", "The Sewage System"}, // 23
2437 {"e4m2", "The Tower of Despair"},
2438 {"e4m3", "The Elder God Shrine"},
2439 {"e4m4", "The Palace of Hate"},
2440 {"e4m5", "Hell's Atrium"},
2441 {"e4m6", "The Pain Maze"},
2442 {"e4m7", "Azure Agony"},
2443 {"e4m8", "The Nameless City"},
2444
2445 {"end", "Shub-Niggurath's Pit"}, // 31
2446
2447 {"dm1", "Place of Two Deaths"}, // 32
2448 {"dm2", "Claustrophobopolis"},
2449 {"dm3", "The Abandoned Base"},
2450 {"dm4", "The Bad Place"},
2451 {"dm5", "The Cistern"},
2452 {"dm6", "The Dark Zone"}
2453 };
2454
2455 //MED 01/06/97 added hipnotic levels
2456 level_t hipnoticlevels[] =
2457 {
2458 {"start", "Command HQ"}, // 0
2459
2460 {"hip1m1", "The Pumping Station"}, // 1
2461 {"hip1m2", "Storage Facility"},
2462 {"hip1m3", "The Lost Mine"},
2463 {"hip1m4", "Research Facility"},
2464 {"hip1m5", "Military Complex"},
2465
2466 {"hip2m1", "Ancient Realms"}, // 6
2467 {"hip2m2", "The Black Cathedral"},
2468 {"hip2m3", "The Catacombs"},
2469 {"hip2m4", "The Crypt"},
2470 {"hip2m5", "Mortum's Keep"},
2471 {"hip2m6", "The Gremlin's Domain"},
2472
2473 {"hip3m1", "Tur Torment"}, // 12
2474 {"hip3m2", "Pandemonium"},
2475 {"hip3m3", "Limbo"},
2476 {"hip3m4", "The Gauntlet"},
2477
2478 {"hipend", "Armagon's Lair"}, // 16
2479
2480 {"hipdm1", "The Edge of Oblivion"} // 17
2481 };
2482
2483 //PGM 01/07/97 added rogue levels
2484 //PGM 03/02/97 added dmatch level
2485 level_t roguelevels[] =
2486 {
2487 {"start", "Split Decision"},
2488 {"r1m1", "Deviant's Domain"},
2489 {"r1m2", "Dread Portal"},
2490 {"r1m3", "Judgement Call"},
2491 {"r1m4", "Cave of Death"},
2492 {"r1m5", "Towers of Wrath"},
2493 {"r1m6", "Temple of Pain"},
2494 {"r1m7", "Tomb of the Overlord"},
2495 {"r2m1", "Tempus Fugit"},
2496 {"r2m2", "Elemental Fury I"},
2497 {"r2m3", "Elemental Fury II"},
2498 {"r2m4", "Curse of Osiris"},
2499 {"r2m5", "Wizard's Keep"},
2500 {"r2m6", "Blood Sacrifice"},
2501 {"r2m7", "Last Bastion"},
2502 {"r2m8", "Source of Evil"},
2503 {"ctf1", "Division of Change"}
2504 };
2505
2506 typedef struct
2507 {
2508 const char *description;
2509 int firstLevel;
2510 int levels;
2511 } episode_t;
2512
2513 episode_t episodes[] =
2514 {
2515 {"Welcome to Quake", 0, 1},
2516 {"Doomed Dimension", 1, 8},
2517 {"Realm of Black Magic", 9, 7},
2518 {"Netherworld", 16, 7},
2519 {"The Elder World", 23, 8},
2520 {"Final Level", 31, 1},
2521 {"Deathmatch Arena", 32, 6}
2522 };
2523
2524 //MED 01/06/97 added hipnotic episodes
2525 episode_t hipnoticepisodes[] =
2526 {
2527 {"Scourge of Armagon", 0, 1},
2528 {"Fortress of the Dead", 1, 5},
2529 {"Dominion of Darkness", 6, 6},
2530 {"The Rift", 12, 4},
2531 {"Final Level", 16, 1},
2532 {"Deathmatch Arena", 17, 1}
2533 };
2534
2535 //PGM 01/07/97 added rogue episodes
2536 //PGM 03/02/97 added dmatch episode
2537 episode_t rogueepisodes[] =
2538 {
2539 {"Introduction", 0, 1},
2540 {"Hell's Fortress", 1, 7},
2541 {"Corridors of Time", 8, 8},
2542 {"Deathmatch Arena", 16, 1}
2543 };
2544
2545 int startepisode;
2546 int startlevel;
2547 int maxplayers;
2548 qboolean m_serverInfoMessage = false;
2549 double m_serverInfoMessageTime;
2550
M_Menu_GameOptions_f(void)2551 void M_Menu_GameOptions_f (void)
2552 {
2553 key_dest = key_menu;
2554 m_state = m_gameoptions;
2555 m_entersound = true;
2556 if (maxplayers == 0)
2557 maxplayers = svs.maxclients;
2558 if (maxplayers < 2)
2559 maxplayers = svs.maxclientslimit;
2560 }
2561
2562
2563 int gameoptions_cursor_table[] = {40, 56, 64, 72, 80, 88, 96, 112, 120};
2564 #define NUM_GAMEOPTIONS 9
2565 int gameoptions_cursor;
2566
M_GameOptions_Draw(void)2567 void M_GameOptions_Draw (void)
2568 {
2569 qpic_t *p;
2570 int x;
2571
2572 M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
2573 p = Draw_CachePic ("gfx/p_multi.lmp");
2574 M_DrawPic ( (320-p->width)/2, 4, p);
2575
2576 M_DrawTextBox (152, 32, 10, 1);
2577 M_Print (160, 40, "begin game");
2578
2579 M_Print (0, 56, " Max players");
2580 M_Print (160, 56, va("%i", maxplayers) );
2581
2582 M_Print (0, 64, " Game Type");
2583 if (coop.value)
2584 M_Print (160, 64, "Cooperative");
2585 else
2586 M_Print (160, 64, "Deathmatch");
2587
2588 M_Print (0, 72, " Teamplay");
2589 if (rogue)
2590 {
2591 const char *msg;
2592
2593 switch((int)teamplay.value)
2594 {
2595 case 1: msg = "No Friendly Fire"; break;
2596 case 2: msg = "Friendly Fire"; break;
2597 case 3: msg = "Tag"; break;
2598 case 4: msg = "Capture the Flag"; break;
2599 case 5: msg = "One Flag CTF"; break;
2600 case 6: msg = "Three Team CTF"; break;
2601 default: msg = "Off"; break;
2602 }
2603 M_Print (160, 72, msg);
2604 }
2605 else
2606 {
2607 const char *msg;
2608
2609 switch((int)teamplay.value)
2610 {
2611 case 1: msg = "No Friendly Fire"; break;
2612 case 2: msg = "Friendly Fire"; break;
2613 default: msg = "Off"; break;
2614 }
2615 M_Print (160, 72, msg);
2616 }
2617
2618 M_Print (0, 80, " Skill");
2619 if (skill.value == 0)
2620 M_Print (160, 80, "Easy difficulty");
2621 else if (skill.value == 1)
2622 M_Print (160, 80, "Normal difficulty");
2623 else if (skill.value == 2)
2624 M_Print (160, 80, "Hard difficulty");
2625 else
2626 M_Print (160, 80, "Nightmare difficulty");
2627
2628 M_Print (0, 88, " Frag Limit");
2629 if (fraglimit.value == 0)
2630 M_Print (160, 88, "none");
2631 else
2632 M_Print (160, 88, va("%i frags", (int)fraglimit.value));
2633
2634 M_Print (0, 96, " Time Limit");
2635 if (timelimit.value == 0)
2636 M_Print (160, 96, "none");
2637 else
2638 M_Print (160, 96, va("%i minutes", (int)timelimit.value));
2639
2640 M_Print (0, 112, " Episode");
2641 //MED 01/06/97 added hipnotic episodes
2642 if (hipnotic)
2643 M_Print (160, 112, hipnoticepisodes[startepisode].description);
2644 //PGM 01/07/97 added rogue episodes
2645 else if (rogue)
2646 M_Print (160, 112, rogueepisodes[startepisode].description);
2647 else
2648 M_Print (160, 112, episodes[startepisode].description);
2649
2650 M_Print (0, 120, " Level");
2651 //MED 01/06/97 added hipnotic episodes
2652 if (hipnotic)
2653 {
2654 M_Print (160, 120, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].description);
2655 M_Print (160, 128, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name);
2656 }
2657 //PGM 01/07/97 added rogue episodes
2658 else if (rogue)
2659 {
2660 M_Print (160, 120, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].description);
2661 M_Print (160, 128, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name);
2662 }
2663 else
2664 {
2665 M_Print (160, 120, levels[episodes[startepisode].firstLevel + startlevel].description);
2666 M_Print (160, 128, levels[episodes[startepisode].firstLevel + startlevel].name);
2667 }
2668
2669 // line cursor
2670 M_DrawCharacter (144, gameoptions_cursor_table[gameoptions_cursor], 12+((int)(realtime*4)&1));
2671
2672 if (m_serverInfoMessage)
2673 {
2674 if ((realtime - m_serverInfoMessageTime) < 5.0)
2675 {
2676 x = (320-26*8)/2;
2677 M_DrawTextBox (x, 138, 24, 4);
2678 x += 8;
2679 M_Print (x, 146, " More than 4 players ");
2680 M_Print (x, 154, " requires using command ");
2681 M_Print (x, 162, "line parameters; please ");
2682 M_Print (x, 170, " see techinfo.txt. ");
2683 }
2684 else
2685 {
2686 m_serverInfoMessage = false;
2687 }
2688 }
2689 }
2690
2691
M_NetStart_Change(int dir)2692 void M_NetStart_Change (int dir)
2693 {
2694 int count;
2695
2696 switch (gameoptions_cursor)
2697 {
2698 case 1:
2699 maxplayers += dir;
2700 if (maxplayers > svs.maxclientslimit)
2701 {
2702 maxplayers = svs.maxclientslimit;
2703 m_serverInfoMessage = true;
2704 m_serverInfoMessageTime = realtime;
2705 }
2706 if (maxplayers < 2)
2707 maxplayers = 2;
2708 break;
2709
2710 case 2:
2711 Cvar_SetValue ("coop", coop.value ? 0 : 1);
2712 break;
2713
2714 case 3:
2715 if (rogue)
2716 count = 6;
2717 else
2718 count = 2;
2719
2720 Cvar_SetValue ("teamplay", teamplay.value + dir);
2721 if (teamplay.value > count)
2722 Cvar_SetValue ("teamplay", 0);
2723 else if (teamplay.value < 0)
2724 Cvar_SetValue ("teamplay", count);
2725 break;
2726
2727 case 4:
2728 Cvar_SetValue ("skill", skill.value + dir);
2729 if (skill.value > 3)
2730 Cvar_SetValue ("skill", 0);
2731 if (skill.value < 0)
2732 Cvar_SetValue ("skill", 3);
2733 break;
2734
2735 case 5:
2736 Cvar_SetValue ("fraglimit", fraglimit.value + dir*10);
2737 if (fraglimit.value > 100)
2738 Cvar_SetValue ("fraglimit", 0);
2739 if (fraglimit.value < 0)
2740 Cvar_SetValue ("fraglimit", 100);
2741 break;
2742
2743 case 6:
2744 Cvar_SetValue ("timelimit", timelimit.value + dir*5);
2745 if (timelimit.value > 60)
2746 Cvar_SetValue ("timelimit", 0);
2747 if (timelimit.value < 0)
2748 Cvar_SetValue ("timelimit", 60);
2749 break;
2750
2751 case 7:
2752 startepisode += dir;
2753 //MED 01/06/97 added hipnotic count
2754 if (hipnotic)
2755 count = 6;
2756 //PGM 01/07/97 added rogue count
2757 //PGM 03/02/97 added 1 for dmatch episode
2758 else if (rogue)
2759 count = 4;
2760 else if (registered.value)
2761 count = 7;
2762 else
2763 count = 2;
2764
2765 if (startepisode < 0)
2766 startepisode = count - 1;
2767
2768 if (startepisode >= count)
2769 startepisode = 0;
2770
2771 startlevel = 0;
2772 break;
2773
2774 case 8:
2775 startlevel += dir;
2776 //MED 01/06/97 added hipnotic episodes
2777 if (hipnotic)
2778 count = hipnoticepisodes[startepisode].levels;
2779 //PGM 01/06/97 added hipnotic episodes
2780 else if (rogue)
2781 count = rogueepisodes[startepisode].levels;
2782 else
2783 count = episodes[startepisode].levels;
2784
2785 if (startlevel < 0)
2786 startlevel = count - 1;
2787
2788 if (startlevel >= count)
2789 startlevel = 0;
2790 break;
2791 }
2792 }
2793
M_GameOptions_Key(int key)2794 void M_GameOptions_Key (int key)
2795 {
2796 switch (key)
2797 {
2798 case K_ESCAPE:
2799 M_Menu_Net_f ();
2800 break;
2801
2802 case K_UPARROW:
2803 S_LocalSound ("misc/menu1.wav");
2804 gameoptions_cursor--;
2805 if (gameoptions_cursor < 0)
2806 gameoptions_cursor = NUM_GAMEOPTIONS-1;
2807 break;
2808
2809 case K_DOWNARROW:
2810 S_LocalSound ("misc/menu1.wav");
2811 gameoptions_cursor++;
2812 if (gameoptions_cursor >= NUM_GAMEOPTIONS)
2813 gameoptions_cursor = 0;
2814 break;
2815
2816 case K_LEFTARROW:
2817 if (gameoptions_cursor == 0)
2818 break;
2819 S_LocalSound ("misc/menu3.wav");
2820 M_NetStart_Change (-1);
2821 break;
2822
2823 case K_RIGHTARROW:
2824 if (gameoptions_cursor == 0)
2825 break;
2826 S_LocalSound ("misc/menu3.wav");
2827 M_NetStart_Change (1);
2828 break;
2829
2830 case K_ENTER:
2831 S_LocalSound ("misc/menu2.wav");
2832 if (gameoptions_cursor == 0)
2833 {
2834 if (sv.active)
2835 Cbuf_AddText ("disconnect\n");
2836 Cbuf_AddText ("listen 0\n"); // so host_netport will be re-examined
2837 Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) );
2838 SCR_BeginLoadingPlaque ();
2839
2840 if (hipnotic)
2841 Cbuf_AddText ( va ("map %s\n", hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name) );
2842 else if (rogue)
2843 Cbuf_AddText ( va ("map %s\n", roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name) );
2844 else
2845 Cbuf_AddText ( va ("map %s\n", levels[episodes[startepisode].firstLevel + startlevel].name) );
2846
2847 return;
2848 }
2849
2850 M_NetStart_Change (1);
2851 break;
2852 }
2853 }
2854
2855 //=============================================================================
2856 /* SEARCH MENU */
2857
2858 qboolean searchComplete = false;
2859 double searchCompleteTime;
2860
M_Menu_Search_f(void)2861 void M_Menu_Search_f (void)
2862 {
2863 key_dest = key_menu;
2864 m_state = m_search;
2865 m_entersound = false;
2866 slistSilent = true;
2867 slistLocal = false;
2868 searchComplete = false;
2869 NET_Slist_f();
2870
2871 }
2872
2873
M_Search_Draw(void)2874 void M_Search_Draw (void)
2875 {
2876 qpic_t *p;
2877 int x;
2878
2879 p = Draw_CachePic ("gfx/p_multi.lmp");
2880 M_DrawPic ( (320-p->width)/2, 4, p);
2881 x = (320/2) - ((12*8)/2) + 4;
2882 M_DrawTextBox (x-8, 32, 12, 1);
2883 M_Print (x, 40, "Searching...");
2884
2885 if(slistInProgress)
2886 {
2887 NET_Poll();
2888 return;
2889 }
2890
2891 if (! searchComplete)
2892 {
2893 searchComplete = true;
2894 searchCompleteTime = realtime;
2895 }
2896
2897 if (hostCacheCount)
2898 {
2899 M_Menu_ServerList_f ();
2900 return;
2901 }
2902
2903 M_PrintWhite ((320/2) - ((22*8)/2), 64, "No Quake servers found");
2904 if ((realtime - searchCompleteTime) < 3.0)
2905 return;
2906
2907 M_Menu_LanConfig_f ();
2908 }
2909
2910
M_Search_Key(int key)2911 void M_Search_Key (int key)
2912 {
2913 }
2914
2915 //=============================================================================
2916 /* SLIST MENU */
2917
2918 int slist_cursor;
2919 qboolean slist_sorted;
2920
M_Menu_ServerList_f(void)2921 void M_Menu_ServerList_f (void)
2922 {
2923 key_dest = key_menu;
2924 m_state = m_slist;
2925 m_entersound = true;
2926 slist_cursor = 0;
2927 m_return_onerror = false;
2928 m_return_reason[0] = 0;
2929 slist_sorted = false;
2930 }
2931
2932
M_ServerList_Draw(void)2933 void M_ServerList_Draw (void)
2934 {
2935 int n;
2936 char string [64];
2937 qpic_t *p;
2938
2939 if (!slist_sorted)
2940 {
2941 if (hostCacheCount > 1)
2942 {
2943 int i,j;
2944 hostcache_t temp;
2945 for (i = 0; i < hostCacheCount; i++)
2946 for (j = i+1; j < hostCacheCount; j++)
2947 if (strcmp(hostcache[j].name, hostcache[i].name) < 0)
2948 {
2949 Q_memcpy(&temp, &hostcache[j], sizeof(hostcache_t));
2950 Q_memcpy(&hostcache[j], &hostcache[i], sizeof(hostcache_t));
2951 Q_memcpy(&hostcache[i], &temp, sizeof(hostcache_t));
2952 }
2953 }
2954 slist_sorted = true;
2955 }
2956
2957 p = Draw_CachePic ("gfx/p_multi.lmp");
2958 M_DrawPic ( (320-p->width)/2, 4, p);
2959 for (n = 0; n < hostCacheCount; n++)
2960 {
2961 if (hostcache[n].maxusers)
2962 sprintf(string, "%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers);
2963 else
2964 sprintf(string, "%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map);
2965 M_Print (16, 32 + 8*n, string);
2966 }
2967 M_DrawCharacter (0, 32 + slist_cursor*8, 12+((int)(realtime*4)&1));
2968
2969 if (*m_return_reason)
2970 M_PrintWhite (16, 148, m_return_reason);
2971 }
2972
2973
M_ServerList_Key(int k)2974 void M_ServerList_Key (int k)
2975 {
2976 switch (k)
2977 {
2978 case K_ESCAPE:
2979 M_Menu_LanConfig_f ();
2980 break;
2981
2982 case K_SPACE:
2983 M_Menu_Search_f ();
2984 break;
2985
2986 case K_UPARROW:
2987 case K_LEFTARROW:
2988 S_LocalSound ("misc/menu1.wav");
2989 slist_cursor--;
2990 if (slist_cursor < 0)
2991 slist_cursor = hostCacheCount - 1;
2992 break;
2993
2994 case K_DOWNARROW:
2995 case K_RIGHTARROW:
2996 S_LocalSound ("misc/menu1.wav");
2997 slist_cursor++;
2998 if (slist_cursor >= hostCacheCount)
2999 slist_cursor = 0;
3000 break;
3001
3002 case K_ENTER:
3003 S_LocalSound ("misc/menu2.wav");
3004 m_return_state = m_state;
3005 m_return_onerror = true;
3006 slist_sorted = false;
3007 key_dest = key_game;
3008 m_state = m_none;
3009 Cbuf_AddText ( va ("connect \"%s\"\n", hostcache[slist_cursor].cname) );
3010 break;
3011
3012 default:
3013 break;
3014 }
3015
3016 }
3017
3018 //=============================================================================
3019 /* Menu Subsystem */
3020
3021
M_Init(void)3022 void M_Init (void)
3023 {
3024 Cmd_AddCommand ("togglemenu", M_ToggleMenu_f);
3025
3026 Cmd_AddCommand ("menu_main", M_Menu_Main_f);
3027 Cmd_AddCommand ("menu_singleplayer", M_Menu_SinglePlayer_f);
3028 Cmd_AddCommand ("menu_load", M_Menu_Load_f);
3029 Cmd_AddCommand ("menu_save", M_Menu_Save_f);
3030 Cmd_AddCommand ("menu_multiplayer", M_Menu_MultiPlayer_f);
3031 Cmd_AddCommand ("menu_setup", M_Menu_Setup_f);
3032 Cmd_AddCommand ("menu_options", M_Menu_Options_f);
3033 Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
3034 Cmd_AddCommand ("menu_video", M_Menu_Video_f);
3035 Cmd_AddCommand ("help", M_Menu_Help_f);
3036 Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
3037 }
3038
3039
M_Draw(void)3040 void M_Draw (void)
3041 {
3042 if (m_state == m_none || key_dest != key_menu)
3043 return;
3044
3045 if (!m_recursiveDraw)
3046 {
3047 scr_copyeverything = 1;
3048
3049 if (scr_con_current)
3050 {
3051 Draw_ConsoleBackground (vid.height);
3052 VID_UnlockBuffer ();
3053 S_ExtraUpdate ();
3054 VID_LockBuffer ();
3055 }
3056 else
3057 Draw_FadeScreen ();
3058
3059 scr_fullupdate = 0;
3060 }
3061 else
3062 {
3063 m_recursiveDraw = false;
3064 }
3065
3066 switch (m_state)
3067 {
3068 case m_none:
3069 break;
3070
3071 case m_main:
3072 M_Main_Draw ();
3073 break;
3074
3075 case m_singleplayer:
3076 M_SinglePlayer_Draw ();
3077 break;
3078
3079 case m_load:
3080 M_Load_Draw ();
3081 break;
3082
3083 case m_save:
3084 M_Save_Draw ();
3085 break;
3086
3087 case m_multiplayer:
3088 M_MultiPlayer_Draw ();
3089 break;
3090
3091 case m_setup:
3092 M_Setup_Draw ();
3093 break;
3094
3095 case m_net:
3096 M_Net_Draw ();
3097 break;
3098
3099 case m_options:
3100 M_Options_Draw ();
3101 break;
3102
3103 case m_keys:
3104 M_Keys_Draw ();
3105 break;
3106
3107 case m_video:
3108 M_Video_Draw ();
3109 break;
3110
3111 case m_help:
3112 M_Help_Draw ();
3113 break;
3114
3115 case m_quit:
3116 M_Quit_Draw ();
3117 break;
3118
3119 case m_serialconfig:
3120 M_SerialConfig_Draw ();
3121 break;
3122
3123 case m_modemconfig:
3124 M_ModemConfig_Draw ();
3125 break;
3126
3127 case m_lanconfig:
3128 M_LanConfig_Draw ();
3129 break;
3130
3131 case m_gameoptions:
3132 M_GameOptions_Draw ();
3133 break;
3134
3135 case m_search:
3136 M_Search_Draw ();
3137 break;
3138
3139 case m_slist:
3140 M_ServerList_Draw ();
3141 break;
3142 }
3143
3144 if (m_entersound)
3145 {
3146 S_LocalSound ("misc/menu2.wav");
3147 m_entersound = false;
3148 }
3149
3150 VID_UnlockBuffer ();
3151 S_ExtraUpdate ();
3152 VID_LockBuffer ();
3153 }
3154
3155
M_Keydown(int key)3156 void M_Keydown (int key)
3157 {
3158 switch (m_state)
3159 {
3160 case m_none:
3161 return;
3162
3163 case m_main:
3164 M_Main_Key (key);
3165 return;
3166
3167 case m_singleplayer:
3168 M_SinglePlayer_Key (key);
3169 return;
3170
3171 case m_load:
3172 M_Load_Key (key);
3173 return;
3174
3175 case m_save:
3176 M_Save_Key (key);
3177 return;
3178
3179 case m_multiplayer:
3180 M_MultiPlayer_Key (key);
3181 return;
3182
3183 case m_setup:
3184 M_Setup_Key (key);
3185 return;
3186
3187 case m_net:
3188 M_Net_Key (key);
3189 return;
3190
3191 case m_options:
3192 M_Options_Key (key);
3193 return;
3194
3195 case m_keys:
3196 M_Keys_Key (key);
3197 return;
3198
3199 case m_video:
3200 M_Video_Key (key);
3201 return;
3202
3203 case m_help:
3204 M_Help_Key (key);
3205 return;
3206
3207 case m_quit:
3208 M_Quit_Key (key);
3209 return;
3210
3211 case m_serialconfig:
3212 M_SerialConfig_Key (key);
3213 return;
3214
3215 case m_modemconfig:
3216 M_ModemConfig_Key (key);
3217 return;
3218
3219 case m_lanconfig:
3220 M_LanConfig_Key (key);
3221 return;
3222
3223 case m_gameoptions:
3224 M_GameOptions_Key (key);
3225 return;
3226
3227 case m_search:
3228 M_Search_Key (key);
3229 break;
3230
3231 case m_slist:
3232 M_ServerList_Key (key);
3233 return;
3234 }
3235 }
3236
3237
M_ConfigureNetSubsystem(void)3238 void M_ConfigureNetSubsystem(void)
3239 {
3240 // enable/disable net systems to match desired config
3241
3242 Cbuf_AddText ("stopdemo\n");
3243 if (SerialConfig || DirectConfig)
3244 {
3245 Cbuf_AddText ("com1 enable\n");
3246 }
3247
3248 if (IPXConfig || TCPIPConfig)
3249 net_hostport = lanConfig_port;
3250 }
3251