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.
508 lines
13 KiB
508 lines
13 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "hud.h" |
|
#include "hudelement.h" |
|
#include "hud_macros.h" |
|
#include "hud_bitmapnumericdisplay.h" |
|
#include "iclientmode.h" |
|
#include "c_dod_player.h" |
|
#include "ihudlcd.h" |
|
|
|
#include <vgui/ISurface.h> |
|
#include <vgui_controls/AnimationController.h> |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Displays current ammunition level |
|
//----------------------------------------------------------------------------- |
|
class CHudAmmo : public CHudElement, public vgui::Panel |
|
{ |
|
DECLARE_CLASS_SIMPLE( CHudAmmo, vgui::Panel ); |
|
|
|
public: |
|
CHudAmmo( const char *pElementName ); |
|
void Init( void ); |
|
void VidInit( void ); |
|
|
|
void SetAmmo(int ammo, bool playAnimation); |
|
void SetAmmo2(int ammo2, bool playAnimation); |
|
|
|
protected: |
|
virtual void OnThink(); |
|
virtual void Paint( void ); |
|
virtual void ApplySchemeSettings(vgui::IScheme *pScheme); |
|
|
|
private: |
|
void DrawText( char *text, int x, int y, Color clrText ); |
|
void DrawNumbers( int num, int x, int y ); |
|
|
|
void PaintGrenadeAmmo( CWeaponDODBase *pWpn ); |
|
void PaintBazookaAmmo( CWeaponDODBase *pWpn ); |
|
void PaintMGAmmo( CWeaponDODBase *pWpn ); |
|
void PaintGunAmmo( CWeaponDODBase *pWpn ); |
|
void PaintRifleGrenadeAmmo( CWeaponDODBase *pWpn ); |
|
|
|
CHandle< C_BaseCombatWeapon > m_hCurrentActiveWeapon; |
|
int m_iAmmo; |
|
int m_iAmmo2; |
|
|
|
bool m_bUsesClips; |
|
|
|
int m_iAdditiveWhiteID; |
|
|
|
CPanelAnimationVarAliasType( float, digit2_xpos, "digit2_xpos", "0", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, digit2_ypos, "digit2_ypos", "0", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, bar_xpos, "bar_xpos", "0", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, bar_ypos, "bar_ypos", "0", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, bar_width, "bar_width", "2", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, bar_height, "bar_height", "2", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, icon_xpos, "icon_xpos", "0", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, icon_ypos, "icon_ypos", "0", "proportional_float" ); |
|
|
|
CPanelAnimationVar( vgui::HFont, m_hNumberFont, "NumberFont", "HudSelectionNumbers" ); |
|
|
|
Color m_clrIcon; |
|
|
|
CHudTexture *m_pMGNumbers[10]; |
|
}; |
|
|
|
//DECLARE_HUDELEMENT( CHudAmmo ); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
CHudAmmo::CHudAmmo( const char *pElementName ) : vgui::Panel( NULL, "HudAmmo" ), CHudElement( pElementName ) |
|
{ |
|
SetParent( g_pClientMode->GetViewport() ); |
|
|
|
m_iAdditiveWhiteID = vgui::surface()->CreateNewTextureID(); |
|
vgui::surface()->DrawSetTextureFile( m_iAdditiveWhiteID, "vgui/white_additive" , true, false); |
|
|
|
SetActive( true ); |
|
|
|
m_clrIcon = Color(255,255,255,255); |
|
|
|
SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_PLAYERDEAD | HIDEHUD_WEAPONSELECTION ); |
|
|
|
hudlcd->SetGlobalStat( "(ammo_primary)", "0" ); |
|
hudlcd->SetGlobalStat( "(ammo_secondary)", "0" ); |
|
hudlcd->SetGlobalStat( "(weapon_print_name)", "" ); |
|
hudlcd->SetGlobalStat( "(weapon_name)", "" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CHudAmmo::Init( void ) |
|
{ |
|
m_iAmmo = -1; |
|
m_iAmmo2 = -1; |
|
} |
|
|
|
void CHudAmmo::ApplySchemeSettings(vgui::IScheme *pScheme) |
|
{ |
|
BaseClass::ApplySchemeSettings(pScheme); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CHudAmmo::VidInit( void ) |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: called every frame to get ammo info from the weapon |
|
//----------------------------------------------------------------------------- |
|
void CHudAmmo::OnThink() |
|
{ |
|
C_BaseCombatWeapon *wpn = GetActiveWeapon(); |
|
|
|
hudlcd->SetGlobalStat( "(weapon_print_name)", wpn ? wpn->GetPrintName() : " " ); |
|
hudlcd->SetGlobalStat( "(weapon_name)", wpn ? wpn->GetName() : " " ); |
|
|
|
C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); |
|
if (!wpn || !player || !wpn->UsesPrimaryAmmo()) |
|
{ |
|
hudlcd->SetGlobalStat( "(ammo_primary)", "n/a" ); |
|
hudlcd->SetGlobalStat( "(ammo_secondary)", "n/a" ); |
|
|
|
SetPaintEnabled(false); |
|
SetPaintBackgroundEnabled(false); |
|
return; |
|
} |
|
else |
|
{ |
|
SetPaintEnabled(true); |
|
SetPaintBackgroundEnabled(true); |
|
} |
|
|
|
// get the ammo in our clip |
|
int ammo1 = wpn->Clip1(); |
|
int ammo2; |
|
if (ammo1 < 0) |
|
{ |
|
// we don't use clip ammo, just use the total ammo count |
|
ammo1 = player->GetAmmoCount(wpn->GetPrimaryAmmoType()); |
|
ammo2 = 0; |
|
} |
|
else |
|
{ |
|
// we use clip ammo, so the second ammo is the total ammo |
|
ammo2 = player->GetAmmoCount(wpn->GetPrimaryAmmoType()); |
|
} |
|
|
|
hudlcd->SetGlobalStat( "(ammo_primary)", VarArgs( "%d", ammo1 ) ); |
|
hudlcd->SetGlobalStat( "(ammo_secondary)", VarArgs( "%d", ammo2 ) ); |
|
|
|
if (wpn == m_hCurrentActiveWeapon) |
|
{ |
|
// same weapon, just update counts |
|
SetAmmo(ammo1, true); |
|
SetAmmo2(ammo2, true); |
|
} |
|
else |
|
{ |
|
// diferent weapon, change without triggering |
|
SetAmmo(ammo1, false); |
|
SetAmmo2(ammo2, false); |
|
|
|
// update whether or not we show the total ammo display |
|
if (wpn->UsesClipsForAmmo1()) |
|
{ |
|
m_bUsesClips = true; |
|
|
|
} |
|
else |
|
{ |
|
m_bUsesClips = false; |
|
} |
|
|
|
m_hCurrentActiveWeapon = wpn; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Updates ammo display |
|
//----------------------------------------------------------------------------- |
|
void CHudAmmo::SetAmmo(int ammo, bool playAnimation) |
|
{ |
|
if (ammo != m_iAmmo) |
|
{ |
|
m_iAmmo = ammo; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Updates 2nd ammo display |
|
//----------------------------------------------------------------------------- |
|
void CHudAmmo::SetAmmo2(int ammo2, bool playAnimation) |
|
{ |
|
if (ammo2 != m_iAmmo2) |
|
{ |
|
m_iAmmo2 = ammo2; |
|
} |
|
} |
|
|
|
void CHudAmmo::PaintGrenadeAmmo( CWeaponDODBase *pWpn ) |
|
{ |
|
const CHudTexture *pAmmoIcon = pWpn->GetSpriteAmmo(); |
|
|
|
Assert( pAmmoIcon ); |
|
|
|
int x,y,w,h; |
|
GetBounds( x, y, w, h ); |
|
|
|
if (m_iAmmo > 0 && pAmmoIcon ) |
|
{ |
|
int xpos = w - 2 * pAmmoIcon->Width(); |
|
int ypos = h - pAmmoIcon->Height(); |
|
|
|
pAmmoIcon->DrawSelf( xpos, ypos, pAmmoIcon->Width(), pAmmoIcon->Height(), m_clrIcon ); |
|
|
|
char buf[16]; |
|
Q_snprintf( buf, sizeof(buf), "x %d", m_iAmmo ); |
|
|
|
DrawText( buf, xpos + pAmmoIcon->Width(), ypos + pAmmoIcon->Height() / 2, m_clrIcon ); |
|
} |
|
} |
|
|
|
void CHudAmmo::PaintRifleGrenadeAmmo( CWeaponDODBase *pWpn ) |
|
{ |
|
const CHudTexture *pAmmoIcon = pWpn->GetSpriteAmmo(); |
|
|
|
Assert( pAmmoIcon ); |
|
|
|
int x,y,w,h; |
|
GetBounds( x, y, w, h ); |
|
|
|
int ammo = m_iAmmo + m_iAmmo2; |
|
|
|
if (ammo > 0 && pAmmoIcon ) |
|
{ |
|
int xpos = w - 2 * pAmmoIcon->Width(); |
|
int ypos = h - pAmmoIcon->Height(); |
|
|
|
pAmmoIcon->DrawSelf( xpos, ypos, pAmmoIcon->Width(), pAmmoIcon->Height(), m_clrIcon ); |
|
|
|
char buf[16]; |
|
Q_snprintf( buf, sizeof(buf), "x %d", ammo ); |
|
|
|
DrawText( buf, xpos + pAmmoIcon->Width(), ypos + pAmmoIcon->Height() / 2, m_clrIcon ); |
|
} |
|
} |
|
|
|
void CHudAmmo::PaintBazookaAmmo( CWeaponDODBase *pWpn ) |
|
{ |
|
const CHudTexture *pTubeIcon = pWpn->GetSpriteAmmo2(); |
|
const CHudTexture *pRocketIcon = pWpn->GetSpriteAmmo(); |
|
const CHudTexture *pExtraIcon = pWpn->GetSpriteAutoaim(); |
|
|
|
Assert( pTubeIcon ); |
|
Assert( pRocketIcon ); |
|
Assert( pExtraIcon ); |
|
|
|
int xpos = 0; |
|
int ypos = 0; |
|
|
|
int x, y, w, h; |
|
GetBounds(x,y,w,h); |
|
|
|
//Draw the rocket tube |
|
if( pTubeIcon ) |
|
{ |
|
xpos = w - 2 * pTubeIcon->Width(); |
|
ypos = h - pTubeIcon->Height(); |
|
pTubeIcon->DrawSelf( xpos, ypos, m_clrIcon ); |
|
} |
|
|
|
//If our clip is full, draw the rocket |
|
if( pRocketIcon ) |
|
{ |
|
if( m_iAmmo > 0 ) |
|
pRocketIcon->DrawSelf( xpos, ypos, m_clrIcon ); |
|
|
|
xpos += pRocketIcon->Width() + 10; |
|
ypos += pRocketIcon->Height(); |
|
} |
|
|
|
char buf[16]; |
|
Q_snprintf( buf, sizeof(buf), "%d %d", m_iAmmo, m_iAmmo2 ); |
|
DrawText( buf, xpos, ypos, m_clrIcon ); |
|
|
|
//Draw the extra rockets |
|
if( m_iAmmo2 > 0 && pExtraIcon ) |
|
{ |
|
ypos -= pExtraIcon->Height(); |
|
|
|
pExtraIcon->DrawSelf( xpos, ypos, m_clrIcon ); |
|
|
|
xpos += pExtraIcon->Width(); |
|
|
|
char buf[16]; |
|
Q_snprintf( buf, sizeof(buf), "x %d", m_iAmmo2 ); |
|
DrawText( buf, xpos, ypos + ( pExtraIcon->Height() * 0.75 ), m_clrIcon ); |
|
} |
|
} |
|
|
|
void CHudAmmo::PaintMGAmmo( CWeaponDODBase *pWpn ) |
|
{ |
|
const CHudTexture *pFullClip = pWpn->GetSpriteAmmo(); |
|
const CHudTexture *pExtraClip = pWpn->GetSpriteAmmo2(); |
|
|
|
int xpos = 0; |
|
int ypos = 0; |
|
|
|
int x, y, w, h; |
|
GetBounds(x,y,w,h); |
|
|
|
if( pFullClip ) |
|
{ |
|
xpos = w - pFullClip->Width() * 3; |
|
ypos = h - pFullClip->Height(); |
|
pFullClip->DrawSelf( xpos, ypos, m_clrIcon ); |
|
|
|
//Haxoration! The box that contains the numbers must be in the same position |
|
// in both the webley and mg34/mg42/30cal sprites. |
|
DrawNumbers( m_iAmmo, xpos + 36, ypos + pFullClip->Height() - 16 ); |
|
|
|
xpos += pFullClip->Width(); |
|
ypos += pFullClip->Height(); |
|
} |
|
|
|
//how many full or partially full clips do we have? |
|
int clips = m_iAmmo2 / pWpn->GetMaxClip1(); |
|
|
|
//account for the partial clip, if it exists |
|
if( clips * pWpn->GetMaxClip1() < m_iAmmo2 ) |
|
clips++; |
|
|
|
if( pExtraClip && clips > 0 ) |
|
{ |
|
ypos -= pExtraClip->Height(); |
|
|
|
pExtraClip->DrawSelf( xpos, ypos, m_clrIcon ); |
|
|
|
char buf[16]; |
|
Q_snprintf( buf, sizeof(buf), "x %d", clips ); |
|
DrawText( buf, xpos + pExtraClip->Width(), ypos + pExtraClip->Height() / 2, m_clrIcon ); |
|
} |
|
} |
|
|
|
void CHudAmmo::PaintGunAmmo( CWeaponDODBase *pWpn ) |
|
{ |
|
//regular gun |
|
const CHudTexture *pEmptyClip = pWpn->GetSpriteAmmo(); |
|
const CHudTexture *pFullClip = pWpn->GetSpriteAmmo2(); |
|
const CHudTexture *pExtraClip = pWpn->GetSpriteAutoaim(); |
|
|
|
Assert( pEmptyClip ); |
|
Assert( pFullClip ); |
|
Assert( pExtraClip ); |
|
|
|
int x, y, w, h; |
|
GetBounds( x, y, w, h ); |
|
|
|
int xpos = 0; |
|
int ypos = 0; |
|
|
|
if( pFullClip ) |
|
{ |
|
xpos = w - 3 * pFullClip->Width(); |
|
ypos = h - pFullClip->Height() * 1.2; |
|
|
|
//Always draw the empty clip |
|
pFullClip->DrawSelf( xpos, ypos, Color(255,255,255,255) ); |
|
} |
|
|
|
if( pEmptyClip ) |
|
{ |
|
// base percent is how much of the bullet clip to always draw. |
|
// total cropped height of the bullet sprite will be |
|
// base percent + bullet height * bullets |
|
float flBasePercent = (float)pWpn->GetDODWpnData().m_iHudClipBaseHeight / (float)pWpn->GetDODWpnData().m_iHudClipHeight; |
|
float flBulletHeightPercent = (float)pWpn->GetDODWpnData().m_iHudClipBulletHeight / (float)pWpn->GetDODWpnData().m_iHudClipHeight; |
|
|
|
float flHeight = (float)pEmptyClip->Height(); |
|
|
|
//Now we draw the bullets inside based on how full our clip is |
|
float flDrawHeight = flHeight * ( 1.0 - ( flBasePercent + flBulletHeightPercent * m_iAmmo ) ); |
|
|
|
int nOffset = (int)flDrawHeight; |
|
|
|
pEmptyClip->DrawSelfCropped( xpos, ypos + nOffset, 0, nOffset, pEmptyClip->Width(), pEmptyClip->Height() - nOffset, Color(255,255,255,255) ); |
|
|
|
ypos += pEmptyClip->Height(); |
|
|
|
xpos += pEmptyClip->Width() + 10; |
|
} |
|
|
|
//how many full or partially full clips do we have? |
|
int clips = m_iAmmo2 / pWpn->GetMaxClip1(); |
|
|
|
//account for the partial clip, if it exists |
|
if( clips * pWpn->GetMaxClip1() < m_iAmmo2 ) |
|
clips++; |
|
|
|
if( pExtraClip && clips > 0 ) |
|
{ |
|
//align the extra clip on the same baseline as the large clip |
|
ypos -= pExtraClip->Height(); |
|
|
|
pExtraClip->DrawSelf( xpos, ypos, Color(255,255,255,255) ); |
|
|
|
char buf[16]; |
|
Q_snprintf( buf, sizeof(buf), "x %d", clips ); |
|
DrawText( buf, xpos + pExtraClip->Width(), ypos + pExtraClip->Height() / 2, m_clrIcon ); |
|
} |
|
} |
|
|
|
void CHudAmmo::Paint( void ) |
|
{ |
|
C_DODPlayer *pPlayer = C_DODPlayer::GetLocalDODPlayer(); |
|
|
|
if( !pPlayer ) |
|
return; |
|
|
|
CWeaponDODBase *pWpn = pPlayer->GetActiveDODWeapon(); |
|
|
|
if( !pWpn ) |
|
return; |
|
|
|
switch( pWpn->GetDODWpnData().m_WeaponType ) |
|
{ |
|
case WPN_TYPE_GRENADE: |
|
PaintGrenadeAmmo(pWpn); |
|
break; |
|
|
|
case WPN_TYPE_RIFLEGRENADE: |
|
PaintRifleGrenadeAmmo(pWpn); |
|
break; |
|
|
|
case WPN_TYPE_BAZOOKA: |
|
PaintBazookaAmmo(pWpn); |
|
break; |
|
|
|
case WPN_TYPE_MG: |
|
PaintMGAmmo(pWpn); |
|
break; |
|
|
|
default: |
|
PaintGunAmmo(pWpn); |
|
break; |
|
} |
|
} |
|
|
|
void CHudAmmo::DrawText( char *text, int x, int y, Color clrText ) |
|
{ |
|
vgui::surface()->DrawSetTextColor( clrText ); |
|
vgui::surface()->DrawSetTextFont( m_hNumberFont ); |
|
vgui::surface()->DrawSetTextPos( x, y ); |
|
|
|
for (char *pch = text; *pch != 0; pch++) |
|
{ |
|
vgui::surface()->DrawUnicodeChar(*pch); |
|
} |
|
} |
|
|
|
void CHudAmmo::DrawNumbers( int num, int x, int y ) |
|
{ |
|
if( !m_pMGNumbers[0] ) |
|
{ |
|
int i; |
|
for( i=0;i<10;i++ ) |
|
{ |
|
char buf[8]; |
|
Q_snprintf( buf, sizeof(buf), "mg_%d", i ); |
|
m_pMGNumbers[i] = gHUD.GetIcon( buf ); |
|
} |
|
} |
|
|
|
Assert( num < 1000 ); |
|
|
|
int xpos = x; |
|
int ypos = y; |
|
int num_working = num; |
|
|
|
int iconWidth = m_pMGNumbers[0]->Width(); |
|
|
|
int hundreds = num_working / 100; |
|
num_working -= hundreds * 100; |
|
|
|
m_pMGNumbers[hundreds]->DrawSelf( xpos, ypos, m_clrIcon ); |
|
xpos += iconWidth; |
|
|
|
int tens = num_working / 10; |
|
num_working -= tens * 10; |
|
|
|
m_pMGNumbers[tens]->DrawSelf( xpos, ypos, m_clrIcon ); |
|
xpos += iconWidth; |
|
|
|
m_pMGNumbers[num_working]->DrawSelf( xpos, ypos, m_clrIcon ); |
|
xpos += iconWidth; |
|
} |
|
|
|
|