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