Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.

346 lines
9.2 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "hud.h"
#include "hudelement.h"
#include "c_tf_player.h"
#include "iclientmode.h"
#include "ienginevgui.h"
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <vgui/IVGui.h>
#include <vgui_controls/EditablePanel.h>
#include <vgui_controls/ProgressBar.h>
#include "tf_weapon_medigun.h"
#include <vgui_controls/AnimationController.h>
#include "tf_imagepanel.h"
#include "vgui_controls/Label.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
extern ConVar weapon_medigun_resist_num_chunks;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CHudMedicChargeMeter : public CHudElement, public EditablePanel
{
DECLARE_CLASS_SIMPLE( CHudMedicChargeMeter, EditablePanel );
public:
CHudMedicChargeMeter( const char *pElementName );
virtual void ApplySchemeSettings( IScheme *scheme );
virtual bool ShouldDraw( void );
virtual void OnTick( void );
private:
void UpdateKnownChargeType( bool bForce );
void UpdateControlVisibility();
vgui::ContinuousProgressBar* m_pChargeMeter;
CTFImagePanel* m_pResistPanel;
CUtlVector<vgui::ContinuousProgressBar*> m_vecpChargeMeters;
Label* m_pUberchargeLabel;
Label* m_pUberchargeCountLabel;
bool m_bCharged;
float m_flLastChargeValue;
int m_nLastActiveResist;
medigun_weapontypes_t m_eLastKnownMedigunType;
};
DECLARE_HUDELEMENT( CHudMedicChargeMeter );
struct ResistIcons_t
{
const char* m_pzsRed;
const char* m_pzsBlue;
};
static ResistIcons_t g_ResistIcons[MEDIGUN_NUM_RESISTS] =
{
{ "../HUD/defense_buff_bullet_blue", "../HUD/defense_buff_bullet_red" },
{ "../HUD/defense_buff_explosion_blue", "../HUD/defense_buff_explosion_red" },
{ "../HUD/defense_buff_fire_blue", "../HUD/defense_buff_fire_red" },
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CHudMedicChargeMeter::CHudMedicChargeMeter( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudMedicCharge" )
{
Panel *pParent = g_pClientMode->GetViewport();
SetParent( pParent );
m_pChargeMeter = new ContinuousProgressBar( this, "ChargeMeter" );
for( int i=0; i<weapon_medigun_resist_num_chunks.GetInt(); ++i )
{
m_vecpChargeMeters.AddToTail( new ContinuousProgressBar( this, CFmtStr( "ChargeMeter%d", i+1 ) ) );
}
m_pResistPanel = new CTFImagePanel( this, "ResistIcon" );
m_pResistPanel->SetVisible( false );
SetHiddenBits( HIDEHUD_MISCSTATUS );
vgui::ivgui()->AddTickSignal( GetVPanel() );
m_bCharged = false;
m_flLastChargeValue = -1;
m_eLastKnownMedigunType = MEDIGUN_STANDARD;
m_nLastActiveResist = MEDIGUN_BULLET_RESIST;
SetDialogVariable( "charge", 0 );
SetDialogVariable( "charge_count", 0 );
RegisterForRenderGroup( "inspect_panel" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudMedicChargeMeter::ApplySchemeSettings( IScheme *pScheme )
{
// load control settings...
LoadControlSettings( "resource/UI/HudMedicCharge.res" );
m_pUberchargeLabel = dynamic_cast<Label*>( FindChildByName("ChargeLabel") );
Assert( m_pUberchargeLabel );
m_pUberchargeCountLabel = dynamic_cast<Label*>( FindChildByName("IndividualChargesLabel") );
Assert( m_pUberchargeCountLabel );
if( m_pUberchargeCountLabel )
{
m_pUberchargeCountLabel->SetVisible( false );
}
for( int i=0; i<weapon_medigun_resist_num_chunks.GetInt(); ++i )
{
m_vecpChargeMeters[i]->SetVisible( false );
}
m_pResistPanel->SetVisible( false );
// Figure out which controls to show
UpdateKnownChargeType( true );
BaseClass::ApplySchemeSettings( pScheme );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CHudMedicChargeMeter::ShouldDraw( void )
{
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( !pPlayer || !pPlayer->IsPlayerClass( TF_CLASS_MEDIC ) || !pPlayer->IsAlive() )
{
return false;
}
CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon();
if ( !pWpn )
{
return false;
}
if ( pWpn->GetWeaponID() != TF_WEAPON_MEDIGUN && pWpn->GetWeaponID() != TF_WEAPON_BONESAW &&
!( pWpn->GetWeaponID() == TF_WEAPON_SYRINGEGUN_MEDIC && pWpn->UberChargeAmmoPerShot() > 0.0f ) )
{
return false;
}
return CHudElement::ShouldDraw();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudMedicChargeMeter::OnTick( void )
{
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( !pPlayer )
return;
CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon();
// Might have switched medigun types
UpdateKnownChargeType( false);
if ( !pWpn )
return;
if ( pWpn->GetWeaponID() == TF_WEAPON_BONESAW ||
( pWpn->GetWeaponID() == TF_WEAPON_SYRINGEGUN_MEDIC && pWpn->UberChargeAmmoPerShot() > 0.0f ) )
{
pWpn = pPlayer->Weapon_OwnsThisID( TF_WEAPON_MEDIGUN );
}
if ( !pWpn || ( pWpn->GetWeaponID() != TF_WEAPON_MEDIGUN ) )
return;
CWeaponMedigun *pMedigun = assert_cast< CWeaponMedigun *>( pWpn );
// We need to update the resist that we show here. Only do so if the medigun is actually
// the gun that's eruipped
if( pMedigun->GetMedigunType() == MEDIGUN_RESIST && pPlayer->GetActiveTFWeapon() == pMedigun )
{
int nCurrentActiveResist = pMedigun->GetResistType();
CBaseEntity* pOwner = pMedigun->GetOwner();
// Figure out which image to show based on team
const char* pzsImage = g_ResistIcons[nCurrentActiveResist].m_pzsBlue;
if( pOwner && pOwner->GetTeamNumber() == TF_TEAM_BLUE )
{
pzsImage = g_ResistIcons[nCurrentActiveResist].m_pzsRed;
}
// Resist Medigun is equipped. Update visibulity
m_pResistPanel->SetVisible( true );
m_pResistPanel->MoveToFront();
m_pResistPanel->SetPos( 0, 0 );
m_pResistPanel->SetImage( pzsImage );
}
else
{
m_pResistPanel->SetVisible( false );
}
float flCharge = pMedigun->GetChargeLevel();
if ( flCharge != m_flLastChargeValue )
{
if( pMedigun->GetMedigunType() == MEDIGUN_RESIST )
{
float flChunkSize = 1.f / weapon_medigun_resist_num_chunks.GetFloat();
for( int i=0; i<weapon_medigun_resist_num_chunks.GetInt(); ++i )
{
float flChunkCharge = flCharge - (flChunkSize * i);
float flProgress = MIN(flChunkCharge, flChunkSize) / flChunkSize;
// Not-full bars are dimmed a bit
if( flProgress < 1.f && !pMedigun->IsReleasingCharge() )
{
m_vecpChargeMeters[i]->SetFgColor( Color( 190, 190, 190, 255 ) );
}
else // Full bars are white
{
m_vecpChargeMeters[i]->SetFgColor( Color( 255, 255, 255, 255 ) );
}
m_vecpChargeMeters[i]->SetProgress( flProgress );
}
// We want to count full bars
SetDialogVariable( "charge_count", int(floor(flCharge / flChunkSize)) );
}
else if ( m_pChargeMeter ) // Regular uber
{
m_pChargeMeter->SetProgress( flCharge );
SetDialogVariable( "charge", (int)( flCharge * 100 ) );
}
if ( !m_bCharged )
{
if ( flCharge >= 1.0 )
{
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudMedicCharged" );
m_bCharged = true;
}
}
else
{
// we've got invuln charge or we're using our invuln
if ( !pMedigun->IsReleasingCharge() )
{
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudMedicChargedStop" );
m_bCharged = false;
}
}
}
m_flLastChargeValue = flCharge;
}
void CHudMedicChargeMeter::UpdateKnownChargeType( bool bForce )
{
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( !pPlayer )
return;
CTFWeaponBase *pWpn = pPlayer->Weapon_OwnsThisID( TF_WEAPON_MEDIGUN );
if( !pWpn )
return;
CWeaponMedigun *pMedigun = static_cast< CWeaponMedigun *>( pWpn );
if( pMedigun->GetMedigunType() != m_eLastKnownMedigunType || bForce )
{
m_eLastKnownMedigunType = (medigun_weapontypes_t)pMedigun->GetMedigunType();
UpdateControlVisibility();
}
}
void CHudMedicChargeMeter::UpdateControlVisibility()
{
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( !pPlayer )
return;
CTFWeaponBase *pWpn = pPlayer->Weapon_OwnsThisID( TF_WEAPON_MEDIGUN );
if ( !pWpn || ( pWpn->GetWeaponID() != TF_WEAPON_MEDIGUN ) )
return;
CWeaponMedigun *pMedigun = static_cast< CWeaponMedigun *>( pWpn );
if ( !pMedigun )
return;
bool bResistMedigun = m_eLastKnownMedigunType == MEDIGUN_RESIST;
// Using the resist medigun
if( !bResistMedigun )
{
m_pResistPanel->SetVisible( false );
}
// Conditionally show the medigun chunks
for( int i=0; i<m_vecpChargeMeters.Count(); ++i )
{
m_vecpChargeMeters[i]->SetVisible( bResistMedigun );
}
m_pChargeMeter->SetVisible( !bResistMedigun );
if( m_pUberchargeLabel )
{
m_pUberchargeLabel->SetVisible( !bResistMedigun );
}
if( m_pUberchargeCountLabel )
{
m_pUberchargeCountLabel->SetVisible( bResistMedigun );
}
}