diff options
Diffstat (limited to 'game/client/tf/tf_hud_playerstatus.cpp')
| -rw-r--r-- | game/client/tf/tf_hud_playerstatus.cpp | 1157 |
1 files changed, 1157 insertions, 0 deletions
diff --git a/game/client/tf/tf_hud_playerstatus.cpp b/game/client/tf/tf_hud_playerstatus.cpp new file mode 100644 index 0000000..26723ce --- /dev/null +++ b/game/client/tf/tf_hud_playerstatus.cpp @@ -0,0 +1,1157 @@ +//========= 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 ); + } +} |