Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

ui_splevel.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 //
00023 /*
00024 =============================================================================
00025 
00026 SINGLE PLAYER LEVEL SELECT MENU
00027 
00028 =============================================================================
00029 */
00030 
00031 #include "ui_local.h"
00032 
00033 
00034 #define ART_LEVELFRAME_FOCUS        "menu/art/maps_select"
00035 #define ART_LEVELFRAME_SELECTED     "menu/art/maps_selected"
00036 #define ART_ARROW                   "menu/art/narrow_0"
00037 #define ART_ARROW_FOCUS             "menu/art/narrow_1"
00038 #define ART_MAP_UNKNOWN             "menu/art/unknownmap"
00039 #define ART_MAP_COMPLETE1           "menu/art/level_complete1"
00040 #define ART_MAP_COMPLETE2           "menu/art/level_complete2"
00041 #define ART_MAP_COMPLETE3           "menu/art/level_complete3"
00042 #define ART_MAP_COMPLETE4           "menu/art/level_complete4"
00043 #define ART_MAP_COMPLETE5           "menu/art/level_complete5"
00044 #define ART_BACK0                   "menu/art/back_0"
00045 #define ART_BACK1                   "menu/art/back_1"   
00046 #define ART_FIGHT0                  "menu/art/fight_0"
00047 #define ART_FIGHT1                  "menu/art/fight_1"
00048 #define ART_RESET0                  "menu/art/reset_0"
00049 #define ART_RESET1                  "menu/art/reset_1"  
00050 #define ART_CUSTOM0                 "menu/art/skirmish_0"
00051 #define ART_CUSTOM1                 "menu/art/skirmish_1"
00052 
00053 #define ID_LEFTARROW        10
00054 #define ID_PICTURE0         11
00055 #define ID_PICTURE1         12
00056 #define ID_PICTURE2         13
00057 #define ID_PICTURE3         14
00058 #define ID_RIGHTARROW       15
00059 #define ID_PLAYERPIC        16
00060 #define ID_AWARD1           17
00061 #define ID_AWARD2           18
00062 #define ID_AWARD3           19
00063 #define ID_AWARD4           20
00064 #define ID_AWARD5           21
00065 #define ID_AWARD6           22
00066 #define ID_BACK             23
00067 #define ID_RESET            24
00068 #define ID_CUSTOM           25
00069 #define ID_NEXT             26
00070 
00071 #define PLAYER_Y            314
00072 #define AWARDS_Y            (PLAYER_Y + 26)
00073 
00074 
00075 typedef struct {
00076     menuframework_s menu;
00077     menutext_s      item_banner;
00078     menubitmap_s    item_leftarrow;
00079     menubitmap_s    item_maps[4];
00080     menubitmap_s    item_rightarrow;
00081     menubitmap_s    item_player;
00082     menubitmap_s    item_awards[6];
00083     menubitmap_s    item_back;
00084     menubitmap_s    item_reset;
00085     menubitmap_s    item_custom;
00086     menubitmap_s    item_next;
00087     menubitmap_s    item_null;
00088 
00089     qboolean        reinit;
00090 
00091     const char *    selectedArenaInfo;
00092     int             numMaps;
00093     char            levelPicNames[4][MAX_QPATH];
00094     char            levelNames[4][16];
00095     int             levelScores[4];
00096     int             levelScoresSkill[4];
00097     qhandle_t       levelSelectedPic;
00098     qhandle_t       levelFocusPic;
00099     qhandle_t       levelCompletePic[5];
00100 
00101     char            playerModel[MAX_QPATH];
00102     char            playerPicName[MAX_QPATH];
00103     int             awardLevels[6];
00104     sfxHandle_t     awardSounds[6];
00105 
00106     int             numBots;
00107     qhandle_t       botPics[7];
00108     char            botNames[7][10];
00109 } levelMenuInfo_t;
00110 
00111 static levelMenuInfo_t  levelMenuInfo;
00112 
00113 static int  selectedArenaSet;
00114 static int  selectedArena;
00115 static int  currentSet;
00116 static int  currentGame;
00117 static int  trainingTier;
00118 static int  finalTier;
00119 static int  minTier;
00120 static int  maxTier;
00121 
00122 
00123 /*
00124 =================
00125 PlayerIcon
00126 =================
00127 */
00128 static void PlayerIcon( const char *modelAndSkin, char *iconName, int iconNameMaxSize ) {
00129     char    *skin;
00130     char    model[MAX_QPATH];
00131 
00132     Q_strncpyz( model, modelAndSkin, sizeof(model));
00133     skin = Q_strrchr( model, '/' );
00134     if ( skin ) {
00135         *skin++ = '\0';
00136     }
00137     else {
00138         skin = "default";
00139     }
00140 
00141     Com_sprintf(iconName, iconNameMaxSize, "models/players/%s/icon_%s.tga", model, skin );
00142 
00143     if( !trap_R_RegisterShaderNoMip( iconName ) && Q_stricmp( skin, "default" ) != 0 ) {
00144         Com_sprintf(iconName, iconNameMaxSize, "models/players/%s/icon_default.tga", model );
00145     }
00146 }
00147 
00148 
00149 /*
00150 =================
00151 PlayerIconhandle
00152 =================
00153 */
00154 static qhandle_t PlayerIconHandle( const char *modelAndSkin ) {
00155     char    iconName[MAX_QPATH];
00156 
00157     PlayerIcon( modelAndSkin, iconName, sizeof(iconName) );
00158     return trap_R_RegisterShaderNoMip( iconName );
00159 }
00160 
00161 
00162 /*
00163 =================
00164 UI_SPLevelMenu_SetBots
00165 =================
00166 */
00167 static void UI_SPLevelMenu_SetBots( void ) {
00168     char    *p;
00169     char    *bot;
00170     char    *botInfo;
00171     char    bots[MAX_INFO_STRING];
00172 
00173     levelMenuInfo.numBots = 0;
00174     if ( selectedArenaSet > currentSet ) {
00175         return;
00176     }
00177 
00178     Q_strncpyz( bots, Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "bots" ), sizeof(bots) );
00179 
00180     p = &bots[0];
00181     while( *p && levelMenuInfo.numBots < 7 ) {
00182         //skip spaces
00183         while( *p && *p == ' ' ) {
00184             p++;
00185         }
00186         if( !p ) {
00187             break;
00188         }
00189 
00190         // mark start of bot name
00191         bot = p;
00192 
00193         // skip until space of null
00194         while( *p && *p != ' ' ) {
00195             p++;
00196         }
00197         if( *p ) {
00198             *p++ = 0;
00199         }
00200 
00201         botInfo = UI_GetBotInfoByName( bot );
00202         if( botInfo ) {
00203             levelMenuInfo.botPics[levelMenuInfo.numBots] = PlayerIconHandle( Info_ValueForKey( botInfo, "model" ) );
00204             Q_strncpyz( levelMenuInfo.botNames[levelMenuInfo.numBots], Info_ValueForKey( botInfo, "name" ), 10 );
00205         }
00206         else {
00207             levelMenuInfo.botPics[levelMenuInfo.numBots] = 0;
00208             Q_strncpyz( levelMenuInfo.botNames[levelMenuInfo.numBots], bot, 10 );
00209         }
00210         Q_CleanStr( levelMenuInfo.botNames[levelMenuInfo.numBots] );
00211         levelMenuInfo.numBots++;
00212     }
00213 }
00214 
00215 
00216 /*
00217 =================
00218 UI_SPLevelMenu_SetMenuItems
00219 =================
00220 */
00221 static void UI_SPLevelMenu_SetMenuArena( int n, int level, const char *arenaInfo ) {
00222     char        map[MAX_QPATH];
00223 
00224     Q_strncpyz( map, Info_ValueForKey( arenaInfo, "map" ), sizeof(map) );
00225 
00226     Q_strncpyz( levelMenuInfo.levelNames[n], map, sizeof(levelMenuInfo.levelNames[n]) );
00227     Q_strupr( levelMenuInfo.levelNames[n] );
00228 
00229     UI_GetBestScore( level, &levelMenuInfo.levelScores[n], &levelMenuInfo.levelScoresSkill[n] );
00230     if( levelMenuInfo.levelScores[n] > 8 ) {
00231         levelMenuInfo.levelScores[n] = 8;
00232     }
00233 
00234     strcpy( levelMenuInfo.levelPicNames[n], va( "levelshots/%s.tga", map ) );
00235     if( !trap_R_RegisterShaderNoMip( levelMenuInfo.levelPicNames[n] ) ) {
00236         strcpy( levelMenuInfo.levelPicNames[n], ART_MAP_UNKNOWN );
00237     }
00238     levelMenuInfo.item_maps[n].shader = 0;
00239     if ( selectedArenaSet > currentSet ) {
00240         levelMenuInfo.item_maps[n].generic.flags |= QMF_GRAYED;
00241     }
00242     else {
00243         levelMenuInfo.item_maps[n].generic.flags &= ~QMF_GRAYED;
00244     }
00245 
00246     levelMenuInfo.item_maps[n].generic.flags &= ~QMF_INACTIVE;
00247 }
00248 
00249 static void UI_SPLevelMenu_SetMenuItems( void ) {
00250     int         n;
00251     int         level;
00252     const char  *arenaInfo;
00253 
00254     if ( selectedArenaSet > currentSet ) {
00255         selectedArena = -1;
00256     }
00257     else if ( selectedArena == -1 ) {
00258         selectedArena = 0;
00259     }
00260 
00261     if( selectedArenaSet == trainingTier || selectedArenaSet == finalTier ) {
00262         selectedArena = 0;
00263     }
00264 
00265     if( selectedArena != -1 ) {
00266         trap_Cvar_SetValue( "ui_spSelection", selectedArenaSet * ARENAS_PER_TIER + selectedArena );
00267     }
00268 
00269     if( selectedArenaSet == trainingTier ) {
00270         arenaInfo = UI_GetSpecialArenaInfo( "training" );
00271         level = atoi( Info_ValueForKey( arenaInfo, "num" ) );
00272         UI_SPLevelMenu_SetMenuArena( 0, level, arenaInfo );
00273         levelMenuInfo.selectedArenaInfo = arenaInfo;
00274 
00275         levelMenuInfo.item_maps[0].generic.x = 256;
00276         Bitmap_Init( &levelMenuInfo.item_maps[0] );
00277         levelMenuInfo.item_maps[0].generic.bottom += 32;
00278         levelMenuInfo.numMaps = 1;
00279 
00280         levelMenuInfo.item_maps[1].generic.flags |= QMF_INACTIVE;
00281         levelMenuInfo.item_maps[2].generic.flags |= QMF_INACTIVE;
00282         levelMenuInfo.item_maps[3].generic.flags |= QMF_INACTIVE;
00283         levelMenuInfo.levelPicNames[1][0] = 0;
00284         levelMenuInfo.levelPicNames[2][0] = 0;
00285         levelMenuInfo.levelPicNames[3][0] = 0;
00286         levelMenuInfo.item_maps[1].shader = 0;
00287         levelMenuInfo.item_maps[2].shader = 0;
00288         levelMenuInfo.item_maps[3].shader = 0;
00289     }
00290     else if( selectedArenaSet == finalTier ) {
00291         arenaInfo = UI_GetSpecialArenaInfo( "final" );
00292         level = atoi( Info_ValueForKey( arenaInfo, "num" ) );
00293         UI_SPLevelMenu_SetMenuArena( 0, level, arenaInfo );
00294         levelMenuInfo.selectedArenaInfo = arenaInfo;
00295 
00296         levelMenuInfo.item_maps[0].generic.x = 256;
00297         Bitmap_Init( &levelMenuInfo.item_maps[0] );
00298         levelMenuInfo.item_maps[0].generic.bottom += 32;
00299         levelMenuInfo.numMaps = 1;
00300 
00301         levelMenuInfo.item_maps[1].generic.flags |= QMF_INACTIVE;
00302         levelMenuInfo.item_maps[2].generic.flags |= QMF_INACTIVE;
00303         levelMenuInfo.item_maps[3].generic.flags |= QMF_INACTIVE;
00304         levelMenuInfo.levelPicNames[1][0] = 0;
00305         levelMenuInfo.levelPicNames[2][0] = 0;
00306         levelMenuInfo.levelPicNames[3][0] = 0;
00307         levelMenuInfo.item_maps[1].shader = 0;
00308         levelMenuInfo.item_maps[2].shader = 0;
00309         levelMenuInfo.item_maps[3].shader = 0;
00310     }
00311     else {
00312         levelMenuInfo.item_maps[0].generic.x = 46;
00313         Bitmap_Init( &levelMenuInfo.item_maps[0] );
00314         levelMenuInfo.item_maps[0].generic.bottom += 18;
00315         levelMenuInfo.numMaps = 4;
00316 
00317         for ( n = 0; n < 4; n++ ) {
00318             level = selectedArenaSet * ARENAS_PER_TIER + n;
00319             arenaInfo = UI_GetArenaInfoByNumber( level );
00320             UI_SPLevelMenu_SetMenuArena( n, level, arenaInfo );
00321         }
00322 
00323         if( selectedArena != -1 ) {
00324             levelMenuInfo.selectedArenaInfo = UI_GetArenaInfoByNumber( selectedArenaSet * ARENAS_PER_TIER + selectedArena );
00325         }
00326     }
00327 
00328     // enable/disable arrows when they are valid/invalid
00329     if ( selectedArenaSet == minTier ) {
00330         levelMenuInfo.item_leftarrow.generic.flags |= ( QMF_INACTIVE | QMF_HIDDEN );
00331     }
00332     else {
00333         levelMenuInfo.item_leftarrow.generic.flags &= ~( QMF_INACTIVE | QMF_HIDDEN );
00334     }
00335 
00336     if ( selectedArenaSet == maxTier ) {
00337         levelMenuInfo.item_rightarrow.generic.flags |= ( QMF_INACTIVE | QMF_HIDDEN );
00338     }
00339     else {
00340         levelMenuInfo.item_rightarrow.generic.flags &= ~( QMF_INACTIVE | QMF_HIDDEN );
00341     }
00342 
00343     UI_SPLevelMenu_SetBots();
00344 }
00345 
00346 
00347 /*
00348 =================
00349 UI_SPLevelMenu_ResetEvent
00350 =================
00351 */
00352 static void UI_SPLevelMenu_ResetDraw( void ) {
00353     UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 0, "WARNING: This resets all of the", UI_CENTER|UI_SMALLFONT, color_yellow );
00354     UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 1, "single player game variables.", UI_CENTER|UI_SMALLFONT, color_yellow );
00355     UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 2, "Do this only if you want to", UI_CENTER|UI_SMALLFONT, color_yellow );
00356     UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 3, "start over from the beginning.", UI_CENTER|UI_SMALLFONT, color_yellow );
00357 }
00358 
00359 static void UI_SPLevelMenu_ResetAction( qboolean result ) {
00360     if( !result ) {
00361         return;
00362     }
00363 
00364     // clear game variables
00365     UI_NewGame();
00366     trap_Cvar_SetValue( "ui_spSelection", -4 );
00367 
00368     // make the level select menu re-initialize
00369     UI_PopMenu();
00370     UI_SPLevelMenu();
00371 }
00372 
00373 static void UI_SPLevelMenu_ResetEvent( void* ptr, int event )
00374 {
00375     if (event != QM_ACTIVATED) {
00376         return;
00377     }
00378 
00379     UI_ConfirmMenu( "RESET GAME?", UI_SPLevelMenu_ResetDraw, UI_SPLevelMenu_ResetAction );
00380 }
00381 
00382 
00383 /*
00384 =================
00385 UI_SPLevelMenu_LevelEvent
00386 =================
00387 */
00388 static void UI_SPLevelMenu_LevelEvent( void* ptr, int notification ) {
00389     if (notification != QM_ACTIVATED) {
00390         return;
00391     }
00392 
00393     if ( selectedArenaSet == trainingTier || selectedArenaSet == finalTier ) {
00394         return;
00395     }
00396 
00397     selectedArena = ((menucommon_s*)ptr)->id - ID_PICTURE0;
00398     levelMenuInfo.selectedArenaInfo = UI_GetArenaInfoByNumber( selectedArenaSet * ARENAS_PER_TIER + selectedArena );
00399     UI_SPLevelMenu_SetBots();
00400 
00401     trap_Cvar_SetValue( "ui_spSelection", selectedArenaSet * ARENAS_PER_TIER + selectedArena );
00402 }
00403 
00404 
00405 /*
00406 =================
00407 UI_SPLevelMenu_LeftArrowEvent
00408 =================
00409 */
00410 static void UI_SPLevelMenu_LeftArrowEvent( void* ptr, int notification ) {
00411     if (notification != QM_ACTIVATED) {
00412         return;
00413     }
00414 
00415     if ( selectedArenaSet == minTier ) {
00416         return;
00417     }
00418 
00419     selectedArenaSet--;
00420     UI_SPLevelMenu_SetMenuItems();
00421 }
00422 
00423 
00424 /*
00425 =================
00426 UI_SPLevelMenu_RightArrowEvent
00427 =================
00428 */
00429 static void UI_SPLevelMenu_RightArrowEvent( void* ptr, int notification ) {
00430     if (notification != QM_ACTIVATED) {
00431         return;
00432     }
00433 
00434     if ( selectedArenaSet == maxTier ) {
00435         return;
00436     }
00437 
00438     selectedArenaSet++;
00439     UI_SPLevelMenu_SetMenuItems();
00440 }
00441 
00442 
00443 /*
00444 =================
00445 UI_SPLevelMenu_PlayerEvent
00446 =================
00447 */
00448 static void UI_SPLevelMenu_PlayerEvent( void* ptr, int notification ) {
00449     if (notification != QM_ACTIVATED) {
00450         return;
00451     }
00452 
00453     UI_PlayerSettingsMenu();
00454 }
00455 
00456 
00457 /*
00458 =================
00459 UI_SPLevelMenu_AwardEvent
00460 =================
00461 */
00462 static void UI_SPLevelMenu_AwardEvent( void* ptr, int notification ) {
00463     int     n;
00464 
00465     if (notification != QM_ACTIVATED) {
00466         return;
00467     }
00468 
00469     n = ((menucommon_s*)ptr)->id - ID_AWARD1;
00470     trap_S_StartLocalSound( levelMenuInfo.awardSounds[n], CHAN_ANNOUNCER );
00471 }
00472 
00473 
00474 /*
00475 =================
00476 UI_SPLevelMenu_NextEvent
00477 =================
00478 */
00479 static void UI_SPLevelMenu_NextEvent( void* ptr, int notification ) {
00480     if (notification != QM_ACTIVATED) {
00481         return;
00482     }
00483 
00484     if ( selectedArenaSet > currentSet ) {
00485         return;
00486     }
00487 
00488     if ( selectedArena == -1 ) {
00489         selectedArena = 0;
00490     }
00491 
00492     UI_SPSkillMenu( levelMenuInfo.selectedArenaInfo );
00493 }
00494 
00495 
00496 /*
00497 =================
00498 UI_SPLevelMenu_BackEvent
00499 =================
00500 */
00501 static void UI_SPLevelMenu_BackEvent( void* ptr, int notification ) {
00502     if (notification != QM_ACTIVATED) {
00503         return;
00504     }
00505 
00506     if ( selectedArena == -1 ) {
00507         selectedArena = 0;
00508     }
00509 
00510     UI_PopMenu();
00511 }
00512 
00513 
00514 /*
00515 =================
00516 UI_SPLevelMenu_CustomEvent
00517 =================
00518 */
00519 static void UI_SPLevelMenu_CustomEvent( void* ptr, int notification ) {
00520     if (notification != QM_ACTIVATED) {
00521         return;
00522     }
00523 
00524     UI_StartServerMenu( qfalse );
00525 }
00526 
00527 
00528 /*
00529 =================
00530 UI_SPLevelMenu_MenuDraw
00531 =================
00532 */
00533 #define LEVEL_DESC_LEFT_MARGIN      332
00534 
00535 static void UI_SPLevelMenu_MenuDraw( void ) {
00536     int             n, i;
00537     int             x, y;
00538     vec4_t          color;
00539     int             level;
00540 //  int             fraglimit;
00541     int             pad;
00542     char            buf[MAX_INFO_VALUE];
00543     char            string[64];
00544 
00545     if( levelMenuInfo.reinit ) {
00546         UI_PopMenu();
00547         UI_SPLevelMenu();
00548         return;
00549     }
00550 
00551     // draw player name
00552     trap_Cvar_VariableStringBuffer( "name", string, 32 );
00553     Q_CleanStr( string );
00554     UI_DrawProportionalString( 320, PLAYER_Y, string, UI_CENTER|UI_SMALLFONT, color_orange );
00555 
00556     // check for model changes
00557     trap_Cvar_VariableStringBuffer( "model", buf, sizeof(buf) );
00558     if( Q_stricmp( buf, levelMenuInfo.playerModel ) != 0 ) {
00559         Q_strncpyz( levelMenuInfo.playerModel, buf, sizeof(levelMenuInfo.playerModel) );
00560         PlayerIcon( levelMenuInfo.playerModel, levelMenuInfo.playerPicName, sizeof(levelMenuInfo.playerPicName) );
00561         levelMenuInfo.item_player.shader = 0;
00562     }
00563 
00564     // standard menu drawing
00565     Menu_Draw( &levelMenuInfo.menu );
00566 
00567     // draw player award levels
00568     y = AWARDS_Y;
00569     i = 0;
00570     for( n = 0; n < 6; n++ ) {
00571         level = levelMenuInfo.awardLevels[n];
00572         if( level > 0 ) {
00573             if( i & 1 ) {
00574                 x = 224 - (i - 1 ) / 2 * (48 + 16);
00575             }
00576             else {
00577                 x = 368 + i / 2 * (48 + 16);
00578             }
00579             i++;
00580 
00581             if( level == 1 ) {
00582                 continue;
00583             }
00584 
00585             if( level >= 1000000 ) {
00586                 Com_sprintf( string, sizeof(string), "%im", level / 1000000 );
00587             }
00588             else if( level >= 1000 ) {
00589                 Com_sprintf( string, sizeof(string), "%ik", level / 1000 );
00590             }
00591             else {
00592                 Com_sprintf( string, sizeof(string), "%i", level );
00593             }
00594 
00595             UI_DrawString( x + 24, y + 48, string, UI_CENTER, color_yellow );
00596         }
00597     }
00598 
00599     UI_DrawProportionalString( 18, 38, va( "Tier %i", selectedArenaSet + 1 ), UI_LEFT|UI_SMALLFONT, color_orange );
00600 
00601     for ( n = 0; n < levelMenuInfo.numMaps; n++ ) {
00602         x = levelMenuInfo.item_maps[n].generic.x;
00603         y = levelMenuInfo.item_maps[n].generic.y;
00604         UI_FillRect( x, y + 96, 128, 18, color_black );
00605     }
00606 
00607     if ( selectedArenaSet > currentSet ) {
00608         UI_DrawProportionalString( 320, 216, "ACCESS DENIED", UI_CENTER|UI_BIGFONT, color_red );
00609         return;
00610     }
00611 
00612     // show levelshots for levels of current tier
00613     Vector4Copy( color_white, color );
00614     color[3] = 0.5+0.5*sin(uis.realtime/PULSE_DIVISOR);
00615     for ( n = 0; n < levelMenuInfo.numMaps; n++ ) {
00616         x = levelMenuInfo.item_maps[n].generic.x;
00617         y = levelMenuInfo.item_maps[n].generic.y;
00618 
00619         UI_DrawString( x + 64, y + 96, levelMenuInfo.levelNames[n], UI_CENTER|UI_SMALLFONT, color_orange );
00620 
00621         if( levelMenuInfo.levelScores[n] == 1 ) {
00622             UI_DrawHandlePic( x, y, 128, 96, levelMenuInfo.levelCompletePic[levelMenuInfo.levelScoresSkill[n] - 1] ); 
00623         }
00624 
00625         if ( n == selectedArena ) {
00626             if( Menu_ItemAtCursor( &levelMenuInfo.menu ) == &levelMenuInfo.item_maps[n] ) {
00627                 trap_R_SetColor( color );
00628             }
00629             UI_DrawHandlePic( x-1, y-1, 130, 130 - 14, levelMenuInfo.levelSelectedPic ); 
00630             trap_R_SetColor( NULL );
00631         }
00632         else if( Menu_ItemAtCursor( &levelMenuInfo.menu ) == &levelMenuInfo.item_maps[n] ) {
00633             trap_R_SetColor( color );
00634             UI_DrawHandlePic( x-31, y-30, 256, 256-27, levelMenuInfo.levelFocusPic); 
00635             trap_R_SetColor( NULL );
00636         }
00637     }
00638 
00639     // show map name and long name of selected level
00640     y = 192;
00641     Q_strncpyz( buf, Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "map" ), 20 );
00642     Q_strupr( buf );
00643     Com_sprintf( string, sizeof(string), "%s: %s", buf, Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "longname" ) );
00644     UI_DrawProportionalString( 320, y, string, UI_CENTER|UI_SMALLFONT, color_orange );
00645 
00646 //  fraglimit = atoi( Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "fraglimit" ) );
00647 //  UI_DrawString( 18, 212, va("Frags %i", fraglimit) , UI_LEFT|UI_SMALLFONT, color_orange );
00648 
00649     // draw bot opponents
00650     y += 24;
00651     pad = (7 - levelMenuInfo.numBots) * (64 + 26) / 2;
00652     for( n = 0; n < levelMenuInfo.numBots; n++ ) {
00653         x = 18 + pad + (64 + 26) * n;
00654         if( levelMenuInfo.botPics[n] ) {
00655             UI_DrawHandlePic( x, y, 64, 64, levelMenuInfo.botPics[n]);
00656         }
00657         else {
00658             UI_FillRect( x, y, 64, 64, color_black );
00659             UI_DrawProportionalString( x+22, y+18, "?", UI_BIGFONT, color_orange );
00660         }
00661         UI_DrawString( x, y + 64, levelMenuInfo.botNames[n], UI_SMALLFONT|UI_LEFT, color_orange );
00662     }
00663 }
00664 
00665 
00666 /*
00667 =================
00668 UI_SPLevelMenu_Cache
00669 =================
00670 */
00671 void UI_SPLevelMenu_Cache( void ) {
00672     int             n;
00673 
00674     trap_R_RegisterShaderNoMip( ART_LEVELFRAME_FOCUS );
00675     trap_R_RegisterShaderNoMip( ART_LEVELFRAME_SELECTED );
00676     trap_R_RegisterShaderNoMip( ART_ARROW );
00677     trap_R_RegisterShaderNoMip( ART_ARROW_FOCUS );
00678     trap_R_RegisterShaderNoMip( ART_MAP_UNKNOWN );
00679     trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE1 );
00680     trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE2 );
00681     trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE3 );
00682     trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE4 );
00683     trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE5 );
00684     trap_R_RegisterShaderNoMip( ART_BACK0 );
00685     trap_R_RegisterShaderNoMip( ART_BACK1 );
00686     trap_R_RegisterShaderNoMip( ART_FIGHT0 );
00687     trap_R_RegisterShaderNoMip( ART_FIGHT1 );
00688     trap_R_RegisterShaderNoMip( ART_RESET0 );
00689     trap_R_RegisterShaderNoMip( ART_RESET1 );
00690     trap_R_RegisterShaderNoMip( ART_CUSTOM0 );
00691     trap_R_RegisterShaderNoMip( ART_CUSTOM1 );
00692 
00693     for( n = 0; n < 6; n++ ) {
00694         trap_R_RegisterShaderNoMip( ui_medalPicNames[n] );
00695         levelMenuInfo.awardSounds[n] = trap_S_RegisterSound( ui_medalSounds[n], qfalse );
00696     }
00697 
00698     levelMenuInfo.levelSelectedPic = trap_R_RegisterShaderNoMip( ART_LEVELFRAME_SELECTED );
00699     levelMenuInfo.levelFocusPic = trap_R_RegisterShaderNoMip( ART_LEVELFRAME_FOCUS );
00700     levelMenuInfo.levelCompletePic[0] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE1 );
00701     levelMenuInfo.levelCompletePic[1] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE2 );
00702     levelMenuInfo.levelCompletePic[2] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE3 );
00703     levelMenuInfo.levelCompletePic[3] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE4 );
00704     levelMenuInfo.levelCompletePic[4] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE5 );
00705 }
00706 
00707 
00708 /*
00709 =================
00710 UI_SPLevelMenu_Init
00711 =================
00712 */
00713 static void UI_SPLevelMenu_Init( void ) {
00714     int     skill;
00715     int     n;
00716     int     x, y;
00717     int     count;
00718     char    buf[MAX_QPATH];
00719 
00720     skill = (int)trap_Cvar_VariableValue( "g_spSkill" );
00721     if( skill < 1 || skill > 5 ) {
00722         trap_Cvar_Set( "g_spSkill", "2" );
00723         skill = 2;
00724     }
00725 
00726     memset( &levelMenuInfo, 0, sizeof(levelMenuInfo) );
00727     levelMenuInfo.menu.fullscreen = qtrue;
00728     levelMenuInfo.menu.wrapAround = qtrue;
00729     levelMenuInfo.menu.draw = UI_SPLevelMenu_MenuDraw;
00730 
00731     UI_SPLevelMenu_Cache();
00732 
00733     levelMenuInfo.item_banner.generic.type          = MTYPE_BTEXT;
00734     levelMenuInfo.item_banner.generic.x             = 320;
00735     levelMenuInfo.item_banner.generic.y             = 16;
00736     levelMenuInfo.item_banner.string                = "CHOOSE LEVEL";
00737     levelMenuInfo.item_banner.color                 = color_red;
00738     levelMenuInfo.item_banner.style                 = UI_CENTER;
00739 
00740     levelMenuInfo.item_leftarrow.generic.type       = MTYPE_BITMAP;
00741     levelMenuInfo.item_leftarrow.generic.name       = ART_ARROW;
00742     levelMenuInfo.item_leftarrow.generic.flags      = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
00743     levelMenuInfo.item_leftarrow.generic.x          = 18;
00744     levelMenuInfo.item_leftarrow.generic.y          = 64;
00745     levelMenuInfo.item_leftarrow.generic.callback   = UI_SPLevelMenu_LeftArrowEvent;
00746     levelMenuInfo.item_leftarrow.generic.id         = ID_LEFTARROW;
00747     levelMenuInfo.item_leftarrow.width              = 16;
00748     levelMenuInfo.item_leftarrow.height             = 114;
00749     levelMenuInfo.item_leftarrow.focuspic           = ART_ARROW_FOCUS;
00750 
00751     levelMenuInfo.item_maps[0].generic.type         = MTYPE_BITMAP;
00752     levelMenuInfo.item_maps[0].generic.name         = levelMenuInfo.levelPicNames[0];
00753     levelMenuInfo.item_maps[0].generic.flags        = QMF_LEFT_JUSTIFY;
00754     levelMenuInfo.item_maps[0].generic.x            = 46;
00755     levelMenuInfo.item_maps[0].generic.y            = 64;
00756     levelMenuInfo.item_maps[0].generic.id           = ID_PICTURE0;
00757     levelMenuInfo.item_maps[0].generic.callback     = UI_SPLevelMenu_LevelEvent;
00758     levelMenuInfo.item_maps[0].width                = 128;
00759     levelMenuInfo.item_maps[0].height               = 96;
00760 
00761     levelMenuInfo.item_maps[1].generic.type         = MTYPE_BITMAP;
00762     levelMenuInfo.item_maps[1].generic.name         = levelMenuInfo.levelPicNames[1];
00763     levelMenuInfo.item_maps[1].generic.flags        = QMF_LEFT_JUSTIFY;
00764     levelMenuInfo.item_maps[1].generic.x            = 186;
00765     levelMenuInfo.item_maps[1].generic.y            = 64;
00766     levelMenuInfo.item_maps[1].generic.id           = ID_PICTURE1;
00767     levelMenuInfo.item_maps[1].generic.callback     = UI_SPLevelMenu_LevelEvent;
00768     levelMenuInfo.item_maps[1].width                = 128;
00769     levelMenuInfo.item_maps[1].height               = 96;
00770 
00771     levelMenuInfo.item_maps[2].generic.type         = MTYPE_BITMAP;
00772     levelMenuInfo.item_maps[2].generic.name         = levelMenuInfo.levelPicNames[2];
00773     levelMenuInfo.item_maps[2].generic.flags        = QMF_LEFT_JUSTIFY;
00774     levelMenuInfo.item_maps[2].generic.x            = 326;
00775     levelMenuInfo.item_maps[2].generic.y            = 64;
00776     levelMenuInfo.item_maps[2].generic.id           = ID_PICTURE2;
00777     levelMenuInfo.item_maps[2].generic.callback     = UI_SPLevelMenu_LevelEvent;
00778     levelMenuInfo.item_maps[2].width                = 128;
00779     levelMenuInfo.item_maps[2].height               = 96;
00780 
00781     levelMenuInfo.item_maps[3].generic.type         = MTYPE_BITMAP;
00782     levelMenuInfo.item_maps[3].generic.name         = levelMenuInfo.levelPicNames[3];
00783     levelMenuInfo.item_maps[3].generic.flags        = QMF_LEFT_JUSTIFY;
00784     levelMenuInfo.item_maps[3].generic.x            = 466;
00785     levelMenuInfo.item_maps[3].generic.y            = 64;
00786     levelMenuInfo.item_maps[3].generic.id           = ID_PICTURE3;
00787     levelMenuInfo.item_maps[3].generic.callback     = UI_SPLevelMenu_LevelEvent;
00788     levelMenuInfo.item_maps[3].width                = 128;
00789     levelMenuInfo.item_maps[3].height               = 96;
00790 
00791     levelMenuInfo.item_rightarrow.generic.type      = MTYPE_BITMAP;
00792     levelMenuInfo.item_rightarrow.generic.name      = ART_ARROW;
00793     levelMenuInfo.item_rightarrow.generic.flags     = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
00794     levelMenuInfo.item_rightarrow.generic.x         = 606;
00795     levelMenuInfo.item_rightarrow.generic.y         = 64;
00796     levelMenuInfo.item_rightarrow.generic.callback  = UI_SPLevelMenu_RightArrowEvent;
00797     levelMenuInfo.item_rightarrow.generic.id        = ID_RIGHTARROW;
00798     levelMenuInfo.item_rightarrow.width             = -16;
00799     levelMenuInfo.item_rightarrow.height            = 114;
00800     levelMenuInfo.item_rightarrow.focuspic          = ART_ARROW_FOCUS;
00801 
00802     trap_Cvar_VariableStringBuffer( "model", levelMenuInfo.playerModel, sizeof(levelMenuInfo.playerModel) );
00803     PlayerIcon( levelMenuInfo.playerModel, levelMenuInfo.playerPicName, sizeof(levelMenuInfo.playerPicName) );
00804     levelMenuInfo.item_player.generic.type          = MTYPE_BITMAP;
00805     levelMenuInfo.item_player.generic.name          = levelMenuInfo.playerPicName;
00806     levelMenuInfo.item_player.generic.flags         = QMF_LEFT_JUSTIFY|QMF_MOUSEONLY;
00807     levelMenuInfo.item_player.generic.x             = 288;
00808     levelMenuInfo.item_player.generic.y             = AWARDS_Y;
00809     levelMenuInfo.item_player.generic.id            = ID_PLAYERPIC;
00810     levelMenuInfo.item_player.generic.callback      = UI_SPLevelMenu_PlayerEvent;
00811     levelMenuInfo.item_player.width                 = 64;
00812     levelMenuInfo.item_player.height                = 64;
00813 
00814     for( n = 0; n < 6; n++ ) {
00815         levelMenuInfo.awardLevels[n] = UI_GetAwardLevel( n );
00816     }
00817     levelMenuInfo.awardLevels[AWARD_FRAGS] = 100 * (levelMenuInfo.awardLevels[AWARD_FRAGS] / 100);
00818 
00819     y = AWARDS_Y;
00820     count = 0;
00821     for( n = 0; n < 6; n++ ) {
00822         if( levelMenuInfo.awardLevels[n] ) {
00823             if( count & 1 ) {
00824                 x = 224 - (count - 1 ) / 2 * (48 + 16);
00825             }
00826             else {
00827                 x = 368 + count / 2 * (48 + 16);
00828             }
00829 
00830             levelMenuInfo.item_awards[count].generic.type       = MTYPE_BITMAP;
00831             levelMenuInfo.item_awards[count].generic.name       = ui_medalPicNames[n];
00832             levelMenuInfo.item_awards[count].generic.flags      = QMF_LEFT_JUSTIFY|QMF_SILENT|QMF_MOUSEONLY;
00833             levelMenuInfo.item_awards[count].generic.x          = x;
00834             levelMenuInfo.item_awards[count].generic.y          = y;
00835             levelMenuInfo.item_awards[count].generic.id         = ID_AWARD1 + n;
00836             levelMenuInfo.item_awards[count].generic.callback   = UI_SPLevelMenu_AwardEvent;
00837             levelMenuInfo.item_awards[count].width              = 48;
00838             levelMenuInfo.item_awards[count].height             = 48;
00839             count++;
00840         }
00841     }
00842 
00843     levelMenuInfo.item_back.generic.type            = MTYPE_BITMAP;
00844     levelMenuInfo.item_back.generic.name            = ART_BACK0;
00845     levelMenuInfo.item_back.generic.flags           = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
00846     levelMenuInfo.item_back.generic.x               = 0;
00847     levelMenuInfo.item_back.generic.y               = 480-64;
00848     levelMenuInfo.item_back.generic.callback        = UI_SPLevelMenu_BackEvent;
00849     levelMenuInfo.item_back.generic.id              = ID_BACK;
00850     levelMenuInfo.item_back.width                   = 128;
00851     levelMenuInfo.item_back.height                  = 64;
00852     levelMenuInfo.item_back.focuspic                = ART_BACK1;
00853 
00854     levelMenuInfo.item_reset.generic.type           = MTYPE_BITMAP;
00855     levelMenuInfo.item_reset.generic.name           = ART_RESET0;
00856     levelMenuInfo.item_reset.generic.flags          = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
00857     levelMenuInfo.item_reset.generic.x              = 170;
00858     levelMenuInfo.item_reset.generic.y              = 480-64;
00859     levelMenuInfo.item_reset.generic.callback       = UI_SPLevelMenu_ResetEvent;
00860     levelMenuInfo.item_reset.generic.id             = ID_RESET;
00861     levelMenuInfo.item_reset.width                  = 128;
00862     levelMenuInfo.item_reset.height                 = 64;
00863     levelMenuInfo.item_reset.focuspic               = ART_RESET1;
00864 
00865     levelMenuInfo.item_custom.generic.type          = MTYPE_BITMAP;
00866     levelMenuInfo.item_custom.generic.name          = ART_CUSTOM0;
00867     levelMenuInfo.item_custom.generic.flags         = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
00868     levelMenuInfo.item_custom.generic.x             = 342;
00869     levelMenuInfo.item_custom.generic.y             = 480-64;
00870     levelMenuInfo.item_custom.generic.callback      = UI_SPLevelMenu_CustomEvent;
00871     levelMenuInfo.item_custom.generic.id            = ID_CUSTOM;
00872     levelMenuInfo.item_custom.width                 = 128;
00873     levelMenuInfo.item_custom.height                = 64;
00874     levelMenuInfo.item_custom.focuspic              = ART_CUSTOM1;
00875 
00876     levelMenuInfo.item_next.generic<