cstrike15_src/game/client/cstrike15/Scaleform/HUD/sfhudhealtharmorpanel.cpp
2025-06-04 03:22:50 +02:00

368 lines
11 KiB
C++

//========= Copyright 1996-2005, Valve Corporation, All rights reserved. =============================//
//
// Purpose: Purpose: Displays HUD elements about armor, current weapon, ammo, and TR weapon progress
//
//======================================================================================================//
#include "cbase.h"
#include "hud.h"
#include "hudelement.h"
#include "hud_element_helper.h"
#include "iclientmode.h"
#include "view.h"
#include "vgui_controls/Controls.h"
#include "vgui/ISurface.h"
#include "ivrenderview.h"
#include "scaleformui/scaleformui.h"
#include "sfhudhealtharmorpanel.h"
#include "vgui/ILocalize.h"
#include "c_cs_hostage.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define SAFECALL( handle, func ) \
if ( handle ) \
{ \
func \
}
DECLARE_HUDELEMENT( SFHudHealthArmorPanel );
SFUI_BEGIN_GAME_API_DEF
SFUI_END_GAME_API_DEF( SFHudHealthArmorPanel, HealthArmorModule ); // Asset named WeaponModule to maintain consistency with Flash file naming
// global tunables
const float g_LowHealthPercent = 0.20f;
const float g_HealthFlashSeconds = 1.0f;
extern ConVar cl_draw_only_deathnotices;
SFHudHealthArmorPanel::SFHudHealthArmorPanel( const char *value ) : SFHudFlashInterface( value ),
m_PanelHandle( NULL ),
m_HealthTextHandle( NULL ),
m_HealthTextHandleRed( NULL ),
m_ArmorTextHandle( NULL ),
m_HealthBarHandle( NULL ),
m_HealthRedBarHandle( NULL ),
m_HealthPanel( NULL ),
m_HealthPanelRed( NULL ),
m_HealthPanelRedSmall( NULL ),
m_PrevHealth( -1 ),
m_PrevArmor( -1 ),
m_PrevHasHelmet( false ),
m_PrevHasHeavyArmor( false )
{
// TODO Auto-generated constructor stub
SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_PLAYERDEAD );
m_HealthFlashTimer.Invalidate();
}
SFHudHealthArmorPanel::~SFHudHealthArmorPanel()
{
// TODO Auto-generated destructor stub
}
void SFHudHealthArmorPanel::ShowPanel( bool value )
{
if ( !m_pScaleformUI )
return;
WITH_SLOT_LOCKED
{
if ( m_FlashAPI )
{
if ( value )
{
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showNow", NULL, 0 );
}
else
{
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hideNow", NULL, 0 );
}
}
// This forces the health and armor bars to reset
m_PrevHealth = -1;
m_PrevArmor = -1;
m_PrevHasHelmet = false;
m_PrevHasHeavyArmor = false;
}
}
void SFHudHealthArmorPanel::SetVisible( bool bVisible )
{
if ( FlashAPIIsValid() )
{
WITH_SFVALUEARRAY_SLOT_LOCKED( data, 1 )
{
m_pScaleformUI->ValueArray_SetElement( data, 0, bVisible );
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "setVisible", data, 1 );
}
}
}
void SFHudHealthArmorPanel::LockSlot( bool wantItLocked, bool& currentlyLocked )
{
if ( currentlyLocked != wantItLocked )
{
if ( wantItLocked )
{
LockScaleformSlot();
}
else
{
UnlockScaleformSlot();
}
currentlyLocked = wantItLocked;
}
}
void SFHudHealthArmorPanel::ProcessInput( void )
{
// Update stats
int realHealth = 0;
int realArmor = 0;
float healthPercent = 0.0f;
float armorPercent = 0.0f;
bool bHasHelmet = false;
bool bHasHeavyArmor = false;
// Collect all player, weapon and game state data first:
C_CSPlayer *pPlayer = GetHudPlayer();
if ( pPlayer )
{
realHealth = MAX( pPlayer->GetHealth(), 0 );
realArmor = MAX( pPlayer->ArmorValue(), 0 );
healthPercent = ( ( float )realHealth / ( float )pPlayer->GetMaxHealth() );
// HACK (for now)
float flMaxArmor = pPlayer->HasHeavyArmor() ? 200 : 100;
armorPercent = ( ( float )realArmor / ( float )flMaxArmor );
bHasHelmet = pPlayer->HasHelmet();
bHasHeavyArmor = pPlayer->HasHeavyArmor();
}
// Updating flash, slot locking begins...
bool bSlotIsLocked = false;
char cNewStr[ 128 ];
// Update health and which color health bar to draw
if ( m_PrevHealth != realHealth )
{
LockSlot( true, bSlotIsLocked );
V_snprintf( cNewStr, sizeof( cNewStr ), "%d", realHealth );
SAFECALL( m_HealthTextHandle, m_pScaleformUI->Value_SetText( m_HealthTextHandle, cNewStr ); );
SAFECALL( m_HealthTextHandleRed, m_pScaleformUI->Value_SetText( m_HealthTextHandleRed, cNewStr ); );
bool bTurnHealthRed = false;
// if our health has decreased...
if ( realHealth < m_PrevHealth )
{
bTurnHealthRed = true;
if ( healthPercent <= g_LowHealthPercent )
{
// Turn a steady red, turn off the color restoring timer
m_HealthFlashTimer.Invalidate();
}
else
{
// Flash red briefly, set a timer to restore color later
m_HealthFlashTimer.Start( g_HealthFlashSeconds );
}
}
SAFECALL( m_HealthPanel, m_pScaleformUI->Value_SetVisible( m_HealthPanel, !( healthPercent <= g_LowHealthPercent ) ); );
ConVarRef cl_hud_healthammo_style( "cl_hud_healthammo_style" );
SAFECALL( m_HealthPanelRed, m_pScaleformUI->Value_SetVisible( m_HealthPanelRed, cl_hud_healthammo_style.GetInt() == 0 ? ( healthPercent <= g_LowHealthPercent ) : false ); );
SAFECALL( m_HealthPanelRedSmall, m_pScaleformUI->Value_SetVisible( m_HealthPanelRedSmall, cl_hud_healthammo_style.GetInt( ) == 1 ? ( healthPercent <= g_LowHealthPercent ) : false ); );
SAFECALL( m_HealthBarHandle, m_pScaleformUI->Value_SetVisible( m_HealthBarHandle, !bTurnHealthRed ); );
SAFECALL( m_HealthRedBarHandle, m_pScaleformUI->Value_SetVisible( m_HealthRedBarHandle, bTurnHealthRed ); );
SAFECALL( m_HealthTextHandle, m_pScaleformUI->Value_SetVisible( m_HealthTextHandle, !bTurnHealthRed ); );
SAFECALL( m_HealthTextHandleRed, m_pScaleformUI->Value_SetVisible( m_HealthTextHandleRed, bTurnHealthRed ); );
}
// When timer elapses, restore the standard health bar color
if ( m_HealthFlashTimer.HasStarted() && m_HealthFlashTimer.IsElapsed() )
{
LockSlot( true, bSlotIsLocked );
m_HealthFlashTimer.Invalidate();
SAFECALL( m_HealthBarHandle, m_pScaleformUI->Value_SetVisible( m_HealthBarHandle, true ); );
SAFECALL( m_HealthRedBarHandle, m_pScaleformUI->Value_SetVisible( m_HealthRedBarHandle, false ); );
SAFECALL( m_HealthTextHandle, m_pScaleformUI->Value_SetVisible( m_HealthTextHandle, true ); );
SAFECALL( m_HealthTextHandleRed, m_pScaleformUI->Value_SetVisible( m_HealthTextHandleRed, false ); );
}
// Update armor display
// $TODO: update the icon to reflect the type of armor, per design?
if ( m_PrevArmor != realArmor )
{
LockSlot( true, bSlotIsLocked );
V_snprintf( cNewStr, sizeof( cNewStr ), "%d", realArmor);
SAFECALL( m_ArmorTextHandle, m_pScaleformUI->Value_SetText( m_ArmorTextHandle, cNewStr ); );
}
// Update the health/armor bar lengths
if ( ( m_PrevHealth != realHealth ) ||
( m_PrevArmor != realArmor ) ||
( m_PrevHasHelmet != bHasHelmet ) ||
( m_PrevHasHeavyArmor != bHasHeavyArmor ) )
{
if ( FlashAPIIsValid() )
{
LockSlot( true, bSlotIsLocked );
WITH_SFVALUEARRAY( data, 6 )
{
m_pScaleformUI->ValueArray_SetElement( data, 0, realHealth );
m_pScaleformUI->ValueArray_SetElement( data, 1, clamp( int(healthPercent*100), 1, 100 ) );
m_pScaleformUI->ValueArray_SetElement( data, 2, clamp( realArmor, 1, 100 ) );
m_pScaleformUI->ValueArray_SetElement( data, 3, clamp( int(armorPercent*100), 1, 100 ) );
m_pScaleformUI->ValueArray_SetElement( data, 4, bHasHelmet );
m_pScaleformUI->ValueArray_SetElement( data, 5, bHasHeavyArmor );
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "updateValues", data, 6 );
}
}
}
m_PrevHealth = realHealth;
m_PrevArmor = realArmor;
m_PrevHasHelmet = bHasHelmet;
m_PrevHasHeavyArmor = bHasHeavyArmor;
LockSlot( false, bSlotIsLocked );
}
static void GetTextBoxForElement( IScaleformUI *pScaleformUI, SFVALUE root, const char *elementName, const char *textElementName, SFVALUE &sfv )
{
SFVALUE TempHandle = pScaleformUI->Value_GetMember( root, elementName );
if ( TempHandle )
{
sfv = pScaleformUI->Value_GetMember( TempHandle, textElementName );
pScaleformUI->ReleaseValue( TempHandle );
}
}
void SFHudHealthArmorPanel::FlashReady( void )
{
m_PanelHandle = m_pScaleformUI->Value_GetMember( m_FlashAPI, "HudPanel" );
if ( m_PanelHandle )
{
SFVALUE AnimatedPanelHandle = m_pScaleformUI->Value_GetMember( m_PanelHandle, "HealthArmorPanel" );
if ( AnimatedPanelHandle )
{
GetTextBoxForElement( m_pScaleformUI, AnimatedPanelHandle, "Armor", "TextBox", m_ArmorTextHandle );
GetTextBoxForElement( m_pScaleformUI, AnimatedPanelHandle, "Health", "TextBox", m_HealthTextHandle );
GetTextBoxForElement( m_pScaleformUI, AnimatedPanelHandle, "HealthRed", "TextBox", m_HealthTextHandleRed );
m_HealthPanel = m_pScaleformUI->Value_GetMember( AnimatedPanelHandle, "HealthPanel" );
m_HealthPanelRed = m_pScaleformUI->Value_GetMember( AnimatedPanelHandle, "HealthPanelRed" );
m_HealthPanelRedSmall = m_pScaleformUI->Value_GetMember( AnimatedPanelHandle, "HealthPanelRed_small" );
SAFECALL( m_HealthPanelRed, m_pScaleformUI->Value_SetVisible( m_HealthPanelRed, false ); );
SAFECALL( m_HealthPanelRedSmall, m_pScaleformUI->Value_SetVisible( m_HealthPanelRedSmall, false ); );
SFVALUE HealthPanelHandle = m_pScaleformUI->Value_GetMember( AnimatedPanelHandle, "HealthBar" );
if ( HealthPanelHandle )
{
m_HealthBarHandle = m_pScaleformUI->Value_GetMember( HealthPanelHandle, "HealthBar" );
m_HealthRedBarHandle = m_pScaleformUI->Value_GetMember( HealthPanelHandle, "HealthBarRed" );
SafeReleaseSFVALUE( HealthPanelHandle );
}
SafeReleaseSFVALUE( AnimatedPanelHandle );
}
}
// hide everything initially
SetVisible( false );
}
bool SFHudHealthArmorPanel::PreUnloadFlash( void )
{
SafeReleaseSFVALUE( m_PanelHandle );
SafeReleaseSFVALUE( m_HealthTextHandle );
SafeReleaseSFVALUE( m_HealthTextHandleRed );
SafeReleaseSFVALUE( m_ArmorTextHandle );
SafeReleaseSFVALUE( m_HealthBarHandle );
SafeReleaseSFVALUE( m_HealthRedBarHandle );
SafeReleaseSFVALUE( m_HealthPanel );
SafeReleaseSFVALUE( m_HealthPanelRed );
SafeReleaseSFVALUE( m_HealthPanelRedSmall );
return true;
}
void SFHudHealthArmorPanel::LevelInit( void )
{
if ( !FlashAPIIsValid() )
{
SFUI_REQUEST_ELEMENT( SF_SS_SLOT( GET_ACTIVE_SPLITSCREEN_SLOT() ), g_pScaleformUI, SFHudHealthArmorPanel, this, HealthArmorModule );
}
else
{
// When initially loaded, hide this panel
SetVisible( false );
}
// Reset all transient data
m_PrevHealth = -1;
m_PrevArmor = -1;
m_PrevHasHelmet = false;
m_HealthFlashTimer.Invalidate();
}
void SFHudHealthArmorPanel::LevelShutdown( void )
{
if ( FlashAPIIsValid() )
{
RemoveFlashElement();
}
}
bool SFHudHealthArmorPanel::ShouldDraw( void )
{
return cl_drawhud.GetBool() && cl_draw_only_deathnotices.GetBool() == false && CHudElement::ShouldDraw();
}
void SFHudHealthArmorPanel::SetActive( bool bActive )
{
if ( bActive != m_bActive )
{
ShowPanel( bActive );
}
CHudElement::SetActive( bActive );
}