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.

736 lines
17 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Contains entities for implementing/changing game rules dynamically within each BSP.
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "datamap.h"
  8. #include "gamerules.h"
  9. #include "maprules.h"
  10. #include "player.h"
  11. #include "entitylist.h"
  12. #include "ai_hull.h"
  13. #include "entityoutput.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. class CRuleEntity : public CBaseEntity
  17. {
  18. public:
  19. DECLARE_CLASS( CRuleEntity, CBaseEntity );
  20. void Spawn( void );
  21. DECLARE_DATADESC();
  22. void SetMaster( string_t iszMaster ) { m_iszMaster = iszMaster; }
  23. protected:
  24. bool CanFireForActivator( CBaseEntity *pActivator );
  25. private:
  26. string_t m_iszMaster;
  27. };
  28. BEGIN_DATADESC( CRuleEntity )
  29. DEFINE_KEYFIELD( m_iszMaster, FIELD_STRING, "master" ),
  30. END_DATADESC()
  31. void CRuleEntity::Spawn( void )
  32. {
  33. SetSolid( SOLID_NONE );
  34. SetMoveType( MOVETYPE_NONE );
  35. AddEffects( EF_NODRAW );
  36. }
  37. bool CRuleEntity::CanFireForActivator( CBaseEntity *pActivator )
  38. {
  39. if ( m_iszMaster != NULL_STRING )
  40. {
  41. if ( UTIL_IsMasterTriggered( m_iszMaster, pActivator ) )
  42. return true;
  43. else
  44. return false;
  45. }
  46. return true;
  47. }
  48. //
  49. // CRulePointEntity -- base class for all rule "point" entities (not brushes)
  50. //
  51. class CRulePointEntity : public CRuleEntity
  52. {
  53. public:
  54. DECLARE_DATADESC();
  55. DECLARE_CLASS( CRulePointEntity, CRuleEntity );
  56. int m_Score;
  57. void Spawn( void );
  58. };
  59. //---------------------------------------------------------
  60. // Save/Restore
  61. //---------------------------------------------------------
  62. BEGIN_DATADESC( CRulePointEntity )
  63. DEFINE_FIELD( m_Score, FIELD_INTEGER ),
  64. END_DATADESC()
  65. void CRulePointEntity::Spawn( void )
  66. {
  67. BaseClass::Spawn();
  68. SetModelName( NULL_STRING );
  69. m_Score = 0;
  70. }
  71. //
  72. // CRuleBrushEntity -- base class for all rule "brush" entities (not brushes)
  73. // Default behavior is to set up like a trigger, invisible, but keep the model for volume testing
  74. //
  75. class CRuleBrushEntity : public CRuleEntity
  76. {
  77. public:
  78. DECLARE_CLASS( CRuleBrushEntity, CRuleEntity );
  79. void Spawn( void );
  80. private:
  81. };
  82. void CRuleBrushEntity::Spawn( void )
  83. {
  84. SetModel( STRING( GetModelName() ) );
  85. BaseClass::Spawn();
  86. }
  87. // CGameScore / game_score -- award points to player / team
  88. // Points +/- total
  89. // Flag: Allow negative scores SF_SCORE_NEGATIVE
  90. // Flag: Award points to team in teamplay SF_SCORE_TEAM
  91. #define SF_SCORE_NEGATIVE 0x0001
  92. #define SF_SCORE_TEAM 0x0002
  93. class CGameScore : public CRulePointEntity
  94. {
  95. public:
  96. DECLARE_CLASS( CGameScore, CRulePointEntity );
  97. DECLARE_DATADESC();
  98. void Spawn( void );
  99. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  100. bool KeyValue( const char *szKeyName, const char *szValue );
  101. inline int Points( void ) { return m_Score; }
  102. inline bool AllowNegativeScore( void ) { return m_spawnflags & SF_SCORE_NEGATIVE; }
  103. inline int AwardToTeam( void ) { return (m_spawnflags & SF_SCORE_TEAM); }
  104. inline void SetPoints( int points ) { m_Score = points; }
  105. void InputApplyScore( inputdata_t &inputdata );
  106. private:
  107. };
  108. LINK_ENTITY_TO_CLASS( game_score, CGameScore );
  109. BEGIN_DATADESC( CGameScore )
  110. // Inputs
  111. DEFINE_INPUTFUNC( FIELD_VOID, "ApplyScore", InputApplyScore ),
  112. END_DATADESC()
  113. void CGameScore::Spawn( void )
  114. {
  115. int iScore = Points();
  116. BaseClass::Spawn();
  117. SetPoints( iScore );
  118. }
  119. bool CGameScore::KeyValue( const char *szKeyName, const char *szValue )
  120. {
  121. if (FStrEq(szKeyName, "points"))
  122. {
  123. SetPoints( atoi(szValue) );
  124. }
  125. else
  126. return BaseClass::KeyValue( szKeyName, szValue );
  127. return true;
  128. }
  129. void CGameScore::InputApplyScore( inputdata_t &inputdata )
  130. {
  131. CBaseEntity *pActivator = inputdata.pActivator;
  132. if ( pActivator == NULL )
  133. return;
  134. if ( CanFireForActivator( pActivator ) == false )
  135. return;
  136. // Only players can use this
  137. if ( pActivator->IsPlayer() )
  138. {
  139. if ( AwardToTeam() )
  140. {
  141. pActivator->AddPointsToTeam( Points(), AllowNegativeScore() );
  142. }
  143. else
  144. {
  145. pActivator->AddPoints( Points(), AllowNegativeScore() );
  146. }
  147. }
  148. }
  149. void CGameScore::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  150. {
  151. if ( !CanFireForActivator( pActivator ) )
  152. return;
  153. // Only players can use this
  154. if ( pActivator->IsPlayer() )
  155. {
  156. if ( AwardToTeam() )
  157. {
  158. pActivator->AddPointsToTeam( Points(), AllowNegativeScore() );
  159. }
  160. else
  161. {
  162. pActivator->AddPoints( Points(), AllowNegativeScore() );
  163. }
  164. }
  165. }
  166. // CGameEnd / game_end -- Ends the game in MP
  167. class CGameEnd : public CRulePointEntity
  168. {
  169. DECLARE_CLASS( CGameEnd, CRulePointEntity );
  170. public:
  171. DECLARE_DATADESC();
  172. void InputGameEnd( inputdata_t &inputdata );
  173. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  174. private:
  175. };
  176. BEGIN_DATADESC( CGameEnd )
  177. // inputs
  178. DEFINE_INPUTFUNC( FIELD_VOID, "EndGame", InputGameEnd ),
  179. END_DATADESC()
  180. LINK_ENTITY_TO_CLASS( game_end, CGameEnd );
  181. void CGameEnd::InputGameEnd( inputdata_t &inputdata )
  182. {
  183. g_pGameRules->EndMultiplayerGame();
  184. }
  185. void CGameEnd::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  186. {
  187. if ( !CanFireForActivator( pActivator ) )
  188. return;
  189. g_pGameRules->EndMultiplayerGame();
  190. }
  191. //
  192. // CGameText / game_text -- NON-Localized HUD Message (use env_message to display a titles.txt message)
  193. // Flag: All players SF_ENVTEXT_ALLPLAYERS
  194. //
  195. #define SF_ENVTEXT_ALLPLAYERS 0x0001
  196. class CGameText : public CRulePointEntity
  197. {
  198. public:
  199. DECLARE_CLASS( CGameText, CRulePointEntity );
  200. bool KeyValue( const char *szKeyName, const char *szValue );
  201. DECLARE_DATADESC();
  202. inline bool MessageToAll( void ) { return (m_spawnflags & SF_ENVTEXT_ALLPLAYERS); }
  203. inline void MessageSet( const char *pMessage ) { m_iszMessage = AllocPooledString(pMessage); }
  204. inline const char *MessageGet( void ) { return STRING( m_iszMessage ); }
  205. void InputDisplay( inputdata_t &inputdata );
  206. void Display( CBaseEntity *pActivator );
  207. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  208. {
  209. Display( pActivator );
  210. }
  211. private:
  212. string_t m_iszMessage;
  213. hudtextparms_t m_textParms;
  214. };
  215. LINK_ENTITY_TO_CLASS( game_text, CGameText );
  216. // Save parms as a block. Will break save/restore if the structure changes, but this entity didn't ship with Half-Life, so
  217. // it can't impact saved Half-Life games.
  218. BEGIN_DATADESC( CGameText )
  219. DEFINE_KEYFIELD( m_iszMessage, FIELD_STRING, "message" ),
  220. DEFINE_KEYFIELD( m_textParms.channel, FIELD_INTEGER, "channel" ),
  221. DEFINE_KEYFIELD( m_textParms.x, FIELD_FLOAT, "x" ),
  222. DEFINE_KEYFIELD( m_textParms.y, FIELD_FLOAT, "y" ),
  223. DEFINE_KEYFIELD( m_textParms.effect, FIELD_INTEGER, "effect" ),
  224. DEFINE_KEYFIELD( m_textParms.fadeinTime, FIELD_FLOAT, "fadein" ),
  225. DEFINE_KEYFIELD( m_textParms.fadeoutTime, FIELD_FLOAT, "fadeout" ),
  226. DEFINE_KEYFIELD( m_textParms.holdTime, FIELD_FLOAT, "holdtime" ),
  227. DEFINE_KEYFIELD( m_textParms.fxTime, FIELD_FLOAT, "fxtime" ),
  228. DEFINE_ARRAY( m_textParms, FIELD_CHARACTER, sizeof(hudtextparms_t) ),
  229. // Inputs
  230. DEFINE_INPUTFUNC( FIELD_VOID, "Display", InputDisplay ),
  231. END_DATADESC()
  232. bool CGameText::KeyValue( const char *szKeyName, const char *szValue )
  233. {
  234. if (FStrEq(szKeyName, "color"))
  235. {
  236. int color[4];
  237. UTIL_StringToIntArray( color, 4, szValue );
  238. m_textParms.r1 = color[0];
  239. m_textParms.g1 = color[1];
  240. m_textParms.b1 = color[2];
  241. m_textParms.a1 = color[3];
  242. }
  243. else if (FStrEq(szKeyName, "color2"))
  244. {
  245. int color[4];
  246. UTIL_StringToIntArray( color, 4, szValue );
  247. m_textParms.r2 = color[0];
  248. m_textParms.g2 = color[1];
  249. m_textParms.b2 = color[2];
  250. m_textParms.a2 = color[3];
  251. }
  252. else
  253. return BaseClass::KeyValue( szKeyName, szValue );
  254. return true;
  255. }
  256. void CGameText::InputDisplay( inputdata_t &inputdata )
  257. {
  258. Display( inputdata.pActivator );
  259. }
  260. void CGameText::Display( CBaseEntity *pActivator )
  261. {
  262. if ( !CanFireForActivator( pActivator ) )
  263. return;
  264. if ( MessageToAll() )
  265. {
  266. UTIL_HudMessageAll( m_textParms, MessageGet() );
  267. }
  268. else
  269. {
  270. // If we're in singleplayer, show the message to the player.
  271. if ( gpGlobals->maxClients == 1 )
  272. {
  273. CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
  274. UTIL_HudMessage( pPlayer, m_textParms, MessageGet() );
  275. }
  276. // Otherwise show the message to the player that triggered us.
  277. else if ( pActivator && pActivator->IsNetClient() )
  278. {
  279. UTIL_HudMessage( ToBasePlayer( pActivator ), m_textParms, MessageGet() );
  280. }
  281. }
  282. }
  283. /* TODO: Replace with an entity I/O version
  284. //
  285. // CGameTeamSet / game_team_set -- Changes the team of the entity it targets to the activator's team
  286. // Flag: Fire once
  287. // Flag: Clear team -- Sets the team to "NONE" instead of activator
  288. #define SF_TEAMSET_FIREONCE 0x0001
  289. #define SF_TEAMSET_CLEARTEAM 0x0002
  290. class CGameTeamSet : public CRulePointEntity
  291. {
  292. public:
  293. DECLARE_CLASS( CGameTeamSet, CRulePointEntity );
  294. inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_TEAMSET_FIREONCE) ? true : false; }
  295. inline bool ShouldClearTeam( void ) { return (m_spawnflags & SF_TEAMSET_CLEARTEAM) ? true : false; }
  296. void InputTrigger( inputdata_t &inputdata );
  297. private:
  298. COutputEvent m_OnTrigger;
  299. };
  300. LINK_ENTITY_TO_CLASS( game_team_set, CGameTeamSet );
  301. void CGameTeamSet::InputTrigger( inputdata_t &inputdata )
  302. {
  303. if ( !CanFireForActivator( inputdata.pActivator ) )
  304. return;
  305. if ( ShouldClearTeam() )
  306. {
  307. // clear the team of our target
  308. }
  309. else
  310. {
  311. // set the team of our target to our activator's team
  312. }
  313. m_OnTrigger.FireOutput(pActivator, this);
  314. if ( RemoveOnFire() )
  315. {
  316. UTIL_Remove( this );
  317. }
  318. }
  319. */
  320. //
  321. // CGamePlayerZone / game_player_zone -- players in the zone fire my target when I'm fired
  322. //
  323. // Needs master?
  324. class CGamePlayerZone : public CRuleBrushEntity
  325. {
  326. public:
  327. DECLARE_CLASS( CGamePlayerZone, CRuleBrushEntity );
  328. void InputCountPlayersInZone( inputdata_t &inputdata );
  329. DECLARE_DATADESC();
  330. private:
  331. COutputEvent m_OnPlayerInZone;
  332. COutputEvent m_OnPlayerOutZone;
  333. COutputInt m_PlayersInCount;
  334. COutputInt m_PlayersOutCount;
  335. };
  336. LINK_ENTITY_TO_CLASS( game_zone_player, CGamePlayerZone );
  337. BEGIN_DATADESC( CGamePlayerZone )
  338. // Inputs
  339. DEFINE_INPUTFUNC(FIELD_VOID, "CountPlayersInZone", InputCountPlayersInZone),
  340. // Outputs
  341. DEFINE_OUTPUT(m_OnPlayerInZone, "OnPlayerInZone"),
  342. DEFINE_OUTPUT(m_OnPlayerOutZone, "OnPlayerOutZone"),
  343. DEFINE_OUTPUT(m_PlayersInCount, "PlayersInCount"),
  344. DEFINE_OUTPUT(m_PlayersOutCount, "PlayersOutCount"),
  345. END_DATADESC()
  346. //-----------------------------------------------------------------------------
  347. // Purpose: Counts all the players in the zone. Fires one output per player
  348. // in the zone, one output per player out of the zone, and outputs
  349. // with the total counts of players in and out of the zone.
  350. //-----------------------------------------------------------------------------
  351. void CGamePlayerZone::InputCountPlayersInZone( inputdata_t &inputdata )
  352. {
  353. int playersInCount = 0;
  354. int playersOutCount = 0;
  355. if ( !CanFireForActivator( inputdata.pActivator ) )
  356. return;
  357. CBaseEntity *pPlayer = NULL;
  358. for ( int i = 1; i <= gpGlobals->maxClients; i++ )
  359. {
  360. pPlayer = UTIL_PlayerByIndex( i );
  361. if ( pPlayer )
  362. {
  363. trace_t trace;
  364. Hull_t hullType;
  365. hullType = HULL_HUMAN;
  366. if ( pPlayer->GetFlags() & FL_DUCKING )
  367. {
  368. hullType = HULL_SMALL_CENTERED;
  369. }
  370. UTIL_TraceModel( pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin(), NAI_Hull::Mins(hullType),
  371. NAI_Hull::Maxs(hullType), this, COLLISION_GROUP_NONE, &trace );
  372. if ( trace.startsolid )
  373. {
  374. playersInCount++;
  375. m_OnPlayerInZone.FireOutput(pPlayer, this);
  376. }
  377. else
  378. {
  379. playersOutCount++;
  380. m_OnPlayerOutZone.FireOutput(pPlayer, this);
  381. }
  382. }
  383. }
  384. m_PlayersInCount.Set(playersInCount, inputdata.pActivator, this);
  385. m_PlayersOutCount.Set(playersOutCount, inputdata.pActivator, this);
  386. }
  387. /*
  388. // Disable. Eventually will be replace by new activator filter entities. (LHL)
  389. //
  390. // CGamePlayerHurt / game_player_hurt -- Damages the player who fires it
  391. // Flag: Fire once
  392. #define SF_PKILL_FIREONCE 0x0001
  393. class CGamePlayerHurt : public CRulePointEntity
  394. {
  395. public:
  396. DECLARE_CLASS( CGamePlayerHurt, CRulePointEntity );
  397. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  398. inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_PKILL_FIREONCE) ? true : false; }
  399. DECLARE_DATADESC();
  400. private:
  401. float m_flDamage; // Damage to inflict, negative values give health.
  402. COutputEvent m_OnUse;
  403. };
  404. LINK_ENTITY_TO_CLASS( game_player_hurt, CGamePlayerHurt );
  405. BEGIN_DATADESC( CGamePlayerHurt )
  406. DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "dmg" ),
  407. END_DATADESC()
  408. void CGamePlayerHurt::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  409. {
  410. if ( !CanFireForActivator( pActivator ) )
  411. return;
  412. if ( pActivator->IsPlayer() )
  413. {
  414. if ( m_flDamage < 0 )
  415. {
  416. pActivator->TakeHealth( -m_flDamage, DMG_GENERIC );
  417. }
  418. else
  419. {
  420. pActivator->TakeDamage( this, this, m_flDamage, DMG_GENERIC );
  421. }
  422. }
  423. SUB_UseTargets( pActivator, useType, value );
  424. m_OnUse.FireOutput(pActivator, this); // dvsents2: handle useType and value here - they are passed through
  425. if ( RemoveOnFire() )
  426. {
  427. UTIL_Remove( this );
  428. }
  429. }
  430. */
  431. //
  432. // CGamePlayerEquip / game_playerequip -- Sets the default player equipment
  433. // Flag: USE Only
  434. #define SF_PLAYEREQUIP_USEONLY 0x0001
  435. #define MAX_EQUIP 32
  436. class CGamePlayerEquip : public CRulePointEntity
  437. {
  438. DECLARE_DATADESC();
  439. public:
  440. DECLARE_CLASS( CGamePlayerEquip, CRulePointEntity );
  441. bool KeyValue( const char *szKeyName, const char *szValue );
  442. void Touch( CBaseEntity *pOther );
  443. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  444. inline bool UseOnly( void ) { return (m_spawnflags & SF_PLAYEREQUIP_USEONLY) ? true : false; }
  445. private:
  446. void EquipPlayer( CBaseEntity *pPlayer );
  447. string_t m_weaponNames[MAX_EQUIP];
  448. int m_weaponCount[MAX_EQUIP];
  449. };
  450. LINK_ENTITY_TO_CLASS( game_player_equip, CGamePlayerEquip );
  451. //---------------------------------------------------------
  452. // Save/Restore
  453. //---------------------------------------------------------
  454. BEGIN_DATADESC( CGamePlayerEquip )
  455. DEFINE_AUTO_ARRAY( m_weaponNames, FIELD_STRING ),
  456. DEFINE_AUTO_ARRAY( m_weaponCount, FIELD_INTEGER ),
  457. END_DATADESC()
  458. bool CGamePlayerEquip::KeyValue( const char *szKeyName, const char *szValue )
  459. {
  460. if ( !BaseClass::KeyValue( szKeyName, szValue ) )
  461. {
  462. for ( int i = 0; i < MAX_EQUIP; i++ )
  463. {
  464. if ( !m_weaponNames[i] )
  465. {
  466. char tmp[128];
  467. UTIL_StripToken( szKeyName, tmp, Q_ARRAYSIZE( tmp ) );
  468. m_weaponNames[i] = AllocPooledString(tmp);
  469. m_weaponCount[i] = atoi(szValue);
  470. m_weaponCount[i] = MAX(1,m_weaponCount[i]);
  471. return true;
  472. }
  473. }
  474. }
  475. return false;
  476. }
  477. void CGamePlayerEquip::Touch( CBaseEntity *pOther )
  478. {
  479. if ( !CanFireForActivator( pOther ) )
  480. return;
  481. if ( UseOnly() )
  482. return;
  483. EquipPlayer( pOther );
  484. }
  485. void CGamePlayerEquip::EquipPlayer( CBaseEntity *pEntity )
  486. {
  487. CBasePlayer *pPlayer = ToBasePlayer(pEntity);
  488. if ( !pPlayer )
  489. return;
  490. for ( int i = 0; i < MAX_EQUIP; i++ )
  491. {
  492. if ( !m_weaponNames[i] )
  493. break;
  494. for ( int j = 0; j < m_weaponCount[i]; j++ )
  495. {
  496. pPlayer->GiveNamedItem( STRING(m_weaponNames[i]) );
  497. }
  498. }
  499. }
  500. void CGamePlayerEquip::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  501. {
  502. EquipPlayer( pActivator );
  503. }
  504. //
  505. // CGamePlayerTeam / game_player_team -- Changes the team of the player who fired it
  506. // Flag: Fire once
  507. // Flag: Kill Player
  508. // Flag: Gib Player
  509. #define SF_PTEAM_FIREONCE 0x0001
  510. #define SF_PTEAM_KILL 0x0002
  511. #define SF_PTEAM_GIB 0x0004
  512. class CGamePlayerTeam : public CRulePointEntity
  513. {
  514. public:
  515. DECLARE_CLASS( CGamePlayerTeam, CRulePointEntity );
  516. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  517. private:
  518. inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_PTEAM_FIREONCE) ? true : false; }
  519. inline bool ShouldKillPlayer( void ) { return (m_spawnflags & SF_PTEAM_KILL) ? true : false; }
  520. inline bool ShouldGibPlayer( void ) { return (m_spawnflags & SF_PTEAM_GIB) ? true : false; }
  521. const char *TargetTeamName( const char *pszTargetName, CBaseEntity *pActivator );
  522. };
  523. LINK_ENTITY_TO_CLASS( game_player_team, CGamePlayerTeam );
  524. const char *CGamePlayerTeam::TargetTeamName( const char *pszTargetName, CBaseEntity *pActivator )
  525. {
  526. CBaseEntity *pTeamEntity = NULL;
  527. while ((pTeamEntity = gEntList.FindEntityByName( pTeamEntity, pszTargetName, NULL, pActivator )) != NULL)
  528. {
  529. if ( FClassnameIs( pTeamEntity, "game_team_master" ) )
  530. return pTeamEntity->TeamID();
  531. }
  532. return NULL;
  533. }
  534. void CGamePlayerTeam::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  535. {
  536. if ( !CanFireForActivator( pActivator ) )
  537. return;
  538. if ( pActivator->IsPlayer() )
  539. {
  540. const char *pszTargetTeam = TargetTeamName( STRING(m_target), pActivator );
  541. if ( pszTargetTeam )
  542. {
  543. CBasePlayer *pPlayer = (CBasePlayer *)pActivator;
  544. g_pGameRules->ChangePlayerTeam( pPlayer, pszTargetTeam, ShouldKillPlayer(), ShouldGibPlayer() );
  545. }
  546. }
  547. if ( RemoveOnFire() )
  548. {
  549. UTIL_Remove( this );
  550. }
  551. }