ui_sppostgame.c (18879B)
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 POSTGAME MENU 27 28 ============================================================================= 29 */ 30 31 #include "ui_local.h" 32 33 #define MAX_SCOREBOARD_CLIENTS 8 34 35 #define AWARD_PRESENTATION_TIME 2000 36 37 #define ART_MENU0 "menu/art/menu_0" 38 #define ART_MENU1 "menu/art/menu_1" 39 #define ART_REPLAY0 "menu/art/replay_0" 40 #define ART_REPLAY1 "menu/art/replay_1" 41 #define ART_NEXT0 "menu/art/next_0" 42 #define ART_NEXT1 "menu/art/next_1" 43 44 #define ID_AGAIN 10 45 #define ID_NEXT 11 46 #define ID_MENU 12 47 48 typedef struct { 49 menuframework_s menu; 50 menubitmap_s item_again; 51 menubitmap_s item_next; 52 menubitmap_s item_menu; 53 54 int phase; 55 int ignoreKeysTime; 56 int starttime; 57 int scoreboardtime; 58 int serverId; 59 60 int clientNums[MAX_SCOREBOARD_CLIENTS]; 61 int ranks[MAX_SCOREBOARD_CLIENTS]; 62 int scores[MAX_SCOREBOARD_CLIENTS]; 63 64 char placeNames[3][64]; 65 66 int level; 67 int numClients; 68 int won; 69 int numAwards; 70 int awardsEarned[6]; 71 int awardsLevels[6]; 72 qboolean playedSound[6]; 73 int lastTier; 74 sfxHandle_t winnerSound; 75 } postgameMenuInfo_t; 76 77 static postgameMenuInfo_t postgameMenuInfo; 78 static char arenainfo[MAX_INFO_VALUE]; 79 80 char *ui_medalNames[] = {"Accuracy", "Impressive", "Excellent", "Gauntlet", "Frags", "Perfect"}; 81 char *ui_medalPicNames[] = { 82 "menu/medals/medal_accuracy", 83 "menu/medals/medal_impressive", 84 "menu/medals/medal_excellent", 85 "menu/medals/medal_gauntlet", 86 "menu/medals/medal_frags", 87 "menu/medals/medal_victory" 88 }; 89 char *ui_medalSounds[] = { 90 "sound/feedback/accuracy.wav", 91 "sound/feedback/impressive_a.wav", 92 "sound/feedback/excellent_a.wav", 93 "sound/feedback/gauntlet.wav", 94 "sound/feedback/frags.wav", 95 "sound/feedback/perfect.wav" 96 }; 97 98 99 /* 100 ================= 101 UI_SPPostgameMenu_AgainEvent 102 ================= 103 */ 104 static void UI_SPPostgameMenu_AgainEvent( void* ptr, int event ) 105 { 106 if (event != QM_ACTIVATED) { 107 return; 108 } 109 UI_PopMenu(); 110 trap_Cmd_ExecuteText( EXEC_APPEND, "map_restart 0\n" ); 111 } 112 113 114 /* 115 ================= 116 UI_SPPostgameMenu_NextEvent 117 ================= 118 */ 119 static void UI_SPPostgameMenu_NextEvent( void* ptr, int event ) { 120 int currentSet; 121 int levelSet; 122 int level; 123 int currentLevel; 124 const char *arenaInfo; 125 126 if (event != QM_ACTIVATED) { 127 return; 128 } 129 UI_PopMenu(); 130 131 // handle specially if we just won the training map 132 if( postgameMenuInfo.won == 0 ) { 133 level = 0; 134 } 135 else { 136 level = postgameMenuInfo.level + 1; 137 } 138 levelSet = level / ARENAS_PER_TIER; 139 140 currentLevel = UI_GetCurrentGame(); 141 if( currentLevel == -1 ) { 142 currentLevel = postgameMenuInfo.level; 143 } 144 currentSet = currentLevel / ARENAS_PER_TIER; 145 146 if( levelSet > currentSet || levelSet == UI_GetNumSPTiers() ) { 147 level = currentLevel; 148 } 149 150 arenaInfo = UI_GetArenaInfoByNumber( level ); 151 if ( !arenaInfo ) { 152 return; 153 } 154 155 UI_SPArena_Start( arenaInfo ); 156 } 157 158 159 /* 160 ================= 161 UI_SPPostgameMenu_MenuEvent 162 ================= 163 */ 164 static void UI_SPPostgameMenu_MenuEvent( void* ptr, int event ) 165 { 166 if (event != QM_ACTIVATED) { 167 return; 168 } 169 UI_PopMenu(); 170 trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect; levelselect\n" ); 171 } 172 173 174 /* 175 ================= 176 UI_SPPostgameMenu_MenuKey 177 ================= 178 */ 179 static sfxHandle_t UI_SPPostgameMenu_MenuKey( int key ) { 180 if ( uis.realtime < postgameMenuInfo.ignoreKeysTime ) { 181 return 0; 182 } 183 184 if( postgameMenuInfo.phase == 1 ) { 185 trap_Cmd_ExecuteText( EXEC_APPEND, "abort_podium\n" ); 186 postgameMenuInfo.phase = 2; 187 postgameMenuInfo.starttime = uis.realtime; 188 postgameMenuInfo.ignoreKeysTime = uis.realtime + 250; 189 return 0; 190 } 191 192 if( postgameMenuInfo.phase == 2 ) { 193 postgameMenuInfo.phase = 3; 194 postgameMenuInfo.starttime = uis.realtime; 195 postgameMenuInfo.ignoreKeysTime = uis.realtime + 250; 196 return 0; 197 } 198 199 if( key == K_ESCAPE || key == K_MOUSE2 ) { 200 return 0; 201 } 202 203 return Menu_DefaultKey( &postgameMenuInfo.menu, key ); 204 } 205 206 207 static int medalLocations[6] = {144, 448, 88, 504, 32, 560}; 208 209 static void UI_SPPostgameMenu_DrawAwardsMedals( int max ) { 210 int n; 211 int medal; 212 int amount; 213 int x, y; 214 char buf[16]; 215 216 for( n = 0; n < max; n++ ) { 217 x = medalLocations[n]; 218 y = 64; 219 medal = postgameMenuInfo.awardsEarned[n]; 220 amount = postgameMenuInfo.awardsLevels[n]; 221 222 UI_DrawNamedPic( x, y, 48, 48, ui_medalPicNames[medal] ); 223 224 if( medal == AWARD_ACCURACY ) { 225 Com_sprintf( buf, sizeof(buf), "%i%%", amount ); 226 } 227 else { 228 if( amount == 1 ) { 229 continue; 230 } 231 Com_sprintf( buf, sizeof(buf), "%i", amount ); 232 } 233 234 UI_DrawString( x + 24, y + 52, buf, UI_CENTER, color_yellow ); 235 } 236 } 237 238 239 static void UI_SPPostgameMenu_DrawAwardsPresentation( int timer ) { 240 int awardNum; 241 int atimer; 242 vec4_t color; 243 244 awardNum = timer / AWARD_PRESENTATION_TIME; 245 atimer = timer % AWARD_PRESENTATION_TIME; 246 247 color[0] = color[1] = color[2] = 1.0f; 248 color[3] = (float)( AWARD_PRESENTATION_TIME - atimer ) / (float)AWARD_PRESENTATION_TIME; 249 UI_DrawProportionalString( 320, 64, ui_medalNames[postgameMenuInfo.awardsEarned[awardNum]], UI_CENTER, color ); 250 251 UI_SPPostgameMenu_DrawAwardsMedals( awardNum + 1 ); 252 253 if( !postgameMenuInfo.playedSound[awardNum] ) { 254 postgameMenuInfo.playedSound[awardNum] = qtrue; 255 trap_S_StartLocalSound( trap_S_RegisterSound( ui_medalSounds[postgameMenuInfo.awardsEarned[awardNum]], qfalse ), CHAN_ANNOUNCER ); 256 } 257 } 258 259 260 /* 261 ================= 262 UI_SPPostgameMenu_MenuDrawScoreLine 263 ================= 264 */ 265 static void UI_SPPostgameMenu_MenuDrawScoreLine( int n, int y ) { 266 int rank; 267 char name[64]; 268 char info[MAX_INFO_STRING]; 269 270 if( n > (postgameMenuInfo.numClients + 1) ) { 271 n -= (postgameMenuInfo.numClients + 2); 272 } 273 274 if( n >= postgameMenuInfo.numClients ) { 275 return; 276 } 277 278 rank = postgameMenuInfo.ranks[n]; 279 if( rank & RANK_TIED_FLAG ) { 280 UI_DrawString( 640 - 31 * SMALLCHAR_WIDTH, y, "(tie)", UI_LEFT|UI_SMALLFONT, color_white ); 281 rank &= ~RANK_TIED_FLAG; 282 } 283 trap_GetConfigString( CS_PLAYERS + postgameMenuInfo.clientNums[n], info, MAX_INFO_STRING ); 284 Q_strncpyz( name, Info_ValueForKey( info, "n" ), sizeof(name) ); 285 Q_CleanStr( name ); 286 287 UI_DrawString( 640 - 25 * SMALLCHAR_WIDTH, y, va( "#%i: %-16s %2i", rank + 1, name, postgameMenuInfo.scores[n] ), UI_LEFT|UI_SMALLFONT, color_white ); 288 } 289 290 291 /* 292 ================= 293 UI_SPPostgameMenu_MenuDraw 294 ================= 295 */ 296 static void UI_SPPostgameMenu_MenuDraw( void ) { 297 int timer; 298 int serverId; 299 int n; 300 char info[MAX_INFO_STRING]; 301 302 trap_GetConfigString( CS_SYSTEMINFO, info, sizeof(info) ); 303 serverId = atoi( Info_ValueForKey( info, "sv_serverid" ) ); 304 if( serverId != postgameMenuInfo.serverId ) { 305 UI_PopMenu(); 306 return; 307 } 308 309 // phase 1 310 if ( postgameMenuInfo.numClients > 2 ) { 311 UI_DrawProportionalString( 510, 480 - 64 - PROP_HEIGHT, postgameMenuInfo.placeNames[2], UI_CENTER, color_white ); 312 } 313 UI_DrawProportionalString( 130, 480 - 64 - PROP_HEIGHT, postgameMenuInfo.placeNames[1], UI_CENTER, color_white ); 314 UI_DrawProportionalString( 320, 480 - 64 - 2 * PROP_HEIGHT, postgameMenuInfo.placeNames[0], UI_CENTER, color_white ); 315 316 if( postgameMenuInfo.phase == 1 ) { 317 timer = uis.realtime - postgameMenuInfo.starttime; 318 319 if( timer >= 1000 && postgameMenuInfo.winnerSound ) { 320 trap_S_StartLocalSound( postgameMenuInfo.winnerSound, CHAN_ANNOUNCER ); 321 postgameMenuInfo.winnerSound = 0; 322 } 323 324 if( timer < 5000 ) { 325 return; 326 } 327 postgameMenuInfo.phase = 2; 328 postgameMenuInfo.starttime = uis.realtime; 329 } 330 331 // phase 2 332 if( postgameMenuInfo.phase == 2 ) { 333 timer = uis.realtime - postgameMenuInfo.starttime; 334 if( timer >= ( postgameMenuInfo.numAwards * AWARD_PRESENTATION_TIME ) ) { 335 336 if( timer < 5000 ) { 337 return; 338 } 339 340 postgameMenuInfo.phase = 3; 341 postgameMenuInfo.starttime = uis.realtime; 342 } 343 else { 344 UI_SPPostgameMenu_DrawAwardsPresentation( timer ); 345 } 346 } 347 348 // phase 3 349 if( postgameMenuInfo.phase == 3 ) { 350 if( uis.demoversion ) { 351 if( postgameMenuInfo.won == 1 && UI_ShowTierVideo( 8 )) { 352 trap_Cvar_Set( "nextmap", "" ); 353 trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect; cinematic demoEnd.RoQ\n" ); 354 return; 355 } 356 } 357 else if( postgameMenuInfo.won > -1 && UI_ShowTierVideo( postgameMenuInfo.won + 1 )) { 358 if( postgameMenuInfo.won == postgameMenuInfo.lastTier ) { 359 trap_Cvar_Set( "nextmap", "" ); 360 trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect; cinematic end.RoQ\n" ); 361 return; 362 } 363 364 trap_Cvar_SetValue( "ui_spSelection", postgameMenuInfo.won * ARENAS_PER_TIER ); 365 trap_Cvar_Set( "nextmap", "levelselect" ); 366 trap_Cmd_ExecuteText( EXEC_APPEND, va( "disconnect; cinematic tier%i.RoQ\n", postgameMenuInfo.won + 1 ) ); 367 return; 368 } 369 370 postgameMenuInfo.item_again.generic.flags &= ~QMF_INACTIVE; 371 postgameMenuInfo.item_next.generic.flags &= ~QMF_INACTIVE; 372 postgameMenuInfo.item_menu.generic.flags &= ~QMF_INACTIVE; 373 374 UI_SPPostgameMenu_DrawAwardsMedals( postgameMenuInfo.numAwards ); 375 376 Menu_Draw( &postgameMenuInfo.menu ); 377 } 378 379 // draw the scoreboard 380 if( !trap_Cvar_VariableValue( "ui_spScoreboard" ) ) { 381 return; 382 } 383 384 timer = uis.realtime - postgameMenuInfo.scoreboardtime; 385 if( postgameMenuInfo.numClients <= 3 ) { 386 n = 0; 387 } 388 else { 389 n = timer / 1500 % (postgameMenuInfo.numClients + 2); 390 } 391 UI_SPPostgameMenu_MenuDrawScoreLine( n, 0 ); 392 UI_SPPostgameMenu_MenuDrawScoreLine( n + 1, 0 + SMALLCHAR_HEIGHT ); 393 UI_SPPostgameMenu_MenuDrawScoreLine( n + 2, 0 + 2 * SMALLCHAR_HEIGHT ); 394 } 395 396 397 /* 398 ================= 399 UI_SPPostgameMenu_Cache 400 ================= 401 */ 402 void UI_SPPostgameMenu_Cache( void ) { 403 int n; 404 qboolean buildscript; 405 406 buildscript = trap_Cvar_VariableValue("com_buildscript"); 407 408 trap_R_RegisterShaderNoMip( ART_MENU0 ); 409 trap_R_RegisterShaderNoMip( ART_MENU1 ); 410 trap_R_RegisterShaderNoMip( ART_REPLAY0 ); 411 trap_R_RegisterShaderNoMip( ART_REPLAY1 ); 412 trap_R_RegisterShaderNoMip( ART_NEXT0 ); 413 trap_R_RegisterShaderNoMip( ART_NEXT1 ); 414 for( n = 0; n < 6; n++ ) { 415 trap_R_RegisterShaderNoMip( ui_medalPicNames[n] ); 416 trap_S_RegisterSound( ui_medalSounds[n], qfalse ); 417 } 418 419 if( buildscript ) { 420 trap_S_RegisterSound( "music/loss.wav", qfalse ); 421 trap_S_RegisterSound( "music/win.wav", qfalse ); 422 trap_S_RegisterSound( "sound/player/announce/youwin.wav", qfalse ); 423 } 424 } 425 426 427 /* 428 ================= 429 UI_SPPostgameMenu_Init 430 ================= 431 */ 432 static void UI_SPPostgameMenu_Init( void ) { 433 postgameMenuInfo.menu.wrapAround = qtrue; 434 postgameMenuInfo.menu.key = UI_SPPostgameMenu_MenuKey; 435 postgameMenuInfo.menu.draw = UI_SPPostgameMenu_MenuDraw; 436 postgameMenuInfo.ignoreKeysTime = uis.realtime + 1500; 437 438 UI_SPPostgameMenu_Cache(); 439 440 postgameMenuInfo.item_menu.generic.type = MTYPE_BITMAP; 441 postgameMenuInfo.item_menu.generic.name = ART_MENU0; 442 postgameMenuInfo.item_menu.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_INACTIVE; 443 postgameMenuInfo.item_menu.generic.x = 0; 444 postgameMenuInfo.item_menu.generic.y = 480-64; 445 postgameMenuInfo.item_menu.generic.callback = UI_SPPostgameMenu_MenuEvent; 446 postgameMenuInfo.item_menu.generic.id = ID_MENU; 447 postgameMenuInfo.item_menu.width = 128; 448 postgameMenuInfo.item_menu.height = 64; 449 postgameMenuInfo.item_menu.focuspic = ART_MENU1; 450 451 postgameMenuInfo.item_again.generic.type = MTYPE_BITMAP; 452 postgameMenuInfo.item_again.generic.name = ART_REPLAY0; 453 postgameMenuInfo.item_again.generic.flags = QMF_CENTER_JUSTIFY|QMF_PULSEIFFOCUS|QMF_INACTIVE; 454 postgameMenuInfo.item_again.generic.x = 320; 455 postgameMenuInfo.item_again.generic.y = 480-64; 456 postgameMenuInfo.item_again.generic.callback = UI_SPPostgameMenu_AgainEvent; 457 postgameMenuInfo.item_again.generic.id = ID_AGAIN; 458 postgameMenuInfo.item_again.width = 128; 459 postgameMenuInfo.item_again.height = 64; 460 postgameMenuInfo.item_again.focuspic = ART_REPLAY1; 461 462 postgameMenuInfo.item_next.generic.type = MTYPE_BITMAP; 463 postgameMenuInfo.item_next.generic.name = ART_NEXT0; 464 postgameMenuInfo.item_next.generic.flags = QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_INACTIVE; 465 postgameMenuInfo.item_next.generic.x = 640; 466 postgameMenuInfo.item_next.generic.y = 480-64; 467 postgameMenuInfo.item_next.generic.callback = UI_SPPostgameMenu_NextEvent; 468 postgameMenuInfo.item_next.generic.id = ID_NEXT; 469 postgameMenuInfo.item_next.width = 128; 470 postgameMenuInfo.item_next.height = 64; 471 postgameMenuInfo.item_next.focuspic = ART_NEXT1; 472 473 Menu_AddItem( &postgameMenuInfo.menu, ( void * )&postgameMenuInfo.item_menu ); 474 Menu_AddItem( &postgameMenuInfo.menu, ( void * )&postgameMenuInfo.item_again ); 475 Menu_AddItem( &postgameMenuInfo.menu, ( void * )&postgameMenuInfo.item_next ); 476 } 477 478 479 static void Prepname( int index ) { 480 int len; 481 char name[64]; 482 char info[MAX_INFO_STRING]; 483 484 trap_GetConfigString( CS_PLAYERS + postgameMenuInfo.clientNums[index], info, MAX_INFO_STRING ); 485 Q_strncpyz( name, Info_ValueForKey( info, "n" ), sizeof(name) ); 486 Q_CleanStr( name ); 487 len = strlen( name ); 488 489 while( len && UI_ProportionalStringWidth( name ) > 256 ) { 490 len--; 491 name[len] = 0; 492 } 493 494 Q_strncpyz( postgameMenuInfo.placeNames[index], name, sizeof(postgameMenuInfo.placeNames[index]) ); 495 } 496 497 498 /* 499 ================= 500 UI_SPPostgameMenu_f 501 ================= 502 */ 503 void UI_SPPostgameMenu_f( void ) { 504 int playerGameRank; 505 int playerClientNum; 506 int n; 507 int oldFrags, newFrags; 508 const char *arena; 509 int awardValues[6]; 510 char map[MAX_QPATH]; 511 char info[MAX_INFO_STRING]; 512 513 memset( &postgameMenuInfo, 0, sizeof(postgameMenuInfo) ); 514 515 trap_GetConfigString( CS_SYSTEMINFO, info, sizeof(info) ); 516 postgameMenuInfo.serverId = atoi( Info_ValueForKey( info, "sv_serverid" ) ); 517 518 trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) ); 519 Q_strncpyz( map, Info_ValueForKey( info, "mapname" ), sizeof(map) ); 520 arena = UI_GetArenaInfoByMap( map ); 521 if ( !arena ) { 522 return; 523 } 524 Q_strncpyz( arenainfo, arena, sizeof(arenainfo) ); 525 526 postgameMenuInfo.level = atoi( Info_ValueForKey( arenainfo, "num" ) ); 527 528 postgameMenuInfo.numClients = atoi( UI_Argv( 1 ) ); 529 playerClientNum = atoi( UI_Argv( 2 ) ); 530 playerGameRank = 8; // in case they ended game as a spectator 531 532 if( postgameMenuInfo.numClients > MAX_SCOREBOARD_CLIENTS ) { 533 postgameMenuInfo.numClients = MAX_SCOREBOARD_CLIENTS; 534 } 535 536 for( n = 0; n < postgameMenuInfo.numClients; n++ ) { 537 postgameMenuInfo.clientNums[n] = atoi( UI_Argv( 8 + n * 3 + 1 ) ); 538 postgameMenuInfo.ranks[n] = atoi( UI_Argv( 8 + n * 3 + 2 ) ); 539 postgameMenuInfo.scores[n] = atoi( UI_Argv( 8 + n * 3 + 3 ) ); 540 541 if( postgameMenuInfo.clientNums[n] == playerClientNum ) { 542 playerGameRank = (postgameMenuInfo.ranks[n] & ~RANK_TIED_FLAG) + 1; 543 } 544 } 545 546 UI_SetBestScore( postgameMenuInfo.level, playerGameRank ); 547 548 // process award stats and prepare presentation data 549 awardValues[AWARD_ACCURACY] = atoi( UI_Argv( 3 ) ); 550 awardValues[AWARD_IMPRESSIVE] = atoi( UI_Argv( 4 ) ); 551 awardValues[AWARD_EXCELLENT] = atoi( UI_Argv( 5 ) ); 552 awardValues[AWARD_GAUNTLET] = atoi( UI_Argv( 6 ) ); 553 awardValues[AWARD_FRAGS] = atoi( UI_Argv( 7 ) ); 554 awardValues[AWARD_PERFECT] = atoi( UI_Argv( 8 ) ); 555 556 postgameMenuInfo.numAwards = 0; 557 558 if( awardValues[AWARD_ACCURACY] >= 50 ) { 559 UI_LogAwardData( AWARD_ACCURACY, 1 ); 560 postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_ACCURACY; 561 postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_ACCURACY]; 562 postgameMenuInfo.numAwards++; 563 } 564 565 if( awardValues[AWARD_IMPRESSIVE] ) { 566 UI_LogAwardData( AWARD_IMPRESSIVE, awardValues[AWARD_IMPRESSIVE] ); 567 postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_IMPRESSIVE; 568 postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_IMPRESSIVE]; 569 postgameMenuInfo.numAwards++; 570 } 571 572 if( awardValues[AWARD_EXCELLENT] ) { 573 UI_LogAwardData( AWARD_EXCELLENT, awardValues[AWARD_EXCELLENT] ); 574 postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_EXCELLENT; 575 postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_EXCELLENT]; 576 postgameMenuInfo.numAwards++; 577 } 578 579 if( awardValues[AWARD_GAUNTLET] ) { 580 UI_LogAwardData( AWARD_GAUNTLET, awardValues[AWARD_GAUNTLET] ); 581 postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_GAUNTLET; 582 postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_GAUNTLET]; 583 postgameMenuInfo.numAwards++; 584 } 585 586 oldFrags = UI_GetAwardLevel( AWARD_FRAGS ) / 100; 587 UI_LogAwardData( AWARD_FRAGS, awardValues[AWARD_FRAGS] ); 588 newFrags = UI_GetAwardLevel( AWARD_FRAGS ) / 100; 589 if( newFrags > oldFrags ) { 590 postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_FRAGS; 591 postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = newFrags * 100; 592 postgameMenuInfo.numAwards++; 593 } 594 595 if( awardValues[AWARD_PERFECT] ) { 596 UI_LogAwardData( AWARD_PERFECT, 1 ); 597 postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_PERFECT; 598 postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = 1; 599 postgameMenuInfo.numAwards++; 600 } 601 602 if ( playerGameRank == 1 ) { 603 postgameMenuInfo.won = UI_TierCompleted( postgameMenuInfo.level ); 604 } 605 else { 606 postgameMenuInfo.won = -1; 607 } 608 609 postgameMenuInfo.starttime = uis.realtime; 610 postgameMenuInfo.scoreboardtime = uis.realtime; 611 612 trap_Key_SetCatcher( KEYCATCH_UI ); 613 uis.menusp = 0; 614 615 UI_SPPostgameMenu_Init(); 616 UI_PushMenu( &postgameMenuInfo.menu ); 617 618 if ( playerGameRank == 1 ) { 619 Menu_SetCursorToItem( &postgameMenuInfo.menu, &postgameMenuInfo.item_next ); 620 } 621 else { 622 Menu_SetCursorToItem( &postgameMenuInfo.menu, &postgameMenuInfo.item_again ); 623 } 624 625 Prepname( 0 ); 626 Prepname( 1 ); 627 Prepname( 2 ); 628 629 if ( playerGameRank != 1 ) { 630 postgameMenuInfo.winnerSound = trap_S_RegisterSound( va( "sound/player/announce/%s_wins.wav", postgameMenuInfo.placeNames[0] ), qfalse ); 631 trap_Cmd_ExecuteText( EXEC_APPEND, "music music/loss\n" ); 632 } 633 else { 634 postgameMenuInfo.winnerSound = trap_S_RegisterSound( "sound/player/announce/youwin.wav", qfalse ); 635 trap_Cmd_ExecuteText( EXEC_APPEND, "music music/win\n" ); 636 } 637 638 postgameMenuInfo.phase = 1; 639 640 postgameMenuInfo.lastTier = UI_GetNumSPTiers(); 641 if ( UI_GetSpecialArenaInfo( "final" ) ) { 642 postgameMenuInfo.lastTier++; 643 } 644 }