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.
621 lines
16 KiB
621 lines
16 KiB
//========= 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(); |
|
} |
|
} |