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.

743 lines
18 KiB

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