Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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_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
*/
112
void M_DrawCharacter (int cx, int line, int num)
113
{
114
	Draw_Character ( cx + ((vid.width - 320)>>1), line, num);
115
}
116
 
117
void M_Print (int cx, int cy, char *str)
118
{
119
	while (*str)
120
	{
121
		M_DrawCharacter (cx, cy, (*str)+128);
122
		str++;
123
		cx += 8;
124
	}
125
}
126
 
127
void M_PrintWhite (int cx, int cy, char *str)
128
{
129
	while (*str)
130
	{
131
		M_DrawCharacter (cx, cy, *str);
132
		str++;
133
		cx += 8;
134
	}
135
}
136
 
137
void M_DrawTransPic (int x, int y, qpic_t *pic)
138
{
139
	Draw_TransPic (x + ((vid.width - 320)>>1), y, pic);
140
}
141
 
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
 
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
 
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
 
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
*/
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
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
467
			if (m_filenames[i][j] == '_')
468
				m_filenames[i][j] = ' ';
469
		loadable[i] = true;
470
		fclose (f);
471
	}
472
}
473
 
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
 
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
 
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
 
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
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
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
 
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
 
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
 
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
 
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
 
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
 
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
1159
		M_DrawCharacter (x + i*8, y, 129);
1160
	M_DrawCharacter (x+i*8, y, 130);
1161
	M_DrawCharacter (x + (SLIDER_RANGE-1)*8 * range, y, 131);
1162
}
1163
 
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
 
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, lookspring.value);
1219
 
1220
	M_Print (16, 120, "            Lookstrafe");
1221
	M_DrawCheckbox (220, 120, 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
 
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
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
 
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
 
1350
void M_FindKeysForCommand (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
 
1376
void M_UnbindCommand (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
 
1395
void M_Keys_Draw (void)
1396
{
1397
	int		i, l;
1398
	int		keys[2];
1399
	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
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
 
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 >= 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
 
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
 
1517
void M_Video_Draw (void)
1518
{
1519
	(*vid_menudrawfn) ();
1520
}
1521
 
1522
 
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
 
1535
void M_Menu_Help_f (void)
1536
{
1537
	key_dest = key_menu;
1538
	m_state = m_help;
1539
	m_entersound = true;
1540
	help_page = 0;
1541
}
1542
 
1543
 
1544
 
1545
void M_Help_Draw (void)
1546
{
1547
	M_DrawPic (0, 0, Draw_CachePic ( va("gfx/help%i.lmp", help_page)) );
1548
}
1549
 
1550
 
1551
void M_Help_Key (int key)
1552
{
1553
	switch (key)
1554
	{
1555
	case K_ESCAPE:
1556
		M_Menu_Main_f ();
1557
		break;
1558
 
1559
	case K_UPARROW:
1560
	case K_RIGHTARROW:
1561
		m_entersound = true;
1562
		if (++help_page >= NUM_HELP_PAGES)
1563
			help_page = 0;
1564
		break;
1565
 
1566
	case K_DOWNARROW:
1567
	case K_LEFTARROW:
1568
		m_entersound = true;
1569
		if (--help_page < 0)
1570
			help_page = NUM_HELP_PAGES-1;
1571
		break;
1572
	}
1573
 
1574
}
1575
 
1576
//=============================================================================
1577
/* QUIT MENU */
1578
 
1579
int		msgNumber;
1580
int		m_quit_prevstate;
1581
qboolean	wasInMenus;
1582
 
1583
#ifndef	_WIN32
1584
char *quitMessage [] =
1585
{
1586
/* .........1.........2.... */
1587
  "  Are you gonna quit    ",
1588
  "  this game just like   ",
1589
  "   everything else?     ",
1590
  "                        ",
1591
 
1592
  " Milord, methinks that  ",
1593
  "   thou art a lowly     ",
1594
  " quitter. Is this true? ",
1595
  "                        ",
1596
 
1597
  " Do I need to bust your ",
1598
  "  face open for trying  ",
1599
  "        to quit?        ",
1600
  "                        ",
1601
 
1602
  " Man, I oughta smack you",
1603
  "   for trying to quit!  ",
1604
  "     Press Y to get     ",
1605
  "      smacked out.      ",
1606
 
1607
  " Press Y to quit like a ",
1608
  "   big loser in life.   ",
1609
  "  Press N to stay proud ",
1610
  "    and successful!     ",
1611
 
1612
  "   If you press Y to    ",
1613
  "  quit, I will summon   ",
1614
  "  Satan all over your   ",
1615
  "      hard drive!       ",
1616
 
1617
  "  Um, Asmodeus dislikes ",
1618
  " his children trying to ",
1619
  " quit. Press Y to return",
1620
  "   to your Tinkertoys.  ",
1621
 
1622
  "  If you quit now, I'll ",
1623
  "  throw a blanket-party ",
1624
  "   for you next time!   ",
1625
  "                        "
1626
};
1627
#endif
1628
 
1629
void M_Menu_Quit_f (void)
1630
{
1631
	if (m_state == m_quit)
1632
		return;
1633
	wasInMenus = (key_dest == key_menu);
1634
	key_dest = key_menu;
1635
	m_quit_prevstate = m_state;
1636
	m_state = m_quit;
1637
	m_entersound = true;
1638
	msgNumber = rand()&7;
1639
}
1640
 
1641
 
1642
void M_Quit_Key (int key)
1643
{
1644
	switch (key)
1645
	{
1646
	case K_ESCAPE:
1647
	case 'n':
1648
	case 'N':
1649
		if (wasInMenus)
1650
		{
1651
			m_state = m_quit_prevstate;
1652
			m_entersound = true;
1653
		}
1654
		else
1655
		{
1656
			key_dest = key_game;
1657
			m_state = m_none;
1658
		}
1659
		break;
1660
 
1661
	case 'Y':
1662
	case 'y':
1663
		key_dest = key_console;
1664
		Host_Quit_f ();
1665
		break;
1666
 
1667
	default:
1668
		break;
1669
	}
1670
 
1671
}
1672
 
1673
 
1674
void M_Quit_Draw (void)
1675
{
1676
	if (wasInMenus)
1677
	{
1678
		m_state = m_quit_prevstate;
1679
		m_recursiveDraw = true;
1680
		M_Draw ();
1681
		m_state = m_quit;
1682
	}
1683
 
1684
#ifdef _WIN32
1685
	M_DrawTextBox (0, 0, 38, 23);
1686
	M_PrintWhite (16, 12,  "  Quake version 1.09 by id Software\n\n");
1687
	M_PrintWhite (16, 28,  "Programming        Art \n");
1688
	M_Print (16, 36,  " John Carmack       Adrian Carmack\n");
1689
	M_Print (16, 44,  " Michael Abrash     Kevin Cloud\n");
1690
	M_Print (16, 52,  " John Cash          Paul Steed\n");
1691
	M_Print (16, 60,  " Dave 'Zoid' Kirsch\n");
1692
	M_PrintWhite (16, 68,  "Design             Biz\n");
1693
	M_Print (16, 76,  " John Romero        Jay Wilbur\n");
1694
	M_Print (16, 84,  " Sandy Petersen     Mike Wilson\n");
1695
	M_Print (16, 92,  " American McGee     Donna Jackson\n");
1696
	M_Print (16, 100,  " Tim Willits        Todd Hollenshead\n");
1697
	M_PrintWhite (16, 108, "Support            Projects\n");
1698
	M_Print (16, 116, " Barrett Alexander  Shawn Green\n");
1699
	M_PrintWhite (16, 124, "Sound Effects\n");
1700
	M_Print (16, 132, " Trent Reznor and Nine Inch Nails\n\n");
1701
	M_PrintWhite (16, 140, "Quake is a trademark of Id Software,\n");
1702
	M_PrintWhite (16, 148, "inc., (c)1996 Id Software, inc. All\n");
1703
	M_PrintWhite (16, 156, "rights reserved. NIN logo is a\n");
1704
	M_PrintWhite (16, 164, "registered trademark licensed to\n");
1705
	M_PrintWhite (16, 172, "Nothing Interactive, Inc. All rights\n");
1706
	M_PrintWhite (16, 180, "reserved. Press y to exit\n");
1707
#else
1708
	M_DrawTextBox (56, 76, 24, 4);
1709
	M_Print (64, 84,  quitMessage[msgNumber*4+0]);
1710
	M_Print (64, 92,  quitMessage[msgNumber*4+1]);
1711
	M_Print (64, 100, quitMessage[msgNumber*4+2]);
1712
	M_Print (64, 108, quitMessage[msgNumber*4+3]);
1713
#endif
1714
}
1715
 
1716
//=============================================================================
1717
 
1718
/* SERIAL CONFIG MENU */
1719
 
1720
int		serialConfig_cursor;
1721
int		serialConfig_cursor_table[] = {48, 64, 80, 96, 112, 132};
1722
#define	NUM_SERIALCONFIG_CMDS	6
1723
 
1724
static int ISA_uarts[]	= {0x3f8,0x2f8,0x3e8,0x2e8};
1725
static int ISA_IRQs[]	= {4,3,4,3};
1726
int serialConfig_baudrate[] = {9600,14400,19200,28800,38400,57600};
1727
 
1728
int		serialConfig_comport;
1729
int		serialConfig_irq ;
1730
int		serialConfig_baud;
1731
char	serialConfig_phone[16];
1732
 
1733
void M_Menu_SerialConfig_f (void)
1734
{
1735
	int		n;
1736
	int		port;
1737
	int		baudrate;
1738
	qboolean	useModem;
1739
 
1740
	key_dest = key_menu;
1741
	m_state = m_serialconfig;
1742
	m_entersound = true;
1743
	if (JoiningGame && SerialConfig)
1744
		serialConfig_cursor = 4;
1745
	else
1746
		serialConfig_cursor = 5;
1747
 
1748
	(*GetComPortConfig) (0, &port, &serialConfig_irq, &baudrate, &useModem);
1749
 
1750
	// map uart's port to COMx
1751
	for (n = 0; n < 4; n++)
1752
		if (ISA_uarts[n] == port)
1753
			break;
1754
	if (n == 4)
1755
	{
1756
		n = 0;
1757
		serialConfig_irq = 4;
1758
	}
1759
	serialConfig_comport = n + 1;
1760
 
1761
	// map baudrate to index
1762
	for (n = 0; n < 6; n++)
1763
		if (serialConfig_baudrate[n] == baudrate)
1764
			break;
1765
	if (n == 6)
1766
		n = 5;
1767
	serialConfig_baud = n;
1768
 
1769
	m_return_onerror = false;
1770
	m_return_reason[0] = 0;
1771
}
1772
 
1773
 
1774
void M_SerialConfig_Draw (void)
1775
{
1776
	qpic_t	*p;
1777
	int		basex;
1778
	char	*startJoin;
1779
	char	*directModem;
1780
 
1781
	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
1782
	p = Draw_CachePic ("gfx/p_multi.lmp");
1783
	basex = (320-p->width)/2;
1784
	M_DrawPic (basex, 4, p);
1785
 
1786
	if (StartingGame)
1787
		startJoin = "New Game";
1788
	else
1789
		startJoin = "Join Game";
1790
	if (SerialConfig)
1791
		directModem = "Modem";
1792
	else
1793
		directModem = "Direct Connect";
1794
	M_Print (basex, 32, va ("%s - %s", startJoin, directModem));
1795
	basex += 8;
1796
 
1797
	M_Print (basex, serialConfig_cursor_table[0], "Port");
1798
	M_DrawTextBox (160, 40, 4, 1);
1799
	M_Print (168, serialConfig_cursor_table[0], va("COM%u", serialConfig_comport));
1800
 
1801
	M_Print (basex, serialConfig_cursor_table[1], "IRQ");
1802
	M_DrawTextBox (160, serialConfig_cursor_table[1]-8, 1, 1);
1803
	M_Print (168, serialConfig_cursor_table[1], va("%u", serialConfig_irq));
1804
 
1805
	M_Print (basex, serialConfig_cursor_table[2], "Baud");
1806
	M_DrawTextBox (160, serialConfig_cursor_table[2]-8, 5, 1);
1807
	M_Print (168, serialConfig_cursor_table[2], va("%u", serialConfig_baudrate[serialConfig_baud]));
1808
 
1809
	if (SerialConfig)
1810
	{
1811
		M_Print (basex, serialConfig_cursor_table[3], "Modem Setup...");
1812
		if (JoiningGame)
1813
		{
1814
			M_Print (basex, serialConfig_cursor_table[4], "Phone number");
1815
			M_DrawTextBox (160, serialConfig_cursor_table[4]-8, 16, 1);
1816
			M_Print (168, serialConfig_cursor_table[4], serialConfig_phone);
1817
		}
1818
	}
1819
 
1820
	if (JoiningGame)
1821
	{
1822
		M_DrawTextBox (basex, serialConfig_cursor_table[5]-8, 7, 1);
1823
		M_Print (basex+8, serialConfig_cursor_table[5], "Connect");
1824
	}
1825
	else
1826
	{
1827
		M_DrawTextBox (basex, serialConfig_cursor_table[5]-8, 2, 1);
1828
		M_Print (basex+8, serialConfig_cursor_table[5], "OK");
1829
	}
1830
 
1831
	M_DrawCharacter (basex-8, serialConfig_cursor_table [serialConfig_cursor], 12+((int)(realtime*4)&1));
1832
 
1833
	if (serialConfig_cursor == 4)
1834
		M_DrawCharacter (168 + 8*strlen(serialConfig_phone), serialConfig_cursor_table [serialConfig_cursor], 10+((int)(realtime*4)&1));
1835
 
1836
	if (*m_return_reason)
1837
		M_PrintWhite (basex, 148, m_return_reason);
1838
}
1839
 
1840
 
1841
void M_SerialConfig_Key (int key)
1842
{
1843
	int		l;
1844
 
1845
	switch (key)
1846
	{
1847
	case K_ESCAPE:
1848
		M_Menu_Net_f ();
1849
		break;
1850
 
1851
	case K_UPARROW:
1852
		S_LocalSound ("misc/menu1.wav");
1853
		serialConfig_cursor--;
1854
		if (serialConfig_cursor < 0)
1855
			serialConfig_cursor = NUM_SERIALCONFIG_CMDS-1;
1856
		break;
1857
 
1858
	case K_DOWNARROW:
1859
		S_LocalSound ("misc/menu1.wav");
1860
		serialConfig_cursor++;
1861
		if (serialConfig_cursor >= NUM_SERIALCONFIG_CMDS)
1862
			serialConfig_cursor = 0;
1863
		break;
1864
 
1865
	case K_LEFTARROW:
1866
		if (serialConfig_cursor > 2)
1867
			break;
1868
		S_LocalSound ("misc/menu3.wav");
1869
 
1870
		if (serialConfig_cursor == 0)
1871
		{
1872
			serialConfig_comport--;
1873
			if (serialConfig_comport == 0)
1874
				serialConfig_comport = 4;
1875
			serialConfig_irq = ISA_IRQs[serialConfig_comport-1];
1876
		}
1877
 
1878
		if (serialConfig_cursor == 1)
1879
		{
1880
			serialConfig_irq--;
1881
			if (serialConfig_irq == 6)
1882
				serialConfig_irq = 5;
1883
			if (serialConfig_irq == 1)
1884
				serialConfig_irq = 7;
1885
		}
1886
 
1887
		if (serialConfig_cursor == 2)
1888
		{
1889
			serialConfig_baud--;
1890
			if (serialConfig_baud < 0)
1891
				serialConfig_baud = 5;
1892
		}
1893
 
1894
		break;
1895
 
1896
	case K_RIGHTARROW:
1897
		if (serialConfig_cursor > 2)
1898
			break;
1899
forward:
1900
		S_LocalSound ("misc/menu3.wav");
1901
 
1902
		if (serialConfig_cursor == 0)
1903
		{
1904
			serialConfig_comport++;
1905
			if (serialConfig_comport > 4)
1906
				serialConfig_comport = 1;
1907
			serialConfig_irq = ISA_IRQs[serialConfig_comport-1];
1908
		}
1909
 
1910
		if (serialConfig_cursor == 1)
1911
		{
1912
			serialConfig_irq++;
1913
			if (serialConfig_irq == 6)
1914
				serialConfig_irq = 7;
1915
			if (serialConfig_irq == 8)
1916
				serialConfig_irq = 2;
1917
		}
1918
 
1919
		if (serialConfig_cursor == 2)
1920
		{
1921
			serialConfig_baud++;
1922
			if (serialConfig_baud > 5)
1923
				serialConfig_baud = 0;
1924
		}
1925
 
1926
		break;
1927
 
1928
	case K_ENTER:
1929
		if (serialConfig_cursor < 3)
1930
			goto forward;
1931
 
1932
		m_entersound = true;
1933
 
1934
		if (serialConfig_cursor == 3)
1935
		{
1936
			(*SetComPortConfig) (0, ISA_uarts[serialConfig_comport-1], serialConfig_irq, serialConfig_baudrate[serialConfig_baud], SerialConfig);
1937
 
1938
			M_Menu_ModemConfig_f ();
1939
			break;
1940
		}
1941
 
1942
		if (serialConfig_cursor == 4)
1943
		{
1944
			serialConfig_cursor = 5;
1945
			break;
1946
		}
1947
 
1948
		// serialConfig_cursor == 5 (OK/CONNECT)
1949
		(*SetComPortConfig) (0, ISA_uarts[serialConfig_comport-1], serialConfig_irq, serialConfig_baudrate[serialConfig_baud], SerialConfig);
1950
 
1951
		M_ConfigureNetSubsystem ();
1952
 
1953
		if (StartingGame)
1954
		{
1955
			M_Menu_GameOptions_f ();
1956
			break;
1957
		}
1958
 
1959
		m_return_state = m_state;
1960
		m_return_onerror = true;
1961
		key_dest = key_game;
1962
		m_state = m_none;
1963
 
1964
		if (SerialConfig)
1965
			Cbuf_AddText (va ("connect \"%s\"\n", serialConfig_phone));
1966
		else
1967
			Cbuf_AddText ("connect\n");
1968
		break;
1969
 
1970
	case K_BACKSPACE:
1971
		if (serialConfig_cursor == 4)
1972
		{
1973
			if (strlen(serialConfig_phone))
1974
				serialConfig_phone[strlen(serialConfig_phone)-1] = 0;
1975
		}
1976
		break;
1977
 
1978
	default:
1979
		if (key < 32 || key > 127)
1980
			break;
1981
		if (serialConfig_cursor == 4)
1982
		{
1983
			l = strlen(serialConfig_phone);
1984
			if (l < 15)
1985
			{
1986
				serialConfig_phone[l+1] = 0;
1987
				serialConfig_phone[l] = key;
1988
			}
1989
		}
1990
	}
1991
 
1992
	if (DirectConfig && (serialConfig_cursor == 3 || serialConfig_cursor == 4))
1993
		if (key == K_UPARROW)
1994
			serialConfig_cursor = 2;
1995
		else
1996
			serialConfig_cursor = 5;
1997
 
1998
	if (SerialConfig && StartingGame && serialConfig_cursor == 4)
1999
		if (key == K_UPARROW)
2000
			serialConfig_cursor = 3;
2001
		else
2002
			serialConfig_cursor = 5;
2003
}
2004
 
2005
//=============================================================================
2006
/* MODEM CONFIG MENU */
2007
 
2008
int		modemConfig_cursor;
2009
int		modemConfig_cursor_table [] = {40, 56, 88, 120, 156};
2010
#define NUM_MODEMCONFIG_CMDS	5
2011
 
2012
char	modemConfig_dialing;
2013
char	modemConfig_clear [16];
2014
char	modemConfig_init [32];
2015
char	modemConfig_hangup [16];
2016
 
2017
void M_Menu_ModemConfig_f (void)
2018
{
2019
	key_dest = key_menu;
2020
	m_state = m_modemconfig;
2021
	m_entersound = true;
2022
	(*GetModemConfig) (0, &modemConfig_dialing, modemConfig_clear, modemConfig_init, modemConfig_hangup);
2023
}
2024
 
2025
 
2026
void M_ModemConfig_Draw (void)
2027
{
2028
	qpic_t	*p;
2029
	int		basex;
2030
 
2031
	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
2032
	p = Draw_CachePic ("gfx/p_multi.lmp");
2033
	basex = (320-p->width)/2;
2034
	M_DrawPic (basex, 4, p);
2035
	basex += 8;
2036
 
2037
	if (modemConfig_dialing == 'P')
2038
		M_Print (basex, modemConfig_cursor_table[0], "Pulse Dialing");
2039
	else
2040
		M_Print (basex, modemConfig_cursor_table[0], "Touch Tone Dialing");
2041
 
2042
	M_Print (basex, modemConfig_cursor_table[1], "Clear");
2043
	M_DrawTextBox (basex, modemConfig_cursor_table[1]+4, 16, 1);
2044
	M_Print (basex+8, modemConfig_cursor_table[1]+12, modemConfig_clear);
2045
	if (modemConfig_cursor == 1)
2046
		M_DrawCharacter (basex+8 + 8*strlen(modemConfig_clear), modemConfig_cursor_table[1]+12, 10+((int)(realtime*4)&1));
2047
 
2048
	M_Print (basex, modemConfig_cursor_table[2], "Init");
2049
	M_DrawTextBox (basex, modemConfig_cursor_table[2]+4, 30, 1);
2050
	M_Print (basex+8, modemConfig_cursor_table[2]+12, modemConfig_init);
2051
	if (modemConfig_cursor == 2)
2052
		M_DrawCharacter (basex+8 + 8*strlen(modemConfig_init), modemConfig_cursor_table[2]+12, 10+((int)(realtime*4)&1));
2053
 
2054
	M_Print (basex, modemConfig_cursor_table[3], "Hangup");
2055
	M_DrawTextBox (basex, modemConfig_cursor_table[3]+4, 16, 1);
2056
	M_Print (basex+8, modemConfig_cursor_table[3]+12, modemConfig_hangup);
2057
	if (modemConfig_cursor == 3)
2058
		M_DrawCharacter (basex+8 + 8*strlen(modemConfig_hangup), modemConfig_cursor_table[3]+12, 10+((int)(realtime*4)&1));
2059
 
2060
	M_DrawTextBox (basex, modemConfig_cursor_table[4]-8, 2, 1);
2061
	M_Print (basex+8, modemConfig_cursor_table[4], "OK");
2062
 
2063
	M_DrawCharacter (basex-8, modemConfig_cursor_table [modemConfig_cursor], 12+((int)(realtime*4)&1));
2064
}
2065
 
2066
 
2067
void M_ModemConfig_Key (int key)
2068
{
2069
	int		l;
2070
 
2071
	switch (key)
2072
	{
2073
	case K_ESCAPE:
2074
		M_Menu_SerialConfig_f ();
2075
		break;
2076
 
2077
	case K_UPARROW:
2078
		S_LocalSound ("misc/menu1.wav");
2079
		modemConfig_cursor--;
2080
		if (modemConfig_cursor < 0)
2081
			modemConfig_cursor = NUM_MODEMCONFIG_CMDS-1;
2082
		break;
2083
 
2084
	case K_DOWNARROW:
2085
		S_LocalSound ("misc/menu1.wav");
2086
		modemConfig_cursor++;
2087
		if (modemConfig_cursor >= NUM_MODEMCONFIG_CMDS)
2088
			modemConfig_cursor = 0;
2089
		break;
2090
 
2091
	case K_LEFTARROW:
2092
	case K_RIGHTARROW:
2093
		if (modemConfig_cursor == 0)
2094
		{
2095
			if (modemConfig_dialing == 'P')
2096
				modemConfig_dialing = 'T';
2097
			else
2098
				modemConfig_dialing = 'P';
2099
			S_LocalSound ("misc/menu1.wav");
2100
		}
2101
		break;
2102
 
2103
	case K_ENTER:
2104
		if (modemConfig_cursor == 0)
2105
		{
2106
			if (modemConfig_dialing == 'P')
2107
				modemConfig_dialing = 'T';
2108
			else
2109
				modemConfig_dialing = 'P';
2110
			m_entersound = true;
2111
		}
2112
 
2113
		if (modemConfig_cursor == 4)
2114
		{
2115
			(*SetModemConfig) (0, va ("%c", modemConfig_dialing), modemConfig_clear, modemConfig_init, modemConfig_hangup);
2116
			m_entersound = true;
2117
			M_Menu_SerialConfig_f ();
2118
		}
2119
		break;
2120
 
2121
	case K_BACKSPACE:
2122
		if (modemConfig_cursor == 1)
2123
		{
2124
			if (strlen(modemConfig_clear))
2125
				modemConfig_clear[strlen(modemConfig_clear)-1] = 0;
2126
		}
2127
 
2128
		if (modemConfig_cursor == 2)
2129
		{
2130
			if (strlen(modemConfig_init))
2131
				modemConfig_init[strlen(modemConfig_init)-1] = 0;
2132
		}
2133
 
2134
		if (modemConfig_cursor == 3)
2135
		{
2136
			if (strlen(modemConfig_hangup))
2137
				modemConfig_hangup[strlen(modemConfig_hangup)-1] = 0;
2138
		}
2139
		break;
2140
 
2141
	default:
2142
		if (key < 32 || key > 127)
2143
			break;
2144
 
2145
		if (modemConfig_cursor == 1)
2146
		{
2147
			l = strlen(modemConfig_clear);
2148
			if (l < 15)
2149
			{
2150
				modemConfig_clear[l+1] = 0;
2151
				modemConfig_clear[l] = key;
2152
			}
2153
		}
2154
 
2155
		if (modemConfig_cursor == 2)
2156
		{
2157
			l = strlen(modemConfig_init);
2158
			if (l < 29)
2159
			{
2160
				modemConfig_init[l+1] = 0;
2161
				modemConfig_init[l] = key;
2162
			}
2163
		}
2164
 
2165
		if (modemConfig_cursor == 3)
2166
		{
2167
			l = strlen(modemConfig_hangup);
2168
			if (l < 15)
2169
			{
2170
				modemConfig_hangup[l+1] = 0;
2171
				modemConfig_hangup[l] = key;
2172
			}
2173
		}
2174
	}
2175
}
2176
 
2177
//=============================================================================
2178
/* LAN CONFIG MENU */
2179
 
2180
int		lanConfig_cursor = -1;
2181
int		lanConfig_cursor_table [] = {72, 92, 124};
2182
#define NUM_LANCONFIG_CMDS	3
2183
 
2184
int 	lanConfig_port;
2185
char	lanConfig_portname[6];
2186
char	lanConfig_joinname[22];
2187
 
2188
void M_Menu_LanConfig_f (void)
2189
{
2190
	key_dest = key_menu;
2191
	m_state = m_lanconfig;
2192
	m_entersound = true;
2193
	if (lanConfig_cursor == -1)
2194
	{
2195
		if (JoiningGame && TCPIPConfig)
2196
			lanConfig_cursor = 2;
2197
		else
2198
			lanConfig_cursor = 1;
2199
	}
2200
	if (StartingGame && lanConfig_cursor == 2)
2201
		lanConfig_cursor = 1;
2202
	lanConfig_port = DEFAULTnet_hostport;
2203
	sprintf(lanConfig_portname, "%u", lanConfig_port);
2204
 
2205
	m_return_onerror = false;
2206
	m_return_reason[0] = 0;
2207
}
2208
 
2209
 
2210
void M_LanConfig_Draw (void)
2211
{
2212
	qpic_t	*p;
2213
	int		basex;
2214
	char	*startJoin;
2215
	char	*protocol;
2216
 
2217
	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
2218
	p = Draw_CachePic ("gfx/p_multi.lmp");
2219
	basex = (320-p->width)/2;
2220
	M_DrawPic (basex, 4, p);
2221
 
2222
	if (StartingGame)
2223
		startJoin = "New Game";
2224
	else
2225
		startJoin = "Join Game";
2226
	if (IPXConfig)
2227
		protocol = "IPX";
2228
	else
2229
		protocol = "TCP/IP";
2230
	M_Print (basex, 32, va ("%s - %s", startJoin, protocol));
2231
	basex += 8;
2232
 
2233
	M_Print (basex, 52, "Address:");
2234
	if (IPXConfig)
2235
		M_Print (basex+9*8, 52, my_ipx_address);
2236
	else
2237
		M_Print (basex+9*8, 52, my_tcpip_address);
2238
 
2239
	M_Print (basex, lanConfig_cursor_table[0], "Port");
2240
	M_DrawTextBox (basex+8*8, lanConfig_cursor_table[0]-8, 6, 1);
2241
	M_Print (basex+9*8, lanConfig_cursor_table[0], lanConfig_portname);
2242
 
2243
	if (JoiningGame)
2244
	{
2245
		M_Print (basex, lanConfig_cursor_table[1], "Search for local games...");
2246
		M_Print (basex, 108, "Join game at:");
2247
		M_DrawTextBox (basex+8, lanConfig_cursor_table[2]-8, 22, 1);
2248
		M_Print (basex+16, lanConfig_cursor_table[2], lanConfig_joinname);
2249
	}
2250
	else
2251
	{
2252
		M_DrawTextBox (basex, lanConfig_cursor_table[1]-8, 2, 1);
2253
		M_Print (basex+8, lanConfig_cursor_table[1], "OK");
2254
	}
2255
 
2256
	M_DrawCharacter (basex-8, lanConfig_cursor_table [lanConfig_cursor], 12+((int)(realtime*4)&1));
2257
 
2258
	if (lanConfig_cursor == 0)
2259
		M_DrawCharacter (basex+9*8 + 8*strlen(lanConfig_portname), lanConfig_cursor_table [0], 10+((int)(realtime*4)&1));
2260
 
2261
	if (lanConfig_cursor == 2)
2262
		M_DrawCharacter (basex+16 + 8*strlen(lanConfig_joinname), lanConfig_cursor_table [2], 10+((int)(realtime*4)&1));
2263
 
2264
	if (*m_return_reason)
2265
		M_PrintWhite (basex, 148, m_return_reason);
2266
}
2267
 
2268
 
2269
void M_LanConfig_Key (int key)
2270
{
2271
	int		l;
2272
 
2273
	switch (key)
2274
	{
2275
	case K_ESCAPE:
2276
		M_Menu_Net_f ();
2277
		break;
2278
 
2279
	case K_UPARROW:
2280
		S_LocalSound ("misc/menu1.wav");
2281
		lanConfig_cursor--;
2282
		if (lanConfig_cursor < 0)
2283
			lanConfig_cursor = NUM_LANCONFIG_CMDS-1;
2284
		break;
2285
 
2286
	case K_DOWNARROW:
2287
		S_LocalSound ("misc/menu1.wav");
2288
		lanConfig_cursor++;
2289
		if (lanConfig_cursor >= NUM_LANCONFIG_CMDS)
2290
			lanConfig_cursor = 0;
2291
		break;
2292
 
2293
	case K_ENTER:
2294
		if (lanConfig_cursor == 0)
2295
			break;
2296
 
2297
		m_entersound = true;
2298
 
2299
		M_ConfigureNetSubsystem ();
2300
 
2301
		if (lanConfig_cursor == 1)
2302
		{
2303
			if (StartingGame)
2304
			{
2305
				M_Menu_GameOptions_f ();
2306
				break;
2307
			}
2308
			M_Menu_Search_f();
2309
			break;
2310
		}
2311
 
2312
		if (lanConfig_cursor == 2)
2313
		{
2314
			m_return_state = m_state;
2315
			m_return_onerror = true;
2316
			key_dest = key_game;
2317
			m_state = m_none;
2318
			Cbuf_AddText ( va ("connect \"%s\"\n", lanConfig_joinname) );
2319
			break;
2320
		}
2321
 
2322
		break;
2323
 
2324
	case K_BACKSPACE:
2325
		if (lanConfig_cursor == 0)
2326
		{
2327
			if (strlen(lanConfig_portname))
2328
				lanConfig_portname[strlen(lanConfig_portname)-1] = 0;
2329
		}
2330
 
2331
		if (lanConfig_cursor == 2)
2332
		{
2333
			if (strlen(lanConfig_joinname))
2334
				lanConfig_joinname[strlen(lanConfig_joinname)-1] = 0;
2335
		}
2336
		break;
2337
 
2338
	default:
2339
		if (key < 32 || key > 127)
2340
			break;
2341
 
2342
		if (lanConfig_cursor == 2)
2343
		{
2344
			l = strlen(lanConfig_joinname);
2345
			if (l < 21)
2346
			{
2347
				lanConfig_joinname[l+1] = 0;
2348
				lanConfig_joinname[l] = key;
2349
			}
2350
		}
2351
 
2352
		if (key < '0' || key > '9')
2353
			break;
2354
		if (lanConfig_cursor == 0)
2355
		{
2356
			l = strlen(lanConfig_portname);
2357
			if (l < 5)
2358
			{
2359
				lanConfig_portname[l+1] = 0;
2360
				lanConfig_portname[l] = key;
2361
			}
2362
		}
2363
	}
2364
 
2365
	if (StartingGame && lanConfig_cursor == 2)
2366
		if (key == K_UPARROW)
2367
			lanConfig_cursor = 1;
2368
		else
2369
			lanConfig_cursor = 0;
2370
 
2371
	l =  Q_atoi(lanConfig_portname);
2372
	if (l > 65535)
2373
		l = lanConfig_port;
2374
	else
2375
		lanConfig_port = l;
2376
	sprintf(lanConfig_portname, "%u", lanConfig_port);
2377
}
2378
 
2379
//=============================================================================
2380
/* GAME OPTIONS MENU */
2381
 
2382
typedef struct
2383
{
2384
	char	*name;
2385
	char	*description;
2386
} level_t;
2387
 
2388
level_t		levels[] =
2389
{
2390
	{"start", "Entrance"},	// 0
2391
 
2392
	{"e1m1", "Slipgate Complex"},				// 1
2393
	{"e1m2", "Castle of the Damned"},
2394
	{"e1m3", "The Necropolis"},
2395
	{"e1m4", "The Grisly Grotto"},
2396
	{"e1m5", "Gloom Keep"},
2397
	{"e1m6", "The Door To Chthon"},
2398
	{"e1m7", "The House of Chthon"},
2399
	{"e1m8", "Ziggurat Vertigo"},
2400
 
2401
	{"e2m1", "The Installation"},				// 9
2402
	{"e2m2", "Ogre Citadel"},
2403
	{"e2m3", "Crypt of Decay"},
2404
	{"e2m4", "The Ebon Fortress"},
2405
	{"e2m5", "The Wizard's Manse"},
2406
	{"e2m6", "The Dismal Oubliette"},
2407
	{"e2m7", "Underearth"},
2408
 
2409
	{"e3m1", "Termination Central"},			// 16
2410
	{"e3m2", "The Vaults of Zin"},
2411
	{"e3m3", "The Tomb of Terror"},
2412
	{"e3m4", "Satan's Dark Delight"},
2413
	{"e3m5", "Wind Tunnels"},
2414
	{"e3m6", "Chambers of Torment"},
2415
	{"e3m7", "The Haunted Halls"},
2416
 
2417
	{"e4m1", "The Sewage System"},				// 23
2418
	{"e4m2", "The Tower of Despair"},
2419
	{"e4m3", "The Elder God Shrine"},
2420
	{"e4m4", "The Palace of Hate"},
2421
	{"e4m5", "Hell's Atrium"},
2422
	{"e4m6", "The Pain Maze"},
2423
	{"e4m7", "Azure Agony"},
2424
	{"e4m8", "The Nameless City"},
2425
 
2426
	{"end", "Shub-Niggurath's Pit"},			// 31
2427
 
2428
	{"dm1", "Place of Two Deaths"},				// 32
2429
	{"dm2", "Claustrophobopolis"},
2430
	{"dm3", "The Abandoned Base"},
2431
	{"dm4", "The Bad Place"},
2432
	{"dm5", "The Cistern"},
2433
	{"dm6", "The Dark Zone"}
2434
};
2435
 
2436
//MED 01/06/97 added hipnotic levels
2437
level_t     hipnoticlevels[] =
2438
{
2439
   {"start", "Command HQ"},  // 0
2440
 
2441
   {"hip1m1", "The Pumping Station"},          // 1
2442
   {"hip1m2", "Storage Facility"},
2443
   {"hip1m3", "The Lost Mine"},
2444
   {"hip1m4", "Research Facility"},
2445
   {"hip1m5", "Military Complex"},
2446
 
2447
   {"hip2m1", "Ancient Realms"},          // 6
2448
   {"hip2m2", "The Black Cathedral"},
2449
   {"hip2m3", "The Catacombs"},
2450
   {"hip2m4", "The Crypt"},
2451
   {"hip2m5", "Mortum's Keep"},
2452
   {"hip2m6", "The Gremlin's Domain"},
2453
 
2454
   {"hip3m1", "Tur Torment"},       // 12
2455
   {"hip3m2", "Pandemonium"},
2456
   {"hip3m3", "Limbo"},
2457
   {"hip3m4", "The Gauntlet"},
2458
 
2459
   {"hipend", "Armagon's Lair"},       // 16
2460
 
2461
   {"hipdm1", "The Edge of Oblivion"}           // 17
2462
};
2463
 
2464
//PGM 01/07/97 added rogue levels
2465
//PGM 03/02/97 added dmatch level
2466
level_t		roguelevels[] =
2467
{
2468
	{"start",	"Split Decision"},
2469
	{"r1m1",	"Deviant's Domain"},
2470
	{"r1m2",	"Dread Portal"},
2471
	{"r1m3",	"Judgement Call"},
2472
	{"r1m4",	"Cave of Death"},
2473
	{"r1m5",	"Towers of Wrath"},
2474
	{"r1m6",	"Temple of Pain"},
2475
	{"r1m7",	"Tomb of the Overlord"},
2476
	{"r2m1",	"Tempus Fugit"},
2477
	{"r2m2",	"Elemental Fury I"},
2478
	{"r2m3",	"Elemental Fury II"},
2479
	{"r2m4",	"Curse of Osiris"},
2480
	{"r2m5",	"Wizard's Keep"},
2481
	{"r2m6",	"Blood Sacrifice"},
2482
	{"r2m7",	"Last Bastion"},
2483
	{"r2m8",	"Source of Evil"},
2484
	{"ctf1",    "Division of Change"}
2485
};
2486
 
2487
typedef struct
2488
{
2489
	char	*description;
2490
	int		firstLevel;
2491
	int		levels;
2492
} episode_t;
2493
 
2494
episode_t	episodes[] =
2495
{
2496
	{"Welcome to Quake", 0, 1},
2497
	{"Doomed Dimension", 1, 8},
2498
	{"Realm of Black Magic", 9, 7},
2499
	{"Netherworld", 16, 7},
2500
	{"The Elder World", 23, 8},
2501
	{"Final Level", 31, 1},
2502
	{"Deathmatch Arena", 32, 6}
2503
};
2504
 
2505
//MED 01/06/97  added hipnotic episodes
2506
episode_t   hipnoticepisodes[] =
2507
{
2508
   {"Scourge of Armagon", 0, 1},
2509
   {"Fortress of the Dead", 1, 5},
2510
   {"Dominion of Darkness", 6, 6},
2511
   {"The Rift", 12, 4},
2512
   {"Final Level", 16, 1},
2513
   {"Deathmatch Arena", 17, 1}
2514
};
2515
 
2516
//PGM 01/07/97 added rogue episodes
2517
//PGM 03/02/97 added dmatch episode
2518
episode_t	rogueepisodes[] =
2519
{
2520
	{"Introduction", 0, 1},
2521
	{"Hell's Fortress", 1, 7},
2522
	{"Corridors of Time", 8, 8},
2523
	{"Deathmatch Arena", 16, 1}
2524
};
2525
 
2526
int	startepisode;
2527
int	startlevel;
2528
int maxplayers;
2529
qboolean m_serverInfoMessage = false;
2530
double m_serverInfoMessageTime;
2531
 
2532
void M_Menu_GameOptions_f (void)
2533
{
2534
	key_dest = key_menu;
2535
	m_state = m_gameoptions;
2536
	m_entersound = true;
2537
	if (maxplayers == 0)
2538
		maxplayers = svs.maxclients;
2539
	if (maxplayers < 2)
2540
		maxplayers = svs.maxclientslimit;
2541
}
2542
 
2543
 
2544
int gameoptions_cursor_table[] = {40, 56, 64, 72, 80, 88, 96, 112, 120};
2545
#define	NUM_GAMEOPTIONS	9
2546
int		gameoptions_cursor;
2547
 
2548
void M_GameOptions_Draw (void)
2549
{
2550
	qpic_t	*p;
2551
	int		x;
2552
 
2553
	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
2554
	p = Draw_CachePic ("gfx/p_multi.lmp");
2555
	M_DrawPic ( (320-p->width)/2, 4, p);
2556
 
2557
	M_DrawTextBox (152, 32, 10, 1);
2558
	M_Print (160, 40, "begin game");
2559
 
2560
	M_Print (0, 56, "      Max players");
2561
	M_Print (160, 56, va("%i", maxplayers) );
2562
 
2563
	M_Print (0, 64, "        Game Type");
2564
	if (coop.value)
2565
		M_Print (160, 64, "Cooperative");
2566
	else
2567
		M_Print (160, 64, "Deathmatch");
2568
 
2569
	M_Print (0, 72, "        Teamplay");
2570
	if (rogue)
2571
	{
2572
		char *msg;
2573
 
2574
		switch((int)teamplay.value)
2575
		{
2576
			case 1: msg = "No Friendly Fire"; break;
2577
			case 2: msg = "Friendly Fire"; break;
2578
			case 3: msg = "Tag"; break;
2579
			case 4: msg = "Capture the Flag"; break;
2580
			case 5: msg = "One Flag CTF"; break;
2581
			case 6: msg = "Three Team CTF"; break;
2582
			default: msg = "Off"; break;
2583
		}
2584
		M_Print (160, 72, msg);
2585
	}
2586
	else
2587
	{
2588
		char *msg;
2589
 
2590
		switch((int)teamplay.value)
2591
		{
2592
			case 1: msg = "No Friendly Fire"; break;
2593
			case 2: msg = "Friendly Fire"; break;
2594
			default: msg = "Off"; break;
2595
		}
2596
		M_Print (160, 72, msg);
2597
	}
2598
 
2599
	M_Print (0, 80, "            Skill");
2600
	if (skill.value == 0)
2601
		M_Print (160, 80, "Easy difficulty");
2602
	else if (skill.value == 1)
2603
		M_Print (160, 80, "Normal difficulty");
2604
	else if (skill.value == 2)
2605
		M_Print (160, 80, "Hard difficulty");
2606
	else
2607
		M_Print (160, 80, "Nightmare difficulty");
2608
 
2609
	M_Print (0, 88, "       Frag Limit");
2610
	if (fraglimit.value == 0)
2611
		M_Print (160, 88, "none");
2612
	else
2613
		M_Print (160, 88, va("%i frags", (int)fraglimit.value));
2614
 
2615
	M_Print (0, 96, "       Time Limit");
2616
	if (timelimit.value == 0)
2617
		M_Print (160, 96, "none");
2618
	else
2619
		M_Print (160, 96, va("%i minutes", (int)timelimit.value));
2620
 
2621
	M_Print (0, 112, "         Episode");
2622
   //MED 01/06/97 added hipnotic episodes
2623
   if (hipnotic)
2624
      M_Print (160, 112, hipnoticepisodes[startepisode].description);
2625
   //PGM 01/07/97 added rogue episodes
2626
   else if (rogue)
2627
      M_Print (160, 112, rogueepisodes[startepisode].description);
2628
   else
2629
      M_Print (160, 112, episodes[startepisode].description);
2630
 
2631
	M_Print (0, 120, "           Level");
2632
   //MED 01/06/97 added hipnotic episodes
2633
   if (hipnotic)
2634
   {
2635
      M_Print (160, 120, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].description);
2636
      M_Print (160, 128, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name);
2637
   }
2638
   //PGM 01/07/97 added rogue episodes
2639
   else if (rogue)
2640
   {
2641
      M_Print (160, 120, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].description);
2642
      M_Print (160, 128, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name);
2643
   }
2644
   else
2645
   {
2646
      M_Print (160, 120, levels[episodes[startepisode].firstLevel + startlevel].description);
2647
      M_Print (160, 128, levels[episodes[startepisode].firstLevel + startlevel].name);
2648
   }
2649
 
2650
// line cursor
2651
	M_DrawCharacter (144, gameoptions_cursor_table[gameoptions_cursor], 12+((int)(realtime*4)&1));
2652
 
2653
	if (m_serverInfoMessage)
2654
	{
2655
		if ((realtime - m_serverInfoMessageTime) < 5.0)
2656
		{
2657
			x = (320-26*8)/2;
2658
			M_DrawTextBox (x, 138, 24, 4);
2659
			x += 8;
2660
			M_Print (x, 146, "  More than 4 players   ");
2661
			M_Print (x, 154, " requires using command ");
2662
			M_Print (x, 162, "line parameters; please ");
2663
			M_Print (x, 170, "   see techinfo.txt.    ");
2664
		}
2665
		else
2666
		{
2667
			m_serverInfoMessage = false;
2668
		}
2669
	}
2670
}
2671
 
2672
 
2673
void M_NetStart_Change (int dir)
2674
{
2675
	int count;
2676
 
2677
	switch (gameoptions_cursor)
2678
	{
2679
	case 1:
2680
		maxplayers += dir;
2681
		if (maxplayers > svs.maxclientslimit)
2682
		{
2683
			maxplayers = svs.maxclientslimit;
2684
			m_serverInfoMessage = true;
2685
			m_serverInfoMessageTime = realtime;
2686
		}
2687
		if (maxplayers < 2)
2688
			maxplayers = 2;
2689
		break;
2690
 
2691
	case 2:
2692
		Cvar_SetValue ("coop", coop.value ? 0 : 1);
2693
		break;
2694
 
2695
	case 3:
2696
		if (rogue)
2697
			count = 6;
2698
		else
2699
			count = 2;
2700
 
2701
		Cvar_SetValue ("teamplay", teamplay.value + dir);
2702
		if (teamplay.value > count)
2703
			Cvar_SetValue ("teamplay", 0);
2704
		else if (teamplay.value < 0)
2705
			Cvar_SetValue ("teamplay", count);
2706
		break;
2707
 
2708
	case 4:
2709
		Cvar_SetValue ("skill", skill.value + dir);
2710
		if (skill.value > 3)
2711
			Cvar_SetValue ("skill", 0);
2712
		if (skill.value < 0)
2713
			Cvar_SetValue ("skill", 3);
2714
		break;
2715
 
2716
	case 5:
2717
		Cvar_SetValue ("fraglimit", fraglimit.value + dir*10);
2718
		if (fraglimit.value > 100)
2719
			Cvar_SetValue ("fraglimit", 0);
2720
		if (fraglimit.value < 0)
2721
			Cvar_SetValue ("fraglimit", 100);
2722
		break;
2723
 
2724
	case 6:
2725
		Cvar_SetValue ("timelimit", timelimit.value + dir*5);
2726
		if (timelimit.value > 60)
2727
			Cvar_SetValue ("timelimit", 0);
2728
		if (timelimit.value < 0)
2729
			Cvar_SetValue ("timelimit", 60);
2730
		break;
2731
 
2732
	case 7:
2733
		startepisode += dir;
2734
	//MED 01/06/97 added hipnotic count
2735
		if (hipnotic)
2736
			count = 6;
2737
	//PGM 01/07/97 added rogue count
2738
	//PGM 03/02/97 added 1 for dmatch episode
2739
		else if (rogue)
2740
			count = 4;
2741
		else if (registered.value)
2742
			count = 7;
2743
		else
2744
			count = 2;
2745
 
2746
		if (startepisode < 0)
2747
			startepisode = count - 1;
2748
 
2749
		if (startepisode >= count)
2750
			startepisode = 0;
2751
 
2752
		startlevel = 0;
2753
		break;
2754
 
2755
	case 8:
2756
		startlevel += dir;
2757
    //MED 01/06/97 added hipnotic episodes
2758
		if (hipnotic)
2759
			count = hipnoticepisodes[startepisode].levels;
2760
	//PGM 01/06/97 added hipnotic episodes
2761
		else if (rogue)
2762
			count = rogueepisodes[startepisode].levels;
2763
		else
2764
			count = episodes[startepisode].levels;
2765
 
2766
		if (startlevel < 0)
2767
			startlevel = count - 1;
2768
 
2769
		if (startlevel >= count)
2770
			startlevel = 0;
2771
		break;
2772
	}
2773
}
2774
 
2775
void M_GameOptions_Key (int key)
2776
{
2777
	switch (key)
2778
	{
2779
	case K_ESCAPE:
2780
		M_Menu_Net_f ();
2781
		break;
2782
 
2783
	case K_UPARROW:
2784
		S_LocalSound ("misc/menu1.wav");
2785
		gameoptions_cursor--;
2786
		if (gameoptions_cursor < 0)
2787
			gameoptions_cursor = NUM_GAMEOPTIONS-1;
2788
		break;
2789
 
2790
	case K_DOWNARROW:
2791
		S_LocalSound ("misc/menu1.wav");
2792
		gameoptions_cursor++;
2793
		if (gameoptions_cursor >= NUM_GAMEOPTIONS)
2794
			gameoptions_cursor = 0;
2795
		break;
2796
 
2797
	case K_LEFTARROW:
2798
		if (gameoptions_cursor == 0)
2799
			break;
2800
		S_LocalSound ("misc/menu3.wav");
2801
		M_NetStart_Change (-1);
2802
		break;
2803
 
2804
	case K_RIGHTARROW:
2805
		if (gameoptions_cursor == 0)
2806
			break;
2807
		S_LocalSound ("misc/menu3.wav");
2808
		M_NetStart_Change (1);
2809
		break;
2810
 
2811
	case K_ENTER:
2812
		S_LocalSound ("misc/menu2.wav");
2813
		if (gameoptions_cursor == 0)
2814
		{
2815
			if (sv.active)
2816
				Cbuf_AddText ("disconnect\n");
2817
			Cbuf_AddText ("listen 0\n");	// so host_netport will be re-examined
2818
			Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) );
2819
			SCR_BeginLoadingPlaque ();
2820
 
2821
			if (hipnotic)
2822
				Cbuf_AddText ( va ("map %s\n", hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name) );
2823
			else if (rogue)
2824
				Cbuf_AddText ( va ("map %s\n", roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name) );
2825
			else
2826
				Cbuf_AddText ( va ("map %s\n", levels[episodes[startepisode].firstLevel + startlevel].name) );
2827
 
2828
			return;
2829
		}
2830
 
2831
		M_NetStart_Change (1);
2832
		break;
2833
	}
2834
}
2835
 
2836
//=============================================================================
2837
/* SEARCH MENU */
2838
 
2839
qboolean	searchComplete = false;
2840
double		searchCompleteTime;
2841
 
2842
void M_Menu_Search_f (void)
2843
{
2844
	key_dest = key_menu;
2845
	m_state = m_search;
2846
	m_entersound = false;
2847
	slistSilent = true;
2848
	slistLocal = false;
2849
	searchComplete = false;
2850
	NET_Slist_f();
2851
 
2852
}
2853
 
2854
 
2855
void M_Search_Draw (void)
2856
{
2857
	qpic_t	*p;
2858
	int x;
2859
 
2860
	p = Draw_CachePic ("gfx/p_multi.lmp");
2861
	M_DrawPic ( (320-p->width)/2, 4, p);
2862
	x = (320/2) - ((12*8)/2) + 4;
2863
	M_DrawTextBox (x-8, 32, 12, 1);
2864
	M_Print (x, 40, "Searching...");
2865
 
2866
	if(slistInProgress)
2867
	{
2868
		NET_Poll();
2869
		return;
2870
	}
2871
 
2872
	if (! searchComplete)
2873
	{
2874
		searchComplete = true;
2875
		searchCompleteTime = realtime;
2876
	}
2877
 
2878
	if (hostCacheCount)
2879
	{
2880
		M_Menu_ServerList_f ();
2881
		return;
2882
	}
2883
 
2884
	M_PrintWhite ((320/2) - ((22*8)/2), 64, "No Quake servers found");
2885
	if ((realtime - searchCompleteTime) < 3.0)
2886
		return;
2887
 
2888
	M_Menu_LanConfig_f ();
2889
}
2890
 
2891
 
2892
void M_Search_Key (int key)
2893
{
2894
}
2895
 
2896
//=============================================================================
2897
/* SLIST MENU */
2898
 
2899
int		slist_cursor;
2900
qboolean slist_sorted;
2901
 
2902
void M_Menu_ServerList_f (void)
2903
{
2904
	key_dest = key_menu;
2905
	m_state = m_slist;
2906
	m_entersound = true;
2907
	slist_cursor = 0;
2908
	m_return_onerror = false;
2909
	m_return_reason[0] = 0;
2910
	slist_sorted = false;
2911
}
2912
 
2913
 
2914
void M_ServerList_Draw (void)
2915
{
2916
	int		n;
2917
	char	string [64];
2918
	qpic_t	*p;
2919
 
2920
	if (!slist_sorted)
2921
	{
2922
		if (hostCacheCount > 1)
2923
		{
2924
			int	i,j;
2925
			hostcache_t temp;
2926
			for (i = 0; i < hostCacheCount; i++)
2927
				for (j = i+1; j < hostCacheCount; j++)
2928
					if (strcmp(hostcache[j].name, hostcache[i].name) < 0)
2929
					{
2930
						Q_memcpy(&temp, &hostcache[j], sizeof(hostcache_t));
2931
						Q_memcpy(&hostcache[j], &hostcache[i], sizeof(hostcache_t));
2932
						Q_memcpy(&hostcache[i], &temp, sizeof(hostcache_t));
2933
					}
2934
		}
2935
		slist_sorted = true;
2936
	}
2937
 
2938
	p = Draw_CachePic ("gfx/p_multi.lmp");
2939
	M_DrawPic ( (320-p->width)/2, 4, p);
2940
	for (n = 0; n < hostCacheCount; n++)
2941
	{
2942
		if (hostcache[n].maxusers)
2943
			sprintf(string, "%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers);
2944
		else
2945
			sprintf(string, "%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map);
2946
		M_Print (16, 32 + 8*n, string);
2947
	}
2948
	M_DrawCharacter (0, 32 + slist_cursor*8, 12+((int)(realtime*4)&1));
2949
 
2950
	if (*m_return_reason)
2951
		M_PrintWhite (16, 148, m_return_reason);
2952
}
2953
 
2954
 
2955
void M_ServerList_Key (int k)
2956
{
2957
	switch (k)
2958
	{
2959
	case K_ESCAPE:
2960
		M_Menu_LanConfig_f ();
2961
		break;
2962
 
2963
	case K_SPACE:
2964
		M_Menu_Search_f ();
2965
		break;
2966
 
2967
	case K_UPARROW:
2968
	case K_LEFTARROW:
2969
		S_LocalSound ("misc/menu1.wav");
2970
		slist_cursor--;
2971
		if (slist_cursor < 0)
2972
			slist_cursor = hostCacheCount - 1;
2973
		break;
2974
 
2975
	case K_DOWNARROW:
2976
	case K_RIGHTARROW:
2977
		S_LocalSound ("misc/menu1.wav");
2978
		slist_cursor++;
2979
		if (slist_cursor >= hostCacheCount)
2980
			slist_cursor = 0;
2981
		break;
2982
 
2983
	case K_ENTER:
2984
		S_LocalSound ("misc/menu2.wav");
2985
		m_return_state = m_state;
2986
		m_return_onerror = true;
2987
		slist_sorted = false;
2988
		key_dest = key_game;
2989
		m_state = m_none;
2990
		Cbuf_AddText ( va ("connect \"%s\"\n", hostcache[slist_cursor].cname) );
2991
		break;
2992
 
2993
	default:
2994
		break;
2995
	}
2996
 
2997
}
2998
 
2999
//=============================================================================
3000
/* Menu Subsystem */
3001
 
3002
 
3003
void M_Init (void)
3004
{
3005
	Cmd_AddCommand ("togglemenu", M_ToggleMenu_f);
3006
 
3007
	Cmd_AddCommand ("menu_main", M_Menu_Main_f);
3008
	Cmd_AddCommand ("menu_singleplayer", M_Menu_SinglePlayer_f);
3009
	Cmd_AddCommand ("menu_load", M_Menu_Load_f);
3010
	Cmd_AddCommand ("menu_save", M_Menu_Save_f);
3011
	Cmd_AddCommand ("menu_multiplayer", M_Menu_MultiPlayer_f);
3012
	Cmd_AddCommand ("menu_setup", M_Menu_Setup_f);
3013
	Cmd_AddCommand ("menu_options", M_Menu_Options_f);
3014
	Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
3015
	Cmd_AddCommand ("menu_video", M_Menu_Video_f);
3016
	Cmd_AddCommand ("help", M_Menu_Help_f);
3017
	Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
3018
}
3019
 
3020
 
3021
void M_Draw (void)
3022
{
3023
	if (m_state == m_none || key_dest != key_menu)
3024
		return;
3025
 
3026
	if (!m_recursiveDraw)
3027
	{
3028
		scr_copyeverything = 1;
3029
 
3030
		if (scr_con_current)
3031
		{
3032
			Draw_ConsoleBackground (vid.height);
3033
			VID_UnlockBuffer ();
3034
			S_ExtraUpdate ();
3035
			VID_LockBuffer ();
3036
		}
3037
		else
3038
			Draw_FadeScreen ();
3039
 
3040
		scr_fullupdate = 0;
3041
	}
3042
	else
3043
	{
3044
		m_recursiveDraw = false;
3045
	}
3046
 
3047
	switch (m_state)
3048
	{
3049
	case m_none:
3050
		break;
3051
 
3052
	case m_main:
3053
		M_Main_Draw ();
3054
		break;
3055
 
3056
	case m_singleplayer:
3057
		M_SinglePlayer_Draw ();
3058
		break;
3059
 
3060
	case m_load:
3061
		M_Load_Draw ();
3062
		break;
3063
 
3064
	case m_save:
3065
		M_Save_Draw ();
3066
		break;
3067
 
3068
	case m_multiplayer:
3069
		M_MultiPlayer_Draw ();
3070
		break;
3071
 
3072
	case m_setup:
3073
		M_Setup_Draw ();
3074
		break;
3075
 
3076
	case m_net:
3077
		M_Net_Draw ();
3078
		break;
3079
 
3080
	case m_options:
3081
		M_Options_Draw ();
3082
		break;
3083
 
3084
	case m_keys:
3085
		M_Keys_Draw ();
3086
		break;
3087
 
3088
	case m_video:
3089
		M_Video_Draw ();
3090
		break;
3091
 
3092
	case m_help:
3093
		M_Help_Draw ();
3094
		break;
3095
 
3096
	case m_quit:
3097
		M_Quit_Draw ();
3098
		break;
3099
 
3100
	case m_serialconfig:
3101
		M_SerialConfig_Draw ();
3102
		break;
3103
 
3104
	case m_modemconfig:
3105
		M_ModemConfig_Draw ();
3106
		break;
3107
 
3108
	case m_lanconfig:
3109
		M_LanConfig_Draw ();
3110
		break;
3111
 
3112
	case m_gameoptions:
3113
		M_GameOptions_Draw ();
3114
		break;
3115
 
3116
	case m_search:
3117
		M_Search_Draw ();
3118
		break;
3119
 
3120
	case m_slist:
3121
		M_ServerList_Draw ();
3122
		break;
3123
	}
3124
 
3125
	if (m_entersound)
3126
	{
3127
		S_LocalSound ("misc/menu2.wav");
3128
		m_entersound = false;
3129
	}
3130
 
3131
	VID_UnlockBuffer ();
3132
	S_ExtraUpdate ();
3133
	VID_LockBuffer ();
3134
}
3135
 
3136
 
3137
void M_Keydown (int key)
3138
{
3139
	switch (m_state)
3140
	{
3141
	case m_none:
3142
		return;
3143
 
3144
	case m_main:
3145
		M_Main_Key (key);
3146
		return;
3147
 
3148
	case m_singleplayer:
3149
		M_SinglePlayer_Key (key);
3150
		return;
3151
 
3152
	case m_load:
3153
		M_Load_Key (key);
3154
		return;
3155
 
3156
	case m_save:
3157
		M_Save_Key (key);
3158
		return;
3159
 
3160
	case m_multiplayer:
3161
		M_MultiPlayer_Key (key);
3162
		return;
3163
 
3164
	case m_setup:
3165
		M_Setup_Key (key);
3166
		return;
3167
 
3168
	case m_net:
3169
		M_Net_Key (key);
3170
		return;
3171
 
3172
	case m_options:
3173
		M_Options_Key (key);
3174
		return;
3175
 
3176
	case m_keys:
3177
		M_Keys_Key (key);
3178
		return;
3179
 
3180
	case m_video:
3181
		M_Video_Key (key);
3182
		return;
3183
 
3184
	case m_help:
3185
		M_Help_Key (key);
3186
		return;
3187
 
3188
	case m_quit:
3189
		M_Quit_Key (key);
3190
		return;
3191
 
3192
	case m_serialconfig:
3193
		M_SerialConfig_Key (key);
3194
		return;
3195
 
3196
	case m_modemconfig:
3197
		M_ModemConfig_Key (key);
3198
		return;
3199
 
3200
	case m_lanconfig:
3201
		M_LanConfig_Key (key);
3202
		return;
3203
 
3204
	case m_gameoptions:
3205
		M_GameOptions_Key (key);
3206
		return;
3207
 
3208
	case m_search:
3209
		M_Search_Key (key);
3210
		break;
3211
 
3212
	case m_slist:
3213
		M_ServerList_Key (key);
3214
		return;
3215
	}
3216
}
3217
 
3218
 
3219
void M_ConfigureNetSubsystem(void)
3220
{
3221
// enable/disable net systems to match desired config
3222
 
3223
	Cbuf_AddText ("stopdemo\n");
3224
	if (SerialConfig || DirectConfig)
3225
	{
3226
		Cbuf_AddText ("com1 enable\n");
3227
	}
3228
 
3229
	if (IPXConfig || TCPIPConfig)
3230
		net_hostport = lanConfig_port;
3231
}