Team Fortress 2 Source Code as on 22/4/2020
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.

334 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "hud.h"
  8. #include "hudelement.h"
  9. #include "hud_macros.h"
  10. #include "hud_numericdisplay.h"
  11. #include <KeyValues.h>
  12. #include <vgui/IScheme.h>
  13. #include <vgui/ISurface.h>
  14. #include <vgui/ISystem.h>
  15. #include <vgui_controls/AnimationController.h>
  16. #include "iclientmode.h"
  17. #include "tf_shareddefs.h"
  18. #include <vgui_controls/EditablePanel.h>
  19. #include <vgui_controls/ImagePanel.h>
  20. #include <vgui/ISurface.h>
  21. #include <vgui/IImage.h>
  22. #include <vgui_controls/Label.h>
  23. #include "tf_controls.h"
  24. #include "in_buttons.h"
  25. #include "tf_imagepanel.h"
  26. #include "c_team.h"
  27. #include "c_tf_player.h"
  28. #include "ihudlcd.h"
  29. #include "tf_hud_ammostatus.h"
  30. #include "tf_gamerules.h"
  31. #include "tf_logic_halloween_2014.h"
  32. using namespace vgui;
  33. // memdbgon must be the last include file in a .cpp file!!!
  34. #include "tier0/memdbgon.h"
  35. DECLARE_HUDELEMENT( CTFHudWeaponAmmo );
  36. static ConVar hud_low_ammo_warning_threshold( "hud_lowammowarning_threshold", "0.40", FCVAR_CLIENTDLL | FCVAR_DEVELOPMENTONLY, "Percentage threshold at which the low ammo warning will become visible." );
  37. static ConVar hud_low_ammo_warning_max_pos_adjust( "hud_lowammowarning_maxposadjust", "5", FCVAR_CLIENTDLL | FCVAR_DEVELOPMENTONLY, "Maximum pixel amount to increase the low ammo warning image." );
  38. //-----------------------------------------------------------------------------
  39. // Purpose: Constructor
  40. //-----------------------------------------------------------------------------
  41. CTFHudWeaponAmmo::CTFHudWeaponAmmo( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudWeaponAmmo" )
  42. {
  43. Panel *pParent = g_pClientMode->GetViewport();
  44. SetParent( pParent );
  45. SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_PLAYERDEAD );
  46. hudlcd->SetGlobalStat( "(ammo_primary)", "0" );
  47. hudlcd->SetGlobalStat( "(ammo_secondary)", "0" );
  48. hudlcd->SetGlobalStat( "(weapon_print_name)", "" );
  49. hudlcd->SetGlobalStat( "(weapon_name)", "" );
  50. m_pInClip = NULL;
  51. m_pInClipShadow = NULL;
  52. m_pInReserve = NULL;
  53. m_pInReserveShadow = NULL;
  54. m_pNoClip = NULL;
  55. m_pNoClipShadow = NULL;
  56. m_nAmmo = -1;
  57. m_nAmmo2 = -1;
  58. m_hCurrentActiveWeapon = NULL;
  59. m_flNextThink = 0.0f;
  60. RegisterForRenderGroup( "inspect_panel" );
  61. }
  62. //-----------------------------------------------------------------------------
  63. // Purpose:
  64. //-----------------------------------------------------------------------------
  65. void CTFHudWeaponAmmo::Reset()
  66. {
  67. m_flNextThink = gpGlobals->curtime + 0.05f;
  68. }
  69. //-----------------------------------------------------------------------------
  70. // Purpose:
  71. //-----------------------------------------------------------------------------
  72. void CTFHudWeaponAmmo::ApplySchemeSettings( IScheme *pScheme )
  73. {
  74. BaseClass::ApplySchemeSettings( pScheme );
  75. // load control settings...
  76. LoadControlSettings( "resource/UI/HudAmmoWeapons.res" );
  77. m_pInClip = dynamic_cast<CExLabel *>( FindChildByName( "AmmoInClip" ) );
  78. m_pInClipShadow = dynamic_cast<CExLabel *>( FindChildByName( "AmmoInClipShadow" ) );
  79. m_pInReserve = dynamic_cast<CExLabel *>( FindChildByName( "AmmoInReserve" ) );
  80. m_pInReserveShadow = dynamic_cast<CExLabel *>( FindChildByName( "AmmoInReserveShadow" ) );
  81. m_pNoClip = dynamic_cast<CExLabel *>( FindChildByName( "AmmoNoClip" ) );
  82. m_pNoClipShadow = dynamic_cast<CExLabel *>( FindChildByName( "AmmoNoClipShadow" ) );
  83. m_pLowAmmoImage = dynamic_cast<ImagePanel *>( FindChildByName( "HudWeaponLowAmmoImage" ) );
  84. if ( m_pLowAmmoImage )
  85. {
  86. m_pLowAmmoImage->GetBounds( m_nLowAmmoImageOrigX, m_nLowAmmoImageOrigY, m_nLowAmmoImageOrigW, m_nLowAmmoImageOrigH );
  87. }
  88. m_nAmmo = -1;
  89. m_nAmmo2 = -1;
  90. m_hCurrentActiveWeapon = NULL;
  91. m_flNextThink = 0.0f;
  92. UpdateAmmoLabels( false, false, false );
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Purpose:
  96. //-----------------------------------------------------------------------------
  97. bool CTFHudWeaponAmmo::ShouldDraw( void )
  98. {
  99. // Get the player and active weapon.
  100. C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
  101. if ( !pPlayer )
  102. {
  103. return false;
  104. }
  105. CTFWeaponBase *pWeapon = pPlayer->GetActiveTFWeapon();
  106. if ( !pWeapon )
  107. {
  108. return false;
  109. }
  110. if ( pWeapon->GetWeaponID() == TF_WEAPON_MEDIGUN )
  111. {
  112. return false;
  113. }
  114. // Don't show for weapons that don't use any ammo
  115. if ( !pWeapon->UsesPrimaryAmmo() )
  116. return false;
  117. // Don't show for weapons that use metal for their primary ammo
  118. if ( pWeapon->GetPrimaryAmmoType() == TF_AMMO_METAL )
  119. return false;
  120. if ( pWeapon->UberChargeAmmoPerShot() > 0.0f )
  121. return false;
  122. if ( pPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_GHOST_MODE ) )
  123. return false;
  124. if ( CTFMinigameLogic::GetMinigameLogic() && CTFMinigameLogic::GetMinigameLogic()->GetActiveMinigame() )
  125. return false;
  126. if ( TFGameRules() && TFGameRules()->ShowMatchSummary() )
  127. return false;
  128. return CHudElement::ShouldDraw();
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Purpose:
  132. //-----------------------------------------------------------------------------
  133. void CTFHudWeaponAmmo::UpdateAmmoLabels( bool bPrimary, bool bReserve, bool bNoClip )
  134. {
  135. if ( m_pInClip && m_pInClipShadow )
  136. {
  137. if ( m_pInClip->IsVisible() != bPrimary )
  138. {
  139. m_pInClip->SetVisible( bPrimary );
  140. m_pInClipShadow->SetVisible( bPrimary );
  141. }
  142. }
  143. if ( m_pInReserve && m_pInReserveShadow )
  144. {
  145. if ( m_pInReserve->IsVisible() != bReserve )
  146. {
  147. m_pInReserve->SetVisible( bReserve );
  148. m_pInReserveShadow->SetVisible( bReserve );
  149. }
  150. }
  151. if ( m_pNoClip && m_pNoClipShadow )
  152. {
  153. if ( m_pNoClip->IsVisible() != bNoClip )
  154. {
  155. m_pNoClip->SetVisible( bNoClip );
  156. m_pNoClipShadow->SetVisible( bNoClip );
  157. }
  158. }
  159. }
  160. //-----------------------------------------------------------------------------
  161. // Purpose:
  162. //-----------------------------------------------------------------------------
  163. void CTFHudWeaponAmmo::ShowLowAmmoIndicator( void )
  164. {
  165. if ( m_pLowAmmoImage && m_pLowAmmoImage->IsVisible() == false )
  166. {
  167. m_pLowAmmoImage->SetBounds( m_nLowAmmoImageOrigX, m_nLowAmmoImageOrigY, m_nLowAmmoImageOrigW, m_nLowAmmoImageOrigH );
  168. m_pLowAmmoImage->SetVisible( true );
  169. m_pLowAmmoImage->SetFgColor( Color( 255, 0, 0, 255 ) );
  170. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudLowAmmoPulse" );
  171. }
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Purpose:
  175. //-----------------------------------------------------------------------------
  176. void CTFHudWeaponAmmo::SizeLowAmmoIndicator( float flCurrentAmount, float flMaxAmount )
  177. {
  178. if ( m_pLowAmmoImage && m_pLowAmmoImage->IsVisible() == true )
  179. {
  180. float flPercent = ( flMaxAmount - flCurrentAmount ) / flMaxAmount;
  181. float nLowAmmoPosAdj = hud_low_ammo_warning_max_pos_adjust.GetFloat();
  182. int nPosAdj = RoundFloatToInt( flPercent * nLowAmmoPosAdj );
  183. int nSizeAdj = 2 * nPosAdj;
  184. m_pLowAmmoImage->SetBounds( m_nLowAmmoImageOrigX - nPosAdj,
  185. m_nLowAmmoImageOrigY - nPosAdj,
  186. m_nLowAmmoImageOrigW + nSizeAdj,
  187. m_nLowAmmoImageOrigH + nSizeAdj );
  188. }
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Purpose:
  192. //-----------------------------------------------------------------------------
  193. void CTFHudWeaponAmmo::HideLowAmmoIndicator( void )
  194. {
  195. if ( m_pLowAmmoImage && m_pLowAmmoImage->IsVisible() == true )
  196. {
  197. m_pLowAmmoImage->SetBounds( m_nLowAmmoImageOrigX, m_nLowAmmoImageOrigY, m_nLowAmmoImageOrigW, m_nLowAmmoImageOrigH );
  198. m_pLowAmmoImage->SetVisible( false );
  199. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudLowAmmoPulseStop" );
  200. }
  201. }
  202. //-----------------------------------------------------------------------------
  203. // Purpose: Get ammo info from the weapon and update the displays.
  204. //-----------------------------------------------------------------------------
  205. void CTFHudWeaponAmmo::OnThink()
  206. {
  207. // Get the player and active weapon.
  208. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  209. C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
  210. if ( m_flNextThink < gpGlobals->curtime )
  211. {
  212. hudlcd->SetGlobalStat( "(weapon_print_name)", pWeapon ? pWeapon->GetPrintName() : " " );
  213. hudlcd->SetGlobalStat( "(weapon_name)", pWeapon ? pWeapon->GetName() : " " );
  214. if ( !pPlayer || !pWeapon || !pWeapon->UsesPrimaryAmmo() )
  215. {
  216. hudlcd->SetGlobalStat( "(ammo_primary)", "n/a" );
  217. hudlcd->SetGlobalStat( "(ammo_secondary)", "n/a" );
  218. // turn off our ammo counts
  219. UpdateAmmoLabels( false, false, false );
  220. // hide low ammo indicator since it is not applicable
  221. HideLowAmmoIndicator();
  222. m_nAmmo = -1;
  223. m_nAmmo2 = -1;
  224. }
  225. else
  226. {
  227. // Get the ammo in our clip.
  228. int nAmmo1 = pWeapon->Clip1();
  229. int nAmmo2 = 0;
  230. // Clip ammo not used, get total ammo count.
  231. if ( nAmmo1 < 0 )
  232. {
  233. nAmmo1 = pPlayer->GetAmmoCount( pWeapon->GetPrimaryAmmoType() );
  234. }
  235. // Clip ammo, so the second ammo is the total ammo.
  236. else
  237. {
  238. nAmmo2 = pPlayer->GetAmmoCount( pWeapon->GetPrimaryAmmoType() );
  239. }
  240. hudlcd->SetGlobalStat( "(ammo_primary)", VarArgs( "%d", nAmmo1 ) );
  241. hudlcd->SetGlobalStat( "(ammo_secondary)", VarArgs( "%d", nAmmo2 ) );
  242. if ( m_nAmmo != nAmmo1 || m_nAmmo2 != nAmmo2 || m_hCurrentActiveWeapon.Get() != pWeapon )
  243. {
  244. m_nAmmo = nAmmo1;
  245. m_nAmmo2 = nAmmo2;
  246. m_hCurrentActiveWeapon = pWeapon;
  247. if ( m_hCurrentActiveWeapon.Get()->UsesClipsForAmmo1() )
  248. {
  249. UpdateAmmoLabels( true, true, false );
  250. SetDialogVariable( "Ammo", m_nAmmo );
  251. SetDialogVariable( "AmmoInReserve", m_nAmmo2 );
  252. }
  253. else
  254. {
  255. UpdateAmmoLabels( false, false, true );
  256. SetDialogVariable( "Ammo", m_nAmmo );
  257. }
  258. }
  259. // low ammo warning
  260. int nTotalAmmo = nAmmo1 + nAmmo2;
  261. int nMaxTotalAmmo = ((CTFPlayer*)pPlayer)->GetMaxAmmo( pWeapon->GetPrimaryAmmoType() );
  262. // include ammount in the current clip as well
  263. if ( pWeapon->GetMaxClip1() > 0 )
  264. {
  265. nMaxTotalAmmo += pWeapon->GetMaxClip1();
  266. }
  267. float flWarningAmmoThreshold = (float)nMaxTotalAmmo * hud_low_ammo_warning_threshold.GetFloat();
  268. if ( nTotalAmmo < RoundFloatToInt( flWarningAmmoThreshold ) )
  269. {
  270. ShowLowAmmoIndicator();
  271. SizeLowAmmoIndicator( (float)nTotalAmmo, flWarningAmmoThreshold );
  272. }
  273. else
  274. {
  275. HideLowAmmoIndicator();
  276. }
  277. }
  278. m_flNextThink = gpGlobals->curtime + 0.1f;
  279. }
  280. }