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