ui_splevel.c (30569B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 // 23 /* 24 ============================================================================= 25 26 SINGLE PLAYER LEVEL SELECT MENU 27 28 ============================================================================= 29 */ 30 31 #include "ui_local.h" 32 33 34 #define ART_LEVELFRAME_FOCUS "menu/art/maps_select" 35 #define ART_LEVELFRAME_SELECTED "menu/art/maps_selected" 36 #define ART_ARROW "menu/art/narrow_0" 37 #define ART_ARROW_FOCUS "menu/art/narrow_1" 38 #define ART_MAP_UNKNOWN "menu/art/unknownmap" 39 #define ART_MAP_COMPLETE1 "menu/art/level_complete1" 40 #define ART_MAP_COMPLETE2 "menu/art/level_complete2" 41 #define ART_MAP_COMPLETE3 "menu/art/level_complete3" 42 #define ART_MAP_COMPLETE4 "menu/art/level_complete4" 43 #define ART_MAP_COMPLETE5 "menu/art/level_complete5" 44 #define ART_BACK0 "menu/art/back_0" 45 #define ART_BACK1 "menu/art/back_1" 46 #define ART_FIGHT0 "menu/art/fight_0" 47 #define ART_FIGHT1 "menu/art/fight_1" 48 #define ART_RESET0 "menu/art/reset_0" 49 #define ART_RESET1 "menu/art/reset_1" 50 #define ART_CUSTOM0 "menu/art/skirmish_0" 51 #define ART_CUSTOM1 "menu/art/skirmish_1" 52 53 #define ID_LEFTARROW 10 54 #define ID_PICTURE0 11 55 #define ID_PICTURE1 12 56 #define ID_PICTURE2 13 57 #define ID_PICTURE3 14 58 #define ID_RIGHTARROW 15 59 #define ID_PLAYERPIC 16 60 #define ID_AWARD1 17 61 #define ID_AWARD2 18 62 #define ID_AWARD3 19 63 #define ID_AWARD4 20 64 #define ID_AWARD5 21 65 #define ID_AWARD6 22 66 #define ID_BACK 23 67 #define ID_RESET 24 68 #define ID_CUSTOM 25 69 #define ID_NEXT 26 70 71 #define PLAYER_Y 314 72 #define AWARDS_Y (PLAYER_Y + 26) 73 74 75 typedef struct { 76 menuframework_s menu; 77 menutext_s item_banner; 78 menubitmap_s item_leftarrow; 79 menubitmap_s item_maps[4]; 80 menubitmap_s item_rightarrow; 81 menubitmap_s item_player; 82 menubitmap_s item_awards[6]; 83 menubitmap_s item_back; 84 menubitmap_s item_reset; 85 menubitmap_s item_custom; 86 menubitmap_s item_next; 87 menubitmap_s item_null; 88 89 qboolean reinit; 90 91 const char * selectedArenaInfo; 92 int numMaps; 93 char levelPicNames[4][MAX_QPATH]; 94 char levelNames[4][16]; 95 int levelScores[4]; 96 int levelScoresSkill[4]; 97 qhandle_t levelSelectedPic; 98 qhandle_t levelFocusPic; 99 qhandle_t levelCompletePic[5]; 100 101 char playerModel[MAX_QPATH]; 102 char playerPicName[MAX_QPATH]; 103 int awardLevels[6]; 104 sfxHandle_t awardSounds[6]; 105 106 int numBots; 107 qhandle_t botPics[7]; 108 char botNames[7][10]; 109 } levelMenuInfo_t; 110 111 static levelMenuInfo_t levelMenuInfo; 112 113 static int selectedArenaSet; 114 static int selectedArena; 115 static int currentSet; 116 static int currentGame; 117 static int trainingTier; 118 static int finalTier; 119 static int minTier; 120 static int maxTier; 121 122 123 /* 124 ================= 125 PlayerIcon 126 ================= 127 */ 128 static void PlayerIcon( const char *modelAndSkin, char *iconName, int iconNameMaxSize ) { 129 char *skin; 130 char model[MAX_QPATH]; 131 132 Q_strncpyz( model, modelAndSkin, sizeof(model)); 133 skin = Q_strrchr( model, '/' ); 134 if ( skin ) { 135 *skin++ = '\0'; 136 } 137 else { 138 skin = "default"; 139 } 140 141 Com_sprintf(iconName, iconNameMaxSize, "models/players/%s/icon_%s.tga", model, skin ); 142 143 if( !trap_R_RegisterShaderNoMip( iconName ) && Q_stricmp( skin, "default" ) != 0 ) { 144 Com_sprintf(iconName, iconNameMaxSize, "models/players/%s/icon_default.tga", model ); 145 } 146 } 147 148 149 /* 150 ================= 151 PlayerIconhandle 152 ================= 153 */ 154 static qhandle_t PlayerIconHandle( const char *modelAndSkin ) { 155 char iconName[MAX_QPATH]; 156 157 PlayerIcon( modelAndSkin, iconName, sizeof(iconName) ); 158 return trap_R_RegisterShaderNoMip( iconName ); 159 } 160 161 162 /* 163 ================= 164 UI_SPLevelMenu_SetBots 165 ================= 166 */ 167 static void UI_SPLevelMenu_SetBots( void ) { 168 char *p; 169 char *bot; 170 char *botInfo; 171 char bots[MAX_INFO_STRING]; 172 173 levelMenuInfo.numBots = 0; 174 if ( selectedArenaSet > currentSet ) { 175 return; 176 } 177 178 Q_strncpyz( bots, Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "bots" ), sizeof(bots) ); 179 180 p = &bots[0]; 181 while( *p && levelMenuInfo.numBots < 7 ) { 182 //skip spaces 183 while( *p && *p == ' ' ) { 184 p++; 185 } 186 if( !p ) { 187 break; 188 } 189 190 // mark start of bot name 191 bot = p; 192 193 // skip until space of null 194 while( *p && *p != ' ' ) { 195 p++; 196 } 197 if( *p ) { 198 *p++ = 0; 199 } 200 201 botInfo = UI_GetBotInfoByName( bot ); 202 if( botInfo ) { 203 levelMenuInfo.botPics[levelMenuInfo.numBots] = PlayerIconHandle( Info_ValueForKey( botInfo, "model" ) ); 204 Q_strncpyz( levelMenuInfo.botNames[levelMenuInfo.numBots], Info_ValueForKey( botInfo, "name" ), 10 ); 205 } 206 else { 207 levelMenuInfo.botPics[levelMenuInfo.numBots] = 0; 208 Q_strncpyz( levelMenuInfo.botNames[levelMenuInfo.numBots], bot, 10 ); 209 } 210 Q_CleanStr( levelMenuInfo.botNames[levelMenuInfo.numBots] ); 211 levelMenuInfo.numBots++; 212 } 213 } 214 215 216 /* 217 ================= 218 UI_SPLevelMenu_SetMenuItems 219 ================= 220 */ 221 static void UI_SPLevelMenu_SetMenuArena( int n, int level, const char *arenaInfo ) { 222 char map[MAX_QPATH]; 223 224 Q_strncpyz( map, Info_ValueForKey( arenaInfo, "map" ), sizeof(map) ); 225 226 Q_strncpyz( levelMenuInfo.levelNames[n], map, sizeof(levelMenuInfo.levelNames[n]) ); 227 Q_strupr( levelMenuInfo.levelNames[n] ); 228 229 UI_GetBestScore( level, &levelMenuInfo.levelScores[n], &levelMenuInfo.levelScoresSkill[n] ); 230 if( levelMenuInfo.levelScores[n] > 8 ) { 231 levelMenuInfo.levelScores[n] = 8; 232 } 233 234 strcpy( levelMenuInfo.levelPicNames[n], va( "levelshots/%s.tga", map ) ); 235 if( !trap_R_RegisterShaderNoMip( levelMenuInfo.levelPicNames[n] ) ) { 236 strcpy( levelMenuInfo.levelPicNames[n], ART_MAP_UNKNOWN ); 237 } 238 levelMenuInfo.item_maps[n].shader = 0; 239 if ( selectedArenaSet > currentSet ) { 240 levelMenuInfo.item_maps[n].generic.flags |= QMF_GRAYED; 241 } 242 else { 243 levelMenuInfo.item_maps[n].generic.flags &= ~QMF_GRAYED; 244 } 245 246 levelMenuInfo.item_maps[n].generic.flags &= ~QMF_INACTIVE; 247 } 248 249 static void UI_SPLevelMenu_SetMenuItems( void ) { 250 int n; 251 int level; 252 const char *arenaInfo; 253 254 if ( selectedArenaSet > currentSet ) { 255 selectedArena = -1; 256 } 257 else if ( selectedArena == -1 ) { 258 selectedArena = 0; 259 } 260 261 if( selectedArenaSet == trainingTier || selectedArenaSet == finalTier ) { 262 selectedArena = 0; 263 } 264 265 if( selectedArena != -1 ) { 266 trap_Cvar_SetValue( "ui_spSelection", selectedArenaSet * ARENAS_PER_TIER + selectedArena ); 267 } 268 269 if( selectedArenaSet == trainingTier ) { 270 arenaInfo = UI_GetSpecialArenaInfo( "training" ); 271 level = atoi( Info_ValueForKey( arenaInfo, "num" ) ); 272 UI_SPLevelMenu_SetMenuArena( 0, level, arenaInfo ); 273 levelMenuInfo.selectedArenaInfo = arenaInfo; 274 275 levelMenuInfo.item_maps[0].generic.x = 256; 276 Bitmap_Init( &levelMenuInfo.item_maps[0] ); 277 levelMenuInfo.item_maps[0].generic.bottom += 32; 278 levelMenuInfo.numMaps = 1; 279 280 levelMenuInfo.item_maps[1].generic.flags |= QMF_INACTIVE; 281 levelMenuInfo.item_maps[2].generic.flags |= QMF_INACTIVE; 282 levelMenuInfo.item_maps[3].generic.flags |= QMF_INACTIVE; 283 levelMenuInfo.levelPicNames[1][0] = 0; 284 levelMenuInfo.levelPicNames[2][0] = 0; 285 levelMenuInfo.levelPicNames[3][0] = 0; 286 levelMenuInfo.item_maps[1].shader = 0; 287 levelMenuInfo.item_maps[2].shader = 0; 288 levelMenuInfo.item_maps[3].shader = 0; 289 } 290 else if( selectedArenaSet == finalTier ) { 291 arenaInfo = UI_GetSpecialArenaInfo( "final" ); 292 level = atoi( Info_ValueForKey( arenaInfo, "num" ) ); 293 UI_SPLevelMenu_SetMenuArena( 0, level, arenaInfo ); 294 levelMenuInfo.selectedArenaInfo = arenaInfo; 295 296 levelMenuInfo.item_maps[0].generic.x = 256; 297 Bitmap_Init( &levelMenuInfo.item_maps[0] ); 298 levelMenuInfo.item_maps[0].generic.bottom += 32; 299 levelMenuInfo.numMaps = 1; 300 301 levelMenuInfo.item_maps[1].generic.flags |= QMF_INACTIVE; 302 levelMenuInfo.item_maps[2].generic.flags |= QMF_INACTIVE; 303 levelMenuInfo.item_maps[3].generic.flags |= QMF_INACTIVE; 304 levelMenuInfo.levelPicNames[1][0] = 0; 305 levelMenuInfo.levelPicNames[2][0] = 0; 306 levelMenuInfo.levelPicNames[3][0] = 0; 307 levelMenuInfo.item_maps[1].shader = 0; 308 levelMenuInfo.item_maps[2].shader = 0; 309 levelMenuInfo.item_maps[3].shader = 0; 310 } 311 else { 312 levelMenuInfo.item_maps[0].generic.x = 46; 313 Bitmap_Init( &levelMenuInfo.item_maps[0] ); 314 levelMenuInfo.item_maps[0].generic.bottom += 18; 315 levelMenuInfo.numMaps = 4; 316 317 for ( n = 0; n < 4; n++ ) { 318 level = selectedArenaSet * ARENAS_PER_TIER + n; 319 arenaInfo = UI_GetArenaInfoByNumber( level ); 320 UI_SPLevelMenu_SetMenuArena( n, level, arenaInfo ); 321 } 322 323 if( selectedArena != -1 ) { 324 levelMenuInfo.selectedArenaInfo = UI_GetArenaInfoByNumber( selectedArenaSet * ARENAS_PER_TIER + selectedArena ); 325 } 326 } 327 328 // enable/disable arrows when they are valid/invalid 329 if ( selectedArenaSet == minTier ) { 330 levelMenuInfo.item_leftarrow.generic.flags |= ( QMF_INACTIVE | QMF_HIDDEN ); 331 } 332 else { 333 levelMenuInfo.item_leftarrow.generic.flags &= ~( QMF_INACTIVE | QMF_HIDDEN ); 334 } 335 336 if ( selectedArenaSet == maxTier ) { 337 levelMenuInfo.item_rightarrow.generic.flags |= ( QMF_INACTIVE | QMF_HIDDEN ); 338 } 339 else { 340 levelMenuInfo.item_rightarrow.generic.flags &= ~( QMF_INACTIVE | QMF_HIDDEN ); 341 } 342 343 UI_SPLevelMenu_SetBots(); 344 } 345 346 347 /* 348 ================= 349 UI_SPLevelMenu_ResetEvent 350 ================= 351 */ 352 static void UI_SPLevelMenu_ResetDraw( void ) { 353 UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 0, "WARNING: This resets all of the", UI_CENTER|UI_SMALLFONT, color_yellow ); 354 UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 1, "single player game variables.", UI_CENTER|UI_SMALLFONT, color_yellow ); 355 UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 2, "Do this only if you want to", UI_CENTER|UI_SMALLFONT, color_yellow ); 356 UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 3, "start over from the beginning.", UI_CENTER|UI_SMALLFONT, color_yellow ); 357 } 358 359 static void UI_SPLevelMenu_ResetAction( qboolean result ) { 360 if( !result ) { 361 return; 362 } 363 364 // clear game variables 365 UI_NewGame(); 366 trap_Cvar_SetValue( "ui_spSelection", -4 ); 367 368 // make the level select menu re-initialize 369 UI_PopMenu(); 370 UI_SPLevelMenu(); 371 } 372 373 static void UI_SPLevelMenu_ResetEvent( void* ptr, int event ) 374 { 375 if (event != QM_ACTIVATED) { 376 return; 377 } 378 379 UI_ConfirmMenu( "RESET GAME?", UI_SPLevelMenu_ResetDraw, UI_SPLevelMenu_ResetAction ); 380 } 381 382 383 /* 384 ================= 385 UI_SPLevelMenu_LevelEvent 386 ================= 387 */ 388 static void UI_SPLevelMenu_LevelEvent( void* ptr, int notification ) { 389 if (notification != QM_ACTIVATED) { 390 return; 391 } 392 393 if ( selectedArenaSet == trainingTier || selectedArenaSet == finalTier ) { 394 return; 395 } 396 397 selectedArena = ((menucommon_s*)ptr)->id - ID_PICTURE0; 398 levelMenuInfo.selectedArenaInfo = UI_GetArenaInfoByNumber( selectedArenaSet * ARENAS_PER_TIER + selectedArena ); 399 UI_SPLevelMenu_SetBots(); 400 401 trap_Cvar_SetValue( "ui_spSelection", selectedArenaSet * ARENAS_PER_TIER + selectedArena ); 402 } 403 404 405 /* 406 ================= 407 UI_SPLevelMenu_LeftArrowEvent 408 ================= 409 */ 410 static void UI_SPLevelMenu_LeftArrowEvent( void* ptr, int notification ) { 411 if (notification != QM_ACTIVATED) { 412 return; 413 } 414 415 if ( selectedArenaSet == minTier ) { 416 return; 417 } 418 419 selectedArenaSet--; 420 UI_SPLevelMenu_SetMenuItems(); 421 } 422 423 424 /* 425 ================= 426 UI_SPLevelMenu_RightArrowEvent 427 ================= 428 */ 429 static void UI_SPLevelMenu_RightArrowEvent( void* ptr, int notification ) { 430 if (notification != QM_ACTIVATED) { 431 return; 432 } 433 434 if ( selectedArenaSet == maxTier ) { 435 return; 436 } 437 438 selectedArenaSet++; 439 UI_SPLevelMenu_SetMenuItems(); 440 } 441 442 443 /* 444 ================= 445 UI_SPLevelMenu_PlayerEvent 446 ================= 447 */ 448 static void UI_SPLevelMenu_PlayerEvent( void* ptr, int notification ) { 449 if (notification != QM_ACTIVATED) { 450 return; 451 } 452 453 UI_PlayerSettingsMenu(); 454 } 455 456 457 /* 458 ================= 459 UI_SPLevelMenu_AwardEvent 460 ================= 461 */ 462 static void UI_SPLevelMenu_AwardEvent( void* ptr, int notification ) { 463 int n; 464 465 if (notification != QM_ACTIVATED) { 466 return; 467 } 468 469 n = ((menucommon_s*)ptr)->id - ID_AWARD1; 470 trap_S_StartLocalSound( levelMenuInfo.awardSounds[n], CHAN_ANNOUNCER ); 471 } 472 473 474 /* 475 ================= 476 UI_SPLevelMenu_NextEvent 477 ================= 478 */ 479 static void UI_SPLevelMenu_NextEvent( void* ptr, int notification ) { 480 if (notification != QM_ACTIVATED) { 481 return; 482 } 483 484 if ( selectedArenaSet > currentSet ) { 485 return; 486 } 487 488 if ( selectedArena == -1 ) { 489 selectedArena = 0; 490 } 491 492 UI_SPSkillMenu( levelMenuInfo.selectedArenaInfo ); 493 } 494 495 496 /* 497 ================= 498 UI_SPLevelMenu_BackEvent 499 ================= 500 */ 501 static void UI_SPLevelMenu_BackEvent( void* ptr, int notification ) { 502 if (notification != QM_ACTIVATED) { 503 return; 504 } 505 506 if ( selectedArena == -1 ) { 507 selectedArena = 0; 508 } 509 510 UI_PopMenu(); 511 } 512 513 514 /* 515 ================= 516 UI_SPLevelMenu_CustomEvent 517 ================= 518 */ 519 static void UI_SPLevelMenu_CustomEvent( void* ptr, int notification ) { 520 if (notification != QM_ACTIVATED) { 521 return; 522 } 523 524 UI_StartServerMenu( qfalse ); 525 } 526 527 528 /* 529 ================= 530 UI_SPLevelMenu_MenuDraw 531 ================= 532 */ 533 #define LEVEL_DESC_LEFT_MARGIN 332 534 535 static void UI_SPLevelMenu_MenuDraw( void ) { 536 int n, i; 537 int x, y; 538 vec4_t color; 539 int level; 540 // int fraglimit; 541 int pad; 542 char buf[MAX_INFO_VALUE]; 543 char string[64]; 544 545 if( levelMenuInfo.reinit ) { 546 UI_PopMenu(); 547 UI_SPLevelMenu(); 548 return; 549 } 550 551 // draw player name 552 trap_Cvar_VariableStringBuffer( "name", string, 32 ); 553 Q_CleanStr( string ); 554 UI_DrawProportionalString( 320, PLAYER_Y, string, UI_CENTER|UI_SMALLFONT, color_orange ); 555 556 // check for model changes 557 trap_Cvar_VariableStringBuffer( "model", buf, sizeof(buf) ); 558 if( Q_stricmp( buf, levelMenuInfo.playerModel ) != 0 ) { 559 Q_strncpyz( levelMenuInfo.playerModel, buf, sizeof(levelMenuInfo.playerModel) ); 560 PlayerIcon( levelMenuInfo.playerModel, levelMenuInfo.playerPicName, sizeof(levelMenuInfo.playerPicName) ); 561 levelMenuInfo.item_player.shader = 0; 562 } 563 564 // standard menu drawing 565 Menu_Draw( &levelMenuInfo.menu ); 566 567 // draw player award levels 568 y = AWARDS_Y; 569 i = 0; 570 for( n = 0; n < 6; n++ ) { 571 level = levelMenuInfo.awardLevels[n]; 572 if( level > 0 ) { 573 if( i & 1 ) { 574 x = 224 - (i - 1 ) / 2 * (48 + 16); 575 } 576 else { 577 x = 368 + i / 2 * (48 + 16); 578 } 579 i++; 580 581 if( level == 1 ) { 582 continue; 583 } 584 585 if( level >= 1000000 ) { 586 Com_sprintf( string, sizeof(string), "%im", level / 1000000 ); 587 } 588 else if( level >= 1000 ) { 589 Com_sprintf( string, sizeof(string), "%ik", level / 1000 ); 590 } 591 else { 592 Com_sprintf( string, sizeof(string), "%i", level ); 593 } 594 595 UI_DrawString( x + 24, y + 48, string, UI_CENTER, color_yellow ); 596 } 597 } 598 599 UI_DrawProportionalString( 18, 38, va( "Tier %i", selectedArenaSet + 1 ), UI_LEFT|UI_SMALLFONT, color_orange ); 600 601 for ( n = 0; n < levelMenuInfo.numMaps; n++ ) { 602 x = levelMenuInfo.item_maps[n].generic.x; 603 y = levelMenuInfo.item_maps[n].generic.y; 604 UI_FillRect( x, y + 96, 128, 18, color_black ); 605 } 606 607 if ( selectedArenaSet > currentSet ) { 608 UI_DrawProportionalString( 320, 216, "ACCESS DENIED", UI_CENTER|UI_BIGFONT, color_red ); 609 return; 610 } 611 612 // show levelshots for levels of current tier 613 Vector4Copy( color_white, color ); 614 color[3] = 0.5+0.5*sin(uis.realtime/PULSE_DIVISOR); 615 for ( n = 0; n < levelMenuInfo.numMaps; n++ ) { 616 x = levelMenuInfo.item_maps[n].generic.x; 617 y = levelMenuInfo.item_maps[n].generic.y; 618 619 UI_DrawString( x + 64, y + 96, levelMenuInfo.levelNames[n], UI_CENTER|UI_SMALLFONT, color_orange ); 620 621 if( levelMenuInfo.levelScores[n] == 1 ) { 622 UI_DrawHandlePic( x, y, 128, 96, levelMenuInfo.levelCompletePic[levelMenuInfo.levelScoresSkill[n] - 1] ); 623 } 624 625 if ( n == selectedArena ) { 626 if( Menu_ItemAtCursor( &levelMenuInfo.menu ) == &levelMenuInfo.item_maps[n] ) { 627 trap_R_SetColor( color ); 628 } 629 UI_DrawHandlePic( x-1, y-1, 130, 130 - 14, levelMenuInfo.levelSelectedPic ); 630 trap_R_SetColor( NULL ); 631 } 632 else if( Menu_ItemAtCursor( &levelMenuInfo.menu ) == &levelMenuInfo.item_maps[n] ) { 633 trap_R_SetColor( color ); 634 UI_DrawHandlePic( x-31, y-30, 256, 256-27, levelMenuInfo.levelFocusPic); 635 trap_R_SetColor( NULL ); 636 } 637 } 638 639 // show map name and long name of selected level 640 y = 192; 641 Q_strncpyz( buf, Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "map" ), 20 ); 642 Q_strupr( buf ); 643 Com_sprintf( string, sizeof(string), "%s: %s", buf, Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "longname" ) ); 644 UI_DrawProportionalString( 320, y, string, UI_CENTER|UI_SMALLFONT, color_orange ); 645 646 // fraglimit = atoi( Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "fraglimit" ) ); 647 // UI_DrawString( 18, 212, va("Frags %i", fraglimit) , UI_LEFT|UI_SMALLFONT, color_orange ); 648 649 // draw bot opponents 650 y += 24; 651 pad = (7 - levelMenuInfo.numBots) * (64 + 26) / 2; 652 for( n = 0; n < levelMenuInfo.numBots; n++ ) { 653 x = 18 + pad + (64 + 26) * n; 654 if( levelMenuInfo.botPics[n] ) { 655 UI_DrawHandlePic( x, y, 64, 64, levelMenuInfo.botPics[n]); 656 } 657 else { 658 UI_FillRect( x, y, 64, 64, color_black ); 659 UI_DrawProportionalString( x+22, y+18, "?", UI_BIGFONT, color_orange ); 660 } 661 UI_DrawString( x, y + 64, levelMenuInfo.botNames[n], UI_SMALLFONT|UI_LEFT, color_orange ); 662 } 663 } 664 665 666 /* 667 ================= 668 UI_SPLevelMenu_Cache 669 ================= 670 */ 671 void UI_SPLevelMenu_Cache( void ) { 672 int n; 673 674 trap_R_RegisterShaderNoMip( ART_LEVELFRAME_FOCUS ); 675 trap_R_RegisterShaderNoMip( ART_LEVELFRAME_SELECTED ); 676 trap_R_RegisterShaderNoMip( ART_ARROW ); 677 trap_R_RegisterShaderNoMip( ART_ARROW_FOCUS ); 678 trap_R_RegisterShaderNoMip( ART_MAP_UNKNOWN ); 679 trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE1 ); 680 trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE2 ); 681 trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE3 ); 682 trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE4 ); 683 trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE5 ); 684 trap_R_RegisterShaderNoMip( ART_BACK0 ); 685 trap_R_RegisterShaderNoMip( ART_BACK1 ); 686 trap_R_RegisterShaderNoMip( ART_FIGHT0 ); 687 trap_R_RegisterShaderNoMip( ART_FIGHT1 ); 688 trap_R_RegisterShaderNoMip( ART_RESET0 ); 689 trap_R_RegisterShaderNoMip( ART_RESET1 ); 690 trap_R_RegisterShaderNoMip( ART_CUSTOM0 ); 691 trap_R_RegisterShaderNoMip( ART_CUSTOM1 ); 692 693 for( n = 0; n < 6; n++ ) { 694 trap_R_RegisterShaderNoMip( ui_medalPicNames[n] ); 695 levelMenuInfo.awardSounds[n] = trap_S_RegisterSound( ui_medalSounds[n], qfalse ); 696 } 697 698 levelMenuInfo.levelSelectedPic = trap_R_RegisterShaderNoMip( ART_LEVELFRAME_SELECTED ); 699 levelMenuInfo.levelFocusPic = trap_R_RegisterShaderNoMip( ART_LEVELFRAME_FOCUS ); 700 levelMenuInfo.levelCompletePic[0] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE1 ); 701 levelMenuInfo.levelCompletePic[1] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE2 ); 702 levelMenuInfo.levelCompletePic[2] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE3 ); 703 levelMenuInfo.levelCompletePic[3] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE4 ); 704 levelMenuInfo.levelCompletePic[4] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE5 ); 705 } 706 707 708 /* 709 ================= 710 UI_SPLevelMenu_Init 711 ================= 712 */ 713 static void UI_SPLevelMenu_Init( void ) { 714 int skill; 715 int n; 716 int x, y; 717 int count; 718 char buf[MAX_QPATH]; 719 720 skill = (int)trap_Cvar_VariableValue( "g_spSkill" ); 721 if( skill < 1 || skill > 5 ) { 722 trap_Cvar_Set( "g_spSkill", "2" ); 723 skill = 2; 724 } 725 726 memset( &levelMenuInfo, 0, sizeof(levelMenuInfo) ); 727 levelMenuInfo.menu.fullscreen = qtrue; 728 levelMenuInfo.menu.wrapAround = qtrue; 729 levelMenuInfo.menu.draw = UI_SPLevelMenu_MenuDraw; 730 731 UI_SPLevelMenu_Cache(); 732 733 levelMenuInfo.item_banner.generic.type = MTYPE_BTEXT; 734 levelMenuInfo.item_banner.generic.x = 320; 735 levelMenuInfo.item_banner.generic.y = 16; 736 levelMenuInfo.item_banner.string = "CHOOSE LEVEL"; 737 levelMenuInfo.item_banner.color = color_red; 738 levelMenuInfo.item_banner.style = UI_CENTER; 739 740 levelMenuInfo.item_leftarrow.generic.type = MTYPE_BITMAP; 741 levelMenuInfo.item_leftarrow.generic.name = ART_ARROW; 742 levelMenuInfo.item_leftarrow.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; 743 levelMenuInfo.item_leftarrow.generic.x = 18; 744 levelMenuInfo.item_leftarrow.generic.y = 64; 745 levelMenuInfo.item_leftarrow.generic.callback = UI_SPLevelMenu_LeftArrowEvent; 746 levelMenuInfo.item_leftarrow.generic.id = ID_LEFTARROW; 747 levelMenuInfo.item_leftarrow.width = 16; 748 levelMenuInfo.item_leftarrow.height = 114; 749 levelMenuInfo.item_leftarrow.focuspic = ART_ARROW_FOCUS; 750 751 levelMenuInfo.item_maps[0].generic.type = MTYPE_BITMAP; 752 levelMenuInfo.item_maps[0].generic.name = levelMenuInfo.levelPicNames[0]; 753 levelMenuInfo.item_maps[0].generic.flags = QMF_LEFT_JUSTIFY; 754 levelMenuInfo.item_maps[0].generic.x = 46; 755 levelMenuInfo.item_maps[0].generic.y = 64; 756 levelMenuInfo.item_maps[0].generic.id = ID_PICTURE0; 757 levelMenuInfo.item_maps[0].generic.callback = UI_SPLevelMenu_LevelEvent; 758 levelMenuInfo.item_maps[0].width = 128; 759 levelMenuInfo.item_maps[0].height = 96; 760 761 levelMenuInfo.item_maps[1].generic.type = MTYPE_BITMAP; 762 levelMenuInfo.item_maps[1].generic.name = levelMenuInfo.levelPicNames[1]; 763 levelMenuInfo.item_maps[1].generic.flags = QMF_LEFT_JUSTIFY; 764 levelMenuInfo.item_maps[1].generic.x = 186; 765 levelMenuInfo.item_maps[1].generic.y = 64; 766 levelMenuInfo.item_maps[1].generic.id = ID_PICTURE1; 767 levelMenuInfo.item_maps[1].generic.callback = UI_SPLevelMenu_LevelEvent; 768 levelMenuInfo.item_maps[1].width = 128; 769 levelMenuInfo.item_maps[1].height = 96; 770 771 levelMenuInfo.item_maps[2].generic.type = MTYPE_BITMAP; 772 levelMenuInfo.item_maps[2].generic.name = levelMenuInfo.levelPicNames[2]; 773 levelMenuInfo.item_maps[2].generic.flags = QMF_LEFT_JUSTIFY; 774 levelMenuInfo.item_maps[2].generic.x = 326; 775 levelMenuInfo.item_maps[2].generic.y = 64; 776 levelMenuInfo.item_maps[2].generic.id = ID_PICTURE2; 777 levelMenuInfo.item_maps[2].generic.callback = UI_SPLevelMenu_LevelEvent; 778 levelMenuInfo.item_maps[2].width = 128; 779 levelMenuInfo.item_maps[2].height = 96; 780 781 levelMenuInfo.item_maps[3].generic.type = MTYPE_BITMAP; 782 levelMenuInfo.item_maps[3].generic.name = levelMenuInfo.levelPicNames[3]; 783 levelMenuInfo.item_maps[3].generic.flags = QMF_LEFT_JUSTIFY; 784 levelMenuInfo.item_maps[3].generic.x = 466; 785 levelMenuInfo.item_maps[3].generic.y = 64; 786 levelMenuInfo.item_maps[3].generic.id = ID_PICTURE3; 787 levelMenuInfo.item_maps[3].generic.callback = UI_SPLevelMenu_LevelEvent; 788 levelMenuInfo.item_maps[3].width = 128; 789 levelMenuInfo.item_maps[3].height = 96; 790 791 levelMenuInfo.item_rightarrow.generic.type = MTYPE_BITMAP; 792 levelMenuInfo.item_rightarrow.generic.name = ART_ARROW; 793 levelMenuInfo.item_rightarrow.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; 794 levelMenuInfo.item_rightarrow.generic.x = 606; 795 levelMenuInfo.item_rightarrow.generic.y = 64; 796 levelMenuInfo.item_rightarrow.generic.callback = UI_SPLevelMenu_RightArrowEvent; 797 levelMenuInfo.item_rightarrow.generic.id = ID_RIGHTARROW; 798 levelMenuInfo.item_rightarrow.width = -16; 799 levelMenuInfo.item_rightarrow.height = 114; 800 levelMenuInfo.item_rightarrow.focuspic = ART_ARROW_FOCUS; 801 802 trap_Cvar_VariableStringBuffer( "model", levelMenuInfo.playerModel, sizeof(levelMenuInfo.playerModel) ); 803 PlayerIcon( levelMenuInfo.playerModel, levelMenuInfo.playerPicName, sizeof(levelMenuInfo.playerPicName) ); 804 levelMenuInfo.item_player.generic.type = MTYPE_BITMAP; 805 levelMenuInfo.item_player.generic.name = levelMenuInfo.playerPicName; 806 levelMenuInfo.item_player.generic.flags = QMF_LEFT_JUSTIFY|QMF_MOUSEONLY; 807 levelMenuInfo.item_player.generic.x = 288; 808 levelMenuInfo.item_player.generic.y = AWARDS_Y; 809 levelMenuInfo.item_player.generic.id = ID_PLAYERPIC; 810 levelMenuInfo.item_player.generic.callback = UI_SPLevelMenu_PlayerEvent; 811 levelMenuInfo.item_player.width = 64; 812 levelMenuInfo.item_player.height = 64; 813 814 for( n = 0; n < 6; n++ ) { 815 levelMenuInfo.awardLevels[n] = UI_GetAwardLevel( n ); 816 } 817 levelMenuInfo.awardLevels[AWARD_FRAGS] = 100 * (levelMenuInfo.awardLevels[AWARD_FRAGS] / 100); 818 819 y = AWARDS_Y; 820 count = 0; 821 for( n = 0; n < 6; n++ ) { 822 if( levelMenuInfo.awardLevels[n] ) { 823 if( count & 1 ) { 824 x = 224 - (count - 1 ) / 2 * (48 + 16); 825 } 826 else { 827 x = 368 + count / 2 * (48 + 16); 828 } 829 830 levelMenuInfo.item_awards[count].generic.type = MTYPE_BITMAP; 831 levelMenuInfo.item_awards[count].generic.name = ui_medalPicNames[n]; 832 levelMenuInfo.item_awards[count].generic.flags = QMF_LEFT_JUSTIFY|QMF_SILENT|QMF_MOUSEONLY; 833 levelMenuInfo.item_awards[count].generic.x = x; 834 levelMenuInfo.item_awards[count].generic.y = y; 835 levelMenuInfo.item_awards[count].generic.id = ID_AWARD1 + n; 836 levelMenuInfo.item_awards[count].generic.callback = UI_SPLevelMenu_AwardEvent; 837 levelMenuInfo.item_awards[count].width = 48; 838 levelMenuInfo.item_awards[count].height = 48; 839 count++; 840 } 841 } 842 843 levelMenuInfo.item_back.generic.type = MTYPE_BITMAP; 844 levelMenuInfo.item_back.generic.name = ART_BACK0; 845 levelMenuInfo.item_back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; 846 levelMenuInfo.item_back.generic.x = 0; 847 levelMenuInfo.item_back.generic.y = 480-64; 848 levelMenuInfo.item_back.generic.callback = UI_SPLevelMenu_BackEvent; 849 levelMenuInfo.item_back.generic.id = ID_BACK; 850 levelMenuInfo.item_back.width = 128; 851 levelMenuInfo.item_back.height = 64; 852 levelMenuInfo.item_back.focuspic = ART_BACK1; 853 854 levelMenuInfo.item_reset.generic.type = MTYPE_BITMAP; 855 levelMenuInfo.item_reset.generic.name = ART_RESET0; 856 levelMenuInfo.item_reset.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; 857 levelMenuInfo.item_reset.generic.x = 170; 858 levelMenuInfo.item_reset.generic.y = 480-64; 859 levelMenuInfo.item_reset.generic.callback = UI_SPLevelMenu_ResetEvent; 860 levelMenuInfo.item_reset.generic.id = ID_RESET; 861 levelMenuInfo.item_reset.width = 128; 862 levelMenuInfo.item_reset.height = 64; 863 levelMenuInfo.item_reset.focuspic = ART_RESET1; 864 865 levelMenuInfo.item_custom.generic.type = MTYPE_BITMAP; 866 levelMenuInfo.item_custom.generic.name = ART_CUSTOM0; 867 levelMenuInfo.item_custom.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; 868 levelMenuInfo.item_custom.generic.x = 342; 869 levelMenuInfo.item_custom.generic.y = 480-64; 870 levelMenuInfo.item_custom.generic.callback = UI_SPLevelMenu_CustomEvent; 871 levelMenuInfo.item_custom.generic.id = ID_CUSTOM; 872 levelMenuInfo.item_custom.width = 128; 873 levelMenuInfo.item_custom.height = 64; 874 levelMenuInfo.item_custom.focuspic = ART_CUSTOM1; 875 876 levelMenuInfo.item_next.generic.type = MTYPE_BITMAP; 877 levelMenuInfo.item_next.generic.name = ART_FIGHT0; 878 levelMenuInfo.item_next.generic.flags = QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS; 879 levelMenuInfo.item_next.generic.x = 640; 880 levelMenuInfo.item_next.generic.y = 480-64; 881 levelMenuInfo.item_next.generic.callback = UI_SPLevelMenu_NextEvent; 882 levelMenuInfo.item_next.generic.id = ID_NEXT; 883 levelMenuInfo.item_next.width = 128; 884 levelMenuInfo.item_next.height = 64; 885 levelMenuInfo.item_next.focuspic = ART_FIGHT1; 886 887 levelMenuInfo.item_null.generic.type = MTYPE_BITMAP; 888 levelMenuInfo.item_null.generic.flags = QMF_LEFT_JUSTIFY|QMF_MOUSEONLY|QMF_SILENT; 889 levelMenuInfo.item_null.generic.x = 0; 890 levelMenuInfo.item_null.generic.y = 0; 891 levelMenuInfo.item_null.width = 640; 892 levelMenuInfo.item_null.height = 480; 893 894 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_banner ); 895 896 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_leftarrow ); 897 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_maps[0] ); 898 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_maps[1] ); 899 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_maps[2] ); 900 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_maps[3] ); 901 levelMenuInfo.item_maps[0].generic.bottom += 18; 902 levelMenuInfo.item_maps[1].generic.bottom += 18; 903 levelMenuInfo.item_maps[2].generic.bottom += 18; 904 levelMenuInfo.item_maps[3].generic.bottom += 18; 905 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_rightarrow ); 906 907 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_player ); 908 909 for( n = 0; n < count; n++ ) { 910 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_awards[n] ); 911 } 912 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_back ); 913 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_reset ); 914 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_custom ); 915 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_next ); 916 Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_null ); 917 918 trap_Cvar_VariableStringBuffer( "ui_spSelection", buf, sizeof(buf) ); 919 if( *buf ) { 920 n = atoi( buf ); 921 selectedArenaSet = n / ARENAS_PER_TIER; 922 selectedArena = n % ARENAS_PER_TIER; 923 } 924 else { 925 selectedArenaSet = currentSet; 926 selectedArena = currentGame; 927 } 928 929 UI_SPLevelMenu_SetMenuItems(); 930 } 931 932 933 /* 934 ================= 935 UI_SPLevelMenu 936 ================= 937 */ 938 void UI_SPLevelMenu( void ) { 939 int level; 940 int trainingLevel; 941 const char *arenaInfo; 942 943 trainingTier = -1; 944 arenaInfo = UI_GetSpecialArenaInfo( "training" ); 945 if( arenaInfo ) { 946 minTier = trainingTier; 947 trainingLevel = atoi( Info_ValueForKey( arenaInfo, "num" ) ); 948 } 949 else { 950 minTier = 0; 951 trainingLevel = -2; 952 } 953 954 finalTier = UI_GetNumSPTiers(); 955 arenaInfo = UI_GetSpecialArenaInfo( "final" ); 956 if( arenaInfo ) { 957 maxTier = finalTier; 958 } 959 else { 960 maxTier = finalTier - 1; 961 if( maxTier < minTier ) { 962 maxTier = minTier; 963 } 964 } 965 966 level = UI_GetCurrentGame(); 967 if ( level == -1 ) { 968 level = UI_GetNumSPArenas() - 1; 969 if( maxTier == finalTier ) { 970 level++; 971 } 972 } 973 974 if( level == trainingLevel ) { 975 currentSet = -1; 976 currentGame = 0; 977 } 978 else { 979 currentSet = level / ARENAS_PER_TIER; 980 currentGame = level % ARENAS_PER_TIER; 981 } 982 983 UI_SPLevelMenu_Init(); 984 UI_PushMenu( &levelMenuInfo.menu ); 985 Menu_SetCursorToItem( &levelMenuInfo.menu, &levelMenuInfo.item_next ); 986 } 987 988 989 /* 990 ================= 991 UI_SPLevelMenu_f 992 ================= 993 */ 994 void UI_SPLevelMenu_f( void ) { 995 trap_Key_SetCatcher( KEYCATCH_UI ); 996 uis.menusp = 0; 997 UI_SPLevelMenu(); 998 } 999 1000 1001 /* 1002 ================= 1003 UI_SPLevelMenu_ReInit 1004 ================= 1005 */ 1006 void UI_SPLevelMenu_ReInit( void ) { 1007 levelMenuInfo.reinit = qtrue; 1008 }