|
|
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: ! 72: // if this menu is allready 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 root 1620: void M_Credits_MenuDraw( void ) 1621: { 1622: int i, y; 1623: 1624: /* 1625: ** draw the credits 1626: */ 1627: for ( i = 0, y = viddef.height - ( ( cls.realtime - credits_start_time ) / 40.0F ); credits[i] && y < viddef.height; y += 10, i++ ) 1628: { 1629: int j, stringoffset = 0; 1630: int bold = false; 1631: 1632: if ( y <= -8 ) 1633: continue; 1634: 1635: if ( credits[i][0] == '+' ) 1636: { 1637: bold = true; 1638: stringoffset = 1; 1639: } 1640: else 1641: { 1642: bold = false; 1643: stringoffset = 0; 1644: } 1645: 1646: for ( j = 0; credits[i][j+stringoffset]; j++ ) 1647: { 1648: int x; 1649: 1650: x = ( viddef.width - strlen( credits[i] ) * 8 - stringoffset * 8 ) / 2 + ( j + stringoffset ) * 8; 1651: 1652: if ( bold ) 1653: re.DrawChar( x, y, credits[i][j+stringoffset] + 128 ); 1654: else 1655: re.DrawChar( x, y, credits[i][j+stringoffset] ); 1656: } 1657: } 1658: 1659: if ( y < 0 ) 1660: credits_start_time = cls.realtime; 1661: } 1662: 1663: const char *M_Credits_Key( int key ) 1664: { 1665: switch (key) 1666: { 1667: case K_ESCAPE: 1.1.1.2 ! root 1668: if (creditsBuffer) ! 1669: FS_FreeFile (creditsBuffer); 1.1 root 1670: M_PopMenu (); 1671: break; 1672: } 1673: 1674: return menu_out_sound; 1675: 1676: } 1677: 1.1.1.2 ! root 1678: extern int Developer_searchpath (int who); ! 1679: 1.1 root 1680: void M_Menu_Credits_f( void ) 1681: { 1.1.1.2 ! root 1682: int n; ! 1683: int count; ! 1684: char *p; ! 1685: int isdeveloper = 0; ! 1686: ! 1687: creditsBuffer = NULL; ! 1688: count = FS_LoadFile ("credits", &creditsBuffer); ! 1689: if (count != -1) ! 1690: { ! 1691: p = creditsBuffer; ! 1692: for (n = 0; n < 255; n++) ! 1693: { ! 1694: creditsIndex[n] = p; ! 1695: while (*p != '\r' && *p != '\n') ! 1696: { ! 1697: p++; ! 1698: if (--count == 0) ! 1699: break; ! 1700: } ! 1701: if (*p == '\r') ! 1702: { ! 1703: *p++ = 0; ! 1704: if (--count == 0) ! 1705: break; ! 1706: } ! 1707: *p++ = 0; ! 1708: if (--count == 0) ! 1709: break; ! 1710: } ! 1711: creditsIndex[++n] = 0; ! 1712: credits = creditsIndex; ! 1713: } ! 1714: else ! 1715: { ! 1716: isdeveloper = Developer_searchpath (1); ! 1717: ! 1718: if (isdeveloper == 1) // xatrix ! 1719: credits = xatcredits; ! 1720: else ! 1721: { ! 1722: credits = idcredits; ! 1723: } ! 1724: ! 1725: } ! 1726: 1.1 root 1727: credits_start_time = cls.realtime; 1728: M_PushMenu( M_Credits_MenuDraw, M_Credits_Key); 1729: } 1.1.1.2 ! root 1730: 1.1 root 1731: /* 1732: ============================================================================= 1733: 1734: GAME MENU 1735: 1736: ============================================================================= 1737: */ 1.1.1.2 ! root 1738: 1.1 root 1739: static int m_game_cursor; 1.1.1.2 ! root 1740: 1.1 root 1741: static menuframework_s s_game_menu; 1742: static menuaction_s s_easy_game_action; 1743: static menuaction_s s_medium_game_action; 1744: static menuaction_s s_hard_game_action; 1745: static menuaction_s s_load_game_action; 1746: static menuaction_s s_save_game_action; 1747: static menuaction_s s_credits_action; 1748: static menuseparator_s s_blankline; 1.1.1.2 ! root 1749: 1.1 root 1750: static void StartGame( void ) 1751: { 1752: // disable updates and start the cinematic going 1753: cl.servercount = -1; 1754: M_ForceMenuOff (); 1755: Cvar_SetValue( "deathmatch", 0 ); 1756: Cvar_SetValue( "coop", 0 ); 1757: Cbuf_AddText ("loading ; killserver ; wait ; newgame\n"); 1758: cls.key_dest = key_game; 1759: } 1.1.1.2 ! root 1760: 1.1 root 1761: static void EasyGameFunc( void *data ) 1762: { 1763: Cvar_ForceSet( "skill", "0" ); 1764: StartGame(); 1765: } 1.1.1.2 ! root 1766: 1.1 root 1767: static void MediumGameFunc( void *data ) 1768: { 1769: Cvar_ForceSet( "skill", "1" ); 1770: StartGame(); 1771: } 1.1.1.2 ! root 1772: 1.1 root 1773: static void HardGameFunc( void *data ) 1774: { 1775: Cvar_ForceSet( "skill", "2" ); 1776: StartGame(); 1777: } 1.1.1.2 ! root 1778: 1.1 root 1779: static void LoadGameFunc( void *unused ) 1780: { 1781: M_Menu_LoadGame_f (); 1782: } 1.1.1.2 ! root 1783: 1.1 root 1784: static void SaveGameFunc( void *unused ) 1785: { 1786: M_Menu_SaveGame_f(); 1787: } 1.1.1.2 ! root 1788: 1.1 root 1789: static void CreditsFunc( void *unused ) 1790: { 1791: M_Menu_Credits_f(); 1792: } 1.1.1.2 ! root 1793: 1.1 root 1794: void Game_MenuInit( void ) 1795: { 1796: static const char *difficulty_names[] = 1797: { 1798: "easy", 1799: "medium", 1800: "hard", 1801: 0 1802: }; 1.1.1.2 ! root 1803: 1.1 root 1804: s_game_menu.x = viddef.width * 0.50; 1805: s_game_menu.nitems = 0; 1.1.1.2 ! root 1806: 1.1 root 1807: s_easy_game_action.generic.type = MTYPE_ACTION; 1808: s_easy_game_action.generic.flags = QMF_LEFT_JUSTIFY; 1809: s_easy_game_action.generic.x = 0; 1810: s_easy_game_action.generic.y = 0; 1811: s_easy_game_action.generic.name = "easy"; 1812: s_easy_game_action.generic.callback = EasyGameFunc; 1.1.1.2 ! root 1813: 1.1 root 1814: s_medium_game_action.generic.type = MTYPE_ACTION; 1815: s_medium_game_action.generic.flags = QMF_LEFT_JUSTIFY; 1816: s_medium_game_action.generic.x = 0; 1817: s_medium_game_action.generic.y = 10; 1818: s_medium_game_action.generic.name = "medium"; 1819: s_medium_game_action.generic.callback = MediumGameFunc; 1.1.1.2 ! root 1820: 1.1 root 1821: s_hard_game_action.generic.type = MTYPE_ACTION; 1822: s_hard_game_action.generic.flags = QMF_LEFT_JUSTIFY; 1823: s_hard_game_action.generic.x = 0; 1824: s_hard_game_action.generic.y = 20; 1825: s_hard_game_action.generic.name = "hard"; 1826: s_hard_game_action.generic.callback = HardGameFunc; 1.1.1.2 ! root 1827: 1.1 root 1828: s_blankline.generic.type = MTYPE_SEPARATOR; 1829: 1830: s_load_game_action.generic.type = MTYPE_ACTION; 1831: s_load_game_action.generic.flags = QMF_LEFT_JUSTIFY; 1832: s_load_game_action.generic.x = 0; 1833: s_load_game_action.generic.y = 40; 1834: s_load_game_action.generic.name = "load game"; 1835: s_load_game_action.generic.callback = LoadGameFunc; 1.1.1.2 ! root 1836: 1.1 root 1837: s_save_game_action.generic.type = MTYPE_ACTION; 1838: s_save_game_action.generic.flags = QMF_LEFT_JUSTIFY; 1839: s_save_game_action.generic.x = 0; 1840: s_save_game_action.generic.y = 50; 1841: s_save_game_action.generic.name = "save game"; 1842: s_save_game_action.generic.callback = SaveGameFunc; 1843: 1844: s_credits_action.generic.type = MTYPE_ACTION; 1845: s_credits_action.generic.flags = QMF_LEFT_JUSTIFY; 1846: s_credits_action.generic.x = 0; 1847: s_credits_action.generic.y = 60; 1848: s_credits_action.generic.name = "credits"; 1849: s_credits_action.generic.callback = CreditsFunc; 1.1.1.2 ! root 1850: 1.1 root 1851: Menu_AddItem( &s_game_menu, ( void * ) &s_easy_game_action ); 1852: Menu_AddItem( &s_game_menu, ( void * ) &s_medium_game_action ); 1853: Menu_AddItem( &s_game_menu, ( void * ) &s_hard_game_action ); 1854: Menu_AddItem( &s_game_menu, ( void * ) &s_blankline ); 1855: Menu_AddItem( &s_game_menu, ( void * ) &s_load_game_action ); 1856: Menu_AddItem( &s_game_menu, ( void * ) &s_save_game_action ); 1857: Menu_AddItem( &s_game_menu, ( void * ) &s_blankline ); 1858: Menu_AddItem( &s_game_menu, ( void * ) &s_credits_action ); 1.1.1.2 ! root 1859: 1.1 root 1860: Menu_Center( &s_game_menu ); 1861: } 1.1.1.2 ! root 1862: 1.1 root 1863: void Game_MenuDraw( void ) 1864: { 1865: M_Banner( "m_banner_game" ); 1866: Menu_AdjustCursor( &s_game_menu, 1 ); 1867: Menu_Draw( &s_game_menu ); 1868: } 1.1.1.2 ! root 1869: 1.1 root 1870: const char *Game_MenuKey( int key ) 1871: { 1872: return Default_MenuKey( &s_game_menu, key ); 1873: } 1.1.1.2 ! root 1874: 1.1 root 1875: void M_Menu_Game_f (void) 1876: { 1877: Game_MenuInit(); 1878: M_PushMenu( Game_MenuDraw, Game_MenuKey ); 1879: m_game_cursor = 1; 1880: } 1.1.1.2 ! root 1881: 1.1 root 1882: /* 1883: ============================================================================= 1.1.1.2 ! root 1884: 1.1 root 1885: LOADGAME MENU 1.1.1.2 ! root 1886: 1.1 root 1887: ============================================================================= 1888: */ 1.1.1.2 ! root 1889: 1.1 root 1890: #define MAX_SAVEGAMES 15 1.1.1.2 ! root 1891: 1.1 root 1892: static menuframework_s s_savegame_menu; 1.1.1.2 ! root 1893: 1.1 root 1894: static menuframework_s s_loadgame_menu; 1895: static menuaction_s s_loadgame_actions[MAX_SAVEGAMES]; 1.1.1.2 ! root 1896: 1.1 root 1897: char m_savestrings[MAX_SAVEGAMES][32]; 1898: qboolean m_savevalid[MAX_SAVEGAMES]; 1.1.1.2 ! root 1899: 1.1 root 1900: void Create_Savestrings (void) 1901: { 1902: int i; 1903: FILE *f; 1904: char name[MAX_OSPATH]; 1.1.1.2 ! root 1905: 1.1 root 1906: for (i=0 ; i<MAX_SAVEGAMES ; i++) 1907: { 1908: Com_sprintf (name, sizeof(name), "%s/save/save%i/server.ssv", FS_Gamedir(), i); 1909: f = fopen (name, "rb"); 1910: if (!f) 1911: { 1912: strcpy (m_savestrings[i], "<EMPTY>"); 1913: m_savevalid[i] = false; 1914: } 1915: else 1916: { 1917: FS_Read (m_savestrings[i], sizeof(m_savestrings[i]), f); 1918: fclose (f); 1919: m_savevalid[i] = true; 1920: } 1921: } 1922: } 1.1.1.2 ! root 1923: 1.1 root 1924: void LoadGameCallback( void *self ) 1925: { 1926: menuaction_s *a = ( menuaction_s * ) self; 1.1.1.2 ! root 1927: 1.1 root 1928: if ( m_savevalid[ a->generic.localdata[0] ] ) 1929: Cbuf_AddText (va("load save%i\n", a->generic.localdata[0] ) ); 1930: M_ForceMenuOff (); 1931: } 1.1.1.2 ! root 1932: 1.1 root 1933: void LoadGame_MenuInit( void ) 1934: { 1935: int i; 1.1.1.2 ! root 1936: 1.1 root 1937: s_loadgame_menu.x = viddef.width / 2 - 120; 1938: s_loadgame_menu.y = viddef.height / 2 - 58; 1939: s_loadgame_menu.nitems = 0; 1.1.1.2 ! root 1940: 1.1 root 1941: Create_Savestrings(); 1.1.1.2 ! root 1942: 1.1 root 1943: for ( i = 0; i < MAX_SAVEGAMES; i++ ) 1944: { 1945: s_loadgame_actions[i].generic.name = m_savestrings[i]; 1946: s_loadgame_actions[i].generic.flags = QMF_LEFT_JUSTIFY; 1947: s_loadgame_actions[i].generic.localdata[0] = i; 1948: s_loadgame_actions[i].generic.callback = LoadGameCallback; 1.1.1.2 ! root 1949: 1.1 root 1950: s_loadgame_actions[i].generic.x = 0; 1951: s_loadgame_actions[i].generic.y = ( i ) * 10; 1952: if (i>0) // separate from autosave 1953: s_loadgame_actions[i].generic.y += 10; 1.1.1.2 ! root 1954: 1.1 root 1955: s_loadgame_actions[i].generic.type = MTYPE_ACTION; 1.1.1.2 ! root 1956: 1.1 root 1957: Menu_AddItem( &s_loadgame_menu, &s_loadgame_actions[i] ); 1958: } 1959: } 1.1.1.2 ! root 1960: 1.1 root 1961: void LoadGame_MenuDraw( void ) 1962: { 1963: M_Banner( "m_banner_load_game" ); 1964: // Menu_AdjustCursor( &s_loadgame_menu, 1 ); 1965: Menu_Draw( &s_loadgame_menu ); 1966: } 1.1.1.2 ! root 1967: 1.1 root 1968: const char *LoadGame_MenuKey( int key ) 1969: { 1970: if ( key == K_ESCAPE || key == K_ENTER ) 1971: { 1972: s_savegame_menu.cursor = s_loadgame_menu.cursor - 1; 1973: if ( s_savegame_menu.cursor < 0 ) 1974: s_savegame_menu.cursor = 0; 1975: } 1976: return Default_MenuKey( &s_loadgame_menu, key ); 1977: } 1.1.1.2 ! root 1978: 1.1 root 1979: void M_Menu_LoadGame_f (void) 1980: { 1981: LoadGame_MenuInit(); 1982: M_PushMenu( LoadGame_MenuDraw, LoadGame_MenuKey ); 1983: } 1.1.1.2 ! root 1984: ! 1985: 1.1 root 1986: /* 1987: ============================================================================= 1.1.1.2 ! root 1988: 1.1 root 1989: SAVEGAME MENU 1.1.1.2 ! root 1990: 1.1 root 1991: ============================================================================= 1992: */ 1993: static menuframework_s s_savegame_menu; 1994: static menuaction_s s_savegame_actions[MAX_SAVEGAMES]; 1.1.1.2 ! root 1995: 1.1 root 1996: void SaveGameCallback( void *self ) 1997: { 1998: menuaction_s *a = ( menuaction_s * ) self; 1.1.1.2 ! root 1999: 1.1 root 2000: Cbuf_AddText (va("save save%i\n", a->generic.localdata[0] )); 2001: M_ForceMenuOff (); 2002: } 1.1.1.2 ! root 2003: 1.1 root 2004: void SaveGame_MenuDraw( void ) 2005: { 2006: M_Banner( "m_banner_save_game" ); 2007: Menu_AdjustCursor( &s_savegame_menu, 1 ); 2008: Menu_Draw( &s_savegame_menu ); 2009: } 1.1.1.2 ! root 2010: 1.1 root 2011: void SaveGame_MenuInit( void ) 2012: { 2013: int i; 1.1.1.2 ! root 2014: 1.1 root 2015: s_savegame_menu.x = viddef.width / 2 - 120; 2016: s_savegame_menu.y = viddef.height / 2 - 58; 2017: s_savegame_menu.nitems = 0; 1.1.1.2 ! root 2018: 1.1 root 2019: Create_Savestrings(); 1.1.1.2 ! root 2020: 1.1 root 2021: // don't include the autosave slot 2022: for ( i = 0; i < MAX_SAVEGAMES-1; i++ ) 2023: { 2024: s_savegame_actions[i].generic.name = m_savestrings[i+1]; 2025: s_savegame_actions[i].generic.localdata[0] = i+1; 2026: s_savegame_actions[i].generic.flags = QMF_LEFT_JUSTIFY; 2027: s_savegame_actions[i].generic.callback = SaveGameCallback; 1.1.1.2 ! root 2028: 1.1 root 2029: s_savegame_actions[i].generic.x = 0; 2030: s_savegame_actions[i].generic.y = ( i ) * 10; 1.1.1.2 ! root 2031: 1.1 root 2032: s_savegame_actions[i].generic.type = MTYPE_ACTION; 1.1.1.2 ! root 2033: 1.1 root 2034: Menu_AddItem( &s_savegame_menu, &s_savegame_actions[i] ); 2035: } 2036: } 1.1.1.2 ! root 2037: 1.1 root 2038: const char *SaveGame_MenuKey( int key ) 2039: { 2040: if ( key == K_ENTER || key == K_ESCAPE ) 2041: { 2042: s_loadgame_menu.cursor = s_savegame_menu.cursor - 1; 2043: if ( s_loadgame_menu.cursor < 0 ) 2044: s_loadgame_menu.cursor = 0; 2045: } 2046: return Default_MenuKey( &s_savegame_menu, key ); 2047: } 1.1.1.2 ! root 2048: 1.1 root 2049: void M_Menu_SaveGame_f (void) 2050: { 2051: if (!Com_ServerState()) 2052: return; // not playing a game 1.1.1.2 ! root 2053: 1.1 root 2054: SaveGame_MenuInit(); 2055: M_PushMenu( SaveGame_MenuDraw, SaveGame_MenuKey ); 2056: Create_Savestrings (); 2057: } 1.1.1.2 ! root 2058: ! 2059: 1.1 root 2060: /* 2061: ============================================================================= 1.1.1.2 ! root 2062: 1.1 root 2063: JOIN SERVER MENU 1.1.1.2 ! root 2064: 1.1 root 2065: ============================================================================= 2066: */ 2067: #define MAX_LOCAL_SERVERS 8 1.1.1.2 ! root 2068: 1.1 root 2069: static menuframework_s s_joinserver_menu; 2070: static menuseparator_s s_joinserver_server_title; 2071: static menuaction_s s_joinserver_search_action; 2072: static menuaction_s s_joinserver_address_book_action; 2073: static menuaction_s s_joinserver_server_actions[MAX_LOCAL_SERVERS]; 2074: 2075: int m_num_servers; 2076: #define NO_SERVER_STRING "<no server>" 2077: 2078: // user readable information 2079: static char local_server_names[MAX_LOCAL_SERVERS][80]; 2080: 2081: // network address 2082: static netadr_t local_server_netadr[MAX_LOCAL_SERVERS]; 2083: 2084: void M_AddToServerList (netadr_t adr, char *info) 2085: { 2086: int i; 2087: 2088: if (m_num_servers == MAX_LOCAL_SERVERS) 2089: return; 2090: while ( *info == ' ' ) 2091: info++; 2092: 2093: // ignore if duplicated 2094: for (i=0 ; i<m_num_servers ; i++) 2095: if (!strcmp(info, local_server_names[i])) 2096: return; 2097: 2098: local_server_netadr[m_num_servers] = adr; 2099: strncpy (local_server_names[m_num_servers], info, sizeof(local_server_names[0])-1); 2100: m_num_servers++; 2101: } 2102: 1.1.1.2 ! root 2103: 1.1 root 2104: void JoinServerFunc( void *self ) 2105: { 2106: char buffer[128]; 2107: int index; 2108: 2109: index = ( menuaction_s * ) self - s_joinserver_server_actions; 2110: 2111: if ( Q_stricmp( local_server_names[index], NO_SERVER_STRING ) == 0 ) 2112: return; 2113: 2114: if (index >= m_num_servers) 2115: return; 2116: 2117: Com_sprintf (buffer, sizeof(buffer), "connect %s\n", NET_AdrToString (local_server_netadr[index])); 2118: Cbuf_AddText (buffer); 2119: M_ForceMenuOff (); 2120: } 1.1.1.2 ! root 2121: 1.1 root 2122: void AddressBookFunc( void *self ) 2123: { 2124: M_Menu_AddressBook_f(); 2125: } 1.1.1.2 ! root 2126: 1.1 root 2127: void NullCursorDraw( void *self ) 2128: { 2129: } 2130: 2131: void SearchLocalGames( void ) 2132: { 2133: int i; 2134: 2135: m_num_servers = 0; 2136: for (i=0 ; i<MAX_LOCAL_SERVERS ; i++) 2137: strcpy (local_server_names[i], NO_SERVER_STRING); 2138: 2139: M_DrawTextBox( 8, 120 - 48, 36, 3 ); 2140: M_Print( 16 + 16, 120 - 48 + 8, "Searching for local servers, this" ); 2141: M_Print( 16 + 16, 120 - 48 + 16, "could take up to a minute, so" ); 2142: M_Print( 16 + 16, 120 - 48 + 24, "please be patient." ); 2143: 2144: // the text box won't show up unless we do a buffer swap 2145: re.EndFrame(); 2146: 2147: // send out info packets 2148: CL_PingServers_f(); 2149: } 1.1.1.2 ! root 2150: 1.1 root 2151: void SearchLocalGamesFunc( void *self ) 2152: { 2153: SearchLocalGames(); 2154: } 1.1.1.2 ! root 2155: 1.1 root 2156: void JoinServer_MenuInit( void ) 2157: { 2158: int i; 1.1.1.2 ! root 2159: 1.1 root 2160: s_joinserver_menu.x = viddef.width * 0.50 - 120; 2161: s_joinserver_menu.nitems = 0; 1.1.1.2 ! root 2162: 1.1 root 2163: s_joinserver_address_book_action.generic.type = MTYPE_ACTION; 2164: s_joinserver_address_book_action.generic.name = "address book"; 2165: s_joinserver_address_book_action.generic.flags = QMF_LEFT_JUSTIFY; 2166: s_joinserver_address_book_action.generic.x = 0; 2167: s_joinserver_address_book_action.generic.y = 0; 2168: s_joinserver_address_book_action.generic.callback = AddressBookFunc; 1.1.1.2 ! root 2169: 1.1 root 2170: s_joinserver_search_action.generic.type = MTYPE_ACTION; 2171: s_joinserver_search_action.generic.name = "refresh server list"; 2172: s_joinserver_search_action.generic.flags = QMF_LEFT_JUSTIFY; 2173: s_joinserver_search_action.generic.x = 0; 2174: s_joinserver_search_action.generic.y = 10; 2175: s_joinserver_search_action.generic.callback = SearchLocalGamesFunc; 2176: s_joinserver_search_action.generic.statusbar = "search for servers"; 1.1.1.2 ! root 2177: 1.1 root 2178: s_joinserver_server_title.generic.type = MTYPE_SEPARATOR; 2179: s_joinserver_server_title.generic.name = "connect to..."; 2180: s_joinserver_server_title.generic.x = 80; 2181: s_joinserver_server_title.generic.y = 30; 1.1.1.2 ! root 2182: 1.1 root 2183: for ( i = 0; i < MAX_LOCAL_SERVERS; i++ ) 2184: { 2185: s_joinserver_server_actions[i].generic.type = MTYPE_ACTION; 2186: strcpy (local_server_names[i], NO_SERVER_STRING); 2187: s_joinserver_server_actions[i].generic.name = local_server_names[i]; 2188: s_joinserver_server_actions[i].generic.flags = QMF_LEFT_JUSTIFY; 2189: s_joinserver_server_actions[i].generic.x = 0; 2190: s_joinserver_server_actions[i].generic.y = 40 + i*10; 2191: s_joinserver_server_actions[i].generic.callback = JoinServerFunc; 2192: s_joinserver_server_actions[i].generic.statusbar = "press ENTER to connect"; 2193: } 1.1.1.2 ! root 2194: 1.1 root 2195: Menu_AddItem( &s_joinserver_menu, &s_joinserver_address_book_action ); 2196: Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_title ); 2197: Menu_AddItem( &s_joinserver_menu, &s_joinserver_search_action ); 1.1.1.2 ! root 2198: 1.1 root 2199: for ( i = 0; i < 8; i++ ) 2200: Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_actions[i] ); 1.1.1.2 ! root 2201: 1.1 root 2202: Menu_Center( &s_joinserver_menu ); 2203: 2204: SearchLocalGames(); 2205: } 1.1.1.2 ! root 2206: 1.1 root 2207: void JoinServer_MenuDraw(void) 2208: { 2209: M_Banner( "m_banner_join_server" ); 2210: Menu_Draw( &s_joinserver_menu ); 2211: } 1.1.1.2 ! root 2212: ! 2213: 1.1 root 2214: const char *JoinServer_MenuKey( int key ) 2215: { 2216: return Default_MenuKey( &s_joinserver_menu, key ); 2217: } 1.1.1.2 ! root 2218: 1.1 root 2219: void M_Menu_JoinServer_f (void) 2220: { 2221: JoinServer_MenuInit(); 2222: M_PushMenu( JoinServer_MenuDraw, JoinServer_MenuKey ); 2223: } 2224: 1.1.1.2 ! root 2225: 1.1 root 2226: /* 2227: ============================================================================= 1.1.1.2 ! root 2228: 1.1 root 2229: START SERVER MENU 1.1.1.2 ! root 2230: 1.1 root 2231: ============================================================================= 2232: */ 2233: static menuframework_s s_startserver_menu; 2234: static char **mapnames; 2235: static int nummaps; 1.1.1.2 ! root 2236: 1.1 root 2237: static menuaction_s s_startserver_start_action; 2238: static menuaction_s s_startserver_dmoptions_action; 2239: static menufield_s s_timelimit_field; 2240: static menufield_s s_fraglimit_field; 2241: static menufield_s s_maxclients_field; 2242: static menufield_s s_hostname_field; 2243: static menulist_s s_startmap_list; 2244: static menulist_s s_rules_box; 2245: 2246: void DMOptionsFunc( void *self ) 2247: { 2248: if (s_rules_box.curvalue == 1) 2249: return; 2250: M_Menu_DMOptions_f(); 2251: } 2252: 2253: void RulesChangeFunc ( void *self ) 2254: { 2255: // DM 2256: if (s_rules_box.curvalue == 0) 2257: { 2258: s_maxclients_field.generic.statusbar = NULL; 2259: s_startserver_dmoptions_action.generic.statusbar = NULL; 2260: } 2261: else // coop 2262: { 2263: s_maxclients_field.generic.statusbar = "4 maximum for cooperative"; 2264: if (atoi(s_maxclients_field.buffer) > 4) 2265: strcpy( s_maxclients_field.buffer, "4" ); 2266: s_startserver_dmoptions_action.generic.statusbar = "N/A for cooperative"; 2267: } 2268: } 1.1.1.2 ! root 2269: 1.1 root 2270: void StartServerActionFunc( void *self ) 2271: { 2272: char startmap[1024]; 2273: int timelimit; 2274: int fraglimit; 2275: int maxclients; 2276: char *spot; 1.1.1.2 ! root 2277: 1.1 root 2278: strcpy( startmap, strchr( mapnames[s_startmap_list.curvalue], '\n' ) + 1 ); 2279: 2280: maxclients = atoi( s_maxclients_field.buffer ); 2281: timelimit = atoi( s_timelimit_field.buffer ); 2282: fraglimit = atoi( s_fraglimit_field.buffer ); 2283: 2284: Cvar_SetValue( "maxclients", ClampCvar( 0, maxclients, maxclients ) ); 2285: Cvar_SetValue ("timelimit", ClampCvar( 0, timelimit, timelimit ) ); 2286: Cvar_SetValue ("fraglimit", ClampCvar( 0, fraglimit, fraglimit ) ); 2287: Cvar_Set("hostname", s_hostname_field.buffer ); 2288: Cvar_SetValue ("deathmatch", !s_rules_box.curvalue ); 2289: Cvar_SetValue ("coop", s_rules_box.curvalue ); 2290: 2291: spot = NULL; 2292: if (s_rules_box.curvalue) 2293: { 1.1.1.2 ! root 2294: if(Q_stricmp(startmap, "bunk1") == 0) ! 2295: spot = "start"; ! 2296: else if(Q_stricmp(startmap, "mintro") == 0) ! 2297: spot = "start"; ! 2298: else if(Q_stricmp(startmap, "fact1") == 0) ! 2299: spot = "start"; ! 2300: else if(Q_stricmp(startmap, "power1") == 0) ! 2301: spot = "pstart"; ! 2302: else if(Q_stricmp(startmap, "biggun") == 0) ! 2303: spot = "bstart"; ! 2304: else if(Q_stricmp(startmap, "hangar1") == 0) ! 2305: spot = "unitstart"; ! 2306: else if(Q_stricmp(startmap, "city1") == 0) ! 2307: spot = "unitstart"; ! 2308: else if(Q_stricmp(startmap, "boss1") == 0) ! 2309: spot = "bosstart"; 1.1 root 2310: } 2311: 2312: if (spot) 2313: { 2314: if (Com_ServerState()) 2315: Cbuf_AddText ("disconnect\n"); 2316: Cbuf_AddText (va("gamemap \"*%s$%s\"\n", startmap, spot)); 2317: } 2318: else 2319: { 2320: Cbuf_AddText (va("map %s\n", startmap)); 2321: } 2322: 2323: M_ForceMenuOff (); 2324: } 2325: 2326: void StartServer_MenuInit( void ) 2327: { 2328: static const char *dm_coop_names[] = 2329: { 2330: "deathmatch", 2331: "cooperative", 2332: 0 2333: }; 2334: char *buffer; 2335: char mapsname[1024]; 2336: char *s; 2337: int length; 2338: int i; 2339: FILE *fp; 2340: 2341: /* 2342: ** load the list of map names 2343: */ 2344: Com_sprintf( mapsname, sizeof( mapsname ), "%s/maps.lst", FS_Gamedir() ); 2345: if ( ( fp = fopen( mapsname, "rb" ) ) == 0 ) 2346: { 2347: if ( ( length = FS_LoadFile( "maps.lst", ( void ** ) &buffer ) ) == -1 ) 2348: Com_Error( ERR_DROP, "couldn't find maps.lst\n" ); 2349: } 2350: else 2351: { 1.1.1.2 ! root 2352: #ifdef _WIN32 1.1 root 2353: length = filelength( fileno( fp ) ); 1.1.1.2 ! root 2354: #else ! 2355: fseek(fp, 0, SEEK_END); ! 2356: length = ftell(fp); ! 2357: fseek(fp, 0, SEEK_SET); ! 2358: #endif 1.1 root 2359: buffer = malloc( length ); 2360: fread( buffer, length, 1, fp ); 2361: } 2362: 2363: s = buffer; 2364: 2365: i = 0; 2366: while ( i < length ) 2367: { 2368: if ( s[i] == '\r' ) 2369: nummaps++; 2370: i++; 2371: } 2372: 2373: if ( nummaps == 0 ) 2374: Com_Error( ERR_DROP, "no maps in maps.lst\n" ); 2375: 2376: mapnames = malloc( sizeof( char * ) * ( nummaps + 1 ) ); 2377: memset( mapnames, 0, sizeof( char * ) * ( nummaps + 1 ) ); 2378: 2379: s = buffer; 2380: 2381: for ( i = 0; i < nummaps; i++ ) 2382: { 2383: char shortname[MAX_TOKEN_CHARS]; 2384: char longname[MAX_TOKEN_CHARS]; 2385: char scratch[200]; 2386: int j, l; 2387: 2388: strcpy( shortname, COM_Parse( &s ) ); 2389: l = strlen(shortname); 2390: for (j=0 ; j<l ; j++) 2391: shortname[j] = toupper(shortname[j]); 2392: strcpy( longname, COM_Parse( &s ) ); 2393: Com_sprintf( scratch, sizeof( scratch ), "%s\n%s", longname, shortname ); 2394: 2395: mapnames[i] = malloc( strlen( scratch ) + 1 ); 2396: strcpy( mapnames[i], scratch ); 2397: } 2398: mapnames[nummaps] = 0; 2399: 2400: if ( fp != 0 ) 2401: { 2402: fp = 0; 2403: free( buffer ); 2404: } 2405: else 2406: { 2407: FS_FreeFile( buffer ); 2408: } 2409: 2410: /* 2411: ** initialize the menu stuff 2412: */ 2413: s_startserver_menu.x = viddef.width * 0.50; 2414: s_startserver_menu.nitems = 0; 1.1.1.2 ! root 2415: 1.1 root 2416: s_startmap_list.generic.type = MTYPE_SPINCONTROL; 2417: s_startmap_list.generic.x = 0; 2418: s_startmap_list.generic.y = 0; 2419: s_startmap_list.generic.name = "initial map"; 2420: s_startmap_list.itemnames = mapnames; 1.1.1.2 ! root 2421: 1.1 root 2422: s_rules_box.generic.type = MTYPE_SPINCONTROL; 2423: s_rules_box.generic.x = 0; 2424: s_rules_box.generic.y = 20; 2425: s_rules_box.generic.name = "rules"; 2426: s_rules_box.itemnames = dm_coop_names; 2427: if (Cvar_VariableValue("coop")) 2428: s_rules_box.curvalue = 1; 2429: else 2430: s_rules_box.curvalue = 0; 2431: s_rules_box.generic.callback = RulesChangeFunc; 1.1.1.2 ! root 2432: 1.1 root 2433: s_timelimit_field.generic.type = MTYPE_FIELD; 2434: s_timelimit_field.generic.name = "time limit"; 2435: s_timelimit_field.generic.flags = QMF_NUMBERSONLY; 2436: s_timelimit_field.generic.x = 0; 2437: s_timelimit_field.generic.y = 36; 2438: s_timelimit_field.generic.statusbar = "0 = no limit"; 2439: s_timelimit_field.length = 3; 2440: s_timelimit_field.visible_length = 3; 2441: strcpy( s_timelimit_field.buffer, Cvar_VariableString("timelimit") ); 1.1.1.2 ! root 2442: 1.1 root 2443: s_fraglimit_field.generic.type = MTYPE_FIELD; 2444: s_fraglimit_field.generic.name = "frag limit"; 2445: s_fraglimit_field.generic.flags = QMF_NUMBERSONLY; 2446: s_fraglimit_field.generic.x = 0; 2447: s_fraglimit_field.generic.y = 54; 2448: s_fraglimit_field.generic.statusbar = "0 = no limit"; 2449: s_fraglimit_field.length = 3; 2450: s_fraglimit_field.visible_length = 3; 2451: strcpy( s_fraglimit_field.buffer, Cvar_VariableString("fraglimit") ); 2452: 2453: /* 2454: ** maxclients determines the maximum number of players that can join 2455: ** the game. If maxclients is only "1" then we should default the menu 2456: ** option to 8 players, otherwise use whatever its current value is. 2457: ** Clamping will be done when the server is actually started. 2458: */ 2459: s_maxclients_field.generic.type = MTYPE_FIELD; 2460: s_maxclients_field.generic.name = "max players"; 2461: s_maxclients_field.generic.flags = QMF_NUMBERSONLY; 2462: s_maxclients_field.generic.x = 0; 2463: s_maxclients_field.generic.y = 72; 2464: s_maxclients_field.generic.statusbar = NULL; 2465: s_maxclients_field.length = 3; 2466: s_maxclients_field.visible_length = 3; 2467: if ( Cvar_VariableValue( "maxclients" ) == 1 ) 2468: strcpy( s_maxclients_field.buffer, "8" ); 2469: else 2470: strcpy( s_maxclients_field.buffer, Cvar_VariableString("maxclients") ); 2471: 2472: s_hostname_field.generic.type = MTYPE_FIELD; 2473: s_hostname_field.generic.name = "hostname"; 2474: s_hostname_field.generic.flags = 0; 2475: s_hostname_field.generic.x = 0; 2476: s_hostname_field.generic.y = 90; 2477: s_hostname_field.generic.statusbar = NULL; 2478: s_hostname_field.length = 12; 2479: s_hostname_field.visible_length = 12; 2480: strcpy( s_hostname_field.buffer, Cvar_VariableString("hostname") ); 2481: 2482: s_startserver_dmoptions_action.generic.type = MTYPE_ACTION; 2483: s_startserver_dmoptions_action.generic.name = " deathmatch flags"; 2484: s_startserver_dmoptions_action.generic.flags= QMF_LEFT_JUSTIFY; 2485: s_startserver_dmoptions_action.generic.x = 24; 2486: s_startserver_dmoptions_action.generic.y = 108; 2487: s_startserver_dmoptions_action.generic.statusbar = NULL; 2488: s_startserver_dmoptions_action.generic.callback = DMOptionsFunc; 2489: 2490: s_startserver_start_action.generic.type = MTYPE_ACTION; 2491: s_startserver_start_action.generic.name = " begin"; 2492: s_startserver_start_action.generic.flags= QMF_LEFT_JUSTIFY; 2493: s_startserver_start_action.generic.x = 24; 2494: s_startserver_start_action.generic.y = 128; 2495: s_startserver_start_action.generic.callback = StartServerActionFunc; 2496: 2497: Menu_AddItem( &s_startserver_menu, &s_startmap_list ); 2498: Menu_AddItem( &s_startserver_menu, &s_rules_box ); 2499: Menu_AddItem( &s_startserver_menu, &s_timelimit_field ); 2500: Menu_AddItem( &s_startserver_menu, &s_fraglimit_field ); 2501: Menu_AddItem( &s_startserver_menu, &s_maxclients_field ); 2502: Menu_AddItem( &s_startserver_menu, &s_hostname_field ); 2503: Menu_AddItem( &s_startserver_menu, &s_startserver_dmoptions_action ); 2504: Menu_AddItem( &s_startserver_menu, &s_startserver_start_action ); 2505: 2506: Menu_Center( &s_startserver_menu ); 2507: 2508: // call this now to set proper inital state 2509: RulesChangeFunc ( NULL ); 2510: } 1.1.1.2 ! root 2511: 1.1 root 2512: void StartServer_MenuDraw(void) 2513: { 2514: Menu_Draw( &s_startserver_menu ); 2515: } 1.1.1.2 ! root 2516: 1.1 root 2517: const char *StartServer_MenuKey( int key ) 2518: { 2519: if ( key == K_ESCAPE ) 2520: { 2521: if ( mapnames ) 2522: { 2523: int i; 2524: 2525: for ( i = 0; i < nummaps; i++ ) 2526: free( mapnames[i] ); 2527: free( mapnames ); 2528: } 2529: mapnames = 0; 2530: nummaps = 0; 2531: } 1.1.1.2 ! root 2532: 1.1 root 2533: return Default_MenuKey( &s_startserver_menu, key ); 2534: } 1.1.1.2 ! root 2535: 1.1 root 2536: void M_Menu_StartServer_f (void) 2537: { 2538: StartServer_MenuInit(); 2539: M_PushMenu( StartServer_MenuDraw, StartServer_MenuKey ); 2540: } 1.1.1.2 ! root 2541: 1.1 root 2542: /* 2543: ============================================================================= 2544: 2545: DMOPTIONS BOOK MENU 2546: 2547: ============================================================================= 2548: */ 2549: static char dmoptions_statusbar[128]; 2550: 2551: static menuframework_s s_dmoptions_menu; 2552: 2553: static menulist_s s_friendlyfire_box; 2554: static menulist_s s_falls_box; 2555: static menulist_s s_weapons_stay_box; 2556: static menulist_s s_instant_powerups_box; 2557: static menulist_s s_powerups_box; 2558: static menulist_s s_health_box; 2559: static menulist_s s_spawn_farthest_box; 2560: static menulist_s s_teamplay_box; 2561: static menulist_s s_samelevel_box; 2562: static menulist_s s_force_respawn_box; 2563: static menulist_s s_armor_box; 2564: static menulist_s s_allow_exit_box; 2565: static menulist_s s_infinite_ammo_box; 2566: static menulist_s s_fixed_fov_box; 2567: static menulist_s s_quad_drop_box; 2568: 2569: static void DMFlagCallback( void *self ) 2570: { 2571: menulist_s *f = ( menulist_s * ) self; 2572: int flags; 2573: int bit = 0; 2574: 2575: flags = Cvar_VariableValue( "dmflags" ); 2576: 2577: if ( f == &s_friendlyfire_box ) 2578: { 2579: if ( f->curvalue ) 2580: flags &= ~DF_NO_FRIENDLY_FIRE; 2581: else 2582: flags |= DF_NO_FRIENDLY_FIRE; 2583: goto setvalue; 2584: } 2585: else if ( f == &s_falls_box ) 2586: { 2587: if ( f->curvalue ) 2588: flags &= ~DF_NO_FALLING; 2589: else 2590: flags |= DF_NO_FALLING; 2591: goto setvalue; 2592: } 2593: else if ( f == &s_weapons_stay_box ) 2594: { 2595: bit = DF_WEAPONS_STAY; 2596: } 2597: else if ( f == &s_instant_powerups_box ) 2598: { 2599: bit = DF_INSTANT_ITEMS; 2600: } 2601: else if ( f == &s_allow_exit_box ) 2602: { 2603: bit = DF_ALLOW_EXIT; 2604: } 2605: else if ( f == &s_powerups_box ) 2606: { 2607: if ( f->curvalue ) 2608: flags &= ~DF_NO_ITEMS; 2609: else 2610: flags |= DF_NO_ITEMS; 2611: goto setvalue; 2612: } 2613: else if ( f == &s_health_box ) 2614: { 2615: if ( f->curvalue ) 2616: flags &= ~DF_NO_HEALTH; 2617: else 2618: flags |= DF_NO_HEALTH; 2619: goto setvalue; 2620: } 2621: else if ( f == &s_spawn_farthest_box ) 2622: { 2623: bit = DF_SPAWN_FARTHEST; 2624: } 2625: else if ( f == &s_teamplay_box ) 2626: { 2627: if ( f->curvalue == 1 ) 2628: { 2629: flags |= DF_SKINTEAMS; 2630: flags &= ~DF_MODELTEAMS; 2631: } 2632: else if ( f->curvalue == 2 ) 2633: { 2634: flags |= DF_MODELTEAMS; 2635: flags &= ~DF_SKINTEAMS; 2636: } 2637: else 2638: { 2639: flags &= ~( DF_MODELTEAMS | DF_SKINTEAMS ); 2640: } 2641: 2642: goto setvalue; 2643: } 2644: else if ( f == &s_samelevel_box ) 2645: { 2646: bit = DF_SAME_LEVEL; 2647: } 2648: else if ( f == &s_force_respawn_box ) 2649: { 2650: bit = DF_FORCE_RESPAWN; 2651: } 2652: else if ( f == &s_armor_box ) 2653: { 2654: if ( f->curvalue ) 2655: flags &= ~DF_NO_ARMOR; 2656: else 2657: flags |= DF_NO_ARMOR; 2658: goto setvalue; 2659: } 2660: else if ( f == &s_infinite_ammo_box ) 2661: { 2662: bit = DF_INFINITE_AMMO; 2663: } 2664: else if ( f == &s_fixed_fov_box ) 2665: { 2666: bit = DF_FIXED_FOV; 2667: } 2668: else if ( f == &s_quad_drop_box ) 2669: { 2670: bit = DF_QUAD_DROP; 2671: } 2672: 2673: 2674: if ( f ) 2675: { 2676: if ( f->curvalue == 0 ) 2677: flags &= ~bit; 2678: else 2679: flags |= bit; 2680: } 2681: 2682: setvalue: 2683: Cvar_SetValue ("dmflags", flags); 2684: 2685: Com_sprintf( dmoptions_statusbar, sizeof( dmoptions_statusbar ), "dmflags = %d", flags ); 2686: 2687: } 2688: 2689: void DMOptions_MenuInit( void ) 2690: { 2691: static const char *yes_no_names[] = 2692: { 2693: "no", "yes", 0 2694: }; 2695: static const char *teamplay_names[] = 2696: { 2697: "disabled", "by skin", "by model", 0 2698: }; 2699: int dmflags = Cvar_VariableValue( "dmflags" ); 2700: int y = 0; 2701: 2702: s_dmoptions_menu.x = viddef.width * 0.50; 2703: s_dmoptions_menu.nitems = 0; 2704: 2705: s_falls_box.generic.type = MTYPE_SPINCONTROL; 2706: s_falls_box.generic.x = 0; 2707: s_falls_box.generic.y = y; 2708: s_falls_box.generic.name = "falling damage"; 2709: s_falls_box.generic.callback = DMFlagCallback; 2710: s_falls_box.itemnames = yes_no_names; 2711: s_falls_box.curvalue = ( dmflags & DF_NO_FALLING ) == 0; 2712: 2713: s_weapons_stay_box.generic.type = MTYPE_SPINCONTROL; 2714: s_weapons_stay_box.generic.x = 0; 2715: s_weapons_stay_box.generic.y = y += 10; 2716: s_weapons_stay_box.generic.name = "weapons stay"; 2717: s_weapons_stay_box.generic.callback = DMFlagCallback; 2718: s_weapons_stay_box.itemnames = yes_no_names; 2719: s_weapons_stay_box.curvalue = ( dmflags & DF_WEAPONS_STAY ) != 0; 2720: 2721: s_instant_powerups_box.generic.type = MTYPE_SPINCONTROL; 2722: s_instant_powerups_box.generic.x = 0; 2723: s_instant_powerups_box.generic.y = y += 10; 2724: s_instant_powerups_box.generic.name = "instant powerups"; 2725: s_instant_powerups_box.generic.callback = DMFlagCallback; 2726: s_instant_powerups_box.itemnames = yes_no_names; 2727: s_instant_powerups_box.curvalue = ( dmflags & DF_INSTANT_ITEMS ) != 0; 2728: 2729: s_powerups_box.generic.type = MTYPE_SPINCONTROL; 2730: s_powerups_box.generic.x = 0; 2731: s_powerups_box.generic.y = y += 10; 2732: s_powerups_box.generic.name = "allow powerups"; 2733: s_powerups_box.generic.callback = DMFlagCallback; 2734: s_powerups_box.itemnames = yes_no_names; 2735: s_powerups_box.curvalue = ( dmflags & DF_NO_ITEMS ) == 0; 2736: 2737: s_health_box.generic.type = MTYPE_SPINCONTROL; 2738: s_health_box.generic.x = 0; 2739: s_health_box.generic.y = y += 10; 2740: s_health_box.generic.callback = DMFlagCallback; 2741: s_health_box.generic.name = "allow health"; 2742: s_health_box.itemnames = yes_no_names; 2743: s_health_box.curvalue = ( dmflags & DF_NO_HEALTH ) == 0; 2744: 2745: s_armor_box.generic.type = MTYPE_SPINCONTROL; 2746: s_armor_box.generic.x = 0; 2747: s_armor_box.generic.y = y += 10; 2748: s_armor_box.generic.name = "allow armor"; 2749: s_armor_box.generic.callback = DMFlagCallback; 2750: s_armor_box.itemnames = yes_no_names; 2751: s_armor_box.curvalue = ( dmflags & DF_NO_ARMOR ) == 0; 2752: 2753: s_spawn_farthest_box.generic.type = MTYPE_SPINCONTROL; 2754: s_spawn_farthest_box.generic.x = 0; 2755: s_spawn_farthest_box.generic.y = y += 10; 2756: s_spawn_farthest_box.generic.name = "spawn farthest"; 2757: s_spawn_farthest_box.generic.callback = DMFlagCallback; 2758: s_spawn_farthest_box.itemnames = yes_no_names; 2759: s_spawn_farthest_box.curvalue = ( dmflags & DF_SPAWN_FARTHEST ) != 0; 2760: 2761: s_samelevel_box.generic.type = MTYPE_SPINCONTROL; 2762: s_samelevel_box.generic.x = 0; 2763: s_samelevel_box.generic.y = y += 10; 2764: s_samelevel_box.generic.name = "same map"; 2765: s_samelevel_box.generic.callback = DMFlagCallback; 2766: s_samelevel_box.itemnames = yes_no_names; 2767: s_samelevel_box.curvalue = ( dmflags & DF_SAME_LEVEL ) != 0; 2768: 2769: s_force_respawn_box.generic.type = MTYPE_SPINCONTROL; 2770: s_force_respawn_box.generic.x = 0; 2771: s_force_respawn_box.generic.y = y += 10; 2772: s_force_respawn_box.generic.name = "force respawn"; 2773: s_force_respawn_box.generic.callback = DMFlagCallback; 2774: s_force_respawn_box.itemnames = yes_no_names; 2775: s_force_respawn_box.curvalue = ( dmflags & DF_FORCE_RESPAWN ) != 0; 2776: 2777: s_teamplay_box.generic.type = MTYPE_SPINCONTROL; 2778: s_teamplay_box.generic.x = 0; 2779: s_teamplay_box.generic.y = y += 10; 2780: s_teamplay_box.generic.name = "teamplay"; 2781: s_teamplay_box.generic.callback = DMFlagCallback; 2782: s_teamplay_box.itemnames = teamplay_names; 2783: 2784: s_allow_exit_box.generic.type = MTYPE_SPINCONTROL; 2785: s_allow_exit_box.generic.x = 0; 2786: s_allow_exit_box.generic.y = y += 10; 2787: s_allow_exit_box.generic.name = "allow exit"; 2788: s_allow_exit_box.generic.callback = DMFlagCallback; 2789: s_allow_exit_box.itemnames = yes_no_names; 2790: s_allow_exit_box.curvalue = ( dmflags & DF_ALLOW_EXIT ) != 0; 2791: 2792: s_infinite_ammo_box.generic.type = MTYPE_SPINCONTROL; 2793: s_infinite_ammo_box.generic.x = 0; 2794: s_infinite_ammo_box.generic.y = y += 10; 2795: s_infinite_ammo_box.generic.name = "infinite ammo"; 2796: s_infinite_ammo_box.generic.callback = DMFlagCallback; 2797: s_infinite_ammo_box.itemnames = yes_no_names; 2798: s_infinite_ammo_box.curvalue = ( dmflags & DF_INFINITE_AMMO ) != 0; 2799: 2800: s_fixed_fov_box.generic.type = MTYPE_SPINCONTROL; 2801: s_fixed_fov_box.generic.x = 0; 2802: s_fixed_fov_box.generic.y = y += 10; 2803: s_fixed_fov_box.generic.name = "fixed FOV"; 2804: s_fixed_fov_box.generic.callback = DMFlagCallback; 2805: s_fixed_fov_box.itemnames = yes_no_names; 2806: s_fixed_fov_box.curvalue = ( dmflags & DF_FIXED_FOV ) != 0; 2807: 2808: s_quad_drop_box.generic.type = MTYPE_SPINCONTROL; 2809: s_quad_drop_box.generic.x = 0; 2810: s_quad_drop_box.generic.y = y += 10; 2811: s_quad_drop_box.generic.name = "quad drop"; 2812: s_quad_drop_box.generic.callback = DMFlagCallback; 2813: s_quad_drop_box.itemnames = yes_no_names; 2814: s_quad_drop_box.curvalue = ( dmflags & DF_QUAD_DROP ) != 0; 2815: 2816: s_friendlyfire_box.generic.type = MTYPE_SPINCONTROL; 2817: s_friendlyfire_box.generic.x = 0; 2818: s_friendlyfire_box.generic.y = y += 10; 2819: s_friendlyfire_box.generic.name = "friendly fire"; 2820: s_friendlyfire_box.generic.callback = DMFlagCallback; 2821: s_friendlyfire_box.itemnames = yes_no_names; 2822: s_friendlyfire_box.curvalue = ( dmflags & DF_NO_FRIENDLY_FIRE ) == 0; 2823: 2824: Menu_AddItem( &s_dmoptions_menu, &s_falls_box ); 2825: Menu_AddItem( &s_dmoptions_menu, &s_weapons_stay_box ); 2826: Menu_AddItem( &s_dmoptions_menu, &s_instant_powerups_box ); 2827: Menu_AddItem( &s_dmoptions_menu, &s_powerups_box ); 2828: Menu_AddItem( &s_dmoptions_menu, &s_health_box ); 2829: Menu_AddItem( &s_dmoptions_menu, &s_armor_box ); 2830: Menu_AddItem( &s_dmoptions_menu, &s_spawn_farthest_box ); 2831: Menu_AddItem( &s_dmoptions_menu, &s_samelevel_box ); 2832: Menu_AddItem( &s_dmoptions_menu, &s_force_respawn_box ); 2833: Menu_AddItem( &s_dmoptions_menu, &s_teamplay_box ); 2834: Menu_AddItem( &s_dmoptions_menu, &s_allow_exit_box ); 2835: Menu_AddItem( &s_dmoptions_menu, &s_infinite_ammo_box ); 2836: Menu_AddItem( &s_dmoptions_menu, &s_fixed_fov_box ); 2837: Menu_AddItem( &s_dmoptions_menu, &s_quad_drop_box ); 2838: Menu_AddItem( &s_dmoptions_menu, &s_friendlyfire_box ); 2839: 2840: Menu_Center( &s_dmoptions_menu ); 2841: 2842: // set the original dmflags statusbar 2843: DMFlagCallback( 0 ); 2844: Menu_SetStatusBar( &s_dmoptions_menu, dmoptions_statusbar ); 2845: } 2846: 2847: void DMOptions_MenuDraw(void) 2848: { 2849: Menu_Draw( &s_dmoptions_menu ); 2850: } 2851: 2852: const char *DMOptions_MenuKey( int key ) 2853: { 2854: return Default_MenuKey( &s_dmoptions_menu, key ); 2855: } 2856: 2857: void M_Menu_DMOptions_f (void) 2858: { 2859: DMOptions_MenuInit(); 2860: M_PushMenu( DMOptions_MenuDraw, DMOptions_MenuKey ); 2861: } 2862: 2863: /* 2864: ============================================================================= 1.1.1.2 ! root 2865: ! 2866: DOWNLOADOPTIONS BOOK MENU ! 2867: ! 2868: ============================================================================= ! 2869: */ ! 2870: static menuframework_s s_downloadoptions_menu; ! 2871: ! 2872: static menuseparator_s s_download_title; ! 2873: static menulist_s s_allow_download_box; ! 2874: static menulist_s s_allow_download_maps_box; ! 2875: static menulist_s s_allow_download_models_box; ! 2876: static menulist_s s_allow_download_players_box; ! 2877: static menulist_s s_allow_download_sounds_box; ! 2878: ! 2879: static void DownloadCallback( void *self ) ! 2880: { ! 2881: menulist_s *f = ( menulist_s * ) self; ! 2882: ! 2883: if (f == &s_allow_download_box) ! 2884: { ! 2885: Cvar_SetValue("allow_download", f->curvalue); ! 2886: } ! 2887: ! 2888: else if (f == &s_allow_download_maps_box) ! 2889: { ! 2890: Cvar_SetValue("allow_download_maps", f->curvalue); ! 2891: } ! 2892: ! 2893: else if (f == &s_allow_download_models_box) ! 2894: { ! 2895: Cvar_SetValue("allow_download_models", f->curvalue); ! 2896: } ! 2897: ! 2898: else if (f == &s_allow_download_players_box) ! 2899: { ! 2900: Cvar_SetValue("allow_download_players", f->curvalue); ! 2901: } ! 2902: ! 2903: else if (f == &s_allow_download_sounds_box) ! 2904: { ! 2905: Cvar_SetValue("allow_download_sounds", f->curvalue); ! 2906: } ! 2907: } ! 2908: ! 2909: void DownloadOptions_MenuInit( void ) ! 2910: { ! 2911: static const char *yes_no_names[] = ! 2912: { ! 2913: "no", "yes", 0 ! 2914: }; ! 2915: int y = 0; ! 2916: ! 2917: s_downloadoptions_menu.x = viddef.width * 0.50; ! 2918: s_downloadoptions_menu.nitems = 0; ! 2919: ! 2920: s_download_title.generic.type = MTYPE_SEPARATOR; ! 2921: s_download_title.generic.name = "Download Options"; ! 2922: s_download_title.generic.x = 48; ! 2923: s_download_title.generic.y = y; ! 2924: ! 2925: s_allow_download_box.generic.type = MTYPE_SPINCONTROL; ! 2926: s_allow_download_box.generic.x = 0; ! 2927: s_allow_download_box.generic.y = y += 20; ! 2928: s_allow_download_box.generic.name = "allow downloading"; ! 2929: s_allow_download_box.generic.callback = DownloadCallback; ! 2930: s_allow_download_box.itemnames = yes_no_names; ! 2931: s_allow_download_box.curvalue = (Cvar_VariableValue("allow_download") != 0); ! 2932: ! 2933: s_allow_download_maps_box.generic.type = MTYPE_SPINCONTROL; ! 2934: s_allow_download_maps_box.generic.x = 0; ! 2935: s_allow_download_maps_box.generic.y = y += 20; ! 2936: s_allow_download_maps_box.generic.name = "maps"; ! 2937: s_allow_download_maps_box.generic.callback = DownloadCallback; ! 2938: s_allow_download_maps_box.itemnames = yes_no_names; ! 2939: s_allow_download_maps_box.curvalue = (Cvar_VariableValue("allow_download_maps") != 0); ! 2940: ! 2941: s_allow_download_players_box.generic.type = MTYPE_SPINCONTROL; ! 2942: s_allow_download_players_box.generic.x = 0; ! 2943: s_allow_download_players_box.generic.y = y += 10; ! 2944: s_allow_download_players_box.generic.name = "player models/skins"; ! 2945: s_allow_download_players_box.generic.callback = DownloadCallback; ! 2946: s_allow_download_players_box.itemnames = yes_no_names; ! 2947: s_allow_download_players_box.curvalue = (Cvar_VariableValue("allow_download_players") != 0); ! 2948: ! 2949: s_allow_download_models_box.generic.type = MTYPE_SPINCONTROL; ! 2950: s_allow_download_models_box.generic.x = 0; ! 2951: s_allow_download_models_box.generic.y = y += 10; ! 2952: s_allow_download_models_box.generic.name = "models"; ! 2953: s_allow_download_models_box.generic.callback = DownloadCallback; ! 2954: s_allow_download_models_box.itemnames = yes_no_names; ! 2955: s_allow_download_models_box.curvalue = (Cvar_VariableValue("allow_download_models") != 0); ! 2956: ! 2957: s_allow_download_sounds_box.generic.type = MTYPE_SPINCONTROL; ! 2958: s_allow_download_sounds_box.generic.x = 0; ! 2959: s_allow_download_sounds_box.generic.y = y += 10; ! 2960: s_allow_download_sounds_box.generic.name = "sounds"; ! 2961: s_allow_download_sounds_box.generic.callback = DownloadCallback; ! 2962: s_allow_download_sounds_box.itemnames = yes_no_names; ! 2963: s_allow_download_sounds_box.curvalue = (Cvar_VariableValue("allow_download_sounds") != 0); ! 2964: ! 2965: Menu_AddItem( &s_downloadoptions_menu, &s_download_title ); ! 2966: Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_box ); ! 2967: Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_maps_box ); ! 2968: Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_players_box ); ! 2969: Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_models_box ); ! 2970: Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_sounds_box ); ! 2971: ! 2972: Menu_Center( &s_downloadoptions_menu ); ! 2973: ! 2974: // skip over title ! 2975: if (s_downloadoptions_menu.cursor == 0) ! 2976: s_downloadoptions_menu.cursor = 1; ! 2977: } ! 2978: ! 2979: void DownloadOptions_MenuDraw(void) ! 2980: { ! 2981: Menu_Draw( &s_downloadoptions_menu ); ! 2982: } ! 2983: ! 2984: const char *DownloadOptions_MenuKey( int key ) ! 2985: { ! 2986: return Default_MenuKey( &s_downloadoptions_menu, key ); ! 2987: } ! 2988: ! 2989: void M_Menu_DownloadOptions_f (void) ! 2990: { ! 2991: DownloadOptions_MenuInit(); ! 2992: M_PushMenu( DownloadOptions_MenuDraw, DownloadOptions_MenuKey ); ! 2993: } ! 2994: /* ! 2995: ============================================================================= ! 2996: 1.1 root 2997: ADDRESS BOOK MENU 1.1.1.2 ! root 2998: 1.1 root 2999: ============================================================================= 3000: */ 3001: #define NUM_ADDRESSBOOK_ENTRIES 9 1.1.1.2 ! root 3002: 1.1 root 3003: static menuframework_s s_addressbook_menu; 3004: static menufield_s s_addressbook_fields[NUM_ADDRESSBOOK_ENTRIES]; 1.1.1.2 ! root 3005: 1.1 root 3006: void AddressBook_MenuInit( void ) 3007: { 3008: int i; 1.1.1.2 ! root 3009: 1.1 root 3010: s_addressbook_menu.x = viddef.width / 2 - 142; 3011: s_addressbook_menu.y = viddef.height / 2 - 58; 3012: s_addressbook_menu.nitems = 0; 1.1.1.2 ! root 3013: 1.1 root 3014: for ( i = 0; i < NUM_ADDRESSBOOK_ENTRIES; i++ ) 3015: { 3016: cvar_t *adr; 3017: char buffer[20]; 3018: 3019: Com_sprintf( buffer, sizeof( buffer ), "adr%d", i ); 3020: 3021: adr = Cvar_Get( buffer, "", CVAR_ARCHIVE ); 1.1.1.2 ! root 3022: 1.1 root 3023: s_addressbook_fields[i].generic.type = MTYPE_FIELD; 3024: s_addressbook_fields[i].generic.name = 0; 3025: s_addressbook_fields[i].generic.callback = 0; 3026: s_addressbook_fields[i].generic.x = 0; 3027: s_addressbook_fields[i].generic.y = i * 18 + 0; 3028: s_addressbook_fields[i].generic.localdata[0] = i; 3029: s_addressbook_fields[i].cursor = 0; 3030: s_addressbook_fields[i].length = 60; 3031: s_addressbook_fields[i].visible_length = 30; 3032: 3033: strcpy( s_addressbook_fields[i].buffer, adr->string ); 1.1.1.2 ! root 3034: 1.1 root 3035: Menu_AddItem( &s_addressbook_menu, &s_addressbook_fields[i] ); 3036: } 3037: } 1.1.1.2 ! root 3038: 1.1 root 3039: const char *AddressBook_MenuKey( int key ) 3040: { 3041: if ( key == K_ESCAPE ) 3042: { 3043: int index; 3044: char buffer[20]; 3045: 3046: for ( index = 0; index < NUM_ADDRESSBOOK_ENTRIES; index++ ) 3047: { 3048: Com_sprintf( buffer, sizeof( buffer ), "adr%d", index ); 3049: Cvar_Set( buffer, s_addressbook_fields[index].buffer ); 3050: } 3051: } 3052: return Default_MenuKey( &s_addressbook_menu, key ); 3053: } 1.1.1.2 ! root 3054: 1.1 root 3055: void AddressBook_MenuDraw(void) 3056: { 3057: M_Banner( "m_banner_addressbook" ); 3058: Menu_Draw( &s_addressbook_menu ); 3059: } 1.1.1.2 ! root 3060: 1.1 root 3061: void M_Menu_AddressBook_f(void) 3062: { 3063: AddressBook_MenuInit(); 3064: M_PushMenu( AddressBook_MenuDraw, AddressBook_MenuKey ); 3065: } 1.1.1.2 ! root 3066: 1.1 root 3067: /* 3068: ============================================================================= 1.1.1.2 ! root 3069: 1.1 root 3070: PLAYER CONFIG MENU 1.1.1.2 ! root 3071: 1.1 root 3072: ============================================================================= 3073: */ 3074: static menuframework_s s_player_config_menu; 3075: static menufield_s s_player_name_field; 3076: static menulist_s s_player_model_box; 3077: static menulist_s s_player_skin_box; 3078: static menulist_s s_player_handedness_box; 1.1.1.2 ! root 3079: static menulist_s s_player_rate_box; 1.1 root 3080: static menuseparator_s s_player_skin_title; 3081: static menuseparator_s s_player_model_title; 3082: static menuseparator_s s_player_hand_title; 1.1.1.2 ! root 3083: static menuseparator_s s_player_rate_title; ! 3084: static menuaction_s s_player_download_action; 1.1 root 3085: 3086: #define MAX_DISPLAYNAME 16 3087: #define MAX_PLAYERMODELS 1024 3088: 3089: typedef struct 3090: { 3091: int nskins; 3092: char **skindisplaynames; 3093: char displayname[MAX_DISPLAYNAME]; 3094: char directory[MAX_QPATH]; 3095: } playermodelinfo_s; 3096: 3097: static playermodelinfo_s s_pmi[MAX_PLAYERMODELS]; 3098: static char *s_pmnames[MAX_PLAYERMODELS]; 3099: static int s_numplayermodels; 3100: 1.1.1.2 ! root 3101: static int rate_tbl[] = { 2500, 3200, 5000, 10000, 25000, 0 }; ! 3102: static const char *rate_names[] = { "28.8 Modem", "33.6 Modem", "Single ISDN", ! 3103: "Dual ISDN/Cable", "T1/LAN", "User defined", 0 }; ! 3104: ! 3105: void DownloadOptionsFunc( void *self ) ! 3106: { ! 3107: M_Menu_DownloadOptions_f(); ! 3108: } ! 3109: 1.1 root 3110: static void HandednessCallback( void *unused ) 3111: { 3112: Cvar_SetValue( "hand", s_player_handedness_box.curvalue ); 3113: } 3114: 1.1.1.2 ! root 3115: static void RateCallback( void *unused ) ! 3116: { ! 3117: if (s_player_rate_box.curvalue != sizeof(rate_tbl) / sizeof(*rate_tbl) - 1) ! 3118: Cvar_SetValue( "rate", rate_tbl[s_player_rate_box.curvalue] ); ! 3119: } ! 3120: 1.1 root 3121: static void ModelCallback( void *unused ) 3122: { 3123: s_player_skin_box.itemnames = s_pmi[s_player_model_box.curvalue].skindisplaynames; 3124: s_player_skin_box.curvalue = 0; 3125: } 3126: 3127: static void FreeFileList( char **list, int n ) 3128: { 3129: int i; 3130: 3131: for ( i = 0; i < n; i++ ) 3132: { 3133: if ( list[i] ) 3134: { 3135: free( list[i] ); 3136: list[i] = 0; 3137: } 3138: } 3139: free( list ); 3140: } 3141: 3142: static qboolean IconOfSkinExists( char *skin, char **pcxfiles, int npcxfiles ) 3143: { 3144: int i; 3145: char scratch[1024]; 3146: 3147: strcpy( scratch, skin ); 3148: *strrchr( scratch, '.' ) = 0; 3149: strcat( scratch, "_i.pcx" ); 3150: 3151: for ( i = 0; i < npcxfiles; i++ ) 3152: { 3153: if ( strcmp( pcxfiles[i], scratch ) == 0 ) 3154: return true; 3155: } 3156: 3157: return false; 3158: } 3159: 3160: static qboolean PlayerConfig_ScanDirectories( void ) 3161: { 3162: char findname[1024]; 3163: char scratch[1024]; 3164: int ndirs = 0, npms = 0; 3165: char **dirnames; 3166: char *path = NULL; 3167: int i; 3168: 3169: extern char **FS_ListFiles( char *, int *, unsigned, unsigned ); 3170: 3171: s_numplayermodels = 0; 3172: 3173: /* 3174: ** get a list of directories 3175: */ 3176: do 3177: { 3178: path = FS_NextPath( path ); 3179: Com_sprintf( findname, sizeof(findname), "%s/players/*.*", path ); 3180: 3181: if ( ( dirnames = FS_ListFiles( findname, &ndirs, SFF_SUBDIR, 0 ) ) != 0 ) 3182: break; 3183: } while ( path ); 3184: 3185: if ( !dirnames ) 3186: return false; 3187: 3188: /* 3189: ** go through the subdirectories 3190: */ 3191: npms = ndirs; 3192: if ( npms > MAX_PLAYERMODELS ) 3193: npms = MAX_PLAYERMODELS; 3194: 3195: for ( i = 0; i < npms; i++ ) 3196: { 3197: int k, s; 3198: char *a, *b, *c; 3199: char **pcxnames; 3200: char **skinnames; 3201: int npcxfiles; 3202: int nskins = 0; 3203: 3204: if ( dirnames[i] == 0 ) 3205: continue; 3206: 3207: // verify the existence of tris.md2 3208: strcpy( scratch, dirnames[i] ); 3209: strcat( scratch, "/tris.md2" ); 3210: if ( !Sys_FindFirst( scratch, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM ) ) 3211: { 3212: free( dirnames[i] ); 3213: dirnames[i] = 0; 3214: Sys_FindClose(); 3215: continue; 3216: } 3217: Sys_FindClose(); 3218: 3219: // verify the existence of at least one pcx skin 3220: strcpy( scratch, dirnames[i] ); 3221: strcat( scratch, "/*.pcx" ); 3222: pcxnames = FS_ListFiles( scratch, &npcxfiles, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM ); 3223: 3224: if ( !pcxnames ) 3225: { 3226: free( dirnames[i] ); 3227: dirnames[i] = 0; 3228: continue; 3229: } 3230: 3231: // count valid skins, which consist of a skin with a matching "_i" icon 3232: for ( k = 0; k < npcxfiles-1; k++ ) 3233: { 3234: if ( !strstr( pcxnames[k], "_i.pcx" ) ) 3235: { 3236: if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) ) 3237: { 3238: nskins++; 3239: } 3240: } 3241: } 3242: if ( !nskins ) 3243: continue; 3244: 3245: skinnames = malloc( sizeof( char * ) * ( nskins + 1 ) ); 3246: memset( skinnames, 0, sizeof( char * ) * ( nskins + 1 ) ); 3247: 3248: // copy the valid skins 3249: for ( s = 0, k = 0; k < npcxfiles-1; k++ ) 3250: { 3251: char *a, *b, *c; 3252: 3253: if ( !strstr( pcxnames[k], "_i.pcx" ) ) 3254: { 3255: if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) ) 3256: { 3257: a = strrchr( pcxnames[k], '/' ); 3258: b = strrchr( pcxnames[k], '\\' ); 3259: 3260: if ( a > b ) 3261: c = a; 3262: else 3263: c = b; 3264: 3265: strcpy( scratch, c + 1 ); 3266: 3267: if ( strrchr( scratch, '.' ) ) 3268: *strrchr( scratch, '.' ) = 0; 3269: 3270: skinnames[s] = strdup( scratch ); 3271: s++; 3272: } 3273: } 3274: } 3275: 3276: // at this point we have a valid player model 3277: s_pmi[s_numplayermodels].nskins = nskins; 3278: s_pmi[s_numplayermodels].skindisplaynames = skinnames; 3279: 3280: // make short name for the model 3281: a = strrchr( dirnames[i], '/' ); 3282: b = strrchr( dirnames[i], '\\' ); 3283: 3284: if ( a > b ) 3285: c = a; 3286: else 3287: c = b; 3288: 3289: strncpy( s_pmi[s_numplayermodels].displayname, c + 1, MAX_DISPLAYNAME-1 ); 3290: strcpy( s_pmi[s_numplayermodels].directory, c + 1 ); 3291: 3292: FreeFileList( pcxnames, npcxfiles ); 3293: 3294: s_numplayermodels++; 3295: } 3296: if ( dirnames ) 3297: FreeFileList( dirnames, ndirs ); 3298: } 3299: 3300: static int pmicmpfnc( const void *_a, const void *_b ) 3301: { 3302: const playermodelinfo_s *a = ( const playermodelinfo_s * ) _a; 3303: const playermodelinfo_s *b = ( const playermodelinfo_s * ) _b; 3304: 3305: /* 3306: ** sort by male, female, then alphabetical 3307: */ 3308: if ( strcmp( a->directory, "male" ) == 0 ) 3309: return -1; 3310: else if ( strcmp( b->directory, "male" ) == 0 ) 3311: return 1; 3312: 3313: if ( strcmp( a->directory, "female" ) == 0 ) 3314: return -1; 3315: else if ( strcmp( b->directory, "female" ) == 0 ) 3316: return 1; 3317: 3318: return strcmp( a->directory, b->directory ); 3319: } 3320: 1.1.1.2 ! root 3321: ! 3322: qboolean PlayerConfig_MenuInit( void ) 1.1 root 3323: { 3324: extern cvar_t *name; 3325: extern cvar_t *team; 3326: extern cvar_t *skin; 3327: char currentdirectory[1024]; 3328: char currentskin[1024]; 3329: int i = 0; 3330: 3331: int currentdirectoryindex = 0; 3332: int currentskinindex = 0; 3333: 3334: cvar_t *hand = Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE ); 3335: 3336: static const char *handedness[] = { "right", "left", "center", 0 }; 3337: 3338: PlayerConfig_ScanDirectories(); 3339: 1.1.1.2 ! root 3340: if (s_numplayermodels == 0) ! 3341: return false; ! 3342: 1.1 root 3343: if ( hand->value < 0 || hand->value > 2 ) 3344: Cvar_SetValue( "hand", 0 ); 3345: 3346: strcpy( currentdirectory, skin->string ); 3347: 3348: if ( strchr( currentdirectory, '/' ) ) 3349: { 3350: strcpy( currentskin, strchr( currentdirectory, '/' ) + 1 ); 3351: *strchr( currentdirectory, '/' ) = 0; 3352: } 3353: else if ( strchr( currentdirectory, '\\' ) ) 3354: { 3355: strcpy( currentskin, strchr( currentdirectory, '\\' ) + 1 ); 3356: *strchr( currentdirectory, '\\' ) = 0; 3357: } 3358: else 3359: { 3360: strcpy( currentdirectory, "male" ); 3361: strcpy( currentskin, "grunt" ); 3362: } 3363: 3364: qsort( s_pmi, s_numplayermodels, sizeof( s_pmi[0] ), pmicmpfnc ); 3365: 3366: memset( s_pmnames, 0, sizeof( s_pmnames ) ); 3367: for ( i = 0; i < s_numplayermodels; i++ ) 3368: { 3369: s_pmnames[i] = s_pmi[i].displayname; 3370: if ( Q_stricmp( s_pmi[i].directory, currentdirectory ) == 0 ) 3371: { 3372: int j; 3373: 3374: currentdirectoryindex = i; 3375: 3376: for ( j = 0; j < s_pmi[i].nskins; j++ ) 3377: { 3378: if ( Q_stricmp( s_pmi[i].skindisplaynames[j], currentskin ) == 0 ) 3379: { 3380: currentskinindex = j; 3381: break; 3382: } 3383: } 3384: } 3385: } 3386: 3387: s_player_config_menu.x = viddef.width / 2 - 95; 3388: s_player_config_menu.y = viddef.height / 2 - 97; 3389: s_player_config_menu.nitems = 0; 3390: 3391: s_player_name_field.generic.type = MTYPE_FIELD; 3392: s_player_name_field.generic.name = "name"; 3393: s_player_name_field.generic.callback = 0; 3394: s_player_name_field.generic.x = 0; 3395: s_player_name_field.generic.y = 0; 3396: s_player_name_field.length = 20; 3397: s_player_name_field.visible_length = 20; 3398: strcpy( s_player_name_field.buffer, name->string ); 3399: s_player_name_field.cursor = strlen( name->string ); 3400: 3401: s_player_model_title.generic.type = MTYPE_SEPARATOR; 3402: s_player_model_title.generic.name = "model"; 3403: s_player_model_title.generic.x = -8; 3404: s_player_model_title.generic.y = 60; 3405: 3406: s_player_model_box.generic.type = MTYPE_SPINCONTROL; 3407: s_player_model_box.generic.x = -56; 3408: s_player_model_box.generic.y = 70; 3409: s_player_model_box.generic.callback = ModelCallback; 3410: s_player_model_box.generic.cursor_offset = -48; 3411: s_player_model_box.curvalue = currentdirectoryindex; 3412: s_player_model_box.itemnames = s_pmnames; 3413: 3414: s_player_skin_title.generic.type = MTYPE_SEPARATOR; 3415: s_player_skin_title.generic.name = "skin"; 3416: s_player_skin_title.generic.x = -16; 3417: s_player_skin_title.generic.y = 84; 3418: 3419: s_player_skin_box.generic.type = MTYPE_SPINCONTROL; 3420: s_player_skin_box.generic.x = -56; 3421: s_player_skin_box.generic.y = 94; 3422: s_player_skin_box.generic.name = 0; 3423: s_player_skin_box.generic.callback = 0; 3424: s_player_skin_box.generic.cursor_offset = -48; 3425: s_player_skin_box.curvalue = currentskinindex; 3426: s_player_skin_box.itemnames = s_pmi[currentdirectoryindex].skindisplaynames; 3427: 3428: s_player_hand_title.generic.type = MTYPE_SEPARATOR; 3429: s_player_hand_title.generic.name = "handedness"; 3430: s_player_hand_title.generic.x = 32; 3431: s_player_hand_title.generic.y = 108; 3432: 3433: s_player_handedness_box.generic.type = MTYPE_SPINCONTROL; 3434: s_player_handedness_box.generic.x = -56; 3435: s_player_handedness_box.generic.y = 118; 3436: s_player_handedness_box.generic.name = 0; 3437: s_player_handedness_box.generic.cursor_offset = -48; 3438: s_player_handedness_box.generic.callback = HandednessCallback; 3439: s_player_handedness_box.curvalue = Cvar_VariableValue( "hand" ); 3440: s_player_handedness_box.itemnames = handedness; 3441: 1.1.1.2 ! root 3442: for (i = 0; i < sizeof(rate_tbl) / sizeof(*rate_tbl) - 1; i++) ! 3443: if (Cvar_VariableValue("rate") == rate_tbl[i]) ! 3444: break; ! 3445: ! 3446: s_player_rate_title.generic.type = MTYPE_SEPARATOR; ! 3447: s_player_rate_title.generic.name = "connect speed"; ! 3448: s_player_rate_title.generic.x = 56; ! 3449: s_player_rate_title.generic.y = 156; ! 3450: ! 3451: s_player_rate_box.generic.type = MTYPE_SPINCONTROL; ! 3452: s_player_rate_box.generic.x = -56; ! 3453: s_player_rate_box.generic.y = 166; ! 3454: s_player_rate_box.generic.name = 0; ! 3455: s_player_rate_box.generic.cursor_offset = -48; ! 3456: s_player_rate_box.generic.callback = RateCallback; ! 3457: s_player_rate_box.curvalue = i; ! 3458: s_player_rate_box.itemnames = rate_names; ! 3459: ! 3460: s_player_download_action.generic.type = MTYPE_ACTION; ! 3461: s_player_download_action.generic.name = "download options"; ! 3462: s_player_download_action.generic.flags= QMF_LEFT_JUSTIFY; ! 3463: s_player_download_action.generic.x = -24; ! 3464: s_player_download_action.generic.y = 186; ! 3465: s_player_download_action.generic.statusbar = NULL; ! 3466: s_player_download_action.generic.callback = DownloadOptionsFunc; ! 3467: 1.1 root 3468: Menu_AddItem( &s_player_config_menu, &s_player_name_field ); 3469: Menu_AddItem( &s_player_config_menu, &s_player_model_title ); 3470: Menu_AddItem( &s_player_config_menu, &s_player_model_box ); 3471: if ( s_player_skin_box.itemnames ) 3472: { 3473: Menu_AddItem( &s_player_config_menu, &s_player_skin_title ); 3474: Menu_AddItem( &s_player_config_menu, &s_player_skin_box ); 3475: } 3476: Menu_AddItem( &s_player_config_menu, &s_player_hand_title ); 3477: Menu_AddItem( &s_player_config_menu, &s_player_handedness_box ); 1.1.1.2 ! root 3478: Menu_AddItem( &s_player_config_menu, &s_player_rate_title ); ! 3479: Menu_AddItem( &s_player_config_menu, &s_player_rate_box ); ! 3480: Menu_AddItem( &s_player_config_menu, &s_player_download_action ); ! 3481: ! 3482: return true; 1.1 root 3483: } 3484: 3485: void PlayerConfig_MenuDraw( void ) 3486: { 3487: extern float CalcFov( float fov_x, float w, float h ); 3488: refdef_t refdef; 3489: char scratch[MAX_QPATH]; 3490: 3491: memset( &refdef, 0, sizeof( refdef ) ); 3492: 3493: refdef.x = viddef.width / 2; 3494: refdef.y = viddef.height / 2 - 72; 3495: refdef.width = 144; 3496: refdef.height = 168; 3497: refdef.fov_x = 40; 3498: refdef.fov_y = CalcFov( refdef.fov_x, refdef.width, refdef.height ); 3499: refdef.time = cls.realtime*0.001; 3500: 3501: if ( s_pmi[s_player_model_box.curvalue].skindisplaynames ) 3502: { 3503: static int yaw; 3504: int maxframe = 29; 3505: entity_t entity; 3506: 3507: memset( &entity, 0, sizeof( entity ) ); 3508: 3509: Com_sprintf( scratch, sizeof( scratch ), "players/%s/tris.md2", s_pmi[s_player_model_box.curvalue].directory ); 3510: entity.model = re.RegisterModel( scratch ); 3511: 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] ); 3512: entity.skin = re.RegisterSkin( scratch ); 3513: entity.flags = RF_FULLBRIGHT; 3514: entity.origin[0] = 80; 3515: entity.origin[1] = 0; 3516: entity.origin[2] = 0; 3517: VectorCopy( entity.origin, entity.oldorigin ); 3518: entity.frame = 0; 3519: entity.oldframe = 0; 3520: entity.backlerp = 0.0; 3521: entity.angles[1] = yaw++; 3522: if ( ++yaw > 360 ) 3523: yaw -= 360; 3524: 3525: refdef.areabits = 0; 3526: refdef.num_entities = 1; 3527: refdef.entities = &entity; 3528: refdef.lightstyles = 0; 3529: refdef.rdflags = RDF_NOWORLDMODEL; 3530: 3531: Menu_Draw( &s_player_config_menu ); 3532: 3533: M_DrawTextBox( ( refdef.x ) * ( 320.0F / viddef.width ) - 8, ( viddef.height / 2 ) * ( 240.0F / viddef.height) - 77, refdef.width / 8, refdef.height / 8 ); 3534: refdef.height += 4; 3535: 3536: re.RenderFrame( &refdef ); 3537: 3538: Com_sprintf( scratch, sizeof( scratch ), "/players/%s/%s_i.pcx", 3539: s_pmi[s_player_model_box.curvalue].directory, 3540: s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] ); 3541: re.DrawPic( s_player_config_menu.x - 40, refdef.y, scratch ); 3542: } 3543: } 1.1.1.2 ! root 3544: 1.1 root 3545: const char *PlayerConfig_MenuKey (int key) 3546: { 3547: int i; 3548: 3549: if ( key == K_ESCAPE ) 3550: { 3551: char scratch[1024]; 3552: 3553: Cvar_Set( "name", s_player_name_field.buffer ); 3554: 3555: Com_sprintf( scratch, sizeof( scratch ), "%s/%s", 3556: s_pmi[s_player_model_box.curvalue].directory, 1.1.1.2 ! root 3557: s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] ); 1.1 root 3558: 3559: Cvar_Set( "skin", scratch ); 3560: 3561: for ( i = 0; i < s_numplayermodels; i++ ) 3562: { 3563: int j; 3564: 3565: for ( j = 0; j < s_pmi[i].nskins; j++ ) 3566: { 3567: if ( s_pmi[i].skindisplaynames[j] ) 3568: free( s_pmi[i].skindisplaynames[j] ); 3569: s_pmi[i].skindisplaynames[j] = 0; 3570: } 3571: free( s_pmi[i].skindisplaynames ); 3572: s_pmi[i].skindisplaynames = 0; 3573: s_pmi[i].nskins = 0; 3574: } 3575: } 3576: return Default_MenuKey( &s_player_config_menu, key ); 3577: } 1.1.1.2 ! root 3578: ! 3579: 1.1 root 3580: void M_Menu_PlayerConfig_f (void) 3581: { 1.1.1.2 ! root 3582: if (!PlayerConfig_MenuInit()) ! 3583: { ! 3584: Menu_SetStatusBar( &s_multiplayer_menu, "No valid player models found" ); ! 3585: return; ! 3586: } ! 3587: Menu_SetStatusBar( &s_multiplayer_menu, NULL ); 1.1 root 3588: M_PushMenu( PlayerConfig_MenuDraw, PlayerConfig_MenuKey ); 3589: } 1.1.1.2 ! root 3590: ! 3591: 1.1 root 3592: /* 3593: ======================================================================= 3594: 3595: GALLERY MENU 3596: 3597: ======================================================================= 3598: */ 3599: #if 0 3600: void M_Menu_Gallery_f( void ) 3601: { 3602: extern void Gallery_MenuDraw( void ); 3603: extern const char *Gallery_MenuKey( int key ); 1.1.1.2 ! root 3604: 1.1 root 3605: M_PushMenu( Gallery_MenuDraw, Gallery_MenuKey ); 3606: } 3607: #endif 1.1.1.2 ! root 3608: 1.1 root 3609: /* 3610: ======================================================================= 1.1.1.2 ! root 3611: 1.1 root 3612: QUIT MENU 1.1.1.2 ! root 3613: 1.1 root 3614: ======================================================================= 3615: */ 1.1.1.2 ! root 3616: 1.1 root 3617: const char *M_Quit_Key (int key) 3618: { 3619: switch (key) 3620: { 3621: case K_ESCAPE: 3622: case 'n': 3623: case 'N': 3624: M_PopMenu (); 3625: break; 1.1.1.2 ! root 3626: 1.1 root 3627: case 'Y': 3628: case 'y': 3629: cls.key_dest = key_console; 3630: CL_Quit_f (); 3631: break; 1.1.1.2 ! root 3632: 1.1 root 3633: default: 3634: break; 3635: } 1.1.1.2 ! root 3636: 1.1 root 3637: return NULL; 1.1.1.2 ! root 3638: 1.1 root 3639: } 1.1.1.2 ! root 3640: ! 3641: 1.1 root 3642: void M_Quit_Draw (void) 3643: { 3644: int w, h; 1.1.1.2 ! root 3645: 1.1 root 3646: re.DrawGetPicSize (&w, &h, "quit"); 3647: re.DrawPic ( (viddef.width-w)/2, (viddef.height-h)/2, "quit"); 3648: } 1.1.1.2 ! root 3649: ! 3650: 1.1 root 3651: void M_Menu_Quit_f (void) 3652: { 3653: M_PushMenu (M_Quit_Draw, M_Quit_Key); 3654: } 1.1.1.2 ! root 3655: ! 3656: ! 3657: 1.1 root 3658: //============================================================================= 3659: /* Menu Subsystem */ 1.1.1.2 ! root 3660: ! 3661: 1.1 root 3662: /* 3663: ================= 3664: M_Init 3665: ================= 3666: */ 3667: void M_Init (void) 3668: { 3669: Cmd_AddCommand ("menu_main", M_Menu_Main_f); 3670: Cmd_AddCommand ("menu_game", M_Menu_Game_f); 3671: Cmd_AddCommand ("menu_loadgame", M_Menu_LoadGame_f); 3672: Cmd_AddCommand ("menu_savegame", M_Menu_SaveGame_f); 3673: Cmd_AddCommand ("menu_joinserver", M_Menu_JoinServer_f); 3674: Cmd_AddCommand ("menu_addressbook", M_Menu_AddressBook_f); 3675: Cmd_AddCommand ("menu_startserver", M_Menu_StartServer_f); 3676: Cmd_AddCommand ("menu_dmoptions", M_Menu_DMOptions_f); 3677: Cmd_AddCommand ("menu_playerconfig", M_Menu_PlayerConfig_f); 1.1.1.2 ! root 3678: Cmd_AddCommand ("menu_downloadoptions", M_Menu_DownloadOptions_f); 1.1 root 3679: Cmd_AddCommand ("menu_credits", M_Menu_Credits_f ); 3680: Cmd_AddCommand ("menu_multiplayer", M_Menu_Multiplayer_f ); 3681: Cmd_AddCommand ("menu_video", M_Menu_Video_f); 3682: Cmd_AddCommand ("menu_options", M_Menu_Options_f); 3683: Cmd_AddCommand ("menu_keys", M_Menu_Keys_f); 3684: Cmd_AddCommand ("menu_quit", M_Menu_Quit_f); 3685: } 1.1.1.2 ! root 3686: ! 3687: 1.1 root 3688: /* 3689: ================= 3690: M_Draw 3691: ================= 3692: */ 3693: void M_Draw (void) 3694: { 3695: if (cls.key_dest != key_menu) 3696: return; 1.1.1.2 ! root 3697: 1.1 root 3698: // repaint everything next frame 3699: SCR_DirtyScreen (); 1.1.1.2 ! root 3700: 1.1 root 3701: // dim everything behind it down 3702: if (cl.cinematictime > 0) 3703: re.DrawFill (0,0,viddef.width, viddef.height, 0); 3704: else 3705: re.DrawFadeScreen (); 1.1.1.2 ! root 3706: 1.1 root 3707: m_drawfunc (); 1.1.1.2 ! root 3708: 1.1 root 3709: // delay playing the enter sound until after the 3710: // menu has been drawn, to avoid delay while 3711: // caching images 3712: if (m_entersound) 3713: { 3714: S_StartLocalSound( menu_in_sound ); 3715: m_entersound = false; 3716: } 3717: } 1.1.1.2 ! root 3718: ! 3719: 1.1 root 3720: /* 3721: ================= 3722: M_Keydown 3723: ================= 3724: */ 3725: void M_Keydown (int key) 3726: { 3727: const char *s; 1.1.1.2 ! root 3728: 1.1 root 3729: if (m_keyfunc) 3730: if ( ( s = m_keyfunc( key ) ) != 0 ) 3731: S_StartLocalSound( ( char * ) s ); 3732: } 1.1.1.2 ! root 3733: ! 3734:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.