|
|
1.1 root 1: #include <ctype.h>
2: #include <io.h>
3: #include "client.h"
4: #include "../client/qmenu.h"
5: static int m_main_cursor;
6: #define NUM_CURSOR_FRAMES 15
7: static char *menu_in_sound = "misc/menu1.wav";
8: static char *menu_move_sound = "misc/menu2.wav";
9: static char *menu_out_sound = "misc/menu3.wav";
10: void M_Menu_Main_f (void);
11: void M_Menu_Game_f (void);
12: void M_Menu_LoadGame_f (void);
13: void M_Menu_SaveGame_f (void);
14: void M_Menu_PlayerConfig_f (void);
15: void M_Menu_Credits_f( void );
16: void M_Menu_Multiplayer_f( void );
17: void M_Menu_JoinServer_f (void);
18: void M_Menu_AddressBook_f( void );
19: void M_Menu_StartServer_f (void);
20: void M_Menu_DMOptions_f (void);
21: void M_Menu_Video_f (void);
22: void M_Menu_Options_f (void);
23: void M_Menu_Keys_f (void);
24: void M_Menu_Quit_f (void);
25:
26: void M_Menu_Credits( void );
27: qboolean m_entersound; // play after drawing a frame, so caching
28: // won't disrupt the sound
29: void (*m_drawfunc) (void);
30: const char *(*m_keyfunc) (int key);
31: //=============================================================================
32: /* Support Routines */
33: #define MAX_MENU_DEPTH 8
34: typedef struct
35: {
36: void (*draw) (void);
37: const char *(*key) (int k);
38: } menulayer_t;
39: menulayer_t m_layers[MAX_MENU_DEPTH];
40: int m_menudepth;
41:
42: static void M_Banner( char *name )
43: {
44: int w, h;
45:
46: re.DrawGetPicSize (&w, &h, name );
47: re.DrawPic( viddef.width / 2 - w / 2, viddef.height / 2 - 110, name );
48: }
49: void M_PushMenu ( void (*draw) (void), const char *(*key) (int k) )
50: {
51: int i;
52:
53: if (Cvar_VariableValue ("maxclients") == 1
54: && Com_ServerState ())
55: Cvar_Set ("paused", "1");
56: // if this menu is already present, drop back to that level
57: // to avoid stacking menus by hotkeys
58: for (i=0 ; i<m_menudepth ; i++)
59: if (m_layers[i].draw == draw &&
60: m_layers[i].key == key)
61: {
62: m_menudepth = i;
63: }
64: if (i == m_menudepth)
65: {
66: if (m_menudepth >= MAX_MENU_DEPTH)
67: Com_Error (ERR_FATAL, "M_PushMenu: MAX_MENU_DEPTH");
68: m_layers[m_menudepth].draw = m_drawfunc;
69: m_layers[m_menudepth].key = m_keyfunc;
70: m_menudepth++;
71: }
72: m_drawfunc = draw;
73: m_keyfunc = key;
74: m_entersound = true;
75: cls.key_dest = key_menu;
76: }
77: void M_ForceMenuOff (void)
78: {
79: m_drawfunc = 0;
80: m_keyfunc = 0;
81: cls.key_dest = key_game;
82: m_menudepth = 0;
83: Key_ClearStates ();
84: Cvar_Set ("paused", "0");
85: }
86: void M_PopMenu (void)
87: {
88: S_StartLocalSound( menu_out_sound );
89: if (m_menudepth < 1)
90: Com_Error (ERR_FATAL, "M_PopMenu: depth < 1");
91: m_menudepth--;
92: m_drawfunc = m_layers[m_menudepth].draw;
93: m_keyfunc = m_layers[m_menudepth].key;
94: if (!m_menudepth)
95: M_ForceMenuOff ();
96: }
97: const char *Default_MenuKey( menuframework_s *m, int key )
98: {
99: const char *sound = NULL;
100: menucommon_s *item;
101: if ( m )
102: {
103: if ( ( item = Menu_ItemAtCursor( m ) ) != 0 )
104: {
105: if ( item->type == MTYPE_FIELD )
106: {
107: if ( Field_Key( ( menufield_s * ) item, key ) )
108: return NULL;
109: }
110: }
111: }
112: switch ( key )
113: {
114: case K_ESCAPE:
115: M_PopMenu();
116: return menu_out_sound;
117: case K_KP_UPARROW:
118: case K_UPARROW:
119: if ( m )
120: {
121: m->cursor--;
122: Menu_AdjustCursor( m, -1 );
123: sound = menu_move_sound;
124: }
125: break;
126: case K_TAB:
127: if ( m )
128: {
129: m->cursor++;
130: Menu_AdjustCursor( m, 1 );
131: sound = menu_move_sound;
132: }
133: break;
134: case K_KP_DOWNARROW:
135: case K_DOWNARROW:
136: if ( m )
137: {
138: m->cursor++;
139: Menu_AdjustCursor( m, 1 );
140: sound = menu_move_sound;
141: }
142: break;
143: case K_KP_LEFTARROW:
144: case K_LEFTARROW:
145: if ( m )
146: {
147: Menu_SlideItem( m, -1 );
148: sound = menu_move_sound;
149: }
150: break;
151: case K_KP_RIGHTARROW:
152: case K_RIGHTARROW:
153: if ( m )
154: {
155: Menu_SlideItem( m, 1 );
156: sound = menu_move_sound;
157: }
158: break;
159:
160: case K_MOUSE1:
161: case K_MOUSE2:
162: case K_MOUSE3:
163: case K_JOY1:
164: case K_JOY2:
165: case K_JOY3:
166: case K_JOY4:
167: case K_AUX1:
168: case K_AUX2:
169: case K_AUX3:
170: case K_AUX4:
171: case K_AUX5:
172: case K_AUX6:
173: case K_AUX7:
174: case K_AUX8:
175: case K_AUX9:
176: case K_AUX10:
177: case K_AUX11:
178: case K_AUX12:
179: case K_AUX13:
180: case K_AUX14:
181: case K_AUX15:
182: case K_AUX16:
183: case K_AUX17:
184: case K_AUX18:
185: case K_AUX19:
186: case K_AUX20:
187: case K_AUX21:
188: case K_AUX22:
189: case K_AUX23:
190: case K_AUX24:
191: case K_AUX25:
192: case K_AUX26:
193: case K_AUX27:
194: case K_AUX28:
195: case K_AUX29:
196: case K_AUX30:
197: case K_AUX31:
198: case K_AUX32:
199:
200: case K_KP_ENTER:
201: case K_ENTER:
202: if ( m )
203: Menu_SelectItem( m );
204: sound = menu_move_sound;
205: break;
206: }
207: return sound;
208: }
209: //=============================================================================
210: /*
211: ================
212: M_DrawCharacter
213: Draws one solid graphics character
214: cx and cy are in 320*240 coordinates, and will be centered on
215: higher res screens.
216: ================
217: */
218: void M_DrawCharacter (int cx, int cy, int num)
219: {
220: re.DrawChar ( cx + ((viddef.width - 320)>>1), cy + ((viddef.height - 240)>>1), num);
221: }
222: void M_Print (int cx, int cy, char *str)
223: {
224: while (*str)
225: {
226: M_DrawCharacter (cx, cy, (*str)+128);
227: str++;
228: cx += 8;
229: }
230: }
231: void M_PrintWhite (int cx, int cy, char *str)
232: {
233: while (*str)
234: {
235: M_DrawCharacter (cx, cy, *str);
236: str++;
237: cx += 8;
238: }
239: }
240: void M_DrawPic (int x, int y, char *pic)
241: {
242: re.DrawPic (x + ((viddef.width - 320)>>1), y + ((viddef.height - 240)>>1), pic);
243: }
244: /*
245: =============
246: M_DrawCursor
247: Draws an animating cursor with the point at
248: x,y. The pic will extend to the left of x,
249: and both above and below y.
250: =============
251: */
252: void M_DrawCursor( int x, int y, int f )
253: {
254: char cursorname[80];
255: static qboolean cached;
256:
257: if ( !cached )
258: {
259: int i;
260:
261: for ( i = 0; i < NUM_CURSOR_FRAMES; i++ )
262: {
263: Com_sprintf( cursorname, sizeof( cursorname ), "m_cursor%d", i );
264:
265: re.RegisterPic( cursorname );
266: }
267: cached = true;
268: }
269: Com_sprintf( cursorname, sizeof(cursorname), "m_cursor%d", f );
270: re.DrawPic( x, y, cursorname );
271: }
272: void M_DrawTextBox (int x, int y, int width, int lines)
273: {
274: int cx, cy;
275: int n;
276: // draw left side
277: cx = x;
278: cy = y;
279: M_DrawCharacter (cx, cy, 1);
280: for (n = 0; n < lines; n++)
281: {
282: cy += 8;
283: M_DrawCharacter (cx, cy, 4);
284: }
285: M_DrawCharacter (cx, cy+8, 7);
286: // draw middle
287: cx += 8;
288: while (width > 0)
289: {
290: cy = y;
291: M_DrawCharacter (cx, cy, 2);
292: for (n = 0; n < lines; n++)
293: {
294: cy += 8;
295: M_DrawCharacter (cx, cy, 5);
296: }
297: M_DrawCharacter (cx, cy+8, 8);
298: width -= 1;
299: cx += 8;
300: }
301: // draw right side
302: cy = y;
303: M_DrawCharacter (cx, cy, 3);
304: for (n = 0; n < lines; n++)
305: {
306: cy += 8;
307: M_DrawCharacter (cx, cy, 6);
308: }
309: M_DrawCharacter (cx, cy+8, 9);
310: }
311:
312: /*
313: =======================================================================
314: MAIN MENU
315: =======================================================================
316: */
317: #define MAIN_ITEMS 5
318: void M_Main_Draw (void)
319: {
320: int i;
321: int w, h;
322: int ystart;
323: int xoffset;
324: int widest = -1;
325: int totalheight = 0;
326: char litname[80];
327: char *names[] =
328: {
329: "m_main_game",
330: "m_main_multiplayer",
331: "m_main_options",
332: "m_main_video",
333: "m_main_quit",
334: 0
335: };
336: for ( i = 0; names[i] != 0; i++ )
337: {
338: re.DrawGetPicSize( &w, &h, names[i] );
339: if ( w > widest )
340: widest = w;
341: totalheight += ( h + 12 );
342: }
343:
344: ystart = ( viddef.height / 2 - 110 );
345: xoffset = ( viddef.width - widest + 70 ) / 2;
346: for ( i = 0; names[i] != 0; i++ )
347: {
348: if ( i != m_main_cursor )
349: re.DrawPic( xoffset, ystart + i * 40 + 13, names[i] );
350: }
351: strcpy( litname, names[m_main_cursor] );
352: strcat( litname, "_sel" );
353: re.DrawPic( xoffset, ystart + m_main_cursor * 40 + 13, litname );
354: M_DrawCursor( xoffset - 25, ystart + m_main_cursor * 40 + 11, (int)(cls.realtime / 100)%NUM_CURSOR_FRAMES );
355: re.DrawGetPicSize( &w, &h, "m_main_plaque" );
356: re.DrawPic( xoffset - 30 - w, ystart, "m_main_plaque" );
357: re.DrawPic( xoffset - 30 - w, ystart + h + 5, "m_main_logo" );
358: }
359: const char *M_Main_Key (int key)
360: {
361: const char *sound = menu_move_sound;
362: switch (key)
363: {
364: case K_ESCAPE:
365: M_PopMenu ();
366: break;
367:
368: case K_KP_DOWNARROW:
369: case K_DOWNARROW:
370: if (++m_main_cursor >= MAIN_ITEMS)
371: m_main_cursor = 0;
372: return sound;
373: case K_KP_UPARROW:
374: case K_UPARROW:
375: if (--m_main_cursor < 0)
376: m_main_cursor = MAIN_ITEMS - 1;
377: return sound;
378:
379: case K_KP_ENTER:
380: case K_ENTER:
381: m_entersound = true;
382: switch (m_main_cursor)
383: {
384: case 0:
385: M_Menu_Game_f ();
386: break;
387: case 1:
388: M_Menu_Multiplayer_f();
389: break;
390: case 2:
391: M_Menu_Options_f ();
392: break;
393: case 3:
394: M_Menu_Video_f ();
395: break;
396: case 4:
397: M_Menu_Quit_f ();
398: break;
399: }
400: }
401: return NULL;
402: }
403: void M_Menu_Main_f (void)
404: {
405: M_PushMenu (M_Main_Draw, M_Main_Key);
406: }
407:
408: /*
409: =======================================================================
410:
411: MULTIPLAYER MENU
412:
413: =======================================================================
414: */
415: static menuframework_s s_multiplayer_menu;
416: static menuaction_s s_join_network_server_action;
417: static menuaction_s s_start_network_server_action;
418: static menuaction_s s_player_setup_action;
419:
420: static void Multiplayer_MenuDraw (void)
421: {
422: M_Banner( "m_banner_multiplayer" );
423:
424: Menu_AdjustCursor( &s_multiplayer_menu, 1 );
425: Menu_Draw( &s_multiplayer_menu );
426: }
427:
428: static void PlayerSetupFunc( void *unused )
429: {
430: M_Menu_PlayerConfig_f();
431: }
432:
433: static void JoinNetworkServerFunc( void *unused )
434: {
435: M_Menu_JoinServer_f();
436: }
437:
438: static void StartNetworkServerFunc( void *unused )
439: {
440: M_Menu_StartServer_f ();
441: }
442:
443: void Multiplayer_MenuInit( void )
444: {
445: s_multiplayer_menu.x = viddef.width * 0.50 - 64;
446: s_multiplayer_menu.nitems = 0;
447:
448: s_join_network_server_action.generic.type = MTYPE_ACTION;
449: s_join_network_server_action.generic.flags = QMF_LEFT_JUSTIFY;
450: s_join_network_server_action.generic.x = 0;
451: s_join_network_server_action.generic.y = 0;
452: s_join_network_server_action.generic.name = " join network server";
453: s_join_network_server_action.generic.callback = JoinNetworkServerFunc;
454:
455: s_start_network_server_action.generic.type = MTYPE_ACTION;
456: s_start_network_server_action.generic.flags = QMF_LEFT_JUSTIFY;
457: s_start_network_server_action.generic.x = 0;
458: s_start_network_server_action.generic.y = 10;
459: s_start_network_server_action.generic.name = " start network server";
460: s_start_network_server_action.generic.callback = StartNetworkServerFunc;
461:
462: s_player_setup_action.generic.type = MTYPE_ACTION;
463: s_player_setup_action.generic.flags = QMF_LEFT_JUSTIFY;
464: s_player_setup_action.generic.x = 0;
465: s_player_setup_action.generic.y = 20;
466: s_player_setup_action.generic.name = " player setup";
467: s_player_setup_action.generic.callback = PlayerSetupFunc;
468:
469: Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_join_network_server_action );
470: Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_start_network_server_action );
471: Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_player_setup_action );
472:
473: Menu_Center( &s_multiplayer_menu );
474: }
475:
476: const char *Multiplayer_MenuKey( int key )
477: {
478: return Default_MenuKey( &s_multiplayer_menu, key );
479: }
480:
481: void M_Menu_Multiplayer_f( void )
482: {
483: Multiplayer_MenuInit();
484: M_PushMenu( Multiplayer_MenuDraw, Multiplayer_MenuKey );
485: }
486: /*
487: =======================================================================
488:
489: KEYS MENU
490:
491: =======================================================================
492: */
493: char *bindnames[][2] =
494: {
495: {"+attack", "attack"},
496: {"weapnext", "next weapon"},
497: {"+forward", "walk forward"},
498: {"+back", "backpedal"},
499: {"+left", "turn left"},
500: {"+right", "turn right"},
501: {"+speed", "run"},
502: {"+moveleft", "step left"},
503: {"+moveright", "step right"},
504: {"+strafe", "sidestep"},
505: {"+lookup", "look up"},
506: {"+lookdown", "look down"},
507: {"centerview", "center view"},
508: {"+mlook", "mouse look"},
509: {"+klook", "keyboard look"},
510: {"+moveup", "up / jump"},
511: {"+movedown", "down / crouch"},
512: {"inven", "inventory"},
513: {"invuse", "use item"},
514: {"invdrop", "drop item"},
515: {"invprev", "prev item"},
516: {"invnext", "next item"},
517: {"cmd help", "help computer" },
518: { 0, 0 }
519: };
520: int keys_cursor;
521: static int bind_grab;
522: static menuframework_s s_keys_menu;
523: static menuaction_s s_keys_attack_action;
524: static menuaction_s s_keys_change_weapon_action;
525: static menuaction_s s_keys_walk_forward_action;
526: static menuaction_s s_keys_backpedal_action;
527: static menuaction_s s_keys_turn_left_action;
528: static menuaction_s s_keys_turn_right_action;
529: static menuaction_s s_keys_run_action;
530: static menuaction_s s_keys_step_left_action;
531: static menuaction_s s_keys_step_right_action;
532: static menuaction_s s_keys_sidestep_action;
533: static menuaction_s s_keys_look_up_action;
534: static menuaction_s s_keys_look_down_action;
535: static menuaction_s s_keys_center_view_action;
536: static menuaction_s s_keys_mouse_look_action;
537: static menuaction_s s_keys_keyboard_look_action;
538: static menuaction_s s_keys_move_up_action;
539: static menuaction_s s_keys_move_down_action;
540: static menuaction_s s_keys_inventory_action;
541: static menuaction_s s_keys_inv_use_action;
542: static menuaction_s s_keys_inv_drop_action;
543: static menuaction_s s_keys_inv_prev_action;
544: static menuaction_s s_keys_inv_next_action;
545: static menuaction_s s_keys_help_computer_action;
546: static void M_UnbindCommand (char *command)
547: {
548: int j;
549: int l;
550: char *b;
551: l = strlen(command);
552: for (j=0 ; j<256 ; j++)
553: {
554: b = keybindings[j];
555: if (!b)
556: continue;
557: if (!strncmp (b, command, l) )
558: Key_SetBinding (j, "");
559: }
560: }
561: static void M_FindKeysForCommand (char *command, int *twokeys)
562: {
563: int count;
564: int j;
565: int l;
566: char *b;
567: twokeys[0] = twokeys[1] = -1;
568: l = strlen(command);
569: count = 0;
570: for (j=0 ; j<256 ; j++)
571: {
572: b = keybindings[j];
573: if (!b)
574: continue;
575: if (!strncmp (b, command, l) )
576: {
577: twokeys[count] = j;
578: count++;
579: if (count == 2)
580: break;
581: }
582: }
583: }
584: static void KeyCursorDrawFunc( menuframework_s *menu )
585: {
586: if ( bind_grab )
587: re.DrawChar( menu->x, menu->y + menu->cursor * 9, '=' );
588: else
589: re.DrawChar( menu->x, menu->y + menu->cursor * 9, 12 + ( ( int ) ( Sys_Milliseconds() / 250 ) & 1 ) );
590: }
591: static void DrawKeyBindingFunc( void *self )
592: {
593: int keys[2];
594: menuaction_s *a = ( menuaction_s * ) self;
595: M_FindKeysForCommand( bindnames[a->generic.localdata[0]][0], keys);
596:
597: if (keys[0] == -1)
598: {
599: Menu_DrawString( a->generic.x + a->generic.parent->x + 16, a->generic.y + a->generic.parent->y, "???" );
600: }
601: else
602: {
603: int x;
604: const char *name;
605: name = Key_KeynumToString (keys[0]);
606: Menu_DrawString( a->generic.x + a->generic.parent->x + 16, a->generic.y + a->generic.parent->y, name );
607: x = strlen(name) * 8;
608: if (keys[1] != -1)
609: {
610: Menu_DrawString( a->generic.x + a->generic.parent->x + 24 + x, a->generic.y + a->generic.parent->y, "or" );
611: Menu_DrawString( a->generic.x + a->generic.parent->x + 48 + x, a->generic.y + a->generic.parent->y, Key_KeynumToString (keys[1]) );
612: }
613: }
614: }
615: static void KeyBindingFunc( void *self )
616: {
617: menuaction_s *a = ( menuaction_s * ) self;
618: int keys[2];
619: M_FindKeysForCommand( bindnames[a->generic.localdata[0]][0], keys );
620: if (keys[1] != -1)
621: M_UnbindCommand( bindnames[a->generic.localdata[0]][0]);
622: bind_grab = true;
623: Menu_SetStatusBar( &s_keys_menu, "press a key or button for this action" );
624: }
625: static void Keys_MenuInit( void )
626: {
627: int y = 0;
628: int i = 0;
629: s_keys_menu.x = viddef.width * 0.50;
630: s_keys_menu.nitems = 0;
631: s_keys_menu.cursordraw = KeyCursorDrawFunc;
632: s_keys_attack_action.generic.type = MTYPE_ACTION;
633: s_keys_attack_action.generic.flags = QMF_GRAYED;
634: s_keys_attack_action.generic.x = 0;
635: s_keys_attack_action.generic.y = y;
636: s_keys_attack_action.generic.ownerdraw = DrawKeyBindingFunc;
637: s_keys_attack_action.generic.localdata[0] = i;
638: s_keys_attack_action.generic.name = bindnames[s_keys_attack_action.generic.localdata[0]][1];
639: s_keys_change_weapon_action.generic.type = MTYPE_ACTION;
640: s_keys_change_weapon_action.generic.flags = QMF_GRAYED;
641: s_keys_change_weapon_action.generic.x = 0;
642: s_keys_change_weapon_action.generic.y = y += 9;
643: s_keys_change_weapon_action.generic.ownerdraw = DrawKeyBindingFunc;
644: s_keys_change_weapon_action.generic.localdata[0] = ++i;
645: s_keys_change_weapon_action.generic.name = bindnames[s_keys_change_weapon_action.generic.localdata[0]][1];
646: s_keys_walk_forward_action.generic.type = MTYPE_ACTION;
647: s_keys_walk_forward_action.generic.flags = QMF_GRAYED;
648: s_keys_walk_forward_action.generic.x = 0;
649: s_keys_walk_forward_action.generic.y = y += 9;
650: s_keys_walk_forward_action.generic.ownerdraw = DrawKeyBindingFunc;
651: s_keys_walk_forward_action.generic.localdata[0] = ++i;
652: s_keys_walk_forward_action.generic.name = bindnames[s_keys_walk_forward_action.generic.localdata[0]][1];
653: s_keys_backpedal_action.generic.type = MTYPE_ACTION;
654: s_keys_backpedal_action.generic.flags = QMF_GRAYED;
655: s_keys_backpedal_action.generic.x = 0;
656: s_keys_backpedal_action.generic.y = y += 9;
657: s_keys_backpedal_action.generic.ownerdraw = DrawKeyBindingFunc;
658: s_keys_backpedal_action.generic.localdata[0] = ++i;
659: s_keys_backpedal_action.generic.name = bindnames[s_keys_backpedal_action.generic.localdata[0]][1];
660: s_keys_turn_left_action.generic.type = MTYPE_ACTION;
661: s_keys_turn_left_action.generic.flags = QMF_GRAYED;
662: s_keys_turn_left_action.generic.x = 0;
663: s_keys_turn_left_action.generic.y = y += 9;
664: s_keys_turn_left_action.generic.ownerdraw = DrawKeyBindingFunc;
665: s_keys_turn_left_action.generic.localdata[0] = ++i;
666: s_keys_turn_left_action.generic.name = bindnames[s_keys_turn_left_action.generic.localdata[0]][1];
667: s_keys_turn_right_action.generic.type = MTYPE_ACTION;
668: s_keys_turn_right_action.generic.flags = QMF_GRAYED;
669: s_keys_turn_right_action.generic.x = 0;
670: s_keys_turn_right_action.generic.y = y += 9;
671: s_keys_turn_right_action.generic.ownerdraw = DrawKeyBindingFunc;
672: s_keys_turn_right_action.generic.localdata[0] = ++i;
673: s_keys_turn_right_action.generic.name = bindnames[s_keys_turn_right_action.generic.localdata[0]][1];
674: s_keys_run_action.generic.type = MTYPE_ACTION;
675: s_keys_run_action.generic.flags = QMF_GRAYED;
676: s_keys_run_action.generic.x = 0;
677: s_keys_run_action.generic.y = y += 9;
678: s_keys_run_action.generic.ownerdraw = DrawKeyBindingFunc;
679: s_keys_run_action.generic.localdata[0] = ++i;
680: s_keys_run_action.generic.name = bindnames[s_keys_run_action.generic.localdata[0]][1];
681: s_keys_step_left_action.generic.type = MTYPE_ACTION;
682: s_keys_step_left_action.generic.flags = QMF_GRAYED;
683: s_keys_step_left_action.generic.x = 0;
684: s_keys_step_left_action.generic.y = y += 9;
685: s_keys_step_left_action.generic.ownerdraw = DrawKeyBindingFunc;
686: s_keys_step_left_action.generic.localdata[0] = ++i;
687: s_keys_step_left_action.generic.name = bindnames[s_keys_step_left_action.generic.localdata[0]][1];
688: s_keys_step_right_action.generic.type = MTYPE_ACTION;
689: s_keys_step_right_action.generic.flags = QMF_GRAYED;
690: s_keys_step_right_action.generic.x = 0;
691: s_keys_step_right_action.generic.y = y += 9;
692: s_keys_step_right_action.generic.ownerdraw = DrawKeyBindingFunc;
693: s_keys_step_right_action.generic.localdata[0] = ++i;
694: s_keys_step_right_action.generic.name = bindnames[s_keys_step_right_action.generic.localdata[0]][1];
695: s_keys_sidestep_action.generic.type = MTYPE_ACTION;
696: s_keys_sidestep_action.generic.flags = QMF_GRAYED;
697: s_keys_sidestep_action.generic.x = 0;
698: s_keys_sidestep_action.generic.y = y += 9;
699: s_keys_sidestep_action.generic.ownerdraw = DrawKeyBindingFunc;
700: s_keys_sidestep_action.generic.localdata[0] = ++i;
701: s_keys_sidestep_action.generic.name = bindnames[s_keys_sidestep_action.generic.localdata[0]][1];
702: s_keys_look_up_action.generic.type = MTYPE_ACTION;
703: s_keys_look_up_action.generic.flags = QMF_GRAYED;
704: s_keys_look_up_action.generic.x = 0;
705: s_keys_look_up_action.generic.y = y += 9;
706: s_keys_look_up_action.generic.ownerdraw = DrawKeyBindingFunc;
707: s_keys_look_up_action.generic.localdata[0] = ++i;
708: s_keys_look_up_action.generic.name = bindnames[s_keys_look_up_action.generic.localdata[0]][1];
709: s_keys_look_down_action.generic.type = MTYPE_ACTION;
710: s_keys_look_down_action.generic.flags = QMF_GRAYED;
711: s_keys_look_down_action.generic.x = 0;
712: s_keys_look_down_action.generic.y = y += 9;
713: s_keys_look_down_action.generic.ownerdraw = DrawKeyBindingFunc;
714: s_keys_look_down_action.generic.localdata[0] = ++i;
715: s_keys_look_down_action.generic.name = bindnames[s_keys_look_down_action.generic.localdata[0]][1];
716: s_keys_center_view_action.generic.type = MTYPE_ACTION;
717: s_keys_center_view_action.generic.flags = QMF_GRAYED;
718: s_keys_center_view_action.generic.x = 0;
719: s_keys_center_view_action.generic.y = y += 9;
720: s_keys_center_view_action.generic.ownerdraw = DrawKeyBindingFunc;
721: s_keys_center_view_action.generic.localdata[0] = ++i;
722: s_keys_center_view_action.generic.name = bindnames[s_keys_center_view_action.generic.localdata[0]][1];
723: s_keys_mouse_look_action.generic.type = MTYPE_ACTION;
724: s_keys_mouse_look_action.generic.flags = QMF_GRAYED;
725: s_keys_mouse_look_action.generic.x = 0;
726: s_keys_mouse_look_action.generic.y = y += 9;
727: s_keys_mouse_look_action.generic.ownerdraw = DrawKeyBindingFunc;
728: s_keys_mouse_look_action.generic.localdata[0] = ++i;
729: s_keys_mouse_look_action.generic.name = bindnames[s_keys_mouse_look_action.generic.localdata[0]][1];
730: s_keys_keyboard_look_action.generic.type = MTYPE_ACTION;
731: s_keys_keyboard_look_action.generic.flags = QMF_GRAYED;
732: s_keys_keyboard_look_action.generic.x = 0;
733: s_keys_keyboard_look_action.generic.y = y += 9;
734: s_keys_keyboard_look_action.generic.ownerdraw = DrawKeyBindingFunc;
735: s_keys_keyboard_look_action.generic.localdata[0] = ++i;
736: s_keys_keyboard_look_action.generic.name = bindnames[s_keys_keyboard_look_action.generic.localdata[0]][1];
737: s_keys_move_up_action.generic.type = MTYPE_ACTION;
738: s_keys_move_up_action.generic.flags = QMF_GRAYED;
739: s_keys_move_up_action.generic.x = 0;
740: s_keys_move_up_action.generic.y = y += 9;
741: s_keys_move_up_action.generic.ownerdraw = DrawKeyBindingFunc;
742: s_keys_move_up_action.generic.localdata[0] = ++i;
743: s_keys_move_up_action.generic.name = bindnames[s_keys_move_up_action.generic.localdata[0]][1];
744: s_keys_move_down_action.generic.type = MTYPE_ACTION;
745: s_keys_move_down_action.generic.flags = QMF_GRAYED;
746: s_keys_move_down_action.generic.x = 0;
747: s_keys_move_down_action.generic.y = y += 9;
748: s_keys_move_down_action.generic.ownerdraw = DrawKeyBindingFunc;
749: s_keys_move_down_action.generic.localdata[0] = ++i;
750: s_keys_move_down_action.generic.name = bindnames[s_keys_move_down_action.generic.localdata[0]][1];
751: s_keys_inventory_action.generic.type = MTYPE_ACTION;
752: s_keys_inventory_action.generic.flags = QMF_GRAYED;
753: s_keys_inventory_action.generic.x = 0;
754: s_keys_inventory_action.generic.y = y += 9;
755: s_keys_inventory_action.generic.ownerdraw = DrawKeyBindingFunc;
756: s_keys_inventory_action.generic.localdata[0] = ++i;
757: s_keys_inventory_action.generic.name = bindnames[s_keys_inventory_action.generic.localdata[0]][1];
758: s_keys_inv_use_action.generic.type = MTYPE_ACTION;
759: s_keys_inv_use_action.generic.flags = QMF_GRAYED;
760: s_keys_inv_use_action.generic.x = 0;
761: s_keys_inv_use_action.generic.y = y += 9;
762: s_keys_inv_use_action.generic.ownerdraw = DrawKeyBindingFunc;
763: s_keys_inv_use_action.generic.localdata[0] = ++i;
764: s_keys_inv_use_action.generic.name = bindnames[s_keys_inv_use_action.generic.localdata[0]][1];
765: s_keys_inv_drop_action.generic.type = MTYPE_ACTION;
766: s_keys_inv_drop_action.generic.flags = QMF_GRAYED;
767: s_keys_inv_drop_action.generic.x = 0;
768: s_keys_inv_drop_action.generic.y = y += 9;
769: s_keys_inv_drop_action.generic.ownerdraw = DrawKeyBindingFunc;
770: s_keys_inv_drop_action.generic.localdata[0] = ++i;
771: s_keys_inv_drop_action.generic.name = bindnames[s_keys_inv_drop_action.generic.localdata[0]][1];
772: s_keys_inv_prev_action.generic.type = MTYPE_ACTION;
773: s_keys_inv_prev_action.generic.flags = QMF_GRAYED;
774: s_keys_inv_prev_action.generic.x = 0;
775: s_keys_inv_prev_action.generic.y = y += 9;
776: s_keys_inv_prev_action.generic.ownerdraw = DrawKeyBindingFunc;
777: s_keys_inv_prev_action.generic.localdata[0] = ++i;
778: s_keys_inv_prev_action.generic.name = bindnames[s_keys_inv_prev_action.generic.localdata[0]][1];
779: s_keys_inv_next_action.generic.type = MTYPE_ACTION;
780: s_keys_inv_next_action.generic.flags = QMF_GRAYED;
781: s_keys_inv_next_action.generic.x = 0;
782: s_keys_inv_next_action.generic.y = y += 9;
783: s_keys_inv_next_action.generic.ownerdraw = DrawKeyBindingFunc;
784: s_keys_inv_next_action.generic.localdata[0] = ++i;
785: s_keys_inv_next_action.generic.name = bindnames[s_keys_inv_next_action.generic.localdata[0]][1];
786: s_keys_help_computer_action.generic.type = MTYPE_ACTION;
787: s_keys_help_computer_action.generic.flags = QMF_GRAYED;
788: s_keys_help_computer_action.generic.x = 0;
789: s_keys_help_computer_action.generic.y = y += 9;
790: s_keys_help_computer_action.generic.ownerdraw = DrawKeyBindingFunc;
791: s_keys_help_computer_action.generic.localdata[0] = ++i;
792: s_keys_help_computer_action.generic.name = bindnames[s_keys_help_computer_action.generic.localdata[0]][1];
793: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_attack_action );
794: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_change_weapon_action );
795: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_walk_forward_action );
796: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_backpedal_action );
797: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_turn_left_action );
798: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_turn_right_action );
799: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_run_action );
800: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_step_left_action );
801: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_step_right_action );
802: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_sidestep_action );
803: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_look_up_action );
804: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_look_down_action );
805: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_center_view_action );
806: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_mouse_look_action );
807: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_keyboard_look_action );
808: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_move_up_action );
809: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_move_down_action );
810: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inventory_action );
811: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_use_action );
812: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_drop_action );
813: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_prev_action );
814: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_next_action );
815: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_help_computer_action );
816:
817: Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
818: Menu_Center( &s_keys_menu );
819: }
820: static void Keys_MenuDraw (void)
821: {
822: Menu_AdjustCursor( &s_keys_menu, 1 );
823: Menu_Draw( &s_keys_menu );
824: }
825: static const char *Keys_MenuKey( int key )
826: {
827: menuaction_s *item = ( menuaction_s * ) Menu_ItemAtCursor( &s_keys_menu );
828: if ( bind_grab )
829: {
830: if ( key != K_ESCAPE && key != '`' )
831: {
832: char cmd[1024];
833: Com_sprintf (cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", Key_KeynumToString(key), bindnames[item->generic.localdata[0]][0]);
834: Cbuf_InsertText (cmd);
835: }
836:
837: Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
838: bind_grab = false;
839: return menu_out_sound;
840: }
841: switch ( key )
842: {
843: case K_KP_ENTER:
844: case K_ENTER:
845: KeyBindingFunc( item );
846: return menu_in_sound;
847: case K_BACKSPACE: // delete bindings
848: case K_DEL: // delete bindings
849: case K_KP_DEL:
850: M_UnbindCommand( bindnames[item->generic.localdata[0]][0] );
851: return menu_out_sound;
852: default:
853: return Default_MenuKey( &s_keys_menu, key );
854: }
855: }
856: void M_Menu_Keys_f (void)
857: {
858: Keys_MenuInit();
859: M_PushMenu( Keys_MenuDraw, Keys_MenuKey );
860: }
861: /*
862: =======================================================================
863: CONTROLS MENU
864: =======================================================================
865: */
866: static cvar_t *win_noalttab;
867: extern cvar_t *in_joystick;
868: static menuframework_s s_options_menu;
869: static menuaction_s s_options_defaults_action;
870: static menuaction_s s_options_customize_options_action;
871: static menuslider_s s_options_sensitivity_slider;
872: static menulist_s s_options_freelook_box;
873: static menulist_s s_options_noalttab_box;
874: static menulist_s s_options_alwaysrun_box;
875: static menulist_s s_options_invertmouse_box;
876: static menulist_s s_options_lookspring_box;
877: static menulist_s s_options_lookstrafe_box;
878: static menulist_s s_options_crosshair_box;
879: static menuslider_s s_options_sfxvolume_slider;
880: static menulist_s s_options_joystick_box;
881: static menulist_s s_options_cdvolume_box;
882: static menulist_s s_options_quality_list;
883: static menulist_s s_options_compatibility_list;
884: static menulist_s s_options_console_action;
885:
886: static void CrosshairFunc( void *unused )
887: {
888: Cvar_SetValue( "crosshair", s_options_crosshair_box.curvalue );
889: }
890:
891: static void JoystickFunc( void *unused )
892: {
893: Cvar_SetValue( "in_joystick", s_options_joystick_box.curvalue );
894: }
895: static void CustomizeControlsFunc( void *unused )
896: {
897: M_Menu_Keys_f();
898: }
899: static void AlwaysRunFunc( void *unused )
900: {
901: Cvar_SetValue( "cl_run", s_options_alwaysrun_box.curvalue );
902: }
903: static void FreeLookFunc( void *unused )
904: {
905: Cvar_SetValue( "freelook", s_options_freelook_box.curvalue );
906: }
907: static void MouseSpeedFunc( void *unused )
908: {
909: Cvar_SetValue( "sensitivity", s_options_sensitivity_slider.curvalue / 2.0F );
910: }
911: static void NoAltTabFunc( void *unused )
912: {
913: Cvar_SetValue( "win_noalttab", s_options_noalttab_box.curvalue );
914: }
915: static float ClampCvar( float min, float max, float value )
916: {
917: if ( value < min ) return min;
918: if ( value > max ) return max;
919: return value;
920: }
921:
922: static void ControlsSetMenuItemValues( void )
923: {
924: s_options_sfxvolume_slider.curvalue = Cvar_VariableValue( "s_volume" ) * 10;
925: s_options_cdvolume_box.curvalue = !Cvar_VariableValue("cd_nocd");
926: s_options_quality_list.curvalue = !Cvar_VariableValue( "s_loadas8bit" );
927: s_options_sensitivity_slider.curvalue = ( sensitivity->value ) * 2;
928:
929: Cvar_SetValue( "cl_run", ClampCvar( 0, 1, cl_run->value ) );
930: s_options_alwaysrun_box.curvalue = cl_run->value;
931:
932: s_options_invertmouse_box.curvalue = m_pitch->value < 0;
933:
934: Cvar_SetValue( "lookspring", ClampCvar( 0, 1, lookspring->value ) );
935: s_options_lookspring_box.curvalue = lookspring->value;
936:
937: Cvar_SetValue( "lookstrafe", ClampCvar( 0, 1, lookstrafe->value ) );
938: s_options_lookstrafe_box.curvalue = lookstrafe->value;
939:
940: Cvar_SetValue( "freelook", ClampCvar( 0, 1, freelook->value ) );
941: s_options_freelook_box.curvalue = freelook->value;
942:
943: Cvar_SetValue( "crosshair", ClampCvar( 0, 3, crosshair->value ) );
944: s_options_crosshair_box.curvalue = crosshair->value;
945:
946: Cvar_SetValue( "in_joystick", ClampCvar( 0, 1, in_joystick->value ) );
947: s_options_joystick_box.curvalue = in_joystick->value;
948:
949: s_options_noalttab_box.curvalue = win_noalttab->value;
950: }
951: static void ControlsResetDefaultsFunc( void *unused )
952: {
953: Cbuf_AddText ("exec default.cfg\n");
954: Cbuf_Execute();
955:
956: ControlsSetMenuItemValues();
957: }
958: static void InvertMouseFunc( void *unused )
959: {
960: Cvar_SetValue( "m_pitch", -m_pitch->value );
961: }
962: static void LookspringFunc( void *unused )
963: {
964: Cvar_SetValue( "lookspring", !lookspring->value );
965: }
966: static void LookstrafeFunc( void *unused )
967: {
968: Cvar_SetValue( "lookstrafe", !lookstrafe->value );
969: }
970: static void UpdateVolumeFunc( void *unused )
971: {
972: Cvar_SetValue( "s_volume", s_options_sfxvolume_slider.curvalue / 10 );
973: }
974:
975: static void UpdateCDVolumeFunc( void *unused )
976: {
977: Cvar_SetValue( "cd_nocd", !s_options_cdvolume_box.curvalue );
978: }
979:
980: static void ConsoleFunc( void *unused )
981: {
982: /*
983: ** the proper way to do this is probably to have ToggleConsole_f accept a parameter
984: */
985: extern void Key_ClearTyping( void );
986:
987: if ( cl.attractloop )
988: {
989: Cbuf_AddText ("killserver\n");
990: return;
991: }
992:
993: Key_ClearTyping ();
994: Con_ClearNotify ();
995:
996: M_ForceMenuOff ();
997: cls.key_dest = key_console;
998: }
999:
1000: static void UpdateSoundQualityFunc( void *unused )
1001: {
1002: if ( s_options_quality_list.curvalue )
1003: {
1004: Cvar_SetValue( "s_khz", 22 );
1005: Cvar_SetValue( "s_loadas8bit", false );
1006: }
1007: else
1008: {
1009: Cvar_SetValue( "s_khz", 11 );
1010: Cvar_SetValue( "s_loadas8bit", true );
1011: }
1012:
1013: Cvar_SetValue( "s_primary", s_options_compatibility_list.curvalue );
1014:
1015: M_DrawTextBox( 8, 120 - 48, 36, 3 );
1016: M_Print( 16 + 16, 120 - 48 + 8, "Restarting the sound system. This" );
1017: M_Print( 16 + 16, 120 - 48 + 16, "could take up to a minute, so" );
1018: M_Print( 16 + 16, 120 - 48 + 24, "please be patient." );
1019:
1020: // the text box won't show up unless we do a buffer swap
1021: re.EndFrame();
1022:
1023: CL_Snd_Restart_f();
1024: }
1025:
1026: void Options_MenuInit( void )
1027: {
1028: static const char *cd_music_items[] =
1029: {
1030: "disabled",
1031: "enabled",
1032: 0
1033: };
1034: static const char *quality_items[] =
1035: {
1036: "low", "high", 0
1037: };
1038:
1039: static const char *compatibility_items[] =
1040: {
1041: "max compatibility", "max performance", 0
1042: };
1043:
1044: static const char *yesno_names[] =
1045: {
1046: "no",
1047: "yes",
1048: 0
1049: };
1050: static const char *crosshair_names[] =
1051: {
1052: "none",
1053: "cross",
1054: "dot",
1055: "angle",
1056: 0
1057: };
1058: win_noalttab = Cvar_Get( "win_noalttab", "0", CVAR_ARCHIVE );
1059: /*
1060: ** configure controls menu and menu items
1061: */
1062: s_options_menu.x = viddef.width / 2;
1063: s_options_menu.y = viddef.height / 2 - 58;
1064: s_options_menu.nitems = 0;
1065:
1066: s_options_sfxvolume_slider.generic.type = MTYPE_SLIDER;
1067: s_options_sfxvolume_slider.generic.x = 0;
1068: s_options_sfxvolume_slider.generic.y = 0;
1069: s_options_sfxvolume_slider.generic.name = "effects volume";
1070: s_options_sfxvolume_slider.generic.callback = UpdateVolumeFunc;
1071: s_options_sfxvolume_slider.minvalue = 0;
1072: s_options_sfxvolume_slider.maxvalue = 10;
1073: s_options_sfxvolume_slider.curvalue = Cvar_VariableValue( "s_volume" ) * 10;
1074:
1075: s_options_cdvolume_box.generic.type = MTYPE_SPINCONTROL;
1076: s_options_cdvolume_box.generic.x = 0;
1077: s_options_cdvolume_box.generic.y = 10;
1078: s_options_cdvolume_box.generic.name = "CD music";
1079: s_options_cdvolume_box.generic.callback = UpdateCDVolumeFunc;
1080: s_options_cdvolume_box.itemnames = cd_music_items;
1081: s_options_cdvolume_box.curvalue = !Cvar_VariableValue("cd_nocd");
1082:
1083: s_options_quality_list.generic.type = MTYPE_SPINCONTROL;
1084: s_options_quality_list.generic.x = 0;
1085: s_options_quality_list.generic.y = 20;;
1086: s_options_quality_list.generic.name = "sound quality";
1087: s_options_quality_list.generic.callback = UpdateSoundQualityFunc;
1088: s_options_quality_list.itemnames = quality_items;
1089: s_options_quality_list.curvalue = !Cvar_VariableValue( "s_loadas8bit" );
1090:
1091: s_options_compatibility_list.generic.type = MTYPE_SPINCONTROL;
1092: s_options_compatibility_list.generic.x = 0;
1093: s_options_compatibility_list.generic.y = 30;
1094: s_options_compatibility_list.generic.name = "sound compatibility";
1095: s_options_compatibility_list.generic.callback = UpdateSoundQualityFunc;
1096: s_options_compatibility_list.itemnames = compatibility_items;
1097: s_options_compatibility_list.curvalue = Cvar_VariableValue( "s_primary" );
1098:
1099: s_options_sensitivity_slider.generic.type = MTYPE_SLIDER;
1100: s_options_sensitivity_slider.generic.x = 0;
1101: s_options_sensitivity_slider.generic.y = 50;
1102: s_options_sensitivity_slider.generic.name = "mouse speed";
1103: s_options_sensitivity_slider.generic.callback = MouseSpeedFunc;
1104: s_options_sensitivity_slider.minvalue = 2;
1105: s_options_sensitivity_slider.maxvalue = 22;
1106: s_options_alwaysrun_box.generic.type = MTYPE_SPINCONTROL;
1107: s_options_alwaysrun_box.generic.x = 0;
1108: s_options_alwaysrun_box.generic.y = 60;
1109: s_options_alwaysrun_box.generic.name = "always run";
1110: s_options_alwaysrun_box.generic.callback = AlwaysRunFunc;
1111: s_options_alwaysrun_box.itemnames = yesno_names;
1112: s_options_invertmouse_box.generic.type = MTYPE_SPINCONTROL;
1113: s_options_invertmouse_box.generic.x = 0;
1114: s_options_invertmouse_box.generic.y = 70;
1115: s_options_invertmouse_box.generic.name = "invert mouse";
1116: s_options_invertmouse_box.generic.callback = InvertMouseFunc;
1117: s_options_invertmouse_box.itemnames = yesno_names;
1118: s_options_lookspring_box.generic.type = MTYPE_SPINCONTROL;
1119: s_options_lookspring_box.generic.x = 0;
1120: s_options_lookspring_box.generic.y = 80;
1121: s_options_lookspring_box.generic.name = "lookspring";
1122: s_options_lookspring_box.generic.callback = LookspringFunc;
1123: s_options_lookspring_box.itemnames = yesno_names;
1124: s_options_lookstrafe_box.generic.type = MTYPE_SPINCONTROL;
1125: s_options_lookstrafe_box.generic.x = 0;
1126: s_options_lookstrafe_box.generic.y = 90;
1127: s_options_lookstrafe_box.generic.name = "lookstrafe";
1128: s_options_lookstrafe_box.generic.callback = LookstrafeFunc;
1129: s_options_lookstrafe_box.itemnames = yesno_names;
1130: s_options_freelook_box.generic.type = MTYPE_SPINCONTROL;
1131: s_options_freelook_box.generic.x = 0;
1132: s_options_freelook_box.generic.y = 100;
1133: s_options_freelook_box.generic.name = "free look";
1134: s_options_freelook_box.generic.callback = FreeLookFunc;
1135: s_options_freelook_box.itemnames = yesno_names;
1136:
1137: s_options_crosshair_box.generic.type = MTYPE_SPINCONTROL;
1138: s_options_crosshair_box.generic.x = 0;
1139: s_options_crosshair_box.generic.y = 110;
1140: s_options_crosshair_box.generic.name = "crosshair";
1141: s_options_crosshair_box.generic.callback = CrosshairFunc;
1142: s_options_crosshair_box.itemnames = crosshair_names;
1143: /*
1144: s_options_noalttab_box.generic.type = MTYPE_SPINCONTROL;
1145: s_options_noalttab_box.generic.x = 0;
1146: s_options_noalttab_box.generic.y = 110;
1147: s_options_noalttab_box.generic.name = "disable alt-tab";
1148: s_options_noalttab_box.generic.callback = NoAltTabFunc;
1149: s_options_noalttab_box.itemnames = yesno_names;
1150: */
1151: s_options_joystick_box.generic.type = MTYPE_SPINCONTROL;
1152: s_options_joystick_box.generic.x = 0;
1153: s_options_joystick_box.generic.y = 120;
1154: s_options_joystick_box.generic.name = "use joystick";
1155: s_options_joystick_box.generic.callback = JoystickFunc;
1156: s_options_joystick_box.itemnames = yesno_names;
1157:
1158: s_options_customize_options_action.generic.type = MTYPE_ACTION;
1159: s_options_customize_options_action.generic.x = 0;
1160: s_options_customize_options_action.generic.y = 140;
1161: s_options_customize_options_action.generic.name = "customize controls";
1162: s_options_customize_options_action.generic.callback = CustomizeControlsFunc;
1163: s_options_defaults_action.generic.type = MTYPE_ACTION;
1164: s_options_defaults_action.generic.x = 0;
1165: s_options_defaults_action.generic.y = 150;
1166: s_options_defaults_action.generic.name = "reset defaults";
1167: s_options_defaults_action.generic.callback = ControlsResetDefaultsFunc;
1168:
1169: s_options_console_action.generic.type = MTYPE_ACTION;
1170: s_options_console_action.generic.x = 0;
1171: s_options_console_action.generic.y = 160;
1172: s_options_console_action.generic.name = "go to console";
1173: s_options_console_action.generic.callback = ConsoleFunc;
1174:
1175: ControlsSetMenuItemValues();
1176:
1177: Menu_AddItem( &s_options_menu, ( void * ) &s_options_sfxvolume_slider );
1178: Menu_AddItem( &s_options_menu, ( void * ) &s_options_cdvolume_box );
1179: Menu_AddItem( &s_options_menu, ( void * ) &s_options_quality_list );
1180: Menu_AddItem( &s_options_menu, ( void * ) &s_options_compatibility_list );
1181: Menu_AddItem( &s_options_menu, ( void * ) &s_options_sensitivity_slider );
1182: Menu_AddItem( &s_options_menu, ( void * ) &s_options_alwaysrun_box );
1183: Menu_AddItem( &s_options_menu, ( void * ) &s_options_invertmouse_box );
1184: Menu_AddItem( &s_options_menu, ( void * ) &s_options_lookspring_box );
1185: Menu_AddItem( &s_options_menu, ( void * ) &s_options_lookstrafe_box );
1186: Menu_AddItem( &s_options_menu, ( void * ) &s_options_freelook_box );
1187: Menu_AddItem( &s_options_menu, ( void * ) &s_options_crosshair_box );
1188: Menu_AddItem( &s_options_menu, ( void * ) &s_options_joystick_box );
1189: Menu_AddItem( &s_options_menu, ( void * ) &s_options_customize_options_action );
1190: Menu_AddItem( &s_options_menu, ( void * ) &s_options_defaults_action );
1191: Menu_AddItem( &s_options_menu, ( void * ) &s_options_console_action );
1192: }
1193: void Options_MenuDraw (void)
1194: {
1195: M_Banner( "m_banner_options" );
1196: Menu_AdjustCursor( &s_options_menu, 1 );
1197: Menu_Draw( &s_options_menu );
1198: }
1199: const char *Options_MenuKey( int key )
1200: {
1201: return Default_MenuKey( &s_options_menu, key );
1202: }
1203: void M_Menu_Options_f (void)
1204: {
1205: Options_MenuInit();
1206: M_PushMenu ( Options_MenuDraw, Options_MenuKey );
1207: }
1208: /*
1209: =======================================================================
1210: VIDEO MENU
1211: =======================================================================
1212: */
1213: void M_Menu_Video_f (void)
1214: {
1215: VID_MenuInit();
1216: M_PushMenu( VID_MenuDraw, VID_MenuKey );
1217: }
1218: /*
1219: =============================================================================
1220:
1221: END GAME MENU
1222:
1223: =============================================================================
1224: */
1225: static int credits_start_time;
1226: static const char *credits[] =
1227: {
1228: "+QUAKE II BY ID SOFTWARE",
1229: "",
1230: "+PROGRAMMING",
1231: "John Carmack",
1232: "John Cash",
1233: "Brian Hook",
1234: "",
1235: "+ART",
1236: "Adrian Carmack",
1237: "Kevin Cloud",
1238: "Paul Steed",
1239: "",
1240: "+LEVEL DESIGN",
1241: "Tim Willits",
1242: "American McGee",
1243: "Christian Antkow",
1244: "Paul Jaquays",
1245: "Brandon James",
1246: "",
1247: "+BIZ",
1248: "Todd Hollenshead",
1249: "Barrett (Bear) Alexander",
1250: "Donna Jackson",
1251: "",
1252: "",
1253: "+SPECIAL THANKS",
1254: "Ben Donges for beta testing",
1255: "",
1256: "",
1257: "",
1258: "",
1259: "",
1260: "",
1261: "+ADDITIONAL SUPPORT",
1262: "",
1263: "+LINUX PORT AND CTF",
1264: "Dave \"Zoid\" Kirsch",
1265: "",
1266: "+CINEMATIC SEQUENCES",
1267: "Ending Cinematic by Blur Studio - ",
1268: "Venice, CA",
1269: "",
1270: "Environment models for Introduction",
1271: "Cinematic by Karl Dolgener",
1272: "",
1273: "Assistance with environment design",
1274: "by Cliff Iwai",
1275: "",
1276: "+SOUND EFFECTS AND MUSIC",
1277: "Sound Design by Soundelux Media Labs.",
1278: "Music Composed and Produced by",
1279: "Soundelux Media Labs. Special thanks",
1280: "to Bill Brown, Tom Ozanich, Brian",
1281: "Celano, Jeff Eisner, and The Soundelux",
1282: "Players.",
1283: "",
1284: "\"Level Music\" by Sonic Mayhem",
1285: "www.sonicmayhem.com",
1286: "",
1287: "\"Quake II Theme Song\"",
1288: "(C) 1997 Rob Zombie. All Rights",
1289: "Reserved.",
1290: "",
1291: "Track 10 (\"Climb\") by Jer Sypult",
1292: "",
1293: "Voice of computers by",
1294: "Carly Staehlin-Taylor",
1295: "",
1296: "+THANKS TO ACTIVISION",
1297: "+IN PARTICULAR:",
1298: "",
1299: "John Tam",
1300: "Steve Rosenthal",
1301: "Marty Stratton",
1302: "Henk Hartong",
1303: "",
1304: "Quake II(tm) (C)1997 Id Software, Inc.",
1305: "All Rights Reserved. Distributed by",
1306: "Activision, Inc. under license.",
1307: "Quake II(tm), the Id Software name,",
1308: "the \"Q II\"(tm) logo and id(tm)",
1309: "logo are trademarks of Id Software,",
1310: "Inc. Activision(R) is a registered",
1311: "trademark of Activision, Inc. All",
1312: "other trademarks and trade names are",
1313: "properties of their respective owners.",
1314: 0
1315: };
1316:
1317: void M_Credits_MenuDraw( void )
1318: {
1319: int i, y;
1320:
1321: /*
1322: ** draw the credits
1323: */
1324: for ( i = 0, y = viddef.height - ( ( cls.realtime - credits_start_time ) / 40.0F ); credits[i] && y < viddef.height; y += 10, i++ )
1325: {
1326: int j, stringoffset = 0;
1327: int bold = false;
1328:
1329: if ( y <= -8 )
1330: continue;
1331:
1332: if ( credits[i][0] == '+' )
1333: {
1334: bold = true;
1335: stringoffset = 1;
1336: }
1337: else
1338: {
1339: bold = false;
1340: stringoffset = 0;
1341: }
1342:
1343: for ( j = 0; credits[i][j+stringoffset]; j++ )
1344: {
1345: int x;
1346:
1347: x = ( viddef.width - strlen( credits[i] ) * 8 - stringoffset * 8 ) / 2 + ( j + stringoffset ) * 8;
1348:
1349: if ( bold )
1350: re.DrawChar( x, y, credits[i][j+stringoffset] + 128 );
1351: else
1352: re.DrawChar( x, y, credits[i][j+stringoffset] );
1353: }
1354: }
1355:
1356: if ( y < 0 )
1357: credits_start_time = cls.realtime;
1358: }
1359:
1360: const char *M_Credits_Key( int key )
1361: {
1362: switch (key)
1363: {
1364: case K_ESCAPE:
1365: M_PopMenu ();
1366: break;
1367: }
1368:
1369: return menu_out_sound;
1370:
1371: }
1372:
1373: void M_Menu_Credits_f( void )
1374: {
1375: credits_start_time = cls.realtime;
1376: M_PushMenu( M_Credits_MenuDraw, M_Credits_Key);
1377: }
1378: /*
1379: =============================================================================
1380:
1381: GAME MENU
1382:
1383: =============================================================================
1384: */
1385: static int m_game_cursor;
1386: static menuframework_s s_game_menu;
1387: static menuaction_s s_easy_game_action;
1388: static menuaction_s s_medium_game_action;
1389: static menuaction_s s_hard_game_action;
1390: static menuaction_s s_load_game_action;
1391: static menuaction_s s_save_game_action;
1392: static menuaction_s s_credits_action;
1393: static menuseparator_s s_blankline;
1394: static void StartGame( void )
1395: {
1396: // disable updates and start the cinematic going
1397: cl.servercount = -1;
1398: M_ForceMenuOff ();
1399: Cvar_SetValue( "deathmatch", 0 );
1400: Cvar_SetValue( "coop", 0 );
1401: Cbuf_AddText ("loading ; killserver ; wait ; newgame\n");
1402: cls.key_dest = key_game;
1403: }
1404: static void EasyGameFunc( void *data )
1405: {
1406: Cvar_ForceSet( "skill", "0" );
1407: StartGame();
1408: }
1409: static void MediumGameFunc( void *data )
1410: {
1411: Cvar_ForceSet( "skill", "1" );
1412: StartGame();
1413: }
1414: static void HardGameFunc( void *data )
1415: {
1416: Cvar_ForceSet( "skill", "2" );
1417: StartGame();
1418: }
1419: static void LoadGameFunc( void *unused )
1420: {
1421: M_Menu_LoadGame_f ();
1422: }
1423: static void SaveGameFunc( void *unused )
1424: {
1425: M_Menu_SaveGame_f();
1426: }
1427: static void CreditsFunc( void *unused )
1428: {
1429: M_Menu_Credits_f();
1430: }
1431: void Game_MenuInit( void )
1432: {
1433: static const char *difficulty_names[] =
1434: {
1435: "easy",
1436: "medium",
1437: "hard",
1438: 0
1439: };
1440: s_game_menu.x = viddef.width * 0.50;
1441: s_game_menu.nitems = 0;
1442: s_easy_game_action.generic.type = MTYPE_ACTION;
1443: s_easy_game_action.generic.flags = QMF_LEFT_JUSTIFY;
1444: s_easy_game_action.generic.x = 0;
1445: s_easy_game_action.generic.y = 0;
1446: s_easy_game_action.generic.name = "easy";
1447: s_easy_game_action.generic.callback = EasyGameFunc;
1448: s_medium_game_action.generic.type = MTYPE_ACTION;
1449: s_medium_game_action.generic.flags = QMF_LEFT_JUSTIFY;
1450: s_medium_game_action.generic.x = 0;
1451: s_medium_game_action.generic.y = 10;
1452: s_medium_game_action.generic.name = "medium";
1453: s_medium_game_action.generic.callback = MediumGameFunc;
1454: s_hard_game_action.generic.type = MTYPE_ACTION;
1455: s_hard_game_action.generic.flags = QMF_LEFT_JUSTIFY;
1456: s_hard_game_action.generic.x = 0;
1457: s_hard_game_action.generic.y = 20;
1458: s_hard_game_action.generic.name = "hard";
1459: s_hard_game_action.generic.callback = HardGameFunc;
1460: s_blankline.generic.type = MTYPE_SEPARATOR;
1461:
1462: s_load_game_action.generic.type = MTYPE_ACTION;
1463: s_load_game_action.generic.flags = QMF_LEFT_JUSTIFY;
1464: s_load_game_action.generic.x = 0;
1465: s_load_game_action.generic.y = 40;
1466: s_load_game_action.generic.name = "load game";
1467: s_load_game_action.generic.callback = LoadGameFunc;
1468: s_save_game_action.generic.type = MTYPE_ACTION;
1469: s_save_game_action.generic.flags = QMF_LEFT_JUSTIFY;
1470: s_save_game_action.generic.x = 0;
1471: s_save_game_action.generic.y = 50;
1472: s_save_game_action.generic.name = "save game";
1473: s_save_game_action.generic.callback = SaveGameFunc;
1474:
1475: s_credits_action.generic.type = MTYPE_ACTION;
1476: s_credits_action.generic.flags = QMF_LEFT_JUSTIFY;
1477: s_credits_action.generic.x = 0;
1478: s_credits_action.generic.y = 60;
1479: s_credits_action.generic.name = "credits";
1480: s_credits_action.generic.callback = CreditsFunc;
1481: Menu_AddItem( &s_game_menu, ( void * ) &s_easy_game_action );
1482: Menu_AddItem( &s_game_menu, ( void * ) &s_medium_game_action );
1483: Menu_AddItem( &s_game_menu, ( void * ) &s_hard_game_action );
1484: Menu_AddItem( &s_game_menu, ( void * ) &s_blankline );
1485: Menu_AddItem( &s_game_menu, ( void * ) &s_load_game_action );
1486: Menu_AddItem( &s_game_menu, ( void * ) &s_save_game_action );
1487: Menu_AddItem( &s_game_menu, ( void * ) &s_blankline );
1488: Menu_AddItem( &s_game_menu, ( void * ) &s_credits_action );
1489: Menu_Center( &s_game_menu );
1490: }
1491: void Game_MenuDraw( void )
1492: {
1493: M_Banner( "m_banner_game" );
1494: Menu_AdjustCursor( &s_game_menu, 1 );
1495: Menu_Draw( &s_game_menu );
1496: }
1497: const char *Game_MenuKey( int key )
1498: {
1499: return Default_MenuKey( &s_game_menu, key );
1500: }
1501: void M_Menu_Game_f (void)
1502: {
1503: Game_MenuInit();
1504: M_PushMenu( Game_MenuDraw, Game_MenuKey );
1505: m_game_cursor = 1;
1506: }
1507: /*
1508: =============================================================================
1509: LOADGAME MENU
1510: =============================================================================
1511: */
1512: #define MAX_SAVEGAMES 15
1513: static menuframework_s s_savegame_menu;
1514: static menuframework_s s_loadgame_menu;
1515: static menuaction_s s_loadgame_actions[MAX_SAVEGAMES];
1516: char m_savestrings[MAX_SAVEGAMES][32];
1517: qboolean m_savevalid[MAX_SAVEGAMES];
1518: void Create_Savestrings (void)
1519: {
1520: int i;
1521: FILE *f;
1522: char name[MAX_OSPATH];
1523: for (i=0 ; i<MAX_SAVEGAMES ; i++)
1524: {
1525: Com_sprintf (name, sizeof(name), "%s/save/save%i/server.ssv", FS_Gamedir(), i);
1526: f = fopen (name, "rb");
1527: if (!f)
1528: {
1529: strcpy (m_savestrings[i], "<EMPTY>");
1530: m_savevalid[i] = false;
1531: }
1532: else
1533: {
1534: FS_Read (m_savestrings[i], sizeof(m_savestrings[i]), f);
1535: fclose (f);
1536: m_savevalid[i] = true;
1537: }
1538: }
1539: }
1540: void LoadGameCallback( void *self )
1541: {
1542: menuaction_s *a = ( menuaction_s * ) self;
1543: if ( m_savevalid[ a->generic.localdata[0] ] )
1544: Cbuf_AddText (va("load save%i\n", a->generic.localdata[0] ) );
1545: M_ForceMenuOff ();
1546: }
1547: void LoadGame_MenuInit( void )
1548: {
1549: int i;
1550: s_loadgame_menu.x = viddef.width / 2 - 120;
1551: s_loadgame_menu.y = viddef.height / 2 - 58;
1552: s_loadgame_menu.nitems = 0;
1553: Create_Savestrings();
1554: for ( i = 0; i < MAX_SAVEGAMES; i++ )
1555: {
1556: s_loadgame_actions[i].generic.name = m_savestrings[i];
1557: s_loadgame_actions[i].generic.flags = QMF_LEFT_JUSTIFY;
1558: s_loadgame_actions[i].generic.localdata[0] = i;
1559: s_loadgame_actions[i].generic.callback = LoadGameCallback;
1560: s_loadgame_actions[i].generic.x = 0;
1561: s_loadgame_actions[i].generic.y = ( i ) * 10;
1562: if (i>0) // separate from autosave
1563: s_loadgame_actions[i].generic.y += 10;
1564: s_loadgame_actions[i].generic.type = MTYPE_ACTION;
1565: Menu_AddItem( &s_loadgame_menu, &s_loadgame_actions[i] );
1566: }
1567: }
1568: void LoadGame_MenuDraw( void )
1569: {
1570: M_Banner( "m_banner_load_game" );
1571: // Menu_AdjustCursor( &s_loadgame_menu, 1 );
1572: Menu_Draw( &s_loadgame_menu );
1573: }
1574: const char *LoadGame_MenuKey( int key )
1575: {
1576: if ( key == K_ESCAPE || key == K_ENTER )
1577: {
1578: s_savegame_menu.cursor = s_loadgame_menu.cursor - 1;
1579: if ( s_savegame_menu.cursor < 0 )
1580: s_savegame_menu.cursor = 0;
1581: }
1582: return Default_MenuKey( &s_loadgame_menu, key );
1583: }
1584: void M_Menu_LoadGame_f (void)
1585: {
1586: LoadGame_MenuInit();
1587: M_PushMenu( LoadGame_MenuDraw, LoadGame_MenuKey );
1588: }
1589: /*
1590: =============================================================================
1591: SAVEGAME MENU
1592: =============================================================================
1593: */
1594: static menuframework_s s_savegame_menu;
1595: static menuaction_s s_savegame_actions[MAX_SAVEGAMES];
1596: void SaveGameCallback( void *self )
1597: {
1598: menuaction_s *a = ( menuaction_s * ) self;
1599: Cbuf_AddText (va("save save%i\n", a->generic.localdata[0] ));
1600: M_ForceMenuOff ();
1601: }
1602: void SaveGame_MenuDraw( void )
1603: {
1604: M_Banner( "m_banner_save_game" );
1605: Menu_AdjustCursor( &s_savegame_menu, 1 );
1606: Menu_Draw( &s_savegame_menu );
1607: }
1608: void SaveGame_MenuInit( void )
1609: {
1610: int i;
1611: s_savegame_menu.x = viddef.width / 2 - 120;
1612: s_savegame_menu.y = viddef.height / 2 - 58;
1613: s_savegame_menu.nitems = 0;
1614: Create_Savestrings();
1615: // don't include the autosave slot
1616: for ( i = 0; i < MAX_SAVEGAMES-1; i++ )
1617: {
1618: s_savegame_actions[i].generic.name = m_savestrings[i+1];
1619: s_savegame_actions[i].generic.localdata[0] = i+1;
1620: s_savegame_actions[i].generic.flags = QMF_LEFT_JUSTIFY;
1621: s_savegame_actions[i].generic.callback = SaveGameCallback;
1622: s_savegame_actions[i].generic.x = 0;
1623: s_savegame_actions[i].generic.y = ( i ) * 10;
1624: s_savegame_actions[i].generic.type = MTYPE_ACTION;
1625: Menu_AddItem( &s_savegame_menu, &s_savegame_actions[i] );
1626: }
1627: }
1628: const char *SaveGame_MenuKey( int key )
1629: {
1630: if ( key == K_ENTER || key == K_ESCAPE )
1631: {
1632: s_loadgame_menu.cursor = s_savegame_menu.cursor - 1;
1633: if ( s_loadgame_menu.cursor < 0 )
1634: s_loadgame_menu.cursor = 0;
1635: }
1636: return Default_MenuKey( &s_savegame_menu, key );
1637: }
1638: void M_Menu_SaveGame_f (void)
1639: {
1640: if (!Com_ServerState())
1641: return; // not playing a game
1642: SaveGame_MenuInit();
1643: M_PushMenu( SaveGame_MenuDraw, SaveGame_MenuKey );
1644: Create_Savestrings ();
1645: }
1646: /*
1647: =============================================================================
1648: JOIN SERVER MENU
1649: =============================================================================
1650: */
1651: #define MAX_LOCAL_SERVERS 8
1652: static menuframework_s s_joinserver_menu;
1653: static menuseparator_s s_joinserver_server_title;
1654: static menuaction_s s_joinserver_search_action;
1655: static menuaction_s s_joinserver_address_book_action;
1656: static menuaction_s s_joinserver_server_actions[MAX_LOCAL_SERVERS];
1657:
1658: int m_num_servers;
1659: #define NO_SERVER_STRING "<no server>"
1660:
1661: // user readable information
1662: static char local_server_names[MAX_LOCAL_SERVERS][80];
1663:
1664: // network address
1665: static netadr_t local_server_netadr[MAX_LOCAL_SERVERS];
1666:
1667: void M_AddToServerList (netadr_t adr, char *info)
1668: {
1669: int i;
1670:
1671: if (m_num_servers == MAX_LOCAL_SERVERS)
1672: return;
1673: while ( *info == ' ' )
1674: info++;
1675:
1676: // ignore if duplicated
1677: for (i=0 ; i<m_num_servers ; i++)
1678: if (!strcmp(info, local_server_names[i]))
1679: return;
1680:
1681: local_server_netadr[m_num_servers] = adr;
1682: strncpy (local_server_names[m_num_servers], info, sizeof(local_server_names[0])-1);
1683: m_num_servers++;
1684: }
1685:
1686: void JoinServerFunc( void *self )
1687: {
1688: char buffer[128];
1689: int index;
1690:
1691: index = ( menuaction_s * ) self - s_joinserver_server_actions;
1692:
1693: if ( Q_stricmp( local_server_names[index], NO_SERVER_STRING ) == 0 )
1694: return;
1695:
1696: if (index >= m_num_servers)
1697: return;
1698:
1699: Com_sprintf (buffer, sizeof(buffer), "connect %s\n", NET_AdrToString (local_server_netadr[index]));
1700: Cbuf_AddText (buffer);
1701: M_ForceMenuOff ();
1702: }
1703: void AddressBookFunc( void *self )
1704: {
1705: M_Menu_AddressBook_f();
1706: }
1707: void NullCursorDraw( void *self )
1708: {
1709: }
1710:
1711: void SearchLocalGames( void )
1712: {
1713: int i;
1714:
1715: m_num_servers = 0;
1716: for (i=0 ; i<MAX_LOCAL_SERVERS ; i++)
1717: strcpy (local_server_names[i], NO_SERVER_STRING);
1718:
1719: M_DrawTextBox( 8, 120 - 48, 36, 3 );
1720: M_Print( 16 + 16, 120 - 48 + 8, "Searching for local servers, this" );
1721: M_Print( 16 + 16, 120 - 48 + 16, "could take up to a minute, so" );
1722: M_Print( 16 + 16, 120 - 48 + 24, "please be patient." );
1723:
1724: // the text box won't show up unless we do a buffer swap
1725: re.EndFrame();
1726:
1727: // send out info packets
1728: CL_PingServers_f();
1729: }
1730: void SearchLocalGamesFunc( void *self )
1731: {
1732: SearchLocalGames();
1733: }
1734: void JoinServer_MenuInit( void )
1735: {
1736: int i;
1737: s_joinserver_menu.x = viddef.width * 0.50 - 120;
1738: s_joinserver_menu.nitems = 0;
1739: s_joinserver_address_book_action.generic.type = MTYPE_ACTION;
1740: s_joinserver_address_book_action.generic.name = "address book";
1741: s_joinserver_address_book_action.generic.flags = QMF_LEFT_JUSTIFY;
1742: s_joinserver_address_book_action.generic.x = 0;
1743: s_joinserver_address_book_action.generic.y = 0;
1744: s_joinserver_address_book_action.generic.callback = AddressBookFunc;
1745: s_joinserver_search_action.generic.type = MTYPE_ACTION;
1746: s_joinserver_search_action.generic.name = "refresh server list";
1747: s_joinserver_search_action.generic.flags = QMF_LEFT_JUSTIFY;
1748: s_joinserver_search_action.generic.x = 0;
1749: s_joinserver_search_action.generic.y = 10;
1750: s_joinserver_search_action.generic.callback = SearchLocalGamesFunc;
1751: s_joinserver_search_action.generic.statusbar = "search for servers";
1752: s_joinserver_server_title.generic.type = MTYPE_SEPARATOR;
1753: s_joinserver_server_title.generic.name = "connect to...";
1754: s_joinserver_server_title.generic.x = 80;
1755: s_joinserver_server_title.generic.y = 30;
1756: for ( i = 0; i < MAX_LOCAL_SERVERS; i++ )
1757: {
1758: s_joinserver_server_actions[i].generic.type = MTYPE_ACTION;
1759: strcpy (local_server_names[i], NO_SERVER_STRING);
1760: s_joinserver_server_actions[i].generic.name = local_server_names[i];
1761: s_joinserver_server_actions[i].generic.flags = QMF_LEFT_JUSTIFY;
1762: s_joinserver_server_actions[i].generic.x = 0;
1763: s_joinserver_server_actions[i].generic.y = 40 + i*10;
1764: s_joinserver_server_actions[i].generic.callback = JoinServerFunc;
1765: s_joinserver_server_actions[i].generic.statusbar = "press ENTER to connect";
1766: }
1767: Menu_AddItem( &s_joinserver_menu, &s_joinserver_address_book_action );
1768: Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_title );
1769: Menu_AddItem( &s_joinserver_menu, &s_joinserver_search_action );
1770: for ( i = 0; i < 8; i++ )
1771: Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_actions[i] );
1772: Menu_Center( &s_joinserver_menu );
1773:
1774: SearchLocalGames();
1775: }
1776: void JoinServer_MenuDraw(void)
1777: {
1778: M_Banner( "m_banner_join_server" );
1779: Menu_Draw( &s_joinserver_menu );
1780: }
1781: const char *JoinServer_MenuKey( int key )
1782: {
1783: return Default_MenuKey( &s_joinserver_menu, key );
1784: }
1785: void M_Menu_JoinServer_f (void)
1786: {
1787: JoinServer_MenuInit();
1788: M_PushMenu( JoinServer_MenuDraw, JoinServer_MenuKey );
1789: }
1790:
1791: /*
1792: =============================================================================
1793: START SERVER MENU
1794: =============================================================================
1795: */
1796: static menuframework_s s_startserver_menu;
1797: static char **mapnames;
1798: static int nummaps;
1799: static menuaction_s s_startserver_start_action;
1800: static menuaction_s s_startserver_dmoptions_action;
1801: static menufield_s s_timelimit_field;
1802: static menufield_s s_fraglimit_field;
1803: static menufield_s s_maxclients_field;
1804: static menufield_s s_hostname_field;
1805: static menulist_s s_startmap_list;
1806: static menulist_s s_rules_box;
1807:
1808: void DMOptionsFunc( void *self )
1809: {
1810: if (s_rules_box.curvalue == 1)
1811: return;
1812: M_Menu_DMOptions_f();
1813: }
1814:
1815: void RulesChangeFunc ( void *self )
1816: {
1817: // DM
1818: if (s_rules_box.curvalue == 0)
1819: {
1820: s_maxclients_field.generic.statusbar = NULL;
1821: s_startserver_dmoptions_action.generic.statusbar = NULL;
1822: }
1823: else // coop
1824: {
1825: s_maxclients_field.generic.statusbar = "4 maximum for cooperative";
1826: if (atoi(s_maxclients_field.buffer) > 4)
1827: strcpy( s_maxclients_field.buffer, "4" );
1828: s_startserver_dmoptions_action.generic.statusbar = "N/A for cooperative";
1829: }
1830: }
1831: void StartServerActionFunc( void *self )
1832: {
1833: char startmap[1024];
1834: int timelimit;
1835: int fraglimit;
1836: int maxclients;
1837: char *spot;
1838: strcpy( startmap, strchr( mapnames[s_startmap_list.curvalue], '\n' ) + 1 );
1839:
1840: maxclients = atoi( s_maxclients_field.buffer );
1841: timelimit = atoi( s_timelimit_field.buffer );
1842: fraglimit = atoi( s_fraglimit_field.buffer );
1843:
1844: Cvar_SetValue( "maxclients", ClampCvar( 0, maxclients, maxclients ) );
1845: Cvar_SetValue ("timelimit", ClampCvar( 0, timelimit, timelimit ) );
1846: Cvar_SetValue ("fraglimit", ClampCvar( 0, fraglimit, fraglimit ) );
1847: Cvar_Set("hostname", s_hostname_field.buffer );
1848: Cvar_SetValue ("deathmatch", !s_rules_box.curvalue );
1849: Cvar_SetValue ("coop", s_rules_box.curvalue );
1850:
1851: spot = NULL;
1852: if (s_rules_box.curvalue)
1853: {
1854: if(stricmp(startmap, "bunk1") == 0)
1855: spot = "start";
1856: else if(stricmp(startmap, "mintro") == 0)
1857: spot = "start";
1858: else if(stricmp(startmap, "fact1") == 0)
1859: spot = "start";
1860: else if(stricmp(startmap, "power1") == 0)
1861: spot = "pstart";
1862: else if(stricmp(startmap, "biggun") == 0)
1863: spot = "bstart";
1864: else if(stricmp(startmap, "hangar1") == 0)
1865: spot = "unitstart";
1866: else if(stricmp(startmap, "city1") == 0)
1867: spot = "unitstart";
1868: else if(stricmp(startmap, "boss1") == 0)
1869: spot = "bosstart";
1870: }
1871:
1872: if (spot)
1873: {
1874: if (Com_ServerState())
1875: Cbuf_AddText ("disconnect\n");
1876: Cbuf_AddText (va("gamemap \"*%s$%s\"\n", startmap, spot));
1877: }
1878: else
1879: {
1880: Cbuf_AddText (va("map %s\n", startmap));
1881: }
1882:
1883: M_ForceMenuOff ();
1884: }
1885:
1886: void StartServer_MenuInit( void )
1887: {
1888: static const char *dm_coop_names[] =
1889: {
1890: "deathmatch",
1891: "cooperative",
1892: 0
1893: };
1894: char *buffer;
1895: char mapsname[1024];
1896: char *s;
1897: int length;
1898: int i;
1899: FILE *fp;
1900:
1901: /*
1902: ** load the list of map names
1903: */
1904: Com_sprintf( mapsname, sizeof( mapsname ), "%s/maps.lst", FS_Gamedir() );
1905: if ( ( fp = fopen( mapsname, "rb" ) ) == 0 )
1906: {
1907: if ( ( length = FS_LoadFile( "maps.lst", ( void ** ) &buffer ) ) == -1 )
1908: Com_Error( ERR_DROP, "couldn't find maps.lst\n" );
1909: }
1910: else
1911: {
1912: length = filelength( fileno( fp ) );
1913: buffer = malloc( length );
1914: fread( buffer, length, 1, fp );
1915: }
1916:
1917: s = buffer;
1918:
1919: i = 0;
1920: while ( i < length )
1921: {
1922: if ( s[i] == '\r' )
1923: nummaps++;
1924: i++;
1925: }
1926:
1927: if ( nummaps == 0 )
1928: Com_Error( ERR_DROP, "no maps in maps.lst\n" );
1929:
1930: mapnames = malloc( sizeof( char * ) * ( nummaps + 1 ) );
1931: memset( mapnames, 0, sizeof( char * ) * ( nummaps + 1 ) );
1932:
1933: s = buffer;
1934:
1935: for ( i = 0; i < nummaps; i++ )
1936: {
1937: char shortname[MAX_TOKEN_CHARS];
1938: char longname[MAX_TOKEN_CHARS];
1939: char scratch[200];
1940: int j, l;
1941:
1942: strcpy( shortname, COM_Parse( &s ) );
1943: l = strlen(shortname);
1944: for (j=0 ; j<l ; j++)
1945: shortname[j] = toupper(shortname[j]);
1946: strcpy( longname, COM_Parse( &s ) );
1947: Com_sprintf( scratch, sizeof( scratch ), "%s\n%s", longname, shortname );
1948:
1949: mapnames[i] = malloc( strlen( scratch ) + 1 );
1950: strcpy( mapnames[i], scratch );
1951: }
1952: mapnames[nummaps] = 0;
1953:
1954: if ( fp != 0 )
1955: {
1956: fp = 0;
1957: free( buffer );
1958: }
1959: else
1960: {
1961: FS_FreeFile( buffer );
1962: }
1963:
1964: /*
1965: ** initialize the menu stuff
1966: */
1967: s_startserver_menu.x = viddef.width * 0.50;
1968: s_startserver_menu.nitems = 0;
1969: s_startmap_list.generic.type = MTYPE_SPINCONTROL;
1970: s_startmap_list.generic.x = 0;
1971: s_startmap_list.generic.y = 0;
1972: s_startmap_list.generic.name = "initial map";
1973: s_startmap_list.itemnames = mapnames;
1974: s_rules_box.generic.type = MTYPE_SPINCONTROL;
1975: s_rules_box.generic.x = 0;
1976: s_rules_box.generic.y = 20;
1977: s_rules_box.generic.name = "rules";
1978: s_rules_box.itemnames = dm_coop_names;
1979: if (Cvar_VariableValue("coop"))
1980: s_rules_box.curvalue = 1;
1981: else
1982: s_rules_box.curvalue = 0;
1983: s_rules_box.generic.callback = RulesChangeFunc;
1984: s_timelimit_field.generic.type = MTYPE_FIELD;
1985: s_timelimit_field.generic.name = "time limit";
1986: s_timelimit_field.generic.flags = QMF_NUMBERSONLY;
1987: s_timelimit_field.generic.x = 0;
1988: s_timelimit_field.generic.y = 36;
1989: s_timelimit_field.generic.statusbar = "0 = no limit";
1990: s_timelimit_field.length = 3;
1991: s_timelimit_field.visible_length = 3;
1992: strcpy( s_timelimit_field.buffer, Cvar_VariableString("timelimit") );
1993: s_fraglimit_field.generic.type = MTYPE_FIELD;
1994: s_fraglimit_field.generic.name = "frag limit";
1995: s_fraglimit_field.generic.flags = QMF_NUMBERSONLY;
1996: s_fraglimit_field.generic.x = 0;
1997: s_fraglimit_field.generic.y = 54;
1998: s_fraglimit_field.generic.statusbar = "0 = no limit";
1999: s_fraglimit_field.length = 3;
2000: s_fraglimit_field.visible_length = 3;
2001: strcpy( s_fraglimit_field.buffer, Cvar_VariableString("fraglimit") );
2002:
2003: /*
2004: ** maxclients determines the maximum number of players that can join
2005: ** the game. If maxclients is only "1" then we should default the menu
2006: ** option to 8 players, otherwise use whatever its current value is.
2007: ** Clamping will be done when the server is actually started.
2008: */
2009: s_maxclients_field.generic.type = MTYPE_FIELD;
2010: s_maxclients_field.generic.name = "max players";
2011: s_maxclients_field.generic.flags = QMF_NUMBERSONLY;
2012: s_maxclients_field.generic.x = 0;
2013: s_maxclients_field.generic.y = 72;
2014: s_maxclients_field.generic.statusbar = NULL;
2015: s_maxclients_field.length = 3;
2016: s_maxclients_field.visible_length = 3;
2017: if ( Cvar_VariableValue( "maxclients" ) == 1 )
2018: strcpy( s_maxclients_field.buffer, "8" );
2019: else
2020: strcpy( s_maxclients_field.buffer, Cvar_VariableString("maxclients") );
2021:
2022: s_hostname_field.generic.type = MTYPE_FIELD;
2023: s_hostname_field.generic.name = "hostname";
2024: s_hostname_field.generic.flags = 0;
2025: s_hostname_field.generic.x = 0;
2026: s_hostname_field.generic.y = 90;
2027: s_hostname_field.generic.statusbar = NULL;
2028: s_hostname_field.length = 12;
2029: s_hostname_field.visible_length = 12;
2030: strcpy( s_hostname_field.buffer, Cvar_VariableString("hostname") );
2031:
2032: s_startserver_dmoptions_action.generic.type = MTYPE_ACTION;
2033: s_startserver_dmoptions_action.generic.name = " deathmatch flags";
2034: s_startserver_dmoptions_action.generic.flags= QMF_LEFT_JUSTIFY;
2035: s_startserver_dmoptions_action.generic.x = 24;
2036: s_startserver_dmoptions_action.generic.y = 108;
2037: s_startserver_dmoptions_action.generic.statusbar = NULL;
2038: s_startserver_dmoptions_action.generic.callback = DMOptionsFunc;
2039:
2040: s_startserver_start_action.generic.type = MTYPE_ACTION;
2041: s_startserver_start_action.generic.name = " begin";
2042: s_startserver_start_action.generic.flags= QMF_LEFT_JUSTIFY;
2043: s_startserver_start_action.generic.x = 24;
2044: s_startserver_start_action.generic.y = 128;
2045: s_startserver_start_action.generic.callback = StartServerActionFunc;
2046:
2047: Menu_AddItem( &s_startserver_menu, &s_startmap_list );
2048: Menu_AddItem( &s_startserver_menu, &s_rules_box );
2049: Menu_AddItem( &s_startserver_menu, &s_timelimit_field );
2050: Menu_AddItem( &s_startserver_menu, &s_fraglimit_field );
2051: Menu_AddItem( &s_startserver_menu, &s_maxclients_field );
2052: Menu_AddItem( &s_startserver_menu, &s_hostname_field );
2053: Menu_AddItem( &s_startserver_menu, &s_startserver_dmoptions_action );
2054: Menu_AddItem( &s_startserver_menu, &s_startserver_start_action );
2055:
2056: Menu_Center( &s_startserver_menu );
2057:
2058: // call this now to set proper inital state
2059: RulesChangeFunc ( NULL );
2060: }
2061: void StartServer_MenuDraw(void)
2062: {
2063: Menu_Draw( &s_startserver_menu );
2064: }
2065: const char *StartServer_MenuKey( int key )
2066: {
2067: if ( key == K_ESCAPE )
2068: {
2069: if ( mapnames )
2070: {
2071: int i;
2072:
2073: for ( i = 0; i < nummaps; i++ )
2074: free( mapnames[i] );
2075: free( mapnames );
2076: }
2077: mapnames = 0;
2078: nummaps = 0;
2079: }
2080: return Default_MenuKey( &s_startserver_menu, key );
2081: }
2082: void M_Menu_StartServer_f (void)
2083: {
2084: StartServer_MenuInit();
2085: M_PushMenu( StartServer_MenuDraw, StartServer_MenuKey );
2086: }
2087: /*
2088: =============================================================================
2089:
2090: DMOPTIONS BOOK MENU
2091:
2092: =============================================================================
2093: */
2094: static char dmoptions_statusbar[128];
2095:
2096: static menuframework_s s_dmoptions_menu;
2097:
2098: static menulist_s s_friendlyfire_box;
2099: static menulist_s s_falls_box;
2100: static menulist_s s_weapons_stay_box;
2101: static menulist_s s_instant_powerups_box;
2102: static menulist_s s_powerups_box;
2103: static menulist_s s_health_box;
2104: static menulist_s s_spawn_farthest_box;
2105: static menulist_s s_teamplay_box;
2106: static menulist_s s_samelevel_box;
2107: static menulist_s s_force_respawn_box;
2108: static menulist_s s_armor_box;
2109: static menulist_s s_allow_exit_box;
2110: static menulist_s s_infinite_ammo_box;
2111: static menulist_s s_fixed_fov_box;
2112: static menulist_s s_quad_drop_box;
2113:
2114: static void DMFlagCallback( void *self )
2115: {
2116: menulist_s *f = ( menulist_s * ) self;
2117: int flags;
2118: int bit = 0;
2119:
2120: flags = Cvar_VariableValue( "dmflags" );
2121:
2122: if ( f == &s_friendlyfire_box )
2123: {
2124: if ( f->curvalue )
2125: flags &= ~DF_NO_FRIENDLY_FIRE;
2126: else
2127: flags |= DF_NO_FRIENDLY_FIRE;
2128: goto setvalue;
2129: }
2130: else if ( f == &s_falls_box )
2131: {
2132: if ( f->curvalue )
2133: flags &= ~DF_NO_FALLING;
2134: else
2135: flags |= DF_NO_FALLING;
2136: goto setvalue;
2137: }
2138: else if ( f == &s_weapons_stay_box )
2139: {
2140: bit = DF_WEAPONS_STAY;
2141: }
2142: else if ( f == &s_instant_powerups_box )
2143: {
2144: bit = DF_INSTANT_ITEMS;
2145: }
2146: else if ( f == &s_allow_exit_box )
2147: {
2148: bit = DF_ALLOW_EXIT;
2149: }
2150: else if ( f == &s_powerups_box )
2151: {
2152: if ( f->curvalue )
2153: flags &= ~DF_NO_ITEMS;
2154: else
2155: flags |= DF_NO_ITEMS;
2156: goto setvalue;
2157: }
2158: else if ( f == &s_health_box )
2159: {
2160: if ( f->curvalue )
2161: flags &= ~DF_NO_HEALTH;
2162: else
2163: flags |= DF_NO_HEALTH;
2164: goto setvalue;
2165: }
2166: else if ( f == &s_spawn_farthest_box )
2167: {
2168: bit = DF_SPAWN_FARTHEST;
2169: }
2170: else if ( f == &s_teamplay_box )
2171: {
2172: if ( f->curvalue == 1 )
2173: {
2174: flags |= DF_SKINTEAMS;
2175: flags &= ~DF_MODELTEAMS;
2176: }
2177: else if ( f->curvalue == 2 )
2178: {
2179: flags |= DF_MODELTEAMS;
2180: flags &= ~DF_SKINTEAMS;
2181: }
2182: else
2183: {
2184: flags &= ~( DF_MODELTEAMS | DF_SKINTEAMS );
2185: }
2186:
2187: goto setvalue;
2188: }
2189: else if ( f == &s_samelevel_box )
2190: {
2191: bit = DF_SAME_LEVEL;
2192: }
2193: else if ( f == &s_force_respawn_box )
2194: {
2195: bit = DF_FORCE_RESPAWN;
2196: }
2197: else if ( f == &s_armor_box )
2198: {
2199: if ( f->curvalue )
2200: flags &= ~DF_NO_ARMOR;
2201: else
2202: flags |= DF_NO_ARMOR;
2203: goto setvalue;
2204: }
2205: else if ( f == &s_infinite_ammo_box )
2206: {
2207: bit = DF_INFINITE_AMMO;
2208: }
2209: else if ( f == &s_fixed_fov_box )
2210: {
2211: bit = DF_FIXED_FOV;
2212: }
2213: else if ( f == &s_quad_drop_box )
2214: {
2215: bit = DF_QUAD_DROP;
2216: }
2217:
2218:
2219: if ( f )
2220: {
2221: if ( f->curvalue == 0 )
2222: flags &= ~bit;
2223: else
2224: flags |= bit;
2225: }
2226:
2227: setvalue:
2228: Cvar_SetValue ("dmflags", flags);
2229:
2230: Com_sprintf( dmoptions_statusbar, sizeof( dmoptions_statusbar ), "dmflags = %d", flags );
2231:
2232: }
2233:
2234: void DMOptions_MenuInit( void )
2235: {
2236: static const char *yes_no_names[] =
2237: {
2238: "no", "yes", 0
2239: };
2240: static const char *teamplay_names[] =
2241: {
2242: "disabled", "by skin", "by model", 0
2243: };
2244: int dmflags = Cvar_VariableValue( "dmflags" );
2245: int y = 0;
2246:
2247: s_dmoptions_menu.x = viddef.width * 0.50;
2248: s_dmoptions_menu.nitems = 0;
2249:
2250: s_falls_box.generic.type = MTYPE_SPINCONTROL;
2251: s_falls_box.generic.x = 0;
2252: s_falls_box.generic.y = y;
2253: s_falls_box.generic.name = "falling damage";
2254: s_falls_box.generic.callback = DMFlagCallback;
2255: s_falls_box.itemnames = yes_no_names;
2256: s_falls_box.curvalue = ( dmflags & DF_NO_FALLING ) == 0;
2257:
2258: s_weapons_stay_box.generic.type = MTYPE_SPINCONTROL;
2259: s_weapons_stay_box.generic.x = 0;
2260: s_weapons_stay_box.generic.y = y += 10;
2261: s_weapons_stay_box.generic.name = "weapons stay";
2262: s_weapons_stay_box.generic.callback = DMFlagCallback;
2263: s_weapons_stay_box.itemnames = yes_no_names;
2264: s_weapons_stay_box.curvalue = ( dmflags & DF_WEAPONS_STAY ) != 0;
2265:
2266: s_instant_powerups_box.generic.type = MTYPE_SPINCONTROL;
2267: s_instant_powerups_box.generic.x = 0;
2268: s_instant_powerups_box.generic.y = y += 10;
2269: s_instant_powerups_box.generic.name = "instant powerups";
2270: s_instant_powerups_box.generic.callback = DMFlagCallback;
2271: s_instant_powerups_box.itemnames = yes_no_names;
2272: s_instant_powerups_box.curvalue = ( dmflags & DF_INSTANT_ITEMS ) != 0;
2273:
2274: s_powerups_box.generic.type = MTYPE_SPINCONTROL;
2275: s_powerups_box.generic.x = 0;
2276: s_powerups_box.generic.y = y += 10;
2277: s_powerups_box.generic.name = "allow powerups";
2278: s_powerups_box.generic.callback = DMFlagCallback;
2279: s_powerups_box.itemnames = yes_no_names;
2280: s_powerups_box.curvalue = ( dmflags & DF_NO_ITEMS ) == 0;
2281:
2282: s_health_box.generic.type = MTYPE_SPINCONTROL;
2283: s_health_box.generic.x = 0;
2284: s_health_box.generic.y = y += 10;
2285: s_health_box.generic.callback = DMFlagCallback;
2286: s_health_box.generic.name = "allow health";
2287: s_health_box.itemnames = yes_no_names;
2288: s_health_box.curvalue = ( dmflags & DF_NO_HEALTH ) == 0;
2289:
2290: s_armor_box.generic.type = MTYPE_SPINCONTROL;
2291: s_armor_box.generic.x = 0;
2292: s_armor_box.generic.y = y += 10;
2293: s_armor_box.generic.name = "allow armor";
2294: s_armor_box.generic.callback = DMFlagCallback;
2295: s_armor_box.itemnames = yes_no_names;
2296: s_armor_box.curvalue = ( dmflags & DF_NO_ARMOR ) == 0;
2297:
2298: s_spawn_farthest_box.generic.type = MTYPE_SPINCONTROL;
2299: s_spawn_farthest_box.generic.x = 0;
2300: s_spawn_farthest_box.generic.y = y += 10;
2301: s_spawn_farthest_box.generic.name = "spawn farthest";
2302: s_spawn_farthest_box.generic.callback = DMFlagCallback;
2303: s_spawn_farthest_box.itemnames = yes_no_names;
2304: s_spawn_farthest_box.curvalue = ( dmflags & DF_SPAWN_FARTHEST ) != 0;
2305:
2306: s_samelevel_box.generic.type = MTYPE_SPINCONTROL;
2307: s_samelevel_box.generic.x = 0;
2308: s_samelevel_box.generic.y = y += 10;
2309: s_samelevel_box.generic.name = "same map";
2310: s_samelevel_box.generic.callback = DMFlagCallback;
2311: s_samelevel_box.itemnames = yes_no_names;
2312: s_samelevel_box.curvalue = ( dmflags & DF_SAME_LEVEL ) != 0;
2313:
2314: s_force_respawn_box.generic.type = MTYPE_SPINCONTROL;
2315: s_force_respawn_box.generic.x = 0;
2316: s_force_respawn_box.generic.y = y += 10;
2317: s_force_respawn_box.generic.name = "force respawn";
2318: s_force_respawn_box.generic.callback = DMFlagCallback;
2319: s_force_respawn_box.itemnames = yes_no_names;
2320: s_force_respawn_box.curvalue = ( dmflags & DF_FORCE_RESPAWN ) != 0;
2321:
2322: s_teamplay_box.generic.type = MTYPE_SPINCONTROL;
2323: s_teamplay_box.generic.x = 0;
2324: s_teamplay_box.generic.y = y += 10;
2325: s_teamplay_box.generic.name = "teamplay";
2326: s_teamplay_box.generic.callback = DMFlagCallback;
2327: s_teamplay_box.itemnames = teamplay_names;
2328:
2329: s_allow_exit_box.generic.type = MTYPE_SPINCONTROL;
2330: s_allow_exit_box.generic.x = 0;
2331: s_allow_exit_box.generic.y = y += 10;
2332: s_allow_exit_box.generic.name = "allow exit";
2333: s_allow_exit_box.generic.callback = DMFlagCallback;
2334: s_allow_exit_box.itemnames = yes_no_names;
2335: s_allow_exit_box.curvalue = ( dmflags & DF_ALLOW_EXIT ) != 0;
2336:
2337: s_infinite_ammo_box.generic.type = MTYPE_SPINCONTROL;
2338: s_infinite_ammo_box.generic.x = 0;
2339: s_infinite_ammo_box.generic.y = y += 10;
2340: s_infinite_ammo_box.generic.name = "infinite ammo";
2341: s_infinite_ammo_box.generic.callback = DMFlagCallback;
2342: s_infinite_ammo_box.itemnames = yes_no_names;
2343: s_infinite_ammo_box.curvalue = ( dmflags & DF_INFINITE_AMMO ) != 0;
2344:
2345: s_fixed_fov_box.generic.type = MTYPE_SPINCONTROL;
2346: s_fixed_fov_box.generic.x = 0;
2347: s_fixed_fov_box.generic.y = y += 10;
2348: s_fixed_fov_box.generic.name = "fixed FOV";
2349: s_fixed_fov_box.generic.callback = DMFlagCallback;
2350: s_fixed_fov_box.itemnames = yes_no_names;
2351: s_fixed_fov_box.curvalue = ( dmflags & DF_FIXED_FOV ) != 0;
2352:
2353: s_quad_drop_box.generic.type = MTYPE_SPINCONTROL;
2354: s_quad_drop_box.generic.x = 0;
2355: s_quad_drop_box.generic.y = y += 10;
2356: s_quad_drop_box.generic.name = "quad drop";
2357: s_quad_drop_box.generic.callback = DMFlagCallback;
2358: s_quad_drop_box.itemnames = yes_no_names;
2359: s_quad_drop_box.curvalue = ( dmflags & DF_QUAD_DROP ) != 0;
2360:
2361: s_friendlyfire_box.generic.type = MTYPE_SPINCONTROL;
2362: s_friendlyfire_box.generic.x = 0;
2363: s_friendlyfire_box.generic.y = y += 10;
2364: s_friendlyfire_box.generic.name = "friendly fire";
2365: s_friendlyfire_box.generic.callback = DMFlagCallback;
2366: s_friendlyfire_box.itemnames = yes_no_names;
2367: s_friendlyfire_box.curvalue = ( dmflags & DF_NO_FRIENDLY_FIRE ) == 0;
2368:
2369: Menu_AddItem( &s_dmoptions_menu, &s_falls_box );
2370: Menu_AddItem( &s_dmoptions_menu, &s_weapons_stay_box );
2371: Menu_AddItem( &s_dmoptions_menu, &s_instant_powerups_box );
2372: Menu_AddItem( &s_dmoptions_menu, &s_powerups_box );
2373: Menu_AddItem( &s_dmoptions_menu, &s_health_box );
2374: Menu_AddItem( &s_dmoptions_menu, &s_armor_box );
2375: Menu_AddItem( &s_dmoptions_menu, &s_spawn_farthest_box );
2376: Menu_AddItem( &s_dmoptions_menu, &s_samelevel_box );
2377: Menu_AddItem( &s_dmoptions_menu, &s_force_respawn_box );
2378: Menu_AddItem( &s_dmoptions_menu, &s_teamplay_box );
2379: Menu_AddItem( &s_dmoptions_menu, &s_allow_exit_box );
2380: Menu_AddItem( &s_dmoptions_menu, &s_infinite_ammo_box );
2381: Menu_AddItem( &s_dmoptions_menu, &s_fixed_fov_box );
2382: Menu_AddItem( &s_dmoptions_menu, &s_quad_drop_box );
2383: Menu_AddItem( &s_dmoptions_menu, &s_friendlyfire_box );
2384:
2385: Menu_Center( &s_dmoptions_menu );
2386:
2387: // set the original dmflags statusbar
2388: DMFlagCallback( 0 );
2389: Menu_SetStatusBar( &s_dmoptions_menu, dmoptions_statusbar );
2390: }
2391:
2392: void DMOptions_MenuDraw(void)
2393: {
2394: Menu_Draw( &s_dmoptions_menu );
2395: }
2396:
2397: const char *DMOptions_MenuKey( int key )
2398: {
2399: return Default_MenuKey( &s_dmoptions_menu, key );
2400: }
2401:
2402: void M_Menu_DMOptions_f (void)
2403: {
2404: DMOptions_MenuInit();
2405: M_PushMenu( DMOptions_MenuDraw, DMOptions_MenuKey );
2406: }
2407:
2408: /*
2409: =============================================================================
2410: ADDRESS BOOK MENU
2411: =============================================================================
2412: */
2413: #define NUM_ADDRESSBOOK_ENTRIES 9
2414: static menuframework_s s_addressbook_menu;
2415: static menufield_s s_addressbook_fields[NUM_ADDRESSBOOK_ENTRIES];
2416: void AddressBook_MenuInit( void )
2417: {
2418: int i;
2419: s_addressbook_menu.x = viddef.width / 2 - 142;
2420: s_addressbook_menu.y = viddef.height / 2 - 58;
2421: s_addressbook_menu.nitems = 0;
2422: for ( i = 0; i < NUM_ADDRESSBOOK_ENTRIES; i++ )
2423: {
2424: cvar_t *adr;
2425: char buffer[20];
2426:
2427: Com_sprintf( buffer, sizeof( buffer ), "adr%d", i );
2428:
2429: adr = Cvar_Get( buffer, "", CVAR_ARCHIVE );
2430: s_addressbook_fields[i].generic.type = MTYPE_FIELD;
2431: s_addressbook_fields[i].generic.name = 0;
2432: s_addressbook_fields[i].generic.callback = 0;
2433: s_addressbook_fields[i].generic.x = 0;
2434: s_addressbook_fields[i].generic.y = i * 18 + 0;
2435: s_addressbook_fields[i].generic.localdata[0] = i;
2436: s_addressbook_fields[i].cursor = 0;
2437: s_addressbook_fields[i].length = 60;
2438: s_addressbook_fields[i].visible_length = 30;
2439:
2440: strcpy( s_addressbook_fields[i].buffer, adr->string );
2441: Menu_AddItem( &s_addressbook_menu, &s_addressbook_fields[i] );
2442: }
2443: }
2444: const char *AddressBook_MenuKey( int key )
2445: {
2446: if ( key == K_ESCAPE )
2447: {
2448: int index;
2449: char buffer[20];
2450:
2451: for ( index = 0; index < NUM_ADDRESSBOOK_ENTRIES; index++ )
2452: {
2453: Com_sprintf( buffer, sizeof( buffer ), "adr%d", index );
2454: Cvar_Set( buffer, s_addressbook_fields[index].buffer );
2455: }
2456: }
2457: return Default_MenuKey( &s_addressbook_menu, key );
2458: }
2459: void AddressBook_MenuDraw(void)
2460: {
2461: M_Banner( "m_banner_addressbook" );
2462: Menu_Draw( &s_addressbook_menu );
2463: }
2464: void M_Menu_AddressBook_f(void)
2465: {
2466: AddressBook_MenuInit();
2467: M_PushMenu( AddressBook_MenuDraw, AddressBook_MenuKey );
2468: }
2469: /*
2470: =============================================================================
2471: PLAYER CONFIG MENU
2472: =============================================================================
2473: */
2474: static menuframework_s s_player_config_menu;
2475: static menufield_s s_player_name_field;
2476: static menulist_s s_player_model_box;
2477: static menulist_s s_player_skin_box;
2478: static menulist_s s_player_handedness_box;
2479: static menuseparator_s s_player_skin_title;
2480: static menuseparator_s s_player_model_title;
2481: static menuseparator_s s_player_hand_title;
2482:
2483: #define MAX_DISPLAYNAME 16
2484: #define MAX_PLAYERMODELS 1024
2485:
2486: typedef struct
2487: {
2488: int nskins;
2489: char **skindisplaynames;
2490: char displayname[MAX_DISPLAYNAME];
2491: char directory[MAX_QPATH];
2492: } playermodelinfo_s;
2493:
2494: static playermodelinfo_s s_pmi[MAX_PLAYERMODELS];
2495: static char *s_pmnames[MAX_PLAYERMODELS];
2496: static int s_numplayermodels;
2497:
2498: static void HandednessCallback( void *unused )
2499: {
2500: Cvar_SetValue( "hand", s_player_handedness_box.curvalue );
2501: }
2502:
2503: static void ModelCallback( void *unused )
2504: {
2505: s_player_skin_box.itemnames = s_pmi[s_player_model_box.curvalue].skindisplaynames;
2506: s_player_skin_box.curvalue = 0;
2507: }
2508:
2509: static void FreeFileList( char **list, int n )
2510: {
2511: int i;
2512:
2513: for ( i = 0; i < n; i++ )
2514: {
2515: if ( list[i] )
2516: {
2517: free( list[i] );
2518: list[i] = 0;
2519: }
2520: }
2521: free( list );
2522: }
2523:
2524: static qboolean IconOfSkinExists( char *skin, char **pcxfiles, int npcxfiles )
2525: {
2526: int i;
2527: char scratch[1024];
2528:
2529: strcpy( scratch, skin );
2530: *strrchr( scratch, '.' ) = 0;
2531: strcat( scratch, "_i.pcx" );
2532:
2533: for ( i = 0; i < npcxfiles; i++ )
2534: {
2535: if ( strcmp( pcxfiles[i], scratch ) == 0 )
2536: return true;
2537: }
2538:
2539: return false;
2540: }
2541:
2542: static qboolean PlayerConfig_ScanDirectories( void )
2543: {
2544: char findname[1024];
2545: char scratch[1024];
2546: int ndirs = 0, npms = 0;
2547: char **dirnames;
2548: char *path = NULL;
2549: int i;
2550:
2551: extern char **FS_ListFiles( char *, int *, unsigned, unsigned );
2552:
2553: s_numplayermodels = 0;
2554:
2555: /*
2556: ** get a list of directories
2557: */
2558: do
2559: {
2560: path = FS_NextPath( path );
2561: Com_sprintf( findname, sizeof(findname), "%s/players/*.*", path );
2562:
2563: if ( ( dirnames = FS_ListFiles( findname, &ndirs, SFF_SUBDIR, 0 ) ) != 0 )
2564: break;
2565: } while ( path );
2566:
2567: if ( !dirnames )
2568: return false;
2569:
2570: /*
2571: ** go through the subdirectories
2572: */
2573: npms = ndirs;
2574: if ( npms > MAX_PLAYERMODELS )
2575: npms = MAX_PLAYERMODELS;
2576:
2577: for ( i = 0; i < npms; i++ )
2578: {
2579: int k, s;
2580: char *a, *b, *c;
2581: char **pcxnames;
2582: char **skinnames;
2583: int npcxfiles;
2584: int nskins = 0;
2585:
2586: if ( dirnames[i] == 0 )
2587: continue;
2588:
2589: // verify the existence of tris.md2
2590: strcpy( scratch, dirnames[i] );
2591: strcat( scratch, "/tris.md2" );
2592: if ( !Sys_FindFirst( scratch, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM ) )
2593: {
2594: free( dirnames[i] );
2595: dirnames[i] = 0;
2596: Sys_FindClose();
2597: continue;
2598: }
2599: Sys_FindClose();
2600:
2601: // verify the existence of at least one pcx skin
2602: strcpy( scratch, dirnames[i] );
2603: strcat( scratch, "/*.pcx" );
2604: pcxnames = FS_ListFiles( scratch, &npcxfiles, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM );
2605:
2606: if ( !pcxnames )
2607: {
2608: free( dirnames[i] );
2609: dirnames[i] = 0;
2610: continue;
2611: }
2612:
2613: // count valid skins, which consist of a skin with a matching "_i" icon
2614: for ( k = 0; k < npcxfiles-1; k++ )
2615: {
2616: if ( !strstr( pcxnames[k], "_i.pcx" ) )
2617: {
2618: if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) )
2619: {
2620: nskins++;
2621: }
2622: }
2623: }
2624: if ( !nskins )
2625: continue;
2626:
2627: skinnames = malloc( sizeof( char * ) * ( nskins + 1 ) );
2628: memset( skinnames, 0, sizeof( char * ) * ( nskins + 1 ) );
2629:
2630: // copy the valid skins
2631: for ( s = 0, k = 0; k < npcxfiles-1; k++ )
2632: {
2633: char *a, *b, *c;
2634:
2635: if ( !strstr( pcxnames[k], "_i.pcx" ) )
2636: {
2637: if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) )
2638: {
2639: a = strrchr( pcxnames[k], '/' );
2640: b = strrchr( pcxnames[k], '\\' );
2641:
2642: if ( a > b )
2643: c = a;
2644: else
2645: c = b;
2646:
2647: strcpy( scratch, c + 1 );
2648:
2649: if ( strrchr( scratch, '.' ) )
2650: *strrchr( scratch, '.' ) = 0;
2651:
2652: skinnames[s] = strdup( scratch );
2653: s++;
2654: }
2655: }
2656: }
2657:
2658: // at this point we have a valid player model
2659: s_pmi[s_numplayermodels].nskins = nskins;
2660: s_pmi[s_numplayermodels].skindisplaynames = skinnames;
2661:
2662: // make short name for the model
2663: a = strrchr( dirnames[i], '/' );
2664: b = strrchr( dirnames[i], '\\' );
2665:
2666: if ( a > b )
2667: c = a;
2668: else
2669: c = b;
2670:
2671: strncpy( s_pmi[s_numplayermodels].displayname, c + 1, MAX_DISPLAYNAME-1 );
2672: strcpy( s_pmi[s_numplayermodels].directory, c + 1 );
2673:
2674: FreeFileList( pcxnames, npcxfiles );
2675:
2676: s_numplayermodels++;
2677: }
2678: if ( dirnames )
2679: FreeFileList( dirnames, ndirs );
2680: }
2681:
2682: static int pmicmpfnc( const void *_a, const void *_b )
2683: {
2684: const playermodelinfo_s *a = ( const playermodelinfo_s * ) _a;
2685: const playermodelinfo_s *b = ( const playermodelinfo_s * ) _b;
2686:
2687: /*
2688: ** sort by male, female, then alphabetical
2689: */
2690: if ( strcmp( a->directory, "male" ) == 0 )
2691: return -1;
2692: else if ( strcmp( b->directory, "male" ) == 0 )
2693: return 1;
2694:
2695: if ( strcmp( a->directory, "female" ) == 0 )
2696: return -1;
2697: else if ( strcmp( b->directory, "female" ) == 0 )
2698: return 1;
2699:
2700: return strcmp( a->directory, b->directory );
2701: }
2702:
2703: void PlayerConfig_MenuInit( void )
2704: {
2705: extern cvar_t *name;
2706: extern cvar_t *team;
2707: extern cvar_t *skin;
2708: char currentdirectory[1024];
2709: char currentskin[1024];
2710: int i = 0;
2711:
2712: int currentdirectoryindex = 0;
2713: int currentskinindex = 0;
2714:
2715: cvar_t *hand = Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
2716:
2717: static const char *handedness[] = { "right", "left", "center", 0 };
2718:
2719: PlayerConfig_ScanDirectories();
2720:
2721: if ( hand->value < 0 || hand->value > 2 )
2722: Cvar_SetValue( "hand", 0 );
2723:
2724: strcpy( currentdirectory, skin->string );
2725:
2726: if ( strchr( currentdirectory, '/' ) )
2727: {
2728: strcpy( currentskin, strchr( currentdirectory, '/' ) + 1 );
2729: *strchr( currentdirectory, '/' ) = 0;
2730: }
2731: else if ( strchr( currentdirectory, '\\' ) )
2732: {
2733: strcpy( currentskin, strchr( currentdirectory, '\\' ) + 1 );
2734: *strchr( currentdirectory, '\\' ) = 0;
2735: }
2736: else
2737: {
2738: strcpy( currentdirectory, "male" );
2739: strcpy( currentskin, "grunt" );
2740: }
2741:
2742: qsort( s_pmi, s_numplayermodels, sizeof( s_pmi[0] ), pmicmpfnc );
2743:
2744: memset( s_pmnames, 0, sizeof( s_pmnames ) );
2745: for ( i = 0; i < s_numplayermodels; i++ )
2746: {
2747: s_pmnames[i] = s_pmi[i].displayname;
2748: if ( Q_stricmp( s_pmi[i].directory, currentdirectory ) == 0 )
2749: {
2750: int j;
2751:
2752: currentdirectoryindex = i;
2753:
2754: for ( j = 0; j < s_pmi[i].nskins; j++ )
2755: {
2756: if ( Q_stricmp( s_pmi[i].skindisplaynames[j], currentskin ) == 0 )
2757: {
2758: currentskinindex = j;
2759: break;
2760: }
2761: }
2762: }
2763: }
2764:
2765: s_player_config_menu.x = viddef.width / 2 - 95;
2766: s_player_config_menu.y = viddef.height / 2 - 97;
2767: s_player_config_menu.nitems = 0;
2768:
2769: s_player_name_field.generic.type = MTYPE_FIELD;
2770: s_player_name_field.generic.name = "name";
2771: s_player_name_field.generic.callback = 0;
2772: s_player_name_field.generic.x = 0;
2773: s_player_name_field.generic.y = 0;
2774: s_player_name_field.length = 20;
2775: s_player_name_field.visible_length = 20;
2776: strcpy( s_player_name_field.buffer, name->string );
2777: s_player_name_field.cursor = strlen( name->string );
2778:
2779: s_player_model_title.generic.type = MTYPE_SEPARATOR;
2780: s_player_model_title.generic.name = "model";
2781: s_player_model_title.generic.x = -8;
2782: s_player_model_title.generic.y = 60;
2783:
2784: s_player_model_box.generic.type = MTYPE_SPINCONTROL;
2785: s_player_model_box.generic.x = -56;
2786: s_player_model_box.generic.y = 70;
2787: s_player_model_box.generic.callback = ModelCallback;
2788: s_player_model_box.generic.cursor_offset = -48;
2789: s_player_model_box.curvalue = currentdirectoryindex;
2790: s_player_model_box.itemnames = s_pmnames;
2791:
2792: s_player_skin_title.generic.type = MTYPE_SEPARATOR;
2793: s_player_skin_title.generic.name = "skin";
2794: s_player_skin_title.generic.x = -16;
2795: s_player_skin_title.generic.y = 84;
2796:
2797: s_player_skin_box.generic.type = MTYPE_SPINCONTROL;
2798: s_player_skin_box.generic.x = -56;
2799: s_player_skin_box.generic.y = 94;
2800: s_player_skin_box.generic.name = 0;
2801: s_player_skin_box.generic.callback = 0;
2802: s_player_skin_box.generic.cursor_offset = -48;
2803: s_player_skin_box.curvalue = currentskinindex;
2804: s_player_skin_box.itemnames = s_pmi[currentdirectoryindex].skindisplaynames;
2805:
2806: s_player_hand_title.generic.type = MTYPE_SEPARATOR;
2807: s_player_hand_title.generic.name = "handedness";
2808: s_player_hand_title.generic.x = 32;
2809: s_player_hand_title.generic.y = 108;
2810:
2811: s_player_handedness_box.generic.type = MTYPE_SPINCONTROL;
2812: s_player_handedness_box.generic.x = -56;
2813: s_player_handedness_box.generic.y = 118;
2814: s_player_handedness_box.generic.name = 0;
2815: s_player_handedness_box.generic.cursor_offset = -48;
2816: s_player_handedness_box.generic.callback = HandednessCallback;
2817: s_player_handedness_box.curvalue = Cvar_VariableValue( "hand" );
2818: s_player_handedness_box.itemnames = handedness;
2819:
2820: Menu_AddItem( &s_player_config_menu, &s_player_name_field );
2821: Menu_AddItem( &s_player_config_menu, &s_player_model_title );
2822: Menu_AddItem( &s_player_config_menu, &s_player_model_box );
2823: if ( s_player_skin_box.itemnames )
2824: {
2825: Menu_AddItem( &s_player_config_menu, &s_player_skin_title );
2826: Menu_AddItem( &s_player_config_menu, &s_player_skin_box );
2827: }
2828: Menu_AddItem( &s_player_config_menu, &s_player_hand_title );
2829: Menu_AddItem( &s_player_config_menu, &s_player_handedness_box );
2830: }
2831:
2832: void PlayerConfig_MenuDraw( void )
2833: {
2834: extern float CalcFov( float fov_x, float w, float h );
2835: refdef_t refdef;
2836: char scratch[MAX_QPATH];
2837:
2838: memset( &refdef, 0, sizeof( refdef ) );
2839:
2840: refdef.x = viddef.width / 2;
2841: refdef.y = viddef.height / 2 - 72;
2842: refdef.width = 144;
2843: refdef.height = 168;
2844: refdef.fov_x = 40;
2845: refdef.fov_y = CalcFov( refdef.fov_x, refdef.width, refdef.height );
2846: refdef.time = cls.realtime*0.001;
2847:
2848: if ( s_pmi[s_player_model_box.curvalue].skindisplaynames )
2849: {
2850: static int yaw;
2851: int maxframe = 29;
2852: entity_t entity;
2853:
2854: memset( &entity, 0, sizeof( entity ) );
2855:
2856: Com_sprintf( scratch, sizeof( scratch ), "players/%s/tris.md2", s_pmi[s_player_model_box.curvalue].directory );
2857: entity.model = re.RegisterModel( scratch );
2858: Com_sprintf( scratch, sizeof( scratch ), "players/%s/%s.pcx", s_pmi[s_player_model_box.curvalue].directory, s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
2859: entity.skin = re.RegisterSkin( scratch );
2860: entity.flags = RF_FULLBRIGHT;
2861: entity.origin[0] = 80;
2862: entity.origin[1] = 0;
2863: entity.origin[2] = 0;
2864: VectorCopy( entity.origin, entity.oldorigin );
2865: entity.frame = 0;
2866: entity.oldframe = 0;
2867: entity.backlerp = 0.0;
2868: entity.angles[1] = yaw++;
2869: if ( ++yaw > 360 )
2870: yaw -= 360;
2871:
2872: refdef.areabits = 0;
2873: refdef.num_entities = 1;
2874: refdef.entities = &entity;
2875: refdef.lightstyles = 0;
2876: refdef.rdflags = RDF_NOWORLDMODEL;
2877:
2878: Menu_Draw( &s_player_config_menu );
2879:
2880: M_DrawTextBox( ( refdef.x ) * ( 320.0F / viddef.width ) - 8, ( viddef.height / 2 ) * ( 240.0F / viddef.height) - 77, refdef.width / 8, refdef.height / 8 );
2881: refdef.height += 4;
2882:
2883: re.RenderFrame( &refdef );
2884:
2885: Com_sprintf( scratch, sizeof( scratch ), "/players/%s/%s_i.pcx",
2886: s_pmi[s_player_model_box.curvalue].directory,
2887: s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
2888: re.DrawPic( s_player_config_menu.x - 40, refdef.y, scratch );
2889: }
2890: }
2891: const char *PlayerConfig_MenuKey (int key)
2892: {
2893: int i;
2894:
2895: if ( key == K_ESCAPE )
2896: {
2897: char scratch[1024];
2898:
2899: Cvar_Set( "name", s_player_name_field.buffer );
2900:
2901: Com_sprintf( scratch, sizeof( scratch ), "%s/%s",
2902: s_pmi[s_player_model_box.curvalue].directory,
2903: s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
2904:
2905: Cvar_Set( "skin", scratch );
2906:
2907: for ( i = 0; i < s_numplayermodels; i++ )
2908: {
2909: int j;
2910:
2911: for ( j = 0; j < s_pmi[i].nskins; j++ )
2912: {
2913: if ( s_pmi[i].skindisplaynames[j] )
2914: free( s_pmi[i].skindisplaynames[j] );
2915: s_pmi[i].skindisplaynames[j] = 0;
2916: }
2917: free( s_pmi[i].skindisplaynames );
2918: s_pmi[i].skindisplaynames = 0;
2919: s_pmi[i].nskins = 0;
2920: }
2921: }
2922: return Default_MenuKey( &s_player_config_menu, key );
2923: }
2924: void M_Menu_PlayerConfig_f (void)
2925: {
2926: PlayerConfig_MenuInit();
2927: M_PushMenu( PlayerConfig_MenuDraw, PlayerConfig_MenuKey );
2928: }
2929: /*
2930: =======================================================================
2931:
2932: GALLERY MENU
2933:
2934: =======================================================================
2935: */
2936: #if 0
2937: void M_Menu_Gallery_f( void )
2938: {
2939: extern void Gallery_MenuDraw( void );
2940: extern const char *Gallery_MenuKey( int key );
2941: M_PushMenu( Gallery_MenuDraw, Gallery_MenuKey );
2942: }
2943: #endif
2944: /*
2945: =======================================================================
2946: QUIT MENU
2947: =======================================================================
2948: */
2949: const char *M_Quit_Key (int key)
2950: {
2951: switch (key)
2952: {
2953: case K_ESCAPE:
2954: case 'n':
2955: case 'N':
2956: M_PopMenu ();
2957: break;
2958: case 'Y':
2959: case 'y':
2960: cls.key_dest = key_console;
2961: CL_Quit_f ();
2962: break;
2963: default:
2964: break;
2965: }
2966: return NULL;
2967: }
2968: void M_Quit_Draw (void)
2969: {
2970: int w, h;
2971: re.DrawGetPicSize (&w, &h, "quit");
2972: re.DrawPic ( (viddef.width-w)/2, (viddef.height-h)/2, "quit");
2973: }
2974: void M_Menu_Quit_f (void)
2975: {
2976: M_PushMenu (M_Quit_Draw, M_Quit_Key);
2977: }
2978: //=============================================================================
2979: /* Menu Subsystem */
2980: /*
2981: =================
2982: M_Init
2983: =================
2984: */
2985: void M_Init (void)
2986: {
2987: Cmd_AddCommand ("menu_main", M_Menu_Main_f);
2988: Cmd_AddCommand ("menu_game", M_Menu_Game_f);
2989: Cmd_AddCommand ("menu_loadgame", M_Menu_LoadGame_f);
2990: Cmd_AddCommand ("menu_savegame", M_Menu_SaveGame_f);
2991: Cmd_AddCommand ("menu_joinserver", M_Menu_JoinServer_f);
2992: Cmd_AddCommand ("menu_addressbook", M_Menu_AddressBook_f);
2993: Cmd_AddCommand ("menu_startserver", M_Menu_StartServer_f);
2994: Cmd_AddCommand ("menu_dmoptions", M_Menu_DMOptions_f);
2995: Cmd_AddCommand ("menu_playerconfig", M_Menu_PlayerConfig_f);
2996: Cmd_AddCommand ("menu_credits", M_Menu_Credits_f );
2997: Cmd_AddCommand ("menu_multiplayer", M_Menu_Multiplayer_f );
2998: Cmd_AddCommand ("menu_video", M_Menu_Video_f);
2999: Cmd_AddCommand ("menu_options", M_Menu_Options_f);
3000: Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
3001: Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
3002: }
3003: /*
3004: =================
3005: M_Draw
3006: =================
3007: */
3008: void M_Draw (void)
3009: {
3010: if (cls.key_dest != key_menu)
3011: return;
3012: // repaint everything next frame
3013: SCR_DirtyScreen ();
3014: // dim everything behind it down
3015: if (cl.cinematictime > 0)
3016: re.DrawFill (0,0,viddef.width, viddef.height, 0);
3017: else
3018: re.DrawFadeScreen ();
3019: m_drawfunc ();
3020: // delay playing the enter sound until after the
3021: // menu has been drawn, to avoid delay while
3022: // caching images
3023: if (m_entersound)
3024: {
3025: S_StartLocalSound( menu_in_sound );
3026: m_entersound = false;
3027: }
3028: }
3029: /*
3030: =================
3031: M_Keydown
3032: =================
3033: */
3034: void M_Keydown (int key)
3035: {
3036: const char *s;
3037: if (m_keyfunc)
3038: if ( ( s = m_keyfunc( key ) ) != 0 )
3039: S_StartLocalSound( ( char * ) s );
3040: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.