diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/server/maprules.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/server/maprules.cpp')
| -rw-r--r-- | mp/src/game/server/maprules.cpp | 737 |
1 files changed, 737 insertions, 0 deletions
diff --git a/mp/src/game/server/maprules.cpp b/mp/src/game/server/maprules.cpp new file mode 100644 index 00000000..23c43a3c --- /dev/null +++ b/mp/src/game/server/maprules.cpp @@ -0,0 +1,737 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Contains entities for implementing/changing game rules dynamically within each BSP.
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "datamap.h"
+#include "gamerules.h"
+#include "maprules.h"
+#include "player.h"
+#include "entitylist.h"
+#include "ai_hull.h"
+#include "entityoutput.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+class CRuleEntity : public CBaseEntity
+{
+public:
+ DECLARE_CLASS( CRuleEntity, CBaseEntity );
+
+ void Spawn( void );
+
+ DECLARE_DATADESC();
+
+ void SetMaster( string_t iszMaster ) { m_iszMaster = iszMaster; }
+
+protected:
+ bool CanFireForActivator( CBaseEntity *pActivator );
+
+private:
+ string_t m_iszMaster;
+};
+
+BEGIN_DATADESC( CRuleEntity )
+
+ DEFINE_KEYFIELD( m_iszMaster, FIELD_STRING, "master" ),
+
+END_DATADESC()
+
+
+
+void CRuleEntity::Spawn( void )
+{
+ SetSolid( SOLID_NONE );
+ SetMoveType( MOVETYPE_NONE );
+ AddEffects( EF_NODRAW );
+}
+
+
+bool CRuleEntity::CanFireForActivator( CBaseEntity *pActivator )
+{
+ if ( m_iszMaster != NULL_STRING )
+ {
+ if ( UTIL_IsMasterTriggered( m_iszMaster, pActivator ) )
+ return true;
+ else
+ return false;
+ }
+
+ return true;
+}
+
+//
+// CRulePointEntity -- base class for all rule "point" entities (not brushes)
+//
+class CRulePointEntity : public CRuleEntity
+{
+public:
+ DECLARE_DATADESC();
+ DECLARE_CLASS( CRulePointEntity, CRuleEntity );
+
+ int m_Score;
+ void Spawn( void );
+};
+
+//---------------------------------------------------------
+// Save/Restore
+//---------------------------------------------------------
+BEGIN_DATADESC( CRulePointEntity )
+
+ DEFINE_FIELD( m_Score, FIELD_INTEGER ),
+
+END_DATADESC()
+
+
+void CRulePointEntity::Spawn( void )
+{
+ BaseClass::Spawn();
+ SetModelName( NULL_STRING );
+ m_Score = 0;
+}
+
+//
+// CRuleBrushEntity -- base class for all rule "brush" entities (not brushes)
+// Default behavior is to set up like a trigger, invisible, but keep the model for volume testing
+//
+class CRuleBrushEntity : public CRuleEntity
+{
+public:
+ DECLARE_CLASS( CRuleBrushEntity, CRuleEntity );
+
+ void Spawn( void );
+
+private:
+};
+
+void CRuleBrushEntity::Spawn( void )
+{
+ SetModel( STRING( GetModelName() ) );
+ BaseClass::Spawn();
+}
+
+
+// CGameScore / game_score -- award points to player / team
+// Points +/- total
+// Flag: Allow negative scores SF_SCORE_NEGATIVE
+// Flag: Award points to team in teamplay SF_SCORE_TEAM
+
+#define SF_SCORE_NEGATIVE 0x0001
+#define SF_SCORE_TEAM 0x0002
+
+class CGameScore : public CRulePointEntity
+{
+public:
+ DECLARE_CLASS( CGameScore, CRulePointEntity );
+ DECLARE_DATADESC();
+
+ void Spawn( void );
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+ bool KeyValue( const char *szKeyName, const char *szValue );
+
+ inline int Points( void ) { return m_Score; }
+ inline bool AllowNegativeScore( void ) { return m_spawnflags & SF_SCORE_NEGATIVE; }
+ inline int AwardToTeam( void ) { return (m_spawnflags & SF_SCORE_TEAM); }
+
+ inline void SetPoints( int points ) { m_Score = points; }
+
+ void InputApplyScore( inputdata_t &inputdata );
+
+private:
+};
+
+LINK_ENTITY_TO_CLASS( game_score, CGameScore );
+
+BEGIN_DATADESC( CGameScore )
+ // Inputs
+ DEFINE_INPUTFUNC( FIELD_VOID, "ApplyScore", InputApplyScore ),
+END_DATADESC()
+
+void CGameScore::Spawn( void )
+{
+ int iScore = Points();
+ BaseClass::Spawn();
+ SetPoints( iScore );
+}
+
+
+bool CGameScore::KeyValue( const char *szKeyName, const char *szValue )
+{
+ if (FStrEq(szKeyName, "points"))
+ {
+ SetPoints( atoi(szValue) );
+ }
+ else
+ return BaseClass::KeyValue( szKeyName, szValue );
+
+ return true;
+}
+
+void CGameScore::InputApplyScore( inputdata_t &inputdata )
+{
+ CBaseEntity *pActivator = inputdata.pActivator;
+
+ if ( pActivator == NULL )
+ return;
+
+ if ( CanFireForActivator( pActivator ) == false )
+ return;
+
+ // Only players can use this
+ if ( pActivator->IsPlayer() )
+ {
+ if ( AwardToTeam() )
+ {
+ pActivator->AddPointsToTeam( Points(), AllowNegativeScore() );
+ }
+ else
+ {
+ pActivator->AddPoints( Points(), AllowNegativeScore() );
+ }
+ }
+}
+
+void CGameScore::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ if ( !CanFireForActivator( pActivator ) )
+ return;
+
+ // Only players can use this
+ if ( pActivator->IsPlayer() )
+ {
+ if ( AwardToTeam() )
+ {
+ pActivator->AddPointsToTeam( Points(), AllowNegativeScore() );
+ }
+ else
+ {
+ pActivator->AddPoints( Points(), AllowNegativeScore() );
+ }
+ }
+}
+
+
+// CGameEnd / game_end -- Ends the game in MP
+
+class CGameEnd : public CRulePointEntity
+{
+ DECLARE_CLASS( CGameEnd, CRulePointEntity );
+
+public:
+ DECLARE_DATADESC();
+
+ void InputGameEnd( inputdata_t &inputdata );
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+private:
+};
+
+BEGIN_DATADESC( CGameEnd )
+
+ // inputs
+ DEFINE_INPUTFUNC( FIELD_VOID, "EndGame", InputGameEnd ),
+
+END_DATADESC()
+
+LINK_ENTITY_TO_CLASS( game_end, CGameEnd );
+
+
+void CGameEnd::InputGameEnd( inputdata_t &inputdata )
+{
+ g_pGameRules->EndMultiplayerGame();
+}
+
+void CGameEnd::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ if ( !CanFireForActivator( pActivator ) )
+ return;
+
+ g_pGameRules->EndMultiplayerGame();
+}
+
+
+//
+// CGameText / game_text -- NON-Localized HUD Message (use env_message to display a titles.txt message)
+// Flag: All players SF_ENVTEXT_ALLPLAYERS
+//
+#define SF_ENVTEXT_ALLPLAYERS 0x0001
+
+
+class CGameText : public CRulePointEntity
+{
+public:
+ DECLARE_CLASS( CGameText, CRulePointEntity );
+
+ bool KeyValue( const char *szKeyName, const char *szValue );
+
+ DECLARE_DATADESC();
+
+ inline bool MessageToAll( void ) { return (m_spawnflags & SF_ENVTEXT_ALLPLAYERS); }
+ inline void MessageSet( const char *pMessage ) { m_iszMessage = AllocPooledString(pMessage); }
+ inline const char *MessageGet( void ) { return STRING( m_iszMessage ); }
+
+ void InputDisplay( inputdata_t &inputdata );
+ void Display( CBaseEntity *pActivator );
+
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+ {
+ Display( pActivator );
+ }
+
+private:
+
+ string_t m_iszMessage;
+ hudtextparms_t m_textParms;
+};
+
+LINK_ENTITY_TO_CLASS( game_text, CGameText );
+
+// Save parms as a block. Will break save/restore if the structure changes, but this entity didn't ship with Half-Life, so
+// it can't impact saved Half-Life games.
+BEGIN_DATADESC( CGameText )
+
+ DEFINE_KEYFIELD( m_iszMessage, FIELD_STRING, "message" ),
+
+ DEFINE_KEYFIELD( m_textParms.channel, FIELD_INTEGER, "channel" ),
+ DEFINE_KEYFIELD( m_textParms.x, FIELD_FLOAT, "x" ),
+ DEFINE_KEYFIELD( m_textParms.y, FIELD_FLOAT, "y" ),
+ DEFINE_KEYFIELD( m_textParms.effect, FIELD_INTEGER, "effect" ),
+ DEFINE_KEYFIELD( m_textParms.fadeinTime, FIELD_FLOAT, "fadein" ),
+ DEFINE_KEYFIELD( m_textParms.fadeoutTime, FIELD_FLOAT, "fadeout" ),
+ DEFINE_KEYFIELD( m_textParms.holdTime, FIELD_FLOAT, "holdtime" ),
+ DEFINE_KEYFIELD( m_textParms.fxTime, FIELD_FLOAT, "fxtime" ),
+
+ DEFINE_ARRAY( m_textParms, FIELD_CHARACTER, sizeof(hudtextparms_t) ),
+
+ // Inputs
+ DEFINE_INPUTFUNC( FIELD_VOID, "Display", InputDisplay ),
+
+END_DATADESC()
+
+
+
+bool CGameText::KeyValue( const char *szKeyName, const char *szValue )
+{
+ if (FStrEq(szKeyName, "color"))
+ {
+ int color[4];
+ UTIL_StringToIntArray( color, 4, szValue );
+ m_textParms.r1 = color[0];
+ m_textParms.g1 = color[1];
+ m_textParms.b1 = color[2];
+ m_textParms.a1 = color[3];
+ }
+ else if (FStrEq(szKeyName, "color2"))
+ {
+ int color[4];
+ UTIL_StringToIntArray( color, 4, szValue );
+ m_textParms.r2 = color[0];
+ m_textParms.g2 = color[1];
+ m_textParms.b2 = color[2];
+ m_textParms.a2 = color[3];
+ }
+ else
+ return BaseClass::KeyValue( szKeyName, szValue );
+
+ return true;
+}
+
+
+void CGameText::InputDisplay( inputdata_t &inputdata )
+{
+ Display( inputdata.pActivator );
+}
+
+void CGameText::Display( CBaseEntity *pActivator )
+{
+ if ( !CanFireForActivator( pActivator ) )
+ return;
+
+ if ( MessageToAll() )
+ {
+ UTIL_HudMessageAll( m_textParms, MessageGet() );
+ }
+ else
+ {
+ // If we're in singleplayer, show the message to the player.
+ if ( gpGlobals->maxClients == 1 )
+ {
+ CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
+ UTIL_HudMessage( pPlayer, m_textParms, MessageGet() );
+ }
+ // Otherwise show the message to the player that triggered us.
+ else if ( pActivator && pActivator->IsNetClient() )
+ {
+ UTIL_HudMessage( ToBasePlayer( pActivator ), m_textParms, MessageGet() );
+ }
+ }
+}
+
+
+/* TODO: Replace with an entity I/O version
+//
+// CGameTeamSet / game_team_set -- Changes the team of the entity it targets to the activator's team
+// Flag: Fire once
+// Flag: Clear team -- Sets the team to "NONE" instead of activator
+
+#define SF_TEAMSET_FIREONCE 0x0001
+#define SF_TEAMSET_CLEARTEAM 0x0002
+
+class CGameTeamSet : public CRulePointEntity
+{
+public:
+ DECLARE_CLASS( CGameTeamSet, CRulePointEntity );
+
+ inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_TEAMSET_FIREONCE) ? true : false; }
+ inline bool ShouldClearTeam( void ) { return (m_spawnflags & SF_TEAMSET_CLEARTEAM) ? true : false; }
+ void InputTrigger( inputdata_t &inputdata );
+
+private:
+ COutputEvent m_OnTrigger;
+};
+
+LINK_ENTITY_TO_CLASS( game_team_set, CGameTeamSet );
+
+
+void CGameTeamSet::InputTrigger( inputdata_t &inputdata )
+{
+ if ( !CanFireForActivator( inputdata.pActivator ) )
+ return;
+
+ if ( ShouldClearTeam() )
+ {
+ // clear the team of our target
+ }
+ else
+ {
+ // set the team of our target to our activator's team
+ }
+
+ m_OnTrigger.FireOutput(pActivator, this);
+
+ if ( RemoveOnFire() )
+ {
+ UTIL_Remove( this );
+ }
+}
+*/
+
+
+//
+// CGamePlayerZone / game_player_zone -- players in the zone fire my target when I'm fired
+//
+// Needs master?
+class CGamePlayerZone : public CRuleBrushEntity
+{
+public:
+ DECLARE_CLASS( CGamePlayerZone, CRuleBrushEntity );
+ void InputCountPlayersInZone( inputdata_t &inputdata );
+
+ DECLARE_DATADESC();
+
+private:
+
+ COutputEvent m_OnPlayerInZone;
+ COutputEvent m_OnPlayerOutZone;
+
+ COutputInt m_PlayersInCount;
+ COutputInt m_PlayersOutCount;
+};
+
+LINK_ENTITY_TO_CLASS( game_zone_player, CGamePlayerZone );
+BEGIN_DATADESC( CGamePlayerZone )
+
+ // Inputs
+ DEFINE_INPUTFUNC(FIELD_VOID, "CountPlayersInZone", InputCountPlayersInZone),
+
+ // Outputs
+ DEFINE_OUTPUT(m_OnPlayerInZone, "OnPlayerInZone"),
+ DEFINE_OUTPUT(m_OnPlayerOutZone, "OnPlayerOutZone"),
+ DEFINE_OUTPUT(m_PlayersInCount, "PlayersInCount"),
+ DEFINE_OUTPUT(m_PlayersOutCount, "PlayersOutCount"),
+
+END_DATADESC()
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Counts all the players in the zone. Fires one output per player
+// in the zone, one output per player out of the zone, and outputs
+// with the total counts of players in and out of the zone.
+//-----------------------------------------------------------------------------
+void CGamePlayerZone::InputCountPlayersInZone( inputdata_t &inputdata )
+{
+ int playersInCount = 0;
+ int playersOutCount = 0;
+
+ if ( !CanFireForActivator( inputdata.pActivator ) )
+ return;
+
+ CBaseEntity *pPlayer = NULL;
+
+ for ( int i = 1; i <= gpGlobals->maxClients; i++ )
+ {
+ pPlayer = UTIL_PlayerByIndex( i );
+ if ( pPlayer )
+ {
+ trace_t trace;
+ Hull_t hullType;
+
+ hullType = HULL_HUMAN;
+ if ( pPlayer->GetFlags() & FL_DUCKING )
+ {
+ hullType = HULL_SMALL_CENTERED;
+ }
+
+ UTIL_TraceModel( pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin(), NAI_Hull::Mins(hullType),
+ NAI_Hull::Maxs(hullType), this, COLLISION_GROUP_NONE, &trace );
+
+ if ( trace.startsolid )
+ {
+ playersInCount++;
+ m_OnPlayerInZone.FireOutput(pPlayer, this);
+ }
+ else
+ {
+ playersOutCount++;
+ m_OnPlayerOutZone.FireOutput(pPlayer, this);
+ }
+ }
+ }
+
+ m_PlayersInCount.Set(playersInCount, inputdata.pActivator, this);
+ m_PlayersOutCount.Set(playersOutCount, inputdata.pActivator, this);
+}
+
+
+/*
+// Disable. Eventually will be replace by new activator filter entities. (LHL)
+//
+// CGamePlayerHurt / game_player_hurt -- Damages the player who fires it
+// Flag: Fire once
+
+#define SF_PKILL_FIREONCE 0x0001
+class CGamePlayerHurt : public CRulePointEntity
+{
+public:
+ DECLARE_CLASS( CGamePlayerHurt, CRulePointEntity );
+
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+ inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_PKILL_FIREONCE) ? true : false; }
+
+ DECLARE_DATADESC();
+
+private:
+
+ float m_flDamage; // Damage to inflict, negative values give health.
+
+ COutputEvent m_OnUse;
+};
+
+LINK_ENTITY_TO_CLASS( game_player_hurt, CGamePlayerHurt );
+
+
+BEGIN_DATADESC( CGamePlayerHurt )
+
+ DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "dmg" ),
+
+END_DATADESC()
+
+
+
+void CGamePlayerHurt::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ if ( !CanFireForActivator( pActivator ) )
+ return;
+
+ if ( pActivator->IsPlayer() )
+ {
+ if ( m_flDamage < 0 )
+ {
+ pActivator->TakeHealth( -m_flDamage, DMG_GENERIC );
+ }
+ else
+ {
+ pActivator->TakeDamage( this, this, m_flDamage, DMG_GENERIC );
+ }
+ }
+
+ SUB_UseTargets( pActivator, useType, value );
+ m_OnUse.FireOutput(pActivator, this); // dvsents2: handle useType and value here - they are passed through
+
+ if ( RemoveOnFire() )
+ {
+ UTIL_Remove( this );
+ }
+}
+*/
+
+//
+// CGamePlayerEquip / game_playerequip -- Sets the default player equipment
+// Flag: USE Only
+
+#define SF_PLAYEREQUIP_USEONLY 0x0001
+#define MAX_EQUIP 32
+
+class CGamePlayerEquip : public CRulePointEntity
+{
+ DECLARE_DATADESC();
+
+public:
+ DECLARE_CLASS( CGamePlayerEquip, CRulePointEntity );
+
+ bool KeyValue( const char *szKeyName, const char *szValue );
+ void Touch( CBaseEntity *pOther );
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+
+ inline bool UseOnly( void ) { return (m_spawnflags & SF_PLAYEREQUIP_USEONLY) ? true : false; }
+
+private:
+
+ void EquipPlayer( CBaseEntity *pPlayer );
+
+ string_t m_weaponNames[MAX_EQUIP];
+ int m_weaponCount[MAX_EQUIP];
+};
+
+LINK_ENTITY_TO_CLASS( game_player_equip, CGamePlayerEquip );
+
+//---------------------------------------------------------
+// Save/Restore
+//---------------------------------------------------------
+BEGIN_DATADESC( CGamePlayerEquip )
+
+ DEFINE_AUTO_ARRAY( m_weaponNames, FIELD_STRING ),
+ DEFINE_AUTO_ARRAY( m_weaponCount, FIELD_INTEGER ),
+
+END_DATADESC()
+
+
+
+
+bool CGamePlayerEquip::KeyValue( const char *szKeyName, const char *szValue )
+{
+ if ( !BaseClass::KeyValue( szKeyName, szValue ) )
+ {
+ for ( int i = 0; i < MAX_EQUIP; i++ )
+ {
+ if ( !m_weaponNames[i] )
+ {
+ char tmp[128];
+
+ UTIL_StripToken( szKeyName, tmp );
+
+ m_weaponNames[i] = AllocPooledString(tmp);
+ m_weaponCount[i] = atoi(szValue);
+ m_weaponCount[i] = MAX(1,m_weaponCount[i]);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+void CGamePlayerEquip::Touch( CBaseEntity *pOther )
+{
+ if ( !CanFireForActivator( pOther ) )
+ return;
+
+ if ( UseOnly() )
+ return;
+
+ EquipPlayer( pOther );
+}
+
+void CGamePlayerEquip::EquipPlayer( CBaseEntity *pEntity )
+{
+ CBasePlayer *pPlayer = ToBasePlayer(pEntity);
+
+ if ( !pPlayer )
+ return;
+
+ for ( int i = 0; i < MAX_EQUIP; i++ )
+ {
+ if ( !m_weaponNames[i] )
+ break;
+ for ( int j = 0; j < m_weaponCount[i]; j++ )
+ {
+ pPlayer->GiveNamedItem( STRING(m_weaponNames[i]) );
+ }
+ }
+}
+
+
+void CGamePlayerEquip::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ EquipPlayer( pActivator );
+}
+
+
+//
+// CGamePlayerTeam / game_player_team -- Changes the team of the player who fired it
+// Flag: Fire once
+// Flag: Kill Player
+// Flag: Gib Player
+
+#define SF_PTEAM_FIREONCE 0x0001
+#define SF_PTEAM_KILL 0x0002
+#define SF_PTEAM_GIB 0x0004
+
+class CGamePlayerTeam : public CRulePointEntity
+{
+public:
+ DECLARE_CLASS( CGamePlayerTeam, CRulePointEntity );
+
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+
+private:
+
+ inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_PTEAM_FIREONCE) ? true : false; }
+ inline bool ShouldKillPlayer( void ) { return (m_spawnflags & SF_PTEAM_KILL) ? true : false; }
+ inline bool ShouldGibPlayer( void ) { return (m_spawnflags & SF_PTEAM_GIB) ? true : false; }
+
+ const char *TargetTeamName( const char *pszTargetName, CBaseEntity *pActivator );
+};
+
+LINK_ENTITY_TO_CLASS( game_player_team, CGamePlayerTeam );
+
+
+const char *CGamePlayerTeam::TargetTeamName( const char *pszTargetName, CBaseEntity *pActivator )
+{
+ CBaseEntity *pTeamEntity = NULL;
+
+ while ((pTeamEntity = gEntList.FindEntityByName( pTeamEntity, pszTargetName, NULL, pActivator )) != NULL)
+ {
+ if ( FClassnameIs( pTeamEntity, "game_team_master" ) )
+ return pTeamEntity->TeamID();
+ }
+
+ return NULL;
+}
+
+
+void CGamePlayerTeam::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ if ( !CanFireForActivator( pActivator ) )
+ return;
+
+ if ( pActivator->IsPlayer() )
+ {
+ const char *pszTargetTeam = TargetTeamName( STRING(m_target), pActivator );
+ if ( pszTargetTeam )
+ {
+ CBasePlayer *pPlayer = (CBasePlayer *)pActivator;
+ g_pGameRules->ChangePlayerTeam( pPlayer, pszTargetTeam, ShouldKillPlayer(), ShouldGibPlayer() );
+ }
+ }
+
+ if ( RemoveOnFire() )
+ {
+ UTIL_Remove( this );
+ }
+}
+
+
|