//---------------------------------------------------------------- // StatWindow.cpp // // Copyright 2002-2005 Raven Software //---------------------------------------------------------------- #include "precompiled.h" #pragma hdrstop #include "../../Game_local.h" #include "StatWindow.h" #include "StatManager.h" /* ================ rvStatWindow::rvStatWindow() ================ */ rvStatWindow::rvStatWindow() { statHud = NULL; } /* ================ rvStatWindow::SetupStatWindow() Sets up a selectable window of current stats ================ */ void rvStatWindow::SetupStatWindow( idUserInterface* hud, bool useSpectator ) { idPlayer* player = gameLocal.GetLocalPlayer(); assert( player ); if ( !player ) { return; } // mekberg: added idList marineScores; idList stroggScores; int selectionIndex = -1; int selectionTeam = -1; statHud = hud; if( gameLocal.IsTeamGame() ) { if( gameLocal.IsFlagGameType() ) { statHud->SetStateInt( "ctf_awards", 1 ); } else { statHud->SetStateInt( "ctf_awards", 0 ); } stroggPlayers.Clear(); marinePlayers.Clear(); for( int i = 0; i < gameLocal.mpGame.GetNumRankedPlayers(); i++ ) { idPlayer* player = gameLocal.mpGame.GetRankedPlayer( i ); if( player->team == TEAM_MARINE ) { marinePlayers.Append( player ); marineScores.Append( gameLocal.mpGame.GetRankedPlayerScore( i ) ); } else if ( player->team == TEAM_STROGG ) { stroggPlayers.Append( player ); stroggScores.Append( gameLocal.mpGame.GetRankedPlayerScore( i ) ); } } for( int i = 0; i < MAX_CLIENTS; i++ ) { if( i < marinePlayers.Num() ) { statHud->SetStateString( va( "team_1_names_item_%d", i ), va( "%s\t%s\t%s\t%d\t", ( player->IsFriend( marinePlayers[ i ] ) ? I_FRIEND_ENABLED : I_FRIEND_DISABLED ), ( player->IsPlayerMuted( marinePlayers[ i ] ) ? I_VOICE_DISABLED : I_VOICE_ENABLED ), marinePlayers[ i ]->GetUserInfo()->GetString( "ui_name"), marineScores[ i ] ) ); if( useSpectator ) { if( marinePlayers[ i ]->entityNumber == player->spectator ) { selectionTeam = TEAM_MARINE; selectionIndex = i; } } else { if( marinePlayers[ i ] == player ) { selectionTeam = TEAM_MARINE; selectionIndex = i; } } } else { statHud->SetStateString( va( "team_1_names_item_%d", i ), "" ); } } for( int i = 0; i < MAX_CLIENTS; i++ ) { if( i < stroggPlayers.Num() ) { statHud->SetStateString( va( "team_2_names_item_%d", i ), va( "%s\t%s\t%s\t%d\t", ( player->IsFriend( stroggPlayers[ i ] ) ? I_FRIEND_ENABLED : I_FRIEND_DISABLED ), ( player->IsPlayerMuted( stroggPlayers[ i ] ) ? I_VOICE_DISABLED : I_VOICE_ENABLED ), stroggPlayers[ i ]->GetUserInfo()->GetString( "ui_name"), stroggScores[ i ] ) ); if( useSpectator ) { if( stroggPlayers[ i ]->entityNumber == player->spectator ) { selectionTeam = TEAM_STROGG; selectionIndex = i; } } else { if( stroggPlayers[ i ] == player ) { selectionTeam = TEAM_STROGG; selectionIndex = i; } } } else { statHud->SetStateString( va( "team_2_names_item_%d", i ), "" ); } } statHud->SetStateInt ( "num_strogg_players", stroggPlayers.Num() ); statHud->SetStateInt ( "num_marine_players", marinePlayers.Num() ); } else { statHud->SetStateInt( "ctf_awards", 0 ); players.Clear(); for( int i = 0; i < gameLocal.mpGame.GetNumRankedPlayers(); i++ ) { players.Append( gameLocal.mpGame.GetRankedPlayer( i ) ); } for( int i = 0; i < MAX_CLIENTS; i++ ) { if( i < players.Num() ) { statHud->SetStateString( va( "dm_names_item_%d", i ), va( "%s\t%s\t%s\t%d\t", ( player->IsFriend( players[ i ] ) ? I_FRIEND_ENABLED : I_FRIEND_DISABLED ), ( player->IsPlayerMuted( players[ i ] ) ? I_VOICE_DISABLED : I_VOICE_ENABLED ), players[ i ]->GetUserInfo()->GetString( "ui_name"), gameLocal.mpGame.GetScore( players[ i ] ) ) ); if( useSpectator ) { if( players[ i ]->entityNumber == player->spectator ) { selectionTeam = 0; selectionIndex = i; } } else { if( players[ i ] == player ) { selectionTeam = 0; selectionIndex = i; } } } else { statHud->SetStateString( va( "dm_names_item_%d", i ), "" ); } } statHud->SetStateInt ( "num_players", players.Num() ); } // spectators spectators.Clear(); for( int i = 0; i < gameLocal.mpGame.GetNumUnrankedPlayers(); i++ ) { spectators.Append( gameLocal.mpGame.GetUnrankedPlayer( i ) ); } for( int i = 0; i < MAX_CLIENTS; i++ ) { if( i < spectators.Num() ) { statHud->SetStateString( va( "spec_names_item_%d", i ), va( "%s\t%s\t%s\t", ( player->IsFriend( spectators[ i ] ) ? I_FRIEND_ENABLED : I_FRIEND_DISABLED ), ( player->IsPlayerMuted( spectators[ i ] ) ? I_VOICE_DISABLED : I_VOICE_ENABLED ), spectators[ i ]->GetUserInfo()->GetString( "ui_name") ) ); if( useSpectator ) { if( spectators[ i ]->entityNumber == player->spectator ) { selectionTeam = TEAM_MAX; selectionIndex = i; } } else { if( spectators[ i ] == player ) { selectionTeam = TEAM_MAX; selectionIndex = i; } } } else { statHud->SetStateString( va( "spec_names_item_%d", i ), "" ); } } statHud->SetStateInt( "gametype", gameLocal.gameType ); statHud->SetStateInt( "playerteam", gameLocal.GetLocalPlayer()->team ); statHud->StateChanged ( gameLocal.time ); statHud->Redraw( gameLocal.time ); // we shouldn't ever draw a hud unless we're in-game assert( selectionIndex >= 0 && selectionTeam >= 0 ); statManager->SelectStatWindow( selectionIndex, selectionTeam ); } /* ================ rvStatWindow::ClearWindow() Clears the stat part of the stat window, but not the player lists boxes ================ */ void rvStatWindow::ClearWindow( void ) { for( int i = 0; i < MAX_WEAPONS; i++ ) { statHud->SetStateString( va( "stat_%d_pct", i ), "" ); } for( int i = 0; i < IGA_NUM_AWARDS; i++ ) { statHud->SetStateString( inGameAwardInfo[ i ].name, "" ); } // end-game awards for( int i = 0; i < EGA_NUM_AWARDS; i++ ) { statHud->SetStateInt( va( "eg_award%d", i ), 0 ); statHud->SetStateString( va( "eg_award%d_text", i ), "" ); } // kills statHud->SetStateString( "stat_frags", "" ); // deaths statHud->SetStateString( "stat_deaths", "" ); // score statHud->SetStateString( "stat_score", "" ); statHud->StateChanged ( gameLocal.time ); statHud->Redraw( gameLocal.time ); } /* ================ rvStatWindow::SelectPlayer() Selects the specified player ================ */ void rvStatWindow::SelectPlayer( int clientNum ) { if( statHud == NULL ) { return; } if( clientNum < 0 || clientNum >= MAX_CLIENTS ) { ClearWindow(); return; } assert( gameLocal.GetLocalPlayer() ); rvPlayerStat* clientStat = statManager->GetPlayerStat( clientNum ); if( gameLocal.isClient && ( clientStat == NULL || ( gameLocal.time - clientStat->lastUpdateTime ) > 5000 ) ) { // get new stats idBitMsg outMsg; byte msgBuf[ 128 ]; outMsg.Init( msgBuf, sizeof( msgBuf ) ); outMsg.WriteByte( GAME_RELIABLE_MESSAGE_STAT ); outMsg.WriteByte( clientNum ); networkSystem->ClientSendReliableMessage( outMsg ); return; } // weapon accuracy for( int i = 0; i < MAX_WEAPONS; i++ ) { int weaponAccuracy = 0; if( clientStat->weaponShots[ i ] != 0 ) { weaponAccuracy = (int)(((float)clientStat->weaponHits[ i ] / (float)clientStat->weaponShots[ i ]) * 100.0f); } statHud->SetStateString( va( "stat_%d_pct", i ), va( "%d%%", weaponAccuracy ) ); } int igAwardCount[ IGA_NUM_AWARDS ]; memset( igAwardCount, 0, sizeof( int ) * IGA_NUM_AWARDS ); for( int i = 0; i < IGA_NUM_AWARDS; i++ ) { igAwardCount[i] = clientStat->inGameAwards[i]; } for( int i = 0; i < IGA_NUM_AWARDS; i++ ) { statHud->SetStateString( inGameAwardInfo[ i ].name, va( "%d", igAwardCount[ i ] ) ); } // end-game awards for( int i = 0; i < EGA_NUM_AWARDS; i++ ) { if( i < clientStat->endGameAwards.Num() ) { statHud->SetStateInt( va( "eg_award%d", i ), 1 ); // RAVEN BEGIN // rhummer: Localized the award strings.. statHud->SetStateString( va( "eg_award%d_text", i ), common->GetLocalizedString( endGameAwardInfo[ clientStat->endGameAwards[ i ] ].name ) ); // RAVEN END } else { statHud->SetStateInt( va( "eg_award%d", i), 0 ); } } // kills statHud->SetStateString( "stat_frags", va( "%d", clientStat->kills ) ); // deaths statHud->SetStateString( "stat_deaths", va( "%d", clientStat->deaths ) ); // score int score = gameLocal.IsTeamGame() ? (gameLocal.mpGame.GetTeamScore( clientNum ) + gameLocal.mpGame.GetScore( clientNum )): gameLocal.mpGame.GetScore( clientNum ); statHud->SetStateString( "stat_score", va( "%d", score ) ); if( gameLocal.GetLocalPlayer()->IsFriend( clientNum ) ) { // remove friend label statHud->SetStateString( "friend_button", common->GetLocalizedString( "#str_200249" ) ); } else { // add friend label statHud->SetStateString( "friend_button", common->GetLocalizedString( "#str_200248" ) ); } if( gameLocal.GetLocalPlayer()->IsPlayerMuted( clientNum ) ) { // unmute label statHud->SetStateString( "mute_button", common->GetLocalizedString( "#str_200251" ) ); } else { // mute label statHud->SetStateString( "mute_button", common->GetLocalizedString( "#str_200250" ) ); } statHud->StateChanged ( gameLocal.time ); statHud->Redraw( gameLocal.time ); } /* ================ rvStatWindow::ClientNumFromSelection() Parses a selection index and team into a clientNum ================ */ int rvStatWindow::ClientNumFromSelection( int selectionIndex, int selectionTeam ) { int clientNum = -1; if( gameLocal.IsTeamGame() ) { if( selectionTeam == TEAM_MARINE ) { if( selectionIndex < 0 || selectionIndex >= marinePlayers.Num() ) { gameLocal.Warning( "rvStatManager::SelectPlayerStats() - invalid selection '%d'\n", selectionIndex ); return -1; } clientNum = marinePlayers[ selectionIndex ]->entityNumber; // explicitly set the gui selection if we called in here not from a GUI statHud->SetStateInt( "team_1_names_sel_0", selectionIndex ); statHud->SetStateString( "dm_names_sel_0", "-1" ); statHud->SetStateString( "spec_names_sel_0", "-1" ); statHud->SetStateString( "team_2_names_sel_0", "-1" ); } else if( selectionTeam == TEAM_STROGG ) { if( selectionIndex < 0 || selectionIndex >= stroggPlayers.Num() ) { gameLocal.Warning( "rvStatManager::SelectPlayerStats() - invalid selection '%d'\n", selectionIndex ); return -1; } clientNum = stroggPlayers[ selectionIndex ]->entityNumber; // explicitly set the gui selection if we called in here not from a GUI statHud->SetStateInt( "team_2_names_sel_0", selectionIndex ); statHud->SetStateString( "dm_names_sel_0", "-1" ); statHud->SetStateString( "spec_names_sel_0", "-1" ); statHud->SetStateString( "team_1_names_sel_0", "-1" ); } else { if( selectionIndex < 0 || selectionIndex >= spectators.Num() ) { gameLocal.Warning( "rvStatManager::SelectPlayerStats() - invalid selection '%d'\n", selectionIndex ); return -1; } clientNum = spectators[ selectionIndex ]->entityNumber; // explicitly set the gui selection if we called in here not from a GUI statHud->SetStateInt( "spec_names_sel_0", selectionIndex ); statHud->SetStateString( "dm_names_sel_0", "-1" ); statHud->SetStateString( "team_1_names_sel_0", "-1" ); statHud->SetStateString( "team_2_names_sel_0", "-1" ); } } else { if( selectionTeam == TEAM_MAX ) { if( selectionIndex < 0 || selectionIndex >= spectators.Num() ) { gameLocal.Warning( "rvStatManager::SelectPlayerStats() - invalid selection '%d'\n", selectionIndex ); return -1; } clientNum = spectators[ selectionIndex ]->entityNumber; // explicitly set the gui selection if we called in here not from a GUI statHud->SetStateInt( "spec_names_sel_0", selectionIndex ); statHud->SetStateString( "dm_names_sel_0", "-1" ); statHud->SetStateString( "team_1_names_sel_0", "-1" ); statHud->SetStateString( "team_2_names_sel_0", "-1" ); } else { if( selectionIndex < 0 || selectionIndex >= players.Num() ) { gameLocal.Warning( "rvStatManager::SelectPlayerStats() - invalid selection '%d'\n", selectionIndex ); return -1; } clientNum = players[ selectionIndex ]->entityNumber; // explicitly set the gui selection if we called in here not from a GUI statHud->SetStateInt( "dm_names_sel_0", selectionIndex ); statHud->SetStateString( "spec_names_sel_0", "-1" ); statHud->SetStateString( "team_1_names_sel_0", "-1" ); statHud->SetStateString( "team_2_names_sel_0", "-1" ); } } return clientNum; } /* ================ rvStatWindow::GetSelectedClientNum() Queries the gui dict to figure out the currently selected selectionIndex/selectionTeam. Uses the selectionIndex/selectionTeam to return the selected client num. ================ */ int rvStatWindow::GetSelectedClientNum( int* selectionIndexOut, int* selectionTeamOut ) { if( statHud == NULL ) { return -1; } int selectionIndex = -1; int selectionTeam = -1; // StatWindow update code should assure that only one selection of all these listDefs is is valid // Find the valid one if( statHud->State().GetInt( "spec_names_sel_0", "-1" ) >= 0 ) { selectionIndex = statHud->State().GetInt( "spec_names_sel_0", "-1" ); selectionTeam = TEAM_MAX; } if ( statHud->State().GetInt( "dm_names_sel_0", "-1" ) >= 0 ) { // if this assert fails, more than one selection is valid assert( selectionIndex == -1 && selectionTeam == -1 ); selectionIndex = statHud->State().GetInt( "dm_names_sel_0", "-1" ); selectionTeam = 0; } if ( statHud->State().GetInt( "team_1_names_sel_0", "-1" ) >= 0 ) { // if this assert fails, more than one selection is valid assert( selectionIndex == -1 && selectionTeam == -1 ); selectionIndex = statHud->State().GetInt( "team_1_names_sel_0", "-1" ); selectionTeam = TEAM_MARINE; } if ( statHud->State().GetInt( "team_2_names_sel_0", "-1" ) >= 0 ) { // if this assert fails, more than one selection is valid assert( selectionIndex == -1 && selectionTeam == -1 ); selectionIndex = statHud->State().GetInt( "team_2_names_sel_0", "-1" ); selectionTeam = TEAM_STROGG; } // return the selection index & team if( selectionIndexOut ) { (*selectionIndexOut) = selectionIndex; } if( selectionTeamOut ) { (*selectionTeamOut) = selectionTeam; } return ClientNumFromSelection( selectionIndex, selectionTeam ); }