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