You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
411 lines
10 KiB
411 lines
10 KiB
//========= 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 <spectatorgui.h> |
|
#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 <vgui/ILocalize.h> |
|
#include <vgui/ISurface.h> |
|
#include <VGuiMatSurface/IMatSystemSurface.h> |
|
#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<CTFClassImage*>( 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; |
|
} |
|
|
|
|
|
|