ioef/code/q3_ui/ui_splevel.c
Zack Middleton daa604ae9b Fix parsing bots in arena info with trailing spaces
q3_ui would shown bot at index of number of bots in list.
game would send empty name to addbot command and command would think skill
(i.e., 2.000000) was the bot name.
2015-01-12 21:28:03 -06:00

1016 lines
30 KiB
C

/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*
=============================================================================
SINGLE PLAYER LEVEL SELECT MENU
=============================================================================
*/
#include "ui_local.h"
#define ART_LEVELFRAME_FOCUS "menu/art/maps_select"
#define ART_LEVELFRAME_SELECTED "menu/art/maps_selected"
#define ART_ARROW "menu/art/narrow_0"
#define ART_ARROW_FOCUS "menu/art/narrow_1"
#define ART_MAP_UNKNOWN "menu/art/unknownmap"
#define ART_MAP_COMPLETE1 "menu/art/level_complete1"
#define ART_MAP_COMPLETE2 "menu/art/level_complete2"
#define ART_MAP_COMPLETE3 "menu/art/level_complete3"
#define ART_MAP_COMPLETE4 "menu/art/level_complete4"
#define ART_MAP_COMPLETE5 "menu/art/level_complete5"
#define ART_BACK0 "menu/art/back_0"
#define ART_BACK1 "menu/art/back_1"
#define ART_FIGHT0 "menu/art/fight_0"
#define ART_FIGHT1 "menu/art/fight_1"
#define ART_RESET0 "menu/art/reset_0"
#define ART_RESET1 "menu/art/reset_1"
#define ART_CUSTOM0 "menu/art/skirmish_0"
#define ART_CUSTOM1 "menu/art/skirmish_1"
#define ID_LEFTARROW 10
#define ID_PICTURE0 11
#define ID_PICTURE1 12
#define ID_PICTURE2 13
#define ID_PICTURE3 14
#define ID_RIGHTARROW 15
#define ID_PLAYERPIC 16
#define ID_AWARD1 17
#define ID_AWARD2 18
#define ID_AWARD3 19
#define ID_AWARD4 20
#define ID_AWARD5 21
#define ID_AWARD6 22
#define ID_BACK 23
#define ID_RESET 24
#define ID_CUSTOM 25
#define ID_NEXT 26
#define PLAYER_Y 314
#define AWARDS_Y (PLAYER_Y + 26)
typedef struct {
menuframework_s menu;
menutext_s item_banner;
menubitmap_s item_leftarrow;
menubitmap_s item_maps[4];
menubitmap_s item_rightarrow;
menubitmap_s item_player;
menubitmap_s item_awards[6];
menubitmap_s item_back;
menubitmap_s item_reset;
menubitmap_s item_custom;
menubitmap_s item_next;
menubitmap_s item_null;
qboolean reinit;
const char * selectedArenaInfo;
int numMaps;
char levelPicNames[4][MAX_QPATH];
char levelNames[4][16];
int levelScores[4];
int levelScoresSkill[4];
qhandle_t levelSelectedPic;
qhandle_t levelFocusPic;
qhandle_t levelCompletePic[5];
char playerModel[MAX_QPATH];
char playerPicName[MAX_QPATH];
int awardLevels[6];
sfxHandle_t awardSounds[6];
int numBots;
qhandle_t botPics[7];
char botNames[7][10];
} levelMenuInfo_t;
static levelMenuInfo_t levelMenuInfo;
static int selectedArenaSet;
static int selectedArena;
static int currentSet;
static int currentGame;
static int trainingTier;
static int finalTier;
static int minTier;
static int maxTier;
/*
=================
PlayerIcon
=================
*/
static void PlayerIcon( const char *modelAndSkin, char *iconName, int iconNameMaxSize ) {
char *skin;
char model[MAX_QPATH];
Q_strncpyz( model, modelAndSkin, sizeof(model));
skin = strrchr( model, '/' );
if ( skin ) {
*skin++ = '\0';
}
else {
skin = "default";
}
Com_sprintf(iconName, iconNameMaxSize, "models/players/%s/icon_%s.tga", model, skin );
if( !trap_R_RegisterShaderNoMip( iconName ) && Q_stricmp( skin, "default" ) != 0 ) {
Com_sprintf(iconName, iconNameMaxSize, "models/players/%s/icon_default.tga", model );
}
}
/*
=================
PlayerIconhandle
=================
*/
static qhandle_t PlayerIconHandle( const char *modelAndSkin ) {
char iconName[MAX_QPATH];
PlayerIcon( modelAndSkin, iconName, sizeof(iconName) );
return trap_R_RegisterShaderNoMip( iconName );
}
/*
=================
UI_SPLevelMenu_SetBots
=================
*/
static void UI_SPLevelMenu_SetBots( void ) {
char *p;
char *bot;
char *botInfo;
char bots[MAX_INFO_STRING];
levelMenuInfo.numBots = 0;
if ( selectedArenaSet > currentSet ) {
return;
}
Q_strncpyz( bots, Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "bots" ), sizeof(bots) );
p = &bots[0];
while( *p && levelMenuInfo.numBots < 7 ) {
//skip spaces
while( *p && *p == ' ' ) {
p++;
}
if( !*p ) {
break;
}
// mark start of bot name
bot = p;
// skip until space of null
while( *p && *p != ' ' ) {
p++;
}
if( *p ) {
*p++ = 0;
}
botInfo = UI_GetBotInfoByName( bot );
if(!botInfo)
{
botInfo = UI_GetBotInfoByNumber( levelMenuInfo.numBots );
}
if( botInfo ) {
levelMenuInfo.botPics[levelMenuInfo.numBots] = PlayerIconHandle( Info_ValueForKey( botInfo, "model" ) );
Q_strncpyz( levelMenuInfo.botNames[levelMenuInfo.numBots], Info_ValueForKey( botInfo, "name" ), 10 );
}
else {
levelMenuInfo.botPics[levelMenuInfo.numBots] = 0;
Q_strncpyz( levelMenuInfo.botNames[levelMenuInfo.numBots], bot, 10 );
}
Q_CleanStr( levelMenuInfo.botNames[levelMenuInfo.numBots] );
levelMenuInfo.numBots++;
}
}
/*
=================
UI_SPLevelMenu_SetMenuItems
=================
*/
static void UI_SPLevelMenu_SetMenuArena( int n, int level, const char *arenaInfo ) {
char map[MAX_QPATH];
Q_strncpyz( map, Info_ValueForKey( arenaInfo, "map" ), sizeof(map) );
Q_strncpyz( levelMenuInfo.levelNames[n], map, sizeof(levelMenuInfo.levelNames[n]) );
Q_strupr( levelMenuInfo.levelNames[n] );
UI_GetBestScore( level, &levelMenuInfo.levelScores[n], &levelMenuInfo.levelScoresSkill[n] );
if( levelMenuInfo.levelScores[n] > 8 ) {
levelMenuInfo.levelScores[n] = 8;
}
strcpy( levelMenuInfo.levelPicNames[n], va( "levelshots/%s.tga", map ) );
if( !trap_R_RegisterShaderNoMip( levelMenuInfo.levelPicNames[n] ) ) {
strcpy( levelMenuInfo.levelPicNames[n], ART_MAP_UNKNOWN );
}
levelMenuInfo.item_maps[n].shader = 0;
if ( selectedArenaSet > currentSet ) {
levelMenuInfo.item_maps[n].generic.flags |= QMF_GRAYED;
}
else {
levelMenuInfo.item_maps[n].generic.flags &= ~QMF_GRAYED;
}
levelMenuInfo.item_maps[n].generic.flags &= ~QMF_INACTIVE;
}
static void UI_SPLevelMenu_SetMenuItems( void ) {
int n;
int level;
const char *arenaInfo;
if ( selectedArenaSet > currentSet ) {
selectedArena = -1;
}
else if ( selectedArena == -1 ) {
selectedArena = 0;
}
if( selectedArenaSet == trainingTier || selectedArenaSet == finalTier ) {
selectedArena = 0;
}
if( selectedArena != -1 ) {
trap_Cvar_SetValue( "ui_spSelection", selectedArenaSet * ARENAS_PER_TIER + selectedArena );
}
if( selectedArenaSet == trainingTier ) {
arenaInfo = UI_GetSpecialArenaInfo( "training" );
level = atoi( Info_ValueForKey( arenaInfo, "num" ) );
UI_SPLevelMenu_SetMenuArena( 0, level, arenaInfo );
levelMenuInfo.selectedArenaInfo = arenaInfo;
levelMenuInfo.item_maps[0].generic.x = 256;
Bitmap_Init( &levelMenuInfo.item_maps[0] );
levelMenuInfo.item_maps[0].generic.bottom += 32;
levelMenuInfo.numMaps = 1;
levelMenuInfo.item_maps[1].generic.flags |= QMF_INACTIVE;
levelMenuInfo.item_maps[2].generic.flags |= QMF_INACTIVE;
levelMenuInfo.item_maps[3].generic.flags |= QMF_INACTIVE;
levelMenuInfo.levelPicNames[1][0] = 0;
levelMenuInfo.levelPicNames[2][0] = 0;
levelMenuInfo.levelPicNames[3][0] = 0;
levelMenuInfo.item_maps[1].shader = 0;
levelMenuInfo.item_maps[2].shader = 0;
levelMenuInfo.item_maps[3].shader = 0;
}
else if( selectedArenaSet == finalTier ) {
arenaInfo = UI_GetSpecialArenaInfo( "final" );
level = atoi( Info_ValueForKey( arenaInfo, "num" ) );
UI_SPLevelMenu_SetMenuArena( 0, level, arenaInfo );
levelMenuInfo.selectedArenaInfo = arenaInfo;
levelMenuInfo.item_maps[0].generic.x = 256;
Bitmap_Init( &levelMenuInfo.item_maps[0] );
levelMenuInfo.item_maps[0].generic.bottom += 32;
levelMenuInfo.numMaps = 1;
levelMenuInfo.item_maps[1].generic.flags |= QMF_INACTIVE;
levelMenuInfo.item_maps[2].generic.flags |= QMF_INACTIVE;
levelMenuInfo.item_maps[3].generic.flags |= QMF_INACTIVE;
levelMenuInfo.levelPicNames[1][0] = 0;
levelMenuInfo.levelPicNames[2][0] = 0;
levelMenuInfo.levelPicNames[3][0] = 0;
levelMenuInfo.item_maps[1].shader = 0;
levelMenuInfo.item_maps[2].shader = 0;
levelMenuInfo.item_maps[3].shader = 0;
}
else {
levelMenuInfo.item_maps[0].generic.x = 46;
Bitmap_Init( &levelMenuInfo.item_maps[0] );
levelMenuInfo.item_maps[0].generic.bottom += 18;
levelMenuInfo.numMaps = 4;
for ( n = 0; n < 4; n++ ) {
level = selectedArenaSet * ARENAS_PER_TIER + n;
arenaInfo = UI_GetArenaInfoByNumber( level );
UI_SPLevelMenu_SetMenuArena( n, level, arenaInfo );
}
if( selectedArena != -1 ) {
levelMenuInfo.selectedArenaInfo = UI_GetArenaInfoByNumber( selectedArenaSet * ARENAS_PER_TIER + selectedArena );
}
}
// enable/disable arrows when they are valid/invalid
if ( selectedArenaSet == minTier ) {
levelMenuInfo.item_leftarrow.generic.flags |= ( QMF_INACTIVE | QMF_HIDDEN );
}
else {
levelMenuInfo.item_leftarrow.generic.flags &= ~( QMF_INACTIVE | QMF_HIDDEN );
}
if ( selectedArenaSet == maxTier ) {
levelMenuInfo.item_rightarrow.generic.flags |= ( QMF_INACTIVE | QMF_HIDDEN );
}
else {
levelMenuInfo.item_rightarrow.generic.flags &= ~( QMF_INACTIVE | QMF_HIDDEN );
}
UI_SPLevelMenu_SetBots();
}
/*
=================
UI_SPLevelMenu_ResetEvent
=================
*/
static void UI_SPLevelMenu_ResetDraw( void ) {
UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 0, "WARNING: This resets all of the", UI_CENTER|UI_SMALLFONT, color_yellow );
UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 1, "single player game variables.", UI_CENTER|UI_SMALLFONT, color_yellow );
UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 2, "Do this only if you want to", UI_CENTER|UI_SMALLFONT, color_yellow );
UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 3, "start over from the beginning.", UI_CENTER|UI_SMALLFONT, color_yellow );
}
static void UI_SPLevelMenu_ResetAction( qboolean result ) {
if( !result ) {
return;
}
// clear game variables
UI_NewGame();
if ( UI_GetSpecialArenaInfo( "training" ) ) {
trap_Cvar_SetValue( "ui_spSelection", -4 );
} else {
trap_Cvar_SetValue( "ui_spSelection", 0 );
}
// make the level select menu re-initialize
UI_PopMenu();
UI_SPLevelMenu();
}
static void UI_SPLevelMenu_ResetEvent( void* ptr, int event )
{
if (event != QM_ACTIVATED) {
return;
}
UI_ConfirmMenu( "RESET GAME?", UI_SPLevelMenu_ResetDraw, UI_SPLevelMenu_ResetAction );
}
/*
=================
UI_SPLevelMenu_LevelEvent
=================
*/
static void UI_SPLevelMenu_LevelEvent( void* ptr, int notification ) {
if (notification != QM_ACTIVATED) {
return;
}
if ( selectedArenaSet == trainingTier || selectedArenaSet == finalTier ) {
return;
}
selectedArena = ((menucommon_s*)ptr)->id - ID_PICTURE0;
levelMenuInfo.selectedArenaInfo = UI_GetArenaInfoByNumber( selectedArenaSet * ARENAS_PER_TIER + selectedArena );
UI_SPLevelMenu_SetBots();
trap_Cvar_SetValue( "ui_spSelection", selectedArenaSet * ARENAS_PER_TIER + selectedArena );
}
/*
=================
UI_SPLevelMenu_LeftArrowEvent
=================
*/
static void UI_SPLevelMenu_LeftArrowEvent( void* ptr, int notification ) {
if (notification != QM_ACTIVATED) {
return;
}
if ( selectedArenaSet == minTier ) {
return;
}
selectedArenaSet--;
UI_SPLevelMenu_SetMenuItems();
}
/*
=================
UI_SPLevelMenu_RightArrowEvent
=================
*/
static void UI_SPLevelMenu_RightArrowEvent( void* ptr, int notification ) {
if (notification != QM_ACTIVATED) {
return;
}
if ( selectedArenaSet == maxTier ) {
return;
}
selectedArenaSet++;
UI_SPLevelMenu_SetMenuItems();
}
/*
=================
UI_SPLevelMenu_PlayerEvent
=================
*/
static void UI_SPLevelMenu_PlayerEvent( void* ptr, int notification ) {
if (notification != QM_ACTIVATED) {
return;
}
UI_PlayerSettingsMenu();
}
/*
=================
UI_SPLevelMenu_AwardEvent
=================
*/
static void UI_SPLevelMenu_AwardEvent( void* ptr, int notification ) {
int n;
if (notification != QM_ACTIVATED) {
return;
}
n = ((menucommon_s*)ptr)->id - ID_AWARD1;
trap_S_StartLocalSound( levelMenuInfo.awardSounds[n], CHAN_ANNOUNCER );
}
/*
=================
UI_SPLevelMenu_NextEvent
=================
*/
static void UI_SPLevelMenu_NextEvent( void* ptr, int notification ) {
if (notification != QM_ACTIVATED) {
return;
}
if ( selectedArenaSet > currentSet ) {
return;
}
if ( selectedArena == -1 ) {
selectedArena = 0;
}
UI_SPSkillMenu( levelMenuInfo.selectedArenaInfo );
}
/*
=================
UI_SPLevelMenu_BackEvent
=================
*/
static void UI_SPLevelMenu_BackEvent( void* ptr, int notification ) {
if (notification != QM_ACTIVATED) {
return;
}
if ( selectedArena == -1 ) {
selectedArena = 0;
}
UI_PopMenu();
}
/*
=================
UI_SPLevelMenu_CustomEvent
=================
*/
static void UI_SPLevelMenu_CustomEvent( void* ptr, int notification ) {
if (notification != QM_ACTIVATED) {
return;
}
UI_StartServerMenu( qfalse );
}
/*
=================
UI_SPLevelMenu_MenuDraw
=================
*/
#define LEVEL_DESC_LEFT_MARGIN 332
static void UI_SPLevelMenu_MenuDraw( void ) {
int n, i;
int x, y;
vec4_t color;
int level;
// int fraglimit;
int pad;
char buf[MAX_INFO_VALUE];
char string[64];
if( levelMenuInfo.reinit ) {
UI_PopMenu();
UI_SPLevelMenu();
return;
}
// draw player name
trap_Cvar_VariableStringBuffer( "name", string, 32 );
Q_CleanStr( string );
UI_DrawProportionalString( 320, PLAYER_Y, string, UI_CENTER|UI_SMALLFONT, color_orange );
// check for model changes
trap_Cvar_VariableStringBuffer( "model", buf, sizeof(buf) );
if( Q_stricmp( buf, levelMenuInfo.playerModel ) != 0 ) {
Q_strncpyz( levelMenuInfo.playerModel, buf, sizeof(levelMenuInfo.playerModel) );
PlayerIcon( levelMenuInfo.playerModel, levelMenuInfo.playerPicName, sizeof(levelMenuInfo.playerPicName) );
levelMenuInfo.item_player.shader = 0;
}
// standard menu drawing
Menu_Draw( &levelMenuInfo.menu );
// draw player award levels
y = AWARDS_Y;
i = 0;
for( n = 0; n < 6; n++ ) {
level = levelMenuInfo.awardLevels[n];
if( level > 0 ) {
if( i & 1 ) {
x = 224 - (i - 1 ) / 2 * (48 + 16);
}
else {
x = 368 + i / 2 * (48 + 16);
}
i++;
if( level == 1 ) {
continue;
}
if( level >= 1000000 ) {
Com_sprintf( string, sizeof(string), "%im", level / 1000000 );
}
else if( level >= 1000 ) {
Com_sprintf( string, sizeof(string), "%ik", level / 1000 );
}
else {
Com_sprintf( string, sizeof(string), "%i", level );
}
UI_DrawString( x + 24, y + 48, string, UI_CENTER, color_yellow );
}
}
UI_DrawProportionalString( 18, 38, va( "Tier %i", selectedArenaSet + 1 ), UI_LEFT|UI_SMALLFONT, color_orange );
for ( n = 0; n < levelMenuInfo.numMaps; n++ ) {
x = levelMenuInfo.item_maps[n].generic.x;
y = levelMenuInfo.item_maps[n].generic.y;
UI_FillRect( x, y + 96, 128, 18, color_black );
}
if ( selectedArenaSet > currentSet ) {
UI_DrawProportionalString( 320, 216, "ACCESS DENIED", UI_CENTER|UI_BIGFONT, color_red );
return;
}
// show levelshots for levels of current tier
Vector4Copy( color_white, color );
color[3] = 0.5+0.5*sin(uis.realtime/PULSE_DIVISOR);
for ( n = 0; n < levelMenuInfo.numMaps; n++ ) {
x = levelMenuInfo.item_maps[n].generic.x;
y = levelMenuInfo.item_maps[n].generic.y;
UI_DrawString( x + 64, y + 96, levelMenuInfo.levelNames[n], UI_CENTER|UI_SMALLFONT, color_orange );
if( levelMenuInfo.levelScores[n] == 1 ) {
UI_DrawHandlePic( x, y, 128, 96, levelMenuInfo.levelCompletePic[levelMenuInfo.levelScoresSkill[n] - 1] );
}
if ( n == selectedArena ) {
if( Menu_ItemAtCursor( &levelMenuInfo.menu ) == &levelMenuInfo.item_maps[n] ) {
trap_R_SetColor( color );
}
UI_DrawHandlePic( x-1, y-1, 130, 130 - 14, levelMenuInfo.levelSelectedPic );
trap_R_SetColor( NULL );
}
else if( Menu_ItemAtCursor( &levelMenuInfo.menu ) == &levelMenuInfo.item_maps[n] ) {
trap_R_SetColor( color );
UI_DrawHandlePic( x-31, y-30, 256, 256-27, levelMenuInfo.levelFocusPic);
trap_R_SetColor( NULL );
}
}
// show map name and long name of selected level
y = 192;
Q_strncpyz( buf, Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "map" ), 20 );
Q_strupr( buf );
Com_sprintf( string, sizeof(string), "%s: %s", buf, Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "longname" ) );
UI_DrawProportionalString( 320, y, string, UI_CENTER|UI_SMALLFONT, color_orange );
// fraglimit = atoi( Info_ValueForKey( levelMenuInfo.selectedArenaInfo, "fraglimit" ) );
// UI_DrawString( 18, 212, va("Frags %i", fraglimit) , UI_LEFT|UI_SMALLFONT, color_orange );
// draw bot opponents
y += 24;
pad = (7 - levelMenuInfo.numBots) * (64 + 26) / 2;
for( n = 0; n < levelMenuInfo.numBots; n++ ) {
x = 18 + pad + (64 + 26) * n;
if( levelMenuInfo.botPics[n] ) {
UI_DrawHandlePic( x, y, 64, 64, levelMenuInfo.botPics[n]);
}
else {
UI_FillRect( x, y, 64, 64, color_black );
UI_DrawProportionalString( x+22, y+18, "?", UI_BIGFONT, color_orange );
}
UI_DrawString( x, y + 64, levelMenuInfo.botNames[n], UI_SMALLFONT|UI_LEFT, color_orange );
}
}
/*
=================
UI_SPLevelMenu_Cache
=================
*/
void UI_SPLevelMenu_Cache( void ) {
int n;
trap_R_RegisterShaderNoMip( ART_LEVELFRAME_FOCUS );
trap_R_RegisterShaderNoMip( ART_LEVELFRAME_SELECTED );
trap_R_RegisterShaderNoMip( ART_ARROW );
trap_R_RegisterShaderNoMip( ART_ARROW_FOCUS );
trap_R_RegisterShaderNoMip( ART_MAP_UNKNOWN );
trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE1 );
trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE2 );
trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE3 );
trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE4 );
trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE5 );
trap_R_RegisterShaderNoMip( ART_BACK0 );
trap_R_RegisterShaderNoMip( ART_BACK1 );
trap_R_RegisterShaderNoMip( ART_FIGHT0 );
trap_R_RegisterShaderNoMip( ART_FIGHT1 );
trap_R_RegisterShaderNoMip( ART_RESET0 );
trap_R_RegisterShaderNoMip( ART_RESET1 );
trap_R_RegisterShaderNoMip( ART_CUSTOM0 );
trap_R_RegisterShaderNoMip( ART_CUSTOM1 );
for( n = 0; n < 6; n++ ) {
trap_R_RegisterShaderNoMip( ui_medalPicNames[n] );
levelMenuInfo.awardSounds[n] = trap_S_RegisterSound( ui_medalSounds[n], qfalse );
}
levelMenuInfo.levelSelectedPic = trap_R_RegisterShaderNoMip( ART_LEVELFRAME_SELECTED );
levelMenuInfo.levelFocusPic = trap_R_RegisterShaderNoMip( ART_LEVELFRAME_FOCUS );
levelMenuInfo.levelCompletePic[0] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE1 );
levelMenuInfo.levelCompletePic[1] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE2 );
levelMenuInfo.levelCompletePic[2] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE3 );
levelMenuInfo.levelCompletePic[3] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE4 );
levelMenuInfo.levelCompletePic[4] = trap_R_RegisterShaderNoMip( ART_MAP_COMPLETE5 );
}
/*
=================
UI_SPLevelMenu_Init
=================
*/
static void UI_SPLevelMenu_Init( void ) {
int skill;
int n;
int x, y;
int count;
char buf[MAX_QPATH];
skill = (int)trap_Cvar_VariableValue( "g_spSkill" );
if( skill < 1 || skill > 5 ) {
trap_Cvar_Set( "g_spSkill", "2" );
}
memset( &levelMenuInfo, 0, sizeof(levelMenuInfo) );
levelMenuInfo.menu.fullscreen = qtrue;
levelMenuInfo.menu.wrapAround = qtrue;
levelMenuInfo.menu.draw = UI_SPLevelMenu_MenuDraw;
UI_SPLevelMenu_Cache();
levelMenuInfo.item_banner.generic.type = MTYPE_BTEXT;
levelMenuInfo.item_banner.generic.x = 320;
levelMenuInfo.item_banner.generic.y = 16;
levelMenuInfo.item_banner.string = "CHOOSE LEVEL";
levelMenuInfo.item_banner.color = color_red;
levelMenuInfo.item_banner.style = UI_CENTER;
levelMenuInfo.item_leftarrow.generic.type = MTYPE_BITMAP;
levelMenuInfo.item_leftarrow.generic.name = ART_ARROW;
levelMenuInfo.item_leftarrow.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
levelMenuInfo.item_leftarrow.generic.x = 18;
levelMenuInfo.item_leftarrow.generic.y = 64;
levelMenuInfo.item_leftarrow.generic.callback = UI_SPLevelMenu_LeftArrowEvent;
levelMenuInfo.item_leftarrow.generic.id = ID_LEFTARROW;
levelMenuInfo.item_leftarrow.width = 16;
levelMenuInfo.item_leftarrow.height = 114;
levelMenuInfo.item_leftarrow.focuspic = ART_ARROW_FOCUS;
levelMenuInfo.item_maps[0].generic.type = MTYPE_BITMAP;
levelMenuInfo.item_maps[0].generic.name = levelMenuInfo.levelPicNames[0];
levelMenuInfo.item_maps[0].generic.flags = QMF_LEFT_JUSTIFY;
levelMenuInfo.item_maps[0].generic.x = 46;
levelMenuInfo.item_maps[0].generic.y = 64;
levelMenuInfo.item_maps[0].generic.id = ID_PICTURE0;
levelMenuInfo.item_maps[0].generic.callback = UI_SPLevelMenu_LevelEvent;
levelMenuInfo.item_maps[0].width = 128;
levelMenuInfo.item_maps[0].height = 96;
levelMenuInfo.item_maps[1].generic.type = MTYPE_BITMAP;
levelMenuInfo.item_maps[1].generic.name = levelMenuInfo.levelPicNames[1];
levelMenuInfo.item_maps[1].generic.flags = QMF_LEFT_JUSTIFY;
levelMenuInfo.item_maps[1].generic.x = 186;
levelMenuInfo.item_maps[1].generic.y = 64;
levelMenuInfo.item_maps[1].generic.id = ID_PICTURE1;
levelMenuInfo.item_maps[1].generic.callback = UI_SPLevelMenu_LevelEvent;
levelMenuInfo.item_maps[1].width = 128;
levelMenuInfo.item_maps[1].height = 96;
levelMenuInfo.item_maps[2].generic.type = MTYPE_BITMAP;
levelMenuInfo.item_maps[2].generic.name = levelMenuInfo.levelPicNames[2];
levelMenuInfo.item_maps[2].generic.flags = QMF_LEFT_JUSTIFY;
levelMenuInfo.item_maps[2].generic.x = 326;
levelMenuInfo.item_maps[2].generic.y = 64;
levelMenuInfo.item_maps[2].generic.id = ID_PICTURE2;
levelMenuInfo.item_maps[2].generic.callback = UI_SPLevelMenu_LevelEvent;
levelMenuInfo.item_maps[2].width = 128;
levelMenuInfo.item_maps[2].height = 96;
levelMenuInfo.item_maps[3].generic.type = MTYPE_BITMAP;
levelMenuInfo.item_maps[3].generic.name = levelMenuInfo.levelPicNames[3];
levelMenuInfo.item_maps[3].generic.flags = QMF_LEFT_JUSTIFY;
levelMenuInfo.item_maps[3].generic.x = 466;
levelMenuInfo.item_maps[3].generic.y = 64;
levelMenuInfo.item_maps[3].generic.id = ID_PICTURE3;
levelMenuInfo.item_maps[3].generic.callback = UI_SPLevelMenu_LevelEvent;
levelMenuInfo.item_maps[3].width = 128;
levelMenuInfo.item_maps[3].height = 96;
levelMenuInfo.item_rightarrow.generic.type = MTYPE_BITMAP;
levelMenuInfo.item_rightarrow.generic.name = ART_ARROW;
levelMenuInfo.item_rightarrow.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
levelMenuInfo.item_rightarrow.generic.x = 606;
levelMenuInfo.item_rightarrow.generic.y = 64;
levelMenuInfo.item_rightarrow.generic.callback = UI_SPLevelMenu_RightArrowEvent;
levelMenuInfo.item_rightarrow.generic.id = ID_RIGHTARROW;
levelMenuInfo.item_rightarrow.width = -16;
levelMenuInfo.item_rightarrow.height = 114;
levelMenuInfo.item_rightarrow.focuspic = ART_ARROW_FOCUS;
trap_Cvar_VariableStringBuffer( "model", levelMenuInfo.playerModel, sizeof(levelMenuInfo.playerModel) );
PlayerIcon( levelMenuInfo.playerModel, levelMenuInfo.playerPicName, sizeof(levelMenuInfo.playerPicName) );
levelMenuInfo.item_player.generic.type = MTYPE_BITMAP;
levelMenuInfo.item_player.generic.name = levelMenuInfo.playerPicName;
levelMenuInfo.item_player.generic.flags = QMF_LEFT_JUSTIFY|QMF_MOUSEONLY;
levelMenuInfo.item_player.generic.x = 288;
levelMenuInfo.item_player.generic.y = AWARDS_Y;
levelMenuInfo.item_player.generic.id = ID_PLAYERPIC;
levelMenuInfo.item_player.generic.callback = UI_SPLevelMenu_PlayerEvent;
levelMenuInfo.item_player.width = 64;
levelMenuInfo.item_player.height = 64;
for( n = 0; n < 6; n++ ) {
levelMenuInfo.awardLevels[n] = UI_GetAwardLevel( n );
}
levelMenuInfo.awardLevels[AWARD_FRAGS] = 100 * (levelMenuInfo.awardLevels[AWARD_FRAGS] / 100);
y = AWARDS_Y;
count = 0;
for( n = 0; n < 6; n++ ) {
if( levelMenuInfo.awardLevels[n] ) {
if( count & 1 ) {
x = 224 - (count - 1 ) / 2 * (48 + 16);
}
else {
x = 368 + count / 2 * (48 + 16);
}
levelMenuInfo.item_awards[count].generic.type = MTYPE_BITMAP;
levelMenuInfo.item_awards[count].generic.name = ui_medalPicNames[n];
levelMenuInfo.item_awards[count].generic.flags = QMF_LEFT_JUSTIFY|QMF_SILENT|QMF_MOUSEONLY;
levelMenuInfo.item_awards[count].generic.x = x;
levelMenuInfo.item_awards[count].generic.y = y;
levelMenuInfo.item_awards[count].generic.id = ID_AWARD1 + n;
levelMenuInfo.item_awards[count].generic.callback = UI_SPLevelMenu_AwardEvent;
levelMenuInfo.item_awards[count].width = 48;
levelMenuInfo.item_awards[count].height = 48;
count++;
}
}
levelMenuInfo.item_back.generic.type = MTYPE_BITMAP;
levelMenuInfo.item_back.generic.name = ART_BACK0;
levelMenuInfo.item_back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
levelMenuInfo.item_back.generic.x = 0;
levelMenuInfo.item_back.generic.y = 480-64;
levelMenuInfo.item_back.generic.callback = UI_SPLevelMenu_BackEvent;
levelMenuInfo.item_back.generic.id = ID_BACK;
levelMenuInfo.item_back.width = 128;
levelMenuInfo.item_back.height = 64;
levelMenuInfo.item_back.focuspic = ART_BACK1;
levelMenuInfo.item_reset.generic.type = MTYPE_BITMAP;
levelMenuInfo.item_reset.generic.name = ART_RESET0;
levelMenuInfo.item_reset.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
levelMenuInfo.item_reset.generic.x = 170;
levelMenuInfo.item_reset.generic.y = 480-64;
levelMenuInfo.item_reset.generic.callback = UI_SPLevelMenu_ResetEvent;
levelMenuInfo.item_reset.generic.id = ID_RESET;
levelMenuInfo.item_reset.width = 128;
levelMenuInfo.item_reset.height = 64;
levelMenuInfo.item_reset.focuspic = ART_RESET1;
levelMenuInfo.item_custom.generic.type = MTYPE_BITMAP;
levelMenuInfo.item_custom.generic.name = ART_CUSTOM0;
levelMenuInfo.item_custom.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
levelMenuInfo.item_custom.generic.x = 342;
levelMenuInfo.item_custom.generic.y = 480-64;
levelMenuInfo.item_custom.generic.callback = UI_SPLevelMenu_CustomEvent;
levelMenuInfo.item_custom.generic.id = ID_CUSTOM;
levelMenuInfo.item_custom.width = 128;
levelMenuInfo.item_custom.height = 64;
levelMenuInfo.item_custom.focuspic = ART_CUSTOM1;
levelMenuInfo.item_next.generic.type = MTYPE_BITMAP;
levelMenuInfo.item_next.generic.name = ART_FIGHT0;
levelMenuInfo.item_next.generic.flags = QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS;
levelMenuInfo.item_next.generic.x = 640;
levelMenuInfo.item_next.generic.y = 480-64;
levelMenuInfo.item_next.generic.callback = UI_SPLevelMenu_NextEvent;
levelMenuInfo.item_next.generic.id = ID_NEXT;
levelMenuInfo.item_next.width = 128;
levelMenuInfo.item_next.height = 64;
levelMenuInfo.item_next.focuspic = ART_FIGHT1;
levelMenuInfo.item_null.generic.type = MTYPE_BITMAP;
levelMenuInfo.item_null.generic.flags = QMF_LEFT_JUSTIFY|QMF_MOUSEONLY|QMF_SILENT;
levelMenuInfo.item_null.generic.x = 0;
levelMenuInfo.item_null.generic.y = 0;
levelMenuInfo.item_null.width = 640;
levelMenuInfo.item_null.height = 480;
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_banner );
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_leftarrow );
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_maps[0] );
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_maps[1] );
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_maps[2] );
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_maps[3] );
levelMenuInfo.item_maps[0].generic.bottom += 18;
levelMenuInfo.item_maps[1].generic.bottom += 18;
levelMenuInfo.item_maps[2].generic.bottom += 18;
levelMenuInfo.item_maps[3].generic.bottom += 18;
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_rightarrow );
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_player );
for( n = 0; n < count; n++ ) {
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_awards[n] );
}
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_back );
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_reset );
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_custom );
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_next );
Menu_AddItem( &levelMenuInfo.menu, &levelMenuInfo.item_null );
trap_Cvar_VariableStringBuffer( "ui_spSelection", buf, sizeof(buf) );
if( *buf ) {
n = atoi( buf );
selectedArenaSet = n / ARENAS_PER_TIER;
selectedArena = n % ARENAS_PER_TIER;
}
else {
selectedArenaSet = currentSet;
selectedArena = currentGame;
}
UI_SPLevelMenu_SetMenuItems();
}
/*
=================
UI_SPLevelMenu
=================
*/
void UI_SPLevelMenu( void ) {
int level;
int trainingLevel;
const char *arenaInfo;
trainingTier = -1;
arenaInfo = UI_GetSpecialArenaInfo( "training" );
if( arenaInfo ) {
minTier = trainingTier;
trainingLevel = atoi( Info_ValueForKey( arenaInfo, "num" ) );
}
else {
minTier = 0;
trainingLevel = -2;
}
finalTier = UI_GetNumSPTiers();
arenaInfo = UI_GetSpecialArenaInfo( "final" );
if( arenaInfo ) {
maxTier = finalTier;
}
else {
maxTier = finalTier - 1;
if( maxTier < minTier ) {
maxTier = minTier;
}
}
level = UI_GetCurrentGame();
if ( level == -1 ) {
level = UI_GetNumSPArenas() - 1;
if( maxTier == finalTier ) {
level++;
}
}
if( level == trainingLevel ) {
currentSet = -1;
currentGame = 0;
}
else {
currentSet = level / ARENAS_PER_TIER;
currentGame = level % ARENAS_PER_TIER;
}
UI_SPLevelMenu_Init();
UI_PushMenu( &levelMenuInfo.menu );
Menu_SetCursorToItem( &levelMenuInfo.menu, &levelMenuInfo.item_next );
}
/*
=================
UI_SPLevelMenu_f
=================
*/
void UI_SPLevelMenu_f( void ) {
trap_Key_SetCatcher( KEYCATCH_UI );
uis.menusp = 0;
UI_SPLevelMenu();
}
/*
=================
UI_SPLevelMenu_ReInit
=================
*/
void UI_SPLevelMenu_ReInit( void ) {
levelMenuInfo.reinit = qtrue;
}