You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1158 lines
39 KiB
1158 lines
39 KiB
5 years ago
|
//========= 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 );
|
||
|
}
|
||
|
}
|