diff options
Diffstat (limited to 'game/client/dod/dod_hud_ammo.cpp')
| -rw-r--r-- | game/client/dod/dod_hud_ammo.cpp | 508 |
1 files changed, 508 insertions, 0 deletions
diff --git a/game/client/dod/dod_hud_ammo.cpp b/game/client/dod/dod_hud_ammo.cpp new file mode 100644 index 0000000..94b4ef0 --- /dev/null +++ b/game/client/dod/dod_hud_ammo.cpp @@ -0,0 +1,508 @@ +//========= 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; +} + |