//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: HUD Target ID element // // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include "tf_hud_target_id.h" #include "c_tf_playerresource.h" #include "iclientmode.h" #include "vgui/ILocalize.h" #include "c_baseobject.h" #include "c_team.h" #include "tf_gamerules.h" #include "tf_hud_statpanel.h" #if defined( REPLAY_ENABLED ) #include "replay/iclientreplaycontext.h" #include "replay/ireplaymoviemanager.h" #include "replay/ienginereplay.h" #endif // REPLAY_ENABLED #include "tf_weapon_bonesaw.h" #include "sourcevr/isourcevirtualreality.h" #include "tf_revive.h" #include "tf_logic_robot_destruction.h" #include "entity_capture_flag.h" #include "vgui_avatarimage.h" #include "VGuiMatSurface/IMatSystemSurface.h" #include "renderparm.h" #include "tf_dropped_weapon.h" #include "econ/econ_item_description.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" extern ConVar cl_hud_minmode; DECLARE_HUDELEMENT( CMainTargetID ); DECLARE_HUDELEMENT( CSpectatorTargetID ); DECLARE_HUDELEMENT( CSecondaryTargetID ); using namespace vgui; enum { SPECTATOR_TARGET_ID_NORMAL = 0, SPECTATOR_TARGET_ID_BOTTOM_LEFT, SPECTATOR_TARGET_ID_BOTTOM_CENTER, SPECTATOR_TARGET_ID_BOTTOM_RIGHT, }; void SpectatorTargetLocationCallback( IConVar *var, const char *oldString, float oldFloat ) { CSpectatorTargetID *pSpecTargetID = (CSpectatorTargetID *)GET_HUDELEMENT( CSpectatorTargetID ); if ( pSpecTargetID ) { pSpecTargetID->InvalidateLayout(); } } ConVar tf_spectator_target_location( "tf_spectator_target_location", "0", FCVAR_ARCHIVE, "Determines the location of the spectator targetID panel.", true, 0, true, 3, SpectatorTargetLocationCallback ); ConVar tf_hud_target_id_disable_floating_health( "tf_hud_target_id_disable_floating_health", "0", FCVAR_ARCHIVE, "Set to disable floating health bar" ); ConVar tf_hud_target_id_alpha( "tf_hud_target_id_alpha", "100", FCVAR_ARCHIVE, "Alpha value of target id background, default 100" ); ConVar tf_hud_target_id_offset( "tf_hud_target_id_offset", "0", FCVAR_ARCHIVE, "RES file Y offset for target id" ); ConVar tf_hud_target_id_show_avatars( "tf_hud_target_id_show_avatars", "2", FCVAR_ARCHIVE, "Display Steam avatars on TargetID when using floating health icons. 1 = everyone, 2 = friends only." ); #ifdef STAGING_ONLY ConVar tf_bountymode_showhealth( "tf_bountymode_showhealth", "0", FCVAR_ARCHIVE, "Show floating health icon over enemy players. 1 = show health, 2 = show health and level", true, 0, true, 2 ); #endif // STAGING_ONLY bool ShouldHealthBarBeVisible( CBaseEntity *pTarget, CTFPlayer *pLocalPlayer ) { if ( !pTarget || !pLocalPlayer ) return false; if ( tf_hud_target_id_disable_floating_health.GetBool() ) return false; if ( pTarget->IsHealthBarVisible() ) return true; if ( !pTarget->IsPlayer() ) return false; if ( pLocalPlayer->IsPlayerClass( TF_CLASS_SPY ) ) return true; if ( pLocalPlayer->InSameTeam( pTarget ) ) return true; if ( pLocalPlayer->InSameDisguisedTeam( pTarget ) ) return true; int iSeeEnemyHealth = 0; CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pLocalPlayer, iSeeEnemyHealth, see_enemy_health ) if ( iSeeEnemyHealth ) return true; return false; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CTargetID::CTargetID( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, pElementName ) { vgui::Panel *pParent = g_pClientMode->GetViewport(); SetParent( pParent ); m_hFont = g_hFontTrebuchet24; m_flLastChangeTime = 0; m_iLastEntIndex = 0; m_nOriginalY = 0; m_bArenaPanelVisible = false; SetHiddenBits( HIDEHUD_MISCSTATUS ); m_pTargetNameLabel = NULL; m_pTargetDataLabel = NULL; m_pBGPanel = NULL; m_pMoveableIcon = NULL; m_pMoveableSymbolIcon = NULL; m_pMoveableIconBG = NULL; m_pMoveableKeyLabel = NULL; m_pTargetHealth = new CTFSpectatorGUIHealth( this, "SpectatorGUIHealth" ); m_pTargetAmmoIcon = NULL; m_pTargetKillStreakIcon = NULL; m_bLayoutOnUpdate = false; m_pFloatingHealthIcon = NULL; m_iLastScannedEntIndex = 0; m_pAvatarImage = NULL; RegisterForRenderGroup( "mid" ); RegisterForRenderGroup( "commentary" ); m_iRenderPriority = 5; ListenForGameEvent( "show_class_layout" ); RegisterForRenderGroup( "arena_target_id" ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTargetID::LevelShutdown( void ) { if ( m_pFloatingHealthIcon ) { m_pFloatingHealthIcon->MarkForDeletion(); m_pFloatingHealthIcon = NULL; } } //----------------------------------------------------------------------------- // Purpose: Setup //----------------------------------------------------------------------------- void CTargetID::Reset( void ) { m_pTargetHealth->Reset(); vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); if ( pScheme ) { m_LabelColorDefault = pScheme->GetColor( "Label.TextColor", Color( 255, 255, 255, 255 ) ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTargetID::FireGameEvent( IGameEvent * event ) { const char *eventName = event->GetName(); if ( FStrEq( "show_class_layout", eventName ) ) { if ( TFGameRules() && TFGameRules()->IsInArenaMode() && GetLocalPlayerTeam() > LAST_SHARED_TEAM ) { m_bArenaPanelVisible = event->GetBool( "show", false ); } else { m_bArenaPanelVisible = false; } InvalidateLayout( true ); } } //----------------------------------------------------------------------------- bool CTargetID::DrawHealthIcon() { C_BaseEntity *pEnt = cl_entitylist->GetEnt( GetTargetIndex() ); if ( pEnt && pEnt->IsBaseObject() ) return true; if ( tf_hud_target_id_disable_floating_health.GetBool() ) return true; return false; } //----------------------------------------------------------------------------- // Purpose: Find out which player to pull an avatar image from. pTFPlayer is the player under the crosshair. //----------------------------------------------------------------------------- C_TFPlayer *CTargetID::GetTargetForSteamAvatar( C_TFPlayer *pTFPlayer ) { if ( !tf_hud_target_id_show_avatars.GetBool() ) return NULL; if ( !pTFPlayer || ( g_TF_PR && g_TF_PR->IsFakePlayer( pTFPlayer->entindex() ) ) ) return NULL; C_TFPlayer *pTFLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !pTFLocalPlayer ) return NULL; // Health icon inside the panel (too busy - figure this out later) if ( DrawHealthIcon() ) return NULL; // Save room when healing or being healed if ( pTFLocalPlayer->IsPlayerClass( TF_CLASS_MEDIC ) && pTFLocalPlayer->MedicGetHealTarget() == pTFPlayer ) return NULL; C_TFPlayer *pTFHealer = NULL; float flHealerChargeLevel = -1.f; pTFLocalPlayer->GetHealer( &pTFHealer, &flHealerChargeLevel ); if ( pTFHealer && pTFHealer->entindex() == m_iTargetEntIndex ) return NULL; if ( pTFPlayer->IsPlayerClass( TF_CLASS_SPY ) && pTFPlayer->m_Shared.InCond( TF_COND_DISGUISED ) ) { C_TFPlayer *pDisguiseTarget = ToTFPlayer( pTFPlayer->m_Shared.GetDisguiseTarget() ); if ( pDisguiseTarget && ( pTFLocalPlayer->InSameTeam( pDisguiseTarget ) || pDisguiseTarget == pTFLocalPlayer ) ) { // Bots don't (currently) have avatars. if ( pDisguiseTarget->IsBot() ) return NULL; if ( tf_hud_target_id_show_avatars.GetInt() == 2 && !pTFLocalPlayer->IsPlayerOnSteamFriendsList( pDisguiseTarget ) ) return NULL; return pDisguiseTarget; } } if ( pTFLocalPlayer->IsPlayerOnSteamFriendsList( pTFPlayer ) ) return pTFPlayer; if ( tf_hud_target_id_show_avatars.GetInt() == 1 ) return pTFPlayer; return NULL; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTargetID::ApplySchemeSettings( vgui::IScheme *scheme ) { LoadControlSettings( "resource/UI/TargetID.res" ); BaseClass::ApplySchemeSettings( scheme ); m_pTargetNameLabel = dynamic_cast