//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//

#include "cbase.h"
#include "hudelement.h"
#include "iclientmode.h"
#include <KeyValues.h>
#include <vgui/IScheme.h>
#include <vgui/ISurface.h>
#include <vgui/ISystem.h>
#include <vgui_controls/AnimationController.h>
#include <vgui_controls/EditablePanel.h>
#include <vgui/ISurface.h>
#include <vgui/IImage.h>
#include <vgui_controls/Label.h>

#include "c_tf_playerresource.h"
#include "tf_playermodelpanel.h"
#include "econ_item_description.h"

#include "hud_numericdisplay.h"
#include "c_team.h"
#include "c_tf_player.h"
#include "tf_shareddefs.h"
#include "tf_hud_playerstatus.h"
#include "tf_gamerules.h"
#include "tf_logic_halloween_2014.h"
#include "tf_logic_player_destruction.h"

#include "tf_wheel_of_doom.h"

#include "confirm_dialog.h"

using namespace vgui;

ConVar cl_hud_playerclass_use_playermodel( "cl_hud_playerclass_use_playermodel", "1", FCVAR_ARCHIVE, "Use player model in player class HUD." );

#ifdef STAGING_ONLY
ConVar cl_hud_playerclass_playermodel_lod( "cl_hud_playerclass_playermodel_lod", "0", FCVAR_ARCHIVE, "Adjust lod on player model in the player class HUD." );
#endif // STAGING_ONLY

ConVar cl_hud_playerclass_playermodel_showed_confirm_dialog( "cl_hud_playerclass_playermodel_showed_confirm_dialog", "0", FCVAR_ARCHIVE | FCVAR_HIDDEN );

extern ConVar tf_max_health_boost;


static const char *g_szBlueClassImages[] = 
{ 
	"",
	"../hud/class_scoutblue", 
	"../hud/class_sniperblue",
	"../hud/class_soldierblue",
	"../hud/class_demoblue",
	"../hud/class_medicblue",
	"../hud/class_heavyblue",
	"../hud/class_pyroblue",
	"../hud/class_spyblue",
	"../hud/class_engiblue",
	"../hud/class_scoutblue",
};

static const char *g_szRedClassImages[] = 
{ 
	"",
	"../hud/class_scoutred", 
	"../hud/class_sniperred",
	"../hud/class_soldierred",
	"../hud/class_demored",
	"../hud/class_medicred",
	"../hud/class_heavyred",
	"../hud/class_pyrored",
	"../hud/class_spyred",
	"../hud/class_engired",
	"../hud/class_scoutred",
};

enum
{
	HUD_HEALTH_NO_ANIM = 0,
	HUD_HEALTH_BONUS_ANIM,
	HUD_HEALTH_DYING_ANIM,
};

DECLARE_BUILD_FACTORY( CTFClassImage );

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CTFHudPlayerClass::CTFHudPlayerClass( Panel *parent, const char *name ) : EditablePanel( parent, name )
{
	m_pClassImage = NULL;
	m_pClassImageBG = NULL;
	m_pSpyImage = NULL;
	m_pSpyOutlineImage = NULL;
	m_pPlayerModelPanel = NULL;
	m_pPlayerModelPanelBG = NULL;
	m_pCarryingWeaponPanel = NULL;
	m_pCarryingLabel = NULL;
	m_pCarryingOwnerLabel = NULL;
	m_pCarryingBG = NULL;

	m_nTeam = TEAM_UNASSIGNED;
	m_nClass = TF_CLASS_UNDEFINED;
	m_nDisguiseTeam = TEAM_UNASSIGNED;
	m_nDisguiseClass = TF_CLASS_UNDEFINED;
	m_hDisguiseWeapon = NULL;
	m_flNextThink = 0.0f;
	m_nKillStreak = 0;
#ifdef STAGING_ONLY
	m_nLOD = -1;
#endif // STAGING_ONLY

	m_bUsePlayerModel = cl_hud_playerclass_use_playermodel.GetBool();

	ListenForGameEvent( "localplayer_changedisguise" );
	ListenForGameEvent( "post_inventory_application" );
	ListenForGameEvent( "localplayer_pickup_weapon" );

	for ( int i = 0; i < TF_CLASS_COUNT_ALL; i++ )
	{
		// The materials are given to vgui via the SetImage() function, which prepends 
		// the "vgui/", so we need to precache them with the same.
		if ( g_szBlueClassImages[i] && g_szBlueClassImages[i][0] )
		{
			PrecacheMaterial( VarArgs( "vgui/%s", g_szBlueClassImages[i] ) );
			PrecacheMaterial( VarArgs( "vgui/%s_cloak", g_szBlueClassImages[i] ) );
			PrecacheMaterial( VarArgs( "vgui/%s_halfcloak", g_szBlueClassImages[i] ) );
		}
		if ( g_szRedClassImages[i] && g_szRedClassImages[i][0] )
		{
			PrecacheMaterial( VarArgs( "vgui/%s", g_szRedClassImages[i] ) );
			PrecacheMaterial( VarArgs( "vgui/%s_cloak", g_szRedClassImages[i] ) );
			PrecacheMaterial( VarArgs( "vgui/%s_halfcloak", g_szRedClassImages[i] ) );
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHudPlayerClass::Reset()
{
	m_flNextThink = gpGlobals->curtime + 0.05f;

	g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HudSpyDisguiseHide" );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHudPlayerClass::ApplySchemeSettings( IScheme *pScheme )
{
	// load control settings...
	LoadControlSettings( "resource/UI/HudPlayerClass.res" );

	m_nTeam = TEAM_UNASSIGNED;
	m_nClass = TF_CLASS_UNDEFINED;
	m_nDisguiseTeam = TEAM_UNASSIGNED;
	m_nDisguiseClass = TF_CLASS_UNDEFINED;
	m_hDisguiseWeapon = NULL;
	m_flNextThink = 0.0f;
	m_nCloakLevel = 0;
	m_nLoadoutPosition = LOADOUT_POSITION_PRIMARY;

	m_pClassImage = FindControl<CTFClassImage>( "PlayerStatusClassImage", false );
	m_pClassImageBG = FindControl<CTFImagePanel>( "PlayerStatusClassImageBG", false );
	m_pSpyImage = FindControl<CTFImagePanel>( "PlayerStatusSpyImage", false );
	m_pSpyOutlineImage = FindControl<CTFImagePanel>( "PlayerStatusSpyOutlineImage", false );

	m_pPlayerModelPanel = FindControl<CTFPlayerModelPanel>( "classmodelpanel", false );
	m_pPlayerModelPanelBG = FindControl<CTFImagePanel>( "classmodelpanelBG", false );

	m_pCarryingWeaponPanel = FindControl< EditablePanel >( "CarryingWeapon", false );
	if ( m_pCarryingWeaponPanel )
	{
		m_pCarryingLabel = m_pCarryingWeaponPanel->FindControl< CExLabel >( "CarryingLabel" );
		m_pCarryingOwnerLabel = m_pCarryingWeaponPanel->FindControl< Label >( "OwnerLabel" );
		m_pCarryingBG = m_pCarryingWeaponPanel->FindControl< CTFImagePanel >( "CarryingBackground" );
	}

	BaseClass::ApplySchemeSettings( pScheme );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHudPlayerClass::OnThink()
{
	if ( m_flNextThink > gpGlobals->curtime )
		return;

	m_flNextThink = gpGlobals->curtime + 0.5f;
	C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
	if ( !pPlayer )
		return;

	bool bTeamChange = false;
	// set our background colors
	if ( m_nTeam != pPlayer->GetTeamNumber() )
	{
		bTeamChange = true;
		m_nTeam = pPlayer->GetTeamNumber();
	}

	int nCloakLevel = 0;
	bool bCloakChange = false;
	float flInvis = pPlayer->GetPercentInvisible();

	if ( flInvis > 0.9 )
	{
		nCloakLevel = 2;
	}
	else if ( flInvis > 0.1 )
	{
		nCloakLevel = 1;
	}

	if ( nCloakLevel != m_nCloakLevel )
	{
		m_nCloakLevel = nCloakLevel;
		bCloakChange = true;
	}

	bool bLoadoutPositionChange = false;
	int nLoadoutSlot = pPlayer->GetActiveTFWeapon() ? pPlayer->GetActiveTFWeapon()->GetAttributeContainer()->GetItem()->GetStaticData()->GetLoadoutSlot( m_nClass ) : LOADOUT_POSITION_PRIMARY;
	if ( m_nLoadoutPosition != nLoadoutSlot )
	{
		m_nLoadoutPosition = nLoadoutSlot;
		bLoadoutPositionChange = true;
	}

	bool bPlayerClassModeChange = false;
	if ( m_bUsePlayerModel != cl_hud_playerclass_use_playermodel.GetBool() )
	{
		m_bUsePlayerModel = cl_hud_playerclass_use_playermodel.GetBool();
		bPlayerClassModeChange = true;
	}

#ifdef STAGING_ONLY
	if ( m_nLOD != cl_hud_playerclass_playermodel_lod.GetInt() && m_pPlayerModelPanel )
	{
		m_nLOD = cl_hud_playerclass_playermodel_lod.GetInt();
		m_pPlayerModelPanel->SetLOD( m_nLOD );
	}
#endif // STAGING_ONLY

	bool bForceEyeUpdate = false;
	// set our class image
	if (	m_nClass != pPlayer->GetPlayerClass()->GetClassIndex() || bTeamChange || bCloakChange || bLoadoutPositionChange || bPlayerClassModeChange ||
			(
				m_nClass == TF_CLASS_SPY &&
				(
					m_nDisguiseClass != pPlayer->m_Shared.GetDisguiseClass() ||
					m_nDisguiseTeam != pPlayer->m_Shared.GetDisguiseTeam() ||
					m_hDisguiseWeapon != pPlayer->m_Shared.GetDisguiseWeapon()
				)
			)
		)
	{
		bForceEyeUpdate = true;
		m_nClass = pPlayer->GetPlayerClass()->GetClassIndex();

		if ( m_nClass == TF_CLASS_SPY && pPlayer->m_Shared.InCond( TF_COND_DISGUISED ) )
		{
			if ( !pPlayer->m_Shared.InCond( TF_COND_DISGUISING ) )
			{
				m_nDisguiseTeam = pPlayer->m_Shared.GetDisguiseTeam();
				m_nDisguiseClass = pPlayer->m_Shared.GetDisguiseClass();
				m_hDisguiseWeapon = pPlayer->m_Shared.GetDisguiseWeapon();
			}
		}
		else
		{
			m_nDisguiseTeam = TEAM_UNASSIGNED;
			m_nDisguiseClass = TF_CLASS_UNDEFINED;
			m_hDisguiseWeapon = NULL;
		}

		if ( m_bUsePlayerModel && m_pPlayerModelPanel && m_pPlayerModelPanelBG )
		{
			m_pPlayerModelPanel->SetVisible( true );
			m_pPlayerModelPanelBG->SetVisible( true );

			UpdateModelPanel();
		}
		else if ( m_pClassImage && m_pSpyImage )
		{
			if ( m_pPlayerModelPanel )
				m_pPlayerModelPanel->SetVisible( false );
			if ( m_pPlayerModelPanelBG )
				m_pPlayerModelPanelBG->SetVisible( false );

			m_pClassImage->SetVisible( true );
			m_pClassImageBG->SetVisible( true );

			int iCloakState = 0;
			if ( pPlayer->IsPlayerClass( TF_CLASS_SPY ) )
			{
				iCloakState = m_nCloakLevel;
			}

			if ( m_nDisguiseTeam != TEAM_UNASSIGNED || m_nDisguiseClass != TF_CLASS_UNDEFINED )
			{
				m_pSpyImage->SetVisible( true );
				m_pClassImage->SetClass( m_nDisguiseTeam, m_nDisguiseClass, iCloakState );
			}
			else
			{
				m_pSpyImage->SetVisible( false );
				m_pClassImage->SetClass( m_nTeam, m_nClass, iCloakState );
			}
		}
	}

	if ( m_pCarryingWeaponPanel )
	{
		// Don't show if we're disguised (the panels overlap)
		bool bShowCarryingWeaponPanel = m_nDisguiseClass == TF_CLASS_UNDEFINED;

		if ( pPlayer->GetActiveTFWeapon() && pPlayer->GetActiveTFWeapon()->GetAttributeContainer() )
		{
			CEconItemView* pItem = pPlayer->GetActiveTFWeapon()->GetAttributeContainer()->GetItem();
			if ( pItem )
			{
				CSteamID playerSteamID;
				pPlayer->GetSteamID( &playerSteamID );
				// We're holding a weapon we dont own!
				if ( playerSteamID.GetAccountID() != pItem->GetAccountID() && m_pCarryingLabel )
				{
					locchar_t wszLocString [128];

					// Construct and set the weapon's name
					g_pVGuiLocalize->ConstructString_safe( wszLocString, L"%s1", 1, CEconItemLocalizedFullNameGenerator( GLocalizationProvider(), pItem->GetItemDefinition(), pItem->GetItemQuality() ).GetFullName() );
					m_pCarryingWeaponPanel->SetDialogVariable( "carrying", wszLocString );

					// Get and set the rarity color of the weapon
					const char* pszColorName = GetItemSchema()->GetRarityColor( pItem->GetItemDefinition()->GetRarity() );
					pszColorName = pszColorName ? pszColorName : "TanLight";
					if ( pszColorName )
					{
						m_pCarryingLabel->SetColorStr( pszColorName );
					}

					bool bHasOwner = false;
					locchar_t wszPlayerName [128];
					CBasePlayer *pOwner = GetPlayerByAccountID( pItem->GetAccountID() );
					// Bots will not work here, so don't fill this out if there's no owner
					if ( pOwner )
					{
						// Fill out the actual owner's name
						locchar_t wszStolenString[128];
						g_pVGuiLocalize->ConvertANSIToUnicode( pOwner->GetPlayerName(), wszPlayerName, sizeof(wszPlayerName) );
						g_pVGuiLocalize->ConstructString_safe( wszStolenString, g_pVGuiLocalize->Find( "TF_WhoDropped" ), 1, wszPlayerName );
						m_pCarryingOwnerLabel->SetText( wszStolenString );
						bHasOwner = true;
					}
					else
					{
						m_pCarryingOwnerLabel->SetText( "" );
					}
					
					int nMaxWide = 0, nMaxTall = 0;
					// Resize the panel to just be the width of whichever label is longer
					int nTall, nWide;
					m_pCarryingLabel->SizeToContents();
					m_pCarryingLabel->GetContentSize( nWide, nTall );
					nMaxWide = Max( nMaxWide, nWide );
					nMaxTall = Max( nMaxTall, nTall );

					m_pCarryingOwnerLabel->SizeToContents();
					m_pCarryingOwnerLabel->GetContentSize( nWide, nTall );
					nMaxWide = Max( nMaxWide, nWide );
					nMaxTall = Max( nMaxTall, nTall );

					m_pCarryingBG->SetWide( nMaxWide + ( m_pCarryingLabel->GetXPos() * 2 ) );
					m_pCarryingBG->SetTall( bHasOwner ? m_pCarryingOwnerLabel->GetYPos() + m_pCarryingOwnerLabel->GetTall() + YRES( 2 )
													  : m_pCarryingLabel->GetYPos() + m_pCarryingLabel->GetTall() + YRES( 2 ) );
				}
				else
				{
					bShowCarryingWeaponPanel = false;	
				}
			}
		}
		else
		{
			bShowCarryingWeaponPanel = false;
		}

		if ( CTFPlayerDestructionLogic::GetRobotDestructionLogic() && ( CTFPlayerDestructionLogic::GetRobotDestructionLogic()->GetType() == CTFPlayerDestructionLogic::TYPE_PLAYER_DESTRUCTION ) )
		{
			if ( pPlayer->HasTheFlag() )
			{
				bShowCarryingWeaponPanel = false;			
			}
		}

		m_pCarryingWeaponPanel->SetVisible( bShowCarryingWeaponPanel );
	}

	if ( m_bUsePlayerModel && m_pPlayerModelPanel )
	{
		bool bPlaySparks = false;
		int iKillStreak = pPlayer->m_Shared.GetStreak( CTFPlayerShared::kTFStreak_Kills );
		if ( iKillStreak != m_nKillStreak && iKillStreak > 0 )
		{
			bPlaySparks = true;
		}
		m_nKillStreak = iKillStreak;
		m_pPlayerModelPanel->SetEyeGlowEffect( pPlayer->GetEyeGlowEffect(), pPlayer->GetEyeGlowColor( false ), pPlayer->GetEyeGlowColor( true ), bForceEyeUpdate, bPlaySparks );
	}
}

static void HudPlayerClassUsePlayerModelDialogCallback( bool bConfirmed, void *pContext )
{
	cl_hud_playerclass_use_playermodel.SetValue( bConfirmed );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHudPlayerClass::UpdateModelPanel()
{
	if ( !m_bUsePlayerModel )
	{
		return;
	}

	C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
	if ( !pPlayer || !pPlayer->IsAlive() )
	{
		return;
	}

	if ( !cl_hud_playerclass_playermodel_showed_confirm_dialog.GetBool() )
	{
		// only show this message one time
		ShowConfirmDialog(	"#GameUI_HudPlayerClassUsePlayerModelDialogTitle",
			"#GameUI_HudPlayerClassUsePlayerModelDialogMessage",
			"#GameUI_HudPlayerClassUsePlayerModelDialogConfirm", 
			"#GameUI_HudPlayerClassUsePlayerModelDialogCancel",
			&HudPlayerClassUsePlayerModelDialogCallback );
		cl_hud_playerclass_playermodel_showed_confirm_dialog.SetValue( true );
	}

	// hide old UI
	if ( m_pSpyImage )
		m_pSpyImage->SetVisible( false );
	if ( m_pClassImage )
		m_pClassImage->SetVisible( false );
	if ( m_pClassImageBG )
		m_pClassImageBG->SetVisible( false );

	if ( m_pPlayerModelPanel && m_pPlayerModelPanel->IsVisible() )
	{
		int nClass;
		int nTeam;
		int nItemSlot = m_nLoadoutPosition;
		CEconItemView *pWeapon = NULL;

		bool bDisguised = pPlayer->m_Shared.InCond( TF_COND_DISGUISED );
		if ( bDisguised )
		{
			nClass = pPlayer->m_Shared.GetDisguiseClass();
			nTeam = pPlayer->m_Shared.GetDisguiseTeam();

			if ( pPlayer->m_Shared.GetDisguiseWeapon() )
			{
				CAttributeContainer *pCont = pPlayer->m_Shared.GetDisguiseWeapon()->GetAttributeContainer();
				pWeapon = pCont ? pCont->GetItem() : NULL;
				if ( pWeapon )
				{
					nItemSlot = pWeapon->GetStaticData()->GetLoadoutSlot( nClass );
				}
			}
		}
		else
		{
			nClass = pPlayer->GetPlayerClass()->GetClassIndex();
			nTeam = pPlayer->GetTeamNumber();

			CTFWeaponBase *pEnt = dynamic_cast< CTFWeaponBase* >( pPlayer->GetEntityForLoadoutSlot( nItemSlot ) );
			if ( pEnt )
			{
				pWeapon = pEnt->GetAttributeContainer()->GetItem();
			}
		}

		bool bIsRobot = false;
		int iRobot = 0;
		CALL_ATTRIB_HOOK_INT_ON_OTHER( pPlayer, iRobot, appear_as_mvm_robot );
		bIsRobot = iRobot ? true : false;

		m_pPlayerModelPanel->ClearCarriedItems();
		m_pPlayerModelPanel->SetToPlayerClass( nClass, bIsRobot );
		m_pPlayerModelPanel->SetTeam( nTeam );

		if ( pWeapon )
		{
			m_pPlayerModelPanel->AddCarriedItem( pWeapon );
		}

		for ( int wbl = pPlayer->GetNumWearables()-1; wbl >= 0; wbl-- )
		{
			C_TFWearable *pItem = dynamic_cast<C_TFWearable*>( pPlayer->GetWearable( wbl ) );
			if ( !pItem )
				continue;

			if ( pItem->IsViewModelWearable() )
				continue;

			if ( pItem->IsDisguiseWearable() && !bDisguised )
				continue;

			if ( !pItem->IsDisguiseWearable() && bDisguised )
				continue;

			CAttributeContainer *pCont		   = pItem->GetAttributeContainer();
			CEconItemView		*pEconItemView = pCont ? pCont->GetItem() : NULL;

			if ( pEconItemView && pEconItemView->IsValid() )
			{
				m_pPlayerModelPanel->AddCarriedItem( pEconItemView );
			}
		}

		m_pPlayerModelPanel->HoldItemInSlot( nItemSlot );
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHudPlayerClass::FireGameEvent( IGameEvent * event )
{
	const char* pszEventName = event->GetName();

	if ( FStrEq( "localplayer_changedisguise", pszEventName ) )
	{
		if ( m_pSpyImage && m_pSpyOutlineImage )
		{
			bool bFadeIn = event->GetBool( "disguised", false );

			if ( bFadeIn )
			{
				m_pSpyImage->SetAlpha( 0 );
			}
			else
			{
				m_pSpyImage->SetAlpha( 255 );
			}

			m_pSpyOutlineImage->SetAlpha( 0 );
			
			m_pSpyImage->SetVisible( true );
			m_pSpyOutlineImage->SetVisible( true );

			g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( bFadeIn ? "HudSpyDisguiseFadeIn" : "HudSpyDisguiseFadeOut" );
		}

		UpdateModelPanel();
	}
	else if ( FStrEq( "post_inventory_application", pszEventName ) )
	{
		// Force a refresh. if this is for the local player
		int iUserID = event->GetInt( "userid" );
		C_TFPlayer* pPlayer = ToTFPlayer( C_TFPlayer::GetLocalPlayer() );
		if ( pPlayer && pPlayer->GetUserID() == iUserID )
		{
			UpdateModelPanel();
		}
	}
	else if ( FStrEq( "localplayer_pickup_weapon", pszEventName ) )
	{
		UpdateModelPanel();
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CTFHealthPanel::CTFHealthPanel( Panel *parent, const char *name ) : vgui::Panel( parent, name )
{
	m_flHealth = 1.0f;

	m_iMaterialIndex = surface()->DrawGetTextureId( "hud/health_color" );
	if ( m_iMaterialIndex == -1 ) // we didn't find it, so create a new one
	{
		m_iMaterialIndex = surface()->CreateNewTextureID();	
		surface()->DrawSetTextureFile( m_iMaterialIndex, "hud/health_color", true, false );
	}

	m_iDeadMaterialIndex = surface()->DrawGetTextureId( "hud/health_dead" );
	if ( m_iDeadMaterialIndex == -1 ) // we didn't find it, so create a new one
	{
		m_iDeadMaterialIndex = surface()->CreateNewTextureID();	
		surface()->DrawSetTextureFile( m_iDeadMaterialIndex, "hud/health_dead", true, false );
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHealthPanel::Paint()
{
	BaseClass::Paint();

	int x, y, w, h;
	GetBounds( x, y, w, h );

	Vertex_t vert[4];	
	float uv1 = 0.0f;
	float uv2 = 1.0f;
	int xpos = 0, ypos = 0;

	if ( m_flHealth <= 0 )
	{
		// Draw the dead material
		surface()->DrawSetTexture( m_iDeadMaterialIndex );
		
		vert[0].Init( Vector2D( xpos, ypos ), Vector2D( uv1, uv1 ) );
		vert[1].Init( Vector2D( xpos + w, ypos ), Vector2D( uv2, uv1 ) );
		vert[2].Init( Vector2D( xpos + w, ypos + h ), Vector2D( uv2, uv2 ) );				
		vert[3].Init( Vector2D( xpos, ypos + h ), Vector2D( uv1, uv2 ) );

		surface()->DrawSetColor( Color(255,255,255,255) );
	}
	else
	{
		float flDamageY = h * ( 1.0f - m_flHealth );

		// blend in the red "damage" part
		surface()->DrawSetTexture( m_iMaterialIndex );

		Vector2D uv11( uv1, uv2 - m_flHealth );
		Vector2D uv21( uv2, uv2 - m_flHealth );
		Vector2D uv22( uv2, uv2 );
		Vector2D uv12( uv1, uv2 );

		vert[0].Init( Vector2D( xpos, flDamageY ), uv11 );
		vert[1].Init( Vector2D( xpos + w, flDamageY ), uv21 );
		vert[2].Init( Vector2D( xpos + w, ypos + h ), uv22 );				
		vert[3].Init( Vector2D( xpos, ypos + h ), uv12 );

		surface()->DrawSetColor( GetFgColor() );
	}

	surface()->DrawTexturedPolygon( 4, vert );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CTFHudPlayerHealth::CTFHudPlayerHealth( Panel *parent, const char *name ) : EditablePanel( parent, name )
{
	m_pHealthImage = new CTFHealthPanel( this, "PlayerStatusHealthImage" );	
	m_pHealthImageBG = new ImagePanel( this, "PlayerStatusHealthImageBG" );
	m_pHealthBonusImage = new ImagePanel( this, "PlayerStatusHealthBonusImage" );
	m_pBuildingHealthImageBG = new ImagePanel( this, "BuildingStatusHealthImageBG" );
	m_pBleedImage = new ImagePanel( this, "PlayerStatusBleedImage" );
	m_pHookBleedImage = new ImagePanel( this, "PlayerStatusHookBleedImage" );
	m_pMarkedForDeathImage = new ImagePanel( this, "PlayerStatusMarkedForDeathImage" );
	m_pMarkedForDeathImageSilent = new ImagePanel( this, "PlayerStatusMarkedForDeathSilentImage" );
	m_pMilkImage = new ImagePanel( this, "PlayerStatusMilkImage" );

	m_pWheelOfDoomImage = new ImagePanel( this, "PlayerStatus_WheelOfDoom" );

	m_flNextThink = 0.0f;

	m_nBonusHealthOrigX = -1;
	m_nBonusHealthOrigY = -1;
	m_nBonusHealthOrigW = -1;
	m_nBonusHealthOrigH = -1;

	// Vaccinator
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_MEDIGUN_UBER_BULLET_RESIST, BUFF_CLASS_BULLET_RESIST, new ImagePanel( this, "PlayerStatus_MedicUberBulletResistImage" ),	"../HUD/defense_buff_bullet_blue",		"../HUD/defense_buff_bullet_red"  ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_MEDIGUN_UBER_BLAST_RESIST, BUFF_CLASS_BLAST_RESIST, new ImagePanel( this, "PlayerStatus_MedicUberBlastResistImage" ),		"../HUD/defense_buff_explosion_blue",	"../HUD/defense_buff_explosion_red" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_MEDIGUN_UBER_FIRE_RESIST, BUFF_CLASS_FIRE_RESIST, new ImagePanel( this, "PlayerStatus_MedicUberFireResistImage" ),		"../HUD/defense_buff_fire_blue",		"../HUD/defense_buff_fire_red" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_MEDIGUN_SMALL_BULLET_RESIST, BUFF_CLASS_BULLET_RESIST, new ImagePanel( this, "PlayerStatus_MedicSmallBulletResistImage" ),	"../HUD/defense_buff_bullet_blue",		"../HUD/defense_buff_bullet_red"  ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_MEDIGUN_SMALL_BLAST_RESIST, BUFF_CLASS_BLAST_RESIST, new ImagePanel( this, "PlayerStatus_MedicSmallBlastResistImage" ),	"../HUD/defense_buff_explosion_blue",	"../HUD/defense_buff_explosion_red" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_MEDIGUN_SMALL_FIRE_RESIST, BUFF_CLASS_FIRE_RESIST, new ImagePanel( this, "PlayerStatus_MedicSmallFireResistImage" ),		"../HUD/defense_buff_fire_blue",		"../HUD/defense_buff_fire_red" ) );
	// Soldier buffs
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_OFFENSEBUFF, BUFF_CLASS_SOLDIER_OFFENSE, new ImagePanel( this, "PlayerStatus_SoldierOffenseBuff" ),						"../Effects/soldier_buff_offense_blue",		"../Effects/soldier_buff_offense_red" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_DEFENSEBUFF, BUFF_CLASS_SOLDIER_DEFENSE, new ImagePanel( this, "PlayerStatus_SoldierDefenseBuff" ),						"../Effects/soldier_buff_defense_blue",		"../Effects/soldier_buff_defense_red" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_REGENONDAMAGEBUFF, BUFF_CLASS_SOLDIER_HEALTHONHIT, new ImagePanel( this, "PlayerStatus_SoldierHealOnHitBuff" ),			"../Effects/soldier_buff_healonhit_blue",	"../Effects/soldier_buff_healonhit_red" ) );
	// Powerup Rune status
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_STRENGTH, RUNE_CLASS_STRENGTH, new ImagePanel( this, "PlayerStatus_RuneStrength" ), "../Effects/powerup_strength_hud", "../Effects/powerup_strength_hud" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_HASTE, RUNE_CLASS_HASTE, new ImagePanel( this, "PlayerStatus_RuneHaste" ), "../Effects/powerup_haste_hud", "../Effects/powerup_haste_hud" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_REGEN, RUNE_CLASS_REGEN, new ImagePanel( this, "PlayerStatus_RuneRegen" ), "../Effects/powerup_regen_hud", "../Effects/powerup_regen_hud" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_RESIST, RUNE_CLASS_RESIST, new ImagePanel( this, "PlayerStatus_RuneResist" ), "../Effects/powerup_resist_hud", "../Effects/powerup_resist_hud" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_VAMPIRE, RUNE_CLASS_VAMPIRE, new ImagePanel( this, "PlayerStatus_RuneVampire" ), "../Effects/powerup_vampire_hud", "../Effects/powerup_vampire_hud" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_REFLECT, RUNE_CLASS_REFLECT, new ImagePanel( this, "PlayerStatus_RuneReflect" ), "../Effects/powerup_reflect_hud", "../Effects/powerup_reflect_hud" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_PRECISION, RUNE_CLASS_PRECISION, new ImagePanel( this, "PlayerStatus_RunePrecision" ), "../Effects/powerup_precision_hud", "../Effects/powerup_precision_hud" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_AGILITY, RUNE_CLASS_AGILITY, new ImagePanel( this, "PlayerStatus_RuneAgility" ), "../Effects/powerup_agility_hud", "../Effects/powerup_agility_hud" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_KNOCKOUT, RUNE_CLASS_KNOCKOUT, new ImagePanel( this, "PlayerStatus_RuneKnockout" ), "../Effects/powerup_knockout_hud", "../Effects/powerup_knockout_hud" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_KING, RUNE_CLASS_KING, new ImagePanel( this, "PlayerStatus_RuneKing" ), "../Effects/powerup_king_hud", "../Effects/powerup_king_hud" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_PLAGUE, RUNE_CLASS_PLAGUE, new ImagePanel( this, "PlayerStatus_RunePlague" ), "../Effects/powerup_plague_hud", "../Effects/powerup_plague_hud" ) );
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_RUNE_SUPERNOVA, RUNE_CLASS_SUPERNOVA, new ImagePanel( this, "PlayerStatus_RuneSupernova" ), "../Effects/powerup_supernova_hud", "../Effects/powerup_supernova_hud" ) );
#ifdef STAGING_ONLY
	// Spy Mark
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_TRANQ_MARKED, DEBUFF_CLASS_SPY_MARKED, new ImagePanel( this, "PlayerStatus_SpyMarked" ), "../Effects/tranq_debuff", "../Effects/tranq_debuff" ) );
#endif // STAGING_ONLY

	// Parachute
	m_vecBuffInfo.AddToTail( new CTFBuffInfo( TF_COND_PARACHUTE_DEPLOYED, BUFF_CLASS_PARACHUTE, new ImagePanel( this, "PlayerStatus_Parachute" ), "../HUD/hud_parachute_active", "../HUD/hud_parachute_active" ) );

	m_iAnimState = HUD_HEALTH_NO_ANIM;
	m_bAnimate = true;
}

CTFHudPlayerHealth::~CTFHudPlayerHealth()
{
	m_vecBuffInfo.PurgeAndDeleteElements();
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHudPlayerHealth::Reset()
{
	m_flNextThink = gpGlobals->curtime + 0.05f;
	m_nHealth = -1;
	m_bBuilding = false;

	m_iAnimState = HUD_HEALTH_NO_ANIM;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHudPlayerHealth::ApplySchemeSettings( IScheme *pScheme )
{
	// load control settings...
	LoadControlSettings( GetResFilename() );

	if ( m_pHealthBonusImage )
	{
		m_pHealthBonusImage->GetBounds( m_nBonusHealthOrigX, m_nBonusHealthOrigY, m_nBonusHealthOrigW, m_nBonusHealthOrigH );
	}

	m_flNextThink = 0.0f;

	BaseClass::ApplySchemeSettings( pScheme );

	m_pBuildingHealthImageBG->SetVisible( m_bBuilding );

	m_pPlayerLevelLabel = dynamic_cast<CExLabel*>( FindChildByName( "PlayerStatusPlayerLevel" ) );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHudPlayerHealth::SetHealth( int iNewHealth, int iMaxHealth, int	iMaxBuffedHealth )
{
	// set our health
	m_nHealth = iNewHealth;
	m_nMaxHealth = iMaxHealth;
	m_pHealthImage->SetHealth( (float)(m_nHealth) / (float)(m_nMaxHealth) );

	if ( m_pHealthImage )
	{
		m_pHealthImage->SetFgColor( Color( 255, 255, 255, 255 ) );
	}

	if ( m_nHealth <= 0 )
	{
		if ( m_pHealthImageBG->IsVisible() )
		{
			m_pHealthImageBG->SetVisible( false );
		}
		if ( m_pBuildingHealthImageBG->IsVisible() )
		{
			m_pBuildingHealthImageBG->SetVisible( false );
		}
		HideHealthBonusImage();
	}
	else
	{
		if ( !m_pHealthImageBG->IsVisible() )
		{
			m_pHealthImageBG->SetVisible( true );
		}
		m_pBuildingHealthImageBG->SetVisible( m_bBuilding );

		// are we getting a health bonus?
		if ( m_nHealth > m_nMaxHealth )
		{
			if ( m_pHealthBonusImage && m_nBonusHealthOrigW != -1 )
			{
				if ( !m_pHealthBonusImage->IsVisible() )
				{
					m_pHealthBonusImage->SetVisible( true );
				}

				if ( m_bAnimate && m_iAnimState != HUD_HEALTH_BONUS_ANIM )
				{
					g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudHealthDyingPulseStop" );
					g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudHealthBonusPulse" );

					m_iAnimState = HUD_HEALTH_BONUS_ANIM;
				}

				m_pHealthBonusImage->SetDrawColor( Color( 255, 255, 255, 255 ) );

				// scale the flashing image based on how much health bonus we currently have
				float flBoostMaxAmount = ( iMaxBuffedHealth ) - m_nMaxHealth;
				float flPercent = MIN( ( m_nHealth - m_nMaxHealth ) / flBoostMaxAmount, 1.0f );

				int nPosAdj = RoundFloatToInt( flPercent * m_nHealthBonusPosAdj );
				int nSizeAdj = 2 * nPosAdj;

				m_pHealthBonusImage->SetBounds( m_nBonusHealthOrigX - nPosAdj, 
					m_nBonusHealthOrigY - nPosAdj, 
					m_nBonusHealthOrigW + nSizeAdj,
					m_nBonusHealthOrigH + nSizeAdj );
			}
		}
		// are we close to dying?
		else if ( m_nHealth < m_nMaxHealth * m_flHealthDeathWarning )
		{
			if ( m_pHealthBonusImage && m_nBonusHealthOrigW != -1 )
			{
				if ( !m_pHealthBonusImage->IsVisible() )
				{
					m_pHealthBonusImage->SetVisible( true );
				}

				if ( m_bAnimate && m_iAnimState != HUD_HEALTH_DYING_ANIM )
				{
					g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudHealthBonusPulseStop" );
					g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudHealthDyingPulse" );

					m_iAnimState = HUD_HEALTH_DYING_ANIM;
				}

				m_pHealthBonusImage->SetDrawColor( m_clrHealthDeathWarningColor );

				// scale the flashing image based on how much health bonus we currently have
				float flBoostMaxAmount = m_nMaxHealth * m_flHealthDeathWarning;
				float flPercent = ( flBoostMaxAmount - m_nHealth ) / flBoostMaxAmount;

				int nPosAdj = RoundFloatToInt( flPercent * m_nHealthBonusPosAdj );
				int nSizeAdj = 2 * nPosAdj;

				m_pHealthBonusImage->SetBounds( m_nBonusHealthOrigX - nPosAdj, 
					m_nBonusHealthOrigY - nPosAdj, 
					m_nBonusHealthOrigW + nSizeAdj,
					m_nBonusHealthOrigH + nSizeAdj );
			}

			if ( m_pHealthImage )
			{
				m_pHealthImage->SetFgColor( m_clrHealthDeathWarningColor );
			}
		}
		// turn it off
		else
		{
			HideHealthBonusImage();
		}
	}

	// set our health display value
	if ( m_nHealth > 0 )
	{
		SetDialogVariable( "Health", m_nHealth );
	}
	else
	{
		SetDialogVariable( "Health", "" );
	}	
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHudPlayerHealth::SetLevel( int nLevel )
{
	if ( m_pPlayerLevelLabel )
	{
		bool bVisible = ( nLevel >= 0 ) ? true : false;
		if ( bVisible )
		{
			m_pPlayerLevelLabel->SetText( CFmtStr( "%d", nLevel ) );
		}

		if ( m_pPlayerLevelLabel->IsVisible() != bVisible )
		{
			m_pPlayerLevelLabel->SetVisible( bVisible );
		}
	}
};

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHudPlayerHealth::HideHealthBonusImage( void )
{
	if ( m_pHealthBonusImage && m_pHealthBonusImage->IsVisible() )
	{
		if ( m_nBonusHealthOrigW != -1 )
		{
			m_pHealthBonusImage->SetBounds( m_nBonusHealthOrigX, m_nBonusHealthOrigY, m_nBonusHealthOrigW, m_nBonusHealthOrigH );
		}
		m_pHealthBonusImage->SetVisible( false );
		g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudHealthBonusPulseStop" );
		g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudHealthDyingPulseStop" );

		m_iAnimState = HUD_HEALTH_NO_ANIM;
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
static void SetPlayerHealthImagePanelVisibility( CTFPlayer *pPlayer, ETFCond eCond, vgui::ImagePanel *pImagePanel, int& nXOffset, const Color& colorIfVisible )
{
	Assert( pImagePanel != NULL );

	if ( pPlayer->m_Shared.InCond( eCond ) && !pImagePanel->IsVisible() )
	{
		pImagePanel->SetVisible( true );
		pImagePanel->SetDrawColor( colorIfVisible );
		
		// Reposition ourselves and increase the offset if we are active
		int x,y;
		pImagePanel->GetPos( x, y );
		pImagePanel->SetPos( nXOffset, y );
		nXOffset += 100.f;
	}
}

void CTFBuffInfo::Update( CTFPlayer *pPlayer )
{
	Assert( m_pImagePanel != NULL && pPlayer != NULL );

	if ( pPlayer->m_Shared.InCond( m_eCond ) )
	{
		if( m_pzsBlueImage && m_pzsBlueImage[0] && m_pzsRedImage && m_pzsRedImage[0] )
		{
			if( pPlayer->GetTeamNumber() == TF_TEAM_BLUE )
				m_pImagePanel->SetImage( m_pzsBlueImage );
			else
				m_pImagePanel->SetImage( m_pzsRedImage );
		}
	}
}

void CTFHudPlayerHealth::OnThink()
{
	if ( m_flNextThink < gpGlobals->curtime )
	{
		C_TFPlayer *pPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() );

		if ( pPlayer )
		{
			SetHealth( pPlayer->GetHealth(), pPlayer->GetMaxHealth(), pPlayer->m_Shared.GetMaxBuffedHealth() );

			int color_offset = ((int)(gpGlobals->realtime*10)) % 5;
			int color_fade	 = 160 + (color_offset*10);

			// Find our starting point, just above the health '+'
			int nXOffset,y;
			m_pHealthImage->GetPos( nXOffset, y );
			// Nudge over a bit to get centered
			nXOffset += 25;

			// Turn all the panels off, and below conditionally turn them on
			FOR_EACH_VEC( m_vecBuffInfo, i )
			{
				m_vecBuffInfo[ i ]->m_pImagePanel->SetVisible( false );
			}

			CUtlVector<BuffClass_t> m_vecActiveClasses;
			// Cycle through all the buffs and update them
			FOR_EACH_VEC( m_vecBuffInfo, i )
			{
				// Skip if this class of buff is already being drawn
				if( m_vecActiveClasses.Find( m_vecBuffInfo[i]->m_eClass ) != m_vecActiveClasses.InvalidIndex() )
					continue;

				m_vecBuffInfo[i]->Update( pPlayer );
				SetPlayerHealthImagePanelVisibility( pPlayer, m_vecBuffInfo[i]->m_eCond, m_vecBuffInfo[i]->m_pImagePanel, nXOffset, Color( 255, 255, 255, color_fade ) );

				// This class of buff is now active.
				if( m_vecBuffInfo[i]->m_pImagePanel->IsVisible() )
				{
					m_vecActiveClasses.AddToTail( m_vecBuffInfo[i]->m_eClass );
				}
			}

			// Turn all the panels off, and below conditionally turn them on
			m_pBleedImage->SetVisible( false );
			m_pHookBleedImage->SetVisible( false );
			m_pMilkImage->SetVisible( false );
			m_pMarkedForDeathImage->SetVisible( false );
			m_pMarkedForDeathImageSilent->SetVisible( false );
			
			// Old method for goofy color manipulation
			int nBloodX = nXOffset;
			SetPlayerHealthImagePanelVisibility( pPlayer, TF_COND_BLEEDING,					m_pBleedImage,					nXOffset,	Color( color_fade, 0, 0, 255 ) );
			SetPlayerHealthImagePanelVisibility( pPlayer, TF_COND_GRAPPLINGHOOK_BLEEDING,	m_pHookBleedImage,				nBloodX,	Color( 255, 255, 255, 255 ) ); // draw this on top of bleeding
			SetPlayerHealthImagePanelVisibility( pPlayer, TF_COND_MAD_MILK,					m_pMilkImage,					nXOffset,	Color( color_fade, color_fade, color_fade, 255 ) );
			SetPlayerHealthImagePanelVisibility( pPlayer, TF_COND_MARKEDFORDEATH,			m_pMarkedForDeathImage,			nXOffset,	Color( 255 - color_fade, 245 - color_fade, 245 - color_fade, 255 ) );
			SetPlayerHealthImagePanelVisibility( pPlayer, TF_COND_MARKEDFORDEATH_SILENT,	m_pMarkedForDeathImageSilent,	nXOffset,	Color( 125 - color_fade, 255 - color_fade, 255 - color_fade, 255 ) );
			SetPlayerHealthImagePanelVisibility( pPlayer, TF_COND_PASSTIME_PENALTY_DEBUFF,	m_pMarkedForDeathImageSilent,	nXOffset,	Color( 125 - color_fade, 255 - color_fade, 255 - color_fade, 255 ) );
			
			UpdateHalloweenStatus();
		}

		m_flNextThink = gpGlobals->curtime + 0.05f;
	}
}


void CTFHudPlayerHealth::UpdateHalloweenStatus( void )
{
	if ( TFGameRules()->IsHalloweenEffectStatusActive() )
	{
		int status = TFGameRules()->GetHalloweenEffectStatus();

		if ( status == EFFECT_WHAMMY )
		{
			m_pWheelOfDoomImage->SetImage( "..\\HUD\\death_wheel_whammy" );
		}
		else
		{
			m_pWheelOfDoomImage->SetImage( VarArgs( "..\\HUD\\death_wheel_%d", status - 1 ) );

		}

		float timeLeft = TFGameRules()->GetHalloweenEffectTimeLeft();

		const float warnExpireTime = 3.0f;
		const float blinkInterval = 0.25f;

		if ( timeLeft < warnExpireTime )
		{
			int blink = (int)( timeLeft / blinkInterval );

			m_pWheelOfDoomImage->SetVisible( blink & 0x1 );
		}
		else
		{
			m_pWheelOfDoomImage->SetVisible( true );
		}
	}
	else
	{
		m_pWheelOfDoomImage->SetVisible( false );
	}
}


DECLARE_HUDELEMENT( CTFHudPlayerStatus );

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CTFHudPlayerStatus::CTFHudPlayerStatus( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudPlayerStatus" ) 
{
	Panel *pParent = g_pClientMode->GetViewport();
	SetParent( pParent );

	m_pHudPlayerClass = new CTFHudPlayerClass( this, "HudPlayerClass" );
	m_pHudPlayerHealth = new CTFHudPlayerHealth( this, "HudPlayerHealth" );

	SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_PLAYERDEAD );
}

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

	// HACK: Work around the scheme application order failing
	// to reload the player class hud element's scheme in minmode.
	static ConVarRef cl_hud_minmode( "cl_hud_minmode", true );
	if ( cl_hud_minmode.IsValid() && cl_hud_minmode.GetBool() )
	{
		m_pHudPlayerClass->InvalidateLayout( false, true );
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CTFHudPlayerStatus::ShouldDraw( void )
{
	CTFPlayer *pTFPlayer = CTFPlayer::GetLocalTFPlayer();
	if ( pTFPlayer && pTFPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_GHOST_MODE ) )
		return false;

	if ( CTFMinigameLogic::GetMinigameLogic() && CTFMinigameLogic::GetMinigameLogic()->GetActiveMinigame() )
		return false;

	if ( TFGameRules() && TFGameRules()->ShowMatchSummary() )
		return false;

	return CHudElement::ShouldDraw();
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFHudPlayerStatus::Reset()
{
	if ( m_pHudPlayerClass )
	{
		m_pHudPlayerClass->Reset();
	}

	if ( m_pHudPlayerHealth )
	{
		m_pHudPlayerHealth->Reset();
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFClassImage::SetClass( int iTeam, int iClass, int iCloakstate )
{
	char szImage[128];
	szImage[0] = '\0';

	if ( iTeam == TF_TEAM_BLUE )
	{
		Q_strncpy( szImage, g_szBlueClassImages[ iClass ], sizeof(szImage) );
	}
	else
	{
		Q_strncpy( szImage, g_szRedClassImages[ iClass ], sizeof(szImage) );
	}

	switch( iCloakstate )
	{
	case 2:
		Q_strncat( szImage, "_cloak", sizeof(szImage), COPY_ALL_CHARACTERS );
		break;
	case 1:
		Q_strncat( szImage, "_halfcloak", sizeof(szImage), COPY_ALL_CHARACTERS );
		break;
	default:
		break;
	}

	if ( Q_strlen( szImage ) > 0 )
	{
		SetImage( szImage );
	}
}