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.

777 lines
17 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. /*
  9. ===== h_battery.cpp ========================================================
  10. battery-related code
  11. */
  12. #include "cbase.h"
  13. #include "gamerules.h"
  14. #include "player.h"
  15. #include "engine/IEngineSound.h"
  16. #include "in_buttons.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. static ConVar sk_suitcharger( "sk_suitcharger","0" );
  20. static ConVar sk_suitcharger_citadel( "sk_suitcharger_citadel","0" );
  21. static ConVar sk_suitcharger_citadel_maxarmor( "sk_suitcharger_citadel_maxarmor","0" );
  22. #define SF_CITADEL_RECHARGER 0x2000
  23. #define SF_KLEINER_RECHARGER 0x4000 // Gives only 25 health
  24. class CRecharge : public CBaseToggle
  25. {
  26. public:
  27. DECLARE_CLASS( CRecharge, CBaseToggle );
  28. void Spawn( );
  29. bool CreateVPhysics();
  30. int DrawDebugTextOverlays(void);
  31. void Off(void);
  32. void Recharge(void);
  33. bool KeyValue( const char *szKeyName, const char *szValue );
  34. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  35. virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | FCAP_CONTINUOUS_USE); }
  36. private:
  37. void InputRecharge( inputdata_t &inputdata );
  38. float MaxJuice() const;
  39. void UpdateJuice( int newJuice );
  40. DECLARE_DATADESC();
  41. float m_flNextCharge;
  42. int m_iReactivate ; // DeathMatch Delay until reactvated
  43. int m_iJuice;
  44. int m_iOn; // 0 = off, 1 = startup, 2 = going
  45. float m_flSoundTime;
  46. int m_nState;
  47. COutputFloat m_OutRemainingCharge;
  48. COutputEvent m_OnHalfEmpty;
  49. COutputEvent m_OnEmpty;
  50. COutputEvent m_OnFull;
  51. COutputEvent m_OnPlayerUse;
  52. };
  53. BEGIN_DATADESC( CRecharge )
  54. DEFINE_FIELD( m_flNextCharge, FIELD_TIME ),
  55. DEFINE_FIELD( m_iReactivate, FIELD_INTEGER),
  56. DEFINE_FIELD( m_iJuice, FIELD_INTEGER),
  57. DEFINE_FIELD( m_iOn, FIELD_INTEGER),
  58. DEFINE_FIELD( m_flSoundTime, FIELD_TIME ),
  59. DEFINE_FIELD( m_nState, FIELD_INTEGER ),
  60. // Function Pointers
  61. DEFINE_FUNCTION( Off ),
  62. DEFINE_FUNCTION( Recharge ),
  63. DEFINE_OUTPUT(m_OutRemainingCharge, "OutRemainingCharge"),
  64. DEFINE_OUTPUT(m_OnHalfEmpty, "OnHalfEmpty" ),
  65. DEFINE_OUTPUT(m_OnEmpty, "OnEmpty" ),
  66. DEFINE_OUTPUT(m_OnFull, "OnFull" ),
  67. DEFINE_OUTPUT(m_OnPlayerUse, "OnPlayerUse" ),
  68. DEFINE_INPUTFUNC( FIELD_VOID, "Recharge", InputRecharge ),
  69. END_DATADESC()
  70. LINK_ENTITY_TO_CLASS(func_recharge, CRecharge);
  71. bool CRecharge::KeyValue( const char *szKeyName, const char *szValue )
  72. {
  73. if ( FStrEq(szKeyName, "style") ||
  74. FStrEq(szKeyName, "height") ||
  75. FStrEq(szKeyName, "value1") ||
  76. FStrEq(szKeyName, "value2") ||
  77. FStrEq(szKeyName, "value3"))
  78. {
  79. }
  80. else if (FStrEq(szKeyName, "dmdelay"))
  81. {
  82. m_iReactivate = atoi(szValue);
  83. }
  84. else
  85. {
  86. return BaseClass::KeyValue( szKeyName, szValue );
  87. }
  88. return true;
  89. }
  90. void CRecharge::Spawn()
  91. {
  92. Precache( );
  93. SetSolid( SOLID_BSP );
  94. SetMoveType( MOVETYPE_PUSH );
  95. SetModel( STRING( GetModelName() ) );
  96. UpdateJuice( MaxJuice() );
  97. m_nState = 0;
  98. CreateVPhysics();
  99. }
  100. bool CRecharge::CreateVPhysics()
  101. {
  102. VPhysicsInitStatic();
  103. return true;
  104. }
  105. int CRecharge::DrawDebugTextOverlays(void)
  106. {
  107. int text_offset = BaseClass::DrawDebugTextOverlays();
  108. if (m_debugOverlays & OVERLAY_TEXT_BIT)
  109. {
  110. char tempstr[512];
  111. Q_snprintf(tempstr,sizeof(tempstr),"Charge left: %i", m_iJuice );
  112. EntityText(text_offset,tempstr,0);
  113. text_offset++;
  114. }
  115. return text_offset;
  116. }
  117. //-----------------------------------------------------------------------------
  118. // Max juice for recharger
  119. //-----------------------------------------------------------------------------
  120. float CRecharge::MaxJuice() const
  121. {
  122. if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
  123. {
  124. return sk_suitcharger_citadel.GetFloat();
  125. }
  126. return sk_suitcharger.GetFloat();
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Purpose:
  130. // Input : newJuice -
  131. //-----------------------------------------------------------------------------
  132. void CRecharge::UpdateJuice( int newJuice )
  133. {
  134. bool reduced = newJuice < m_iJuice;
  135. if ( reduced )
  136. {
  137. // Fire 1/2 way output and/or empyt output
  138. int oneHalfJuice = (int)(MaxJuice() * 0.5f);
  139. if ( newJuice <= oneHalfJuice && m_iJuice > oneHalfJuice )
  140. {
  141. m_OnHalfEmpty.FireOutput( this, this );
  142. }
  143. if ( newJuice <= 0 )
  144. {
  145. m_OnEmpty.FireOutput( this, this );
  146. }
  147. }
  148. else if ( newJuice != m_iJuice &&
  149. newJuice == (int)MaxJuice() )
  150. {
  151. m_OnFull.FireOutput( this, this );
  152. }
  153. m_iJuice = newJuice;
  154. }
  155. void CRecharge::InputRecharge( inputdata_t &inputdata )
  156. {
  157. Recharge();
  158. }
  159. void CRecharge::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  160. {
  161. // if it's not a player, ignore
  162. if ( !pActivator || !pActivator->IsPlayer() )
  163. return;
  164. // Only usable if you have the HEV suit on
  165. if ( !((CBasePlayer *)pActivator)->IsSuitEquipped() )
  166. {
  167. if (m_flSoundTime <= gpGlobals->curtime)
  168. {
  169. m_flSoundTime = gpGlobals->curtime + 0.62;
  170. EmitSound( "SuitRecharge.Deny" );
  171. }
  172. return;
  173. }
  174. // if there is no juice left, turn it off
  175. if (m_iJuice <= 0)
  176. {
  177. m_nState = 1;
  178. Off();
  179. }
  180. // if the player doesn't have the suit, or there is no juice left, make the deny noise
  181. if ( m_iJuice <= 0 )
  182. {
  183. if (m_flSoundTime <= gpGlobals->curtime)
  184. {
  185. m_flSoundTime = gpGlobals->curtime + 0.62;
  186. EmitSound( "SuitRecharge.Deny" );
  187. }
  188. return;
  189. }
  190. SetNextThink( gpGlobals->curtime + 0.25 );
  191. SetThink(&CRecharge::Off);
  192. // Time to recharge yet?
  193. if (m_flNextCharge >= gpGlobals->curtime)
  194. return;
  195. // Make sure that we have a caller
  196. if (!pActivator)
  197. return;
  198. m_hActivator = pActivator;
  199. //only recharge the player
  200. if (!m_hActivator->IsPlayer() )
  201. return;
  202. // Play the on sound or the looping charging sound
  203. if (!m_iOn)
  204. {
  205. m_iOn++;
  206. EmitSound( "SuitRecharge.Start" );
  207. m_flSoundTime = 0.56 + gpGlobals->curtime;
  208. m_OnPlayerUse.FireOutput( pActivator, this );
  209. }
  210. if ((m_iOn == 1) && (m_flSoundTime <= gpGlobals->curtime))
  211. {
  212. m_iOn++;
  213. CPASAttenuationFilter filter( this, "SuitRecharge.ChargingLoop" );
  214. filter.MakeReliable();
  215. EmitSound( filter, entindex(), "SuitRecharge.ChargingLoop" );
  216. }
  217. CBasePlayer *pl = (CBasePlayer *) m_hActivator.Get();
  218. // charge the player
  219. int nMaxArmor = 100;
  220. int nIncrementArmor = 1;
  221. if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
  222. {
  223. nMaxArmor = sk_suitcharger_citadel_maxarmor.GetInt();
  224. nIncrementArmor = 10;
  225. // Also give health for the citadel version.
  226. if( pActivator->GetHealth() < pActivator->GetMaxHealth() )
  227. {
  228. pActivator->TakeHealth( 5, DMG_GENERIC );
  229. }
  230. }
  231. if (pl->ArmorValue() < nMaxArmor)
  232. {
  233. UpdateJuice( m_iJuice - nIncrementArmor );
  234. pl->IncrementArmorValue( nIncrementArmor, nMaxArmor );
  235. }
  236. // Send the output.
  237. float flRemaining = m_iJuice / MaxJuice();
  238. m_OutRemainingCharge.Set(flRemaining, pActivator, this);
  239. // govern the rate of charge
  240. m_flNextCharge = gpGlobals->curtime + 0.1;
  241. }
  242. void CRecharge::Recharge(void)
  243. {
  244. UpdateJuice( MaxJuice() );
  245. m_nState = 0;
  246. SetThink( &CRecharge::SUB_DoNothing );
  247. }
  248. void CRecharge::Off(void)
  249. {
  250. // Stop looping sound.
  251. if (m_iOn > 1)
  252. {
  253. StopSound( "SuitRecharge.ChargingLoop" );
  254. }
  255. m_iOn = 0;
  256. if ((!m_iJuice) && ( ( m_iReactivate = g_pGameRules->FlHEVChargerRechargeTime() ) > 0) )
  257. {
  258. SetNextThink( gpGlobals->curtime + m_iReactivate );
  259. SetThink(&CRecharge::Recharge);
  260. }
  261. else
  262. {
  263. SetThink( NULL );
  264. }
  265. }
  266. //NEW
  267. class CNewRecharge : public CBaseAnimating
  268. {
  269. public:
  270. DECLARE_CLASS( CNewRecharge, CBaseAnimating );
  271. void Spawn( );
  272. bool CreateVPhysics();
  273. int DrawDebugTextOverlays(void);
  274. void Off(void);
  275. void Recharge(void);
  276. bool KeyValue( const char *szKeyName, const char *szValue );
  277. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  278. virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | m_iCaps ); }
  279. void SetInitialCharge( void );
  280. private:
  281. void InputRecharge( inputdata_t &inputdata );
  282. void InputSetCharge( inputdata_t &inputdata );
  283. float MaxJuice() const;
  284. void UpdateJuice( int newJuice );
  285. void Precache( void );
  286. DECLARE_DATADESC();
  287. float m_flNextCharge;
  288. int m_iReactivate ; // DeathMatch Delay until reactvated
  289. int m_iJuice;
  290. int m_iOn; // 0 = off, 1 = startup, 2 = going
  291. float m_flSoundTime;
  292. int m_nState;
  293. int m_iCaps;
  294. int m_iMaxJuice;
  295. COutputFloat m_OutRemainingCharge;
  296. COutputEvent m_OnHalfEmpty;
  297. COutputEvent m_OnEmpty;
  298. COutputEvent m_OnFull;
  299. COutputEvent m_OnPlayerUse;
  300. virtual void StudioFrameAdvance ( void );
  301. float m_flJuice;
  302. };
  303. BEGIN_DATADESC( CNewRecharge )
  304. DEFINE_FIELD( m_flNextCharge, FIELD_TIME ),
  305. DEFINE_FIELD( m_iReactivate, FIELD_INTEGER),
  306. DEFINE_FIELD( m_iJuice, FIELD_INTEGER),
  307. DEFINE_FIELD( m_iOn, FIELD_INTEGER),
  308. DEFINE_FIELD( m_flSoundTime, FIELD_TIME ),
  309. DEFINE_FIELD( m_nState, FIELD_INTEGER ),
  310. DEFINE_FIELD( m_iCaps, FIELD_INTEGER ),
  311. DEFINE_FIELD( m_iMaxJuice, FIELD_INTEGER ),
  312. // Function Pointers
  313. DEFINE_FUNCTION( Off ),
  314. DEFINE_FUNCTION( Recharge ),
  315. DEFINE_OUTPUT(m_OutRemainingCharge, "OutRemainingCharge"),
  316. DEFINE_OUTPUT(m_OnHalfEmpty, "OnHalfEmpty" ),
  317. DEFINE_OUTPUT(m_OnEmpty, "OnEmpty" ),
  318. DEFINE_OUTPUT(m_OnFull, "OnFull" ),
  319. DEFINE_OUTPUT(m_OnPlayerUse, "OnPlayerUse" ),
  320. DEFINE_FIELD( m_flJuice, FIELD_FLOAT ),
  321. DEFINE_INPUTFUNC( FIELD_VOID, "Recharge", InputRecharge ),
  322. DEFINE_INPUTFUNC( FIELD_INTEGER, "SetCharge", InputSetCharge ),
  323. END_DATADESC()
  324. LINK_ENTITY_TO_CLASS( item_suitcharger, CNewRecharge);
  325. #define HEALTH_CHARGER_MODEL_NAME "models/props_combine/suit_charger001.mdl"
  326. #define CHARGE_RATE 0.25f
  327. #define CHARGES_PER_SECOND 1 / CHARGE_RATE
  328. #define CITADEL_CHARGES_PER_SECOND 10 / CHARGE_RATE
  329. #define CALLS_PER_SECOND 7.0f * CHARGES_PER_SECOND
  330. bool CNewRecharge::KeyValue( const char *szKeyName, const char *szValue )
  331. {
  332. if ( FStrEq(szKeyName, "style") ||
  333. FStrEq(szKeyName, "height") ||
  334. FStrEq(szKeyName, "value1") ||
  335. FStrEq(szKeyName, "value2") ||
  336. FStrEq(szKeyName, "value3"))
  337. {
  338. }
  339. else if (FStrEq(szKeyName, "dmdelay"))
  340. {
  341. m_iReactivate = atoi(szValue);
  342. }
  343. else
  344. {
  345. return BaseClass::KeyValue( szKeyName, szValue );
  346. }
  347. return true;
  348. }
  349. void CNewRecharge::Precache( void )
  350. {
  351. PrecacheModel( HEALTH_CHARGER_MODEL_NAME );
  352. PrecacheScriptSound( "SuitRecharge.Deny" );
  353. PrecacheScriptSound( "SuitRecharge.Start" );
  354. PrecacheScriptSound( "SuitRecharge.ChargingLoop" );
  355. }
  356. void CNewRecharge::SetInitialCharge( void )
  357. {
  358. if ( HasSpawnFlags( SF_KLEINER_RECHARGER ) )
  359. {
  360. // The charger in Kleiner's lab.
  361. m_iMaxJuice = 25.0f;
  362. return;
  363. }
  364. if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
  365. {
  366. m_iMaxJuice = sk_suitcharger_citadel.GetFloat();
  367. return;
  368. }
  369. m_iMaxJuice = sk_suitcharger.GetFloat();
  370. }
  371. void CNewRecharge::Spawn()
  372. {
  373. Precache( );
  374. SetMoveType( MOVETYPE_NONE );
  375. SetSolid( SOLID_VPHYSICS );
  376. CreateVPhysics();
  377. SetModel( HEALTH_CHARGER_MODEL_NAME );
  378. AddEffects( EF_NOSHADOW );
  379. ResetSequence( LookupSequence( "idle" ) );
  380. SetInitialCharge();
  381. UpdateJuice( MaxJuice() );
  382. m_nState = 0;
  383. m_iCaps = FCAP_CONTINUOUS_USE;
  384. CreateVPhysics();
  385. m_flJuice = m_iJuice;
  386. m_iReactivate = 0;
  387. SetCycle( 1.0f - ( m_flJuice / MaxJuice() ) );
  388. }
  389. bool CNewRecharge::CreateVPhysics()
  390. {
  391. VPhysicsInitStatic();
  392. return true;
  393. }
  394. int CNewRecharge::DrawDebugTextOverlays(void)
  395. {
  396. int text_offset = BaseClass::DrawDebugTextOverlays();
  397. if (m_debugOverlays & OVERLAY_TEXT_BIT)
  398. {
  399. char tempstr[512];
  400. Q_snprintf(tempstr,sizeof(tempstr),"Charge left: %i", m_iJuice );
  401. EntityText(text_offset,tempstr,0);
  402. text_offset++;
  403. }
  404. return text_offset;
  405. }
  406. void CNewRecharge::StudioFrameAdvance( void )
  407. {
  408. m_flPlaybackRate = 0;
  409. float flMaxJuice = MaxJuice() + 0.1f;
  410. float flNewJuice = 1.0f - (float)( m_flJuice / flMaxJuice );
  411. SetCycle( flNewJuice );
  412. // Msg( "Cycle: %f - Juice: %d - m_flJuice :%f - Interval: %f\n", (float)GetCycle(), (int)m_iJuice, (float)m_flJuice, GetAnimTimeInterval() );
  413. if ( !m_flPrevAnimTime )
  414. {
  415. m_flPrevAnimTime = gpGlobals->curtime;
  416. }
  417. // Latch prev
  418. m_flPrevAnimTime = m_flAnimTime;
  419. // Set current
  420. m_flAnimTime = gpGlobals->curtime;
  421. }
  422. //-----------------------------------------------------------------------------
  423. // Max juice for recharger
  424. //-----------------------------------------------------------------------------
  425. float CNewRecharge::MaxJuice() const
  426. {
  427. return m_iMaxJuice;
  428. }
  429. //-----------------------------------------------------------------------------
  430. // Purpose:
  431. // Input : newJuice -
  432. //-----------------------------------------------------------------------------
  433. void CNewRecharge::UpdateJuice( int newJuice )
  434. {
  435. bool reduced = newJuice < m_iJuice;
  436. if ( reduced )
  437. {
  438. // Fire 1/2 way output and/or empyt output
  439. int oneHalfJuice = (int)(MaxJuice() * 0.5f);
  440. if ( newJuice <= oneHalfJuice && m_iJuice > oneHalfJuice )
  441. {
  442. m_OnHalfEmpty.FireOutput( this, this );
  443. }
  444. if ( newJuice <= 0 )
  445. {
  446. m_OnEmpty.FireOutput( this, this );
  447. }
  448. }
  449. else if ( newJuice != m_iJuice &&
  450. newJuice == (int)MaxJuice() )
  451. {
  452. m_OnFull.FireOutput( this, this );
  453. }
  454. m_iJuice = newJuice;
  455. }
  456. void CNewRecharge::InputRecharge( inputdata_t &inputdata )
  457. {
  458. Recharge();
  459. }
  460. void CNewRecharge::InputSetCharge( inputdata_t &inputdata )
  461. {
  462. ResetSequence( LookupSequence( "idle" ) );
  463. int iJuice = inputdata.value.Int();
  464. m_flJuice = m_iMaxJuice = m_iJuice = iJuice;
  465. StudioFrameAdvance();
  466. }
  467. void CNewRecharge::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  468. {
  469. // if it's not a player, ignore
  470. if ( !pActivator || !pActivator->IsPlayer() )
  471. return;
  472. CBasePlayer *pPlayer = static_cast<CBasePlayer *>(pActivator);
  473. // Reset to a state of continuous use.
  474. m_iCaps = FCAP_CONTINUOUS_USE;
  475. if ( m_iOn )
  476. {
  477. float flCharges = CHARGES_PER_SECOND;
  478. float flCalls = CALLS_PER_SECOND;
  479. if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
  480. flCharges = CITADEL_CHARGES_PER_SECOND;
  481. m_flJuice -= flCharges / flCalls;
  482. StudioFrameAdvance();
  483. }
  484. // Only usable if you have the HEV suit on
  485. if ( !pPlayer->IsSuitEquipped() )
  486. {
  487. if (m_flSoundTime <= gpGlobals->curtime)
  488. {
  489. m_flSoundTime = gpGlobals->curtime + 0.62;
  490. EmitSound( "SuitRecharge.Deny" );
  491. }
  492. return;
  493. }
  494. // if there is no juice left, turn it off
  495. if ( m_iJuice <= 0 )
  496. {
  497. // Start our deny animation over again
  498. ResetSequence( LookupSequence( "emptyclick" ) );
  499. m_nState = 1;
  500. // Shut off
  501. Off();
  502. // Play a deny sound
  503. if ( m_flSoundTime <= gpGlobals->curtime )
  504. {
  505. m_flSoundTime = gpGlobals->curtime + 0.62;
  506. EmitSound( "SuitRecharge.Deny" );
  507. }
  508. return;
  509. }
  510. // Get our maximum armor value
  511. int nMaxArmor = 100;
  512. if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
  513. {
  514. nMaxArmor = sk_suitcharger_citadel_maxarmor.GetInt();
  515. }
  516. int nIncrementArmor = 1;
  517. // The citadel charger gives more per charge and also gives health
  518. if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
  519. {
  520. nIncrementArmor = 10;
  521. #ifdef HL2MP
  522. nIncrementArmor = 2;
  523. #endif
  524. // Also give health for the citadel version.
  525. if ( pActivator->GetHealth() < pActivator->GetMaxHealth() && m_flNextCharge < gpGlobals->curtime )
  526. {
  527. pActivator->TakeHealth( 5, DMG_GENERIC );
  528. }
  529. }
  530. // If we're over our limit, debounce our keys
  531. if ( pPlayer->ArmorValue() >= nMaxArmor)
  532. {
  533. // Citadel charger must also be at max health
  534. if ( !HasSpawnFlags(SF_CITADEL_RECHARGER) || ( HasSpawnFlags( SF_CITADEL_RECHARGER ) && pActivator->GetHealth() >= pActivator->GetMaxHealth() ) )
  535. {
  536. // Make the user re-use me to get started drawing health.
  537. pPlayer->m_afButtonPressed &= ~IN_USE;
  538. m_iCaps = FCAP_IMPULSE_USE;
  539. EmitSound( "SuitRecharge.Deny" );
  540. return;
  541. }
  542. }
  543. // This is bumped out if used within the time period
  544. SetNextThink( gpGlobals->curtime + CHARGE_RATE );
  545. SetThink( &CNewRecharge::Off );
  546. // Time to recharge yet?
  547. if ( m_flNextCharge >= gpGlobals->curtime )
  548. return;
  549. // Play the on sound or the looping charging sound
  550. if ( !m_iOn )
  551. {
  552. m_iOn++;
  553. EmitSound( "SuitRecharge.Start" );
  554. m_flSoundTime = 0.56 + gpGlobals->curtime;
  555. m_OnPlayerUse.FireOutput( pActivator, this );
  556. }
  557. if ((m_iOn == 1) && (m_flSoundTime <= gpGlobals->curtime))
  558. {
  559. m_iOn++;
  560. CPASAttenuationFilter filter( this, "SuitRecharge.ChargingLoop" );
  561. filter.MakeReliable();
  562. EmitSound( filter, entindex(), "SuitRecharge.ChargingLoop" );
  563. }
  564. // Give armor if we need it
  565. if ( pPlayer->ArmorValue() < nMaxArmor )
  566. {
  567. UpdateJuice( m_iJuice - nIncrementArmor );
  568. pPlayer->IncrementArmorValue( nIncrementArmor, nMaxArmor );
  569. }
  570. // Send the output.
  571. float flRemaining = m_iJuice / MaxJuice();
  572. m_OutRemainingCharge.Set(flRemaining, pActivator, this);
  573. // govern the rate of charge
  574. m_flNextCharge = gpGlobals->curtime + 0.1;
  575. }
  576. void CNewRecharge::Recharge(void)
  577. {
  578. EmitSound( "SuitRecharge.Start" );
  579. ResetSequence( LookupSequence( "idle" ) );
  580. UpdateJuice( MaxJuice() );
  581. m_nState = 0;
  582. m_flJuice = m_iJuice;
  583. m_iReactivate = 0;
  584. StudioFrameAdvance();
  585. SetThink( &CNewRecharge::SUB_DoNothing );
  586. }
  587. void CNewRecharge::Off(void)
  588. {
  589. // Stop looping sound.
  590. if (m_iOn > 1)
  591. {
  592. StopSound( "SuitRecharge.ChargingLoop" );
  593. }
  594. if ( m_nState == 1 )
  595. {
  596. SetCycle( 1.0f );
  597. }
  598. m_iOn = 0;
  599. m_flJuice = m_iJuice;
  600. if ( m_iReactivate == 0 )
  601. {
  602. if ((!m_iJuice) && g_pGameRules->FlHEVChargerRechargeTime() > 0 )
  603. {
  604. if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
  605. {
  606. m_iReactivate = g_pGameRules->FlHEVChargerRechargeTime() * 2;
  607. }
  608. else
  609. {
  610. m_iReactivate = g_pGameRules->FlHEVChargerRechargeTime();
  611. }
  612. SetNextThink( gpGlobals->curtime + m_iReactivate );
  613. SetThink(&CNewRecharge::Recharge);
  614. }
  615. else
  616. {
  617. SetThink( NULL );
  618. }
  619. }
  620. }