|
|
1.1 root 1: #include <ctype.h>
1.1.1.2 root 2: #ifdef _WIN32
1.1 root 3: #include <io.h>
1.1.1.2 root 4: #endif
1.1 root 5: #include "client.h"
6: #include "../client/qmenu.h"
1.1.1.2 root 7:
1.1 root 8: static int m_main_cursor;
1.1.1.2 root 9:
1.1 root 10: #define NUM_CURSOR_FRAMES 15
1.1.1.2 root 11:
1.1 root 12: static char *menu_in_sound = "misc/menu1.wav";
13: static char *menu_move_sound = "misc/menu2.wav";
14: static char *menu_out_sound = "misc/menu3.wav";
1.1.1.2 root 15:
1.1 root 16: void M_Menu_Main_f (void);
17: void M_Menu_Game_f (void);
18: void M_Menu_LoadGame_f (void);
19: void M_Menu_SaveGame_f (void);
20: void M_Menu_PlayerConfig_f (void);
1.1.1.2 root 21: void M_Menu_DownloadOptions_f (void);
1.1 root 22: void M_Menu_Credits_f( void );
23: void M_Menu_Multiplayer_f( void );
24: void M_Menu_JoinServer_f (void);
25: void M_Menu_AddressBook_f( void );
26: void M_Menu_StartServer_f (void);
27: void M_Menu_DMOptions_f (void);
28: void M_Menu_Video_f (void);
29: void M_Menu_Options_f (void);
30: void M_Menu_Keys_f (void);
31: void M_Menu_Quit_f (void);
32:
33: void M_Menu_Credits( void );
1.1.1.2 root 34:
1.1 root 35: qboolean m_entersound; // play after drawing a frame, so caching
36: // won't disrupt the sound
1.1.1.2 root 37:
1.1 root 38: void (*m_drawfunc) (void);
39: const char *(*m_keyfunc) (int key);
1.1.1.2 root 40:
1.1 root 41: //=============================================================================
42: /* Support Routines */
1.1.1.2 root 43:
1.1 root 44: #define MAX_MENU_DEPTH 8
1.1.1.2 root 45:
46:
1.1 root 47: typedef struct
48: {
49: void (*draw) (void);
50: const char *(*key) (int k);
51: } menulayer_t;
1.1.1.2 root 52:
1.1 root 53: menulayer_t m_layers[MAX_MENU_DEPTH];
54: int m_menudepth;
55:
56: static void M_Banner( char *name )
57: {
58: int w, h;
59:
60: re.DrawGetPicSize (&w, &h, name );
61: re.DrawPic( viddef.width / 2 - w / 2, viddef.height / 2 - 110, name );
62: }
1.1.1.2 root 63:
1.1 root 64: void M_PushMenu ( void (*draw) (void), const char *(*key) (int k) )
65: {
66: int i;
67:
68: if (Cvar_VariableValue ("maxclients") == 1
69: && Com_ServerState ())
70: Cvar_Set ("paused", "1");
1.1.1.2 root 71:
1.1.1.3 ! root 72: // if this menu is already present, drop back to that level
1.1 root 73: // to avoid stacking menus by hotkeys
74: for (i=0 ; i<m_menudepth ; i++)
75: if (m_layers[i].draw == draw &&
76: m_layers[i].key == key)
77: {
78: m_menudepth = i;
79: }
1.1.1.2 root 80:
1.1 root 81: if (i == m_menudepth)
82: {
83: if (m_menudepth >= MAX_MENU_DEPTH)
84: Com_Error (ERR_FATAL, "M_PushMenu: MAX_MENU_DEPTH");
85: m_layers[m_menudepth].draw = m_drawfunc;
86: m_layers[m_menudepth].key = m_keyfunc;
87: m_menudepth++;
88: }
1.1.1.2 root 89:
1.1 root 90: m_drawfunc = draw;
91: m_keyfunc = key;
1.1.1.2 root 92:
1.1 root 93: m_entersound = true;
1.1.1.2 root 94:
1.1 root 95: cls.key_dest = key_menu;
96: }
1.1.1.2 root 97:
1.1 root 98: void M_ForceMenuOff (void)
99: {
100: m_drawfunc = 0;
101: m_keyfunc = 0;
102: cls.key_dest = key_game;
103: m_menudepth = 0;
104: Key_ClearStates ();
105: Cvar_Set ("paused", "0");
106: }
1.1.1.2 root 107:
1.1 root 108: void M_PopMenu (void)
109: {
110: S_StartLocalSound( menu_out_sound );
111: if (m_menudepth < 1)
112: Com_Error (ERR_FATAL, "M_PopMenu: depth < 1");
113: m_menudepth--;
1.1.1.2 root 114:
1.1 root 115: m_drawfunc = m_layers[m_menudepth].draw;
116: m_keyfunc = m_layers[m_menudepth].key;
1.1.1.2 root 117:
1.1 root 118: if (!m_menudepth)
119: M_ForceMenuOff ();
120: }
1.1.1.2 root 121:
122:
1.1 root 123: const char *Default_MenuKey( menuframework_s *m, int key )
124: {
125: const char *sound = NULL;
126: menucommon_s *item;
1.1.1.2 root 127:
1.1 root 128: if ( m )
129: {
130: if ( ( item = Menu_ItemAtCursor( m ) ) != 0 )
131: {
132: if ( item->type == MTYPE_FIELD )
133: {
134: if ( Field_Key( ( menufield_s * ) item, key ) )
135: return NULL;
136: }
137: }
138: }
1.1.1.2 root 139:
1.1 root 140: switch ( key )
141: {
142: case K_ESCAPE:
143: M_PopMenu();
144: return menu_out_sound;
145: case K_KP_UPARROW:
146: case K_UPARROW:
147: if ( m )
148: {
149: m->cursor--;
150: Menu_AdjustCursor( m, -1 );
151: sound = menu_move_sound;
152: }
153: break;
154: case K_TAB:
155: if ( m )
156: {
157: m->cursor++;
158: Menu_AdjustCursor( m, 1 );
159: sound = menu_move_sound;
160: }
161: break;
162: case K_KP_DOWNARROW:
163: case K_DOWNARROW:
164: if ( m )
165: {
166: m->cursor++;
167: Menu_AdjustCursor( m, 1 );
168: sound = menu_move_sound;
169: }
170: break;
171: case K_KP_LEFTARROW:
172: case K_LEFTARROW:
173: if ( m )
174: {
175: Menu_SlideItem( m, -1 );
176: sound = menu_move_sound;
177: }
178: break;
179: case K_KP_RIGHTARROW:
180: case K_RIGHTARROW:
181: if ( m )
182: {
183: Menu_SlideItem( m, 1 );
184: sound = menu_move_sound;
185: }
186: break;
187:
188: case K_MOUSE1:
189: case K_MOUSE2:
190: case K_MOUSE3:
191: case K_JOY1:
192: case K_JOY2:
193: case K_JOY3:
194: case K_JOY4:
195: case K_AUX1:
196: case K_AUX2:
197: case K_AUX3:
198: case K_AUX4:
199: case K_AUX5:
200: case K_AUX6:
201: case K_AUX7:
202: case K_AUX8:
203: case K_AUX9:
204: case K_AUX10:
205: case K_AUX11:
206: case K_AUX12:
207: case K_AUX13:
208: case K_AUX14:
209: case K_AUX15:
210: case K_AUX16:
211: case K_AUX17:
212: case K_AUX18:
213: case K_AUX19:
214: case K_AUX20:
215: case K_AUX21:
216: case K_AUX22:
217: case K_AUX23:
218: case K_AUX24:
219: case K_AUX25:
220: case K_AUX26:
221: case K_AUX27:
222: case K_AUX28:
223: case K_AUX29:
224: case K_AUX30:
225: case K_AUX31:
226: case K_AUX32:
227:
228: case K_KP_ENTER:
229: case K_ENTER:
230: if ( m )
231: Menu_SelectItem( m );
232: sound = menu_move_sound;
233: break;
234: }
1.1.1.2 root 235:
1.1 root 236: return sound;
237: }
1.1.1.2 root 238:
1.1 root 239: //=============================================================================
1.1.1.2 root 240:
1.1 root 241: /*
242: ================
243: M_DrawCharacter
1.1.1.2 root 244:
1.1 root 245: Draws one solid graphics character
246: cx and cy are in 320*240 coordinates, and will be centered on
247: higher res screens.
248: ================
249: */
250: void M_DrawCharacter (int cx, int cy, int num)
251: {
252: re.DrawChar ( cx + ((viddef.width - 320)>>1), cy + ((viddef.height - 240)>>1), num);
253: }
1.1.1.2 root 254:
1.1 root 255: void M_Print (int cx, int cy, char *str)
256: {
257: while (*str)
258: {
259: M_DrawCharacter (cx, cy, (*str)+128);
260: str++;
261: cx += 8;
262: }
263: }
1.1.1.2 root 264:
1.1 root 265: void M_PrintWhite (int cx, int cy, char *str)
266: {
267: while (*str)
268: {
269: M_DrawCharacter (cx, cy, *str);
270: str++;
271: cx += 8;
272: }
273: }
1.1.1.2 root 274:
1.1 root 275: void M_DrawPic (int x, int y, char *pic)
276: {
277: re.DrawPic (x + ((viddef.width - 320)>>1), y + ((viddef.height - 240)>>1), pic);
278: }
1.1.1.2 root 279:
280:
1.1 root 281: /*
282: =============
283: M_DrawCursor
1.1.1.2 root 284:
1.1 root 285: Draws an animating cursor with the point at
286: x,y. The pic will extend to the left of x,
287: and both above and below y.
288: =============
289: */
290: void M_DrawCursor( int x, int y, int f )
291: {
292: char cursorname[80];
293: static qboolean cached;
294:
295: if ( !cached )
296: {
297: int i;
298:
299: for ( i = 0; i < NUM_CURSOR_FRAMES; i++ )
300: {
301: Com_sprintf( cursorname, sizeof( cursorname ), "m_cursor%d", i );
302:
303: re.RegisterPic( cursorname );
304: }
305: cached = true;
306: }
1.1.1.2 root 307:
1.1 root 308: Com_sprintf( cursorname, sizeof(cursorname), "m_cursor%d", f );
309: re.DrawPic( x, y, cursorname );
310: }
1.1.1.2 root 311:
1.1 root 312: void M_DrawTextBox (int x, int y, int width, int lines)
313: {
314: int cx, cy;
315: int n;
1.1.1.2 root 316:
1.1 root 317: // draw left side
318: cx = x;
319: cy = y;
320: M_DrawCharacter (cx, cy, 1);
321: for (n = 0; n < lines; n++)
322: {
323: cy += 8;
324: M_DrawCharacter (cx, cy, 4);
325: }
326: M_DrawCharacter (cx, cy+8, 7);
1.1.1.2 root 327:
1.1 root 328: // draw middle
329: cx += 8;
330: while (width > 0)
331: {
332: cy = y;
333: M_DrawCharacter (cx, cy, 2);
334: for (n = 0; n < lines; n++)
335: {
336: cy += 8;
337: M_DrawCharacter (cx, cy, 5);
338: }
339: M_DrawCharacter (cx, cy+8, 8);
340: width -= 1;
341: cx += 8;
342: }
1.1.1.2 root 343:
1.1 root 344: // draw right side
345: cy = y;
346: M_DrawCharacter (cx, cy, 3);
347: for (n = 0; n < lines; n++)
348: {
349: cy += 8;
350: M_DrawCharacter (cx, cy, 6);
351: }
352: M_DrawCharacter (cx, cy+8, 9);
353: }
1.1.1.2 root 354:
1.1 root 355:
356: /*
357: =======================================================================
1.1.1.2 root 358:
1.1 root 359: MAIN MENU
1.1.1.2 root 360:
1.1 root 361: =======================================================================
362: */
363: #define MAIN_ITEMS 5
1.1.1.2 root 364:
365:
1.1 root 366: void M_Main_Draw (void)
367: {
368: int i;
369: int w, h;
370: int ystart;
371: int xoffset;
372: int widest = -1;
373: int totalheight = 0;
374: char litname[80];
375: char *names[] =
376: {
377: "m_main_game",
378: "m_main_multiplayer",
379: "m_main_options",
380: "m_main_video",
381: "m_main_quit",
382: 0
383: };
1.1.1.2 root 384:
1.1 root 385: for ( i = 0; names[i] != 0; i++ )
386: {
387: re.DrawGetPicSize( &w, &h, names[i] );
1.1.1.2 root 388:
1.1 root 389: if ( w > widest )
390: widest = w;
391: totalheight += ( h + 12 );
392: }
393:
394: ystart = ( viddef.height / 2 - 110 );
395: xoffset = ( viddef.width - widest + 70 ) / 2;
1.1.1.2 root 396:
1.1 root 397: for ( i = 0; names[i] != 0; i++ )
398: {
399: if ( i != m_main_cursor )
400: re.DrawPic( xoffset, ystart + i * 40 + 13, names[i] );
401: }
402: strcpy( litname, names[m_main_cursor] );
403: strcat( litname, "_sel" );
404: re.DrawPic( xoffset, ystart + m_main_cursor * 40 + 13, litname );
1.1.1.2 root 405:
1.1 root 406: M_DrawCursor( xoffset - 25, ystart + m_main_cursor * 40 + 11, (int)(cls.realtime / 100)%NUM_CURSOR_FRAMES );
1.1.1.2 root 407:
1.1 root 408: re.DrawGetPicSize( &w, &h, "m_main_plaque" );
409: re.DrawPic( xoffset - 30 - w, ystart, "m_main_plaque" );
1.1.1.2 root 410:
1.1 root 411: re.DrawPic( xoffset - 30 - w, ystart + h + 5, "m_main_logo" );
412: }
1.1.1.2 root 413:
414:
1.1 root 415: const char *M_Main_Key (int key)
416: {
417: const char *sound = menu_move_sound;
1.1.1.2 root 418:
1.1 root 419: switch (key)
420: {
421: case K_ESCAPE:
422: M_PopMenu ();
423: break;
424:
425: case K_KP_DOWNARROW:
426: case K_DOWNARROW:
427: if (++m_main_cursor >= MAIN_ITEMS)
428: m_main_cursor = 0;
429: return sound;
1.1.1.2 root 430:
1.1 root 431: case K_KP_UPARROW:
432: case K_UPARROW:
433: if (--m_main_cursor < 0)
434: m_main_cursor = MAIN_ITEMS - 1;
435: return sound;
436:
437: case K_KP_ENTER:
438: case K_ENTER:
439: m_entersound = true;
1.1.1.2 root 440:
1.1 root 441: switch (m_main_cursor)
442: {
443: case 0:
444: M_Menu_Game_f ();
445: break;
1.1.1.2 root 446:
1.1 root 447: case 1:
448: M_Menu_Multiplayer_f();
449: break;
1.1.1.2 root 450:
1.1 root 451: case 2:
452: M_Menu_Options_f ();
453: break;
1.1.1.2 root 454:
1.1 root 455: case 3:
456: M_Menu_Video_f ();
457: break;
1.1.1.2 root 458:
1.1 root 459: case 4:
460: M_Menu_Quit_f ();
461: break;
462: }
463: }
1.1.1.2 root 464:
1.1 root 465: return NULL;
466: }
1.1.1.2 root 467:
468:
1.1 root 469: void M_Menu_Main_f (void)
470: {
471: M_PushMenu (M_Main_Draw, M_Main_Key);
472: }
473:
474: /*
475: =======================================================================
476:
477: MULTIPLAYER MENU
478:
479: =======================================================================
480: */
481: static menuframework_s s_multiplayer_menu;
482: static menuaction_s s_join_network_server_action;
483: static menuaction_s s_start_network_server_action;
484: static menuaction_s s_player_setup_action;
485:
486: static void Multiplayer_MenuDraw (void)
487: {
488: M_Banner( "m_banner_multiplayer" );
489:
490: Menu_AdjustCursor( &s_multiplayer_menu, 1 );
491: Menu_Draw( &s_multiplayer_menu );
492: }
493:
494: static void PlayerSetupFunc( void *unused )
495: {
496: M_Menu_PlayerConfig_f();
497: }
498:
499: static void JoinNetworkServerFunc( void *unused )
500: {
501: M_Menu_JoinServer_f();
502: }
503:
504: static void StartNetworkServerFunc( void *unused )
505: {
506: M_Menu_StartServer_f ();
507: }
508:
509: void Multiplayer_MenuInit( void )
510: {
511: s_multiplayer_menu.x = viddef.width * 0.50 - 64;
512: s_multiplayer_menu.nitems = 0;
513:
514: s_join_network_server_action.generic.type = MTYPE_ACTION;
515: s_join_network_server_action.generic.flags = QMF_LEFT_JUSTIFY;
516: s_join_network_server_action.generic.x = 0;
517: s_join_network_server_action.generic.y = 0;
518: s_join_network_server_action.generic.name = " join network server";
519: s_join_network_server_action.generic.callback = JoinNetworkServerFunc;
520:
521: s_start_network_server_action.generic.type = MTYPE_ACTION;
522: s_start_network_server_action.generic.flags = QMF_LEFT_JUSTIFY;
523: s_start_network_server_action.generic.x = 0;
524: s_start_network_server_action.generic.y = 10;
525: s_start_network_server_action.generic.name = " start network server";
526: s_start_network_server_action.generic.callback = StartNetworkServerFunc;
527:
528: s_player_setup_action.generic.type = MTYPE_ACTION;
529: s_player_setup_action.generic.flags = QMF_LEFT_JUSTIFY;
530: s_player_setup_action.generic.x = 0;
531: s_player_setup_action.generic.y = 20;
532: s_player_setup_action.generic.name = " player setup";
533: s_player_setup_action.generic.callback = PlayerSetupFunc;
534:
535: Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_join_network_server_action );
536: Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_start_network_server_action );
537: Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_player_setup_action );
538:
1.1.1.2 root 539: Menu_SetStatusBar( &s_multiplayer_menu, NULL );
540:
1.1 root 541: Menu_Center( &s_multiplayer_menu );
542: }
543:
544: const char *Multiplayer_MenuKey( int key )
545: {
546: return Default_MenuKey( &s_multiplayer_menu, key );
547: }
548:
549: void M_Menu_Multiplayer_f( void )
550: {
551: Multiplayer_MenuInit();
552: M_PushMenu( Multiplayer_MenuDraw, Multiplayer_MenuKey );
553: }
1.1.1.2 root 554:
1.1 root 555: /*
556: =======================================================================
557:
558: KEYS MENU
559:
560: =======================================================================
561: */
562: char *bindnames[][2] =
563: {
564: {"+attack", "attack"},
565: {"weapnext", "next weapon"},
566: {"+forward", "walk forward"},
567: {"+back", "backpedal"},
568: {"+left", "turn left"},
569: {"+right", "turn right"},
570: {"+speed", "run"},
571: {"+moveleft", "step left"},
572: {"+moveright", "step right"},
573: {"+strafe", "sidestep"},
574: {"+lookup", "look up"},
575: {"+lookdown", "look down"},
576: {"centerview", "center view"},
577: {"+mlook", "mouse look"},
578: {"+klook", "keyboard look"},
579: {"+moveup", "up / jump"},
580: {"+movedown", "down / crouch"},
1.1.1.2 root 581:
1.1 root 582: {"inven", "inventory"},
583: {"invuse", "use item"},
584: {"invdrop", "drop item"},
585: {"invprev", "prev item"},
586: {"invnext", "next item"},
1.1.1.2 root 587:
1.1 root 588: {"cmd help", "help computer" },
589: { 0, 0 }
590: };
1.1.1.2 root 591:
1.1 root 592: int keys_cursor;
593: static int bind_grab;
1.1.1.2 root 594:
1.1 root 595: static menuframework_s s_keys_menu;
596: static menuaction_s s_keys_attack_action;
597: static menuaction_s s_keys_change_weapon_action;
598: static menuaction_s s_keys_walk_forward_action;
599: static menuaction_s s_keys_backpedal_action;
600: static menuaction_s s_keys_turn_left_action;
601: static menuaction_s s_keys_turn_right_action;
602: static menuaction_s s_keys_run_action;
603: static menuaction_s s_keys_step_left_action;
604: static menuaction_s s_keys_step_right_action;
605: static menuaction_s s_keys_sidestep_action;
606: static menuaction_s s_keys_look_up_action;
607: static menuaction_s s_keys_look_down_action;
608: static menuaction_s s_keys_center_view_action;
609: static menuaction_s s_keys_mouse_look_action;
610: static menuaction_s s_keys_keyboard_look_action;
611: static menuaction_s s_keys_move_up_action;
612: static menuaction_s s_keys_move_down_action;
613: static menuaction_s s_keys_inventory_action;
614: static menuaction_s s_keys_inv_use_action;
615: static menuaction_s s_keys_inv_drop_action;
616: static menuaction_s s_keys_inv_prev_action;
617: static menuaction_s s_keys_inv_next_action;
1.1.1.2 root 618:
1.1 root 619: static menuaction_s s_keys_help_computer_action;
1.1.1.2 root 620:
1.1 root 621: static void M_UnbindCommand (char *command)
622: {
623: int j;
624: int l;
625: char *b;
1.1.1.2 root 626:
1.1 root 627: l = strlen(command);
1.1.1.2 root 628:
1.1 root 629: for (j=0 ; j<256 ; j++)
630: {
631: b = keybindings[j];
632: if (!b)
633: continue;
634: if (!strncmp (b, command, l) )
635: Key_SetBinding (j, "");
636: }
637: }
1.1.1.2 root 638:
1.1 root 639: static void M_FindKeysForCommand (char *command, int *twokeys)
640: {
641: int count;
642: int j;
643: int l;
644: char *b;
1.1.1.2 root 645:
1.1 root 646: twokeys[0] = twokeys[1] = -1;
647: l = strlen(command);
648: count = 0;
1.1.1.2 root 649:
1.1 root 650: for (j=0 ; j<256 ; j++)
651: {
652: b = keybindings[j];
653: if (!b)
654: continue;
655: if (!strncmp (b, command, l) )
656: {
657: twokeys[count] = j;
658: count++;
659: if (count == 2)
660: break;
661: }
662: }
663: }
1.1.1.2 root 664:
1.1 root 665: static void KeyCursorDrawFunc( menuframework_s *menu )
666: {
667: if ( bind_grab )
668: re.DrawChar( menu->x, menu->y + menu->cursor * 9, '=' );
669: else
670: re.DrawChar( menu->x, menu->y + menu->cursor * 9, 12 + ( ( int ) ( Sys_Milliseconds() / 250 ) & 1 ) );
671: }
1.1.1.2 root 672:
1.1 root 673: static void DrawKeyBindingFunc( void *self )
674: {
675: int keys[2];
676: menuaction_s *a = ( menuaction_s * ) self;
1.1.1.2 root 677:
1.1 root 678: M_FindKeysForCommand( bindnames[a->generic.localdata[0]][0], keys);
679:
680: if (keys[0] == -1)
681: {
682: Menu_DrawString( a->generic.x + a->generic.parent->x + 16, a->generic.y + a->generic.parent->y, "???" );
683: }
684: else
685: {
686: int x;
687: const char *name;
1.1.1.2 root 688:
1.1 root 689: name = Key_KeynumToString (keys[0]);
1.1.1.2 root 690:
1.1 root 691: Menu_DrawString( a->generic.x + a->generic.parent->x + 16, a->generic.y + a->generic.parent->y, name );
1.1.1.2 root 692:
1.1 root 693: x = strlen(name) * 8;
1.1.1.2 root 694:
1.1 root 695: if (keys[1] != -1)
696: {
697: Menu_DrawString( a->generic.x + a->generic.parent->x + 24 + x, a->generic.y + a->generic.parent->y, "or" );
698: Menu_DrawString( a->generic.x + a->generic.parent->x + 48 + x, a->generic.y + a->generic.parent->y, Key_KeynumToString (keys[1]) );
699: }
700: }
701: }
1.1.1.2 root 702:
1.1 root 703: static void KeyBindingFunc( void *self )
704: {
705: menuaction_s *a = ( menuaction_s * ) self;
706: int keys[2];
1.1.1.2 root 707:
1.1 root 708: M_FindKeysForCommand( bindnames[a->generic.localdata[0]][0], keys );
1.1.1.2 root 709:
1.1 root 710: if (keys[1] != -1)
711: M_UnbindCommand( bindnames[a->generic.localdata[0]][0]);
1.1.1.2 root 712:
1.1 root 713: bind_grab = true;
1.1.1.2 root 714:
1.1 root 715: Menu_SetStatusBar( &s_keys_menu, "press a key or button for this action" );
716: }
1.1.1.2 root 717:
1.1 root 718: static void Keys_MenuInit( void )
719: {
720: int y = 0;
721: int i = 0;
1.1.1.2 root 722:
1.1 root 723: s_keys_menu.x = viddef.width * 0.50;
724: s_keys_menu.nitems = 0;
725: s_keys_menu.cursordraw = KeyCursorDrawFunc;
1.1.1.2 root 726:
1.1 root 727: s_keys_attack_action.generic.type = MTYPE_ACTION;
728: s_keys_attack_action.generic.flags = QMF_GRAYED;
729: s_keys_attack_action.generic.x = 0;
730: s_keys_attack_action.generic.y = y;
731: s_keys_attack_action.generic.ownerdraw = DrawKeyBindingFunc;
732: s_keys_attack_action.generic.localdata[0] = i;
733: s_keys_attack_action.generic.name = bindnames[s_keys_attack_action.generic.localdata[0]][1];
1.1.1.2 root 734:
1.1 root 735: s_keys_change_weapon_action.generic.type = MTYPE_ACTION;
736: s_keys_change_weapon_action.generic.flags = QMF_GRAYED;
737: s_keys_change_weapon_action.generic.x = 0;
738: s_keys_change_weapon_action.generic.y = y += 9;
739: s_keys_change_weapon_action.generic.ownerdraw = DrawKeyBindingFunc;
740: s_keys_change_weapon_action.generic.localdata[0] = ++i;
741: s_keys_change_weapon_action.generic.name = bindnames[s_keys_change_weapon_action.generic.localdata[0]][1];
1.1.1.2 root 742:
1.1 root 743: s_keys_walk_forward_action.generic.type = MTYPE_ACTION;
744: s_keys_walk_forward_action.generic.flags = QMF_GRAYED;
745: s_keys_walk_forward_action.generic.x = 0;
746: s_keys_walk_forward_action.generic.y = y += 9;
747: s_keys_walk_forward_action.generic.ownerdraw = DrawKeyBindingFunc;
748: s_keys_walk_forward_action.generic.localdata[0] = ++i;
749: s_keys_walk_forward_action.generic.name = bindnames[s_keys_walk_forward_action.generic.localdata[0]][1];
1.1.1.2 root 750:
1.1 root 751: s_keys_backpedal_action.generic.type = MTYPE_ACTION;
752: s_keys_backpedal_action.generic.flags = QMF_GRAYED;
753: s_keys_backpedal_action.generic.x = 0;
754: s_keys_backpedal_action.generic.y = y += 9;
755: s_keys_backpedal_action.generic.ownerdraw = DrawKeyBindingFunc;
756: s_keys_backpedal_action.generic.localdata[0] = ++i;
757: s_keys_backpedal_action.generic.name = bindnames[s_keys_backpedal_action.generic.localdata[0]][1];
1.1.1.2 root 758:
1.1 root 759: s_keys_turn_left_action.generic.type = MTYPE_ACTION;
760: s_keys_turn_left_action.generic.flags = QMF_GRAYED;
761: s_keys_turn_left_action.generic.x = 0;
762: s_keys_turn_left_action.generic.y = y += 9;
763: s_keys_turn_left_action.generic.ownerdraw = DrawKeyBindingFunc;
764: s_keys_turn_left_action.generic.localdata[0] = ++i;
765: s_keys_turn_left_action.generic.name = bindnames[s_keys_turn_left_action.generic.localdata[0]][1];
1.1.1.2 root 766:
1.1 root 767: s_keys_turn_right_action.generic.type = MTYPE_ACTION;
768: s_keys_turn_right_action.generic.flags = QMF_GRAYED;
769: s_keys_turn_right_action.generic.x = 0;
770: s_keys_turn_right_action.generic.y = y += 9;
771: s_keys_turn_right_action.generic.ownerdraw = DrawKeyBindingFunc;
772: s_keys_turn_right_action.generic.localdata[0] = ++i;
773: s_keys_turn_right_action.generic.name = bindnames[s_keys_turn_right_action.generic.localdata[0]][1];
1.1.1.2 root 774:
1.1 root 775: s_keys_run_action.generic.type = MTYPE_ACTION;
776: s_keys_run_action.generic.flags = QMF_GRAYED;
777: s_keys_run_action.generic.x = 0;
778: s_keys_run_action.generic.y = y += 9;
779: s_keys_run_action.generic.ownerdraw = DrawKeyBindingFunc;
780: s_keys_run_action.generic.localdata[0] = ++i;
781: s_keys_run_action.generic.name = bindnames[s_keys_run_action.generic.localdata[0]][1];
1.1.1.2 root 782:
1.1 root 783: s_keys_step_left_action.generic.type = MTYPE_ACTION;
784: s_keys_step_left_action.generic.flags = QMF_GRAYED;
785: s_keys_step_left_action.generic.x = 0;
786: s_keys_step_left_action.generic.y = y += 9;
787: s_keys_step_left_action.generic.ownerdraw = DrawKeyBindingFunc;
788: s_keys_step_left_action.generic.localdata[0] = ++i;
789: s_keys_step_left_action.generic.name = bindnames[s_keys_step_left_action.generic.localdata[0]][1];
1.1.1.2 root 790:
1.1 root 791: s_keys_step_right_action.generic.type = MTYPE_ACTION;
792: s_keys_step_right_action.generic.flags = QMF_GRAYED;
793: s_keys_step_right_action.generic.x = 0;
794: s_keys_step_right_action.generic.y = y += 9;
795: s_keys_step_right_action.generic.ownerdraw = DrawKeyBindingFunc;
796: s_keys_step_right_action.generic.localdata[0] = ++i;
797: s_keys_step_right_action.generic.name = bindnames[s_keys_step_right_action.generic.localdata[0]][1];
1.1.1.2 root 798:
1.1 root 799: s_keys_sidestep_action.generic.type = MTYPE_ACTION;
800: s_keys_sidestep_action.generic.flags = QMF_GRAYED;
801: s_keys_sidestep_action.generic.x = 0;
802: s_keys_sidestep_action.generic.y = y += 9;
803: s_keys_sidestep_action.generic.ownerdraw = DrawKeyBindingFunc;
804: s_keys_sidestep_action.generic.localdata[0] = ++i;
805: s_keys_sidestep_action.generic.name = bindnames[s_keys_sidestep_action.generic.localdata[0]][1];
1.1.1.2 root 806:
1.1 root 807: s_keys_look_up_action.generic.type = MTYPE_ACTION;
808: s_keys_look_up_action.generic.flags = QMF_GRAYED;
809: s_keys_look_up_action.generic.x = 0;
810: s_keys_look_up_action.generic.y = y += 9;
811: s_keys_look_up_action.generic.ownerdraw = DrawKeyBindingFunc;
812: s_keys_look_up_action.generic.localdata[0] = ++i;
813: s_keys_look_up_action.generic.name = bindnames[s_keys_look_up_action.generic.localdata[0]][1];
1.1.1.2 root 814:
1.1 root 815: s_keys_look_down_action.generic.type = MTYPE_ACTION;
816: s_keys_look_down_action.generic.flags = QMF_GRAYED;
817: s_keys_look_down_action.generic.x = 0;
818: s_keys_look_down_action.generic.y = y += 9;
819: s_keys_look_down_action.generic.ownerdraw = DrawKeyBindingFunc;
820: s_keys_look_down_action.generic.localdata[0] = ++i;
821: s_keys_look_down_action.generic.name = bindnames[s_keys_look_down_action.generic.localdata[0]][1];
1.1.1.2 root 822:
1.1 root 823: s_keys_center_view_action.generic.type = MTYPE_ACTION;
824: s_keys_center_view_action.generic.flags = QMF_GRAYED;
825: s_keys_center_view_action.generic.x = 0;
826: s_keys_center_view_action.generic.y = y += 9;
827: s_keys_center_view_action.generic.ownerdraw = DrawKeyBindingFunc;
828: s_keys_center_view_action.generic.localdata[0] = ++i;
829: s_keys_center_view_action.generic.name = bindnames[s_keys_center_view_action.generic.localdata[0]][1];
1.1.1.2 root 830:
1.1 root 831: s_keys_mouse_look_action.generic.type = MTYPE_ACTION;
832: s_keys_mouse_look_action.generic.flags = QMF_GRAYED;
833: s_keys_mouse_look_action.generic.x = 0;
834: s_keys_mouse_look_action.generic.y = y += 9;
835: s_keys_mouse_look_action.generic.ownerdraw = DrawKeyBindingFunc;
836: s_keys_mouse_look_action.generic.localdata[0] = ++i;
837: s_keys_mouse_look_action.generic.name = bindnames[s_keys_mouse_look_action.generic.localdata[0]][1];
1.1.1.2 root 838:
1.1 root 839: s_keys_keyboard_look_action.generic.type = MTYPE_ACTION;
840: s_keys_keyboard_look_action.generic.flags = QMF_GRAYED;
841: s_keys_keyboard_look_action.generic.x = 0;
842: s_keys_keyboard_look_action.generic.y = y += 9;
843: s_keys_keyboard_look_action.generic.ownerdraw = DrawKeyBindingFunc;
844: s_keys_keyboard_look_action.generic.localdata[0] = ++i;
845: s_keys_keyboard_look_action.generic.name = bindnames[s_keys_keyboard_look_action.generic.localdata[0]][1];
1.1.1.2 root 846:
1.1 root 847: s_keys_move_up_action.generic.type = MTYPE_ACTION;
848: s_keys_move_up_action.generic.flags = QMF_GRAYED;
849: s_keys_move_up_action.generic.x = 0;
850: s_keys_move_up_action.generic.y = y += 9;
851: s_keys_move_up_action.generic.ownerdraw = DrawKeyBindingFunc;
852: s_keys_move_up_action.generic.localdata[0] = ++i;
853: s_keys_move_up_action.generic.name = bindnames[s_keys_move_up_action.generic.localdata[0]][1];
1.1.1.2 root 854:
1.1 root 855: s_keys_move_down_action.generic.type = MTYPE_ACTION;
856: s_keys_move_down_action.generic.flags = QMF_GRAYED;
857: s_keys_move_down_action.generic.x = 0;
858: s_keys_move_down_action.generic.y = y += 9;
859: s_keys_move_down_action.generic.ownerdraw = DrawKeyBindingFunc;
860: s_keys_move_down_action.generic.localdata[0] = ++i;
861: s_keys_move_down_action.generic.name = bindnames[s_keys_move_down_action.generic.localdata[0]][1];
1.1.1.2 root 862:
1.1 root 863: s_keys_inventory_action.generic.type = MTYPE_ACTION;
864: s_keys_inventory_action.generic.flags = QMF_GRAYED;
865: s_keys_inventory_action.generic.x = 0;
866: s_keys_inventory_action.generic.y = y += 9;
867: s_keys_inventory_action.generic.ownerdraw = DrawKeyBindingFunc;
868: s_keys_inventory_action.generic.localdata[0] = ++i;
869: s_keys_inventory_action.generic.name = bindnames[s_keys_inventory_action.generic.localdata[0]][1];
1.1.1.2 root 870:
1.1 root 871: s_keys_inv_use_action.generic.type = MTYPE_ACTION;
872: s_keys_inv_use_action.generic.flags = QMF_GRAYED;
873: s_keys_inv_use_action.generic.x = 0;
874: s_keys_inv_use_action.generic.y = y += 9;
875: s_keys_inv_use_action.generic.ownerdraw = DrawKeyBindingFunc;
876: s_keys_inv_use_action.generic.localdata[0] = ++i;
877: s_keys_inv_use_action.generic.name = bindnames[s_keys_inv_use_action.generic.localdata[0]][1];
1.1.1.2 root 878:
1.1 root 879: s_keys_inv_drop_action.generic.type = MTYPE_ACTION;
880: s_keys_inv_drop_action.generic.flags = QMF_GRAYED;
881: s_keys_inv_drop_action.generic.x = 0;
882: s_keys_inv_drop_action.generic.y = y += 9;
883: s_keys_inv_drop_action.generic.ownerdraw = DrawKeyBindingFunc;
884: s_keys_inv_drop_action.generic.localdata[0] = ++i;
885: s_keys_inv_drop_action.generic.name = bindnames[s_keys_inv_drop_action.generic.localdata[0]][1];
1.1.1.2 root 886:
1.1 root 887: s_keys_inv_prev_action.generic.type = MTYPE_ACTION;
888: s_keys_inv_prev_action.generic.flags = QMF_GRAYED;
889: s_keys_inv_prev_action.generic.x = 0;
890: s_keys_inv_prev_action.generic.y = y += 9;
891: s_keys_inv_prev_action.generic.ownerdraw = DrawKeyBindingFunc;
892: s_keys_inv_prev_action.generic.localdata[0] = ++i;
893: s_keys_inv_prev_action.generic.name = bindnames[s_keys_inv_prev_action.generic.localdata[0]][1];
1.1.1.2 root 894:
1.1 root 895: s_keys_inv_next_action.generic.type = MTYPE_ACTION;
896: s_keys_inv_next_action.generic.flags = QMF_GRAYED;
897: s_keys_inv_next_action.generic.x = 0;
898: s_keys_inv_next_action.generic.y = y += 9;
899: s_keys_inv_next_action.generic.ownerdraw = DrawKeyBindingFunc;
900: s_keys_inv_next_action.generic.localdata[0] = ++i;
901: s_keys_inv_next_action.generic.name = bindnames[s_keys_inv_next_action.generic.localdata[0]][1];
1.1.1.2 root 902:
1.1 root 903: s_keys_help_computer_action.generic.type = MTYPE_ACTION;
904: s_keys_help_computer_action.generic.flags = QMF_GRAYED;
905: s_keys_help_computer_action.generic.x = 0;
906: s_keys_help_computer_action.generic.y = y += 9;
907: s_keys_help_computer_action.generic.ownerdraw = DrawKeyBindingFunc;
908: s_keys_help_computer_action.generic.localdata[0] = ++i;
909: s_keys_help_computer_action.generic.name = bindnames[s_keys_help_computer_action.generic.localdata[0]][1];
1.1.1.2 root 910:
1.1 root 911: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_attack_action );
912: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_change_weapon_action );
913: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_walk_forward_action );
914: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_backpedal_action );
915: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_turn_left_action );
916: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_turn_right_action );
917: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_run_action );
918: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_step_left_action );
919: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_step_right_action );
920: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_sidestep_action );
921: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_look_up_action );
922: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_look_down_action );
923: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_center_view_action );
924: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_mouse_look_action );
925: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_keyboard_look_action );
926: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_move_up_action );
927: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_move_down_action );
1.1.1.2 root 928:
1.1 root 929: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inventory_action );
930: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_use_action );
931: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_drop_action );
932: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_prev_action );
933: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_next_action );
1.1.1.2 root 934:
1.1 root 935: Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_help_computer_action );
936:
937: Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
938: Menu_Center( &s_keys_menu );
939: }
1.1.1.2 root 940:
1.1 root 941: static void Keys_MenuDraw (void)
942: {
943: Menu_AdjustCursor( &s_keys_menu, 1 );
944: Menu_Draw( &s_keys_menu );
945: }
1.1.1.2 root 946:
1.1 root 947: static const char *Keys_MenuKey( int key )
948: {
949: menuaction_s *item = ( menuaction_s * ) Menu_ItemAtCursor( &s_keys_menu );
1.1.1.2 root 950:
1.1 root 951: if ( bind_grab )
952: {
953: if ( key != K_ESCAPE && key != '`' )
954: {
955: char cmd[1024];
1.1.1.2 root 956:
1.1 root 957: Com_sprintf (cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", Key_KeynumToString(key), bindnames[item->generic.localdata[0]][0]);
958: Cbuf_InsertText (cmd);
959: }
960:
961: Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
962: bind_grab = false;
963: return menu_out_sound;
964: }
1.1.1.2 root 965:
1.1 root 966: switch ( key )
967: {
968: case K_KP_ENTER:
969: case K_ENTER:
970: KeyBindingFunc( item );
971: return menu_in_sound;
972: case K_BACKSPACE: // delete bindings
973: case K_DEL: // delete bindings
974: case K_KP_DEL:
975: M_UnbindCommand( bindnames[item->generic.localdata[0]][0] );
976: return menu_out_sound;
977: default:
978: return Default_MenuKey( &s_keys_menu, key );
979: }
980: }
1.1.1.2 root 981:
1.1 root 982: void M_Menu_Keys_f (void)
983: {
984: Keys_MenuInit();
985: M_PushMenu( Keys_MenuDraw, Keys_MenuKey );
986: }
1.1.1.2 root 987:
988:
1.1 root 989: /*
990: =======================================================================
1.1.1.2 root 991:
1.1 root 992: CONTROLS MENU
1.1.1.2 root 993:
1.1 root 994: =======================================================================
995: */
996: static cvar_t *win_noalttab;
997: extern cvar_t *in_joystick;
1.1.1.2 root 998:
1.1 root 999: static menuframework_s s_options_menu;
1000: static menuaction_s s_options_defaults_action;
1001: static menuaction_s s_options_customize_options_action;
1002: static menuslider_s s_options_sensitivity_slider;
1003: static menulist_s s_options_freelook_box;
1004: static menulist_s s_options_noalttab_box;
1005: static menulist_s s_options_alwaysrun_box;
1006: static menulist_s s_options_invertmouse_box;
1007: static menulist_s s_options_lookspring_box;
1008: static menulist_s s_options_lookstrafe_box;
1009: static menulist_s s_options_crosshair_box;
1010: static menuslider_s s_options_sfxvolume_slider;
1011: static menulist_s s_options_joystick_box;
1012: static menulist_s s_options_cdvolume_box;
1013: static menulist_s s_options_quality_list;
1014: static menulist_s s_options_compatibility_list;
1015: static menulist_s s_options_console_action;
1016:
1017: static void CrosshairFunc( void *unused )
1018: {
1019: Cvar_SetValue( "crosshair", s_options_crosshair_box.curvalue );
1020: }
1021:
1022: static void JoystickFunc( void *unused )
1023: {
1024: Cvar_SetValue( "in_joystick", s_options_joystick_box.curvalue );
1025: }
1.1.1.2 root 1026:
1.1 root 1027: static void CustomizeControlsFunc( void *unused )
1028: {
1029: M_Menu_Keys_f();
1030: }
1.1.1.2 root 1031:
1.1 root 1032: static void AlwaysRunFunc( void *unused )
1033: {
1034: Cvar_SetValue( "cl_run", s_options_alwaysrun_box.curvalue );
1035: }
1.1.1.2 root 1036:
1.1 root 1037: static void FreeLookFunc( void *unused )
1038: {
1039: Cvar_SetValue( "freelook", s_options_freelook_box.curvalue );
1040: }
1.1.1.2 root 1041:
1.1 root 1042: static void MouseSpeedFunc( void *unused )
1043: {
1044: Cvar_SetValue( "sensitivity", s_options_sensitivity_slider.curvalue / 2.0F );
1045: }
1.1.1.2 root 1046:
1.1 root 1047: static void NoAltTabFunc( void *unused )
1048: {
1049: Cvar_SetValue( "win_noalttab", s_options_noalttab_box.curvalue );
1050: }
1.1.1.2 root 1051:
1.1 root 1052: static float ClampCvar( float min, float max, float value )
1053: {
1054: if ( value < min ) return min;
1055: if ( value > max ) return max;
1056: return value;
1057: }
1058:
1059: static void ControlsSetMenuItemValues( void )
1060: {
1061: s_options_sfxvolume_slider.curvalue = Cvar_VariableValue( "s_volume" ) * 10;
1062: s_options_cdvolume_box.curvalue = !Cvar_VariableValue("cd_nocd");
1063: s_options_quality_list.curvalue = !Cvar_VariableValue( "s_loadas8bit" );
1064: s_options_sensitivity_slider.curvalue = ( sensitivity->value ) * 2;
1065:
1066: Cvar_SetValue( "cl_run", ClampCvar( 0, 1, cl_run->value ) );
1067: s_options_alwaysrun_box.curvalue = cl_run->value;
1068:
1069: s_options_invertmouse_box.curvalue = m_pitch->value < 0;
1070:
1071: Cvar_SetValue( "lookspring", ClampCvar( 0, 1, lookspring->value ) );
1072: s_options_lookspring_box.curvalue = lookspring->value;
1073:
1074: Cvar_SetValue( "lookstrafe", ClampCvar( 0, 1, lookstrafe->value ) );
1075: s_options_lookstrafe_box.curvalue = lookstrafe->value;
1076:
1077: Cvar_SetValue( "freelook", ClampCvar( 0, 1, freelook->value ) );
1078: s_options_freelook_box.curvalue = freelook->value;
1079:
1080: Cvar_SetValue( "crosshair", ClampCvar( 0, 3, crosshair->value ) );
1081: s_options_crosshair_box.curvalue = crosshair->value;
1082:
1083: Cvar_SetValue( "in_joystick", ClampCvar( 0, 1, in_joystick->value ) );
1084: s_options_joystick_box.curvalue = in_joystick->value;
1085:
1086: s_options_noalttab_box.curvalue = win_noalttab->value;
1087: }
1.1.1.2 root 1088:
1.1 root 1089: static void ControlsResetDefaultsFunc( void *unused )
1090: {
1091: Cbuf_AddText ("exec default.cfg\n");
1092: Cbuf_Execute();
1093:
1094: ControlsSetMenuItemValues();
1095: }
1.1.1.2 root 1096:
1.1 root 1097: static void InvertMouseFunc( void *unused )
1098: {
1099: Cvar_SetValue( "m_pitch", -m_pitch->value );
1100: }
1.1.1.2 root 1101:
1.1 root 1102: static void LookspringFunc( void *unused )
1103: {
1104: Cvar_SetValue( "lookspring", !lookspring->value );
1105: }
1.1.1.2 root 1106:
1.1 root 1107: static void LookstrafeFunc( void *unused )
1108: {
1109: Cvar_SetValue( "lookstrafe", !lookstrafe->value );
1110: }
1.1.1.2 root 1111:
1.1 root 1112: static void UpdateVolumeFunc( void *unused )
1113: {
1114: Cvar_SetValue( "s_volume", s_options_sfxvolume_slider.curvalue / 10 );
1115: }
1116:
1117: static void UpdateCDVolumeFunc( void *unused )
1118: {
1119: Cvar_SetValue( "cd_nocd", !s_options_cdvolume_box.curvalue );
1120: }
1121:
1122: static void ConsoleFunc( void *unused )
1123: {
1124: /*
1125: ** the proper way to do this is probably to have ToggleConsole_f accept a parameter
1126: */
1127: extern void Key_ClearTyping( void );
1128:
1129: if ( cl.attractloop )
1130: {
1131: Cbuf_AddText ("killserver\n");
1132: return;
1133: }
1134:
1135: Key_ClearTyping ();
1136: Con_ClearNotify ();
1137:
1138: M_ForceMenuOff ();
1139: cls.key_dest = key_console;
1140: }
1141:
1142: static void UpdateSoundQualityFunc( void *unused )
1143: {
1144: if ( s_options_quality_list.curvalue )
1145: {
1146: Cvar_SetValue( "s_khz", 22 );
1147: Cvar_SetValue( "s_loadas8bit", false );
1148: }
1149: else
1150: {
1151: Cvar_SetValue( "s_khz", 11 );
1152: Cvar_SetValue( "s_loadas8bit", true );
1153: }
1154:
1155: Cvar_SetValue( "s_primary", s_options_compatibility_list.curvalue );
1156:
1157: M_DrawTextBox( 8, 120 - 48, 36, 3 );
1158: M_Print( 16 + 16, 120 - 48 + 8, "Restarting the sound system. This" );
1159: M_Print( 16 + 16, 120 - 48 + 16, "could take up to a minute, so" );
1160: M_Print( 16 + 16, 120 - 48 + 24, "please be patient." );
1161:
1162: // the text box won't show up unless we do a buffer swap
1163: re.EndFrame();
1164:
1165: CL_Snd_Restart_f();
1166: }
1167:
1168: void Options_MenuInit( void )
1169: {
1170: static const char *cd_music_items[] =
1171: {
1172: "disabled",
1173: "enabled",
1174: 0
1175: };
1176: static const char *quality_items[] =
1177: {
1178: "low", "high", 0
1179: };
1180:
1181: static const char *compatibility_items[] =
1182: {
1183: "max compatibility", "max performance", 0
1184: };
1185:
1186: static const char *yesno_names[] =
1187: {
1188: "no",
1189: "yes",
1190: 0
1191: };
1.1.1.2 root 1192:
1.1 root 1193: static const char *crosshair_names[] =
1194: {
1195: "none",
1196: "cross",
1197: "dot",
1198: "angle",
1199: 0
1200: };
1.1.1.2 root 1201:
1.1 root 1202: win_noalttab = Cvar_Get( "win_noalttab", "0", CVAR_ARCHIVE );
1.1.1.2 root 1203:
1.1 root 1204: /*
1205: ** configure controls menu and menu items
1206: */
1207: s_options_menu.x = viddef.width / 2;
1208: s_options_menu.y = viddef.height / 2 - 58;
1209: s_options_menu.nitems = 0;
1210:
1211: s_options_sfxvolume_slider.generic.type = MTYPE_SLIDER;
1212: s_options_sfxvolume_slider.generic.x = 0;
1213: s_options_sfxvolume_slider.generic.y = 0;
1214: s_options_sfxvolume_slider.generic.name = "effects volume";
1215: s_options_sfxvolume_slider.generic.callback = UpdateVolumeFunc;
1216: s_options_sfxvolume_slider.minvalue = 0;
1217: s_options_sfxvolume_slider.maxvalue = 10;
1218: s_options_sfxvolume_slider.curvalue = Cvar_VariableValue( "s_volume" ) * 10;
1219:
1220: s_options_cdvolume_box.generic.type = MTYPE_SPINCONTROL;
1221: s_options_cdvolume_box.generic.x = 0;
1222: s_options_cdvolume_box.generic.y = 10;
1223: s_options_cdvolume_box.generic.name = "CD music";
1224: s_options_cdvolume_box.generic.callback = UpdateCDVolumeFunc;
1225: s_options_cdvolume_box.itemnames = cd_music_items;
1226: s_options_cdvolume_box.curvalue = !Cvar_VariableValue("cd_nocd");
1227:
1228: s_options_quality_list.generic.type = MTYPE_SPINCONTROL;
1229: s_options_quality_list.generic.x = 0;
1230: s_options_quality_list.generic.y = 20;;
1231: s_options_quality_list.generic.name = "sound quality";
1232: s_options_quality_list.generic.callback = UpdateSoundQualityFunc;
1233: s_options_quality_list.itemnames = quality_items;
1234: s_options_quality_list.curvalue = !Cvar_VariableValue( "s_loadas8bit" );
1235:
1236: s_options_compatibility_list.generic.type = MTYPE_SPINCONTROL;
1237: s_options_compatibility_list.generic.x = 0;
1238: s_options_compatibility_list.generic.y = 30;
1239: s_options_compatibility_list.generic.name = "sound compatibility";
1240: s_options_compatibility_list.generic.callback = UpdateSoundQualityFunc;
1241: s_options_compatibility_list.itemnames = compatibility_items;
1242: s_options_compatibility_list.curvalue = Cvar_VariableValue( "s_primary" );
1243:
1244: s_options_sensitivity_slider.generic.type = MTYPE_SLIDER;
1245: s_options_sensitivity_slider.generic.x = 0;
1246: s_options_sensitivity_slider.generic.y = 50;
1247: s_options_sensitivity_slider.generic.name = "mouse speed";
1248: s_options_sensitivity_slider.generic.callback = MouseSpeedFunc;
1249: s_options_sensitivity_slider.minvalue = 2;
1250: s_options_sensitivity_slider.maxvalue = 22;
1.1.1.2 root 1251:
1.1 root 1252: s_options_alwaysrun_box.generic.type = MTYPE_SPINCONTROL;
1253: s_options_alwaysrun_box.generic.x = 0;
1254: s_options_alwaysrun_box.generic.y = 60;
1255: s_options_alwaysrun_box.generic.name = "always run";
1256: s_options_alwaysrun_box.generic.callback = AlwaysRunFunc;
1257: s_options_alwaysrun_box.itemnames = yesno_names;
1.1.1.2 root 1258:
1.1 root 1259: s_options_invertmouse_box.generic.type = MTYPE_SPINCONTROL;
1260: s_options_invertmouse_box.generic.x = 0;
1261: s_options_invertmouse_box.generic.y = 70;
1262: s_options_invertmouse_box.generic.name = "invert mouse";
1263: s_options_invertmouse_box.generic.callback = InvertMouseFunc;
1264: s_options_invertmouse_box.itemnames = yesno_names;
1.1.1.2 root 1265:
1.1 root 1266: s_options_lookspring_box.generic.type = MTYPE_SPINCONTROL;
1267: s_options_lookspring_box.generic.x = 0;
1268: s_options_lookspring_box.generic.y = 80;
1269: s_options_lookspring_box.generic.name = "lookspring";
1270: s_options_lookspring_box.generic.callback = LookspringFunc;
1271: s_options_lookspring_box.itemnames = yesno_names;
1.1.1.2 root 1272:
1.1 root 1273: s_options_lookstrafe_box.generic.type = MTYPE_SPINCONTROL;
1274: s_options_lookstrafe_box.generic.x = 0;
1275: s_options_lookstrafe_box.generic.y = 90;
1276: s_options_lookstrafe_box.generic.name = "lookstrafe";
1277: s_options_lookstrafe_box.generic.callback = LookstrafeFunc;
1278: s_options_lookstrafe_box.itemnames = yesno_names;
1.1.1.2 root 1279:
1.1 root 1280: s_options_freelook_box.generic.type = MTYPE_SPINCONTROL;
1281: s_options_freelook_box.generic.x = 0;
1282: s_options_freelook_box.generic.y = 100;
1283: s_options_freelook_box.generic.name = "free look";
1284: s_options_freelook_box.generic.callback = FreeLookFunc;
1285: s_options_freelook_box.itemnames = yesno_names;
1286:
1287: s_options_crosshair_box.generic.type = MTYPE_SPINCONTROL;
1288: s_options_crosshair_box.generic.x = 0;
1289: s_options_crosshair_box.generic.y = 110;
1290: s_options_crosshair_box.generic.name = "crosshair";
1291: s_options_crosshair_box.generic.callback = CrosshairFunc;
1292: s_options_crosshair_box.itemnames = crosshair_names;
1293: /*
1294: s_options_noalttab_box.generic.type = MTYPE_SPINCONTROL;
1295: s_options_noalttab_box.generic.x = 0;
1296: s_options_noalttab_box.generic.y = 110;
1297: s_options_noalttab_box.generic.name = "disable alt-tab";
1298: s_options_noalttab_box.generic.callback = NoAltTabFunc;
1299: s_options_noalttab_box.itemnames = yesno_names;
1300: */
1301: s_options_joystick_box.generic.type = MTYPE_SPINCONTROL;
1302: s_options_joystick_box.generic.x = 0;
1303: s_options_joystick_box.generic.y = 120;
1304: s_options_joystick_box.generic.name = "use joystick";
1305: s_options_joystick_box.generic.callback = JoystickFunc;
1306: s_options_joystick_box.itemnames = yesno_names;
1307:
1308: s_options_customize_options_action.generic.type = MTYPE_ACTION;
1309: s_options_customize_options_action.generic.x = 0;
1310: s_options_customize_options_action.generic.y = 140;
1311: s_options_customize_options_action.generic.name = "customize controls";
1312: s_options_customize_options_action.generic.callback = CustomizeControlsFunc;
1.1.1.2 root 1313:
1.1 root 1314: s_options_defaults_action.generic.type = MTYPE_ACTION;
1315: s_options_defaults_action.generic.x = 0;
1316: s_options_defaults_action.generic.y = 150;
1317: s_options_defaults_action.generic.name = "reset defaults";
1318: s_options_defaults_action.generic.callback = ControlsResetDefaultsFunc;
1319:
1320: s_options_console_action.generic.type = MTYPE_ACTION;
1321: s_options_console_action.generic.x = 0;
1322: s_options_console_action.generic.y = 160;
1323: s_options_console_action.generic.name = "go to console";
1324: s_options_console_action.generic.callback = ConsoleFunc;
1325:
1326: ControlsSetMenuItemValues();
1327:
1328: Menu_AddItem( &s_options_menu, ( void * ) &s_options_sfxvolume_slider );
1329: Menu_AddItem( &s_options_menu, ( void * ) &s_options_cdvolume_box );
1330: Menu_AddItem( &s_options_menu, ( void * ) &s_options_quality_list );
1331: Menu_AddItem( &s_options_menu, ( void * ) &s_options_compatibility_list );
1332: Menu_AddItem( &s_options_menu, ( void * ) &s_options_sensitivity_slider );
1333: Menu_AddItem( &s_options_menu, ( void * ) &s_options_alwaysrun_box );
1334: Menu_AddItem( &s_options_menu, ( void * ) &s_options_invertmouse_box );
1335: Menu_AddItem( &s_options_menu, ( void * ) &s_options_lookspring_box );
1336: Menu_AddItem( &s_options_menu, ( void * ) &s_options_lookstrafe_box );
1337: Menu_AddItem( &s_options_menu, ( void * ) &s_options_freelook_box );
1338: Menu_AddItem( &s_options_menu, ( void * ) &s_options_crosshair_box );
1339: Menu_AddItem( &s_options_menu, ( void * ) &s_options_joystick_box );
1340: Menu_AddItem( &s_options_menu, ( void * ) &s_options_customize_options_action );
1341: Menu_AddItem( &s_options_menu, ( void * ) &s_options_defaults_action );
1342: Menu_AddItem( &s_options_menu, ( void * ) &s_options_console_action );
1343: }
1.1.1.2 root 1344:
1.1 root 1345: void Options_MenuDraw (void)
1346: {
1347: M_Banner( "m_banner_options" );
1348: Menu_AdjustCursor( &s_options_menu, 1 );
1349: Menu_Draw( &s_options_menu );
1350: }
1.1.1.2 root 1351:
1.1 root 1352: const char *Options_MenuKey( int key )
1353: {
1354: return Default_MenuKey( &s_options_menu, key );
1355: }
1.1.1.2 root 1356:
1.1 root 1357: void M_Menu_Options_f (void)
1358: {
1359: Options_MenuInit();
1360: M_PushMenu ( Options_MenuDraw, Options_MenuKey );
1361: }
1.1.1.2 root 1362:
1.1 root 1363: /*
1364: =======================================================================
1.1.1.2 root 1365:
1.1 root 1366: VIDEO MENU
1.1.1.2 root 1367:
1.1 root 1368: =======================================================================
1369: */
1.1.1.2 root 1370:
1.1 root 1371: void M_Menu_Video_f (void)
1372: {
1373: VID_MenuInit();
1374: M_PushMenu( VID_MenuDraw, VID_MenuKey );
1375: }
1.1.1.2 root 1376:
1.1 root 1377: /*
1378: =============================================================================
1379:
1380: END GAME MENU
1381:
1382: =============================================================================
1383: */
1384: static int credits_start_time;
1.1.1.2 root 1385: static const char **credits;
1386: static char *creditsIndex[256];
1387: static char *creditsBuffer;
1388: static const char *idcredits[] =
1.1 root 1389: {
1390: "+QUAKE II BY ID SOFTWARE",
1391: "",
1392: "+PROGRAMMING",
1393: "John Carmack",
1394: "John Cash",
1395: "Brian Hook",
1396: "",
1397: "+ART",
1398: "Adrian Carmack",
1399: "Kevin Cloud",
1400: "Paul Steed",
1401: "",
1402: "+LEVEL DESIGN",
1403: "Tim Willits",
1404: "American McGee",
1405: "Christian Antkow",
1406: "Paul Jaquays",
1407: "Brandon James",
1408: "",
1409: "+BIZ",
1410: "Todd Hollenshead",
1411: "Barrett (Bear) Alexander",
1412: "Donna Jackson",
1413: "",
1414: "",
1415: "+SPECIAL THANKS",
1416: "Ben Donges for beta testing",
1417: "",
1418: "",
1419: "",
1420: "",
1421: "",
1422: "",
1423: "+ADDITIONAL SUPPORT",
1424: "",
1425: "+LINUX PORT AND CTF",
1426: "Dave \"Zoid\" Kirsch",
1427: "",
1428: "+CINEMATIC SEQUENCES",
1429: "Ending Cinematic by Blur Studio - ",
1430: "Venice, CA",
1431: "",
1432: "Environment models for Introduction",
1433: "Cinematic by Karl Dolgener",
1434: "",
1435: "Assistance with environment design",
1436: "by Cliff Iwai",
1437: "",
1438: "+SOUND EFFECTS AND MUSIC",
1439: "Sound Design by Soundelux Media Labs.",
1440: "Music Composed and Produced by",
1441: "Soundelux Media Labs. Special thanks",
1442: "to Bill Brown, Tom Ozanich, Brian",
1443: "Celano, Jeff Eisner, and The Soundelux",
1444: "Players.",
1445: "",
1446: "\"Level Music\" by Sonic Mayhem",
1447: "www.sonicmayhem.com",
1448: "",
1449: "\"Quake II Theme Song\"",
1450: "(C) 1997 Rob Zombie. All Rights",
1451: "Reserved.",
1452: "",
1453: "Track 10 (\"Climb\") by Jer Sypult",
1454: "",
1455: "Voice of computers by",
1456: "Carly Staehlin-Taylor",
1457: "",
1458: "+THANKS TO ACTIVISION",
1459: "+IN PARTICULAR:",
1460: "",
1461: "John Tam",
1462: "Steve Rosenthal",
1463: "Marty Stratton",
1464: "Henk Hartong",
1465: "",
1466: "Quake II(tm) (C)1997 Id Software, Inc.",
1467: "All Rights Reserved. Distributed by",
1468: "Activision, Inc. under license.",
1469: "Quake II(tm), the Id Software name,",
1470: "the \"Q II\"(tm) logo and id(tm)",
1471: "logo are trademarks of Id Software,",
1472: "Inc. Activision(R) is a registered",
1473: "trademark of Activision, Inc. All",
1474: "other trademarks and trade names are",
1475: "properties of their respective owners.",
1476: 0
1477: };
1478:
1.1.1.2 root 1479: static const char *xatcredits[] =
1480: {
1481: "+QUAKE II MISSION PACK: THE RECKONING",
1482: "+BY",
1483: "+XATRIX ENTERTAINMENT, INC.",
1484: "",
1485: "+DESIGN AND DIRECTION",
1486: "Drew Markham",
1487: "",
1488: "+PRODUCED BY",
1489: "Greg Goodrich",
1490: "",
1491: "+PROGRAMMING",
1492: "Rafael Paiz",
1493: "",
1494: "+LEVEL DESIGN / ADDITIONAL GAME DESIGN",
1495: "Alex Mayberry",
1496: "",
1497: "+LEVEL DESIGN",
1498: "Mal Blackwell",
1499: "Dan Koppel",
1500: "",
1501: "+ART DIRECTION",
1502: "Michael \"Maxx\" Kaufman",
1503: "",
1504: "+COMPUTER GRAPHICS SUPERVISOR AND",
1505: "+CHARACTER ANIMATION DIRECTION",
1506: "Barry Dempsey",
1507: "",
1508: "+SENIOR ANIMATOR AND MODELER",
1509: "Jason Hoover",
1510: "",
1511: "+CHARACTER ANIMATION AND",
1512: "+MOTION CAPTURE SPECIALIST",
1513: "Amit Doron",
1514: "",
1515: "+ART",
1516: "Claire Praderie-Markham",
1517: "Viktor Antonov",
1518: "Corky Lehmkuhl",
1519: "",
1520: "+INTRODUCTION ANIMATION",
1521: "Dominique Drozdz",
1522: "",
1523: "+ADDITIONAL LEVEL DESIGN",
1524: "Aaron Barber",
1525: "Rhett Baldwin",
1526: "",
1527: "+3D CHARACTER ANIMATION TOOLS",
1528: "Gerry Tyra, SA Technology",
1529: "",
1530: "+ADDITIONAL EDITOR TOOL PROGRAMMING",
1531: "Robert Duffy",
1532: "",
1533: "+ADDITIONAL PROGRAMMING",
1534: "Ryan Feltrin",
1535: "",
1536: "+PRODUCTION COORDINATOR",
1537: "Victoria Sylvester",
1538: "",
1539: "+SOUND DESIGN",
1540: "Gary Bradfield",
1541: "",
1542: "+MUSIC BY",
1543: "Sonic Mayhem",
1544: "",
1545: "",
1546: "",
1547: "+SPECIAL THANKS",
1548: "+TO",
1549: "+OUR FRIENDS AT ID SOFTWARE",
1550: "",
1551: "John Carmack",
1552: "John Cash",
1553: "Brian Hook",
1554: "Adrian Carmack",
1555: "Kevin Cloud",
1556: "Paul Steed",
1557: "Tim Willits",
1558: "Christian Antkow",
1559: "Paul Jaquays",
1560: "Brandon James",
1561: "Todd Hollenshead",
1562: "Barrett (Bear) Alexander",
1563: "Dave \"Zoid\" Kirsch",
1564: "Donna Jackson",
1565: "",
1566: "",
1567: "",
1568: "+THANKS TO ACTIVISION",
1569: "+IN PARTICULAR:",
1570: "",
1571: "Marty Stratton",
1572: "Henk \"The Original Ripper\" Hartong",
1573: "Kevin Kraff",
1574: "Jamey Gottlieb",
1575: "Chris Hepburn",
1576: "",
1577: "+AND THE GAME TESTERS",
1578: "",
1579: "Tim Vanlaw",
1580: "Doug Jacobs",
1581: "Steven Rosenthal",
1582: "David Baker",
1583: "Chris Campbell",
1584: "Aaron Casillas",
1585: "Steve Elwell",
1586: "Derek Johnstone",
1587: "Igor Krinitskiy",
1588: "Samantha Lee",
1589: "Michael Spann",
1590: "Chris Toft",
1591: "Juan Valdes",
1592: "",
1593: "+THANKS TO INTERGRAPH COMPUTER SYTEMS",
1594: "+IN PARTICULAR:",
1595: "",
1596: "Michael T. Nicolaou",
1597: "",
1598: "",
1599: "Quake II Mission Pack: The Reckoning",
1600: "(tm) (C)1998 Id Software, Inc. All",
1601: "Rights Reserved. Developed by Xatrix",
1602: "Entertainment, Inc. for Id Software,",
1603: "Inc. Distributed by Activision Inc.",
1604: "under license. Quake(R) is a",
1605: "registered trademark of Id Software,",
1606: "Inc. Quake II Mission Pack: The",
1607: "Reckoning(tm), Quake II(tm), the Id",
1608: "Software name, the \"Q II\"(tm) logo",
1609: "and id(tm) logo are trademarks of Id",
1610: "Software, Inc. Activision(R) is a",
1611: "registered trademark of Activision,",
1612: "Inc. Xatrix(R) is a registered",
1613: "trademark of Xatrix Entertainment,",
1614: "Inc. All other trademarks and trade",
1615: "names are properties of their",
1616: "respective owners.",
1617: 0
1618: };
1619:
1.1.1.3 ! root 1620: static const char *roguecredits[] =
! 1621: {
! 1622: "+QUAKE II MISSION PACK 2: GROUND ZERO",
! 1623: "+BY",
! 1624: "+ROGUE ENTERTAINMENT, INC.",
! 1625: "",
! 1626: "+PRODUCED BY",
! 1627: "Jim Molinets",
! 1628: "",
! 1629: "+PROGRAMMING",
! 1630: "Peter Mack",
! 1631: "Patrick Magruder",
! 1632: "",
! 1633: "+LEVEL DESIGN",
! 1634: "Jim Molinets",
! 1635: "Cameron Lamprecht",
! 1636: "Berenger Fish",
! 1637: "Robert Selitto",
! 1638: "Steve Tietze",
! 1639: "Steve Thoms",
! 1640: "",
! 1641: "+ART DIRECTION",
! 1642: "Rich Fleider",
! 1643: "",
! 1644: "+ART",
! 1645: "Rich Fleider",
! 1646: "Steve Maines",
! 1647: "Won Choi",
! 1648: "",
! 1649: "+ANIMATION SEQUENCES",
! 1650: "Creat Studios",
! 1651: "Steve Maines",
! 1652: "",
! 1653: "+ADDITIONAL LEVEL DESIGN",
! 1654: "Rich Fleider",
! 1655: "Steve Maines",
! 1656: "Peter Mack",
! 1657: "",
! 1658: "+SOUND",
! 1659: "James Grunke",
! 1660: "",
! 1661: "+GROUND ZERO THEME",
! 1662: "+AND",
! 1663: "+MUSIC BY",
! 1664: "Sonic Mayhem",
! 1665: "",
! 1666: "+VWEP MODELS",
! 1667: "Brent \"Hentai\" Dill",
! 1668: "",
! 1669: "",
! 1670: "",
! 1671: "+SPECIAL THANKS",
! 1672: "+TO",
! 1673: "+OUR FRIENDS AT ID SOFTWARE",
! 1674: "",
! 1675: "John Carmack",
! 1676: "John Cash",
! 1677: "Brian Hook",
! 1678: "Adrian Carmack",
! 1679: "Kevin Cloud",
! 1680: "Paul Steed",
! 1681: "Tim Willits",
! 1682: "Christian Antkow",
! 1683: "Paul Jaquays",
! 1684: "Brandon James",
! 1685: "Todd Hollenshead",
! 1686: "Barrett (Bear) Alexander",
! 1687: "Katherine Anna Kang",
! 1688: "Donna Jackson",
! 1689: "Dave \"Zoid\" Kirsch",
! 1690: "",
! 1691: "",
! 1692: "",
! 1693: "+THANKS TO ACTIVISION",
! 1694: "+IN PARTICULAR:",
! 1695: "",
! 1696: "Marty Stratton",
! 1697: "Henk Hartong",
! 1698: "Mitch Lasky",
! 1699: "Steve Rosenthal",
! 1700: "Steve Elwell",
! 1701: "",
! 1702: "+AND THE GAME TESTERS",
! 1703: "",
! 1704: "The Ranger Clan",
! 1705: "Dave \"Zoid\" Kirsch",
! 1706: "Nihilistic Software",
! 1707: "Robert Duffy",
! 1708: "",
! 1709: "And Countless Others",
! 1710: "",
! 1711: "",
! 1712: "",
! 1713: "Quake II Mission Pack 2: Ground Zero",
! 1714: "(tm) (C)1998 Id Software, Inc. All",
! 1715: "Rights Reserved. Developed by Rogue",
! 1716: "Entertainment, Inc. for Id Software,",
! 1717: "Inc. Distributed by Activision Inc.",
! 1718: "under license. Quake(R) is a",
! 1719: "registered trademark of Id Software,",
! 1720: "Inc. Quake II Mission Pack 2: Ground",
! 1721: "Zero(tm), Quake II(tm), the Id",
! 1722: "Software name, the \"Q II\"(tm) logo",
! 1723: "and id(tm) logo are trademarks of Id",
! 1724: "Software, Inc. Activision(R) is a",
! 1725: "registered trademark of Activision,",
! 1726: "Inc. Rogue(R) is a registered",
! 1727: "trademark of Rogue Entertainment,",
! 1728: "Inc. All other trademarks and trade",
! 1729: "names are properties of their",
! 1730: "respective owners.",
! 1731: 0
! 1732: };
! 1733:
! 1734:
1.1 root 1735: void M_Credits_MenuDraw( void )
1736: {
1737: int i, y;
1738:
1739: /*
1740: ** draw the credits
1741: */
1742: for ( i = 0, y = viddef.height - ( ( cls.realtime - credits_start_time ) / 40.0F ); credits[i] && y < viddef.height; y += 10, i++ )
1743: {
1744: int j, stringoffset = 0;
1745: int bold = false;
1746:
1747: if ( y <= -8 )
1748: continue;
1749:
1750: if ( credits[i][0] == '+' )
1751: {
1752: bold = true;
1753: stringoffset = 1;
1754: }
1755: else
1756: {
1757: bold = false;
1758: stringoffset = 0;
1759: }
1760:
1761: for ( j = 0; credits[i][j+stringoffset]; j++ )
1762: {
1763: int x;
1764:
1765: x = ( viddef.width - strlen( credits[i] ) * 8 - stringoffset * 8 ) / 2 + ( j + stringoffset ) * 8;
1766:
1767: if ( bold )
1768: re.DrawChar( x, y, credits[i][j+stringoffset] + 128 );
1769: else
1770: re.DrawChar( x, y, credits[i][j+stringoffset] );
1771: }
1772: }
1773:
1774: if ( y < 0 )
1775: credits_start_time = cls.realtime;
1776: }
1777:
1778: const char *M_Credits_Key( int key )
1779: {
1780: switch (key)
1781: {
1782: case K_ESCAPE:
1.1.1.2 root 1783: if (creditsBuffer)
1784: FS_FreeFile (creditsBuffer);
1.1 root 1785: M_PopMenu ();
1786: break;
1787: }
1788:
1789: return menu_out_sound;
1790:
1791: }
1792:
1.1.1.2 root 1793: extern int Developer_searchpath (int who);
1794:
1.1 root 1795: void M_Menu_Credits_f( void )
1796: {
1.1.1.2 root 1797: int n;
1798: int count;
1799: char *p;
1800: int isdeveloper = 0;
1801:
1802: creditsBuffer = NULL;
1803: count = FS_LoadFile ("credits", &creditsBuffer);
1804: if (count != -1)
1805: {
1806: p = creditsBuffer;
1807: for (n = 0; n < 255; n++)
1808: {
1809: creditsIndex[n] = p;
1810: while (*p != '\r' && *p != '\n')
1811: {
1812: p++;
1813: if (--count == 0)
1814: break;
1815: }
1816: if (*p == '\r')
1817: {
1818: *p++ = 0;
1819: if (--count == 0)
1820: break;
1821: }
1822: *p++ = 0;
1823: if (--count == 0)
1824: break;
1825: }
1826: creditsIndex[++n] = 0;
1827: credits = creditsIndex;
1828: }
1829: else
1830: {
1831: isdeveloper = Developer_searchpath (1);
1832:
1.1.1.3 ! root 1833: if (isdeveloper == 1) // xatrix
1.1.1.2 root 1834: credits = xatcredits;
1.1.1.3 ! root 1835: else if (isdeveloper == 2) // ROGUE
! 1836: credits = roguecredits;
1.1.1.2 root 1837: else
1838: {
1839: credits = idcredits;
1840: }
1841:
1842: }
1843:
1.1 root 1844: credits_start_time = cls.realtime;
1845: M_PushMenu( M_Credits_MenuDraw, M_Credits_Key);
1846: }
1.1.1.2 root 1847:
1.1 root 1848: /*
1849: =============================================================================
1850:
1851: GAME MENU
1852:
1853: =============================================================================
1854: */
1.1.1.2 root 1855:
1.1 root 1856: static int m_game_cursor;
1.1.1.2 root 1857:
1.1 root 1858: static menuframework_s s_game_menu;
1859: static menuaction_s s_easy_game_action;
1860: static menuaction_s s_medium_game_action;
1861: static menuaction_s s_hard_game_action;
1862: static menuaction_s s_load_game_action;
1863: static menuaction_s s_save_game_action;
1864: static menuaction_s s_credits_action;
1865: static menuseparator_s s_blankline;
1.1.1.2 root 1866:
1.1 root 1867: static void StartGame( void )
1868: {
1869: // disable updates and start the cinematic going
1870: cl.servercount = -1;
1871: M_ForceMenuOff ();
1872: Cvar_SetValue( "deathmatch", 0 );
1873: Cvar_SetValue( "coop", 0 );
1.1.1.3 ! root 1874:
! 1875: Cvar_SetValue( "gamerules", 0 ); //PGM
! 1876:
1.1 root 1877: Cbuf_AddText ("loading ; killserver ; wait ; newgame\n");
1878: cls.key_dest = key_game;
1879: }
1.1.1.2 root 1880:
1.1 root 1881: static void EasyGameFunc( void *data )
1882: {
1883: Cvar_ForceSet( "skill", "0" );
1884: StartGame();
1885: }
1.1.1.2 root 1886:
1.1 root 1887: static void MediumGameFunc( void *data )
1888: {
1889: Cvar_ForceSet( "skill", "1" );
1890: StartGame();
1891: }
1.1.1.2 root 1892:
1.1 root 1893: static void HardGameFunc( void *data )
1894: {
1895: Cvar_ForceSet( "skill", "2" );
1896: StartGame();
1897: }
1.1.1.2 root 1898:
1.1 root 1899: static void LoadGameFunc( void *unused )
1900: {
1901: M_Menu_LoadGame_f ();
1902: }
1.1.1.2 root 1903:
1.1 root 1904: static void SaveGameFunc( void *unused )
1905: {
1906: M_Menu_SaveGame_f();
1907: }
1.1.1.2 root 1908:
1.1 root 1909: static void CreditsFunc( void *unused )
1910: {
1911: M_Menu_Credits_f();
1912: }
1.1.1.2 root 1913:
1.1 root 1914: void Game_MenuInit( void )
1915: {
1916: static const char *difficulty_names[] =
1917: {
1918: "easy",
1919: "medium",
1920: "hard",
1921: 0
1922: };
1.1.1.2 root 1923:
1.1 root 1924: s_game_menu.x = viddef.width * 0.50;
1925: s_game_menu.nitems = 0;
1.1.1.2 root 1926:
1.1 root 1927: s_easy_game_action.generic.type = MTYPE_ACTION;
1928: s_easy_game_action.generic.flags = QMF_LEFT_JUSTIFY;
1929: s_easy_game_action.generic.x = 0;
1930: s_easy_game_action.generic.y = 0;
1931: s_easy_game_action.generic.name = "easy";
1932: s_easy_game_action.generic.callback = EasyGameFunc;
1.1.1.2 root 1933:
1.1 root 1934: s_medium_game_action.generic.type = MTYPE_ACTION;
1935: s_medium_game_action.generic.flags = QMF_LEFT_JUSTIFY;
1936: s_medium_game_action.generic.x = 0;
1937: s_medium_game_action.generic.y = 10;
1938: s_medium_game_action.generic.name = "medium";
1939: s_medium_game_action.generic.callback = MediumGameFunc;
1.1.1.2 root 1940:
1.1 root 1941: s_hard_game_action.generic.type = MTYPE_ACTION;
1942: s_hard_game_action.generic.flags = QMF_LEFT_JUSTIFY;
1943: s_hard_game_action.generic.x = 0;
1944: s_hard_game_action.generic.y = 20;
1945: s_hard_game_action.generic.name = "hard";
1946: s_hard_game_action.generic.callback = HardGameFunc;
1.1.1.2 root 1947:
1.1 root 1948: s_blankline.generic.type = MTYPE_SEPARATOR;
1949:
1950: s_load_game_action.generic.type = MTYPE_ACTION;
1951: s_load_game_action.generic.flags = QMF_LEFT_JUSTIFY;
1952: s_load_game_action.generic.x = 0;
1953: s_load_game_action.generic.y = 40;
1954: s_load_game_action.generic.name = "load game";
1955: s_load_game_action.generic.callback = LoadGameFunc;
1.1.1.2 root 1956:
1.1 root 1957: s_save_game_action.generic.type = MTYPE_ACTION;
1958: s_save_game_action.generic.flags = QMF_LEFT_JUSTIFY;
1959: s_save_game_action.generic.x = 0;
1960: s_save_game_action.generic.y = 50;
1961: s_save_game_action.generic.name = "save game";
1962: s_save_game_action.generic.callback = SaveGameFunc;
1963:
1964: s_credits_action.generic.type = MTYPE_ACTION;
1965: s_credits_action.generic.flags = QMF_LEFT_JUSTIFY;
1966: s_credits_action.generic.x = 0;
1967: s_credits_action.generic.y = 60;
1968: s_credits_action.generic.name = "credits";
1969: s_credits_action.generic.callback = CreditsFunc;
1.1.1.2 root 1970:
1.1 root 1971: Menu_AddItem( &s_game_menu, ( void * ) &s_easy_game_action );
1972: Menu_AddItem( &s_game_menu, ( void * ) &s_medium_game_action );
1973: Menu_AddItem( &s_game_menu, ( void * ) &s_hard_game_action );
1974: Menu_AddItem( &s_game_menu, ( void * ) &s_blankline );
1975: Menu_AddItem( &s_game_menu, ( void * ) &s_load_game_action );
1976: Menu_AddItem( &s_game_menu, ( void * ) &s_save_game_action );
1977: Menu_AddItem( &s_game_menu, ( void * ) &s_blankline );
1978: Menu_AddItem( &s_game_menu, ( void * ) &s_credits_action );
1.1.1.2 root 1979:
1.1 root 1980: Menu_Center( &s_game_menu );
1981: }
1.1.1.2 root 1982:
1.1 root 1983: void Game_MenuDraw( void )
1984: {
1985: M_Banner( "m_banner_game" );
1986: Menu_AdjustCursor( &s_game_menu, 1 );
1987: Menu_Draw( &s_game_menu );
1988: }
1.1.1.2 root 1989:
1.1 root 1990: const char *Game_MenuKey( int key )
1991: {
1992: return Default_MenuKey( &s_game_menu, key );
1993: }
1.1.1.2 root 1994:
1.1 root 1995: void M_Menu_Game_f (void)
1996: {
1997: Game_MenuInit();
1998: M_PushMenu( Game_MenuDraw, Game_MenuKey );
1999: m_game_cursor = 1;
2000: }
1.1.1.2 root 2001:
1.1 root 2002: /*
2003: =============================================================================
1.1.1.2 root 2004:
1.1 root 2005: LOADGAME MENU
1.1.1.2 root 2006:
1.1 root 2007: =============================================================================
2008: */
1.1.1.2 root 2009:
1.1 root 2010: #define MAX_SAVEGAMES 15
1.1.1.2 root 2011:
1.1 root 2012: static menuframework_s s_savegame_menu;
1.1.1.2 root 2013:
1.1 root 2014: static menuframework_s s_loadgame_menu;
2015: static menuaction_s s_loadgame_actions[MAX_SAVEGAMES];
1.1.1.2 root 2016:
1.1 root 2017: char m_savestrings[MAX_SAVEGAMES][32];
2018: qboolean m_savevalid[MAX_SAVEGAMES];
1.1.1.2 root 2019:
1.1 root 2020: void Create_Savestrings (void)
2021: {
2022: int i;
2023: FILE *f;
2024: char name[MAX_OSPATH];
1.1.1.2 root 2025:
1.1 root 2026: for (i=0 ; i<MAX_SAVEGAMES ; i++)
2027: {
2028: Com_sprintf (name, sizeof(name), "%s/save/save%i/server.ssv", FS_Gamedir(), i);
2029: f = fopen (name, "rb");
2030: if (!f)
2031: {
2032: strcpy (m_savestrings[i], "<EMPTY>");
2033: m_savevalid[i] = false;
2034: }
2035: else
2036: {
2037: FS_Read (m_savestrings[i], sizeof(m_savestrings[i]), f);
2038: fclose (f);
2039: m_savevalid[i] = true;
2040: }
2041: }
2042: }
1.1.1.2 root 2043:
1.1 root 2044: void LoadGameCallback( void *self )
2045: {
2046: menuaction_s *a = ( menuaction_s * ) self;
1.1.1.2 root 2047:
1.1 root 2048: if ( m_savevalid[ a->generic.localdata[0] ] )
2049: Cbuf_AddText (va("load save%i\n", a->generic.localdata[0] ) );
2050: M_ForceMenuOff ();
2051: }
1.1.1.2 root 2052:
1.1 root 2053: void LoadGame_MenuInit( void )
2054: {
2055: int i;
1.1.1.2 root 2056:
1.1 root 2057: s_loadgame_menu.x = viddef.width / 2 - 120;
2058: s_loadgame_menu.y = viddef.height / 2 - 58;
2059: s_loadgame_menu.nitems = 0;
1.1.1.2 root 2060:
1.1 root 2061: Create_Savestrings();
1.1.1.2 root 2062:
1.1 root 2063: for ( i = 0; i < MAX_SAVEGAMES; i++ )
2064: {
2065: s_loadgame_actions[i].generic.name = m_savestrings[i];
2066: s_loadgame_actions[i].generic.flags = QMF_LEFT_JUSTIFY;
2067: s_loadgame_actions[i].generic.localdata[0] = i;
2068: s_loadgame_actions[i].generic.callback = LoadGameCallback;
1.1.1.2 root 2069:
1.1 root 2070: s_loadgame_actions[i].generic.x = 0;
2071: s_loadgame_actions[i].generic.y = ( i ) * 10;
2072: if (i>0) // separate from autosave
2073: s_loadgame_actions[i].generic.y += 10;
1.1.1.2 root 2074:
1.1 root 2075: s_loadgame_actions[i].generic.type = MTYPE_ACTION;
1.1.1.2 root 2076:
1.1 root 2077: Menu_AddItem( &s_loadgame_menu, &s_loadgame_actions[i] );
2078: }
2079: }
1.1.1.2 root 2080:
1.1 root 2081: void LoadGame_MenuDraw( void )
2082: {
2083: M_Banner( "m_banner_load_game" );
2084: // Menu_AdjustCursor( &s_loadgame_menu, 1 );
2085: Menu_Draw( &s_loadgame_menu );
2086: }
1.1.1.2 root 2087:
1.1 root 2088: const char *LoadGame_MenuKey( int key )
2089: {
2090: if ( key == K_ESCAPE || key == K_ENTER )
2091: {
2092: s_savegame_menu.cursor = s_loadgame_menu.cursor - 1;
2093: if ( s_savegame_menu.cursor < 0 )
2094: s_savegame_menu.cursor = 0;
2095: }
2096: return Default_MenuKey( &s_loadgame_menu, key );
2097: }
1.1.1.2 root 2098:
1.1 root 2099: void M_Menu_LoadGame_f (void)
2100: {
2101: LoadGame_MenuInit();
2102: M_PushMenu( LoadGame_MenuDraw, LoadGame_MenuKey );
2103: }
1.1.1.2 root 2104:
2105:
1.1 root 2106: /*
2107: =============================================================================
1.1.1.2 root 2108:
1.1 root 2109: SAVEGAME MENU
1.1.1.2 root 2110:
1.1 root 2111: =============================================================================
2112: */
2113: static menuframework_s s_savegame_menu;
2114: static menuaction_s s_savegame_actions[MAX_SAVEGAMES];
1.1.1.2 root 2115:
1.1 root 2116: void SaveGameCallback( void *self )
2117: {
2118: menuaction_s *a = ( menuaction_s * ) self;
1.1.1.2 root 2119:
1.1 root 2120: Cbuf_AddText (va("save save%i\n", a->generic.localdata[0] ));
2121: M_ForceMenuOff ();
2122: }
1.1.1.2 root 2123:
1.1 root 2124: void SaveGame_MenuDraw( void )
2125: {
2126: M_Banner( "m_banner_save_game" );
2127: Menu_AdjustCursor( &s_savegame_menu, 1 );
2128: Menu_Draw( &s_savegame_menu );
2129: }
1.1.1.2 root 2130:
1.1 root 2131: void SaveGame_MenuInit( void )
2132: {
2133: int i;
1.1.1.2 root 2134:
1.1 root 2135: s_savegame_menu.x = viddef.width / 2 - 120;
2136: s_savegame_menu.y = viddef.height / 2 - 58;
2137: s_savegame_menu.nitems = 0;
1.1.1.2 root 2138:
1.1 root 2139: Create_Savestrings();
1.1.1.2 root 2140:
1.1 root 2141: // don't include the autosave slot
2142: for ( i = 0; i < MAX_SAVEGAMES-1; i++ )
2143: {
2144: s_savegame_actions[i].generic.name = m_savestrings[i+1];
2145: s_savegame_actions[i].generic.localdata[0] = i+1;
2146: s_savegame_actions[i].generic.flags = QMF_LEFT_JUSTIFY;
2147: s_savegame_actions[i].generic.callback = SaveGameCallback;
1.1.1.2 root 2148:
1.1 root 2149: s_savegame_actions[i].generic.x = 0;
2150: s_savegame_actions[i].generic.y = ( i ) * 10;
1.1.1.2 root 2151:
1.1 root 2152: s_savegame_actions[i].generic.type = MTYPE_ACTION;
1.1.1.2 root 2153:
1.1 root 2154: Menu_AddItem( &s_savegame_menu, &s_savegame_actions[i] );
2155: }
2156: }
1.1.1.2 root 2157:
1.1 root 2158: const char *SaveGame_MenuKey( int key )
2159: {
2160: if ( key == K_ENTER || key == K_ESCAPE )
2161: {
2162: s_loadgame_menu.cursor = s_savegame_menu.cursor - 1;
2163: if ( s_loadgame_menu.cursor < 0 )
2164: s_loadgame_menu.cursor = 0;
2165: }
2166: return Default_MenuKey( &s_savegame_menu, key );
2167: }
1.1.1.2 root 2168:
1.1 root 2169: void M_Menu_SaveGame_f (void)
2170: {
2171: if (!Com_ServerState())
2172: return; // not playing a game
1.1.1.2 root 2173:
1.1 root 2174: SaveGame_MenuInit();
2175: M_PushMenu( SaveGame_MenuDraw, SaveGame_MenuKey );
2176: Create_Savestrings ();
2177: }
1.1.1.2 root 2178:
2179:
1.1 root 2180: /*
2181: =============================================================================
1.1.1.2 root 2182:
1.1 root 2183: JOIN SERVER MENU
1.1.1.2 root 2184:
1.1 root 2185: =============================================================================
2186: */
2187: #define MAX_LOCAL_SERVERS 8
1.1.1.2 root 2188:
1.1 root 2189: static menuframework_s s_joinserver_menu;
2190: static menuseparator_s s_joinserver_server_title;
2191: static menuaction_s s_joinserver_search_action;
2192: static menuaction_s s_joinserver_address_book_action;
2193: static menuaction_s s_joinserver_server_actions[MAX_LOCAL_SERVERS];
2194:
2195: int m_num_servers;
2196: #define NO_SERVER_STRING "<no server>"
2197:
2198: // user readable information
2199: static char local_server_names[MAX_LOCAL_SERVERS][80];
2200:
2201: // network address
2202: static netadr_t local_server_netadr[MAX_LOCAL_SERVERS];
2203:
2204: void M_AddToServerList (netadr_t adr, char *info)
2205: {
2206: int i;
2207:
2208: if (m_num_servers == MAX_LOCAL_SERVERS)
2209: return;
2210: while ( *info == ' ' )
2211: info++;
2212:
2213: // ignore if duplicated
2214: for (i=0 ; i<m_num_servers ; i++)
2215: if (!strcmp(info, local_server_names[i]))
2216: return;
2217:
2218: local_server_netadr[m_num_servers] = adr;
2219: strncpy (local_server_names[m_num_servers], info, sizeof(local_server_names[0])-1);
2220: m_num_servers++;
2221: }
2222:
1.1.1.2 root 2223:
1.1 root 2224: void JoinServerFunc( void *self )
2225: {
2226: char buffer[128];
2227: int index;
2228:
2229: index = ( menuaction_s * ) self - s_joinserver_server_actions;
2230:
2231: if ( Q_stricmp( local_server_names[index], NO_SERVER_STRING ) == 0 )
2232: return;
2233:
2234: if (index >= m_num_servers)
2235: return;
2236:
2237: Com_sprintf (buffer, sizeof(buffer), "connect %s\n", NET_AdrToString (local_server_netadr[index]));
2238: Cbuf_AddText (buffer);
2239: M_ForceMenuOff ();
2240: }
1.1.1.2 root 2241:
1.1 root 2242: void AddressBookFunc( void *self )
2243: {
2244: M_Menu_AddressBook_f();
2245: }
1.1.1.2 root 2246:
1.1 root 2247: void NullCursorDraw( void *self )
2248: {
2249: }
2250:
2251: void SearchLocalGames( void )
2252: {
2253: int i;
2254:
2255: m_num_servers = 0;
2256: for (i=0 ; i<MAX_LOCAL_SERVERS ; i++)
2257: strcpy (local_server_names[i], NO_SERVER_STRING);
2258:
2259: M_DrawTextBox( 8, 120 - 48, 36, 3 );
2260: M_Print( 16 + 16, 120 - 48 + 8, "Searching for local servers, this" );
2261: M_Print( 16 + 16, 120 - 48 + 16, "could take up to a minute, so" );
2262: M_Print( 16 + 16, 120 - 48 + 24, "please be patient." );
2263:
2264: // the text box won't show up unless we do a buffer swap
2265: re.EndFrame();
2266:
2267: // send out info packets
2268: CL_PingServers_f();
2269: }
1.1.1.2 root 2270:
1.1 root 2271: void SearchLocalGamesFunc( void *self )
2272: {
2273: SearchLocalGames();
2274: }
1.1.1.2 root 2275:
1.1 root 2276: void JoinServer_MenuInit( void )
2277: {
2278: int i;
1.1.1.2 root 2279:
1.1 root 2280: s_joinserver_menu.x = viddef.width * 0.50 - 120;
2281: s_joinserver_menu.nitems = 0;
1.1.1.2 root 2282:
1.1 root 2283: s_joinserver_address_book_action.generic.type = MTYPE_ACTION;
2284: s_joinserver_address_book_action.generic.name = "address book";
2285: s_joinserver_address_book_action.generic.flags = QMF_LEFT_JUSTIFY;
2286: s_joinserver_address_book_action.generic.x = 0;
2287: s_joinserver_address_book_action.generic.y = 0;
2288: s_joinserver_address_book_action.generic.callback = AddressBookFunc;
1.1.1.2 root 2289:
1.1 root 2290: s_joinserver_search_action.generic.type = MTYPE_ACTION;
2291: s_joinserver_search_action.generic.name = "refresh server list";
2292: s_joinserver_search_action.generic.flags = QMF_LEFT_JUSTIFY;
2293: s_joinserver_search_action.generic.x = 0;
2294: s_joinserver_search_action.generic.y = 10;
2295: s_joinserver_search_action.generic.callback = SearchLocalGamesFunc;
2296: s_joinserver_search_action.generic.statusbar = "search for servers";
1.1.1.2 root 2297:
1.1 root 2298: s_joinserver_server_title.generic.type = MTYPE_SEPARATOR;
2299: s_joinserver_server_title.generic.name = "connect to...";
2300: s_joinserver_server_title.generic.x = 80;
2301: s_joinserver_server_title.generic.y = 30;
1.1.1.2 root 2302:
1.1 root 2303: for ( i = 0; i < MAX_LOCAL_SERVERS; i++ )
2304: {
2305: s_joinserver_server_actions[i].generic.type = MTYPE_ACTION;
2306: strcpy (local_server_names[i], NO_SERVER_STRING);
2307: s_joinserver_server_actions[i].generic.name = local_server_names[i];
2308: s_joinserver_server_actions[i].generic.flags = QMF_LEFT_JUSTIFY;
2309: s_joinserver_server_actions[i].generic.x = 0;
2310: s_joinserver_server_actions[i].generic.y = 40 + i*10;
2311: s_joinserver_server_actions[i].generic.callback = JoinServerFunc;
2312: s_joinserver_server_actions[i].generic.statusbar = "press ENTER to connect";
2313: }
1.1.1.2 root 2314:
1.1 root 2315: Menu_AddItem( &s_joinserver_menu, &s_joinserver_address_book_action );
2316: Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_title );
2317: Menu_AddItem( &s_joinserver_menu, &s_joinserver_search_action );
1.1.1.2 root 2318:
1.1 root 2319: for ( i = 0; i < 8; i++ )
2320: Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_actions[i] );
1.1.1.2 root 2321:
1.1 root 2322: Menu_Center( &s_joinserver_menu );
2323:
2324: SearchLocalGames();
2325: }
1.1.1.2 root 2326:
1.1 root 2327: void JoinServer_MenuDraw(void)
2328: {
2329: M_Banner( "m_banner_join_server" );
2330: Menu_Draw( &s_joinserver_menu );
2331: }
1.1.1.2 root 2332:
2333:
1.1 root 2334: const char *JoinServer_MenuKey( int key )
2335: {
2336: return Default_MenuKey( &s_joinserver_menu, key );
2337: }
1.1.1.2 root 2338:
1.1 root 2339: void M_Menu_JoinServer_f (void)
2340: {
2341: JoinServer_MenuInit();
2342: M_PushMenu( JoinServer_MenuDraw, JoinServer_MenuKey );
2343: }
2344:
1.1.1.2 root 2345:
1.1 root 2346: /*
2347: =============================================================================
1.1.1.2 root 2348:
1.1 root 2349: START SERVER MENU
1.1.1.2 root 2350:
1.1 root 2351: =============================================================================
2352: */
2353: static menuframework_s s_startserver_menu;
2354: static char **mapnames;
2355: static int nummaps;
1.1.1.2 root 2356:
1.1 root 2357: static menuaction_s s_startserver_start_action;
2358: static menuaction_s s_startserver_dmoptions_action;
2359: static menufield_s s_timelimit_field;
2360: static menufield_s s_fraglimit_field;
2361: static menufield_s s_maxclients_field;
2362: static menufield_s s_hostname_field;
2363: static menulist_s s_startmap_list;
2364: static menulist_s s_rules_box;
2365:
2366: void DMOptionsFunc( void *self )
2367: {
2368: if (s_rules_box.curvalue == 1)
2369: return;
2370: M_Menu_DMOptions_f();
2371: }
2372:
2373: void RulesChangeFunc ( void *self )
2374: {
2375: // DM
2376: if (s_rules_box.curvalue == 0)
2377: {
2378: s_maxclients_field.generic.statusbar = NULL;
2379: s_startserver_dmoptions_action.generic.statusbar = NULL;
2380: }
1.1.1.3 ! root 2381: else if(s_rules_box.curvalue == 1) // coop // PGM
1.1 root 2382: {
2383: s_maxclients_field.generic.statusbar = "4 maximum for cooperative";
2384: if (atoi(s_maxclients_field.buffer) > 4)
2385: strcpy( s_maxclients_field.buffer, "4" );
2386: s_startserver_dmoptions_action.generic.statusbar = "N/A for cooperative";
2387: }
1.1.1.3 ! root 2388: //=====
! 2389: //PGM
! 2390: // ROGUE GAMES
! 2391: else if(Developer_searchpath(2) == 2)
! 2392: {
! 2393: if (s_rules_box.curvalue == 2) // tag
! 2394: {
! 2395: s_maxclients_field.generic.statusbar = NULL;
! 2396: s_startserver_dmoptions_action.generic.statusbar = NULL;
! 2397: }
! 2398: /*
! 2399: else if(s_rules_box.curvalue == 3) // deathball
! 2400: {
! 2401: s_maxclients_field.generic.statusbar = NULL;
! 2402: s_startserver_dmoptions_action.generic.statusbar = NULL;
! 2403: }
! 2404: */
! 2405: }
! 2406: //PGM
! 2407: //=====
1.1 root 2408: }
1.1.1.2 root 2409:
1.1 root 2410: void StartServerActionFunc( void *self )
2411: {
2412: char startmap[1024];
2413: int timelimit;
2414: int fraglimit;
2415: int maxclients;
2416: char *spot;
1.1.1.2 root 2417:
1.1 root 2418: strcpy( startmap, strchr( mapnames[s_startmap_list.curvalue], '\n' ) + 1 );
2419:
2420: maxclients = atoi( s_maxclients_field.buffer );
2421: timelimit = atoi( s_timelimit_field.buffer );
2422: fraglimit = atoi( s_fraglimit_field.buffer );
2423:
2424: Cvar_SetValue( "maxclients", ClampCvar( 0, maxclients, maxclients ) );
2425: Cvar_SetValue ("timelimit", ClampCvar( 0, timelimit, timelimit ) );
2426: Cvar_SetValue ("fraglimit", ClampCvar( 0, fraglimit, fraglimit ) );
2427: Cvar_Set("hostname", s_hostname_field.buffer );
1.1.1.3 ! root 2428: // Cvar_SetValue ("deathmatch", !s_rules_box.curvalue );
! 2429: // Cvar_SetValue ("coop", s_rules_box.curvalue );
! 2430:
! 2431: //PGM
! 2432: if((s_rules_box.curvalue < 2) || (Developer_searchpath(2) != 2))
! 2433: {
! 2434: Cvar_SetValue ("deathmatch", !s_rules_box.curvalue );
! 2435: Cvar_SetValue ("coop", s_rules_box.curvalue );
! 2436: Cvar_SetValue ("gamerules", 0 );
! 2437: }
! 2438: else
! 2439: {
! 2440: Cvar_SetValue ("deathmatch", 1 ); // deathmatch is always true for rogue games, right?
! 2441: Cvar_SetValue ("coop", 0 ); // FIXME - this might need to depend on which game we're running
! 2442: Cvar_SetValue ("gamerules", s_rules_box.curvalue );
! 2443: }
! 2444: //PGM
1.1 root 2445:
2446: spot = NULL;
1.1.1.3 ! root 2447: if (s_rules_box.curvalue == 1) // PGM
1.1 root 2448: {
1.1.1.2 root 2449: if(Q_stricmp(startmap, "bunk1") == 0)
2450: spot = "start";
2451: else if(Q_stricmp(startmap, "mintro") == 0)
2452: spot = "start";
2453: else if(Q_stricmp(startmap, "fact1") == 0)
2454: spot = "start";
2455: else if(Q_stricmp(startmap, "power1") == 0)
2456: spot = "pstart";
2457: else if(Q_stricmp(startmap, "biggun") == 0)
2458: spot = "bstart";
2459: else if(Q_stricmp(startmap, "hangar1") == 0)
2460: spot = "unitstart";
2461: else if(Q_stricmp(startmap, "city1") == 0)
2462: spot = "unitstart";
2463: else if(Q_stricmp(startmap, "boss1") == 0)
1.1.1.3 ! root 2464: spot = "bosstart";
1.1 root 2465: }
2466:
2467: if (spot)
2468: {
2469: if (Com_ServerState())
2470: Cbuf_AddText ("disconnect\n");
2471: Cbuf_AddText (va("gamemap \"*%s$%s\"\n", startmap, spot));
2472: }
2473: else
2474: {
2475: Cbuf_AddText (va("map %s\n", startmap));
2476: }
2477:
2478: M_ForceMenuOff ();
2479: }
2480:
2481: void StartServer_MenuInit( void )
2482: {
2483: static const char *dm_coop_names[] =
2484: {
2485: "deathmatch",
2486: "cooperative",
2487: 0
2488: };
1.1.1.3 ! root 2489: //=======
! 2490: //PGM
! 2491: static const char *dm_coop_names_rogue[] =
! 2492: {
! 2493: "deathmatch",
! 2494: "cooperative",
! 2495: "tag",
! 2496: // "deathball",
! 2497: 0
! 2498: };
! 2499: //PGM
! 2500: //=======
1.1 root 2501: char *buffer;
2502: char mapsname[1024];
2503: char *s;
2504: int length;
2505: int i;
2506: FILE *fp;
2507:
2508: /*
2509: ** load the list of map names
2510: */
2511: Com_sprintf( mapsname, sizeof( mapsname ), "%s/maps.lst", FS_Gamedir() );
2512: if ( ( fp = fopen( mapsname, "rb" ) ) == 0 )
2513: {
2514: if ( ( length = FS_LoadFile( "maps.lst", ( void ** ) &buffer ) ) == -1 )
2515: Com_Error( ERR_DROP, "couldn't find maps.lst\n" );
2516: }
2517: else
2518: {
1.1.1.2 root 2519: #ifdef _WIN32
1.1 root 2520: length = filelength( fileno( fp ) );
1.1.1.2 root 2521: #else
2522: fseek(fp, 0, SEEK_END);
2523: length = ftell(fp);
2524: fseek(fp, 0, SEEK_SET);
2525: #endif
1.1 root 2526: buffer = malloc( length );
2527: fread( buffer, length, 1, fp );
2528: }
2529:
2530: s = buffer;
2531:
2532: i = 0;
2533: while ( i < length )
2534: {
2535: if ( s[i] == '\r' )
2536: nummaps++;
2537: i++;
2538: }
2539:
2540: if ( nummaps == 0 )
2541: Com_Error( ERR_DROP, "no maps in maps.lst\n" );
2542:
2543: mapnames = malloc( sizeof( char * ) * ( nummaps + 1 ) );
2544: memset( mapnames, 0, sizeof( char * ) * ( nummaps + 1 ) );
2545:
2546: s = buffer;
2547:
2548: for ( i = 0; i < nummaps; i++ )
2549: {
2550: char shortname[MAX_TOKEN_CHARS];
2551: char longname[MAX_TOKEN_CHARS];
2552: char scratch[200];
2553: int j, l;
2554:
2555: strcpy( shortname, COM_Parse( &s ) );
2556: l = strlen(shortname);
2557: for (j=0 ; j<l ; j++)
2558: shortname[j] = toupper(shortname[j]);
2559: strcpy( longname, COM_Parse( &s ) );
2560: Com_sprintf( scratch, sizeof( scratch ), "%s\n%s", longname, shortname );
2561:
2562: mapnames[i] = malloc( strlen( scratch ) + 1 );
2563: strcpy( mapnames[i], scratch );
2564: }
2565: mapnames[nummaps] = 0;
2566:
2567: if ( fp != 0 )
2568: {
2569: fp = 0;
2570: free( buffer );
2571: }
2572: else
2573: {
2574: FS_FreeFile( buffer );
2575: }
2576:
2577: /*
2578: ** initialize the menu stuff
2579: */
2580: s_startserver_menu.x = viddef.width * 0.50;
2581: s_startserver_menu.nitems = 0;
1.1.1.2 root 2582:
1.1 root 2583: s_startmap_list.generic.type = MTYPE_SPINCONTROL;
2584: s_startmap_list.generic.x = 0;
2585: s_startmap_list.generic.y = 0;
2586: s_startmap_list.generic.name = "initial map";
2587: s_startmap_list.itemnames = mapnames;
1.1.1.2 root 2588:
1.1 root 2589: s_rules_box.generic.type = MTYPE_SPINCONTROL;
2590: s_rules_box.generic.x = 0;
2591: s_rules_box.generic.y = 20;
2592: s_rules_box.generic.name = "rules";
1.1.1.3 ! root 2593:
! 2594: //PGM - rogue games only available with rogue DLL.
! 2595: if(Developer_searchpath(2) == 2)
! 2596: s_rules_box.itemnames = dm_coop_names_rogue;
! 2597: else
! 2598: s_rules_box.itemnames = dm_coop_names;
! 2599: //PGM
! 2600:
1.1 root 2601: if (Cvar_VariableValue("coop"))
2602: s_rules_box.curvalue = 1;
2603: else
2604: s_rules_box.curvalue = 0;
2605: s_rules_box.generic.callback = RulesChangeFunc;
1.1.1.2 root 2606:
1.1 root 2607: s_timelimit_field.generic.type = MTYPE_FIELD;
2608: s_timelimit_field.generic.name = "time limit";
2609: s_timelimit_field.generic.flags = QMF_NUMBERSONLY;
2610: s_timelimit_field.generic.x = 0;
2611: s_timelimit_field.generic.y = 36;
2612: s_timelimit_field.generic.statusbar = "0 = no limit";
2613: s_timelimit_field.length = 3;
2614: s_timelimit_field.visible_length = 3;
2615: strcpy( s_timelimit_field.buffer, Cvar_VariableString("timelimit") );
1.1.1.2 root 2616:
1.1 root 2617: s_fraglimit_field.generic.type = MTYPE_FIELD;
2618: s_fraglimit_field.generic.name = "frag limit";
2619: s_fraglimit_field.generic.flags = QMF_NUMBERSONLY;
2620: s_fraglimit_field.generic.x = 0;
2621: s_fraglimit_field.generic.y = 54;
2622: s_fraglimit_field.generic.statusbar = "0 = no limit";
2623: s_fraglimit_field.length = 3;
2624: s_fraglimit_field.visible_length = 3;
2625: strcpy( s_fraglimit_field.buffer, Cvar_VariableString("fraglimit") );
2626:
2627: /*
2628: ** maxclients determines the maximum number of players that can join
2629: ** the game. If maxclients is only "1" then we should default the menu
2630: ** option to 8 players, otherwise use whatever its current value is.
2631: ** Clamping will be done when the server is actually started.
2632: */
2633: s_maxclients_field.generic.type = MTYPE_FIELD;
2634: s_maxclients_field.generic.name = "max players";
2635: s_maxclients_field.generic.flags = QMF_NUMBERSONLY;
2636: s_maxclients_field.generic.x = 0;
2637: s_maxclients_field.generic.y = 72;
2638: s_maxclients_field.generic.statusbar = NULL;
2639: s_maxclients_field.length = 3;
2640: s_maxclients_field.visible_length = 3;
2641: if ( Cvar_VariableValue( "maxclients" ) == 1 )
2642: strcpy( s_maxclients_field.buffer, "8" );
2643: else
2644: strcpy( s_maxclients_field.buffer, Cvar_VariableString("maxclients") );
2645:
2646: s_hostname_field.generic.type = MTYPE_FIELD;
2647: s_hostname_field.generic.name = "hostname";
2648: s_hostname_field.generic.flags = 0;
2649: s_hostname_field.generic.x = 0;
2650: s_hostname_field.generic.y = 90;
2651: s_hostname_field.generic.statusbar = NULL;
2652: s_hostname_field.length = 12;
2653: s_hostname_field.visible_length = 12;
2654: strcpy( s_hostname_field.buffer, Cvar_VariableString("hostname") );
2655:
2656: s_startserver_dmoptions_action.generic.type = MTYPE_ACTION;
2657: s_startserver_dmoptions_action.generic.name = " deathmatch flags";
2658: s_startserver_dmoptions_action.generic.flags= QMF_LEFT_JUSTIFY;
2659: s_startserver_dmoptions_action.generic.x = 24;
2660: s_startserver_dmoptions_action.generic.y = 108;
2661: s_startserver_dmoptions_action.generic.statusbar = NULL;
2662: s_startserver_dmoptions_action.generic.callback = DMOptionsFunc;
2663:
2664: s_startserver_start_action.generic.type = MTYPE_ACTION;
2665: s_startserver_start_action.generic.name = " begin";
2666: s_startserver_start_action.generic.flags= QMF_LEFT_JUSTIFY;
2667: s_startserver_start_action.generic.x = 24;
2668: s_startserver_start_action.generic.y = 128;
2669: s_startserver_start_action.generic.callback = StartServerActionFunc;
2670:
2671: Menu_AddItem( &s_startserver_menu, &s_startmap_list );
2672: Menu_AddItem( &s_startserver_menu, &s_rules_box );
2673: Menu_AddItem( &s_startserver_menu, &s_timelimit_field );
2674: Menu_AddItem( &s_startserver_menu, &s_fraglimit_field );
2675: Menu_AddItem( &s_startserver_menu, &s_maxclients_field );
2676: Menu_AddItem( &s_startserver_menu, &s_hostname_field );
2677: Menu_AddItem( &s_startserver_menu, &s_startserver_dmoptions_action );
2678: Menu_AddItem( &s_startserver_menu, &s_startserver_start_action );
2679:
2680: Menu_Center( &s_startserver_menu );
2681:
2682: // call this now to set proper inital state
2683: RulesChangeFunc ( NULL );
2684: }
1.1.1.2 root 2685:
1.1 root 2686: void StartServer_MenuDraw(void)
2687: {
2688: Menu_Draw( &s_startserver_menu );
2689: }
1.1.1.2 root 2690:
1.1 root 2691: const char *StartServer_MenuKey( int key )
2692: {
2693: if ( key == K_ESCAPE )
2694: {
2695: if ( mapnames )
2696: {
2697: int i;
2698:
2699: for ( i = 0; i < nummaps; i++ )
2700: free( mapnames[i] );
2701: free( mapnames );
2702: }
2703: mapnames = 0;
2704: nummaps = 0;
2705: }
1.1.1.2 root 2706:
1.1 root 2707: return Default_MenuKey( &s_startserver_menu, key );
2708: }
1.1.1.2 root 2709:
1.1 root 2710: void M_Menu_StartServer_f (void)
2711: {
2712: StartServer_MenuInit();
2713: M_PushMenu( StartServer_MenuDraw, StartServer_MenuKey );
2714: }
1.1.1.2 root 2715:
1.1 root 2716: /*
2717: =============================================================================
2718:
2719: DMOPTIONS BOOK MENU
2720:
2721: =============================================================================
2722: */
2723: static char dmoptions_statusbar[128];
2724:
2725: static menuframework_s s_dmoptions_menu;
2726:
2727: static menulist_s s_friendlyfire_box;
2728: static menulist_s s_falls_box;
2729: static menulist_s s_weapons_stay_box;
2730: static menulist_s s_instant_powerups_box;
2731: static menulist_s s_powerups_box;
2732: static menulist_s s_health_box;
2733: static menulist_s s_spawn_farthest_box;
2734: static menulist_s s_teamplay_box;
2735: static menulist_s s_samelevel_box;
2736: static menulist_s s_force_respawn_box;
2737: static menulist_s s_armor_box;
2738: static menulist_s s_allow_exit_box;
2739: static menulist_s s_infinite_ammo_box;
2740: static menulist_s s_fixed_fov_box;
2741: static menulist_s s_quad_drop_box;
2742:
1.1.1.3 ! root 2743: //ROGUE
! 2744: static menulist_s s_no_mines_box;
! 2745: static menulist_s s_no_nukes_box;
! 2746: static menulist_s s_stack_double_box;
! 2747: static menulist_s s_no_spheres_box;
! 2748: //ROGUE
! 2749:
1.1 root 2750: static void DMFlagCallback( void *self )
2751: {
2752: menulist_s *f = ( menulist_s * ) self;
2753: int flags;
2754: int bit = 0;
2755:
2756: flags = Cvar_VariableValue( "dmflags" );
2757:
2758: if ( f == &s_friendlyfire_box )
2759: {
2760: if ( f->curvalue )
2761: flags &= ~DF_NO_FRIENDLY_FIRE;
2762: else
2763: flags |= DF_NO_FRIENDLY_FIRE;
2764: goto setvalue;
2765: }
2766: else if ( f == &s_falls_box )
2767: {
2768: if ( f->curvalue )
2769: flags &= ~DF_NO_FALLING;
2770: else
2771: flags |= DF_NO_FALLING;
2772: goto setvalue;
2773: }
2774: else if ( f == &s_weapons_stay_box )
2775: {
2776: bit = DF_WEAPONS_STAY;
2777: }
2778: else if ( f == &s_instant_powerups_box )
2779: {
2780: bit = DF_INSTANT_ITEMS;
2781: }
2782: else if ( f == &s_allow_exit_box )
2783: {
2784: bit = DF_ALLOW_EXIT;
2785: }
2786: else if ( f == &s_powerups_box )
2787: {
2788: if ( f->curvalue )
2789: flags &= ~DF_NO_ITEMS;
2790: else
2791: flags |= DF_NO_ITEMS;
2792: goto setvalue;
2793: }
2794: else if ( f == &s_health_box )
2795: {
2796: if ( f->curvalue )
2797: flags &= ~DF_NO_HEALTH;
2798: else
2799: flags |= DF_NO_HEALTH;
2800: goto setvalue;
2801: }
2802: else if ( f == &s_spawn_farthest_box )
2803: {
2804: bit = DF_SPAWN_FARTHEST;
2805: }
2806: else if ( f == &s_teamplay_box )
2807: {
2808: if ( f->curvalue == 1 )
2809: {
2810: flags |= DF_SKINTEAMS;
2811: flags &= ~DF_MODELTEAMS;
2812: }
2813: else if ( f->curvalue == 2 )
2814: {
2815: flags |= DF_MODELTEAMS;
2816: flags &= ~DF_SKINTEAMS;
2817: }
2818: else
2819: {
2820: flags &= ~( DF_MODELTEAMS | DF_SKINTEAMS );
2821: }
2822:
2823: goto setvalue;
2824: }
2825: else if ( f == &s_samelevel_box )
2826: {
2827: bit = DF_SAME_LEVEL;
2828: }
2829: else if ( f == &s_force_respawn_box )
2830: {
2831: bit = DF_FORCE_RESPAWN;
2832: }
2833: else if ( f == &s_armor_box )
2834: {
2835: if ( f->curvalue )
2836: flags &= ~DF_NO_ARMOR;
2837: else
2838: flags |= DF_NO_ARMOR;
2839: goto setvalue;
2840: }
2841: else if ( f == &s_infinite_ammo_box )
2842: {
2843: bit = DF_INFINITE_AMMO;
2844: }
2845: else if ( f == &s_fixed_fov_box )
2846: {
2847: bit = DF_FIXED_FOV;
2848: }
2849: else if ( f == &s_quad_drop_box )
2850: {
2851: bit = DF_QUAD_DROP;
2852: }
2853:
1.1.1.3 ! root 2854: //=======
! 2855: //ROGUE
! 2856: else if (Developer_searchpath(2) == 2)
! 2857: {
! 2858: if ( f == &s_no_mines_box)
! 2859: {
! 2860: bit = DF_NO_MINES;
! 2861: }
! 2862: else if ( f == &s_no_nukes_box)
! 2863: {
! 2864: bit = DF_NO_NUKES;
! 2865: }
! 2866: else if ( f == &s_stack_double_box)
! 2867: {
! 2868: bit = DF_NO_STACK_DOUBLE;
! 2869: }
! 2870: else if ( f == &s_no_spheres_box)
! 2871: {
! 2872: bit = DF_NO_SPHERES;
! 2873: }
! 2874: }
! 2875: //ROGUE
! 2876: //=======
1.1 root 2877:
2878: if ( f )
2879: {
2880: if ( f->curvalue == 0 )
2881: flags &= ~bit;
2882: else
2883: flags |= bit;
2884: }
2885:
2886: setvalue:
2887: Cvar_SetValue ("dmflags", flags);
2888:
2889: Com_sprintf( dmoptions_statusbar, sizeof( dmoptions_statusbar ), "dmflags = %d", flags );
2890:
2891: }
2892:
2893: void DMOptions_MenuInit( void )
2894: {
2895: static const char *yes_no_names[] =
2896: {
2897: "no", "yes", 0
2898: };
2899: static const char *teamplay_names[] =
2900: {
2901: "disabled", "by skin", "by model", 0
2902: };
2903: int dmflags = Cvar_VariableValue( "dmflags" );
2904: int y = 0;
2905:
2906: s_dmoptions_menu.x = viddef.width * 0.50;
2907: s_dmoptions_menu.nitems = 0;
2908:
2909: s_falls_box.generic.type = MTYPE_SPINCONTROL;
2910: s_falls_box.generic.x = 0;
2911: s_falls_box.generic.y = y;
2912: s_falls_box.generic.name = "falling damage";
2913: s_falls_box.generic.callback = DMFlagCallback;
2914: s_falls_box.itemnames = yes_no_names;
2915: s_falls_box.curvalue = ( dmflags & DF_NO_FALLING ) == 0;
2916:
2917: s_weapons_stay_box.generic.type = MTYPE_SPINCONTROL;
2918: s_weapons_stay_box.generic.x = 0;
2919: s_weapons_stay_box.generic.y = y += 10;
2920: s_weapons_stay_box.generic.name = "weapons stay";
2921: s_weapons_stay_box.generic.callback = DMFlagCallback;
2922: s_weapons_stay_box.itemnames = yes_no_names;
2923: s_weapons_stay_box.curvalue = ( dmflags & DF_WEAPONS_STAY ) != 0;
2924:
2925: s_instant_powerups_box.generic.type = MTYPE_SPINCONTROL;
2926: s_instant_powerups_box.generic.x = 0;
2927: s_instant_powerups_box.generic.y = y += 10;
2928: s_instant_powerups_box.generic.name = "instant powerups";
2929: s_instant_powerups_box.generic.callback = DMFlagCallback;
2930: s_instant_powerups_box.itemnames = yes_no_names;
2931: s_instant_powerups_box.curvalue = ( dmflags & DF_INSTANT_ITEMS ) != 0;
2932:
2933: s_powerups_box.generic.type = MTYPE_SPINCONTROL;
2934: s_powerups_box.generic.x = 0;
2935: s_powerups_box.generic.y = y += 10;
2936: s_powerups_box.generic.name = "allow powerups";
2937: s_powerups_box.generic.callback = DMFlagCallback;
2938: s_powerups_box.itemnames = yes_no_names;
2939: s_powerups_box.curvalue = ( dmflags & DF_NO_ITEMS ) == 0;
2940:
2941: s_health_box.generic.type = MTYPE_SPINCONTROL;
2942: s_health_box.generic.x = 0;
2943: s_health_box.generic.y = y += 10;
2944: s_health_box.generic.callback = DMFlagCallback;
2945: s_health_box.generic.name = "allow health";
2946: s_health_box.itemnames = yes_no_names;
2947: s_health_box.curvalue = ( dmflags & DF_NO_HEALTH ) == 0;
2948:
2949: s_armor_box.generic.type = MTYPE_SPINCONTROL;
2950: s_armor_box.generic.x = 0;
2951: s_armor_box.generic.y = y += 10;
2952: s_armor_box.generic.name = "allow armor";
2953: s_armor_box.generic.callback = DMFlagCallback;
2954: s_armor_box.itemnames = yes_no_names;
2955: s_armor_box.curvalue = ( dmflags & DF_NO_ARMOR ) == 0;
2956:
2957: s_spawn_farthest_box.generic.type = MTYPE_SPINCONTROL;
2958: s_spawn_farthest_box.generic.x = 0;
2959: s_spawn_farthest_box.generic.y = y += 10;
2960: s_spawn_farthest_box.generic.name = "spawn farthest";
2961: s_spawn_farthest_box.generic.callback = DMFlagCallback;
2962: s_spawn_farthest_box.itemnames = yes_no_names;
2963: s_spawn_farthest_box.curvalue = ( dmflags & DF_SPAWN_FARTHEST ) != 0;
2964:
2965: s_samelevel_box.generic.type = MTYPE_SPINCONTROL;
2966: s_samelevel_box.generic.x = 0;
2967: s_samelevel_box.generic.y = y += 10;
2968: s_samelevel_box.generic.name = "same map";
2969: s_samelevel_box.generic.callback = DMFlagCallback;
2970: s_samelevel_box.itemnames = yes_no_names;
2971: s_samelevel_box.curvalue = ( dmflags & DF_SAME_LEVEL ) != 0;
2972:
2973: s_force_respawn_box.generic.type = MTYPE_SPINCONTROL;
2974: s_force_respawn_box.generic.x = 0;
2975: s_force_respawn_box.generic.y = y += 10;
2976: s_force_respawn_box.generic.name = "force respawn";
2977: s_force_respawn_box.generic.callback = DMFlagCallback;
2978: s_force_respawn_box.itemnames = yes_no_names;
2979: s_force_respawn_box.curvalue = ( dmflags & DF_FORCE_RESPAWN ) != 0;
2980:
2981: s_teamplay_box.generic.type = MTYPE_SPINCONTROL;
2982: s_teamplay_box.generic.x = 0;
2983: s_teamplay_box.generic.y = y += 10;
2984: s_teamplay_box.generic.name = "teamplay";
2985: s_teamplay_box.generic.callback = DMFlagCallback;
2986: s_teamplay_box.itemnames = teamplay_names;
2987:
2988: s_allow_exit_box.generic.type = MTYPE_SPINCONTROL;
2989: s_allow_exit_box.generic.x = 0;
2990: s_allow_exit_box.generic.y = y += 10;
2991: s_allow_exit_box.generic.name = "allow exit";
2992: s_allow_exit_box.generic.callback = DMFlagCallback;
2993: s_allow_exit_box.itemnames = yes_no_names;
2994: s_allow_exit_box.curvalue = ( dmflags & DF_ALLOW_EXIT ) != 0;
2995:
2996: s_infinite_ammo_box.generic.type = MTYPE_SPINCONTROL;
2997: s_infinite_ammo_box.generic.x = 0;
2998: s_infinite_ammo_box.generic.y = y += 10;
2999: s_infinite_ammo_box.generic.name = "infinite ammo";
3000: s_infinite_ammo_box.generic.callback = DMFlagCallback;
3001: s_infinite_ammo_box.itemnames = yes_no_names;
3002: s_infinite_ammo_box.curvalue = ( dmflags & DF_INFINITE_AMMO ) != 0;
3003:
3004: s_fixed_fov_box.generic.type = MTYPE_SPINCONTROL;
3005: s_fixed_fov_box.generic.x = 0;
3006: s_fixed_fov_box.generic.y = y += 10;
3007: s_fixed_fov_box.generic.name = "fixed FOV";
3008: s_fixed_fov_box.generic.callback = DMFlagCallback;
3009: s_fixed_fov_box.itemnames = yes_no_names;
3010: s_fixed_fov_box.curvalue = ( dmflags & DF_FIXED_FOV ) != 0;
3011:
3012: s_quad_drop_box.generic.type = MTYPE_SPINCONTROL;
3013: s_quad_drop_box.generic.x = 0;
3014: s_quad_drop_box.generic.y = y += 10;
3015: s_quad_drop_box.generic.name = "quad drop";
3016: s_quad_drop_box.generic.callback = DMFlagCallback;
3017: s_quad_drop_box.itemnames = yes_no_names;
3018: s_quad_drop_box.curvalue = ( dmflags & DF_QUAD_DROP ) != 0;
3019:
3020: s_friendlyfire_box.generic.type = MTYPE_SPINCONTROL;
3021: s_friendlyfire_box.generic.x = 0;
3022: s_friendlyfire_box.generic.y = y += 10;
3023: s_friendlyfire_box.generic.name = "friendly fire";
3024: s_friendlyfire_box.generic.callback = DMFlagCallback;
3025: s_friendlyfire_box.itemnames = yes_no_names;
3026: s_friendlyfire_box.curvalue = ( dmflags & DF_NO_FRIENDLY_FIRE ) == 0;
3027:
1.1.1.3 ! root 3028: //============
! 3029: //ROGUE
! 3030: if(Developer_searchpath(2) == 2)
! 3031: {
! 3032: s_no_mines_box.generic.type = MTYPE_SPINCONTROL;
! 3033: s_no_mines_box.generic.x = 0;
! 3034: s_no_mines_box.generic.y = y += 10;
! 3035: s_no_mines_box.generic.name = "remove mines";
! 3036: s_no_mines_box.generic.callback = DMFlagCallback;
! 3037: s_no_mines_box.itemnames = yes_no_names;
! 3038: s_no_mines_box.curvalue = ( dmflags & DF_NO_MINES ) != 0;
! 3039:
! 3040: s_no_nukes_box.generic.type = MTYPE_SPINCONTROL;
! 3041: s_no_nukes_box.generic.x = 0;
! 3042: s_no_nukes_box.generic.y = y += 10;
! 3043: s_no_nukes_box.generic.name = "remove nukes";
! 3044: s_no_nukes_box.generic.callback = DMFlagCallback;
! 3045: s_no_nukes_box.itemnames = yes_no_names;
! 3046: s_no_nukes_box.curvalue = ( dmflags & DF_NO_NUKES ) != 0;
! 3047:
! 3048: s_stack_double_box.generic.type = MTYPE_SPINCONTROL;
! 3049: s_stack_double_box.generic.x = 0;
! 3050: s_stack_double_box.generic.y = y += 10;
! 3051: s_stack_double_box.generic.name = "2x/4x stacking off";
! 3052: s_stack_double_box.generic.callback = DMFlagCallback;
! 3053: s_stack_double_box.itemnames = yes_no_names;
! 3054: s_stack_double_box.curvalue = ( dmflags & DF_NO_STACK_DOUBLE ) != 0;
! 3055:
! 3056: s_no_spheres_box.generic.type = MTYPE_SPINCONTROL;
! 3057: s_no_spheres_box.generic.x = 0;
! 3058: s_no_spheres_box.generic.y = y += 10;
! 3059: s_no_spheres_box.generic.name = "remove spheres";
! 3060: s_no_spheres_box.generic.callback = DMFlagCallback;
! 3061: s_no_spheres_box.itemnames = yes_no_names;
! 3062: s_no_spheres_box.curvalue = ( dmflags & DF_NO_SPHERES ) != 0;
! 3063:
! 3064: }
! 3065: //ROGUE
! 3066: //============
! 3067:
1.1 root 3068: Menu_AddItem( &s_dmoptions_menu, &s_falls_box );
3069: Menu_AddItem( &s_dmoptions_menu, &s_weapons_stay_box );
3070: Menu_AddItem( &s_dmoptions_menu, &s_instant_powerups_box );
3071: Menu_AddItem( &s_dmoptions_menu, &s_powerups_box );
3072: Menu_AddItem( &s_dmoptions_menu, &s_health_box );
3073: Menu_AddItem( &s_dmoptions_menu, &s_armor_box );
3074: Menu_AddItem( &s_dmoptions_menu, &s_spawn_farthest_box );
3075: Menu_AddItem( &s_dmoptions_menu, &s_samelevel_box );
3076: Menu_AddItem( &s_dmoptions_menu, &s_force_respawn_box );
3077: Menu_AddItem( &s_dmoptions_menu, &s_teamplay_box );
3078: Menu_AddItem( &s_dmoptions_menu, &s_allow_exit_box );
3079: Menu_AddItem( &s_dmoptions_menu, &s_infinite_ammo_box );
3080: Menu_AddItem( &s_dmoptions_menu, &s_fixed_fov_box );
3081: Menu_AddItem( &s_dmoptions_menu, &s_quad_drop_box );
3082: Menu_AddItem( &s_dmoptions_menu, &s_friendlyfire_box );
3083:
1.1.1.3 ! root 3084: //=======
! 3085: //ROGUE
! 3086: if(Developer_searchpath(2) == 2)
! 3087: {
! 3088: Menu_AddItem( &s_dmoptions_menu, &s_no_mines_box );
! 3089: Menu_AddItem( &s_dmoptions_menu, &s_no_nukes_box );
! 3090: Menu_AddItem( &s_dmoptions_menu, &s_stack_double_box );
! 3091: Menu_AddItem( &s_dmoptions_menu, &s_no_spheres_box );
! 3092: }
! 3093: //ROGUE
! 3094: //=======
! 3095:
1.1 root 3096: Menu_Center( &s_dmoptions_menu );
3097:
3098: // set the original dmflags statusbar
3099: DMFlagCallback( 0 );
3100: Menu_SetStatusBar( &s_dmoptions_menu, dmoptions_statusbar );
3101: }
3102:
3103: void DMOptions_MenuDraw(void)
3104: {
3105: Menu_Draw( &s_dmoptions_menu );
3106: }
3107:
3108: const char *DMOptions_MenuKey( int key )
3109: {
3110: return Default_MenuKey( &s_dmoptions_menu, key );
3111: }
3112:
3113: void M_Menu_DMOptions_f (void)
3114: {
3115: DMOptions_MenuInit();
3116: M_PushMenu( DMOptions_MenuDraw, DMOptions_MenuKey );
3117: }
3118:
3119: /*
3120: =============================================================================
1.1.1.2 root 3121:
3122: DOWNLOADOPTIONS BOOK MENU
3123:
3124: =============================================================================
3125: */
3126: static menuframework_s s_downloadoptions_menu;
3127:
3128: static menuseparator_s s_download_title;
3129: static menulist_s s_allow_download_box;
3130: static menulist_s s_allow_download_maps_box;
3131: static menulist_s s_allow_download_models_box;
3132: static menulist_s s_allow_download_players_box;
3133: static menulist_s s_allow_download_sounds_box;
3134:
3135: static void DownloadCallback( void *self )
3136: {
3137: menulist_s *f = ( menulist_s * ) self;
3138:
3139: if (f == &s_allow_download_box)
3140: {
3141: Cvar_SetValue("allow_download", f->curvalue);
3142: }
3143:
3144: else if (f == &s_allow_download_maps_box)
3145: {
3146: Cvar_SetValue("allow_download_maps", f->curvalue);
3147: }
3148:
3149: else if (f == &s_allow_download_models_box)
3150: {
3151: Cvar_SetValue("allow_download_models", f->curvalue);
3152: }
3153:
3154: else if (f == &s_allow_download_players_box)
3155: {
3156: Cvar_SetValue("allow_download_players", f->curvalue);
3157: }
3158:
3159: else if (f == &s_allow_download_sounds_box)
3160: {
3161: Cvar_SetValue("allow_download_sounds", f->curvalue);
3162: }
3163: }
3164:
3165: void DownloadOptions_MenuInit( void )
3166: {
3167: static const char *yes_no_names[] =
3168: {
3169: "no", "yes", 0
3170: };
3171: int y = 0;
3172:
3173: s_downloadoptions_menu.x = viddef.width * 0.50;
3174: s_downloadoptions_menu.nitems = 0;
3175:
3176: s_download_title.generic.type = MTYPE_SEPARATOR;
3177: s_download_title.generic.name = "Download Options";
3178: s_download_title.generic.x = 48;
3179: s_download_title.generic.y = y;
3180:
3181: s_allow_download_box.generic.type = MTYPE_SPINCONTROL;
3182: s_allow_download_box.generic.x = 0;
3183: s_allow_download_box.generic.y = y += 20;
3184: s_allow_download_box.generic.name = "allow downloading";
3185: s_allow_download_box.generic.callback = DownloadCallback;
3186: s_allow_download_box.itemnames = yes_no_names;
3187: s_allow_download_box.curvalue = (Cvar_VariableValue("allow_download") != 0);
3188:
3189: s_allow_download_maps_box.generic.type = MTYPE_SPINCONTROL;
3190: s_allow_download_maps_box.generic.x = 0;
3191: s_allow_download_maps_box.generic.y = y += 20;
3192: s_allow_download_maps_box.generic.name = "maps";
3193: s_allow_download_maps_box.generic.callback = DownloadCallback;
3194: s_allow_download_maps_box.itemnames = yes_no_names;
3195: s_allow_download_maps_box.curvalue = (Cvar_VariableValue("allow_download_maps") != 0);
3196:
3197: s_allow_download_players_box.generic.type = MTYPE_SPINCONTROL;
3198: s_allow_download_players_box.generic.x = 0;
3199: s_allow_download_players_box.generic.y = y += 10;
3200: s_allow_download_players_box.generic.name = "player models/skins";
3201: s_allow_download_players_box.generic.callback = DownloadCallback;
3202: s_allow_download_players_box.itemnames = yes_no_names;
3203: s_allow_download_players_box.curvalue = (Cvar_VariableValue("allow_download_players") != 0);
3204:
3205: s_allow_download_models_box.generic.type = MTYPE_SPINCONTROL;
3206: s_allow_download_models_box.generic.x = 0;
3207: s_allow_download_models_box.generic.y = y += 10;
3208: s_allow_download_models_box.generic.name = "models";
3209: s_allow_download_models_box.generic.callback = DownloadCallback;
3210: s_allow_download_models_box.itemnames = yes_no_names;
3211: s_allow_download_models_box.curvalue = (Cvar_VariableValue("allow_download_models") != 0);
3212:
3213: s_allow_download_sounds_box.generic.type = MTYPE_SPINCONTROL;
3214: s_allow_download_sounds_box.generic.x = 0;
3215: s_allow_download_sounds_box.generic.y = y += 10;
3216: s_allow_download_sounds_box.generic.name = "sounds";
3217: s_allow_download_sounds_box.generic.callback = DownloadCallback;
3218: s_allow_download_sounds_box.itemnames = yes_no_names;
3219: s_allow_download_sounds_box.curvalue = (Cvar_VariableValue("allow_download_sounds") != 0);
3220:
3221: Menu_AddItem( &s_downloadoptions_menu, &s_download_title );
3222: Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_box );
3223: Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_maps_box );
3224: Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_players_box );
3225: Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_models_box );
3226: Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_sounds_box );
3227:
3228: Menu_Center( &s_downloadoptions_menu );
3229:
3230: // skip over title
3231: if (s_downloadoptions_menu.cursor == 0)
3232: s_downloadoptions_menu.cursor = 1;
3233: }
3234:
3235: void DownloadOptions_MenuDraw(void)
3236: {
3237: Menu_Draw( &s_downloadoptions_menu );
3238: }
3239:
3240: const char *DownloadOptions_MenuKey( int key )
3241: {
3242: return Default_MenuKey( &s_downloadoptions_menu, key );
3243: }
3244:
3245: void M_Menu_DownloadOptions_f (void)
3246: {
3247: DownloadOptions_MenuInit();
3248: M_PushMenu( DownloadOptions_MenuDraw, DownloadOptions_MenuKey );
3249: }
3250: /*
3251: =============================================================================
3252:
1.1 root 3253: ADDRESS BOOK MENU
1.1.1.2 root 3254:
1.1 root 3255: =============================================================================
3256: */
3257: #define NUM_ADDRESSBOOK_ENTRIES 9
1.1.1.2 root 3258:
1.1 root 3259: static menuframework_s s_addressbook_menu;
3260: static menufield_s s_addressbook_fields[NUM_ADDRESSBOOK_ENTRIES];
1.1.1.2 root 3261:
1.1 root 3262: void AddressBook_MenuInit( void )
3263: {
3264: int i;
1.1.1.2 root 3265:
1.1 root 3266: s_addressbook_menu.x = viddef.width / 2 - 142;
3267: s_addressbook_menu.y = viddef.height / 2 - 58;
3268: s_addressbook_menu.nitems = 0;
1.1.1.2 root 3269:
1.1 root 3270: for ( i = 0; i < NUM_ADDRESSBOOK_ENTRIES; i++ )
3271: {
3272: cvar_t *adr;
3273: char buffer[20];
3274:
3275: Com_sprintf( buffer, sizeof( buffer ), "adr%d", i );
3276:
3277: adr = Cvar_Get( buffer, "", CVAR_ARCHIVE );
1.1.1.2 root 3278:
1.1 root 3279: s_addressbook_fields[i].generic.type = MTYPE_FIELD;
3280: s_addressbook_fields[i].generic.name = 0;
3281: s_addressbook_fields[i].generic.callback = 0;
3282: s_addressbook_fields[i].generic.x = 0;
3283: s_addressbook_fields[i].generic.y = i * 18 + 0;
3284: s_addressbook_fields[i].generic.localdata[0] = i;
3285: s_addressbook_fields[i].cursor = 0;
3286: s_addressbook_fields[i].length = 60;
3287: s_addressbook_fields[i].visible_length = 30;
3288:
3289: strcpy( s_addressbook_fields[i].buffer, adr->string );
1.1.1.2 root 3290:
1.1 root 3291: Menu_AddItem( &s_addressbook_menu, &s_addressbook_fields[i] );
3292: }
3293: }
1.1.1.2 root 3294:
1.1 root 3295: const char *AddressBook_MenuKey( int key )
3296: {
3297: if ( key == K_ESCAPE )
3298: {
3299: int index;
3300: char buffer[20];
3301:
3302: for ( index = 0; index < NUM_ADDRESSBOOK_ENTRIES; index++ )
3303: {
3304: Com_sprintf( buffer, sizeof( buffer ), "adr%d", index );
3305: Cvar_Set( buffer, s_addressbook_fields[index].buffer );
3306: }
3307: }
3308: return Default_MenuKey( &s_addressbook_menu, key );
3309: }
1.1.1.2 root 3310:
1.1 root 3311: void AddressBook_MenuDraw(void)
3312: {
3313: M_Banner( "m_banner_addressbook" );
3314: Menu_Draw( &s_addressbook_menu );
3315: }
1.1.1.2 root 3316:
1.1 root 3317: void M_Menu_AddressBook_f(void)
3318: {
3319: AddressBook_MenuInit();
3320: M_PushMenu( AddressBook_MenuDraw, AddressBook_MenuKey );
3321: }
1.1.1.2 root 3322:
1.1 root 3323: /*
3324: =============================================================================
1.1.1.2 root 3325:
1.1 root 3326: PLAYER CONFIG MENU
1.1.1.2 root 3327:
1.1 root 3328: =============================================================================
3329: */
3330: static menuframework_s s_player_config_menu;
3331: static menufield_s s_player_name_field;
3332: static menulist_s s_player_model_box;
3333: static menulist_s s_player_skin_box;
3334: static menulist_s s_player_handedness_box;
1.1.1.2 root 3335: static menulist_s s_player_rate_box;
1.1 root 3336: static menuseparator_s s_player_skin_title;
3337: static menuseparator_s s_player_model_title;
3338: static menuseparator_s s_player_hand_title;
1.1.1.2 root 3339: static menuseparator_s s_player_rate_title;
3340: static menuaction_s s_player_download_action;
1.1 root 3341:
3342: #define MAX_DISPLAYNAME 16
3343: #define MAX_PLAYERMODELS 1024
3344:
3345: typedef struct
3346: {
3347: int nskins;
3348: char **skindisplaynames;
3349: char displayname[MAX_DISPLAYNAME];
3350: char directory[MAX_QPATH];
3351: } playermodelinfo_s;
3352:
3353: static playermodelinfo_s s_pmi[MAX_PLAYERMODELS];
3354: static char *s_pmnames[MAX_PLAYERMODELS];
3355: static int s_numplayermodels;
3356:
1.1.1.2 root 3357: static int rate_tbl[] = { 2500, 3200, 5000, 10000, 25000, 0 };
3358: static const char *rate_names[] = { "28.8 Modem", "33.6 Modem", "Single ISDN",
3359: "Dual ISDN/Cable", "T1/LAN", "User defined", 0 };
3360:
3361: void DownloadOptionsFunc( void *self )
3362: {
3363: M_Menu_DownloadOptions_f();
3364: }
3365:
1.1 root 3366: static void HandednessCallback( void *unused )
3367: {
3368: Cvar_SetValue( "hand", s_player_handedness_box.curvalue );
3369: }
3370:
1.1.1.2 root 3371: static void RateCallback( void *unused )
3372: {
3373: if (s_player_rate_box.curvalue != sizeof(rate_tbl) / sizeof(*rate_tbl) - 1)
3374: Cvar_SetValue( "rate", rate_tbl[s_player_rate_box.curvalue] );
3375: }
3376:
1.1 root 3377: static void ModelCallback( void *unused )
3378: {
3379: s_player_skin_box.itemnames = s_pmi[s_player_model_box.curvalue].skindisplaynames;
3380: s_player_skin_box.curvalue = 0;
3381: }
3382:
3383: static void FreeFileList( char **list, int n )
3384: {
3385: int i;
3386:
3387: for ( i = 0; i < n; i++ )
3388: {
3389: if ( list[i] )
3390: {
3391: free( list[i] );
3392: list[i] = 0;
3393: }
3394: }
3395: free( list );
3396: }
3397:
3398: static qboolean IconOfSkinExists( char *skin, char **pcxfiles, int npcxfiles )
3399: {
3400: int i;
3401: char scratch[1024];
3402:
3403: strcpy( scratch, skin );
3404: *strrchr( scratch, '.' ) = 0;
3405: strcat( scratch, "_i.pcx" );
3406:
3407: for ( i = 0; i < npcxfiles; i++ )
3408: {
3409: if ( strcmp( pcxfiles[i], scratch ) == 0 )
3410: return true;
3411: }
3412:
3413: return false;
3414: }
3415:
3416: static qboolean PlayerConfig_ScanDirectories( void )
3417: {
3418: char findname[1024];
3419: char scratch[1024];
3420: int ndirs = 0, npms = 0;
3421: char **dirnames;
3422: char *path = NULL;
3423: int i;
3424:
3425: extern char **FS_ListFiles( char *, int *, unsigned, unsigned );
3426:
3427: s_numplayermodels = 0;
3428:
3429: /*
3430: ** get a list of directories
3431: */
3432: do
3433: {
3434: path = FS_NextPath( path );
3435: Com_sprintf( findname, sizeof(findname), "%s/players/*.*", path );
3436:
3437: if ( ( dirnames = FS_ListFiles( findname, &ndirs, SFF_SUBDIR, 0 ) ) != 0 )
3438: break;
3439: } while ( path );
3440:
3441: if ( !dirnames )
3442: return false;
3443:
3444: /*
3445: ** go through the subdirectories
3446: */
3447: npms = ndirs;
3448: if ( npms > MAX_PLAYERMODELS )
3449: npms = MAX_PLAYERMODELS;
3450:
3451: for ( i = 0; i < npms; i++ )
3452: {
3453: int k, s;
3454: char *a, *b, *c;
3455: char **pcxnames;
3456: char **skinnames;
3457: int npcxfiles;
3458: int nskins = 0;
3459:
3460: if ( dirnames[i] == 0 )
3461: continue;
3462:
3463: // verify the existence of tris.md2
3464: strcpy( scratch, dirnames[i] );
3465: strcat( scratch, "/tris.md2" );
3466: if ( !Sys_FindFirst( scratch, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM ) )
3467: {
3468: free( dirnames[i] );
3469: dirnames[i] = 0;
3470: Sys_FindClose();
3471: continue;
3472: }
3473: Sys_FindClose();
3474:
3475: // verify the existence of at least one pcx skin
3476: strcpy( scratch, dirnames[i] );
3477: strcat( scratch, "/*.pcx" );
3478: pcxnames = FS_ListFiles( scratch, &npcxfiles, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM );
3479:
3480: if ( !pcxnames )
3481: {
3482: free( dirnames[i] );
3483: dirnames[i] = 0;
3484: continue;
3485: }
3486:
3487: // count valid skins, which consist of a skin with a matching "_i" icon
3488: for ( k = 0; k < npcxfiles-1; k++ )
3489: {
3490: if ( !strstr( pcxnames[k], "_i.pcx" ) )
3491: {
3492: if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) )
3493: {
3494: nskins++;
3495: }
3496: }
3497: }
3498: if ( !nskins )
3499: continue;
3500:
3501: skinnames = malloc( sizeof( char * ) * ( nskins + 1 ) );
3502: memset( skinnames, 0, sizeof( char * ) * ( nskins + 1 ) );
3503:
3504: // copy the valid skins
3505: for ( s = 0, k = 0; k < npcxfiles-1; k++ )
3506: {
3507: char *a, *b, *c;
3508:
3509: if ( !strstr( pcxnames[k], "_i.pcx" ) )
3510: {
3511: if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) )
3512: {
3513: a = strrchr( pcxnames[k], '/' );
3514: b = strrchr( pcxnames[k], '\\' );
3515:
3516: if ( a > b )
3517: c = a;
3518: else
3519: c = b;
3520:
3521: strcpy( scratch, c + 1 );
3522:
3523: if ( strrchr( scratch, '.' ) )
3524: *strrchr( scratch, '.' ) = 0;
3525:
3526: skinnames[s] = strdup( scratch );
3527: s++;
3528: }
3529: }
3530: }
3531:
3532: // at this point we have a valid player model
3533: s_pmi[s_numplayermodels].nskins = nskins;
3534: s_pmi[s_numplayermodels].skindisplaynames = skinnames;
3535:
3536: // make short name for the model
3537: a = strrchr( dirnames[i], '/' );
3538: b = strrchr( dirnames[i], '\\' );
3539:
3540: if ( a > b )
3541: c = a;
3542: else
3543: c = b;
3544:
3545: strncpy( s_pmi[s_numplayermodels].displayname, c + 1, MAX_DISPLAYNAME-1 );
3546: strcpy( s_pmi[s_numplayermodels].directory, c + 1 );
3547:
3548: FreeFileList( pcxnames, npcxfiles );
3549:
3550: s_numplayermodels++;
3551: }
3552: if ( dirnames )
3553: FreeFileList( dirnames, ndirs );
3554: }
3555:
3556: static int pmicmpfnc( const void *_a, const void *_b )
3557: {
3558: const playermodelinfo_s *a = ( const playermodelinfo_s * ) _a;
3559: const playermodelinfo_s *b = ( const playermodelinfo_s * ) _b;
3560:
3561: /*
3562: ** sort by male, female, then alphabetical
3563: */
3564: if ( strcmp( a->directory, "male" ) == 0 )
3565: return -1;
3566: else if ( strcmp( b->directory, "male" ) == 0 )
3567: return 1;
3568:
3569: if ( strcmp( a->directory, "female" ) == 0 )
3570: return -1;
3571: else if ( strcmp( b->directory, "female" ) == 0 )
3572: return 1;
3573:
3574: return strcmp( a->directory, b->directory );
3575: }
3576:
1.1.1.2 root 3577:
3578: qboolean PlayerConfig_MenuInit( void )
1.1 root 3579: {
3580: extern cvar_t *name;
3581: extern cvar_t *team;
3582: extern cvar_t *skin;
3583: char currentdirectory[1024];
3584: char currentskin[1024];
3585: int i = 0;
3586:
3587: int currentdirectoryindex = 0;
3588: int currentskinindex = 0;
3589:
3590: cvar_t *hand = Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
3591:
3592: static const char *handedness[] = { "right", "left", "center", 0 };
3593:
3594: PlayerConfig_ScanDirectories();
3595:
1.1.1.2 root 3596: if (s_numplayermodels == 0)
3597: return false;
3598:
1.1 root 3599: if ( hand->value < 0 || hand->value > 2 )
3600: Cvar_SetValue( "hand", 0 );
3601:
3602: strcpy( currentdirectory, skin->string );
3603:
3604: if ( strchr( currentdirectory, '/' ) )
3605: {
3606: strcpy( currentskin, strchr( currentdirectory, '/' ) + 1 );
3607: *strchr( currentdirectory, '/' ) = 0;
3608: }
3609: else if ( strchr( currentdirectory, '\\' ) )
3610: {
3611: strcpy( currentskin, strchr( currentdirectory, '\\' ) + 1 );
3612: *strchr( currentdirectory, '\\' ) = 0;
3613: }
3614: else
3615: {
3616: strcpy( currentdirectory, "male" );
3617: strcpy( currentskin, "grunt" );
3618: }
3619:
3620: qsort( s_pmi, s_numplayermodels, sizeof( s_pmi[0] ), pmicmpfnc );
3621:
3622: memset( s_pmnames, 0, sizeof( s_pmnames ) );
3623: for ( i = 0; i < s_numplayermodels; i++ )
3624: {
3625: s_pmnames[i] = s_pmi[i].displayname;
3626: if ( Q_stricmp( s_pmi[i].directory, currentdirectory ) == 0 )
3627: {
3628: int j;
3629:
3630: currentdirectoryindex = i;
3631:
3632: for ( j = 0; j < s_pmi[i].nskins; j++ )
3633: {
3634: if ( Q_stricmp( s_pmi[i].skindisplaynames[j], currentskin ) == 0 )
3635: {
3636: currentskinindex = j;
3637: break;
3638: }
3639: }
3640: }
3641: }
3642:
3643: s_player_config_menu.x = viddef.width / 2 - 95;
3644: s_player_config_menu.y = viddef.height / 2 - 97;
3645: s_player_config_menu.nitems = 0;
3646:
3647: s_player_name_field.generic.type = MTYPE_FIELD;
3648: s_player_name_field.generic.name = "name";
3649: s_player_name_field.generic.callback = 0;
3650: s_player_name_field.generic.x = 0;
3651: s_player_name_field.generic.y = 0;
3652: s_player_name_field.length = 20;
3653: s_player_name_field.visible_length = 20;
3654: strcpy( s_player_name_field.buffer, name->string );
3655: s_player_name_field.cursor = strlen( name->string );
3656:
3657: s_player_model_title.generic.type = MTYPE_SEPARATOR;
3658: s_player_model_title.generic.name = "model";
3659: s_player_model_title.generic.x = -8;
3660: s_player_model_title.generic.y = 60;
3661:
3662: s_player_model_box.generic.type = MTYPE_SPINCONTROL;
3663: s_player_model_box.generic.x = -56;
3664: s_player_model_box.generic.y = 70;
3665: s_player_model_box.generic.callback = ModelCallback;
3666: s_player_model_box.generic.cursor_offset = -48;
3667: s_player_model_box.curvalue = currentdirectoryindex;
3668: s_player_model_box.itemnames = s_pmnames;
3669:
3670: s_player_skin_title.generic.type = MTYPE_SEPARATOR;
3671: s_player_skin_title.generic.name = "skin";
3672: s_player_skin_title.generic.x = -16;
3673: s_player_skin_title.generic.y = 84;
3674:
3675: s_player_skin_box.generic.type = MTYPE_SPINCONTROL;
3676: s_player_skin_box.generic.x = -56;
3677: s_player_skin_box.generic.y = 94;
3678: s_player_skin_box.generic.name = 0;
3679: s_player_skin_box.generic.callback = 0;
3680: s_player_skin_box.generic.cursor_offset = -48;
3681: s_player_skin_box.curvalue = currentskinindex;
3682: s_player_skin_box.itemnames = s_pmi[currentdirectoryindex].skindisplaynames;
3683:
3684: s_player_hand_title.generic.type = MTYPE_SEPARATOR;
3685: s_player_hand_title.generic.name = "handedness";
3686: s_player_hand_title.generic.x = 32;
3687: s_player_hand_title.generic.y = 108;
3688:
3689: s_player_handedness_box.generic.type = MTYPE_SPINCONTROL;
3690: s_player_handedness_box.generic.x = -56;
3691: s_player_handedness_box.generic.y = 118;
3692: s_player_handedness_box.generic.name = 0;
3693: s_player_handedness_box.generic.cursor_offset = -48;
3694: s_player_handedness_box.generic.callback = HandednessCallback;
3695: s_player_handedness_box.curvalue = Cvar_VariableValue( "hand" );
3696: s_player_handedness_box.itemnames = handedness;
3697:
1.1.1.2 root 3698: for (i = 0; i < sizeof(rate_tbl) / sizeof(*rate_tbl) - 1; i++)
3699: if (Cvar_VariableValue("rate") == rate_tbl[i])
3700: break;
3701:
3702: s_player_rate_title.generic.type = MTYPE_SEPARATOR;
3703: s_player_rate_title.generic.name = "connect speed";
3704: s_player_rate_title.generic.x = 56;
3705: s_player_rate_title.generic.y = 156;
3706:
3707: s_player_rate_box.generic.type = MTYPE_SPINCONTROL;
3708: s_player_rate_box.generic.x = -56;
3709: s_player_rate_box.generic.y = 166;
3710: s_player_rate_box.generic.name = 0;
3711: s_player_rate_box.generic.cursor_offset = -48;
3712: s_player_rate_box.generic.callback = RateCallback;
3713: s_player_rate_box.curvalue = i;
3714: s_player_rate_box.itemnames = rate_names;
3715:
3716: s_player_download_action.generic.type = MTYPE_ACTION;
3717: s_player_download_action.generic.name = "download options";
3718: s_player_download_action.generic.flags= QMF_LEFT_JUSTIFY;
3719: s_player_download_action.generic.x = -24;
3720: s_player_download_action.generic.y = 186;
3721: s_player_download_action.generic.statusbar = NULL;
3722: s_player_download_action.generic.callback = DownloadOptionsFunc;
3723:
1.1 root 3724: Menu_AddItem( &s_player_config_menu, &s_player_name_field );
3725: Menu_AddItem( &s_player_config_menu, &s_player_model_title );
3726: Menu_AddItem( &s_player_config_menu, &s_player_model_box );
3727: if ( s_player_skin_box.itemnames )
3728: {
3729: Menu_AddItem( &s_player_config_menu, &s_player_skin_title );
3730: Menu_AddItem( &s_player_config_menu, &s_player_skin_box );
3731: }
3732: Menu_AddItem( &s_player_config_menu, &s_player_hand_title );
3733: Menu_AddItem( &s_player_config_menu, &s_player_handedness_box );
1.1.1.2 root 3734: Menu_AddItem( &s_player_config_menu, &s_player_rate_title );
3735: Menu_AddItem( &s_player_config_menu, &s_player_rate_box );
3736: Menu_AddItem( &s_player_config_menu, &s_player_download_action );
3737:
3738: return true;
1.1 root 3739: }
3740:
3741: void PlayerConfig_MenuDraw( void )
3742: {
3743: extern float CalcFov( float fov_x, float w, float h );
3744: refdef_t refdef;
3745: char scratch[MAX_QPATH];
3746:
3747: memset( &refdef, 0, sizeof( refdef ) );
3748:
3749: refdef.x = viddef.width / 2;
3750: refdef.y = viddef.height / 2 - 72;
3751: refdef.width = 144;
3752: refdef.height = 168;
3753: refdef.fov_x = 40;
3754: refdef.fov_y = CalcFov( refdef.fov_x, refdef.width, refdef.height );
3755: refdef.time = cls.realtime*0.001;
3756:
3757: if ( s_pmi[s_player_model_box.curvalue].skindisplaynames )
3758: {
3759: static int yaw;
3760: int maxframe = 29;
3761: entity_t entity;
3762:
3763: memset( &entity, 0, sizeof( entity ) );
3764:
3765: Com_sprintf( scratch, sizeof( scratch ), "players/%s/tris.md2", s_pmi[s_player_model_box.curvalue].directory );
3766: entity.model = re.RegisterModel( scratch );
3767: 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] );
3768: entity.skin = re.RegisterSkin( scratch );
3769: entity.flags = RF_FULLBRIGHT;
3770: entity.origin[0] = 80;
3771: entity.origin[1] = 0;
3772: entity.origin[2] = 0;
3773: VectorCopy( entity.origin, entity.oldorigin );
3774: entity.frame = 0;
3775: entity.oldframe = 0;
3776: entity.backlerp = 0.0;
3777: entity.angles[1] = yaw++;
3778: if ( ++yaw > 360 )
3779: yaw -= 360;
3780:
3781: refdef.areabits = 0;
3782: refdef.num_entities = 1;
3783: refdef.entities = &entity;
3784: refdef.lightstyles = 0;
3785: refdef.rdflags = RDF_NOWORLDMODEL;
3786:
3787: Menu_Draw( &s_player_config_menu );
3788:
3789: M_DrawTextBox( ( refdef.x ) * ( 320.0F / viddef.width ) - 8, ( viddef.height / 2 ) * ( 240.0F / viddef.height) - 77, refdef.width / 8, refdef.height / 8 );
3790: refdef.height += 4;
3791:
3792: re.RenderFrame( &refdef );
3793:
3794: Com_sprintf( scratch, sizeof( scratch ), "/players/%s/%s_i.pcx",
3795: s_pmi[s_player_model_box.curvalue].directory,
3796: s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
3797: re.DrawPic( s_player_config_menu.x - 40, refdef.y, scratch );
3798: }
3799: }
1.1.1.2 root 3800:
1.1 root 3801: const char *PlayerConfig_MenuKey (int key)
3802: {
3803: int i;
3804:
3805: if ( key == K_ESCAPE )
3806: {
3807: char scratch[1024];
3808:
3809: Cvar_Set( "name", s_player_name_field.buffer );
3810:
3811: Com_sprintf( scratch, sizeof( scratch ), "%s/%s",
3812: s_pmi[s_player_model_box.curvalue].directory,
1.1.1.3 ! root 3813: s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
1.1 root 3814:
3815: Cvar_Set( "skin", scratch );
3816:
3817: for ( i = 0; i < s_numplayermodels; i++ )
3818: {
3819: int j;
3820:
3821: for ( j = 0; j < s_pmi[i].nskins; j++ )
3822: {
3823: if ( s_pmi[i].skindisplaynames[j] )
3824: free( s_pmi[i].skindisplaynames[j] );
3825: s_pmi[i].skindisplaynames[j] = 0;
3826: }
3827: free( s_pmi[i].skindisplaynames );
3828: s_pmi[i].skindisplaynames = 0;
3829: s_pmi[i].nskins = 0;
3830: }
3831: }
3832: return Default_MenuKey( &s_player_config_menu, key );
3833: }
1.1.1.2 root 3834:
3835:
1.1 root 3836: void M_Menu_PlayerConfig_f (void)
3837: {
1.1.1.2 root 3838: if (!PlayerConfig_MenuInit())
3839: {
3840: Menu_SetStatusBar( &s_multiplayer_menu, "No valid player models found" );
3841: return;
3842: }
3843: Menu_SetStatusBar( &s_multiplayer_menu, NULL );
1.1 root 3844: M_PushMenu( PlayerConfig_MenuDraw, PlayerConfig_MenuKey );
3845: }
1.1.1.2 root 3846:
3847:
1.1 root 3848: /*
3849: =======================================================================
3850:
3851: GALLERY MENU
3852:
3853: =======================================================================
3854: */
3855: #if 0
3856: void M_Menu_Gallery_f( void )
3857: {
3858: extern void Gallery_MenuDraw( void );
3859: extern const char *Gallery_MenuKey( int key );
1.1.1.2 root 3860:
1.1 root 3861: M_PushMenu( Gallery_MenuDraw, Gallery_MenuKey );
3862: }
3863: #endif
1.1.1.2 root 3864:
1.1 root 3865: /*
3866: =======================================================================
1.1.1.2 root 3867:
1.1 root 3868: QUIT MENU
1.1.1.2 root 3869:
1.1 root 3870: =======================================================================
3871: */
1.1.1.2 root 3872:
1.1 root 3873: const char *M_Quit_Key (int key)
3874: {
3875: switch (key)
3876: {
3877: case K_ESCAPE:
3878: case 'n':
3879: case 'N':
3880: M_PopMenu ();
3881: break;
1.1.1.2 root 3882:
1.1 root 3883: case 'Y':
3884: case 'y':
3885: cls.key_dest = key_console;
3886: CL_Quit_f ();
3887: break;
1.1.1.2 root 3888:
1.1 root 3889: default:
3890: break;
3891: }
1.1.1.2 root 3892:
1.1 root 3893: return NULL;
1.1.1.2 root 3894:
1.1 root 3895: }
1.1.1.2 root 3896:
3897:
1.1 root 3898: void M_Quit_Draw (void)
3899: {
3900: int w, h;
1.1.1.2 root 3901:
1.1 root 3902: re.DrawGetPicSize (&w, &h, "quit");
3903: re.DrawPic ( (viddef.width-w)/2, (viddef.height-h)/2, "quit");
3904: }
1.1.1.2 root 3905:
3906:
1.1 root 3907: void M_Menu_Quit_f (void)
3908: {
3909: M_PushMenu (M_Quit_Draw, M_Quit_Key);
3910: }
1.1.1.2 root 3911:
3912:
3913:
1.1 root 3914: //=============================================================================
3915: /* Menu Subsystem */
1.1.1.2 root 3916:
3917:
1.1 root 3918: /*
3919: =================
3920: M_Init
3921: =================
3922: */
3923: void M_Init (void)
3924: {
3925: Cmd_AddCommand ("menu_main", M_Menu_Main_f);
3926: Cmd_AddCommand ("menu_game", M_Menu_Game_f);
3927: Cmd_AddCommand ("menu_loadgame", M_Menu_LoadGame_f);
3928: Cmd_AddCommand ("menu_savegame", M_Menu_SaveGame_f);
3929: Cmd_AddCommand ("menu_joinserver", M_Menu_JoinServer_f);
3930: Cmd_AddCommand ("menu_addressbook", M_Menu_AddressBook_f);
3931: Cmd_AddCommand ("menu_startserver", M_Menu_StartServer_f);
3932: Cmd_AddCommand ("menu_dmoptions", M_Menu_DMOptions_f);
3933: Cmd_AddCommand ("menu_playerconfig", M_Menu_PlayerConfig_f);
1.1.1.2 root 3934: Cmd_AddCommand ("menu_downloadoptions", M_Menu_DownloadOptions_f);
1.1 root 3935: Cmd_AddCommand ("menu_credits", M_Menu_Credits_f );
3936: Cmd_AddCommand ("menu_multiplayer", M_Menu_Multiplayer_f );
3937: Cmd_AddCommand ("menu_video", M_Menu_Video_f);
3938: Cmd_AddCommand ("menu_options", M_Menu_Options_f);
3939: Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
3940: Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
3941: }
1.1.1.2 root 3942:
3943:
1.1 root 3944: /*
3945: =================
3946: M_Draw
3947: =================
3948: */
3949: void M_Draw (void)
3950: {
3951: if (cls.key_dest != key_menu)
3952: return;
1.1.1.2 root 3953:
1.1 root 3954: // repaint everything next frame
3955: SCR_DirtyScreen ();
1.1.1.2 root 3956:
1.1 root 3957: // dim everything behind it down
3958: if (cl.cinematictime > 0)
3959: re.DrawFill (0,0,viddef.width, viddef.height, 0);
3960: else
3961: re.DrawFadeScreen ();
1.1.1.2 root 3962:
1.1 root 3963: m_drawfunc ();
1.1.1.2 root 3964:
1.1 root 3965: // delay playing the enter sound until after the
3966: // menu has been drawn, to avoid delay while
3967: // caching images
3968: if (m_entersound)
3969: {
3970: S_StartLocalSound( menu_in_sound );
3971: m_entersound = false;
3972: }
3973: }
1.1.1.2 root 3974:
3975:
1.1 root 3976: /*
3977: =================
3978: M_Keydown
3979: =================
3980: */
3981: void M_Keydown (int key)
3982: {
3983: const char *s;
1.1.1.2 root 3984:
1.1 root 3985: if (m_keyfunc)
3986: if ( ( s = m_keyfunc( key ) ) != 0 )
3987: S_StartLocalSound( ( char * ) s );
3988: }
1.1.1.2 root 3989:
3990:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.