diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf/tf_teamstatus.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/tf/tf_teamstatus.cpp')
| -rw-r--r-- | game/client/tf/tf_teamstatus.cpp | 621 |
1 files changed, 621 insertions, 0 deletions
diff --git a/game/client/tf/tf_teamstatus.cpp b/game/client/tf/tf_teamstatus.cpp new file mode 100644 index 0000000..432b579 --- /dev/null +++ b/game/client/tf/tf_teamstatus.cpp @@ -0,0 +1,621 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "iclientmode.h" +#include <vgui_controls/AnimationController.h> +#include <vgui_controls/EditablePanel.h> +#include <vgui_controls/ProgressBar.h> + +#include "tf_gamerules.h" +#include "tf_logic_halloween_2014.h" +#include "c_tf_playerresource.h" +#include "tf_playerpanel.h" +#include "tf_teamstatus.h" +#include "tf_matchmaking_shared.h" +#include "tf_match_description.h" + +using namespace vgui; + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +CTFTeamStatusPlayerPanel::CTFTeamStatusPlayerPanel( vgui::Panel *parent, const char *name ) : CTFPlayerPanel( parent, name ) +{ + m_pHealthBar = new vgui::ContinuousProgressBar( this, "healthbar" ); + m_pOverhealBar = new vgui::ContinuousProgressBar( this, "overhealbar" ); + m_pClassImageBG = new vgui::Panel( this, "classimagebg" ); + m_pDeathFlag = new vgui::ImagePanel( this, "DeathPanel" ); + + m_iTeam = TEAM_UNASSIGNED; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFTeamStatusPlayerPanel::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFTeamStatusPlayerPanel::UpdateBorder( void ) +{ + // do nothing +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CTFTeamStatusPlayerPanel::Update( void ) +{ + if ( !g_TF_PR || !TFGameRules() ) + return false; + + C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); + if ( !pLocalPlayer || ( pLocalPlayer->GetTeamNumber() < FIRST_GAME_TEAM ) ) + return false; + + bool bChanged = false; + bool bVisible = GetTeam() >= FIRST_GAME_TEAM; + int iRespawnWait = -1; + + if ( IsVisible() != bVisible ) + { + SetVisible( bVisible ); + bChanged = true; + } + + if ( bVisible && g_TF_PR ) + { + bool bSameTeamAsLocalPlayer = ( GetTeam() == g_TF_PR->GetTeam( pLocalPlayer->entindex() ) ); + + // are we connected with a class? + Assert( TF_CLASS_UNDEFINED == 0 ); + int iClass = -1; + bool bAlive = false; + int iHealth = -1; + bool bIsLocalPlayer = false; + if ( m_iPlayerIndex > 0 ) + { + bIsLocalPlayer = pLocalPlayer->entindex() == m_iPlayerIndex; + + iClass = g_TF_PR->GetPlayerClass( m_iPlayerIndex ); + + if ( iClass != TF_CLASS_UNDEFINED ) + { + bAlive = g_TF_PR->IsAlive( m_iPlayerIndex ); + } + if ( bAlive ) + { + iHealth = g_TF_PR->GetHealth( m_iPlayerIndex ); + } + + // calc respawn time remaining + if ( !bAlive && ( iClass != TF_CLASS_UNDEFINED ) ) + { + 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 ( !bSameTeamAsLocalPlayer ) + { + iClass = TF_CLASS_UNDEFINED; + } + } + + if ( m_iTeam != GetTeam() ) + { + m_iTeam = GetTeam(); + bChanged = true; + } + + if ( m_pClassImageBG ) + { + if ( m_iTeam == TF_TEAM_RED ) + { + Color bgColor( m_ColorPortraitBGRedLocalPlayer ); + if ( !bIsLocalPlayer ) + { + bgColor = bAlive ? m_ColorPortraitBGRed : m_ColorPortraitBGRedDead; + } + + m_pClassImageBG->SetBgColor( bgColor ); + } + else + { + Color bgColor( m_ColorPortraitBGBlueLocalPlayer ); + if ( !bIsLocalPlayer ) + { + bgColor = bAlive ? m_ColorPortraitBGBlue : m_ColorPortraitBGBlueDead; + } + m_pClassImageBG->SetBgColor( bgColor ); + } + } + + // update live state + if ( m_pClassImage ) + { + if ( m_bPrevAlive != bAlive ) + { + bChanged = true; + m_bPrevAlive = bAlive; + if ( !bAlive ) + { + m_pClassImage->SetDrawColor( ( m_iTeam == TF_TEAM_RED ) ? m_ColorPortraitBlendDeadRed : m_ColorPortraitBlendDeadBlue ); + } + + m_pDeathFlag->SetImage( ( m_iTeam == TF_TEAM_RED ) ? "../HUD/comp_player_status" : "../HUD/comp_player_status_blue" ); + + if ( bAlive ) + { + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "TeamStatus_PlayerAlive", false ); + } + else + { + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "TeamStatus_PlayerDead", false ); + } + } + + // update class image + if ( ( m_iPrevClass != iClass ) || bChanged ) + { + bChanged = true; + m_iPrevClass = iClass; + if ( iClass < 0 ) + { + m_pClassImage->SetImage( "hud_connecting" ); + } + else if ( iClass == TF_CLASS_UNDEFINED ) + { + int iDeadClass = g_TF_PR->GetPlayerClassWhenKilled( m_iPlayerIndex ); + if ( !bAlive && !bSameTeamAsLocalPlayer && ( m_iTeam >= FIRST_GAME_TEAM ) && ( iDeadClass > TF_CLASS_UNDEFINED ) ) + { + m_pClassImage->SetImage( VarArgs( "%s_alpha", ( m_iTeam == TF_TEAM_RED ) ? g_pszItemClassImagesRed[iDeadClass + 9] : g_pszItemClassImagesBlue[iDeadClass + 9] ) ); + } + else + { + m_pClassImage->SetImage( "class_portraits/silhouette_alpha" ); + } + } + else + { + if ( bAlive ) + { + m_pClassImage->SetImage( VarArgs( "%s_alpha", ( m_iTeam == TF_TEAM_RED ) ? g_pszItemClassImagesRed[iClass] : g_pszItemClassImagesBlue[iClass] ) ); + } + else + { + m_pClassImage->SetImage( VarArgs( "%s_alpha", ( m_iTeam == TF_TEAM_RED ) ? g_pszItemClassImagesRed[iClass + 9] : g_pszItemClassImagesBlue[iClass + 9] ) ); + + } + } + } + } + + // update health indicator + if ( m_pHealthBar && m_pOverhealBar ) + { + if ( iHealth != m_iPrevHealth ) + { + m_iPrevHealth = iHealth; + + if ( ( iHealth > 0 ) && bSameTeamAsLocalPlayer ) + { + float flMaxHealth = g_TF_PR->GetMaxHealth( m_iPlayerIndex ); + float flProgress = iHealth / flMaxHealth; + + // health bar + if ( !m_pHealthBar->IsVisible() ) + { + m_pHealthBar->SetVisible( true ); + } + m_pHealthBar->SetProgress( ( flProgress >= 1.0f ) ? 1.0f : flProgress ); + + if ( flProgress > m_flPercentageHealthMed ) + { + m_pHealthBar->SetFgColor( m_ColorBarHealthHigh ); + } + else if ( flProgress > m_flPercentageHealthLow ) + { + m_pHealthBar->SetFgColor( m_ColorBarHealthMed ); + } + else + { + m_pHealthBar->SetFgColor( m_ColorBarHealthLow ); + } + + // overheal bar + if ( flProgress > 1.0f ) + { + if ( !m_pOverhealBar->IsVisible() ) + { + m_pOverhealBar->SetVisible( true ); + } + m_pOverhealBar->SetProgress( flProgress - 1.0f ); + } + else + { + if ( m_pOverhealBar->IsVisible() ) + { + m_pOverhealBar->SetVisible( false ); + } + } + } + else + { + if ( m_pHealthBar->IsVisible() ) + { + m_pHealthBar->SetVisible( false ); + } + + if ( m_pOverhealBar->IsVisible() ) + { + m_pOverhealBar->SetVisible( false ); + } + } + + bChanged = true; + } + } + + // update respawn time + if ( iRespawnWait != m_iPrevRespawnWait ) + { + m_iPrevRespawnWait = iRespawnWait; + if ( ( iRespawnWait < 0 ) || !bSameTeamAsLocalPlayer ) + { + SetDialogVariable( "respawntime", "" ); + } + else + { + SetDialogVariable( "respawntime", VarArgs( "%d", iRespawnWait ) ); + } + + bChanged = true; + } + + // gamerules state + if ( TFGameRules()->State_Get() != m_iPrevState ) + { + m_iPrevState = TFGameRules()->State_Get(); + bChanged = true; + } + } + + return bChanged; +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CTFTeamStatus::CTFTeamStatus( Panel *parent, const char *panelName ) : BaseClass( parent, panelName ) +{ + m_pPlayerPanelKVs = NULL; + m_bReapplyPlayerPanelKVs = false; + + Reset(); + + ivgui()->AddTickSignal( GetVPanel(), 100 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFTeamStatus::~CTFTeamStatus() +{ + if ( m_pPlayerPanelKVs ) + { + m_pPlayerPanelKVs->deleteThis(); + m_pPlayerPanelKVs = NULL; + } +} + +void SetGrowDir( CTFTeamStatus::EGrowDir* pGrowDir, const char* pszString ) +{ + if ( FStrEq( pszString, "east" ) ) + { + (*pGrowDir) = CTFTeamStatus::EGrowDir::GROW_EAST; + } + else if ( FStrEq( pszString, "west" ) ) + { + (*pGrowDir) = CTFTeamStatus::EGrowDir::GROW_WEST; + } + else + { + Assert( !"Invalid direction string for team status team grow direction" ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFTeamStatus::ApplySettings( KeyValues *inResourceData ) +{ + BaseClass::ApplySettings( inResourceData ); + + SetGrowDir( &m_eTeam1GrowDir, inResourceData->GetString( "team1_grow_dir" ) ); + SetGrowDir( &m_eTeam2GrowDir, inResourceData->GetString( "team2_grow_dir" ) ); + + KeyValues *pItemKV = inResourceData->FindKey( "playerpanels_kv" ); + if ( pItemKV ) + { + if ( m_pPlayerPanelKVs ) + { + m_pPlayerPanelKVs->deleteThis(); + } + m_pPlayerPanelKVs = new KeyValues( "playerpanels_kv" ); + pItemKV->CopySubkeys( m_pPlayerPanelKVs ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFTeamStatus::ApplySchemeSettings( IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + m_bReapplyPlayerPanelKVs = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFTeamStatus::PerformLayout( void ) +{ + BaseClass::PerformLayout(); + + int iTeam1Count = 0; + int iTeam2Count = 0; + + // Tally up how many are on each team so we can scale them appropriately down below + for ( int i = 0; i < m_PlayerPanels.Count(); i++ ) + { + if ( m_PlayerPanels[i]->GetTeam() == TF_TEAM_BLUE ) + { + ++iTeam1Count; + } + else if ( m_PlayerPanels[i]->GetTeam() == TF_TEAM_RED ) + { + ++iTeam2Count; + } + } + + C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); + + // Snag local player info + int nLocalPlayerTeam = TF_TEAM_COUNT; + int nLocalPlayerIndex = -1; + if ( pLocalPlayer ) + { + nLocalPlayerIndex = pLocalPlayer->entindex(); + nLocalPlayerTeam = pLocalPlayer->GetTeamNumber(); + } + + int iTeam1Processed = 0; + int iTeam2Processed = 0; + + for ( int i = 0; i < m_PlayerPanels.Count(); i++ ) + { + if ( m_PlayerPanels[i]->GetPlayerIndex() <= 0 ) + { + m_PlayerPanels[i]->SetVisible( false ); + continue; + } + + bool bIsLocalPlayerPanel = nLocalPlayerIndex == m_PlayerPanels[i]->GetPlayerIndex(); + int iTeam = m_PlayerPanels[i]->GetTeam(); + int iXPos = 0; + + // Setup vars + EGrowDir& eGrowDir = iTeam == TF_TEAM_BLUE ? m_eTeam1GrowDir : m_eTeam2GrowDir; + int& iTeamCount = iTeam == TF_TEAM_BLUE ? iTeam1Count : iTeam2Count; + int& iBaseX = iTeam == TF_TEAM_BLUE ? m_iTeam1BaseX : m_iTeam2BaseX; + int& iProcessed = iTeam == TF_TEAM_BLUE ? iTeam1Processed : iTeam2Processed; + int& iMaxExpand = iTeam == TF_TEAM_BLUE ? m_iTeam1MaxExpand : m_iTeam2MaxExpand; + const int iGap = RemapValClamped( iTeamCount, 6, 12, m_i6v6Gap, m_i12v12Gap ); + + // Local player is always the innermost panel + int nTeamPanelIndex = bIsLocalPlayerPanel ? 0 + : iTeam == nLocalPlayerTeam ? iProcessed + 1 + : iProcessed; + + // Setup X-position and widths + // Use the max width if less than 6 (to fill out the space) + int nNewWide = iTeamCount <= 6 ? m_iMaxSize : ( iMaxExpand - ( iGap * ( iTeamCount - 1 ) ) ) / iTeamCount; + + // How far each panel is apart from each other + const int iXStep = iGap + nNewWide; + // How many steps out this panel should be + const int iXOffset = iXStep * nTeamPanelIndex; + // Step out the panels by the step + iXPos = eGrowDir == GROW_EAST ? iBaseX + iXOffset // Align the left edge of the left-most panel on the specified point + : eGrowDir == GROW_WEST ? iBaseX - iXOffset - nNewWide // Align the right edge of the right-most panel on the specified point + : 0; + + // This is expensive, so only do it if we need to + if ( nNewWide != m_PlayerPanels[i]->GetWide() ) + { + // We change the width in the KV's then reapply settings so the children will do their + // magical proportionaltoparent layout. + if ( m_pPlayerPanelKVs ) + { + m_pPlayerPanelKVs->SetInt( "wide", scheme()->GetProportionalNormalizedValueEx( GetScheme(), nNewWide ) ); + m_PlayerPanels[i]->ApplySettings( m_pPlayerPanelKVs ); + m_PlayerPanels[i]->InvalidateLayout( false, true ); + m_PlayerPanels[i]->Update(); + } + } + + if ( !bIsLocalPlayerPanel ) + { + ++iProcessed; + } + + m_PlayerPanels[i]->SetPos( iXPos, m_PlayerPanels[i]->GetYPos() ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFTeamStatus::Reset() +{ + for ( int i = 0; i < m_PlayerPanels.Count(); i++ ) + { + m_PlayerPanels[i]->Reset(); + } + + InvalidateLayout(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CTFTeamStatus::ShouldDraw( void ) +{ + // Get the player and active weapon. + C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer(); + + if ( !pPlayer ) + return false; + + int iLocalTeam = g_TF_PR->GetTeam( pPlayer->entindex() ); + if ( iLocalTeam < FIRST_GAME_TEAM ) + return false; + + if ( TFGameRules() ) + { + const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() ); + if ( !pMatchDesc || !pMatchDesc->m_params.m_bUseMatchHud ) + return false; + + if ( TFGameRules()->ShowMatchSummary() ) + return false; + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFTeamStatus::OnTick() +{ + if ( IsVisible() != ShouldDraw() ) + { + SetVisible( ShouldDraw() ); + } + + if ( IsVisible() ) + { + RecalculatePlayerPanels(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFTeamStatusPlayerPanel *CTFTeamStatus::GetOrAddPanel( int iPanelIndex ) +{ + if ( iPanelIndex < m_PlayerPanels.Count() ) + { + return m_PlayerPanels[iPanelIndex]; + } + Assert( iPanelIndex == m_PlayerPanels.Count() ); + CTFTeamStatusPlayerPanel *pPanel = new CTFTeamStatusPlayerPanel( this, VarArgs( "playerpanel%d", iPanelIndex ) ); + if ( m_pPlayerPanelKVs ) + { + pPanel->ApplySettings( m_pPlayerPanelKVs ); + pPanel->InvalidateLayout( false, true ); + InvalidateLayout(); + } + m_PlayerPanels.AddToTail( pPanel ); + return pPanel; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFTeamStatus::RecalculatePlayerPanels( void ) +{ + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( !pPlayer || !g_TF_PR ) + return; + + int iPanel = 0; + bool bNeedsLayout = false; + int iLocalTeam = g_TF_PR->GetTeam( pPlayer->entindex() ); + if ( iLocalTeam >= FIRST_GAME_TEAM ) + { + for ( int i = 1; i <= MAX_PLAYERS; i++ ) + { + if ( !g_TF_PR->IsConnected( i ) ) + continue; + + int iTeam = g_TF_PR->GetTeam( i ); + if ( iTeam < FIRST_GAME_TEAM ) + continue; + + // Add an entry + CTFTeamStatusPlayerPanel *pPanel = GetOrAddPanel( iPanel ); + + if ( pPanel->GetPlayerIndex() != i ) + { + bNeedsLayout = true; + } + + pPanel->SetPlayerIndex( i ); + + if ( pPanel->GetPreviousTeam() != pPanel->GetTeam() ) + { + bNeedsLayout = true; + } + + ++iPanel; + } + } + + // Clear out any extra panels + for ( int i = iPanel; i < m_PlayerPanels.Count(); i++ ) + { + if ( m_PlayerPanels[i]->GetPlayerIndex() != 0 ) + { + bNeedsLayout = true; + } + + m_PlayerPanels[i]->SetPlayerIndex( 0 ); + } + + UpdatePlayerPanels(); + + if ( bNeedsLayout ) + { + InvalidateLayout(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFTeamStatus::UpdatePlayerPanels( void ) +{ + if ( !g_TF_PR ) + return; + + for ( int i = 0; i < m_PlayerPanels.Count(); i++ ) + { + m_PlayerPanels[i]->Update(); + } +}
\ No newline at end of file |