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.

502 lines
13 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 "iclientmode.h"
  12. #include "iclientvehicle.h"
  13. #include <vgui_controls/AnimationController.h>
  14. #include <vgui/ILocalize.h>
  15. #include <vgui/ISurface.h>
  16. #include "ihudlcd.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. using namespace vgui;
  20. //-----------------------------------------------------------------------------
  21. // Purpose: Displays current ammunition level
  22. //-----------------------------------------------------------------------------
  23. class CHudAmmo : public CHudNumericDisplay, public CHudElement
  24. {
  25. DECLARE_CLASS_SIMPLE( CHudAmmo, CHudNumericDisplay );
  26. public:
  27. CHudAmmo( const char *pElementName );
  28. void Init( void );
  29. void VidInit( void );
  30. void Reset();
  31. void SetAmmo(int ammo, bool playAnimation);
  32. void SetAmmo2(int ammo2, bool playAnimation);
  33. virtual void Paint( void );
  34. protected:
  35. virtual void OnThink();
  36. void UpdateAmmoDisplays();
  37. void UpdatePlayerAmmo( C_BasePlayer *player );
  38. void UpdateVehicleAmmo( C_BasePlayer *player, IClientVehicle *pVehicle );
  39. private:
  40. CHandle< C_BaseCombatWeapon > m_hCurrentActiveWeapon;
  41. CHandle< C_BaseEntity > m_hCurrentVehicle;
  42. int m_iAmmo;
  43. int m_iAmmo2;
  44. CHudTexture *m_iconPrimaryAmmo;
  45. };
  46. DECLARE_HUDELEMENT( CHudAmmo );
  47. //-----------------------------------------------------------------------------
  48. // Purpose: Constructor
  49. //-----------------------------------------------------------------------------
  50. CHudAmmo::CHudAmmo( const char *pElementName ) : BaseClass(NULL, "HudAmmo"), CHudElement( pElementName )
  51. {
  52. SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_PLAYERDEAD | HIDEHUD_NEEDSUIT | HIDEHUD_WEAPONSELECTION );
  53. hudlcd->SetGlobalStat( "(ammo_primary)", "0" );
  54. hudlcd->SetGlobalStat( "(ammo_secondary)", "0" );
  55. hudlcd->SetGlobalStat( "(weapon_print_name)", "" );
  56. hudlcd->SetGlobalStat( "(weapon_name)", "" );
  57. }
  58. //-----------------------------------------------------------------------------
  59. // Purpose:
  60. //-----------------------------------------------------------------------------
  61. void CHudAmmo::Init( void )
  62. {
  63. m_iAmmo = -1;
  64. m_iAmmo2 = -1;
  65. m_iconPrimaryAmmo = NULL;
  66. wchar_t *tempString = g_pVGuiLocalize->Find("#Valve_Hud_AMMO");
  67. if (tempString)
  68. {
  69. SetLabelText(tempString);
  70. }
  71. else
  72. {
  73. SetLabelText(L"AMMO");
  74. }
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Purpose:
  78. //-----------------------------------------------------------------------------
  79. void CHudAmmo::VidInit( void )
  80. {
  81. }
  82. //-----------------------------------------------------------------------------
  83. // Purpose: Resets hud after save/restore
  84. //-----------------------------------------------------------------------------
  85. void CHudAmmo::Reset()
  86. {
  87. BaseClass::Reset();
  88. m_hCurrentActiveWeapon = NULL;
  89. m_hCurrentVehicle = NULL;
  90. m_iAmmo = 0;
  91. m_iAmmo2 = 0;
  92. UpdateAmmoDisplays();
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Purpose: called every frame to get ammo info from the weapon
  96. //-----------------------------------------------------------------------------
  97. void CHudAmmo::UpdatePlayerAmmo( C_BasePlayer *player )
  98. {
  99. // Clear out the vehicle entity
  100. m_hCurrentVehicle = NULL;
  101. C_BaseCombatWeapon *wpn = GetActiveWeapon();
  102. hudlcd->SetGlobalStat( "(weapon_print_name)", wpn ? wpn->GetPrintName() : " " );
  103. hudlcd->SetGlobalStat( "(weapon_name)", wpn ? wpn->GetName() : " " );
  104. if ( !wpn || !player || !wpn->UsesPrimaryAmmo() )
  105. {
  106. hudlcd->SetGlobalStat( "(ammo_primary)", "n/a" );
  107. hudlcd->SetGlobalStat( "(ammo_secondary)", "n/a" );
  108. SetPaintEnabled(false);
  109. SetPaintBackgroundEnabled(false);
  110. return;
  111. }
  112. SetPaintEnabled(true);
  113. SetPaintBackgroundEnabled(true);
  114. // Get our icons for the ammo types
  115. m_iconPrimaryAmmo = gWR.GetAmmoIconFromWeapon( wpn->GetPrimaryAmmoType() );
  116. // get the ammo in our clip
  117. int ammo1 = wpn->Clip1();
  118. int ammo2;
  119. if (ammo1 < 0)
  120. {
  121. // we don't use clip ammo, just use the total ammo count
  122. ammo1 = player->GetAmmoCount(wpn->GetPrimaryAmmoType());
  123. ammo2 = 0;
  124. }
  125. else
  126. {
  127. // we use clip ammo, so the second ammo is the total ammo
  128. ammo2 = player->GetAmmoCount(wpn->GetPrimaryAmmoType());
  129. }
  130. hudlcd->SetGlobalStat( "(ammo_primary)", VarArgs( "%d", ammo1 ) );
  131. hudlcd->SetGlobalStat( "(ammo_secondary)", VarArgs( "%d", ammo2 ) );
  132. if (wpn == m_hCurrentActiveWeapon)
  133. {
  134. // same weapon, just update counts
  135. SetAmmo(ammo1, true);
  136. SetAmmo2(ammo2, true);
  137. }
  138. else
  139. {
  140. // diferent weapon, change without triggering
  141. SetAmmo(ammo1, false);
  142. SetAmmo2(ammo2, false);
  143. // update whether or not we show the total ammo display
  144. if (wpn->UsesClipsForAmmo1())
  145. {
  146. SetShouldDisplaySecondaryValue(true);
  147. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponUsesClips");
  148. }
  149. else
  150. {
  151. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponDoesNotUseClips");
  152. SetShouldDisplaySecondaryValue(false);
  153. }
  154. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponChanged");
  155. m_hCurrentActiveWeapon = wpn;
  156. }
  157. }
  158. void CHudAmmo::UpdateVehicleAmmo( C_BasePlayer *player, IClientVehicle *pVehicle )
  159. {
  160. m_hCurrentActiveWeapon = NULL;
  161. CBaseEntity *pVehicleEnt = pVehicle->GetVehicleEnt();
  162. if ( !pVehicleEnt || pVehicle->GetPrimaryAmmoType() < 0 )
  163. {
  164. SetPaintEnabled(false);
  165. SetPaintBackgroundEnabled(false);
  166. return;
  167. }
  168. SetPaintEnabled(true);
  169. SetPaintBackgroundEnabled(true);
  170. // get the ammo in our clip
  171. int ammo1 = pVehicle->GetPrimaryAmmoClip();
  172. int ammo2;
  173. if (ammo1 < 0)
  174. {
  175. // we don't use clip ammo, just use the total ammo count
  176. ammo1 = pVehicle->GetPrimaryAmmoCount();
  177. ammo2 = 0;
  178. }
  179. else
  180. {
  181. // we use clip ammo, so the second ammo is the total ammo
  182. ammo2 = pVehicle->GetPrimaryAmmoCount();
  183. }
  184. if (pVehicleEnt == m_hCurrentVehicle)
  185. {
  186. // same weapon, just update counts
  187. SetAmmo(ammo1, true);
  188. SetAmmo2(ammo2, true);
  189. }
  190. else
  191. {
  192. // diferent weapon, change without triggering
  193. SetAmmo(ammo1, false);
  194. SetAmmo2(ammo2, false);
  195. // update whether or not we show the total ammo display
  196. if (pVehicle->PrimaryAmmoUsesClips())
  197. {
  198. SetShouldDisplaySecondaryValue(true);
  199. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponUsesClips");
  200. }
  201. else
  202. {
  203. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponDoesNotUseClips");
  204. SetShouldDisplaySecondaryValue(false);
  205. }
  206. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponChanged");
  207. m_hCurrentVehicle = pVehicleEnt;
  208. }
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Purpose: called every frame to get ammo info from the weapon
  212. //-----------------------------------------------------------------------------
  213. void CHudAmmo::OnThink()
  214. {
  215. UpdateAmmoDisplays();
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Purpose: updates the ammo display counts
  219. //-----------------------------------------------------------------------------
  220. void CHudAmmo::UpdateAmmoDisplays()
  221. {
  222. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  223. IClientVehicle *pVehicle = player ? player->GetVehicle() : NULL;
  224. if ( !pVehicle )
  225. {
  226. UpdatePlayerAmmo( player );
  227. }
  228. else
  229. {
  230. UpdateVehicleAmmo( player, pVehicle );
  231. }
  232. }
  233. //-----------------------------------------------------------------------------
  234. // Purpose: Updates ammo display
  235. //-----------------------------------------------------------------------------
  236. void CHudAmmo::SetAmmo(int ammo, bool playAnimation)
  237. {
  238. if (ammo != m_iAmmo)
  239. {
  240. if (ammo == 0)
  241. {
  242. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoEmpty");
  243. }
  244. else if (ammo < m_iAmmo)
  245. {
  246. // ammo has decreased
  247. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoDecreased");
  248. }
  249. else
  250. {
  251. // ammunition has increased
  252. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoIncreased");
  253. }
  254. m_iAmmo = ammo;
  255. }
  256. SetDisplayValue(ammo);
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Purpose: Updates 2nd ammo display
  260. //-----------------------------------------------------------------------------
  261. void CHudAmmo::SetAmmo2(int ammo2, bool playAnimation)
  262. {
  263. if (ammo2 != m_iAmmo2)
  264. {
  265. if (ammo2 == 0)
  266. {
  267. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("Ammo2Empty");
  268. }
  269. else if (ammo2 < m_iAmmo2)
  270. {
  271. // ammo has decreased
  272. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("Ammo2Decreased");
  273. }
  274. else
  275. {
  276. // ammunition has increased
  277. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("Ammo2Increased");
  278. }
  279. m_iAmmo2 = ammo2;
  280. }
  281. SetSecondaryValue(ammo2);
  282. }
  283. //-----------------------------------------------------------------------------
  284. // Purpose: We add an icon into the
  285. //-----------------------------------------------------------------------------
  286. void CHudAmmo::Paint( void )
  287. {
  288. BaseClass::Paint();
  289. #ifndef HL2MP
  290. if ( m_hCurrentVehicle == NULL && m_iconPrimaryAmmo )
  291. {
  292. int nLabelHeight;
  293. int nLabelWidth;
  294. surface()->GetTextSize( m_hTextFont, m_LabelText, nLabelWidth, nLabelHeight );
  295. // Figure out where we're going to put this
  296. int x = text_xpos + ( nLabelWidth - m_iconPrimaryAmmo->Width() ) / 2;
  297. int y = text_ypos - ( nLabelHeight + ( m_iconPrimaryAmmo->Height() / 2 ) );
  298. m_iconPrimaryAmmo->DrawSelf( x, y, GetFgColor() );
  299. }
  300. #endif // HL2MP
  301. }
  302. //-----------------------------------------------------------------------------
  303. // Purpose: Displays the secondary ammunition level
  304. //-----------------------------------------------------------------------------
  305. class CHudSecondaryAmmo : public CHudNumericDisplay, public CHudElement
  306. {
  307. DECLARE_CLASS_SIMPLE( CHudSecondaryAmmo, CHudNumericDisplay );
  308. public:
  309. CHudSecondaryAmmo( const char *pElementName ) : BaseClass( NULL, "HudAmmoSecondary" ), CHudElement( pElementName )
  310. {
  311. m_iAmmo = -1;
  312. SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_WEAPONSELECTION | HIDEHUD_PLAYERDEAD | HIDEHUD_NEEDSUIT );
  313. }
  314. void Init( void )
  315. {
  316. #ifndef HL2MP
  317. wchar_t *tempString = g_pVGuiLocalize->Find("#Valve_Hud_AMMO_ALT");
  318. if (tempString)
  319. {
  320. SetLabelText(tempString);
  321. }
  322. else
  323. {
  324. SetLabelText(L"ALT");
  325. }
  326. #endif // HL2MP
  327. }
  328. void VidInit( void )
  329. {
  330. }
  331. void SetAmmo( int ammo )
  332. {
  333. if (ammo != m_iAmmo)
  334. {
  335. if (ammo == 0)
  336. {
  337. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoSecondaryEmpty");
  338. }
  339. else if (ammo < m_iAmmo)
  340. {
  341. // ammo has decreased
  342. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoSecondaryDecreased");
  343. }
  344. else
  345. {
  346. // ammunition has increased
  347. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoSecondaryIncreased");
  348. }
  349. m_iAmmo = ammo;
  350. }
  351. SetDisplayValue( ammo );
  352. }
  353. void Reset()
  354. {
  355. // hud reset, update ammo state
  356. BaseClass::Reset();
  357. m_iAmmo = 0;
  358. m_hCurrentActiveWeapon = NULL;
  359. SetAlpha( 0 );
  360. UpdateAmmoState();
  361. }
  362. virtual void Paint( void )
  363. {
  364. BaseClass::Paint();
  365. #ifndef HL2MP
  366. if ( m_iconSecondaryAmmo )
  367. {
  368. int nLabelHeight;
  369. int nLabelWidth;
  370. surface()->GetTextSize( m_hTextFont, m_LabelText, nLabelWidth, nLabelHeight );
  371. // Figure out where we're going to put this
  372. int x = text_xpos + ( nLabelWidth - m_iconSecondaryAmmo->Width() ) / 2;
  373. int y = text_ypos - ( nLabelHeight + ( m_iconSecondaryAmmo->Height() / 2 ) );
  374. m_iconSecondaryAmmo->DrawSelf( x, y, GetFgColor() );
  375. }
  376. #endif // HL2MP
  377. }
  378. protected:
  379. virtual void OnThink()
  380. {
  381. // set whether or not the panel draws based on if we have a weapon that supports secondary ammo
  382. C_BaseCombatWeapon *wpn = GetActiveWeapon();
  383. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  384. IClientVehicle *pVehicle = player ? player->GetVehicle() : NULL;
  385. if (!wpn || !player || pVehicle)
  386. {
  387. m_hCurrentActiveWeapon = NULL;
  388. SetPaintEnabled(false);
  389. SetPaintBackgroundEnabled(false);
  390. return;
  391. }
  392. else
  393. {
  394. SetPaintEnabled(true);
  395. SetPaintBackgroundEnabled(true);
  396. }
  397. UpdateAmmoState();
  398. }
  399. void UpdateAmmoState()
  400. {
  401. C_BaseCombatWeapon *wpn = GetActiveWeapon();
  402. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  403. if (player && wpn && wpn->UsesSecondaryAmmo())
  404. {
  405. SetAmmo(player->GetAmmoCount(wpn->GetSecondaryAmmoType()));
  406. }
  407. if ( m_hCurrentActiveWeapon != wpn )
  408. {
  409. if ( wpn->UsesSecondaryAmmo() )
  410. {
  411. // we've changed to a weapon that uses secondary ammo
  412. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponUsesSecondaryAmmo");
  413. }
  414. else
  415. {
  416. // we've changed away from a weapon that uses secondary ammo
  417. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponDoesNotUseSecondaryAmmo");
  418. }
  419. m_hCurrentActiveWeapon = wpn;
  420. // Get the icon we should be displaying
  421. m_iconSecondaryAmmo = gWR.GetAmmoIconFromWeapon( m_hCurrentActiveWeapon->GetSecondaryAmmoType() );
  422. }
  423. }
  424. private:
  425. CHandle< C_BaseCombatWeapon > m_hCurrentActiveWeapon;
  426. CHudTexture *m_iconSecondaryAmmo;
  427. int m_iAmmo;
  428. };
  429. DECLARE_HUDELEMENT( CHudSecondaryAmmo );