//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include "hud.h" #include "c_team.h" #include "tf_shareddefs.h" #include "tf_gamerules.h" #include "tf_hud_objectivestatus.h" #include "tf_hud_statpanel.h" #include "iclientmode.h" #include "c_playerresource.h" #include "tf_hud_building_status.h" #include "tf_hud_mann_vs_machine_status.h" #include "tf_hud_tournament.h" #include "tf_hud_winpanel.h" #include "tf_tips.h" #include "tf_mapinfomenu.h" #include "econ_wearable.h" #include "c_tf_playerresource.h" #include "playerspawncache.h" #include "econ_notifications.h" #include #include "hudelement.h" #include "tf_spectatorgui.h" #include "tf_hud_playerstatus.h" #include "item_model_panel.h" #include "tf_gamerules.h" #include "tf_playerpanel.h" #include "tf_gc_client.h" #include "tf_lobby_server.h" #include #include #include #include "vgui_avatarimage.h" using namespace vgui; extern ConVar tf_max_health_boost; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CTFPlayerPanel::CTFPlayerPanel( vgui::Panel *parent, const char *name ) : vgui::EditablePanel( parent, name ) { m_pHealthIcon = new CTFPlayerPanelGUIHealth( this, "HealthIcon" ); m_pClassImage = NULL; m_bPlayerReadyModeActive = false; m_pReadyBG = new ScalableImagePanel( this , "ReadyBG" ); m_pReadyImage = new ImagePanel( this, "ReadyImage" ); SetDialogVariable( "chargeamount", "" ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFPlayerPanel::Reset( void ) { m_pHealthIcon->Reset(); m_iPrevHealth = -999; m_iPrevClass = -999; m_bPrevAlive = false; m_iPrevRespawnWait = -999; m_iPrevCharge = -1; m_bPrevReady = true; m_iPrevState = GR_STATE_PREGAME; m_bPlayerReadyModeActive = false; m_nGCTeam = TEAM_INVALID; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CTFPlayerPanel::Update( void ) { if ( !g_TF_PR || !TFGameRules() ) return false; C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); if ( !pLocalPlayer ) return false; bool bChanged = false; bool bObserver = pLocalPlayer->GetObserverMode() != OBS_MODE_NONE; bool bVisible = GetTeam() >= FIRST_GAME_TEAM; int iRespawnWait = -1; m_bPlayerReadyModeActive = ( !bObserver && TFGameRules()->UsePlayerReadyStatusMode() && TFGameRules()->State_Get() == GR_STATE_BETWEEN_RNDS ); CTFGSLobby *pLobby = GTFGCClientSystem()->GetLobby(); if ( pLobby ) { const CTFLobbyMember *pMember = pLobby->GetMemberDetails( m_steamID ); if ( pMember ) { // Keep this updated m_nGCTeam = pMember->team(); if ( !m_iPlayerIndex && pMember->has_last_connect_time() ) { iRespawnWait = CRTime::RTime32DateAdd( pMember->last_connect_time(), 180, k_ETimeUnitSecond ) - CRTime::RTime32TimeCur(); if ( iRespawnWait <= 0 ) iRespawnWait = -1; } } } if ( IsVisible() != bVisible ) { SetVisible( bVisible ); bChanged = true; } if ( bVisible ) { if ( g_TF_PR ) { // Are we connected with a class? Assert( TF_CLASS_UNDEFINED == 0 ); int iClass = -1; bool bAlive = false; const int k_Health_Dead = -1; const int k_Health_NotINGame = -2; int iHealth = k_Health_NotINGame; if ( m_iPlayerIndex > 0 ) { iClass = g_TF_PR->GetPlayerClass( m_iPlayerIndex ); if ( iClass != TF_CLASS_UNDEFINED ) { bAlive = g_TF_PR->IsAlive( m_iPlayerIndex ); iHealth = k_Health_Dead; } if ( bAlive ) iHealth = g_TF_PR->GetHealth( m_iPlayerIndex ); // Calc respawn time remaining if ( iClass != TF_CLASS_UNDEFINED && !bAlive ) { float flRespawnAt = g_TF_PR->GetNextRespawnTime( m_iPlayerIndex ); iRespawnWait = (flRespawnAt - gpGlobals->curtime); if ( iRespawnWait <= 0 ) iRespawnWait = -1; } // Hide class info from the other team? if ( !bObserver && TFGameRules()->IsCompetitiveMode() && GetTeam() != g_TF_PR->GetTeam( pLocalPlayer->entindex() ) ) { iClass = TF_CLASS_UNDEFINED; } } // Update live state if ( m_pClassImage ) { if ( m_bPrevAlive != bAlive ) { bChanged = true; m_bPrevAlive = bAlive; if ( bAlive ) { m_pClassImage->SetDrawColor( Color( 255, 255, 255, 255 ) ); } else { m_pClassImage->SetDrawColor( Color( 96, 96, 96, 255 ) ); } UpdateBorder(); } // Update class image if ( m_iPrevClass != iClass ) { bChanged = true; m_iPrevClass = iClass; if ( iClass < 0 ) { m_pClassImage->SetImage( "hud_connecting" ); } else if ( iClass == TF_CLASS_UNDEFINED ) { m_pClassImage->SetImage( "hud_class_not_chosen" ); } else { m_pClassImage->SetImage( VarArgs( "%s_alpha", ( GetTeam() == TF_TEAM_RED ) ? g_pszItemClassImagesRed[iClass] : g_pszItemClassImagesBlue[iClass] ) ); } } } // update health indicator if ( iHealth != m_iPrevHealth && m_pHealthIcon ) { m_iPrevHealth = iHealth; if ( iHealth == k_Health_NotINGame ) { m_pHealthIcon->SetVisible( false ); } else { m_pHealthIcon->SetVisible( true ); if ( iHealth < 0 ) { Assert( iHealth == k_Health_Dead ); m_pHealthIcon->SetHealth( -1, 1, 1 ); } else { float flMaxHealth = g_TF_PR->GetMaxHealth( m_iPlayerIndex ); float iMaxBuffedHealth = flMaxHealth * tf_max_health_boost.GetFloat(); // Hacky, but it'll work. m_pHealthIcon->SetHealth( iHealth, flMaxHealth, iMaxBuffedHealth ); bChanged = true; } } } // Update respawn time text if ( iRespawnWait != m_iPrevRespawnWait ) { m_iPrevRespawnWait = iRespawnWait; if ( iRespawnWait < 0 ) { SetDialogVariable( "respawntime", "" ); } else { SetDialogVariable( "respawntime", VarArgs( "%d s", iRespawnWait ) ); bChanged = true; } } bool bReadyMode = TFGameRules()->UsePlayerReadyStatusMode(); int iCharge = ( iClass == TF_CLASS_MEDIC ) ? g_TF_PR->GetChargeLevel( m_iPlayerIndex ) : 0; if ( iCharge != m_iPrevCharge ) { if ( iCharge > 0 && !( bReadyMode && !bObserver ) ) { SetDialogVariable( "chargeamount", VarArgs( "%d%%", iCharge ) ); bChanged = true; } else { SetDialogVariable( "chargeamount", "" ); } m_iPrevCharge = iCharge; } if ( bReadyMode ) { bool bPlayerReady = false; if ( m_bPlayerReadyModeActive ) { if ( m_iPlayerIndex && g_TF_PR->IsConnected( m_iPlayerIndex ) ) { bPlayerReady = TFGameRules()->IsPlayerReady( m_iPlayerIndex ); } } if ( m_pReadyImage && ( m_pReadyImage->IsVisible() != bPlayerReady ) ) { m_pReadyImage->SetVisible( bPlayerReady ); } if ( m_pHealthIcon && ( m_pHealthIcon->IsVisible() == m_bPlayerReadyModeActive ) ) { m_pHealthIcon->SetVisible( !m_bPlayerReadyModeActive ); } if ( m_pReadyBG && ( m_pReadyBG->IsVisible() != m_bPlayerReadyModeActive ) ) { m_pReadyBG->SetVisible( m_bPlayerReadyModeActive ); } if ( TFGameRules()->State_Get() != m_iPrevState ) { bChanged = true; } m_iPrevState = TFGameRules()->State_Get(); } } } return bChanged; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFPlayerPanel::ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme ); m_pClassImage = dynamic_cast( FindChildByName( "classimage" ) ); Reset(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFPlayerPanel::SetPlayerIndex( int iIndex ) { if ( iIndex <= 0 ) { Setup( iIndex, CSteamID(), "" ); } else { Setup( iIndex, GetSteamIDForPlayerIndex( iIndex ), g_TF_PR->GetPlayerName( iIndex ) ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFPlayerPanel::Setup( int iPlayerIndex, CSteamID steamID, const char *pszPlayerName, int nLobbyTeam /*= TEAM_INVALID*/ ) { if ( pszPlayerName == NULL ) pszPlayerName = ""; if ( m_iPlayerIndex != iPlayerIndex || m_steamID != steamID || Q_strcmp( m_sPlayerName, pszPlayerName ) ) { Reset(); m_iPlayerIndex = iPlayerIndex; m_steamID = steamID; m_sPlayerName = pszPlayerName; SetDialogVariable( "playername", m_sPlayerName ); m_nGCTeam = nLobbyTeam; } if ( m_iPlayerIndex > 0 || m_steamID.IsValid() ) { UpdateBorder(); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFPlayerPanel::SetSpecIndex( int iIndex ) { m_iSpecIndex = iIndex; if ( m_iSpecIndex > 0 && m_iSpecIndex <= 12 && !m_bPlayerReadyModeActive ) { SetDialogVariable( "specindex", VarArgs( "%d", m_iSpecIndex ) ); } else { SetDialogVariable( "specindex", "" ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFPlayerPanel::UpdateBorder( void ) { if ( !g_TF_PR ) return; vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); if ( !m_bPrevAlive ) { SetBorder( pScheme->GetBorder("TFFatLineBorder") ); } else { if ( GetTeam() == TF_TEAM_RED ) { SetBorder( pScheme->GetBorder( "TFFatLineBorderRedBG" ) ); } else { SetBorder( pScheme->GetBorder( "TFFatLineBorderBlueBG" ) ); } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CTFPlayerPanel::GetTeam( void ) { if ( m_nGCTeam != TEAM_INVALID && TFGameRules() ) { return TFGameRules()->GetGameTeamForGCTeam( (TF_GC_TEAM)m_nGCTeam ); } else if ( GetPlayerIndex() && g_TF_PR ) { return g_TF_PR->GetTeam( GetPlayerIndex() ); } return TEAM_INVALID; }