|
|
//========= 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<Label *>(FindChildByName("TargetNameLabel")); m_pTargetDataLabel = dynamic_cast<Label *>(FindChildByName("TargetDataLabel")); m_pBGPanel = dynamic_cast<CTFImagePanel *> ( FindChildByName("TargetIDBG") ); m_pMoveableSubPanel = dynamic_cast<vgui::EditablePanel *> ( FindChildByName("MoveableSubPanel") ); if ( m_pMoveableSubPanel ) { m_pMoveableIcon = dynamic_cast<CIconPanel *> ( m_pMoveableSubPanel->FindChildByName("MoveableIcon") ); m_pMoveableSymbolIcon = dynamic_cast<vgui::ImagePanel *> ( m_pMoveableSubPanel->FindChildByName("MoveableSymbolIcon") ); m_pMoveableIconBG = dynamic_cast<CIconPanel *> ( m_pMoveableSubPanel->FindChildByName("MoveableIconBG") ); m_pMoveableKeyLabel = dynamic_cast<Label *>( m_pMoveableSubPanel->FindChildByName("MoveableKeyLabel") ); } m_hFont = scheme->GetFont( "TargetID", true ); m_pTargetAmmoIcon = dynamic_cast<vgui::ImagePanel *>( FindChildByName( "AmmoIcon" ) ); m_pTargetKillStreakIcon = dynamic_cast<vgui::ImagePanel *>( FindChildByName( "KillStreakIcon" ) ); m_pAvatarImage = dynamic_cast< CAvatarImagePanel* >( FindChildByName( "AvatarImage" ) ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTargetID::ApplySettings( KeyValues *inResourceData ) { BaseClass::ApplySettings( inResourceData );
m_iRenderPriority = inResourceData->GetInt( "priority" );
int x; GetPos( x, m_nOriginalY ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CTargetID::GetRenderGroupPriority( void ) { return m_iRenderPriority; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTargetID::UpdateFloatingHealthIconVisibility( bool bVisible ) { if ( m_pFloatingHealthIcon && ( m_pFloatingHealthIcon->IsVisible() != bVisible ) ) { m_pFloatingHealthIcon->SetVisible( bVisible ); } }
//-----------------------------------------------------------------------------
// Purpose: clear out string etc between levels
//-----------------------------------------------------------------------------
void CTargetID::VidInit() { CHudElement::VidInit();
m_flLastChangeTime = 0; m_iLastEntIndex = 0; }
bool CTargetID::IsValidIDTarget( int nEntIndex, float flOldTargetRetainFOV, float &flNewTargetRetainFOV ) { bool bReturn = false; flNewTargetRetainFOV = 0.0f;
C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !pLocalTFPlayer ) return false;
#ifdef STAGING_ONLY
if ( pLocalTFPlayer->m_Shared.InCond( TF_COND_STEALTHED_PHASE ) ) return false; #endif // STAGING_ONLY
if ( nEntIndex ) { C_BaseEntity *pEnt = cl_entitylist->GetEnt( nEntIndex ); if ( pEnt ) { Vector vDiff = pEnt->EyePosition() - pLocalTFPlayer->EyePosition(); float flDist; flDist = VectorNormalize( vDiff );
if ( flOldTargetRetainFOV != 0.0f ) { // It has a FOV that maintains previous targets
Vector vForward; pLocalTFPlayer->EyeVectors( &vForward );
float fAngle = 1.0f - vDiff.Dot( vForward ); fAngle = RemapVal( fAngle, 0.0f, 1.0f, 0.0f, 90.0f );
if ( fAngle > flOldTargetRetainFOV ) { return false; } }
C_TFPlayer *pPlayer = ToTFPlayer( pEnt );
int iHideEnemyHealth = 0; CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pLocalTFPlayer, iHideEnemyHealth, hide_enemy_health );
bool bInSameTeam = pLocalTFPlayer->InSameDisguisedTeam( pEnt ); bool bSpy = pLocalTFPlayer->IsPlayerClass( TF_CLASS_SPY ) && iHideEnemyHealth == 0;
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) { // We don't want to show health bars to the spy in MVM because it's distracting
bSpy = false;
// Are we disguised as the enemy?
if ( pLocalTFPlayer->m_Shared.InCond( TF_COND_DISGUISED ) && pLocalTFPlayer->m_Shared.GetDisguiseTeam() != pLocalTFPlayer->GetTeamNumber() ) { // Get the target's apparent team
int iTheirApparentTeam = pEnt->GetTeamNumber(); if ( pPlayer && pPlayer->m_Shared.InCond( TF_COND_DISGUISED ) ) { iTheirApparentTeam = pPlayer->m_Shared.GetDisguiseTeam(); }
// Are we disguised as they appear?
if ( pLocalTFPlayer->m_Shared.GetDisguiseTeam() == iTheirApparentTeam ) { // Don't show the health
bInSameTeam = false; } } }
bool bSpectator = pLocalTFPlayer->GetTeamNumber() == TEAM_SPECTATOR; int iSeeEnemyHealth = 0; bool bStealthed = false; bool bHealthBarVisible = ShouldHealthBarBeVisible( pEnt, pLocalTFPlayer ); bool bShow = bHealthBarVisible;
if ( pPlayer ) { if ( pPlayer->m_Shared.IsStealthed() ) { bStealthed = true; bHealthBarVisible = false; bShow = false; }
if ( !bStealthed ) { CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pLocalTFPlayer, iSeeEnemyHealth, see_enemy_health ); }
bool bMaintainInFOV = !pLocalTFPlayer->InSameTeam( pEnt );
if ( bHealthBarVisible ) { bool bEnemyPlayer = pPlayer->GetTeamNumber() != pLocalTFPlayer->GetTeamNumber(); bool bEnemyMiniBoss = pPlayer->IsMiniBoss() && bEnemyPlayer; bShow = bEnemyMiniBoss; #ifdef STAGING_ONLY
bShow |= TFGameRules() && TFGameRules()->IsBountyMode() && tf_bountymode_showhealth.GetInt() && bEnemyPlayer; #endif // STAGING_ONLY
if ( bShow ) { bMaintainInFOV = false;
// Minibosses keep the health indicator up within a small FOV until a different valid target is selected
// The FOV needs to grow exponentially when a target is getting near
if ( bEnemyMiniBoss ) { bMaintainInFOV = true; } } }
if ( bMaintainInFOV ) { const float flMaxDist = 800.0f; float fInterp = RemapVal( flMaxDist - MIN( flDist, flMaxDist ), 0.0f, flMaxDist, 0.0f, 1.0f ); fInterp *= fInterp; flNewTargetRetainFOV = fInterp * 13.0f + 0.75f; }
bReturn = ( bSpectator || pLocalTFPlayer->InSameTeam( pEnt ) || ( ( bInSameTeam || bSpy || iSeeEnemyHealth ) && !bStealthed ) ); }
if ( bShow || bHealthBarVisible ) { // See if we're re-targeting our previous
if ( m_pFloatingHealthIcon ) { if ( m_pFloatingHealthIcon->GetEntity() && m_pFloatingHealthIcon->GetEntity() == pEnt ) { UpdateFloatingHealthIconVisibility( true ); } else { // New target - clear previous
m_pFloatingHealthIcon->MarkForDeletion(); m_pFloatingHealthIcon = NULL; } }
//Recreate the floating health icon if there isn't one, we're not a spectator, and
// we're not a spy or this was a robot from Robot Destruction-Mode
if ( !m_pFloatingHealthIcon && !bSpectator && ( !bSpy || bHealthBarVisible ) && !DrawHealthIcon() ) { m_pFloatingHealthIcon = CFloatingHealthIcon::AddFloatingHealthIcon( pEnt ); } } else if ( pEnt->IsBaseObject() && ( bInSameTeam || bSpy ) ) { bReturn = true; } else if ( pEnt->IsVisibleToTargetID() ) { bReturn = true; } else { UpdateFloatingHealthIconVisibility( false ); } } }
return bReturn; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CTargetID::ShouldDraw( void ) { if ( !CHudElement::ShouldDraw() ) { UpdateFloatingHealthIconVisibility( false ); return false; }
if ( TFGameRules() && TFGameRules()->ShowMatchSummary() ) { UpdateFloatingHealthIconVisibility( false ); return false; }
C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !pLocalTFPlayer ) { UpdateFloatingHealthIconVisibility( false ); return false; }
if ( pLocalTFPlayer->IsTaunting() ) { UpdateFloatingHealthIconVisibility( false ); return false; }
// Get our target's ent index
m_iTargetEntIndex = CalculateTargetIndex(pLocalTFPlayer); if ( !m_iTargetEntIndex ) { if ( m_flTargetRetainFOV == 0.0f ) { // Check to see if we should clear our ID
if ( m_flLastChangeTime && ( gpGlobals->curtime > m_flLastChangeTime ) ) { m_flLastChangeTime = 0; m_iLastEntIndex = 0; } else { // Keep re-using the old one
m_iTargetEntIndex = m_iLastEntIndex; } }
// If we're showing a floating health icon, and no longer have a target,
// hide it and see if it's the same entity next time
UpdateFloatingHealthIconVisibility( false ); } else { m_flLastChangeTime = gpGlobals->curtime;
if ( m_iTargetEntIndex != m_iLastScannedEntIndex ) { // If we switched to another, valid target for a floating health icon, recreate it on the next pass
if ( m_pFloatingHealthIcon ) { m_pFloatingHealthIcon->MarkForDeletion(); m_pFloatingHealthIcon = NULL; } m_iLastScannedEntIndex = m_iTargetEntIndex; } }
float flTargetRetainFOV = 0.0f; bool bReturn = IsValidIDTarget( m_iTargetEntIndex, 0.0f, flTargetRetainFOV );
if ( !bReturn ) { m_iLastEntIndex = 0; } else { if ( !IsVisible() || (m_iTargetEntIndex != m_iLastEntIndex) ) { m_iLastEntIndex = m_iTargetEntIndex; m_bLayoutOnUpdate = true; m_flTargetRetainFOV = flTargetRetainFOV; if ( m_pAvatarImage ) { m_pAvatarImage->SetVisible( false ); } }
UpdateID(); }
return bReturn; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTargetID::PerformLayout( void ) { int iXIndent = XRES(5); int iXPostdent = XRES(10); int iWidth = iXIndent + iXPostdent; if ( DrawHealthIcon() ) { iWidth += m_pTargetHealth->GetWide(); } if ( m_pAvatarImage && m_pAvatarImage->IsVisible() ) { iWidth += m_pAvatarImage->GetWide() + XRES( 2 ); }
int iTextW, iTextH; int iDataW, iDataH;
if ( m_pTargetNameLabel && m_pTargetDataLabel ) { m_pTargetNameLabel->GetContentSize( iTextW, iTextH ); m_pTargetDataLabel->GetContentSize( iDataW, iDataH ); iWidth += MAX(iTextW,iDataW);
if ( m_pBGPanel ) { m_pBGPanel->SetSize( iWidth, GetTall() ); }
int x1 = 0, y1 = 0; int x2 = 0, y2 = 0; int x3 = 0, y3 = 0; m_pTargetNameLabel->GetPos( x1, y1 ); m_pTargetDataLabel->GetPos( x2, y2 ); if ( m_pTargetKillStreakIcon ) { m_pTargetKillStreakIcon->GetPos( x3, y3 ); } int iWideExtra = 0; if ( DrawHealthIcon() ) { iWideExtra += m_pTargetHealth->GetWide(); } if ( m_pAvatarImage && m_pAvatarImage->IsVisible() ) { iWideExtra += m_pAvatarImage->GetWide() + XRES( 4 ); }
int nBuffer = ( m_pAvatarImage && m_pAvatarImage->IsVisible() ) ? 6 : 8; m_pTargetNameLabel->SetPos( XRES( nBuffer ) + iWideExtra, y1 ); m_pTargetDataLabel->SetPos( XRES( nBuffer ) + iWideExtra, y2 );
if ( m_pTargetKillStreakIcon ) { int nKSBuffer = ( cl_hud_minmode.GetBool() ) ? 6 : 9; m_pTargetKillStreakIcon->SetPos( XRES( nKSBuffer ) + iWideExtra, y3 ); } }
// Put the moveable icon to the right hand of our panel
if ( m_pMoveableSubPanel && m_pMoveableSubPanel->IsVisible() ) { if ( m_pMoveableKeyLabel && m_pMoveableIcon && m_pMoveableSymbolIcon && m_pMoveableIconBG ) { m_pMoveableKeyLabel->SizeToContents();
int iIndent = XRES(4); int iMoveWide = MAX( XRES(16) + m_pMoveableKeyLabel->GetWide() + iIndent, (m_pMoveableIcon->GetWide()) + iIndent + XRES(8) ); m_pMoveableKeyLabel->SetWide( iMoveWide ); m_pMoveableSubPanel->SetSize( iMoveWide, GetTall() ); m_pMoveableSubPanel->SetPos( iWidth - iIndent, 0 );
int x,y; m_pMoveableKeyLabel->GetPos( x, y ); m_pMoveableSymbolIcon->SetPos( (iMoveWide - m_pMoveableSymbolIcon->GetWide()) * 0.5, y - m_pMoveableSymbolIcon->GetTall() ); m_pMoveableSymbolIcon->GetPos( x, y ); m_pMoveableIcon->SetPos( (iMoveWide - m_pMoveableIcon->GetWide()) * 0.5, y - m_pMoveableIcon->GetTall() ); m_pMoveableIconBG->SetSize( m_pMoveableSubPanel->GetWide(), m_pMoveableSubPanel->GetTall() ); } }
if ( m_pMoveableSubPanel && m_pMoveableSubPanel->IsVisible() ) { // Now add our extra width to the total size
iWidth += m_pMoveableSubPanel->GetWide(); }
SetSize( iWidth, GetTall() );
int nOffset = m_bArenaPanelVisible ? YRES (120) : 0; // HACK: move the targetID up a bit so it won't overlap the panel
if( UseVR() ) { SetPos( ScreenWidth() - iWidth - m_iXOffset, m_nOriginalY - nOffset + YRES( tf_hud_target_id_offset.GetInt() ) ); } else { SetPos( (ScreenWidth() - iWidth) * 0.5, m_nOriginalY - nOffset + YRES( tf_hud_target_id_offset.GetInt() ) ); } };
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CTargetID::CalculateTargetIndex( C_TFPlayer *pLocalTFPlayer ) { int iIndex = pLocalTFPlayer->GetIDTarget();
// If our target entity is already in our secondary ID, don't show it in primary.
CSecondaryTargetID *pSecondaryID = GET_HUDELEMENT( CSecondaryTargetID ); if ( pSecondaryID && pSecondaryID != this && pSecondaryID->GetTargetIndex() == iIndex ) { iIndex = 0; }
return iIndex; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTargetID::UpdateID( void ) { wchar_t sIDString[ MAX_ID_STRING ] = L""; wchar_t sDataString[ MAX_ID_STRING ] = L"";
C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !pLocalTFPlayer ) return;
// Default the labels' colors
Color colorName = m_LabelColorDefault; Color colorData = m_LabelColorDefault;
// Get our target's ent index
// Is this an entindex sent by the server?
if ( m_iTargetEntIndex ) { C_BaseEntity *pEnt = cl_entitylist->GetEnt( m_iTargetEntIndex ); if ( !pEnt ) return;
bool bShowHealth = false; float flHealth = 0; float flMaxHealth = 1; int iMaxBuffedHealth = 0; int iTargetTeam = pEnt->GetTeamNumber(); const char *pszActionCommand = NULL; const char *pszActionIcon = NULL;
m_pTargetHealth->SetBuilding( false ); m_pTargetHealth->SetLevel( -1 );
// Some entities we always want to check, cause the text may change
// even while we're looking at it
// Is it a player?
if ( IsPlayerIndex( m_iTargetEntIndex ) ) { const char *printFormatString = NULL; wchar_t wszPlayerName[ MAX_PLAYER_NAME_LENGTH ]; bool bDisguisedTarget = false; bool bDisguisedEnemy = false;
C_TFPlayer *pPlayer = static_cast<C_TFPlayer*>( pEnt ); if ( !pPlayer ) return;
C_TFPlayer *pDisguiseTarget = NULL; g_pVGuiLocalize->ConvertANSIToUnicode( pPlayer->GetPlayerName(), wszPlayerName, sizeof(wszPlayerName) );
// determine if the target is a disguised spy (either friendly or enemy)
if ( pPlayer->m_Shared.InCond( TF_COND_DISGUISED ) && // they're disguised
//!pPlayer->m_Shared.InCond( TF_COND_DISGUISING ) && // they're not in the process of disguising
!pPlayer->m_Shared.IsStealthed() ) // they're not cloaked
{ bDisguisedTarget = true; pDisguiseTarget = ToTFPlayer( pPlayer->m_Shared.GetDisguiseTarget() );
if ( pLocalTFPlayer->InSameTeam( pEnt ) == false ) { iTargetTeam = pPlayer->m_Shared.GetDisguiseTeam(); } }
if ( bDisguisedTarget ) { // is the target a disguised enemy spy?
if ( pPlayer->IsEnemyPlayer() ) { if ( pDisguiseTarget ) { bDisguisedEnemy = true; // change the player name
g_pVGuiLocalize->ConvertANSIToUnicode( pDisguiseTarget->GetPlayerName(), wszPlayerName, sizeof(wszPlayerName) ); // change the team / team color
} } }
bool bInSameTeam = pLocalTFPlayer->InSameDisguisedTeam( pEnt ); bool bSpy = pLocalTFPlayer->IsPlayerClass( TF_CLASS_SPY ); bool bMedic = pLocalTFPlayer->IsPlayerClass( TF_CLASS_MEDIC ); bool bHeavy = pLocalTFPlayer->IsPlayerClass( TF_CLASS_HEAVYWEAPONS );
// See if the player wants to fill in the data string
bool bIsAmmoData = false; bool bIsKillStreakData = false; pPlayer->GetTargetIDDataString( bDisguisedTarget, sDataString, sizeof(sDataString), bIsAmmoData, bIsKillStreakData ); if ( pLocalTFPlayer->GetTeamNumber() == TEAM_SPECTATOR || bInSameTeam || bSpy || bDisguisedEnemy || bMedic || bHeavy ) { printFormatString = "#TF_playerid_sameteam"; bShowHealth = true; } else if ( pLocalTFPlayer->m_Shared.GetState() == TF_STATE_DYING ) { // We're looking at an enemy who killed us.
printFormatString = "#TF_playerid_diffteam"; bShowHealth = true; }
if ( bShowHealth ) { if ( g_TF_PR ) { if ( bDisguisedEnemy ) { flHealth = (float)pPlayer->m_Shared.GetDisguiseHealth(); flMaxHealth = (float)pPlayer->m_Shared.GetDisguiseMaxHealth(); iMaxBuffedHealth = pPlayer->m_Shared.GetDisguiseMaxBuffedHealth(); } else { flHealth = (float)pPlayer->GetHealth(); flMaxHealth = g_TF_PR->GetMaxHealth( m_iTargetEntIndex ); iMaxBuffedHealth = pPlayer->m_Shared.GetMaxBuffedHealth(); } } else { bShowHealth = false; } }
if ( printFormatString ) { const wchar_t *pszPrepend = GetPrepend(); if ( !pszPrepend || !pszPrepend[0] ) { pszPrepend = L""; } g_pVGuiLocalize->ConstructString_safe( sIDString, g_pVGuiLocalize->Find(printFormatString), 2, pszPrepend, wszPlayerName ); }
// Show target's clip state to attached medics
bool bShowClipInfo = bIsAmmoData && sDataString[0] && ToTFPlayer( pLocalTFPlayer->MedicGetHealTarget() ) == pPlayer; if ( m_pTargetAmmoIcon && m_pTargetAmmoIcon->IsVisible() != bShowClipInfo ) { m_pTargetAmmoIcon->SetVisible( bShowClipInfo ); }
bool bShowKillStreak = bIsKillStreakData && sDataString[0]; if ( m_pTargetKillStreakIcon && m_pTargetKillStreakIcon->IsVisible() != bShowKillStreak ) { m_pTargetKillStreakIcon->SetVisible( bShowKillStreak ); } } else { // see if it is an object
if ( pEnt->IsBaseObject() ) { C_BaseObject *pObj = assert_cast<C_BaseObject *>( pEnt );
pObj->GetTargetIDString( sIDString, sizeof(sIDString), false ); pObj->GetTargetIDDataString( sDataString, sizeof(sDataString) ); bShowHealth = true; flHealth = pObj->GetHealth(); flMaxHealth = pObj->GetMaxHealth(); m_pTargetHealth->SetBuilding( true ); if ( m_pTargetKillStreakIcon ) { m_pTargetKillStreakIcon->SetVisible( false ); }
// Switch the icon to the right object
if ( pObj->GetBuilder() == pLocalTFPlayer ) { int iObj = pObj->GetType();
if ( iObj >= OBJ_DISPENSER && iObj <= OBJ_SENTRYGUN ) { if ( pLocalTFPlayer->CanPickupBuilding(pObj) ) { pszActionCommand = "+attack2"; }
switch ( iObj ) { default: case OBJ_DISPENSER: pszActionIcon = "obj_status_dispenser"; break; case OBJ_TELEPORTER: { pszActionIcon = (pObj->GetObjectMode() == MODE_TELEPORTER_ENTRANCE) ? "obj_status_tele_entrance" : "obj_status_tele_exit"; } break; case OBJ_SENTRYGUN: { int iLevel = pObj->GetUpgradeLevel(); if ( iLevel == 3 ) { pszActionIcon = "obj_status_sentrygun_3"; } else { pszActionIcon = (iLevel == 2) ? "obj_status_sentrygun_2" : "obj_status_sentrygun_1"; } } break; } } } } // Generic
else if ( pEnt->IsVisibleToTargetID() ) { CCaptureFlag *pFlag = dynamic_cast< CCaptureFlag * >( pEnt ); if ( pFlag && pFlag->GetPointValue() > 0 ) { bShowHealth = false; g_pVGuiLocalize->ConvertANSIToUnicode( CFmtStr("%d Points", pFlag->GetPointValue() ), sIDString, sizeof(sIDString) ); } else { CTFDroppedWeapon *pDroppedWeapon = dynamic_cast< CTFDroppedWeapon * >( pEnt ); if ( pDroppedWeapon ) { CEconItemView* pDroppedEconItem = pDroppedWeapon->GetItem(); if ( pLocalTFPlayer->GetDroppedWeaponInRange() != NULL ) { pszActionIcon = "obj_weapon_pickup"; pszActionCommand = "+use_action_slot_item"; } if ( FStrEq( pDroppedEconItem->GetStaticData()->GetItemClass(), "tf_weapon_medigun" ) ) { wchar_t wszChargeLevel[10]; _snwprintf( wszChargeLevel, ARRAYSIZE( wszChargeLevel ) - 1, L"%.0f", pDroppedWeapon->GetChargeLevel() * 100 ); wszChargeLevel[ARRAYSIZE( wszChargeLevel ) - 1] = '\0';
g_pVGuiLocalize->ConstructString_safe( sIDString, L"%s1 (%s2%)", 2, CEconItemLocalizedFullNameGenerator( GLocalizationProvider(), pDroppedEconItem->GetItemDefinition(), pDroppedEconItem->GetItemQuality() ).GetFullName(), wszChargeLevel ); } else { g_pVGuiLocalize->ConstructString_safe( sIDString, L"%s1", 1, CEconItemLocalizedFullNameGenerator( GLocalizationProvider(), pDroppedEconItem->GetItemDefinition(), pDroppedEconItem->GetItemQuality() ).GetFullName() ); }
locchar_t wszPlayerName [128]; CBasePlayer *pOwner = GetPlayerByAccountID( pDroppedEconItem->GetAccountID() ); // Bots will not work here, so don't fill this out.
if ( pOwner ) { g_pVGuiLocalize->ConvertANSIToUnicode( pOwner->GetPlayerName(), wszPlayerName, sizeof(wszPlayerName) ); g_pVGuiLocalize->ConstructString_safe( sDataString, g_pVGuiLocalize->Find( "#TF_WhoDropped" ), 1, wszPlayerName );
// Get the rarity color
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); if ( pScheme ) { const char* pszColorName = GetItemSchema()->GetRarityColor( pDroppedEconItem->GetItemDefinition()->GetRarity() ); pszColorName = pszColorName ? pszColorName : "TanLight"; colorName = pScheme->GetColor( pszColorName, Color( 255, 255, 255, 255 ) ); } } } else if ( pLocalTFPlayer->InSameTeam( pEnt ) ) { bShowHealth = true; flHealth = pEnt->GetHealth(); flMaxHealth = pEnt->GetMaxHealth(); iMaxBuffedHealth = pEnt->GetMaxHealth();
// Display respawn timer on revive markers by hacking bountymode's player level display
if ( !pEnt->IsPlayer() ) { CTFReviveMarker *pMarker = dynamic_cast< CTFReviveMarker* >( pEnt ); if ( pMarker && pMarker->GetOwner() ) { float flRespawn = TFGameRules()->GetNextRespawnWave( pMarker->GetTeamNumber(), pMarker->GetOwner() ) - gpGlobals->curtime; m_pTargetHealth->SetLevel( (int)flRespawn );
g_pVGuiLocalize->ConvertANSIToUnicode( pMarker->GetOwner()->GetPlayerName(), sIDString, sizeof(sIDString) ); } } } } } }
// Setup health icon
if ( !pEnt->IsAlive() && ( pEnt->IsPlayer() || pEnt->IsBaseObject() ) ) { flHealth = 0; // fixup for health being 1 when dead
}
m_pTargetHealth->SetHealth( flHealth, flMaxHealth, iMaxBuffedHealth ); m_pTargetHealth->SetVisible( DrawHealthIcon() ); if ( m_pMoveableSubPanel ) { bool bShowActionKey = pszActionCommand != NULL; if ( m_pMoveableSubPanel->IsVisible() != bShowActionKey ) { m_pMoveableSubPanel->SetVisible( bShowActionKey ); m_bLayoutOnUpdate = true; }
if ( m_pMoveableSubPanel->IsVisible() ) { const char *pBoundKey = engine->Key_LookupBinding( pszActionCommand ); m_pMoveableSubPanel->SetDialogVariable( "movekey", pBoundKey ); }
if ( m_pMoveableIcon ) { if ( pszActionIcon ) { m_pMoveableIcon->SetIcon( pszActionIcon ); } m_pMoveableIcon->SetVisible( pszActionIcon != NULL ); } }
if ( m_pAvatarImage && pEnt->IsPlayer() ) { C_BasePlayer *pTFTarget = GetTargetForSteamAvatar( ToTFPlayer( pEnt ) );
bool bShowAvatar = ( pTFTarget ) ? true : false; if ( m_pAvatarImage->IsVisible() != bShowAvatar ) { m_pAvatarImage->SetVisible( bShowAvatar ); if ( bShowAvatar ) { m_pAvatarImage->SetPlayer( pTFTarget ); m_pAvatarImage->SetShouldDrawFriendIcon( false ); m_pAvatarImage->SetAlpha( tf_hud_target_id_alpha.GetInt() ); } } }
if ( m_pTargetNameLabel && m_pTargetDataLabel ) { int iNameW, iDataW, iIgnored; m_pTargetNameLabel->GetContentSize( iNameW, iIgnored ); m_pTargetDataLabel->GetContentSize( iDataW, iIgnored );
// Target name
if ( sIDString[0] ) { sIDString[ ARRAYSIZE(sIDString)-1 ] = '\0'; m_pTargetNameLabel->SetVisible(true); m_pTargetNameLabel->SetFgColor( colorName );
// TODO: Support if( hud_centerid.GetInt() == 0 )
SetDialogVariable( "targetname", sIDString ); } else { m_pTargetNameLabel->SetVisible(false); m_pTargetNameLabel->SetText(""); }
// Extra target data
if ( sDataString[0] ) { sDataString[ ARRAYSIZE(sDataString)-1 ] = '\0'; m_pTargetDataLabel->SetVisible(true); m_pTargetDataLabel->SetFgColor( colorData );
SetDialogVariable( "targetdata", sDataString ); } else { m_pTargetDataLabel->SetVisible(false); m_pTargetDataLabel->SetText(""); }
int iPostNameW, iPostDataW; m_pTargetNameLabel->GetContentSize( iPostNameW, iIgnored ); m_pTargetDataLabel->GetContentSize( iPostDataW, iIgnored );
if ( m_pBGPanel ) { m_pBGPanel->SetBGTeam( iTargetTeam ); m_pBGPanel->UpdateBGImage(); m_pBGPanel->SetAlpha( tf_hud_target_id_alpha.GetInt() ); }
if ( m_bLayoutOnUpdate || (iPostDataW != iDataW) || (iPostNameW != iNameW) ) { InvalidateLayout( true ); m_bLayoutOnUpdate = false; } } } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CSecondaryTargetID::CSecondaryTargetID( const char *pElementName ) : CTargetID( pElementName ) { m_wszPrepend[0] = '\0';
RegisterForRenderGroup( "mid" );
m_bWasHidingLowerElements = false; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CSecondaryTargetID::ShouldDraw( void ) { bool bDraw = BaseClass::ShouldDraw();
if ( bDraw ) { if ( !m_bWasHidingLowerElements ) { HideLowerPriorityHudElementsInGroup( "mid" ); m_bWasHidingLowerElements = true; } } else { if ( m_bWasHidingLowerElements ) { UnhideLowerPriorityHudElementsInGroup( "mid" ); m_bWasHidingLowerElements = false; } }
return bDraw; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CSecondaryTargetID::CalculateTargetIndex( C_TFPlayer *pLocalTFPlayer ) { // If we're a medic & we're healing someone, target him.
CBaseEntity *pHealTarget = pLocalTFPlayer->MedicGetHealTarget(); if ( pHealTarget ) { if ( pHealTarget->entindex() != m_iTargetEntIndex ) { g_pVGuiLocalize->ConstructString_safe( m_wszPrepend, g_pVGuiLocalize->Find("#TF_playerid_healtarget" ), 0 ); } return pHealTarget->entindex(); }
// If we have a healer, target him.
C_TFPlayer *pHealer; float flHealerChargeLevel; pLocalTFPlayer->GetHealer( &pHealer, &flHealerChargeLevel ); if ( pHealer ) { if ( pHealer->entindex() != m_iTargetEntIndex ) { g_pVGuiLocalize->ConstructString_safe( m_wszPrepend, g_pVGuiLocalize->Find("#TF_playerid_healer" ), 0 ); } return pHealer->entindex(); }
if ( m_iTargetEntIndex ) { m_wszPrepend[0] = '\0'; } return 0; }
// Separately declared versions of the hud element for alive and dead so they
// can have different positions
bool CMainTargetID::ShouldDraw( void ) { C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !pLocalTFPlayer ) return false;
if ( pLocalTFPlayer->GetObserverMode() > OBS_MODE_NONE ) return false;
return BaseClass::ShouldDraw(); }
bool CSpectatorTargetID::ShouldDraw( void ) { C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !pLocalTFPlayer ) return false;
if ( pLocalTFPlayer->GetObserverMode() <= OBS_MODE_NONE || pLocalTFPlayer->GetObserverMode() == OBS_MODE_FREEZECAM ) return false;
if ( pLocalTFPlayer->m_bIsCoaching ) { return false; }
// Hide panel for freeze-cam screenshot?
extern bool IsTakingAFreezecamScreenshot(); extern ConVar hud_freezecamhide; if ( IsTakingAFreezecamScreenshot() && hud_freezecamhide.GetBool() ) return false;
#if defined( REPLAY_ENABLED )
if ( g_pEngineClientReplay->IsPlayingReplayDemo() ) return false; #endif
return BaseClass::ShouldDraw(); }
int CSpectatorTargetID::CalculateTargetIndex( C_TFPlayer *pLocalTFPlayer ) { int iIndex = BaseClass::CalculateTargetIndex( pLocalTFPlayer );
#if defined( REPLAY_ENABLED )
// Don't execute this if we're watching a replay
if ( ( !g_pEngineClientReplay || !g_pEngineClientReplay->IsPlayingReplayDemo() ) && pLocalTFPlayer->GetObserverMode() == OBS_MODE_IN_EYE && pLocalTFPlayer->GetObserverTarget() ) #else
if ( pLocalTFPlayer->GetObserverMode() == OBS_MODE_IN_EYE && pLocalTFPlayer->GetObserverTarget() ) #endif
{ iIndex = pLocalTFPlayer->GetObserverTarget()->entindex(); }
return iIndex; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSpectatorTargetID::ApplySchemeSettings( vgui::IScheme *scheme ) { BaseClass::ApplySchemeSettings( scheme );
if ( m_pBGPanel ) { m_pBGPanel->SetVisible( false ); }
m_pBGPanel_Spec_Blue = FindChildByName("TargetIDBG_Spec_Blue"); m_pBGPanel_Spec_Red = FindChildByName("TargetIDBG_Spec_Red");
if ( m_pBGPanel_Spec_Blue ) { m_pBGPanel_Spec_Blue->SetVisible( true ); } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSpectatorTargetID::PerformLayout( void ) { int iXIndent = XRES(5); int iXPostdent = XRES(10); int iWidth = m_pTargetHealth->GetWide() + iXIndent + iXPostdent;
int iTextW, iTextH; int iDataW, iDataH;
if ( m_pTargetNameLabel && m_pTargetDataLabel ) { m_pTargetNameLabel->GetContentSize( iTextW, iTextH ); m_pTargetDataLabel->GetContentSize( iDataW, iDataH ); iWidth += MAX(iTextW,iDataW);
SetSize( iWidth, GetTall() );
int nOffset = m_bArenaPanelVisible ? YRES (120) : 0; // HACK: move the targetID up a bit so it won't overlap the panel
int x1 = 0, y1 = 0; int x2 = 0, y2 = 0; int x3 = 0, y3 = 0; m_pTargetNameLabel->GetPos( x1, y1 ); m_pTargetDataLabel->GetPos( x2, y2 ); if ( m_pTargetKillStreakIcon ) { m_pTargetKillStreakIcon->GetPos( x3, y3 ); }
// Shift Labels
{ int nBuffer = ( m_pAvatarImage && m_pAvatarImage->IsVisible() ) ? 6 : 8; m_pTargetNameLabel->SetPos( XRES( nBuffer ) + m_pTargetHealth->GetWide(), y1 ); m_pTargetDataLabel->SetPos( XRES( nBuffer ) + m_pTargetHealth->GetWide(), y2 );
if ( m_pTargetKillStreakIcon ) { m_pTargetKillStreakIcon->SetPos( XRES( 10 ) + m_pTargetHealth->GetWide(), y3 ); } }
if ( tf_spectator_target_location.GetInt() == SPECTATOR_TARGET_ID_NORMAL ) { SetPos( (ScreenWidth() - iWidth) * 0.5, m_nOriginalY - nOffset ); } else { int iBottomBarHeight = 0; if ( g_pSpectatorGUI && g_pSpectatorGUI->IsVisible() ) { iBottomBarHeight = g_pSpectatorGUI->GetBottomBarHeight(); }
int iYPos = ScreenHeight() - GetTall() - iBottomBarHeight - m_iYOffset;
if ( tf_spectator_target_location.GetInt() == SPECTATOR_TARGET_ID_BOTTOM_LEFT ) { SetPos( m_iXOffset, iYPos ); } else if ( tf_spectator_target_location.GetInt() == SPECTATOR_TARGET_ID_BOTTOM_CENTER ) { SetPos( (ScreenWidth() - iWidth) * 0.5, iYPos ); } else if ( tf_spectator_target_location.GetInt() == SPECTATOR_TARGET_ID_BOTTOM_RIGHT ) { SetPos( ScreenWidth() - iWidth - m_iXOffset, iYPos ); } }
if ( m_pBGPanel_Spec_Blue ) { m_pBGPanel_Spec_Blue->SetSize( iWidth, GetTall() ); }
if ( m_pBGPanel_Spec_Red ) { m_pBGPanel_Spec_Red->SetSize( iWidth, GetTall() ); }
if ( m_pBGPanel_Spec_Blue && m_pBGPanel_Spec_Red ) { if ( m_iTargetEntIndex ) { C_BaseEntity *pEnt = cl_entitylist->GetEnt( m_iTargetEntIndex ); if ( pEnt ) { bool bRed = ( pEnt->GetTeamNumber() == TF_TEAM_RED ); m_pBGPanel_Spec_Blue->SetVisible( !bRed ); m_pBGPanel_Spec_Red->SetVisible( bRed );
m_pBGPanel_Spec_Blue->SetAlpha( tf_hud_target_id_alpha.GetInt() ); m_pBGPanel_Spec_Red->SetAlpha( tf_hud_target_id_alpha.GetInt() ); } } } } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CFloatingHealthIcon::CFloatingHealthIcon( vgui::Panel *parent, const char *name ) : EditablePanel( parent, name ) { m_flPrevHealth = -1.f; m_nPrevLevel = 0;
SetVisible( false ); SetBounds( 0, 0, 128, 128 );
vgui::ivgui()->AddTickSignal( GetVPanel(), 50 ); OnTick();
m_pTargetHealth = new CTFSpectatorGUIHealth( this, "SpectatorGUIHealth" ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFloatingHealthIcon::Reset( void ) { m_pTargetHealth->Reset(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFloatingHealthIcon::SetEntity( C_BaseEntity *pEntity ) { m_hEntity = pEntity;
if ( !m_pTargetHealth ) return;
m_pTargetHealth->SetAllowAnimations( false ); m_pTargetHealth->HideHealthBonusImage();
bool bBuilding = false;
if ( m_hEntity->IsPlayer() ) { C_TFPlayer *pPlayer = ToTFPlayer( m_hEntity ); bBuilding = ( pPlayer && pPlayer->IsMiniBoss() ) ? true : false; } m_pTargetHealth->SetBuilding( bBuilding ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CFloatingHealthIcon* CFloatingHealthIcon::AddFloatingHealthIcon( C_BaseEntity *pEntity ) { CFloatingHealthIcon *pHealthIcon = new CFloatingHealthIcon( g_pClientMode->GetViewport(), "HealthIcon" ); vgui::SETUP_PANEL( pHealthIcon ); pHealthIcon->SetEntity( pEntity );
return pHealthIcon; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFloatingHealthIcon::ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/UI/HealthIconPanel.res" ); SetVisible( false ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFloatingHealthIcon::OnTick( void ) { if ( !m_pTargetHealth ) return;
C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( !ShouldHealthBarBeVisible( m_hEntity, pLocalTFPlayer ) ) { SetVisible( false ); return; }
C_TFPlayer *pTargetPlayer = ToTFPlayer( m_hEntity ); if ( pTargetPlayer && pTargetPlayer->m_Shared.IsStealthed() ) { SetVisible( false ); return; }
// Defaults for all entities
float flHealth = m_hEntity->GetHealth(); float flMaxHealth = m_hEntity->GetMaxHealth(); float iMaxBuffedHealth = m_hEntity->GetMaxHealth();
if ( pTargetPlayer && pTargetPlayer->m_Shared.InCond( TF_COND_DISGUISED ) && pTargetPlayer->IsEnemyPlayer() ) { flHealth = (float)pTargetPlayer->m_Shared.GetDisguiseHealth(); flMaxHealth = (float)pTargetPlayer->m_Shared.GetDisguiseMaxHealth(); iMaxBuffedHealth = pTargetPlayer->m_Shared.GetDisguiseMaxBuffedHealth(); } if ( flHealth != m_flPrevHealth ) { m_pTargetHealth->SetHealth( flHealth, flMaxHealth, iMaxBuffedHealth ); m_flPrevHealth = flHealth; }
#ifdef STAGING_ONLY
if ( TFGameRules() && TFGameRules()->IsBountyMode() && tf_bountymode_showhealth.GetInt() == 2 ) { if ( m_hEntity->IsPlayer() ) { if ( !pTargetPlayer || pTargetPlayer->IsMiniBoss() ) return;
int nPlayerLevel = pTargetPlayer->GetExperienceLevel(); if ( nPlayerLevel != m_nPrevLevel ) { m_pTargetHealth->SetLevel( nPlayerLevel ); m_nPrevLevel = nPlayerLevel; } } } #endif // STAGING_ONLY
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ConVar tf_healthicon_height_offset( "tf_healthicon_height_offset", "10", FCVAR_ARCHIVE, "Offset of the health icon away from the top of the target." ); void CFloatingHealthIcon::Paint( void ) { if ( !CalculatePosition() ) return;
BaseClass::Paint(); }
//-----------------------------------------------------------------------------
bool CFloatingHealthIcon::CalculatePosition( ) { C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !pLocalTFPlayer ) return false;
if ( !m_hEntity || m_hEntity->IsDormant() ) { return false; }
Vector vecTarget = m_hEntity->GetAbsOrigin();
// Reposition based on our target's position
Vector vecDistance = vecTarget - pLocalTFPlayer->GetAbsOrigin(); vecTarget.z += VEC_HULL_MAX_SCALED( m_hEntity->GetBaseAnimating() ).z + tf_healthicon_height_offset.GetInt() + m_hEntity->GetHealthBarHeightOffset();
int iX, iY; GetVectorInHudSpace( vecTarget, iX, iY ); // TODO: GetVectorInHudSpace or GetVectorInScreenSpace?
SetPos( iX - ( GetWide() / 2 ), iY - GetTall() );
return true; }
//-----------------------------------------------------------------------------
void CFloatingHealthIcon::SetVisible( bool state ) { if ( state ) { CalculatePosition(); }
BaseClass::SetVisible( state ); }
//-----------------------------------------------------------------------------
bool CFloatingHealthIcon::IsVisible( void ) { if ( !m_pTargetHealth ) return false;
C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !pLocalTFPlayer ) return false;
//if ( pLocalTFPlayer->GetObserverMode() == OBS_MODE_FREEZECAM )
if ( pLocalTFPlayer->GetObserverMode() > OBS_MODE_NONE ) return false;
if ( TFGameRules() && TFGameRules()->ShowMatchSummary() ) return false;
return BaseClass::IsVisible(); }
|