//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include <stdio.h> #include <cdll_client_int.h> #include <cdll_util.h> #include <globalvars_base.h> #include <igameresources.h> #include "clientscoreboarddialog.h" #include <vgui/IScheme.h> #include <vgui/ILocalize.h> #include <vgui/ISurface.h> #include <vgui/IVGui.h> #include <vstdlib/IKeyValuesSystem.h> #include <KeyValues.h> #include <vgui_controls/ImageList.h> #include <vgui_controls/Label.h> #include <vgui_controls/SectionedListPanel.h> #include <cl_dll/iviewport.h> #include <igameresources.h> //#include "voice_status.h" //#include "Friends/IFriendsUser.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" // extern vars //extern IFriendsUser *g_pFriendsUser; using namespace vgui; //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- CClientScoreBoardDialog::CClientScoreBoardDialog(IViewPort *pViewPort) : Frame( NULL, PANEL_SCOREBOARD ) { m_iPlayerIndexSymbol = KeyValuesSystem()->GetSymbolForString("playerIndex"); //memset(s_VoiceImage, 0x0, sizeof( s_VoiceImage )); TrackerImage = 0; m_pViewPort = pViewPort; // initialize dialog SetProportional(true); SetKeyBoardInputEnabled(false); SetMouseInputEnabled(false); SetSizeable(false); // hide the system buttons SetTitleBarVisible( false ); // 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; // update scoreboard instantly if on of these events occure gameeventmanager->AddListener(this, "hltv_status", false ); gameeventmanager->AddListener(this, "server_spawn", false ); } //----------------------------------------------------------------------------- // Purpose: Destructor //----------------------------------------------------------------------------- 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(); } //----------------------------------------------------------------------------- // Purpose: adds all the team sections to the scoreboard //----------------------------------------------------------------------------- void CClientScoreBoardDialog::InitScoreboardSections() { } //----------------------------------------------------------------------------- // Purpose: sets up screen //----------------------------------------------------------------------------- void CClientScoreBoardDialog::ApplySchemeSettings( IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme ); ImageList *imageList = new ImageList(false); // s_VoiceImage[0] = 0; // index 0 is always blank // s_VoiceImage[CVoiceStatus::VOICE_NEVERSPOKEN] = imageList->AddImage(scheme()->GetImage("gfx/vgui/640_speaker1", true)); // s_VoiceImage[CVoiceStatus::VOICE_NOTTALKING] = imageList->AddImage(scheme()->GetImage("gfx/vgui/640_speaker2", true)); // s_VoiceImage[CVoiceStatus::VOICE_TALKING] = imageList->AddImage(scheme()->GetImage( "gfx/vgui/640_speaker3", true)); // s_VoiceImage[CVoiceStatus::VOICE_BANNED] = imageList->AddImage(scheme()->GetImage("gfx/vgui/640_voiceblocked", true)); // TrackerImage = imageList->AddImage(scheme()->GetImage("gfx/vgui/640_scoreboardtracker", true)); // resize the images to our resolution for (int i = 0; i < imageList->GetImageCount(); i++ ) { int wide, tall; imageList->GetImage(i)->GetSize(wide, tall); imageList->GetImage(i)->SetSize(scheme()->GetProportionalScaledValueEx( GetScheme(),wide), scheme()->GetProportionalScaledValueEx( GetScheme(),tall)); } m_pPlayerList->SetImageList(imageList, false); m_pPlayerList->SetVisible( true ); // light up scoreboard a bit SetBgColor( Color( 0,0,0,0) ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CClientScoreBoardDialog::ShowPanel(bool bShow) { if ( BaseClass::IsVisible() == bShow ) return; if ( bShow ) { Reset(); Update(); Activate(); } else { BaseClass::SetVisible( false ); SetMouseInputEnabled( false ); SetKeyBoardInputEnabled( false ); } } void CClientScoreBoardDialog::FireGameEvent( IGameEvent *event ) { const char * type = event->GetName(); if ( Q_strcmp(type, "hltv_status") == 0 ) { // spectators = clients - proxies m_HLTVSpectators = event->GetInt( "clients" ); m_HLTVSpectators -= event->GetInt( "proxies" ); } else if ( Q_strcmp(type, "server_spawn") == 0 ) { // We'll post the message ourselves instead of using SetControlString() // so we don't try to translate the hostname. const char *hostname = event->GetString( "hostname" ); Panel *control = FindChildByName( "ServerName" ); if ( control ) { PostMessage( control, new KeyValues( "SetText", "text", hostname ) ); } control->MoveToFront(); } if( IsVisible() ) Update(); } bool CClientScoreBoardDialog::NeedsUpdate( void ) { return (m_fNextUpdateTime < gpGlobals->curtime); } //----------------------------------------------------------------------------- // Purpose: Recalculate the internal scoreboard data //----------------------------------------------------------------------------- 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 m_fNextUpdateTime = gpGlobals->curtime + 1.0f; } //----------------------------------------------------------------------------- // Purpose: Sort all the teams //----------------------------------------------------------------------------- void CClientScoreBoardDialog::UpdateTeamInfo() { } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CClientScoreBoardDialog::UpdatePlayerInfo() { m_iSectionId = 0; // 0'th row is a header int selectedRow = -1; // walk all the players and make sure they're in the scoreboard for ( int i = 1; i <= gpGlobals->maxClients; ++i ) { IGameResources *gr = GameResources(); if ( gr && gr->IsConnected( i ) ) { // add the player to the list KeyValues *playerData = new KeyValues("data"); GetPlayerScoreInfo( i, playerData ); const char *oldName = playerData->GetString("name",""); int bufsize = strlen(oldName) * 2 + 1; char *newName = (char *)_alloca( bufsize ); UTIL_MakeSafeName( oldName, newName, bufsize ); playerData->SetString("name", newName); int itemID = FindItemIDForPlayerIndex( i ); int sectionID = gr->GetTeam( i ); if ( gr->IsLocalPlayer( i ) ) { selectedRow = itemID; } if (itemID == -1) { // add a new row itemID = m_pPlayerList->AddItem( sectionID, playerData ); } else { // modify the current row m_pPlayerList->ModifyItem( itemID, sectionID, playerData ); } // set the row color based on the players team m_pPlayerList->SetItemFgColor( itemID, gr->GetTeamColor( sectionID ) ); playerData->deleteThis(); } else { // remove the player int itemID = FindItemIDForPlayerIndex( i ); if (itemID != -1) { m_pPlayerList->RemoveItem(itemID); } } } if ( selectedRow != -1 ) { m_pPlayerList->SetSelectedItem(selectedRow); } } //----------------------------------------------------------------------------- // Purpose: adds the top header of the scoreboars //----------------------------------------------------------------------------- void CClientScoreBoardDialog::AddHeader() { // add the top header m_pPlayerList->AddSection(m_iSectionId, ""); m_pPlayerList->SetSectionAlwaysVisible(m_iSectionId); m_pPlayerList->AddColumnToSection(m_iSectionId, "name", "#PlayerName", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),NAME_WIDTH) ); m_pPlayerList->AddColumnToSection(m_iSectionId, "frags", "#PlayerScore", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),SCORE_WIDTH) ); m_pPlayerList->AddColumnToSection(m_iSectionId, "deaths", "#PlayerDeath", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),DEATH_WIDTH) ); m_pPlayerList->AddColumnToSection(m_iSectionId, "ping", "#PlayerPing", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),PING_WIDTH) ); // m_pPlayerList->AddColumnToSection(m_iSectionId, "voice", "#PlayerVoice", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_CENTER, scheme()->GetProportionalScaledValueEx( GetScheme(),VOICE_WIDTH) ); // m_pPlayerList->AddColumnToSection(m_iSectionId, "tracker", "#PlayerTracker", SectionedListPanel::COLUMN_IMAGE, scheme()->GetProportionalScaledValueEx( GetScheme(),FRIENDS_WIDTH) ); } //----------------------------------------------------------------------------- // Purpose: Adds a new section to the scoreboard (i.e the team header) //----------------------------------------------------------------------------- void CClientScoreBoardDialog::AddSection(int teamType, int teamNumber) { if ( teamType == TYPE_TEAM ) { IGameResources *gr = GameResources(); if ( !gr ) return; // setup the team name wchar_t *teamName = localize()->Find( gr->GetTeamName(teamNumber) ); wchar_t name[64]; wchar_t string1[1024]; if (!teamName) { localize()->ConvertANSIToUnicode(gr->GetTeamName(teamNumber), name, sizeof(name)); teamName = name; } localize()->ConstructString( string1, sizeof( string1 ), localize()->Find("#Player"), 2, teamName ); m_pPlayerList->AddSection(m_iSectionId, "", StaticPlayerSortFunc); m_pPlayerList->AddColumnToSection(m_iSectionId, "name", string1, 0, scheme()->GetProportionalScaledValueEx( GetScheme(),NAME_WIDTH) ); m_pPlayerList->AddColumnToSection(m_iSectionId, "frags", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),SCORE_WIDTH) ); m_pPlayerList->AddColumnToSection(m_iSectionId, "deaths", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),DEATH_WIDTH) ); m_pPlayerList->AddColumnToSection(m_iSectionId, "ping", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),PING_WIDTH) ); } else if ( teamType == TYPE_SPECTATORS ) { m_pPlayerList->AddSection(m_iSectionId, ""); m_pPlayerList->AddColumnToSection(m_iSectionId, "name", "#Spectators", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),NAME_WIDTH)); m_pPlayerList->AddColumnToSection(m_iSectionId, "frags", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),SCORE_WIDTH) ); } } //----------------------------------------------------------------------------- // Purpose: Used for sorting players //----------------------------------------------------------------------------- bool CClientScoreBoardDialog::StaticPlayerSortFunc(vgui::SectionedListPanel *list, int itemID1, int itemID2) { KeyValues *it1 = list->GetItemData(itemID1); KeyValues *it2 = list->GetItemData(itemID2); Assert(it1 && it2); // first compare frags int v1 = it1->GetInt("frags"); int v2 = it2->GetInt("frags"); if (v1 > v2) return true; else if (v1 < v2) return false; // next compare deaths v1 = it1->GetInt("deaths"); v2 = it2->GetInt("deaths"); if (v1 > v2) return false; else if (v1 < v2) return true; // 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 *gr = GameResources(); if (!gr ) return false; kv->SetInt("deaths", gr->GetDeaths( playerIndex ) ); kv->SetInt("frags", gr->GetFrags( playerIndex ) ); kv->SetInt("ping", gr->GetPing( playerIndex ) ) ; kv->SetString("name", gr->GetPlayerName( playerIndex ) ); kv->SetInt("playerIndex", playerIndex); // kv->SetInt("voice", s_VoiceImage[GetClientVoice()->GetSpeakerStatus( playerIndex - 1) ]); /* // setup the tracker column if (g_pFriendsUser) { unsigned int trackerID = gEngfuncs.GetTrackerIDForPlayer(row); if (g_pFriendsUser->IsBuddy(trackerID) && trackerID != g_pFriendsUser->GetFriendsID()) { kv->SetInt("tracker",TrackerImage); } } */ 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<Label *>(FindChildByName(textEntryName)); if (entry) { entry->MoveToFront(); } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 5821 | Knut Wikstrom |
Added Valve Source code. This is NOT to be commited to other than new code from Valve. |