📄 ui_sppostgame.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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*
=============================================================================
SINGLE PLAYER POSTGAME MENU
=============================================================================
*/
#include "ui_local.h"
#define MAX_SCOREBOARD_CLIENTS 8
#define AWARD_PRESENTATION_TIME 2000
#define ART_MENU0 "menu/art/menu_0"
#define ART_MENU1 "menu/art/menu_1"
#define ART_REPLAY0 "menu/art/replay_0"
#define ART_REPLAY1 "menu/art/replay_1"
#define ART_NEXT0 "menu/art/next_0"
#define ART_NEXT1 "menu/art/next_1"
#define ID_AGAIN 10
#define ID_NEXT 11
#define ID_MENU 12
typedef struct {
menuframework_s menu;
menubitmap_s item_again;
menubitmap_s item_next;
menubitmap_s item_menu;
int phase;
int ignoreKeysTime;
int starttime;
int scoreboardtime;
int serverId;
int clientNums[MAX_SCOREBOARD_CLIENTS];
int ranks[MAX_SCOREBOARD_CLIENTS];
int scores[MAX_SCOREBOARD_CLIENTS];
char placeNames[3][64];
int level;
int numClients;
int won;
int numAwards;
int awardsEarned[6];
int awardsLevels[6];
qboolean playedSound[6];
int lastTier;
sfxHandle_t winnerSound;
} postgameMenuInfo_t;
static postgameMenuInfo_t postgameMenuInfo;
static char arenainfo[MAX_INFO_VALUE];
char *ui_medalNames[] = {"Accuracy", "Impressive", "Excellent", "Gauntlet", "Frags", "Perfect"};
char *ui_medalPicNames[] = {
"menu/medals/medal_accuracy",
"menu/medals/medal_impressive",
"menu/medals/medal_excellent",
"menu/medals/medal_gauntlet",
"menu/medals/medal_frags",
"menu/medals/medal_victory"
};
char *ui_medalSounds[] = {
"sound/feedback/accuracy.wav",
"sound/feedback/impressive_a.wav",
"sound/feedback/excellent_a.wav",
"sound/feedback/gauntlet.wav",
"sound/feedback/frags.wav",
"sound/feedback/perfect.wav"
};
/*
=================
UI_SPPostgameMenu_AgainEvent
=================
*/
static void UI_SPPostgameMenu_AgainEvent( void* ptr, int event )
{
if (event != QM_ACTIVATED) {
return;
}
UI_PopMenu();
trap_Cmd_ExecuteText( EXEC_APPEND, "map_restart 0\n" );
}
/*
=================
UI_SPPostgameMenu_NextEvent
=================
*/
static void UI_SPPostgameMenu_NextEvent( void* ptr, int event ) {
int currentSet;
int levelSet;
int level;
int currentLevel;
const char *arenaInfo;
if (event != QM_ACTIVATED) {
return;
}
UI_PopMenu();
// handle specially if we just won the training map
if( postgameMenuInfo.won == 0 ) {
level = 0;
}
else {
level = postgameMenuInfo.level + 1;
}
levelSet = level / ARENAS_PER_TIER;
currentLevel = UI_GetCurrentGame();
if( currentLevel == -1 ) {
currentLevel = postgameMenuInfo.level;
}
currentSet = currentLevel / ARENAS_PER_TIER;
if( levelSet > currentSet || levelSet == UI_GetNumSPTiers() ) {
level = currentLevel;
}
arenaInfo = UI_GetArenaInfoByNumber( level );
if ( !arenaInfo ) {
return;
}
UI_SPArena_Start( arenaInfo );
}
/*
=================
UI_SPPostgameMenu_MenuEvent
=================
*/
static void UI_SPPostgameMenu_MenuEvent( void* ptr, int event )
{
if (event != QM_ACTIVATED) {
return;
}
UI_PopMenu();
trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect; levelselect\n" );
}
/*
=================
UI_SPPostgameMenu_MenuKey
=================
*/
static sfxHandle_t UI_SPPostgameMenu_MenuKey( int key ) {
if ( uis.realtime < postgameMenuInfo.ignoreKeysTime ) {
return 0;
}
if( postgameMenuInfo.phase == 1 ) {
trap_Cmd_ExecuteText( EXEC_APPEND, "abort_podium\n" );
postgameMenuInfo.phase = 2;
postgameMenuInfo.starttime = uis.realtime;
postgameMenuInfo.ignoreKeysTime = uis.realtime + 250;
return 0;
}
if( postgameMenuInfo.phase == 2 ) {
postgameMenuInfo.phase = 3;
postgameMenuInfo.starttime = uis.realtime;
postgameMenuInfo.ignoreKeysTime = uis.realtime + 250;
return 0;
}
if( key == K_ESCAPE || key == K_MOUSE2 ) {
return 0;
}
return Menu_DefaultKey( &postgameMenuInfo.menu, key );
}
static int medalLocations[6] = {144, 448, 88, 504, 32, 560};
static void UI_SPPostgameMenu_DrawAwardsMedals( int max ) {
int n;
int medal;
int amount;
int x, y;
char buf[16];
for( n = 0; n < max; n++ ) {
x = medalLocations[n];
y = 64;
medal = postgameMenuInfo.awardsEarned[n];
amount = postgameMenuInfo.awardsLevels[n];
UI_DrawNamedPic( x, y, 48, 48, ui_medalPicNames[medal] );
if( medal == AWARD_ACCURACY ) {
Com_sprintf( buf, sizeof(buf), "%i%%", amount );
}
else {
if( amount == 1 ) {
continue;
}
Com_sprintf( buf, sizeof(buf), "%i", amount );
}
UI_DrawString( x + 24, y + 52, buf, UI_CENTER, color_yellow );
}
}
static void UI_SPPostgameMenu_DrawAwardsPresentation( int timer ) {
int awardNum;
int atimer;
vec4_t color;
awardNum = timer / AWARD_PRESENTATION_TIME;
atimer = timer % AWARD_PRESENTATION_TIME;
color[0] = color[1] = color[2] = 1.0f;
color[3] = (float)( AWARD_PRESENTATION_TIME - atimer ) / (float)AWARD_PRESENTATION_TIME;
UI_DrawProportionalString( 320, 64, ui_medalNames[postgameMenuInfo.awardsEarned[awardNum]], UI_CENTER, color );
UI_SPPostgameMenu_DrawAwardsMedals( awardNum + 1 );
if( !postgameMenuInfo.playedSound[awardNum] ) {
postgameMenuInfo.playedSound[awardNum] = qtrue;
trap_S_StartLocalSound( trap_S_RegisterSound( ui_medalSounds[postgameMenuInfo.awardsEarned[awardNum]], qfalse ), CHAN_ANNOUNCER );
}
}
/*
=================
UI_SPPostgameMenu_MenuDrawScoreLine
=================
*/
static void UI_SPPostgameMenu_MenuDrawScoreLine( int n, int y ) {
int rank;
char name[64];
char info[MAX_INFO_STRING];
if( n > (postgameMenuInfo.numClients + 1) ) {
n -= (postgameMenuInfo.numClients + 2);
}
if( n >= postgameMenuInfo.numClients ) {
return;
}
rank = postgameMenuInfo.ranks[n];
if( rank & RANK_TIED_FLAG ) {
UI_DrawString( 640 - 31 * SMALLCHAR_WIDTH, y, "(tie)", UI_LEFT|UI_SMALLFONT, color_white );
rank &= ~RANK_TIED_FLAG;
}
trap_GetConfigString( CS_PLAYERS + postgameMenuInfo.clientNums[n], info, MAX_INFO_STRING );
Q_strncpyz( name, Info_ValueForKey( info, "n" ), sizeof(name) );
Q_CleanStr( name );
UI_DrawString( 640 - 25 * SMALLCHAR_WIDTH, y, va( "#%i: %-16s %2i", rank + 1, name, postgameMenuInfo.scores[n] ), UI_LEFT|UI_SMALLFONT, color_white );
}
/*
=================
UI_SPPostgameMenu_MenuDraw
=================
*/
static void UI_SPPostgameMenu_MenuDraw( void ) {
int timer;
int serverId;
int n;
char info[MAX_INFO_STRING];
trap_GetConfigString( CS_SYSTEMINFO, info, sizeof(info) );
serverId = atoi( Info_ValueForKey( info, "sv_serverid" ) );
if( serverId != postgameMenuInfo.serverId ) {
UI_PopMenu();
return;
}
// phase 1
if ( postgameMenuInfo.numClients > 2 ) {
UI_DrawProportionalString( 510, 480 - 64 - PROP_HEIGHT, postgameMenuInfo.placeNames[2], UI_CENTER, color_white );
}
UI_DrawProportionalString( 130, 480 - 64 - PROP_HEIGHT, postgameMenuInfo.placeNames[1], UI_CENTER, color_white );
UI_DrawProportionalString( 320, 480 - 64 - 2 * PROP_HEIGHT, postgameMenuInfo.placeNames[0], UI_CENTER, color_white );
if( postgameMenuInfo.phase == 1 ) {
timer = uis.realtime - postgameMenuInfo.starttime;
if( timer >= 1000 && postgameMenuInfo.winnerSound ) {
trap_S_StartLocalSound( postgameMenuInfo.winnerSound, CHAN_ANNOUNCER );
postgameMenuInfo.winnerSound = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -