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.

618 lines
20 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: CTF Rune.
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "items.h"
  8. #include "tf_gamerules.h"
  9. #include "tf_shareddefs.h"
  10. #include "tf_player.h"
  11. #include "tf_team.h"
  12. #include "engine/IEngineSound.h"
  13. #include "entity_rune.h"
  14. #include "tf_gamestats.h"
  15. #include "func_respawnroom.h"
  16. #include "particle_parse.h"
  17. #include "tf_fx.h"
  18. #include "collisionutils.h"
  19. //=============================================================================
  20. //
  21. // CTF Rune defines.
  22. //
  23. extern ConVar tf_powerup_mode;
  24. #define RUNE_BLINK_CONTEXT "blink_think"
  25. #define TF_RUNE_TEMP_RESPAWN_DELAY 90.f
  26. #define TF_RUNE_TEMP_UBER_RESPAWN_DELAY 180.f
  27. // Regular Runes (non temporary) will reposition themselves if they haven't been picked up in time
  28. #define BLINK_TIME 10.f
  29. LINK_ENTITY_TO_CLASS( item_powerup_rune, CTFRune );
  30. LINK_ENTITY_TO_CLASS( item_powerup_rune_temp, CTFRuneTemp );
  31. LINK_ENTITY_TO_CLASS( item_powerup_crit, CTFRuneTempCrit );
  32. LINK_ENTITY_TO_CLASS( item_powerup_uber, CTFRuneTempUber );
  33. LINK_ENTITY_TO_CLASS( info_powerup_spawn, CTFInfoPowerupSpawn );
  34. IMPLEMENT_AUTO_LIST( IInfoPowerupSpawnAutoList );
  35. //=============================================================================
  36. //
  37. // CTF Rune functions.
  38. //
  39. //-----------------------------------------------------------------------------
  40. // Purpose: Constructor
  41. //-----------------------------------------------------------------------------
  42. CTFRune::CTFRune()
  43. {
  44. m_bApplyForce = true;
  45. m_nRuneType = RUNE_STRENGTH;
  46. m_nTeam = TEAM_ANY;
  47. m_bShouldReposition = false;
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Purpose: Destructor
  51. //-----------------------------------------------------------------------------
  52. CTFRune::~CTFRune()
  53. {
  54. }
  55. //-----------------------------------------------------------------------------
  56. // Purpose: Spawn powerup rune
  57. //-----------------------------------------------------------------------------
  58. void CTFRune::Spawn( void )
  59. {
  60. BaseClass::Spawn();
  61. RemoveSolidFlags( FSOLID_TRIGGER );
  62. m_bActivateWhenAtRest = true;
  63. m_vecSpawnDirection.z = 0.7f;
  64. VectorNormalize( m_vecSpawnDirection );
  65. SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
  66. SetSolid( SOLID_BBOX );
  67. if ( m_bApplyForce )
  68. {
  69. SetAbsVelocity( m_vecSpawnDirection * 350.f );
  70. m_bThrownSingleInstance = true;
  71. }
  72. // Reposition if not picked up in time
  73. m_nBlinkCount = 0;
  74. m_flKillTime = gpGlobals->curtime + GetRuneRepositionTime() + BLINK_TIME;
  75. if ( m_bShouldReposition )
  76. {
  77. SetContextThink( &CTFRune::BlinkThink, gpGlobals->curtime + GetRuneRepositionTime(), RUNE_BLINK_CONTEXT );
  78. }
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Purpose: Precache function for the powerup rune
  82. //-----------------------------------------------------------------------------
  83. void CTFRune::Precache( void )
  84. {
  85. PrecacheScriptSound( "Powerup.PickUpResistance" );
  86. PrecacheScriptSound( "Powerup.PickUpRegeneration" );
  87. PrecacheScriptSound( "Powerup.PickUpStrength" );
  88. PrecacheScriptSound( "Powerup.PickUpHaste" );
  89. PrecacheScriptSound( "Powerup.PickUpVampire" );
  90. PrecacheScriptSound( "Powerup.PickUpReflect" );
  91. PrecacheScriptSound( "Powerup.PickUpPrecision" );
  92. PrecacheScriptSound( "Powerup.PickUpAgility" );
  93. PrecacheScriptSound( "Powerup.PickUpKnockout" );
  94. PrecacheScriptSound( "Powerup.Knockout_Melee_Hit" );
  95. PrecacheScriptSound( "Powerup.Reflect.Reflect" );
  96. PrecacheScriptSound( "Powerup.PickUpKing" );
  97. PrecacheScriptSound( "Powerup.PickUpPlague" );
  98. PrecacheScriptSound( "Powerup.PickUpSupernova" );
  99. PrecacheScriptSound( "Powerup.PickUpSupernovaActivate" );
  100. PrecacheScriptSound( "Powerup.PickUpPlagueInfected" );
  101. PrecacheScriptSound( "Powerup.PickUpPlagueInfectedLoop" );
  102. PrecacheModel( GetDefaultPowerupModel() );
  103. PrecacheModel( TF_RUNE_STRENGTH );
  104. PrecacheModel( TF_RUNE_RESIST );
  105. PrecacheModel( TF_RUNE_REGEN );
  106. PrecacheModel( TF_RUNE_HASTE );
  107. PrecacheModel( TF_RUNE_VAMPIRE );
  108. PrecacheModel( TF_RUNE_REFLECT );
  109. PrecacheModel( TF_RUNE_PRECISION );
  110. PrecacheModel( TF_RUNE_AGILITY );
  111. PrecacheModel( TF_RUNE_KNOCKOUT );
  112. PrecacheModel( TF_RUNE_KING );
  113. PrecacheModel( TF_RUNE_PLAGUE );
  114. PrecacheModel( TF_RUNE_SUPERNOVA );
  115. // precache all powerup icons
  116. for ( int i=0; i<RUNE_TYPES_MAX; ++i )
  117. {
  118. RuneTypes_t type = RuneTypes_t(i);
  119. PrecacheParticleSystem( GetPowerupIconName( type, TF_TEAM_RED ) );
  120. PrecacheParticleSystem( GetPowerupIconName( type, TF_TEAM_BLUE ) );
  121. }
  122. PrecacheParticleSystem( "plague_infect_player" );
  123. PrecacheParticleSystem( "plague_healthkit_pickup" );
  124. PrecacheParticleSystem( "powerup_king_red" );
  125. PrecacheParticleSystem( "powerup_king_blue" );
  126. PrecacheParticleSystem( "powerup_supernova_ready" );
  127. PrecacheParticleSystem( "powerup_supernova_strike_red" );
  128. PrecacheParticleSystem( "powerup_supernova_strike_blue" );
  129. PrecacheParticleSystem( "powerup_supernova_explode_red" );
  130. PrecacheParticleSystem( "powerup_supernova_explode_blue" );
  131. PrecacheParticleSystem( "powerup_plague_carrier" );
  132. BaseClass::Precache();
  133. }
  134. //-----------------------------------------------------------------------------
  135. // Purpose: Make sure Powerup Runes that are away from any players at spawn will accept particle attachments
  136. //-----------------------------------------------------------------------------
  137. int CTFRune::UpdateTransmitState()
  138. {
  139. return SetTransmitState( FL_EDICT_ALWAYS );
  140. }
  141. //-----------------------------------------------------------------------------
  142. // Purpose: Make sure Powerup Runes that are away from any players at spawn will accept particle attachments
  143. //-----------------------------------------------------------------------------
  144. int CTFRune::ShouldTransmit( const CCheckTransmitInfo *pInfo )
  145. {
  146. return FL_EDICT_ALWAYS;
  147. }
  148. //-----------------------------------------------------------------------------
  149. // Purpose: MyTouch function for the powerup rune
  150. //-----------------------------------------------------------------------------
  151. bool CTFRune::MyTouch( CBasePlayer *pPlayer )
  152. {
  153. bool bSuccess = ValidTouch( pPlayer );
  154. if ( bSuccess )
  155. {
  156. CTFPlayer *pTFPlayer = ToTFPlayer( pPlayer );
  157. if ( !pTFPlayer )
  158. return false;
  159. // don't allow different team player to pick up team based rune unless they are a spy disguised as the correct team
  160. if ( m_nTeam != TEAM_ANY && m_nTeam != pTFPlayer->GetTeamNumber() )
  161. if ( !pTFPlayer->GetPlayerClass()->IsClass( TF_CLASS_SPY ) || pTFPlayer->m_Shared.GetDisguiseTeam() != m_nTeam )
  162. {
  163. return false;
  164. }
  165. if ( pTFPlayer->m_Shared.IsStealthed() ||
  166. pTFPlayer->m_Shared.InCond( TF_COND_STEALTHED_BLINK ) ||
  167. pTFPlayer->m_Shared.GetPercentInvisible() > 0.25f )
  168. {
  169. return false;
  170. }
  171. if ( pTFPlayer->m_Shared.IsCarryingRune() )
  172. {
  173. ClientPrint( pPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Deny" );
  174. return false;
  175. }
  176. if ( pTFPlayer->IsTaunting() )
  177. {
  178. return false;
  179. }
  180. #ifdef GAME_DLL
  181. if ( PointInRespawnRoom( pTFPlayer, pTFPlayer->WorldSpaceCenter() ) )
  182. return false;
  183. #endif
  184. Assert( m_nRuneType >= 0 && m_nRuneType < RUNE_TYPES_MAX );
  185. // Order is important because SetSpeed has to occur once SetCarryingRuneType has happened
  186. pTFPlayer->m_Shared.SetCarryingRuneType( m_nRuneType );
  187. CPASAttenuationFilter filter( pTFPlayer );
  188. switch ( m_nRuneType )
  189. {
  190. case RUNE_STRENGTH:
  191. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Strength" );
  192. pTFPlayer->EmitSound( "Powerup.PickUpStrength" );
  193. break;
  194. case RUNE_RESIST:
  195. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Resist" );
  196. pTFPlayer->EmitSound( "Powerup.PickUpResistance" );
  197. break;
  198. case RUNE_REGEN:
  199. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Regen" );
  200. pTFPlayer->EmitSound( "Powerup.PickUpRegeneration" );
  201. break;
  202. case RUNE_HASTE:
  203. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Haste" );
  204. pTFPlayer->EmitSound( "Powerup.PickUpHaste" );
  205. pTFPlayer->TeamFortress_SetSpeed();
  206. break;
  207. case RUNE_VAMPIRE:
  208. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Vampire" );
  209. pTFPlayer->EmitSound( "Powerup.PickUpVampire" );
  210. break;
  211. case RUNE_REFLECT:
  212. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Reflect" );
  213. pTFPlayer->EmitSound( "Powerup.PickUpReflect" );
  214. break;
  215. case RUNE_PRECISION:
  216. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Precision" );
  217. pTFPlayer->EmitSound( "Powerup.PickUpPrecision" );
  218. break;
  219. case RUNE_AGILITY:
  220. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Agility" );
  221. pTFPlayer->EmitSound( "Powerup.PickUpAgility" );
  222. pTFPlayer->TeamFortress_SetSpeed();
  223. break;
  224. case RUNE_KNOCKOUT:
  225. {
  226. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Knockout" );
  227. pTFPlayer->EmitSound( "Powerup.PickUpKnockout" );
  228. // Switch to melee to make sure Engies don't have build menus open
  229. CTFWeaponBase *pMeleeWeapon = dynamic_cast<CTFWeaponBase*>( pTFPlayer->GetEntityForLoadoutSlot( LOADOUT_POSITION_MELEE ) );
  230. Assert( pMeleeWeapon );
  231. if ( pMeleeWeapon )
  232. {
  233. if ( pTFPlayer->GetActiveTFWeapon() && pTFPlayer->GetActiveTFWeapon()->GetWeaponID() != TF_WEAPON_GRAPPLINGHOOK )
  234. {
  235. pTFPlayer->Weapon_Switch( pMeleeWeapon );
  236. }
  237. else
  238. {
  239. // when the player switch away from the hook, it'll go to the last weapon.
  240. // force it to be melee weapon
  241. pTFPlayer->Weapon_SetLast( pMeleeWeapon );
  242. }
  243. }
  244. pTFPlayer->m_Shared.AddCond( TF_COND_CANNOT_SWITCH_FROM_MELEE );
  245. }
  246. break;
  247. case RUNE_KING:
  248. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_King" );
  249. pTFPlayer->EmitSound( "Powerup.PickUpKing" );
  250. break;
  251. case RUNE_PLAGUE:
  252. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Plague" );
  253. pTFPlayer->EmitSound( "Powerup.PickUpPlague" );
  254. break;
  255. case RUNE_SUPERNOVA:
  256. ClientPrint( pTFPlayer, HUD_PRINTCENTER, "#TF_Powerup_Pickup_Supernova" );
  257. pTFPlayer->EmitSound( "Powerup.PickUpSupernova" );
  258. break;
  259. }
  260. UTIL_Remove( this ); //power-up runes don't respawn, only one of them exists in the game
  261. }
  262. return bSuccess;
  263. }
  264. //-----------------------------------------------------------------------------
  265. // Purpose: Create an instance of a powerup rune and drop it into the world with a random vector velocity
  266. //-----------------------------------------------------------------------------
  267. CTFRune* CTFRune::CreateRune( const Vector &vecOrigin, RuneTypes_t nType, int nTeam, bool bShouldReposition, bool bApplyForce, Vector vecSpawnDirection /*= vec3_angle*/ )
  268. {
  269. // Make sure we're passing in a valid rune type
  270. Assert( nType >= 0 && nType < RUNE_TYPES_MAX );
  271. CTFRune *pRune = NULL;
  272. pRune = static_cast< CTFRune* >( CBaseEntity::CreateNoSpawn( "item_powerup_rune", vecOrigin + Vector( 0.f, 0.f, 48.f ), vec3_angle, NULL ) );
  273. pRune->m_bApplyForce = bApplyForce;
  274. pRune->m_nRuneType = nType;
  275. pRune->m_vecSpawnDirection = vecSpawnDirection;
  276. pRune->m_nTeam = nTeam;
  277. pRune->m_bShouldReposition = bShouldReposition;
  278. if ( nTeam == TEAM_ANY )
  279. pRune->m_nSkin = 0;
  280. else
  281. pRune->m_nSkin = nTeam == TF_TEAM_RED ? 1 : 2;
  282. DispatchSpawn( pRune );
  283. return pRune;
  284. }
  285. //-----------------------------------------------------------------------------
  286. // Respawn the Powerup Rune in the event of it coming to rest inside a trigger_hurt or respawn room trigger
  287. //-----------------------------------------------------------------------------
  288. void CTFRune::ComeToRest( void )
  289. {
  290. BaseClass::ComeToRest();
  291. // See if we've come to rest in a trigger_hurt or a respawn room trigger. If so, immediately reposition the Powerup
  292. for ( int i = 0; i < ITriggerHurtAutoList::AutoList().Count(); i++ )
  293. {
  294. CTriggerHurt *pTrigger = static_cast< CTriggerHurt* >( ITriggerHurtAutoList::AutoList()[i] );
  295. if ( pTrigger->m_bDisabled )
  296. continue;
  297. Vector vecMins, vecMaxs;
  298. pTrigger->GetCollideable()->WorldSpaceSurroundingBounds( &vecMins, &vecMaxs );
  299. if ( IsPointInBox( GetCollideable()->GetCollisionOrigin(), vecMins, vecMaxs ) )
  300. {
  301. if ( RepositionRune( m_nRuneType, m_nTeam ) )
  302. {
  303. UTIL_Remove( this );
  304. }
  305. return;
  306. }
  307. }
  308. for ( int j = 0; j < IFuncRespawnRoomAutoList::AutoList().Count(); j++ )
  309. {
  310. CFuncRespawnRoom *pRespawnRoom = static_cast<CFuncRespawnRoom*>( IFuncRespawnRoomAutoList::AutoList()[j] );
  311. Vector vecMins, vecMaxs;
  312. pRespawnRoom->GetCollideable()->WorldSpaceSurroundingBounds( &vecMins, &vecMaxs );
  313. if ( IsPointInBox( GetCollideable()->GetCollisionOrigin(), vecMins, vecMaxs ) )
  314. {
  315. if ( RepositionRune( m_nRuneType, m_nTeam ) )
  316. {
  317. UTIL_Remove( this );
  318. }
  319. return;
  320. }
  321. }
  322. }
  323. //-----------------------------------------------------------------------------
  324. // Purpose: Enter blinking state before removing and respawning this Powerup
  325. //-----------------------------------------------------------------------------
  326. void CTFRune::BlinkThink()
  327. {
  328. float flTimeToKill = m_flKillTime - gpGlobals->curtime;
  329. float flNextBlink = RemapValClamped( flTimeToKill, BLINK_TIME, 0.f, 0.5f, 0.1f );
  330. SetCycle( RandomFloat() );
  331. SetContextThink( &CTFRune::BlinkThink, gpGlobals->curtime + flNextBlink, RUNE_BLINK_CONTEXT );
  332. SetRenderMode( kRenderTransAlpha );
  333. ++m_nBlinkCount;
  334. if ( m_nBlinkCount % 2 == 0 )
  335. {
  336. SetRenderColorA( 25 );
  337. }
  338. else
  339. {
  340. SetRenderColorA( 255 );
  341. }
  342. if ( gpGlobals->curtime >= m_flKillTime )
  343. {
  344. if ( RepositionRune( m_nRuneType, m_nTeam ) )
  345. {
  346. UTIL_Remove( this );
  347. }
  348. }
  349. }
  350. //-----------------------------------------------------------------------------
  351. // Purpose: Enter blinking state before removing and respawning this Powerup
  352. //-----------------------------------------------------------------------------
  353. bool CTFRune::RepositionRune( RuneTypes_t nType, int nTeamNumber )
  354. {
  355. // Powerups will pick a spawn point based on what team color they were when they repositioned. First try your own team color, then neutral, then enemy
  356. CUtlVector< CTFInfoPowerupSpawn* > vecSpawnPoints;
  357. if ( nTeamNumber != TEAM_ANY )
  358. {
  359. for ( int n = 0; n < IInfoPowerupSpawnAutoList::AutoList().Count(); n++ )
  360. {
  361. CTFInfoPowerupSpawn *pSpawnPoint = static_cast<CTFInfoPowerupSpawn*>( IInfoPowerupSpawnAutoList::AutoList()[n] );
  362. // We want to try to spawn on a point that matches the team color
  363. if ( !pSpawnPoint->IsDisabled() && !pSpawnPoint->HasRune() && pSpawnPoint->GetTeamNumber() == nTeamNumber )
  364. {
  365. vecSpawnPoints.AddToTail( pSpawnPoint );
  366. }
  367. }
  368. }
  369. if ( nTeamNumber == TEAM_ANY || vecSpawnPoints.Count() < 1 )
  370. {
  371. for ( int n = 0; n < IInfoPowerupSpawnAutoList::AutoList().Count(); n++ )
  372. {
  373. CTFInfoPowerupSpawn *pSpawnPoint = static_cast<CTFInfoPowerupSpawn*>( IInfoPowerupSpawnAutoList::AutoList()[n] );
  374. // Don't include disabled info_powerup_spawn positions or ones that already have runes on them
  375. if ( !pSpawnPoint->IsDisabled() && !pSpawnPoint->HasRune() )
  376. {
  377. vecSpawnPoints.AddToTail( pSpawnPoint );
  378. }
  379. }
  380. }
  381. Assert( vecSpawnPoints.Count() > 0 ); // We need at least one valid info_powerup_spawn position
  382. if ( vecSpawnPoints.Count() )
  383. {
  384. int index = RandomInt( 0, vecSpawnPoints.Count() - 1 );
  385. CTFInfoPowerupSpawn *pSpawnPoint = vecSpawnPoints[index];
  386. CTFRune *pNewRune = CreateRune( vecSpawnPoints[index]->GetAbsOrigin(), nType, TEAM_ANY, false, false );
  387. pSpawnPoint->SetRune( pNewRune );
  388. return true;
  389. }
  390. return false;
  391. }
  392. //-----------------------------------------------------------------------------
  393. // Purpose:
  394. //-----------------------------------------------------------------------------
  395. float CTFRune::GetRuneRepositionTime()
  396. {
  397. // In freeforall mode, killed players drop enemy team colored powerups. These powerups reposition quicker
  398. if ( m_nTeam != TEAM_ANY )
  399. {
  400. return 30.f;
  401. }
  402. else
  403. {
  404. return 60.f;
  405. }
  406. }
  407. //=============================================================================
  408. //
  409. // CTF Temporary Rune functions.
  410. //
  411. //-----------------------------------------------------------------------------
  412. // Purpose: Constructor
  413. //-----------------------------------------------------------------------------
  414. CTFRuneTemp::CTFRuneTemp()
  415. {
  416. m_nRuneTempType = RUNETYPE_TEMP_NONE;
  417. }
  418. //-----------------------------------------------------------------------------
  419. // Purpose: Precache function for the temporary powerup rune
  420. //-----------------------------------------------------------------------------
  421. void CTFRuneTemp::Precache( void )
  422. {
  423. PrecacheScriptSound( "Powerup.PickUpTemp.Crit" );
  424. PrecacheScriptSound( "Powerup.PickUpTemp.Uber" );
  425. PrecacheModel( TF_RUNE_TEMP_CRIT );
  426. PrecacheModel( TF_RUNE_TEMP_UBER );
  427. BaseClass::Precache();
  428. }
  429. //-----------------------------------------------------------------------------
  430. // Purpose: Spawn Temporary powerup rune
  431. //-----------------------------------------------------------------------------
  432. void CTFRuneTemp::Spawn( void )
  433. {
  434. if ( TFGameRules() && TFGameRules()->IsPowerupMode() )
  435. {
  436. BaseClass::Spawn();
  437. SetMoveType( MOVETYPE_NONE );
  438. SetSolid( SOLID_BBOX );
  439. }
  440. }
  441. //-----------------------------------------------------------------------------
  442. // Purpose: MyTouch function for the temporary powerup rune - needed because these respawn, and don't set the condition TF_COND_RUNE
  443. //-----------------------------------------------------------------------------
  444. bool CTFRuneTemp::MyTouch( CBasePlayer *pPlayer )
  445. {
  446. bool bSuccess = ValidTouch( pPlayer );
  447. if ( bSuccess )
  448. {
  449. CTFPlayer *pTFPlayer = ToTFPlayer( pPlayer );
  450. if ( !pTFPlayer )
  451. return false;
  452. if ( pTFPlayer->m_Shared.IsStealthed() || pTFPlayer->m_Shared.InCond( TF_COND_STEALTHED_BLINK ) || pTFPlayer->m_Shared.GetPercentInvisible() > 0.25f )
  453. {
  454. return false;
  455. }
  456. if ( pTFPlayer->m_Shared.InCond( TF_COND_RUNE_IMBALANCE ) )
  457. {
  458. return false;
  459. }
  460. if ( pTFPlayer->IsTaunting() )
  461. {
  462. return false;
  463. }
  464. if ( pTFPlayer->m_Shared.InCond( TF_COND_INVULNERABLE_USER_BUFF ) || pTFPlayer->m_Shared.InCond( TF_COND_CRITBOOSTED_RUNE_TEMP ) )
  465. {
  466. return false;
  467. }
  468. if ( m_nRuneTempType == RUNETYPE_TEMP_CRIT )
  469. {
  470. if ( pTFPlayer->m_Shared.IsCritBoosted() ) // Disallow players who are already crit boosted
  471. {
  472. return false;
  473. }
  474. else
  475. {
  476. pTFPlayer->m_Shared.AddCond( TF_COND_CRITBOOSTED_RUNE_TEMP, 30.f );
  477. pTFPlayer->EmitSound( "Powerup.PickUpTemp.Crit" );
  478. }
  479. }
  480. if ( m_nRuneTempType == RUNETYPE_TEMP_UBER )
  481. {
  482. if ( pTFPlayer->HasTheFlag() || pTFPlayer->m_Shared.IsInvulnerable() ) // Disallow players who have the flag or are already ubercharged
  483. {
  484. return false;
  485. }
  486. else
  487. {
  488. pTFPlayer->m_Shared.AddCond( TF_COND_INVULNERABLE_USER_BUFF, 20.f );
  489. pTFPlayer->EmitSound( "Powerup.PickUpTemp.Uber" );
  490. }
  491. }
  492. }
  493. return bSuccess;
  494. }
  495. //-----------------------------------------------------------------------------
  496. // Purpose:
  497. //-----------------------------------------------------------------------------
  498. float CTFRuneTemp::GetRespawnDelay( void )
  499. {
  500. if ( m_nRuneTempType == RUNETYPE_TEMP_UBER )
  501. {
  502. return TF_RUNE_TEMP_UBER_RESPAWN_DELAY;
  503. }
  504. else
  505. return TF_RUNE_TEMP_RESPAWN_DELAY;
  506. }
  507. //-----------------------------------------------------------------------------
  508. // Purpose: Constructor
  509. //-----------------------------------------------------------------------------
  510. CTFRuneTempCrit::CTFRuneTempCrit()
  511. {
  512. m_nRuneTempType = RUNETYPE_TEMP_CRIT;
  513. }
  514. //-----------------------------------------------------------------------------
  515. // Purpose: Constructor
  516. //-----------------------------------------------------------------------------
  517. CTFRuneTempUber::CTFRuneTempUber()
  518. {
  519. m_nRuneTempType = RUNETYPE_TEMP_UBER;
  520. }
  521. BEGIN_DATADESC( CTFInfoPowerupSpawn )
  522. DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "disabled" ),
  523. DEFINE_KEYFIELD( m_nTeam, FIELD_INTEGER, "team" ),
  524. END_DATADESC()
  525. //-----------------------------------------------------------------------------
  526. // Purpose: Constructor
  527. //-----------------------------------------------------------------------------
  528. CTFInfoPowerupSpawn::CTFInfoPowerupSpawn()
  529. {
  530. m_bDisabled = false;
  531. m_nTeam = TEAM_ANY;
  532. }
  533. void CTFInfoPowerupSpawn::Spawn()
  534. {
  535. BaseClass::Spawn();
  536. // set baseclass team number
  537. ChangeTeam( m_nTeam );
  538. }