⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ui_splevel.c

📁 3D 游戏界的大牛人 John Carmack 终于放出了 Q3 的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
===========================================================================
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 Foobar; 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 = Q_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 ) {
			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 );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -