#include #include #include #include #include #include //#include "voice_status.h"//#include "Friends/IFriendsUser.h"// memdbgon must be the last include file in a .cpp file!!!#include "tier0/memdbgon.h"
24252627282930313233343536373839404142434445
#include #include #include #include #include #include #include "voice_status.h"//#include "Friends/IFriendsUser.h"#include "in_buttons.h"#include "IGameUIFuncs.h" // for key bindingsextern IGameUIFuncs *gameuifuncs; // for key binding details#include "ff_gamerules.h"#include "c_ff_player.h"// memdbgon must be the last include file in a .cpp file!!!#include "tier0/memdbgon.h"
// initialize dialog SetProportional(true); SetKeyBoardInputEnabled(false); SetMouseInputEnabled(false); SetSizeable(false); // hide the system buttons
141142143144145146147148149150
// initialize dialog SetProportional(true); SetKeyBoardInputEnabled(false); SetMouseInputEnabled(true); // We have to enable this in the constructor // even if it won't always be the case // Otherwise panels within this one will not // receive mouse input (thanks valve) SetSizeable(false); // hide the system buttons
636465666768697071727374
// set the scheme before any child control is created SetScheme("ClientScheme"); m_pPlayerList = new SectionedListPanel(this, "PlayerList"); m_pPlayerList->SetVerticalScrollbar(false); LoadControlSettings("Resource/UI/ScoreBoard.res"); m_iDesiredHeight = GetTall(); m_pPlayerList->SetVisible( false ); // hide this until we load the images in applyschemesettings m_HLTVSpectators = 0;
// set the scheme before any child control is created SetScheme("ClientScheme"); m_iJumpKey = -1; m_pMapName = new Label( this, "MapName", GetFormattedMapName() ); m_pPlayerList = new SectionedListPanel(this, "PlayerList"); //m_pPlayerList->SetVerticalScrollbar(false); LoadControlSettings("Resource/UI/ScoreBoard.res"); m_iDesiredHeight = GetTall(); m_pPlayerList->SetVisible( false ); // hide this until we load the images in applyschemesettings m_pPlayerList->AddActionSignalTarget( this ); m_HLTVSpectators = 0;
757677787980
// update scoreboard instantly if on of these events occure gameeventmanager->AddListener(this, "hltv_status", false ); gameeventmanager->AddListener(this, "server_spawn", false );}//-----------------------------------------------------------------------------
170171172173174175176177
// update scoreboard instantly if on of these events occure gameeventmanager->AddListener(this, "hltv_status", false ); gameeventmanager->AddListener(this, "server_spawn", false ); g_pScoreboard = this;}//-----------------------------------------------------------------------------
8384858687888990919293949596979899100
CClientScoreBoardDialog::~CClientScoreBoardDialog(){ gameeventmanager->RemoveListener(this);}//-----------------------------------------------------------------------------// Purpose: clears everything in the scoreboard and all it's state//-----------------------------------------------------------------------------void CClientScoreBoardDialog::Reset(){ // clear m_pPlayerList->DeleteAllItems(); m_pPlayerList->RemoveAllSections(); m_iSectionId = 0; m_fNextUpdateTime = 0; // add all the sections InitScoreboardSections();
CClientScoreBoardDialog::~CClientScoreBoardDialog(){ gameeventmanager->RemoveListener(this); g_pScoreboard = NULL;}// --> Mirv: Catches the set channel button//-----------------------------------------------------------------------------// Purpose: Run the client command if needed//-----------------------------------------------------------------------------void CClientScoreBoardDialog::OnCommand( const char *command ){ DevMsg( "command: %s\n", command ); engine->ClientCmd( command ); // Update straight away Update(); BaseClass::OnCommand(command);}// <-- Mirv: Catches the set channel button//-----------------------------------------------------------------------------// Purpose: clears everything in the scoreboard and all it's state//-----------------------------------------------------------------------------void CClientScoreBoardDialog::Reset( void ){ // clear m_pPlayerList->RemoveAll(); m_pPlayerList->RemoveAllSections(); //m_iSectionId = 0; m_fNextUpdateTime = 0; // add all the sections InitScoreboardSections();
103104105106107108109110
//-----------------------------------------------------------------------------// Purpose: adds all the team sections to the scoreboard//-----------------------------------------------------------------------------void CClientScoreBoardDialog::InitScoreboardSections(){}//-----------------------------------------------------------------------------
218219220221222223224225226227228229230231232
//-----------------------------------------------------------------------------// Purpose: adds all the team sections to the scoreboard//-----------------------------------------------------------------------------void CClientScoreBoardDialog::InitScoreboardSections( void ){ // Do this initially m_hSections[ TEAM_BLUE ].m_iTeam = TEAM_BLUE; m_hSections[ TEAM_RED ].m_iTeam = TEAM_RED; m_hSections[ TEAM_YELLOW ].m_iTeam = TEAM_YELLOW; m_hSections[ TEAM_GREEN ].m_iTeam = TEAM_GREEN; AddHeader();}//-----------------------------------------------------------------------------
if ( BaseClass::IsVisible() == bShow ) return; // Don't let them unshow the scoreboard if (Client_IsIntermission() && !bShow) return; m_pViewPort->ShowBackGround(false); if ( bShow ) { if( m_iJumpKey == -1 ) // you need to lookup the jump key AFTER the engine has loaded { m_iJumpKey = gameuifuncs->GetEngineKeyCodeForBind( "jump" ); } //SetMouseInputEnabled(true); Reset(); Update(); Activate(); SetMouseInputEnabled(false); } else {
//-----------------------------------------------------------------------------void CClientScoreBoardDialog::Update( void ){ // Set the title // Reset(); m_pPlayerList->DeleteAllItems(); FillScoreBoard(); // grow the scoreboard to fit all the players int wide, tall; m_pPlayerList->GetContentSize(wide, tall); wide = GetWide(); if (m_iDesiredHeight < tall) { SetSize(wide, tall); m_pPlayerList->SetSize(wide, tall); } else { SetSize(wide, m_iDesiredHeight); m_pPlayerList->SetSize(wide, m_iDesiredHeight); } MoveToCenterOfScreen(); // update every second
}//-----------------------------------------------------------------------------// Purpose: Used for sorting players//-----------------------------------------------------------------------------bool CClientScoreBoardDialog::StaticPlayerSortFunc_Name( vgui::SectionedListPanel *list, int itemID1, int itemID2 ){ KeyValues *it1 = list->GetItemData( itemID1 ); KeyValues *it2 = list->GetItemData( itemID2 ); Assert( it1 && it2 ); // first compare frags const char *p1 = it1->GetString( "name" ); const char *p2 = it2->GetString( "name" ); if( Q_stricmp( p1, p2 ) < 0 ) return true; else if( Q_stricmp( p1, p2 ) > 0 ) return false; // the same, so compare itemID's (as a sentinel value to get deterministic sorts) return itemID1 < itemID2;}//-----------------------------------------------------------------------------// Purpose: Adds a new row to the scoreboard, from the playerinfo structure//-----------------------------------------------------------------------------bool CClientScoreBoardDialog::GetPlayerScoreInfo( int playerIndex, KeyValues *kv ){ IGameResources *pGR = GameResources(); if( !pGR ) return false; bool bFriendly = false; int iLocalPlayerTeam = TEAM_UNASSIGNED; int iPlayerTeam = TEAM_UNASSIGNED; // Get local player team. This will always be up to date // since the local player is the one viewing the scoreboard // and whose machine this stuff is running on. C_FFPlayer *pLocalPlayer = C_FFPlayer::GetLocalFFPlayer(); if( pLocalPlayer ) iLocalPlayerTeam = pLocalPlayer->GetTeamNumber(); // Check if player is connected. If connected, compare team to see if // friendly or not but use the player resource as it will be up to date // with server information. I think in the past there was a PVS issue // and the client who was viewing the scoreboard might see old (inaccurate) // data and draw stuff the class identifier wrong. Crosshair info needs // to be revisited for this reason too! if( pGR->IsConnected( playerIndex ) ) iPlayerTeam = pGR->GetTeam( playerIndex ); // Check if an ally bFriendly = FFGameRules()->IsTeam1AlliedToTeam2( iLocalPlayerTeam, iPlayerTeam ); kv->SetInt( "deaths", pGR->GetDeaths( playerIndex ) ); kv->SetInt( "fortpoints", pGR->GetFortPoints( playerIndex ) ); kv->SetInt( "score", pGR->GetFrags( playerIndex ) ); kv->SetInt( "ping", pGR->GetPing( playerIndex ) ) ; kv->SetString( "name", pGR->GetPlayerName( playerIndex ) ); if( bFriendly ) kv->SetString( "class", szClassName[ pGR->GetClass( playerIndex ) ] ); // |-- Mirv: Current class else kv->SetString( "class", "" ); kv->SetInt( "playerIndex", playerIndex ); // --> Mirv: Fixed for an extra setting // kv->SetInt( "voice", s_VoiceImage[ GetClientVoiceMgr()->GetSpeakerStatus( playerIndex - 1 ) ] ); if( bFriendly ) { kv->SetInt( "voice", s_VoiceImage[ GetClientVoiceMgr()->GetSpeakerStatus( playerIndex ) ] + ( g_fBlockedStatus[ playerIndex ] ? 1 : 0 ) ); //kv->SetInt( "channel", s_ChannelImage[ pGR->GetChannel( playerIndex ) ] + 1 ); } else { if(g_fBlockedStatus[playerIndex]) kv->SetInt( "voice", s_VoiceImage[ CVoiceStatus::VOICE_BANNEDTEXT ] ); else kv->SetInt( "voice", s_VoiceImage[ CVoiceStatus::VOICE_ALLOWEDTEXT ] ); //kv->SetInt( "channel", 0 ); } // <-- Mirv: Fixed for an extra setting return true;}
//-----------------------------------------------------------------------------// Purpose: reload the player list on the scoreboard//-----------------------------------------------------------------------------void CClientScoreBoardDialog::FillScoreBoard(){ // update totals information UpdateTeamInfo(); // update player info UpdatePlayerInfo();} //-----------------------------------------------------------------------------// Purpose: searches for the player in the scoreboard//-----------------------------------------------------------------------------int CClientScoreBoardDialog::FindItemIDForPlayerIndex(int playerIndex){ for (int i = 0; i <= m_pPlayerList->GetHighestItemID(); i++) { if (m_pPlayerList->IsItemIDValid(i)) { KeyValues *kv = m_pPlayerList->GetItemData(i); kv = kv->FindKey(m_iPlayerIndexSymbol); if (kv && kv->GetInt() == playerIndex) return i; } } return -1;}//-----------------------------------------------------------------------------// Purpose: Sets the text of a control by name//-----------------------------------------------------------------------------void CClientScoreBoardDialog::MoveLabelToFront(const char *textEntryName){ Label *entry = dynamic_cast if (entry) { entry->MoveToFront(); }}
//-----------------------------------------------------------------------------// Purpose: reload the player list on the scoreboard//-----------------------------------------------------------------------------void CClientScoreBoardDialog::FillScoreBoard( void ){ IGameResources *pGR = GameResources(); if( !pGR ) return; bool bNeedToSort = NeedToSortTeams(); // Set up num players, latency, score, and time scored for each team for( int i = TEAM_BLUE; i <= TEAM_GREEN; i++ ) { int iTeam = m_hSections[ i ].m_iTeam; // Get team score m_hSections[ i ].m_iScore = pGR->GetTeamScore( iTeam ); // Get the time the team last scored m_hSections[ i ].m_flLastScored = pGR->GetTeamScoreTime( iTeam ); int iPlayerCount = 0, iLatency = 0; for( int j = 1; j <= gpGlobals->maxClients; j++ ) { if( pGR->IsConnected( j ) ) { // If the player is on iTeam if( pGR->GetTeam( j ) == iTeam ) { iPlayerCount++; iLatency += pGR->GetPing( j ); } } } // Set number of players on this team m_hSections[ i ].m_iNumPlayers = iPlayerCount; // Set the team's latency m_hSections[ i ].m_iLatency = iLatency; } // Do sorting if( bNeedToSort ) { // YES, THIS IS VERY CHEESY! CUtlVector< ScoreboardSection_s > hTemp; // Copy to vector... for( int i = TEAM_BLUE; i <= TEAM_GREEN; i++ ) hTemp.AddToTail( m_hSections[ i ] ); // Sort! hTemp.Sort( ScoreboardSection_Sort ); // Copy back over... for( int i = TEAM_BLUE; i <= TEAM_GREEN; i++ ) m_hSections[ i ] = hTemp[ i - TEAM_BLUE ]; // Have to remove all sections because if you're // viewing the scoreboard when teams get sorted // the team header doesn't change color until // you hide the scoreboard then bring it back up m_pPlayerList->RemoveAll(); m_pPlayerList->RemoveAllSections(); // Re-add all headers and sections AddHeader(); } // Update team headers UpdateHeaders(); // Update player info UpdatePlayerInfo(); } //-----------------------------------------------------------------------------// Purpose: checks to see if we need to sort the teams//-----------------------------------------------------------------------------bool CClientScoreBoardDialog::NeedToSortTeams( void ) const{ bool bSort = false; int iLastScore = m_hSections[ TEAM_BLUE ].m_iScore; float flLastUpdate = m_hSections[ TEAM_BLUE ].m_flLastScored; for( int i = TEAM_RED; ( i <= TEAM_GREEN ) && !bSort; i++ ) { if( iLastScore < m_hSections[ i ].m_iScore ) bSort = true; else if( iLastScore == m_hSections [ i ].m_iScore ) { if( flLastUpdate < m_hSections[ i ].m_flLastScored ) bSort = true; } // Update 'last' iLastScore = m_hSections[ i ].m_iScore; flLastUpdate = m_hSections[ i ].m_flLastScored; } return bSort;}int CClientScoreBoardDialog::FindItemIDForPlayerIndex( int playerIndex ){ for( int i = 0; i <= m_pPlayerList->GetHighestItemID(); i++) { if( m_pPlayerList->IsItemIDValid( i ) ) { KeyValues *kv = m_pPlayerList->GetItemData( i ); kv = kv->FindKey( m_iPlayerIndexSymbol ); if( kv && kv->GetInt() == playerIndex ) return i; } } return -1;}//-----------------------------------------------------------------------------// Purpose: Sets the text of a control by name//-----------------------------------------------------------------------------void CClientScoreBoardDialog::MoveLabelToFront( const char *textEntryName ){ Label *entry = dynamic_cast< Label * >( FindChildByName( textEntryName ) ); if( entry ) { entry->MoveToFront(); }}void CClientScoreBoardDialog::OnKeyCodePressed( KeyCode code ){ int lastPressedEngineKey = engine->GetLastPressedEngineKey( ); if( ( m_iJumpKey != -1 ) && ( m_iJumpKey == lastPressedEngineKey ) ) { SetMouseInputEnabled( true ); } else { BaseClass::OnKeyCodePressed( code ); }}int CClientScoreBoardDialog::FindPlayerIndexForItemID( int iItemID ){ if( m_pPlayerList->IsItemIDValid( iItemID ) ) { KeyValues *kv = m_pPlayerList->GetItemData( iItemID ); kv = kv->FindKey( m_iPlayerIndexSymbol ); if( kv ) return kv->GetInt(); } return -1;}//-----------------------------------------------------------------------------// Purpose: Scroll between different block modes//-----------------------------------------------------------------------------void CClientScoreBoardDialog::OnItemSelected(KeyValues *data){ int iRowId = data->GetInt("itemID"); int playerIndex = FindPlayerIndexForItemID(iRowId); IGameResources *pGR = GameResources(); // Don't change local player info if (pGR && pGR->IsLocalPlayer(playerIndex)) return; // No valid player selected, do nothing! if( playerIndex == -1 ) return; // This line was causing one of the // Assert(i >= 0 && i < GetNumBits()); // bugs! It's fixed now! // If player is not audible, only toggle text block if (!GetClientVoiceMgr()->IsPlayerAudible(playerIndex)) { g_fBlockedStatus[playerIndex] = !g_fBlockedStatus[playerIndex]; return; } // Get some current states bool fVBlock = GetClientVoiceMgr()->GetSpeakerStatus(playerIndex) == CVoiceStatus::VOICE_BANNED; bool fTBlock = g_fBlockedStatus[playerIndex]; // We have everything blocked, so go onto nothing blocked if (fVBlock && fTBlock) { g_fBlockedStatus[playerIndex] = false; GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, false); } // We just have voice blocked, so go onto everything blocked else if (fVBlock) { g_fBlockedStatus[playerIndex] = true; GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, true); } // We have nothing blocked, so just block voice else { g_fBlockedStatus[playerIndex] = false; GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, true); } // Update right away to show voice icon change Update();}void CClientScoreBoardDialog::PaintBackground(){ int iYPos = scheme()->GetProportionalScaledValue(32); surface()->DrawSetColor(GetFgColor()); surface()->DrawFilledRect(0, iYPos, GetWide(), iYPos + 1); //BaseClass::PaintBackground();}