//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: HUD Target ID element
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "tf_hud_mann_vs_machine_status.h"

#include <vgui_controls/AnimationController.h>
#include "iclientmode.h"
#include "c_tf_objective_resource.h"
#include "tf_gamerules.h"
#include "tf_mann_vs_machine_stats.h"
#include "spectatorgui.h"
#include "engine/IEngineSound.h"
#include "c_tf_mvm_boss_progress_user.h"
#include "hud_macros.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"


using namespace vgui;

extern void AddSubKeyNamed( KeyValues *pKeys, const char *pszName );
extern const ConVar *sv_cheats;
extern ConVar cl_hud_minmode;


#define VICTORY_SPLASH_TIME			1.0f
#define CREDITS_COLLECTED_TIME		2.0f
#define CREDITS_MISSED_TIME			1.0f
#define CREDITS_BONUS_TIME			0.5f
#define RATING_LABEL_TIME			0.5f
#define RATING_SCORE_TIME			0.5f
#define WAIT_TIME					12.0f

// String constants that match variable names in .res files
#define CREDITS_COLLECTED_STR		"creditscollected"
#define CREDITS_MISSED_STR			"creditsmissed"
#define CREDITS_BONUS_STR			"creditbonus"
#define RESPEC_COUNT_STR			"respeccount"
#define RATING_LABEL_STR			"ratinglabel"
#define RATING_SCORE_STR			"ratingscore"


ConVar cl_mvm_wave_status_visible_during_wave( "cl_mvm_wave_status_visible_during_wave", "0", FCVAR_ARCHIVE, "Display full wave contents while a wave is active in MvM." );


//-----------------------------------------------------------------------------
// User Message Callbacks for CTFHudMannVsMachineStatus
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose: Restore Checkpoint status message
//-----------------------------------------------------------------------------
void __MsgFunc_MVMWaveFailed( bf_read &msg )
{
	CTFHudMannVsMachineStatus *pMannVsMachineStatus = GET_HUDELEMENT( CTFHudMannVsMachineStatus );
	if ( pMannVsMachineStatus )
	{
		pMannVsMachineStatus->WaveFailed();
	}
}

//-----------------------------------------------------------------------------
// Purpose: Announce a MVM message on the HUD
//-----------------------------------------------------------------------------
void __MsgFunc_MVMAnnouncement( bf_read &msg )
{
	CTFHudMannVsMachineStatus *pMannVsMachineStatus = GET_HUDELEMENT( CTFHudMannVsMachineStatus );
	if ( pMannVsMachineStatus )
	{
		uint8 nType = msg.ReadByte();
		uint8 nCount = msg.ReadByte();

		switch ( nType )
		{
		case TF_MVM_ANNOUNCEMENT_WAVE_COMPLETE:
			pMannVsMachineStatus->ShowWaveSummary( nCount );
			break;
		default:
			return;
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose: Players have won the MvM Pop File
//-----------------------------------------------------------------------------
void __MsgFunc_MVMVictory( bf_read &msg )
{
	CTFHudMannVsMachineStatus *pMannVsMachineStatus = GET_HUDELEMENT( CTFHudMannVsMachineStatus );
	if ( !pMannVsMachineStatus )
		return;
	
	bool bIsKicking = (bool)msg.ReadByte();
	int nTime = (int)msg.ReadByte();

	pMannVsMachineStatus->MVMVictory( bIsKicking, nTime );
}
//-----------------------------------------------------------------------------
// Update the time to disconnect / kick
//-----------------------------------------------------------------------------
void __MsgFunc_MVMServerKickTimeUpdate( bf_read &msg )
{
	CTFHudMannVsMachineStatus *pMannVsMachineStatus = GET_HUDELEMENT( CTFHudMannVsMachineStatus );
	if ( !pMannVsMachineStatus )
		return;

	int nTime = (int)msg.ReadByte();

	pMannVsMachineStatus->MVMServerKickTimeUpdate( nTime );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CEnemyCountPanel );

CEnemyCountPanel::CEnemyCountPanel( Panel *parent, const char *pName ): vgui::EditablePanel( parent, pName )
{
	m_bFlashing = false;

	ListenForGameEvent( "localplayer_respawn" );

	m_pEnemyCountImage = NULL;
	m_pEnemyCountImageBG = NULL;
	m_pEnemyCountCritBG = NULL;
}

//-----------------------------------------------------------------------------
void CEnemyCountPanel::ApplySchemeSettings( IScheme *pScheme )
{
	BaseClass::ApplySchemeSettings( pScheme );

	// load control settings...
	LoadControlSettings( "resource/UI/EnemyCountPanel.res" );

	// Save refs to images
	m_pEnemyCountImage = dynamic_cast< CTFImagePanel* >( FindChildByName( "EnemyCountImage" ) );
	m_pEnemyCountImageBG = dynamic_cast< Panel* >( FindChildByName( "EnemyCountImageBG" ) );
	m_pEnemyCountCritBG = dynamic_cast< CTFImagePanel* >( FindChildByName( "EnemyCountCritImageBG" ) );
}

//-----------------------------------------------------------------------------
void CEnemyCountPanel::FireGameEvent( IGameEvent * event )
{
	if ( FStrEq( event->GetName(), "localplayer_respawn" ) )
	{
		if ( m_bFlashing )
		{
			// when the player respawns all the animation events
			// are cleared so we need to restart them if necessary
			SetFlashing( true );
		}
	}
}

//-----------------------------------------------------------------------------
void CEnemyCountPanel::SetFlashing( bool bState )
{
	if ( m_bFlashing != bState )
	{
		m_bFlashing = bState;

		if (m_bFlashing)
		{
			g_pClientMode->GetViewportAnimationController()->StartAnimationSequence(this, "SpyWarningFlash");
		}
		else
		{
			g_pClientMode->GetViewportAnimationController()->StartAnimationSequence(this, "SpyWarningFlashEnd");
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CMvMBossProgressBar );

CMvMBossProgressBar::CMvMBossProgressBar( Panel *parent, const char *pName ): vgui::EditablePanel( parent, pName )
{
	m_flPercentage = m_flOldPercentage = 1.0f;
	m_pProgressBar = new ScalableImagePanel( this, "ProgressBar" );
	m_pProgressBarBG = new ScalableImagePanel( this, "ProgressBarBG" );
	m_pBossImage = new CTFImagePanel( this, "TankImage" );

	m_nBarOrgX = m_nBarOrgY = m_nBarOrgW = m_nBarOrgT = 0;
	m_nBgOrgX = m_nBgOrgY = m_nBgOrgW = m_nBgOrgT = 0;

	vgui::ivgui()->AddTickSignal( GetVPanel(), 50 );
}

//-----------------------------------------------------------------------------
void CMvMBossProgressBar::ApplySchemeSettings( IScheme *pScheme )
{
	BaseClass::ApplySchemeSettings( pScheme );

	// load control settings...
	LoadControlSettings( "resource/UI/TankProgressBar.res" );

	if ( m_pProgressBar )
	{
		m_pProgressBar->GetBounds( m_nBarOrgX, m_nBarOrgY, m_nBarOrgW, m_nBarOrgT );
	}

	if ( m_pProgressBarBG )
	{
		m_pProgressBarBG->GetBounds( m_nBgOrgX, m_nBgOrgY, m_nBgOrgW, m_nBgOrgT );
	}
}

//-----------------------------------------------------------------------------
void CMvMBossProgressBar::SetPercentage( float flPercentage )
{ 
	m_flPercentage = flPercentage;
	if ( m_flPercentage < 0.0f )
	{
		m_flPercentage = 0.0f;
	}
	else if ( m_flPercentage > 1.0f )
	{
		m_flPercentage = 1.0f;
	}
}

//-----------------------------------------------------------------------------
void CMvMBossProgressBar::SetImage( const char* pszImageName )
{
	if ( m_pBossImage )
	{
		m_pBossImage->SetImage( pszImageName );
	}
}

//-----------------------------------------------------------------------------
void CMvMBossProgressBar::OnTick( void )
{	
	if ( !TFGameRules() || !TFGameRules()->IsMannVsMachineMode() )
		return;

	if ( m_flOldPercentage != m_flPercentage )
	{
		m_flOldPercentage = m_flPercentage;
				
		if ( m_pProgressBar )
		{
			m_pProgressBar->SetBounds(m_nBarOrgX, m_nBarOrgY, (int)(m_nBarOrgW * m_flPercentage) + m_nWidthSpacer, m_nBarOrgT );
		}

		if ( m_pProgressBarBG )
		{
			m_pProgressBarBG->SetBounds( m_nBgOrgX, m_nBgOrgY, m_nBgOrgW + m_nWidthSpacer, m_nBgOrgT );
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CMvMBossStatusPanel );

CMvMBossStatusPanel::CMvMBossStatusPanel( Panel *parent, const char *pName ): vgui::EditablePanel( parent, pName )
{
	m_pBackground = new ScalableImagePanel( this, "Background" );

	for ( int i = 0; i < MAX_TANK_PROGRESS_BARS; ++i )
	{
		m_ProgressBars.AddToTail();
		m_ProgressBars[ i ] = new CMvMBossProgressBar( this, "TankProgressBar" );
		m_ProgressBars[ i ]->SetVisible( false );
	}	

	m_nBackGroundTall = 0;
	m_bPanelDirty = false;

	vgui::ivgui()->AddTickSignal( GetVPanel(), 100 );
}

//-----------------------------------------------------------------------------
void CMvMBossStatusPanel::ApplySchemeSettings( IScheme *pScheme )
{
	BaseClass::ApplySchemeSettings( pScheme );

	// load control settings...
	LoadControlSettings( "resource/UI/TankStatusPanel.res" );

	if ( m_pBackground )
	{
		m_pBackground->GetBounds( m_nBackgroundOriginalX, m_nBackgroundOriginalY, m_nBackgroundOriginalW, m_nBackgroundOriginalT );
	}

	m_bPanelDirty = true;
}

//-----------------------------------------------------------------------------
void CMvMBossStatusPanel::OnTick( void )
{	
	if ( !TFGameRules() || !TFGameRules()->IsMannVsMachineMode() )
		return;

	CUtlVector< C_TFMvMBossProgressUser* > activeBosses;
	for ( int i = 0; i < ITFMvMBossProgressUserAutoList::AutoList().Count(); ++i )
	{
		C_TFMvMBossProgressUser *pBossProgressUser = static_cast< C_TFMvMBossProgressUser* >( ITFMvMBossProgressUserAutoList::AutoList()[i] );
		if ( pBossProgressUser->GetBossProgressImageName() != NULL )
		{
			C_BaseEntity *pEnt = dynamic_cast< C_BaseEntity* >( pBossProgressUser );
			if ( pEnt && !pEnt->IsDormant() )
			{
				activeBosses.AddToTail( pBossProgressUser );
			}
		}
	}

	// setup the background
	bool bBackgroundVisible = activeBosses.Count() > 0;
	if ( m_pBackground && ( m_pBackground->IsVisible() != bBackgroundVisible ) )
	{
		m_pBackground->SetVisible( bBackgroundVisible );
	}

	int nBackgroundTall = 0;
	int nHeightPerPanel = m_ProgressBars[0]->GetTall(); 
	int nTotalPanelHeight = ( activeBosses.Count() * nHeightPerPanel );// + ( ( nNumBosses - 1 ) * m_nSpaceBetweenPanels );
	if ( m_pBackground && bBackgroundVisible )
	{
		nBackgroundTall =  nTotalPanelHeight + ( m_nSpaceBetweenPanels * 2 );
		if ( ( m_nBackGroundTall != nBackgroundTall ) || m_bPanelDirty )
		{
			m_bPanelDirty = false;
			m_nBackGroundTall = nBackgroundTall;
			m_pBackground->SetBounds( m_nBackgroundOriginalX, m_nBackgroundOriginalY, m_nBackgroundOriginalW, m_nBackGroundTall );
		}
	}
	 
	// setup the tank progress bars
	int iPanelIndex = 0;
	int nYPos = 0;
	if ( nBackgroundTall > 0 )
	{
		nYPos = ( nBackgroundTall * 0.5 ) - ( nTotalPanelHeight * 0.5 );
	}

	for ( int i = 0 ; i < activeBosses.Count() && iPanelIndex < MAX_TANK_PROGRESS_BARS ; i++, iPanelIndex++ )
	{
		m_ProgressBars[ iPanelIndex ]->SetVisible( true );
		m_ProgressBars[ iPanelIndex ]->SetPercentage( activeBosses[i]->GetBossStatusProgress() );
		char szImg[128];
		V_snprintf( szImg, sizeof( szImg ), "../HUD/leaderboard_class_%s", activeBosses[i]->GetBossProgressImageName() );
		m_ProgressBars[ iPanelIndex ]->SetImage( szImg );
		m_ProgressBars[ iPanelIndex ]->SetPos( m_nXOffset, nYPos );

		nYPos += nHeightPerPanel;// + m_nSpaceBetweenPanels;
	}

	// turn off any unused panels
	while ( iPanelIndex < MAX_TANK_PROGRESS_BARS )
	{
		m_ProgressBars[ iPanelIndex ]->SetVisible( false );
		iPanelIndex++;
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CWaveStatusPanel );

CWaveStatusPanel::CWaveStatusPanel( Panel *parent, const char *pName ): vgui::EditablePanel( parent, pName )
{
	m_pSeparatorBar = new vgui::Panel( this, "SeparatorBar" );
	m_pSupportLabel = new CExLabel( this, "SupportLabel", L"" );
	m_pProgressBar = new ScalableImagePanel( this, "ProgressBar" );
	m_pProgressBarBG = new ScalableImagePanel( this, "ProgressBarBG" );
	m_pBackground = new ScalableImagePanel( this, "Background" );

	for ( int i = 0; i < MVM_CLASS_TYPES_PER_WAVE_MAX_NEW; ++i )
	{
		m_EnemyCountPanels.AddToTail();
		m_EnemyCountPanels[ i ] = new CEnemyCountPanel( this, "EnemyCountPanel" );
		m_EnemyCountPanels[ i ]->SetVisible( false );
	}

	m_nBarOrgX = m_nBarOrgY = m_nBarOrgW = m_nBarOrgT = 0;
	m_nBgOrgX = m_nBgOrgY = m_nBgOrgW = m_nBgOrgT = 0;

	m_nWaveCount = -1;
	m_nMaxWaveCount = -1;
	m_nEnemyRemainingNoSupport = 0;
	m_bPanelDirty = false;

	vgui::ivgui()->AddTickSignal( GetVPanel(), 100 );
}

//-----------------------------------------------------------------------------
void CWaveStatusPanel::ApplySchemeSettings( IScheme *pScheme )
{
	BaseClass::ApplySchemeSettings( pScheme );

	KeyValues *pConditions = NULL;

	if ( m_bVerbose )
	{
		pConditions = new KeyValues( "conditions" );
		AddSubKeyNamed( pConditions, "if_verbose" );
	}

	LoadControlSettings( "resource/UI/WaveStatusPanel.res", NULL, NULL, pConditions );

	if ( pConditions )
	{
		pConditions->deleteThis();
	}

	m_bPanelDirty = true;

	if ( m_pProgressBar )
	{
		m_pProgressBar->GetBounds( m_nBarOrgX, m_nBarOrgY, m_nBarOrgW, m_nBarOrgT );
	}

	if ( m_pProgressBarBG )
	{
		m_pProgressBarBG->GetBounds( m_nBgOrgX, m_nBgOrgY, m_nBgOrgW, m_nBgOrgT );
	}
}

//-----------------------------------------------------------------------------
void CWaveStatusPanel::OnTick( void )
{	
	if ( !TFGameRules() || !TFGameRules()->IsMannVsMachineMode() )
		return;

	if ( !TFObjectiveResource() )
		return;

	if ( m_nWaveCount != TFObjectiveResource()->GetMannVsMachineWaveCount() || 
		m_nMaxWaveCount != TFObjectiveResource()->GetMannVsMachineMaxWaveCount() || m_bPanelDirty )
	{
		m_nWaveCount = TFObjectiveResource()->GetMannVsMachineWaveCount();
		m_nMaxWaveCount = TFObjectiveResource()->GetMannVsMachineMaxWaveCount();

		char szbuf[32];
		if ( TFObjectiveResource()->GetMvMEventPopfileType() == MVM_EVENT_POPFILE_HALLOWEEN )
		{
			V_strcpy_safe( szbuf, "666" );
		}
		else if ( m_nMaxWaveCount == 0 )
		{
			V_snprintf( szbuf, sizeof(szbuf), "%d", m_nWaveCount );
		}
		else
		{
			V_snprintf( szbuf, sizeof(szbuf), "%d / %d", m_nWaveCount, m_nMaxWaveCount );
		}

		wchar_t wszFinal[256];
		wchar_t wszCount[32];

		g_pVGuiLocalize->ConvertANSIToUnicode( szbuf, wszCount, sizeof(wszCount) );
		g_pVGuiLocalize->ConstructString_safe( wszFinal, g_pVGuiLocalize->Find( "#TF_PVE_WaveCount" ), 1, wszCount );
		SetDialogVariable( "wave_count", wszFinal );

		m_bPanelDirty = false;
	}

	UpdateEnemyCounts();

	C_BasePlayer *pLocalPlayer = CBasePlayer::GetLocalPlayer();
	if ( pLocalPlayer )
	{
		bool bVisible = m_bVerbose || pLocalPlayer->IsAlive() || ( pLocalPlayer->GetTeamNumber() == TEAM_SPECTATOR ) || ( !m_bVerbose && !pLocalPlayer->IsAlive() );
		
		// turn off if game is over
		bVisible &= TFGameRules()->State_Get() != GR_STATE_GAME_OVER;
		if ( IsVisible() != bVisible )
		{
			SetVisible( bVisible );
		}
	}
}

//-----------------------------------------------------------------------------
void CWaveStatusPanel::AddClassIconBeingUsed( CUtlVector< const char* > &vector, const char *pchIcon ) const
{
	if ( pchIcon && pchIcon[0] && !IsClassIconBeingUsed( vector, pchIcon ) )
	{
		vector.AddToHead( pchIcon );
	}
}

//-----------------------------------------------------------------------------
bool CWaveStatusPanel::IsClassIconBeingUsed( CUtlVector< const char* > &vector, const char *pchIcon ) const
{
	if ( pchIcon && pchIcon[0] )
	{
		for ( int i = 0 ; i < vector.Count() ; i++ )
		{
			if ( FStrEq( vector[i], pchIcon )  )
			{
				return true;
			}
		}
	}

	return false;
}
 
//-----------------------------------------------------------------------------
void CWaveStatusPanel::UpdateEnemyCounts( void )
{
	if ( !TFGameRules() || !TFObjectiveResource() )
		return;

	bool bBetweenWaves = TFGameRules()->InSetup() || TFObjectiveResource()->GetMannVsMachineIsBetweenWaves();
	if ( bBetweenWaves )
	{
		m_nEnemyRemainingNoSupport = 0;
	}

	int nMaxEnemyCountNoSupport = TFObjectiveResource()->GetMannVsMachineWaveEnemyCount();

	// Loop through all the class types to find which enemy counts to display
	CUtlVector< hud_enemy_data_t > miniboss;
	CUtlVector< hud_enemy_data_t > normal;
	CUtlVector< hud_enemy_data_t > support;
	CUtlVector< hud_enemy_data_t > mission;
	int nNumEnemyRemaining = 0;
	int nNumEnemyTypes = 0;
	int nNumNonVerboseTypes = 0;

	for ( int i = 0; i < MVM_CLASS_TYPES_PER_WAVE_MAX_NEW; ++i )
	{
		int nClassCount = TFObjectiveResource()->GetMannVsMachineWaveClassCount( i );
		const char *pchClassIconName = TFObjectiveResource()->GetMannVsMachineWaveClassName( i );
		unsigned int iFlags = TFObjectiveResource()->GetMannVsMachineWaveClassFlags( i );

		if ( pchClassIconName[ 0 ] != '\0' )
		{
			if ( iFlags & MVM_CLASS_FLAG_SUPPORT )
			{
				int index = support.AddToTail();
				support[index].nCount = nClassCount;
				support[index].pchClassIconName = pchClassIconName;
				support[index].iFlags = iFlags;
				support[index].bActive = TFObjectiveResource()->GetMannVsMachineWaveClassActive( i );
				nNumEnemyTypes++;

				// Show support spies
				if ( ( iFlags & MVM_CLASS_FLAG_SUPPORT_LIMITED ) && support[index].bActive )
				{
 					nNumNonVerboseTypes++;
				}
			}
			else if ( iFlags & MVM_CLASS_FLAG_MISSION )
			{
				if ( ( ( TFGameRules()->State_Get() != GR_STATE_RND_RUNNING ) && !( FStrEq( "sentry_buster", pchClassIconName ) || FStrEq( "teleporter", pchClassIconName ) ) ) || ( nClassCount > 0 ) )
				{
					int index = mission.AddToTail();
					mission[index].nCount = nClassCount;
					mission[index].pchClassIconName = pchClassIconName;
					mission[index].iFlags = iFlags;
					mission[index].bActive = TFObjectiveResource()->GetMannVsMachineWaveClassActive( i );
					nNumEnemyTypes++;
					nNumNonVerboseTypes++;
				}
			}
			else if ( iFlags & MVM_CLASS_FLAG_MINIBOSS )
			{
				if ( nClassCount > 0 )
				{
					int index = miniboss.AddToTail();
					miniboss[index].nCount = nClassCount;
					miniboss[index].pchClassIconName = pchClassIconName;
					miniboss[index].iFlags = iFlags;
					miniboss[index].bActive = TFObjectiveResource()->GetMannVsMachineWaveClassActive( i );
					nNumEnemyTypes++;
					nNumEnemyRemaining += nClassCount;
				}
			}
			else if ( iFlags & MVM_CLASS_FLAG_NORMAL )
			{
				// only show classes with > 0 remaining
				if ( nClassCount > 0 )
				{
					int index = normal.AddToTail();
					normal[index].nCount = nClassCount;
					normal[index].pchClassIconName = pchClassIconName;
					normal[index].iFlags = iFlags;
					normal[index].bActive = TFObjectiveResource()->GetMannVsMachineWaveClassActive( i );
					nNumEnemyTypes++;
					nNumEnemyRemaining += nClassCount;

					if ( FStrEq( "spy", pchClassIconName ) )
					{
						nNumNonVerboseTypes++;
					}
				}
			}
		}
	}

	// update the progress bar
	if ( nMaxEnemyCountNoSupport > 0 )
	{
		if ( m_nEnemyRemainingNoSupport != nNumEnemyRemaining )
		{
			m_nEnemyRemainingNoSupport = nNumEnemyRemaining;

			if ( m_pProgressBar )
			{
				float flPercent = (float)m_nEnemyRemainingNoSupport / (float)nMaxEnemyCountNoSupport;
				m_pProgressBar->SetBounds( m_nBarOrgX, m_nBarOrgY, (int)(m_nBarOrgW * flPercent) + m_nWidthSpacer, m_nBarOrgT );
			}
			
			if ( m_pProgressBarBG )
			{
				m_pProgressBarBG->SetBounds( m_nBgOrgX, m_nBgOrgY, m_nBgOrgW + m_nWidthSpacer, m_nBgOrgT );
			}
		}
	}

	int nXPos = 0;
	int nBgX = 0, nBgY = 0, nBgWide = 0, nBgTall = 0;
	int nEnemyCountWide = m_EnemyCountPanels[0]->GetWide();

	CTFPlayer *pLocalPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
	bool bVerbose = ( m_bVerbose || 
		            ( TFGameRules()->State_Get() != GR_STATE_RND_RUNNING ) || 
					( pLocalPlayer && ( pLocalPlayer->GetTeamNumber() == TEAM_SPECTATOR ) ) ||
					  cl_mvm_wave_status_visible_during_wave.GetBool() );
	if ( !bVerbose )
	{
		nNumEnemyTypes = nNumNonVerboseTypes;
	}

	int nSupportLabelRightSide = 0;
	int nBackGroundRightSide = 0;
	int nUpdatedBgWidth = 0;
	int nMinModeReduction = ( cl_hud_minmode.GetBool() ? -YRES(12) : 0 );

	if ( m_pBackground )
	{
		int nNumEnemyWidth = nNumEnemyTypes * nEnemyCountWide;
		int nSpacerWidth = ( nNumEnemyTypes - 1 ) * m_nWaveCountOffset;

		int nSeparatorBarWidth = 0;
		if ( support.Count() > 0 || mission.Count() > 0 )
		{
			nSeparatorBarWidth = m_pSeparatorBar ? m_pSeparatorBar->GetWide() + m_nWaveCountOffset : 0;
		}
		int nTotalEnemyWidth = nNumEnemyWidth + nSpacerWidth + nSeparatorBarWidth;

		m_pBackground->GetBounds( nBgX, nBgY, nBgWide, nBgTall );

		nUpdatedBgWidth = m_nWaveCountBGMinWidth;
		int nNeededBgWidth = nTotalEnemyWidth + ( m_nWaveCountOffset * 3 ); // add little buffer to both ends of the background
		if ( nNeededBgWidth > m_nWaveCountBGMinWidth )
		{
			nUpdatedBgWidth = nNeededBgWidth;
		}

		nBgX = ( GetWide() * 0.5 ) - ( nUpdatedBgWidth * 0.5 );
		
		nBgTall = m_nNormalHeight + nMinModeReduction;

		if ( nNumEnemyTypes > 0 )
		{
			if ( !bVerbose )
			{
				nBgTall = m_nVerboseHeightNoNumbers + nMinModeReduction;
			}
			else
			{
				nBgTall = m_nVerboseHeight + nMinModeReduction;
			}
		}

		SetTall( nBgTall + YRES( 2 ) );

		m_pBackground->SetBounds( nBgX, nBgY, nUpdatedBgWidth, nBgTall );
		nXPos = nBgX + ( nUpdatedBgWidth * 0.5 ) - ( nTotalEnemyWidth * 0.5 );

		nBackGroundRightSide = nBgX	+ nUpdatedBgWidth;
	}

	int iPanelIndex = 0;

	if ( bVerbose )
	{
		// miniboss	enemies
		for ( int i = 0 ; i < miniboss.Count() && iPanelIndex < m_EnemyCountPanels.Count() ; i++, iPanelIndex++ )
		{
			CEnemyCountPanel *pPanel = m_EnemyCountPanels[ iPanelIndex ];

			pPanel->SetVisible( true );
			pPanel->SetDialogVariable( "enemy_count", miniboss[i].nCount );
			pPanel->SetPos( nXPos, m_nWaveCountYPos + nMinModeReduction );
			pPanel->SetFlashing( false );

			if ( pPanel->m_pEnemyCountImage )
			{
				pPanel->m_pEnemyCountImage->SetImage( VarArgs( "../hud/leaderboard_class_%s", miniboss[i].pchClassIconName ) );
				pPanel->m_pEnemyCountImage->SetVisible( true );
			}
			
			if ( pPanel->m_pEnemyCountImageBG  )
			{
				pPanel->m_pEnemyCountImageBG->SetBgColor( m_clrMiniBoss );
			}
			if ( pPanel->m_pEnemyCountCritBG )
			{
				pPanel->m_pEnemyCountCritBG->SetVisible( miniboss[i].iFlags & MVM_CLASS_FLAG_ALWAYSCRIT );
			}

			nXPos += nEnemyCountWide + m_nWaveCountOffset;
		}
	}

	// normal enemies
	for ( int i = 0 ; i < normal.Count() && iPanelIndex < m_EnemyCountPanels.Count() ; i++ )
	{
		bool bNonVerboseSpy = !bVerbose && FStrEq( "spy", normal[i].pchClassIconName );
		if ( bVerbose || bNonVerboseSpy )
		{
			CEnemyCountPanel *pPanel = m_EnemyCountPanels[ iPanelIndex ];

			pPanel->SetVisible( true );
			if ( bNonVerboseSpy )
			{
				pPanel->SetDialogVariable( "enemy_count", "" );
			}
			else
			{
				pPanel->SetDialogVariable( "enemy_count", normal[i].nCount );
			}
			pPanel->SetPos( nXPos, m_nWaveCountYPos + nMinModeReduction );

			if ( pPanel->m_pEnemyCountImage )
			{
				pPanel->m_pEnemyCountImage->SetImage( VarArgs( "../hud/leaderboard_class_%s", normal[i].pchClassIconName ) );
				pPanel->m_pEnemyCountImage->SetVisible( true );
			}

			bool bResetBG = true;

			if ( bNonVerboseSpy )
			{
				if ( pPanel->IsFlashing() )
				{
					// we're already flashing so don't reset the background
					bResetBG = false;
				}
				else
				{
					// start flashing
					pPanel->SetFlashing( true );
				}
			}
			else
			{
				pPanel->SetFlashing( false );
			}

			if ( bResetBG )
			{
				if ( pPanel->m_pEnemyCountImageBG  )
				{
					pPanel->m_pEnemyCountImageBG->SetBgColor( m_clrNormal );
				}
				if ( pPanel->m_pEnemyCountCritBG )
				{
					pPanel->m_pEnemyCountCritBG->SetVisible( normal[i].iFlags & MVM_CLASS_FLAG_ALWAYSCRIT );
				}
			}

			nXPos += nEnemyCountWide + m_nWaveCountOffset;
			iPanelIndex++;
		}
	}

	// bar and label
	if ( bVerbose && ( support.Count() > 0 || mission.Count() > 0 ) )
	{
		if ( m_pSeparatorBar && m_pSupportLabel )
		{
			if ( !m_pSeparatorBar->IsVisible() )
			{
				m_pSeparatorBar->SetVisible( true );
			}

			m_pSeparatorBar->SetPos( nXPos, m_nWaveCountYPos + nMinModeReduction );
			nXPos += m_pSeparatorBar->GetWide() + m_nWaveCountOffset;

			if ( !m_pSupportLabel->IsVisible() )
			{
				m_pSupportLabel->SetVisible( true );
			}

			m_pSupportLabel->SizeToContents();
			m_pSupportLabel->SetPos( nXPos, m_nWaveCountYPos + nMinModeReduction + m_nSupportLabelYOffset );
			nSupportLabelRightSide = nXPos + m_pSupportLabel->GetWide();
		}
	}
	else
	{
		if ( m_pSeparatorBar )
		{
			if ( m_pSeparatorBar->IsVisible() )
			{
				m_pSeparatorBar->SetVisible( false );
			}
		}

		if ( m_pSupportLabel )
		{
			if ( m_pSupportLabel->IsVisible() )
			{
				m_pSupportLabel->SetVisible( false );
			}
		}
	}
	
  	CUtlVector< const char* > classIconsBeingUsed; // used temporarily to track the icons we're showing

	// support
	for ( int i = 0 ; i < support.Count() && iPanelIndex < m_EnemyCountPanels.Count() ; i++ )
	{
		bool bActive = !bVerbose && support[i].bActive && ( support[i].iFlags & MVM_CLASS_FLAG_SUPPORT_LIMITED );
		if ( bVerbose || bActive )
		{
			if ( !IsClassIconBeingUsed( classIconsBeingUsed, support[i].pchClassIconName ) )
			{
				CEnemyCountPanel *pPanel = m_EnemyCountPanels[ iPanelIndex ];

				pPanel->SetVisible( true );
				pPanel->SetDialogVariable( "enemy_count", "" );
				pPanel->SetPos( nXPos, m_nWaveCountYPos + nMinModeReduction );
				pPanel->SetFlashing( false );

				if ( pPanel->m_pEnemyCountImage )
				{
					pPanel->m_pEnemyCountImage->SetImage( VarArgs( "../hud/leaderboard_class_%s", support[i].pchClassIconName ) );
					pPanel->m_pEnemyCountImage->SetVisible( true );
				}

				AddClassIconBeingUsed( classIconsBeingUsed, support[i].pchClassIconName );

				if ( pPanel->m_pEnemyCountImageBG  )
				{
					pPanel->m_pEnemyCountImageBG->SetBgColor( m_clrNormal );
				}

				if ( pPanel->m_pEnemyCountCritBG )
				{
					pPanel->m_pEnemyCountCritBG->SetVisible( support[i].iFlags & MVM_CLASS_FLAG_ALWAYSCRIT );
				}

				nXPos += nEnemyCountWide + m_nWaveCountOffset;
				iPanelIndex++;
			}
		}
	}

	// missions
	for ( int i = 0 ; i < mission.Count() && iPanelIndex < m_EnemyCountPanels.Count() ; i++, iPanelIndex++ )
	{
		if ( !IsClassIconBeingUsed( classIconsBeingUsed, mission[i].pchClassIconName ) )
		{
			CEnemyCountPanel *pPanel = m_EnemyCountPanels[ iPanelIndex ];

			pPanel->SetVisible( true );
			pPanel->SetDialogVariable( "enemy_count", "" );
			pPanel->SetPos( nXPos, m_nWaveCountYPos + nMinModeReduction );

			if ( pPanel->m_pEnemyCountImage )
			{
				const char* pchMissionClassIconName = mission[i].pchClassIconName;
				pPanel->m_pEnemyCountImage->SetImage( VarArgs( "../hud/leaderboard_class_%s", pchMissionClassIconName ) );
				pPanel->m_pEnemyCountImage->SetVisible( true );

				bool bResetBG = true;

				if ( !bBetweenWaves && ( FStrEq( "spy", pchMissionClassIconName ) || FStrEq( "sentry_buster", pchMissionClassIconName ) || FStrEq( "engineer", pchMissionClassIconName ) ) )
				{
					if ( pPanel->IsFlashing() )
					{
						// we're already flashing so don't reset the background
						bResetBG = false;
					}
					else
					{
						// start flashing
						pPanel->SetFlashing( true );
					}
				}
				else
				{
					pPanel->SetFlashing( false );
				}
			
				if ( pPanel->m_pEnemyCountCritBG )
				{
					pPanel->m_pEnemyCountCritBG->SetVisible( mission[i].iFlags & MVM_CLASS_FLAG_ALWAYSCRIT );
				}

				if ( bResetBG )
				{
					if ( pPanel->m_pEnemyCountImageBG )
					{
						pPanel->m_pEnemyCountImageBG->SetBgColor( m_clrNormal );
					}
					if ( pPanel->m_pEnemyCountCritBG )
					{
						pPanel->m_pEnemyCountCritBG->SetVisible( false );
					}
				}
			}
			
			AddClassIconBeingUsed( classIconsBeingUsed, mission[i].pchClassIconName );

			nXPos += nEnemyCountWide + m_nWaveCountOffset;
		}
	}
	
	// final check to make sure the background covers the support label
	if ( nSupportLabelRightSide > nBackGroundRightSide )
	{
		if ( m_pBackground )
		{
			int nDelta = nSupportLabelRightSide - nBackGroundRightSide + ( m_nWaveCountOffset * 1.5 );
			m_pBackground->SetBounds( nBgX - nDelta, nBgY, nUpdatedBgWidth + ( nDelta * 2 ), nBgTall );
		}
	}

	// turn off any unused panels
	while ( iPanelIndex < m_EnemyCountPanels.Count() )
	{
		CEnemyCountPanel *pPanel = m_EnemyCountPanels[ iPanelIndex ];

		pPanel->SetVisible( false );
		pPanel->SetFlashing( false );
		iPanelIndex++;
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CCurrencyStatusPanel );

CCurrencyStatusPanel::CCurrencyStatusPanel( Panel *parent, const char *name ) : vgui::EditablePanel( parent, name )
{
	m_nCurrency = 0;
	m_nTargetCurrency = 0;
	SetDialogVariable( "currency", "" );

	vgui::ivgui()->AddTickSignal( GetVPanel(), 50 );
}

//-----------------------------------------------------------------------------
void CCurrencyStatusPanel::OnTick( void )
{
	BaseClass::OnTick();

	if ( !TFGameRules() || !TFGameRules()->IsMannVsMachineMode() )
		return;

	C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
	if ( !pLocalPlayer || 
		 ( pLocalPlayer->GetTeamNumber() != TF_TEAM_PVE_DEFENDERS ) || 
		 ( pLocalPlayer->GetPlayerClass()->GetClassIndex() == TF_CLASS_UNDEFINED ) )
	{
		if ( IsVisible() )
		{
			SetVisible( false );
		}
		return;
	}

	if ( !IsVisible() )
	{
		SetVisible( true );
	}

	m_nTargetCurrency = pLocalPlayer->GetCurrency();

	if ( UpdateHUD() )
	{
		pLocalPlayer->EmitSound( "Credits.Updated" );
	}
}

//-----------------------------------------------------------------------------
void CCurrencyStatusPanel::ApplySchemeSettings( IScheme *pScheme )
{
	BaseClass::ApplySchemeSettings( pScheme );
	LoadControlSettings( "resource/UI/HudCurrencyAccount.res" );
}

//-----------------------------------------------------------------------------
bool CCurrencyStatusPanel::UpdateHUD( void )
{
	if ( m_nTargetCurrency == m_nCurrency )
	{
		return false;
	}

	int delta = m_nTargetCurrency - m_nCurrency;

	if ( delta > 0 )
	{
		if ( delta > 100 )
		{
			delta = 100;
		}
		else if ( delta > 10 )
		{
			delta = 10;
		}
		else
		{
			delta = 1;
		}
	}
	else
	{
		if ( delta < -100 )
		{
			delta = -100;
		}
		else if ( delta < -10 )
		{
			delta = -10;
		}
		else
		{
			delta = -1;
		}
	}

	m_nCurrency += delta;

	char szTmp[16];
	Q_snprintf( szTmp, ARRAYSIZE( szTmp ), "$%d", m_nCurrency );
	SetDialogVariable( "currency", szTmp );
	
	return true;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CInWorldCurrencyStatus );

CInWorldCurrencyStatus::CInWorldCurrencyStatus( Panel *parent, const char *name ) : vgui::EditablePanel( parent, name )
{
	vgui::ivgui()->AddTickSignal( GetVPanel(), 50 );

	SetDialogVariable( "currency", "" );

	m_pGood = NULL;
	m_pBad = NULL;
}

//-----------------------------------------------------------------------------
void CInWorldCurrencyStatus::ApplySchemeSettings( IScheme *pScheme )
{
	BaseClass::ApplySchemeSettings( pScheme );
	LoadControlSettings( "resource/UI/MvMInWorldCurrency.res" );

	m_pGood = dynamic_cast<vgui::Label*>( FindChildByName( "CurrencyGood" ) );
	m_pBad = dynamic_cast<vgui::Label*>( FindChildByName( "CurrencyBad" ) );
}

//-----------------------------------------------------------------------------
void CInWorldCurrencyStatus::OnTick( void )
{
	if ( !TFGameRules() || !TFGameRules()->IsMannVsMachineMode() )
		return;

	C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
	if ( !pLocalPlayer || pLocalPlayer->GetPlayerClass()->GetClassIndex() == TF_CLASS_UNDEFINED ||
		pLocalPlayer->GetTeamNumber() == TEAM_SPECTATOR )
	{
		if ( IsVisible() )
		{
			SetVisible( false );
		}
		return;
	}

	if ( !IsVisible() )
	{
		SetVisible( true );
	}

	int nWorldMoney = TFObjectiveResource()->GetMvMInWorldMoney();
	int iWaveIndex = TFObjectiveResource()->GetMannVsMachineWaveCount();
	if ( TFObjectiveResource()->GetMannVsMachineIsBetweenWaves() && iWaveIndex > 1 )
	{
		iWaveIndex--;
	}

	if ( m_pGood && m_pBad )
	{
		C_MannVsMachineStats *pStats = MannVsMachineStats_GetInstance();
		int nMissed = pStats ? (int)pStats->GetMissedCredits( iWaveIndex - 1 ) : 0;
		if ( (pStats && nMissed > nWorldMoney) || ( TFObjectiveResource()->GetMannVsMachineIsBetweenWaves() && nWorldMoney == 0 ))
		{
			m_pBad->SetVisible( true );
			m_pGood->SetVisible( false );
		}
		else
		{
			m_pBad->SetVisible( false );
			m_pGood->SetVisible( true );
		}
	}

	char szTmp[16];
	Q_snprintf( szTmp, ARRAYSIZE( szTmp ), "$%d", nWorldMoney );
	SetDialogVariable( "currency", szTmp );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CWarningSwoop );

CWarningSwoop::CWarningSwoop( Panel *parent, const char *name ) : vgui::ImagePanel( parent, name )
{

}

//-----------------------------------------------------------------------------
void CWarningSwoop::PaintBackground( void )
{
	float flElapsedTime = ( gpGlobals->curtime - m_flStartCapAnimStart );

	if ( GetImage() )
	{
		surface()->DrawSetColor( 255, 255, 255, 255 );
		int iYPos = RemapValClamped( flElapsedTime, 0, m_flSwoopTime, 0, GetTall() );
		GetImage()->SetPos( 0, GetTall() - iYPos );
		GetImage()->SetSize( GetWide(), GetTall() );
		GetImage()->Paint();
	}

	if ( flElapsedTime >= m_flSwoopTime )
	{
		SetVisible( false );
	}
}

//-----------------------------------------------------------------------------
bool CWarningSwoop::IsVisible( void )
{
	if ( IsInFreezeCam() == true )
		return false;

	return BaseClass::IsVisible();
}

//-----------------------------------------------------------------------------
void CWarningSwoop::StartSwoop( void )
{
	SetVisible( true );
	m_flStartCapAnimStart = gpGlobals->curtime;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CWaveCompleteSummaryPanel );

CWaveCompleteSummaryPanel::CWaveCompleteSummaryPanel( Panel *parent, const char *pName ): vgui::EditablePanel( parent, pName )
{
	m_eState = FINISHED;

	m_pWaveCompleteContainer = NULL;
	m_pCreditContainerPanel = NULL;
	m_pRatingContainerPanel = NULL;

	m_pCreditBonusTextLabel = NULL;
	m_pCreditBonusCountLabel = NULL;

	m_pRespecBackground = NULL;
	m_pRespecContainerPanel = NULL;
	m_pRespecTextLabel = NULL;
	m_pRespecCountLabel = NULL;
}

//-----------------------------------------------------------------------------
void CWaveCompleteSummaryPanel::ApplySchemeSettings( IScheme *pScheme )
{
	BaseClass::ApplySchemeSettings( pScheme );
	LoadControlSettings( "resource/UI/WaveCompleteSummaryPanel.res" );

	m_pWaveCompleteContainer = dynamic_cast<vgui::EditablePanel*>( FindChildByName("WaveCompleteContainer") );
	m_pCreditContainerPanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName("CreditContainer") );
	m_pRatingContainerPanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName("RatingContainer") );

	if ( m_pCreditContainerPanel )
	{
		m_pCreditBonusTextLabel = dynamic_cast<vgui::Label*>( m_pCreditContainerPanel->FindChildByName("CreditBonusTextLabel") );
		m_pCreditBonusCountLabel = dynamic_cast<vgui::Label*>( m_pCreditContainerPanel->FindChildByName("CreditBonusCountLabel") );
	}
	
	m_pRespecBackground = dynamic_cast<vgui::ScalableImagePanel*>( FindChildByName("RespecBackground") );
	m_pRespecContainerPanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName("RespecContainer") );

	if ( m_pRespecContainerPanel )
	{
		m_pRespecTextLabel = dynamic_cast<vgui::Label*>( m_pRespecContainerPanel->FindChildByName("RespecTextLabelWin") );
		m_pRespecCountLabel = dynamic_cast<vgui::Label*>( m_pRespecContainerPanel->FindChildByName("RespecCountLabel") );
	}
}

//-----------------------------------------------------------------------------
void CWaveCompleteSummaryPanel::ShowWaveSummary( int nWaveNumber )
{
	// if in progress just add time (reset it)
	if ( m_eState != FINISHED ) 
	{
		m_fStateRunningTime = 0;
		return;
	}

	m_nWaveNumber = nWaveNumber;

	if ( m_pWaveCompleteContainer )
	{
		// Set all the values to empty strings
		if ( nWaveNumber == -1 )
		{
			m_pWaveCompleteContainer->SetDialogVariable( "titletext", g_pVGuiLocalize->Find( "#Winpanel_PVE_Evil_Wins" ) );
		}
		else
		{
			m_pWaveCompleteContainer->SetDialogVariable( "titletext", g_pVGuiLocalize->Find( "#TF_PVE_WaveComplete" ) );
		}
	}

	if ( m_pCreditContainerPanel )
	{
		m_pCreditContainerPanel->SetDialogVariable( CREDITS_COLLECTED_STR, "" );
		m_pCreditContainerPanel->SetDialogVariable( CREDITS_MISSED_STR, "" );
		m_pCreditContainerPanel->SetDialogVariable( CREDITS_BONUS_STR, "" );
	}

	if ( m_pRatingContainerPanel )
	{
		m_pRatingContainerPanel->SetDialogVariable( RATING_LABEL_STR, "" );
		m_pRatingContainerPanel->SetDialogVariable( RATING_SCORE_STR, "" );
	}

	if ( m_pRespecContainerPanel )
	{
		m_pRespecContainerPanel->SetDialogVariable( RESPEC_COUNT_STR, "" );
	}

	m_eState = CREDITS_COLLECT;
	m_fStateRunningTime = 0;
	m_fPreviousTick = gpGlobals->curtime;

	int nAcquired = MannVsMachineStats_GetAcquiredCredits( nWaveNumber, false );
	int nDropped = MannVsMachineStats_GetDroppedCredits( nWaveNumber );
	int nPickedUp = MIN( nAcquired, nDropped );

	int nMissed = nDropped - nPickedUp;
	int nBonus = Max( (int)MannVsMachineStats_GetAcquiredCredits( m_nWaveNumber, true ) - nAcquired, 0 );

	m_nCreditsCollected = nPickedUp;
	m_nCreditsMissed = nMissed;
	m_nCreditBonus = nBonus;

	if ( m_pCreditBonusTextLabel )
	{
		m_pCreditBonusTextLabel->SetVisible( false );
	}

	if ( m_pCreditBonusCountLabel )
	{
		m_pCreditBonusCountLabel->SetVisible( false );
	}

	if ( m_pRespecBackground && m_pRespecTextLabel && m_pRespecCountLabel )
	{
		m_pRespecBackground->SetVisible( false );
		m_pRespecTextLabel->SetVisible( false );
		m_pRespecCountLabel->SetVisible( false );
	}

	SetVisible( true );
}

//-----------------------------------------------------------------------------
void CWaveCompleteSummaryPanel::OnTick( void )
{	
	if ( TFGameRules()->State_Get() != GR_STATE_BETWEEN_RNDS && TFGameRules()->State_Get() != GR_STATE_GAME_OVER && TFGameRules()->State_Get() != GR_STATE_TEAM_WIN )
	{
		SetVisible( false );
		return;
	}

	if ( TFObjectiveResource() && TFObjectiveResource()->GetMannVsMachineWaveCount() == 0 )
	{
		SetVisible( false );
		return;
	}

	if ( m_eState == FINISHED )
		return;
	
	m_fStateRunningTime += gpGlobals->curtime - m_fPreviousTick;
	m_fPreviousTick = gpGlobals->curtime;

	CheckCredits();

	// Run through animation loop
	switch ( m_eState )
	{
	case CREDITS_COLLECT:
		StateUpdateValue ( m_pCreditContainerPanel, CREDITS_COLLECTED_STR, CREDITS_COLLECTED_TIME, m_fStateRunningTime, CREDITS_MISSED, m_nCreditsCollected );
		break;
	case CREDITS_MISSED:
		StateUpdateValue ( m_pCreditContainerPanel, CREDITS_MISSED_STR, CREDITS_MISSED_TIME, m_fStateRunningTime, RATING_LABEL, m_nCreditsMissed );
		break;
	case RATING_LABEL:
		RatingLabelUpdate();
		CheckState( RATING_LABEL_TIME, m_fStateRunningTime, RATING_SCORE );
		break;
	case RATING_SCORE:
		RatingScoreUpdate();
		CheckState( RATING_SCORE_TIME, m_fStateRunningTime, WAIT );
		break;
	case WAIT:
		if ( CheckState( WAIT_TIME, m_fStateRunningTime, FINISHED ) )
		{
			SetVisible( false );
		}
		break;
	case FINISHED:
		SetVisible( false );
		break;
	default:
		SetVisible( false );
		break;
	}
}

//-----------------------------------------------------------------------------
// Purpose: updates the target field based on the input args.  Returns TRUE if transitioning to new state
//-----------------------------------------------------------------------------
bool CWaveCompleteSummaryPanel::StateUpdateValue( vgui::EditablePanel *parent, char* field, float targetTime, float currentTime, int nextState, int endValue )
{
	float fPercent = currentTime / targetTime;
	fPercent = 1.0 < fPercent ? 1.0f : fPercent;

	if ( parent )
	{
		parent->SetDialogVariable( field, (int)(endValue * fPercent) );
	}

	// transition to next state
	return CheckState( targetTime, currentTime, nextState );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWaveCompleteSummaryPanel::RatingLabelUpdate( void )
{
	if ( m_pRatingContainerPanel )
	{
		m_pRatingContainerPanel->SetDialogVariable( RATING_LABEL_STR, g_pVGuiLocalize->Find( "#TF_PVE_CreditRating" ) );
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWaveCompleteSummaryPanel::RatingScoreUpdate( )
{
	//calc a score
	const char* pletterScore = "F";

	int nAcquired = MannVsMachineStats_GetAcquiredCredits( m_nWaveNumber, false );
	int nDropped = MannVsMachineStats_GetDroppedCredits( m_nWaveNumber );

	float fPercent = (float)nAcquired / (float)nDropped;

	if ( fPercent >= 1.0 )
	{
		pletterScore = "A+";
	}
	else if ( fPercent >= 0.9 )
	{
		pletterScore = "A";
	}
	else if ( fPercent >= 0.8 )
	{
		pletterScore = "B";
	}
	else if ( fPercent >= 0.7 )
	{
		pletterScore = "C";
	}
	else if ( fPercent >= 0.6 )
	{
		pletterScore = "D";
	}

	if ( m_pRatingContainerPanel )
	{
		m_pRatingContainerPanel->SetDialogVariable( RATING_SCORE_STR, pletterScore );
	}
}
//-----------------------------------------------------------------------------
bool CWaveCompleteSummaryPanel::CheckState( float targetTime, float currentTime, int nextState )
{
	if ( currentTime >= targetTime )
	{
		m_fStateRunningTime = 0;
		m_eState = nextState;
		return true;
	}
	return false;
}
//-----------------------------------------------------------------------------
// Purpose: Check CreditCounts incase they have changed after Summary first showed on screen.
//-----------------------------------------------------------------------------
void CWaveCompleteSummaryPanel::CheckCredits() 
{
	int nAcquired = MannVsMachineStats_GetAcquiredCredits( m_nWaveNumber, false );
	int nDropped = MannVsMachineStats_GetDroppedCredits( m_nWaveNumber );
	int nPickedUp = Min( nAcquired, nDropped );
	int nMissed = nDropped - nPickedUp;
	int nBonus = Max( (int)MannVsMachineStats_GetAcquiredCredits( m_nWaveNumber, true ) - nAcquired, 0 );

	if ( m_eState > CREDITS_COLLECT )
	{
		if ( m_nCreditsCollected != nPickedUp )
		{
			if ( m_pCreditContainerPanel )
			{
				m_pCreditContainerPanel->SetDialogVariable( CREDITS_COLLECTED_STR, nPickedUp );
			}
			m_nCreditsCollected = nPickedUp;
		}
	}

	if ( m_eState > CREDITS_MISSED )
	{
		if ( m_nCreditsMissed != nMissed)
		{
			if ( m_pCreditContainerPanel )
			{
				m_pCreditContainerPanel->SetDialogVariable( CREDITS_MISSED_STR, nMissed );
			}
			m_nCreditsMissed = nMissed;
		}

		if ( m_nCreditBonus != nBonus )
		{
			if ( m_pCreditContainerPanel )
			{
				m_pCreditContainerPanel->SetDialogVariable( CREDITS_BONUS_STR, nBonus );
			}
			m_nCreditBonus = nBonus;
		}

		if ( m_nCreditBonus > 0 )
		{
			if ( m_pCreditBonusCountLabel )
			{
				m_pCreditBonusCountLabel->SetVisible( true );
			}

			if ( m_pCreditBonusTextLabel )
			{
				m_pCreditBonusTextLabel->SetVisible( true );
			}
		}
	}

	// Respec
	if ( TFGameRules()->IsMannVsMachineRespecEnabled() )
	{
		CMannVsMachineStats *pStats = MannVsMachineStats_GetInstance();
		if ( pStats )
		{
			uint16 nRespecs = pStats->GetNumRespecsEarnedInWave();
			bool bVisible = nRespecs > 0;
			if ( bVisible )
			{
				if ( m_pRespecContainerPanel )
				{
					m_pRespecContainerPanel->SetDialogVariable( RESPEC_COUNT_STR, nRespecs );
				}

				if ( m_pRespecBackground && m_pRespecCountLabel && m_pRespecTextLabel )
				{
					if ( !m_pRespecBackground->IsVisible() && !m_pRespecCountLabel->IsVisible() && !m_pRespecTextLabel->IsVisible() )
					{
						C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer();
						if ( pLocalTFPlayer )
						{
							pLocalTFPlayer->EmitSound( "MVM.RespecAwarded" );
						}
						g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "RespecEarnedPulse" );
					}

					if ( m_pRespecBackground->IsVisible() != bVisible )
					{
						m_pRespecBackground->SetVisible( bVisible );
					}
					if ( m_pRespecCountLabel->IsVisible() != bVisible )
					{
						m_pRespecCountLabel->SetVisible( bVisible );
					}
					if ( m_pRespecTextLabel->IsVisible() != bVisible )
					{
						m_pRespecTextLabel->SetVisible( bVisible );
					}					
				}
			}
		}
	}

	if ( m_eState > RATING_SCORE )
	{
		RatingLabelUpdate();
		RatingScoreUpdate();
	}
}


//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CVictorySplash );

CVictorySplash::CVictorySplash( Panel *parent, const char *pName ): vgui::EditablePanel( parent, pName )
{
	
}

//-----------------------------------------------------------------------------
void CVictorySplash::ApplySchemeSettings( IScheme *pScheme )
{
	BaseClass::ApplySchemeSettings( pScheme );
	LoadControlSettings( "resource/UI/MvMVictorySplash.res" );
}

//-----------------------------------------------------------------------------
void CVictorySplash::OnTick( void )
{
	
}

//-----------------------------------------------------------------------------
// CMvMBombCarrierProgress
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CMvMBombCarrierProgress );

CMvMBombCarrierProgress::CMvMBombCarrierProgress( Panel *parent, const char *pName ): vgui::EditablePanel( parent, pName )
{

}

//-----------------------------------------------------------------------------
void CMvMBombCarrierProgress::ApplySchemeSettings( IScheme *pScheme )
{
	BaseClass::ApplySchemeSettings( pScheme );
	LoadControlSettings( "resource/UI/MvMBombCarrierProgressPanel.res" );
}

//-----------------------------------------------------------------------------
// CTFHudMannVsMachineStatus 
//-----------------------------------------------------------------------------
DECLARE_HUDELEMENT( CTFHudMannVsMachineStatus );

CTFHudMannVsMachineStatus::CTFHudMannVsMachineStatus( const char *pElementName ) :
CHudElement( pElementName ), BaseClass( NULL, "HudMannVsMachineStatus" )
{
	Panel *pParent = g_pClientMode->GetViewport();
	SetParent( pParent );

	SetHiddenBits( HIDEHUD_MISCSTATUS );

	m_pWarningSwoop = new CWarningSwoop( this, "WarningSwoop" );
	m_pWaveStatusPanel = new CWaveStatusPanel( this, "WaveStatusPanel" );
	m_pWaveCompletePanel = new CWaveCompleteSummaryPanel( this, "WaveCompleteSummaryPanel" );

	m_pVictorySplash = new CVictorySplash( this, "VictorySplash" );
	m_pVictoryContainer = new CMvMVictoryPanelContainer( this, "VictoryPanelContainer" );
	
	m_pWaveLossPanel = new CMvMWaveLossPanel ( this, "WaveLossPanel" );

	m_nFlagCarrierUpgradeLevel = -1;
	m_pUpgradeLevelContainer = new vgui::EditablePanel( this, "UpgradeLevelContainer" );
	m_pUpgradeLevel1 = new vgui::ImagePanel( m_pUpgradeLevelContainer, "UpgradeLevel1" );
	m_pUpgradeLevel2 = new vgui::ImagePanel( m_pUpgradeLevelContainer, "UpgradeLevel2" );
	m_pUpgradeLevel3 = new vgui::ImagePanel( m_pUpgradeLevelContainer, "UpgradeLevel3" );
	m_pUpgradeLevelBoss = new vgui::ImagePanel( m_pUpgradeLevelContainer, "UpgradeLevelBoss" );

	m_nNextWaveTime = 0;
	m_nSpyMissionCount = 0;

 	m_bSpecPanelVisible = false;

	m_bInVictorySplash = false;

	m_bAdjustWaveStatusPanel = false;

	ListenForGameEvent( "mvm_mission_update" );
	ListenForGameEvent( "localplayer_changeteam" );
	ListenForGameEvent( "mvm_begin_wave" );

	vgui::ivgui()->AddTickSignal( GetVPanel(), 100 );

	HOOK_MESSAGE( MVMWaveFailed );
	HOOK_MESSAGE( MVMAnnouncement );
	HOOK_MESSAGE( MVMVictory );
	HOOK_MESSAGE( MVMServerKickTimeUpdate );
}

//-----------------------------------------------------------------------------
void CTFHudMannVsMachineStatus::ApplySchemeSettings( IScheme *pScheme )
{
	BaseClass::ApplySchemeSettings( pScheme );

	// load control settings...
	LoadControlSettings( "resource/UI/HudMannVsMachineStatus.res" );

	m_bSpecPanelVisible = false;

	m_pWaveCompletePanel->SetVisible( false );

	CMvMBombCarrierProgress *parent = dynamic_cast<CMvMBombCarrierProgress*>( m_pUpgradeLevelContainer->FindChildByName( "UpgradeProgressTrack" ) );
	if ( parent )
	{
		parent->ApplySchemeSettings( pScheme );
		m_pBombUpgradeMeterMask = dynamic_cast<vgui::EditablePanel*>( parent->FindChildByName( "FillContainer" ) );
		m_nUpgradeMaskBaseWidth = scheme()->GetProportionalScaledValueEx( GetScheme(), 20 );
		m_nUpgradeMaskMaxWidth = scheme()->GetProportionalScaledValueEx( GetScheme(), 60 );
	}

	m_pServerChangeMessage = dynamic_cast<vgui::EditablePanel*>( FindChildByName( "ServerChangeMessage" ) );
}

//-----------------------------------------------------------------------------
void CTFHudMannVsMachineStatus::FireGameEvent( IGameEvent * event )
{
	if ( !ShouldDraw() )
		return;

	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();

	const char *type = event->GetName();

	if ( Q_strcmp( type, "mvm_mission_update" ) == 0 )
	{
		int nClass = event->GetInt( "class", 0 );
		if ( nClass == TF_CLASS_SPY )
		{
			int nCount = event->GetInt( "count", 0 );

			if ( nCount > 0 )
			{
				if ( m_nSpyMissionCount == 0 )
				{
					if ( pPlayer )
					{
						pPlayer->EmitSound( "Announcer.MVM_Spy_Alert" );
					}

					if ( m_pWarningSwoop )
					{
						m_pWarningSwoop->StartSwoop();
					}
				}
// 				else if ( m_nSpyMissionCount > nCount )
// 				{
// 					if ( pPlayer )
// 					{
// 						switch ( nCount )
// 						{
// 						case 6: 
// 							pPlayer->EmitSound( "Announcer.mvm_spybot_death_six" );
// 							break;
// 						case 5:
// 							pPlayer->EmitSound( "Announcer.mvm_spybot_death_five" );
// 							break;
// 						case 4:
// 							pPlayer->EmitSound( "Announcer.mvm_spybot_death_four" );
// 							break;
// 						case 3:
// 							pPlayer->EmitSound( "Announcer.mvm_spybot_death_three" );
// 							break;
// 						case 2:
// 							pPlayer->EmitSound( "Announcer.mvm_spybot_death_two" );
// 							break;
// 						case 1:
// 							pPlayer->EmitSound( "Announcer.mvm_spybot_death_one" );
// 							break;
// 						}
// 					}
// 				}

				m_nSpyMissionCount = nCount;
			}
			else
			{
				if ( m_nSpyMissionCount != 0 )
				{
					m_nSpyMissionCount = 0;

					if ( pPlayer )
					{
						pPlayer->EmitSound( "Announcer.mvm_spybot_death_all" );
					}
				}
			}
		}
	}
	else if ( Q_strcmp( type, "localplayer_changeteam" ) == 0 )
	{
		m_bAdjustWaveStatusPanel = true;
	}
	else if ( Q_strcmp( type, "mvm_begin_wave" ) == 0 )
	{
		m_nSpyMissionCount = 0;
	}
}

//-----------------------------------------------------------------------------
bool CTFHudMannVsMachineStatus::ShouldDraw( void )
{
	// Don't draw in freezecam
	C_TFPlayer *pPlayer = CTFPlayer::GetLocalTFPlayer();
	if ( !pPlayer || pPlayer->GetObserverMode() == OBS_MODE_FREEZECAM || !TFGameRules()->IsMannVsMachineMode() )
	{
		return false;
	}

	return CHudElement::ShouldDraw();
}

//-----------------------------------------------------------------------------
void CTFHudMannVsMachineStatus::OnTick( void )
{	
	if ( !TFGameRules() || !TFGameRules()->IsMannVsMachineMode() )
		return;

	if ( m_pVictoryContainer->IsVisible() )
	{
		m_pVictoryContainer->OnTick();
	}

	if ( !IsVisible() || !TFObjectiveResource() )
		return;

	m_pWaveCompletePanel->OnTick();
	
	m_pWaveLossPanel->OnTick();
	
	if ( g_pSpectatorGUI && m_pWaveStatusPanel )
	{
		if ( ( m_bSpecPanelVisible != g_pSpectatorGUI->IsVisible() ) || m_bAdjustWaveStatusPanel )
		{
			int xPos, yPos;
			m_pWaveStatusPanel->GetPos( xPos, yPos );

			m_bSpecPanelVisible = g_pSpectatorGUI->IsVisible();

			if ( m_bSpecPanelVisible )
			{
				m_pWaveStatusPanel->SetPos( xPos, g_pSpectatorGUI->GetTopBarHeight() );
			}
			else
			{
				m_pWaveStatusPanel->SetPos( xPos, 0 );
			}

			m_bAdjustWaveStatusPanel = false;
		}
	}

	int nTime = 0;

	if ( TFObjectiveResource()->GetMannVsMachineNextWaveTime() > 0.0f )
	{
		nTime = TFObjectiveResource()->GetMannVsMachineNextWaveTime() - gpGlobals->curtime;
	}

	if ( TFGameRules()->InSetup() && ObjectiveResource() && !TFGameRules()->IsInTournamentMode() )
	{
		CTeamRoundTimer *pTimer = dynamic_cast< CTeamRoundTimer* >( ClientEntityList().GetEnt( ObjectiveResource()->GetTimerToShowInHUD() ) );
		if ( pTimer )
		{
			nTime = pTimer->GetTimeRemaining();
		}
	}

	if ( nTime < 0 )
	{
		nTime = 0;
	}

	if ( TFGameRules()->State_Get() > GR_STATE_PREGAME )
	{
		if ( m_nNextWaveTime != nTime )
		{
			m_nNextWaveTime = nTime;

			// announcer countdown
			C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
			if ( pPlayer )
			{
				switch( nTime )
				{
				case 10:
					if ( TFObjectiveResource()->GetMannVsMachineWaveCount() + 1 >= TFObjectiveResource()->GetMannVsMachineMaxWaveCount() )
					{
						pPlayer->EmitSound( "Announcer.MVM_Final_Wave_Start" );
					}
					else if ( TFObjectiveResource()->GetMannVsMachineWaveCount() == 0 )
					{
						pPlayer->EmitSound( "Announcer.MVM_First_Wave_Start" );
					}
					else
					{
						pPlayer->EmitSound( "Announcer.MVM_Wave_Start" );
					}
					break;
				case 5:		pPlayer->EmitSound( "Announcer.RoundBegins5Seconds" );	break;
				case 4:		pPlayer->EmitSound( "Announcer.RoundBegins4Seconds" );	break;
				case 3:		pPlayer->EmitSound( "Announcer.RoundBegins3Seconds" );	break;
				case 2:		pPlayer->EmitSound( "Announcer.RoundBegins2Seconds" );	break;
				case 1:		pPlayer->EmitSound( "Announcer.RoundBegins1Seconds" );	break;
				}
			}
		}
	}

	// Bomb Carrier Indictators
	UpdateBombCarrierProgress();

	if ( m_bInVictorySplash && gpGlobals->curtime > m_flVictoryTimer )
	{
		m_bInVictorySplash = false;
		m_pVictorySplash->SetVisible( false );
		m_pVictoryContainer->ShowVictoryPanel( false );
	}

	m_pVictorySplash->SetVisible( m_bInVictorySplash && TFGameRules()->State_Get() == GR_STATE_GAME_OVER );

	// Check to see if we need to display server message
	if ( TFGameRules()->State_Get() == GR_STATE_GAME_OVER && !m_bInVictorySplash)
	{
		//calculate seconds
		m_pServerChangeMessage->SetVisible( true );
		int seconds = MAX(0, (int)(m_flServerEndTime - gpGlobals->curtime) );
		wchar_t wszTime[16];
		_snwprintf( wszTime, ARRAYSIZE( wszTime ), L"%d", seconds );
		wchar_t wszLocalizedMessage[512];

		if ( !m_bIsServerKicking )
		{
			if ( seconds > 1 )
			{
				g_pVGuiLocalize->ConstructString_safe( wszLocalizedMessage, g_pVGuiLocalize->Find( "#TF_PVE_Server_Message_Reset" ), 1, wszTime );
			}
			else
			{
				g_pVGuiLocalize->ConstructString_safe( wszLocalizedMessage, g_pVGuiLocalize->Find( "#TF_PVE_Server_Message_ResetNoS" ), 1, wszTime );
			}
			m_pServerChangeMessage->SetDialogVariable( "servermessage", wszLocalizedMessage);
		}
		else
		{
			if ( seconds > 1 )
			{
				g_pVGuiLocalize->ConstructString_safe( wszLocalizedMessage, g_pVGuiLocalize->Find( "#TF_PVE_Server_Message_Kick" ), 1, wszTime );
			}
			else
			{
				g_pVGuiLocalize->ConstructString_safe( wszLocalizedMessage, g_pVGuiLocalize->Find( "#TF_PVE_Server_Message_KickNoS" ), 1, wszTime );
			}
			m_pServerChangeMessage->SetDialogVariable( "servermessage", wszLocalizedMessage);
		}
	}
	else
	{
		m_pServerChangeMessage->SetVisible( false );
	}
	
}

//-----------------------------------------------------------------------------
void CTFHudMannVsMachineStatus::WaveFailed( void )
{
	if ( TFObjectiveResource() && TFObjectiveResource()->GetMannVsMachineWaveCount() > 1 )
	{
		m_pWaveLossPanel->ShowPanel();
	}
}

//-----------------------------------------------------------------------------
void CTFHudMannVsMachineStatus::ShowWaveSummary( int nWaveNumber) 
{
	m_pWaveCompletePanel->ShowWaveSummary( nWaveNumber );
}
//-----------------------------------------------------------------------------
void CTFHudMannVsMachineStatus::MVMVictory( bool bIsKicking, int nTime )
{
	m_bInVictorySplash = true;
	m_flVictoryTimer = gpGlobals->curtime + VICTORY_SPLASH_TIME;
	m_pVictorySplash->SetVisible( true );

	m_bIsServerKicking = bIsKicking;
	m_flServerEndTime = gpGlobals->curtime + (float)nTime;
}
//-----------------------------------------------------------------------------
void CTFHudMannVsMachineStatus::MVMServerKickTimeUpdate( int nTime )
{
	m_flServerEndTime = gpGlobals->curtime + (float)nTime;
}
//-----------------------------------------------------------------------------
void CTFHudMannVsMachineStatus::MVMVictoryGCResponse( CMsgMvMVictoryInfo &pData )
{
	m_pVictoryContainer->MannUpServerResponse( pData );
}

void CTFHudMannVsMachineStatus::ForceVictoryRefresh()
{
	InvalidateLayout( false, true );
}

void CTFHudMannVsMachineStatus::ReopenVictoryPanel( void )
{
	m_pVictoryContainer->ShowVictoryPanel( true );
}

//-----------------------------------------------------------------------------
// Private
//-----------------------------------------------------------------------------
void CTFHudMannVsMachineStatus::UpdateBombCarrierProgress ( void )
{
	m_pUpgradeLevelContainer->SetVisible( TFGameRules()->State_Get() == GR_STATE_RND_RUNNING );

	if ( !m_pUpgradeLevel1 || !m_pUpgradeLevel2 || !m_pUpgradeLevel3 || !m_pUpgradeLevelBoss )
		return;

	// Width of Meter
	float flBase = TFObjectiveResource()->GetNextMvMBombUpgradeTime() - TFObjectiveResource()->GetBaseMvMBombUpgradeTime();
	float flCurr = TFObjectiveResource()->GetNextMvMBombUpgradeTime() - gpGlobals->curtime;
	
	float flPercent = 0;
	int nFlagLevel = TFObjectiveResource()->GetFlagCarrierUpgradeLevel();
	if ( flBase <= 0 || nFlagLevel >= 3 )
	{
		flPercent = nFlagLevel >= 3 ? 1.0 : 0;
	}
	else 
	{
		flPercent = MIN( 1.0f, 1.0f - (flCurr / flBase) );
	}
	m_pBombUpgradeMeterMask->SetWide( ( m_nUpgradeMaskBaseWidth * ( nFlagLevel + 1 ) ) + flPercent * m_nUpgradeMaskBaseWidth );

	// Updating Image
	if ( m_nFlagCarrierUpgradeLevel == nFlagLevel )
		return;

	m_pUpgradeLevel1->SetImage( "../hud/hud_mvm_bomb_upgrade_1_disabled" );
	m_pUpgradeLevel2->SetImage( "../hud/hud_mvm_bomb_upgrade_2_disabled" );
	m_pUpgradeLevel3->SetImage( "../hud/hud_mvm_bomb_upgrade_3_disabled" );

	m_nFlagCarrierUpgradeLevel = nFlagLevel;

	switch ( m_nFlagCarrierUpgradeLevel )
	{
	case 4:
		m_pUpgradeLevelBoss->SetVisible( true );
		m_pUpgradeLevel1->SetVisible( false );
		m_pUpgradeLevel2->SetVisible( false );
		m_pUpgradeLevel3->SetVisible( false );
		break;

	case 3:
		m_pUpgradeLevel3->SetImage( "../hud/hud_mvm_bomb_upgrade_3" );
		// Intentionally fall through
	case 2:
		m_pUpgradeLevel2->SetImage( "../hud/hud_mvm_bomb_upgrade_2" );
		// Intentionally fall through
	case 1:
		m_pUpgradeLevel1->SetImage( "../hud/hud_mvm_bomb_upgrade_1" );
		// Intentionally fall through

	default:
		m_pUpgradeLevelBoss->SetVisible( false );
		m_pUpgradeLevel1->SetVisible( true );
		m_pUpgradeLevel2->SetVisible( true );
		m_pUpgradeLevel3->SetVisible( true );
	}
}

//-----------------------------------------------------------------------------
void CTFHudMannVsMachineStatus::UpdateServerMessage( void )
{
	
}