home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2000 March / maximum-cd-2000-03.iso / Quake3 Game Source / Q3AGameSource.exe / Main / ui_splevel.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-18  |  29.9 KB  |  989 lines

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