text: //========= Copyright Valve Corporation, All rights reserved. ============//
  //
  // Purpose: 
  //
  // $Workfile:     $
  // $NoKeywords: $
  //=============================================================================//
  #include "cbase.h"
  #include "model_types.h"
  #include "view_shared.h"
  #include "iviewrender.h"
  #include "tempentity.h"
  #include "dlight.h"
  #include "tempent.h"
  #include "c_te_legacytempents.h"
  #include "clientsideeffects.h"
  #include "cl_animevent.h"
  #include "iefx.h"
  #include "engine/IEngineSound.h"
  #include "env_wind_shared.h"
  #include "clienteffectprecachesystem.h"
  #include "fx_sparks.h"
  #include "fx.h"
  #include "movevars_shared.h"
  #include "engine/ivmodelinfo.h"
  #include "SoundEmitterSystem/isoundemittersystembase.h"
  #include "view.h"
  #include "tier0/vprof.h"
  #include "particles_localspace.h"
  #include "physpropclientside.h"
  #include "tier0/icommandline.h"
  #include "datacache/imdlcache.h"
  #include "engine/ivdebugoverlay.h"
  #include "effect_dispatch_data.h"
  #include "c_te_effect_dispatch.h"
  #include "c_props.h"
  #include "c_basedoor.h"
  
  // NOTE: Always include this last!
  #include "tier0/memdbgon.h"
  
  extern ConVar muzzleflash_light;
  
  #define TENT_WIND_ACCEL 50
  
  //Precache the effects
  #ifndef TF_CLIENT_DLL
  CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectMuzzleFlash )
  
  	CLIENTEFFECT_MATERIAL( "effects/muzzleflash1" )
  	CLIENTEFFECT_MATERIAL( "effects/muzzleflash2" )
  	CLIENTEFFECT_MATERIAL( "effects/muzzleflash3" )
  	CLIENTEFFECT_MATERIAL( "effects/muzzleflash4" )
  	CLIENTEFFECT_MATERIAL( "effects/muzzleflash1_noz" )
  	CLIENTEFFECT_MATERIAL( "effects/muzzleflash2_noz" )
  	CLIENTEFFECT_MATERIAL( "effects/muzzleflash3_noz" )
  	CLIENTEFFECT_MATERIAL( "effects/muzzleflash4_noz" )
  #ifndef CSTRIKE_DLL
  	CLIENTEFFECT_MATERIAL( "effects/combinemuzzle1" )
  	CLIENTEFFECT_MATERIAL( "effects/combinemuzzle2" )
  	CLIENTEFFECT_MATERIAL( "effects/combinemuzzle1_noz" )
  	CLIENTEFFECT_MATERIAL( "effects/combinemuzzle2_noz" )
  	CLIENTEFFECT_MATERIAL( "effects/strider_muzzle" )
  #endif
  CLIENTEFFECT_REGISTER_END()
  #endif
  
  //Whether or not to eject brass from weapons
  ConVar cl_ejectbrass( "cl_ejectbrass", "1" );
  
  ConVar func_break_max_pieces( "func_break_max_pieces", "15", FCVAR_ARCHIVE | FCVAR_REPLICATED );
  
  ConVar cl_fasttempentcollision( "cl_fasttempentcollision", "5" );
  
  #if !defined( HL1_CLIENT_DLL )		// HL1 implements a derivative of CTempEnts
  // Temp entity interface
  static CTempEnts g_TempEnts;
  // Expose to rest of the client .dll
  ITempEnts *tempents = ( ITempEnts * )&g_TempEnts;
  #endif
  
  
  
  
  C_LocalTempEntity::C_LocalTempEntity()
  {
  #ifdef _DEBUG
  	tentOffset.Init();
  	m_vecTempEntVelocity.Init();
  	m_vecTempEntAngVelocity.Init();
  	m_vecNormal.Init();
  #endif
  	m_vecTempEntAcceleration.Init();
  	m_pfnDrawHelper = 0;
  	m_pszImpactEffect = NULL;
  }
  
  
  //#if defined( CSTRIKE_DLL ) || defined (SDK_DLL )
  
  #define TE_RIFLE_SHELL 1024
  #define TE_PISTOL_SHELL 2048
  #define TE_SHOTGUN_SHELL 4096
  
  //#endif
  
  //-----------------------------------------------------------------------------
  // Purpose: Prepare a temp entity for creation
  // Input  : time - 
  //			*model - 
  //-----------------------------------------------------------------------------
  void C_LocalTempEntity::Prepare( const model_t *pmodel, float time )
  {
  	Interp_SetupMappings( GetVarMapping() );
  
  	index = -1;
  	Clear();
  
  	// Use these to set per-frame and termination conditions / actions
  	flags = FTENT_NONE;		
  	die = time + 0.75;
  	SetModelPointer( pmodel );
  	SetRenderMode( kRenderNormal );
  	m_nRenderFX = kRenderFxNone;
  	m_nBody = 0;
  	m_nSkin = 0;
  	fadeSpeed = 0.5;
  	hitSound = 0;
  	clientIndex = -1;
  	bounceFactor = 1;
  	m_nFlickerFrame = 0;
  	m_bParticleCollision = false;
  }
  
  //-----------------------------------------------------------------------------
  // Sets the velocity
  //-----------------------------------------------------------------------------
  void C_LocalTempEntity::SetVelocity( const Vector &vecVelocity )
  {
  	m_vecTempEntVelocity = vecVelocity;
  }
  
  //-----------------------------------------------------------------------------
  // Sets the velocity
  //-----------------------------------------------------------------------------
  void C_LocalTempEntity::SetAcceleration( const Vector &vecVelocity )
  {
  	m_vecTempEntAcceleration = vecVelocity;
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  // Output : int
  //-----------------------------------------------------------------------------
  int C_LocalTempEntity::DrawStudioModel( int flags )
  {
  	VPROF_BUDGET( "C_LocalTempEntity::DrawStudioModel", VPROF_BUDGETGROUP_MODEL_RENDERING );
  	int drawn = 0;
  
  	if ( !GetModel() || modelinfo->GetModelType( GetModel() ) != mod_studio )
  		return drawn;
  	
  	// Make sure m_pstudiohdr is valid for drawing
  	MDLCACHE_CRITICAL_SECTION();
  	if ( !GetModelPtr() )
  		return drawn;
  
  	if ( m_pfnDrawHelper )
  	{
  		drawn = ( *m_pfnDrawHelper )( this, flags );
  	}
  	else
  	{
  		drawn = modelrender->DrawModel( 
  			flags, 
  			this,
  			MODEL_INSTANCE_INVALID,
  			index, 
  			GetModel(),
  			GetAbsOrigin(),
  			GetAbsAngles(),
  			m_nSkin,
  			m_nBody,
  			m_nHitboxSet );
  	}
  	return drawn;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  // Input  : flags - 
  //-----------------------------------------------------------------------------
  int	C_LocalTempEntity::DrawModel( int flags )
  {
  	int drawn = 0;
  
  	if ( !GetModel() )
  	{
  		return drawn;
  	}
  
  	if ( GetRenderMode() == kRenderNone )
  		return drawn;
  
  	if ( this->flags & FTENT_BEOCCLUDED )
  	{
  		// Check normal
  		Vector vecDelta = (GetAbsOrigin() - MainViewOrigin());
  		VectorNormalize( vecDelta );
  		float flDot = DotProduct( m_vecNormal, vecDelta );
  		if ( flDot > 0 )
  		{
  			float flAlpha = RemapVal( MIN(flDot,0.3), 0, 0.3, 0, 1 );
  			flAlpha = MAX( 1.0, tempent_renderamt - (tempent_renderamt * flAlpha) );
  			SetRenderColorA( flAlpha );
  		}
  	}
  
  	switch ( modelinfo->GetModelType( GetModel() ) )
  	{
  	case mod_sprite:
  		drawn = DrawSprite( 
  			this,
  			GetModel(), 
  			GetAbsOrigin(), 
  			GetAbsAngles(), 
  			m_flFrame,  // sprite frame to render
  			m_nBody > 0 ? cl_entitylist->GetBaseEntity( m_nBody ) : NULL,  // attach to
  			m_nSkin,  // attachment point
  			GetRenderMode(), // rendermode
  			m_nRenderFX, // renderfx
  			m_clrRender->a, // alpha
  			m_clrRender->r,
  			m_clrRender->g,
  			m_clrRender->b,
  			m_flSpriteScale		  // sprite scale
  			);
  		break;
  	case mod_studio:
  		drawn = DrawStudioModel( flags );
  		break;
  	default:
  		break;
  	}
  
  	return drawn;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  // Output : Returns true on success, false on failure.
  //-----------------------------------------------------------------------------
  bool C_LocalTempEntity::IsActive( void )
  {
  	bool active = true;
  
  	float life = die - gpGlobals->curtime;
  	
  	if ( life < 0 )
  	{
  		if ( flags & FTENT_FADEOUT )
  		{
  			int alpha;
  			if (GetRenderMode() == kRenderNormal)
  			{
  				SetRenderMode( kRenderTransTexture );
  			}
  			
  			alpha = tempent_renderamt * ( 1 + life * fadeSpeed );
  			
  			if ( alpha <= 0 )
  			{
  				active = false;
  				alpha = 0;
  			}
  
  			SetRenderColorA( alpha );
  		}
  		else 
  		{
  			active = false;
  		}
  	}
  
  	// Never die tempents only die when their die is cleared
  	if ( flags & FTENT_NEVERDIE )
  	{
  		active = (die != 0);
  	}
  
  	return active;
  }
  
  bool C_LocalTempEntity::Frame( float frametime, int framenumber )
  {
  	float fastFreq = gpGlobals->curtime * 5.5;
  	float gravity = -frametime * GetCurrentGravity();
  	float gravitySlow = gravity * 0.5;
  	float traceFraction = 1;
  
  	Assert( !GetMoveParent() );
  
  	m_vecPrevLocalOrigin = GetLocalOrigin();
  
  	m_vecTempEntVelocity = m_vecTempEntVelocity + ( m_vecTempEntAcceleration * frametime );
  
  	if ( flags & FTENT_PLYRATTACHMENT )
  	{
  		if ( IClientEntity *pClient = cl_entitylist->GetClientEntity( clientIndex ) )
  		{
  			SetLocalOrigin( pClient->GetAbsOrigin() + tentOffset );
  		}
  	}
  	else if ( flags & FTENT_SINEWAVE )
  	{
  		x += m_vecTempEntVelocity[0] * frametime;
  		y += m_vecTempEntVelocity[1] * frametime;
  
  		SetLocalOrigin( Vector(
  			x + sin( m_vecTempEntVelocity[2] + gpGlobals->curtime /* * anim.prevframe */ ) * (10*m_flSpriteScale),
  			y + sin( m_vecTempEntVelocity[2] + fastFreq + 0.7 ) * (8*m_flSpriteScale),
  			GetLocalOriginDim( Z_INDEX ) + m_vecTempEntVelocity[2] * frametime ) );
  	}
  	else if ( flags & FTENT_SPIRAL )
  	{
  		float s, c;
  		SinCos( m_vecTempEntVelocity[2] + fastFreq, &s, &c );
  
  		SetLocalOrigin( GetLocalOrigin() + Vector(
  			m_vecTempEntVelocity[0] * frametime + 8 * sin( gpGlobals->curtime * 20 ),
  			m_vecTempEntVelocity[1] * frametime + 4 * sin( gpGlobals->curtime * 30 ),
  			m_vecTempEntVelocity[2] * frametime ) );
  	}
  	else
  	{
  		SetLocalOrigin( GetLocalOrigin() + m_vecTempEntVelocity * frametime );
  	}
  	
  	if ( flags & FTENT_SPRANIMATE )
  	{
  		m_flFrame += frametime * m_flFrameRate;
  		if ( m_flFrame >= m_flFrameMax )
  		{
  			m_flFrame = m_flFrame - (int)(m_flFrame);
  
  			if ( !(flags & FTENT_SPRANIMATELOOP) )
  			{
  				// this animating sprite isn't set to loop, so destroy it.
  				die = 0.0f;
  				return false;
  			}
  		}
  	}
  	else if ( flags & FTENT_SPRCYCLE )
  	{
  		m_flFrame += frametime * 10;
  		if ( m_flFrame >= m_flFrameMax )
  		{
  			m_flFrame = m_flFrame - (int)(m_flFrame);
  		}
  	}
  
  	if ( flags & FTENT_SMOKEGROWANDFADE )
  	{
  		m_flSpriteScale += frametime * 0.5f;
  		//m_clrRender.a -= frametime * 1500;
  	}
  
  	if ( flags & FTENT_ROTATE )
  	{
  		SetLocalAngles( GetLocalAngles() + m_vecTempEntAngVelocity * frametime );
  	}
  	else if ( flags & FTENT_ALIGNTOMOTION )
  	{
  		if ( m_vecTempEntVelocity.Length() > 0.0f )
  		{
  			QAngle angles;
  			VectorAngles( m_vecTempEntVelocity, angles );
  			SetAbsAngles( angles );
  		}
  	}
  
  	if ( flags & (FTENT_COLLIDEALL | FTENT_COLLIDEWORLD | FTENT_COLLIDEPROPS ) )
  	{
  		Vector	traceNormal;
  		traceNormal.Init();
  		bool bShouldCollide = true;
  
  		trace_t trace;
  
  		if ( flags & (FTENT_COLLIDEALL | FTENT_COLLIDEPROPS) )
  		{
  			Vector vPrevOrigin = m_vecPrevLocalOrigin;
  
  			if ( cl_fasttempentcollision.GetInt() > 0 && flags & FTENT_USEFASTCOLLISIONS )
  			{
  				if ( m_iLastCollisionFrame + cl_fasttempentcollision.GetInt() > gpGlobals->framecount )
  				{
  					bShouldCollide = false;
  				}
  				else
  				{
  					if ( m_vLastCollisionOrigin != vec3_origin )
  					{
  						vPrevOrigin = m_vLastCollisionOrigin;
  					}
  
  					m_iLastCollisionFrame = gpGlobals->framecount;
  					bShouldCollide = true; 
  				}
  			}
  
  			if ( bShouldCollide == true )
  			{
  				// If the FTENT_COLLISIONGROUP flag is set, use the entity's collision group
  				int collisionGroup = COLLISION_GROUP_NONE;
  				if ( flags & FTENT_COLLISIONGROUP )
  				{
  					collisionGroup = GetCollisionGroup();
  				}
  
  				UTIL_TraceLine( vPrevOrigin, GetLocalOrigin(), MASK_SOLID, GetOwnerEntity(), collisionGroup, &trace );
  
  				if ( (flags & FTENT_COLLIDEPROPS) && trace.m_pEnt )
  				{
  					bool bIsDynamicProp = ( NULL != dynamic_cast<CDynamicProp *>( trace.m_pEnt ) );
  					bool bIsDoor = ( NULL != dynamic_cast<CBaseDoor *>( trace.m_pEnt ) );
  					if ( !bIsDynamicProp && !bIsDoor && !trace.m_pEnt->IsWorld() ) // Die on props, doors, and the world.
  						return true;
  				}
  
  				// Make sure it didn't bump into itself... (?!?)
  				if  ( 
  					(trace.fraction != 1) && 
  						( (trace.DidHitWorld()) || 
  						  (trace.m_pEnt != ClientEntityList().GetEnt(clientIndex)) ) 
  					)
  				{
  					traceFraction = trace.fraction;
  					VectorCopy( trace.plane.normal, traceNormal );
  				}
  
  				m_vLastCollisionOrigin = trace.endpos;
  			}
  		}
  		else if ( flags & FTENT_COLLIDEWORLD )
  		{
  			CTraceFilterWorldOnly traceFilter;
  			UTIL_TraceLine( m_vecPrevLocalOrigin, GetLocalOrigin(), MASK_SOLID, &traceFilter, &trace );
  			if ( trace.fraction != 1 )
  			{
  				traceFraction = trace.fraction;
  				VectorCopy( trace.plane.normal, traceNormal );
  			}
  		}
  		
  		if ( traceFraction != 1  )	// Decent collision now, and damping works
  		{
  			float  proj, damp;
  			SetLocalOrigin( trace.endpos );
  			
  			// Damp velocity
  			damp = bounceFactor;
  			if ( flags & (FTENT_GRAVITY|FTENT_SLOWGRAVITY) )
  			{
  				damp *= 0.5;
  				if ( traceNormal[2] > 0.9 )		// Hit floor?
  				{
  					if ( m_vecTempEntVelocity[2] <= 0 && m_vecTempEntVelocity[2] >= gravity*3 )
  					{
  						damp = 0;		// Stop
  						flags &= ~(FTENT_ROTATE|FTENT_GRAVITY|FTENT_SLOWGRAVITY|FTENT_COLLIDEWORLD|FTENT_SMOKETRAIL);
  						SetLocalAnglesDim( X_INDEX, 0 );
  						SetLocalAnglesDim( Z_INDEX, 0 );
  					}
  				}
  			}
  
  			if ( flags & (FTENT_CHANGERENDERONCOLLIDE) )
  			{
  				m_RenderGroup = RENDER_GROUP_OTHER;
  				flags &= ~FTENT_CHANGERENDERONCOLLIDE;
  			}	
  
  			if (hitSound)
  			{
  				tempents->PlaySound(this, damp);
  			}
  
  			if ( m_pszImpactEffect )
  			{
  				CEffectData data;
  				//data.m_vOrigin = newOrigin;
  				data.m_vOrigin = trace.endpos;
  				data.m_vStart = trace.startpos;
  				data.m_nSurfaceProp = trace.surface.surfaceProps;
  				data.m_nHitBox = trace.hitbox;
  
  				data.m_nDamageType = TEAM_UNASSIGNED;
  
  				IClientNetworkable *pClient = cl_entitylist->GetClientEntity( clientIndex );
  
  				if ( pClient )
  				{
  					C_BasePlayer *pPlayer = dynamic_cast<C_BasePlayer*>(pClient);
  					if( pPlayer )
  					{
  						data.m_nDamageType = pPlayer->GetTeamNumber();
  					}
  				}
  
  				if ( trace.m_pEnt )
  				{
  					data.m_hEntity = ClientEntityList().EntIndexToHandle( trace.m_pEnt->entindex() );
  				}
  				DispatchEffect( m_pszImpactEffect, data );
  			}
  
  			// Check for a collision and stop the particle system.
  			if ( flags & FTENT_CLIENTSIDEPARTICLES )
  			{
  				// Stop the emission of particles on collision - removed from the ClientEntityList on removal from the tempent pool.
  				ParticleProp()->StopEmission();
  				m_bParticleCollision = true;
  			}
  
  			if (flags & FTENT_COLLIDEKILL)
  			{
  				// die on impact
  				flags &= ~FTENT_FADEOUT;	
  				die = gpGlobals->curtime;			
  			}
  			else if ( flags & FTENT_ATTACHTOTARGET)
  			{
  				// If we've hit the world, just stop moving
  				if ( trace.DidHitWorld() && !( trace.surface.flags & SURF_SKY ) )
  				{
  					m_vecTempEntVelocity = vec3_origin;
  					m_vecTempEntAcceleration = vec3_origin;
  
  					// Remove movement flags so we don't keep tracing
  					flags &= ~(FTENT_COLLIDEALL | FTENT_COLLIDEWORLD);
  				}
  				else
  				{
  					// Couldn't attach to this entity. Die.
  					flags &= ~FTENT_FADEOUT;
  					die = gpGlobals->curtime;
  				}
  			}
  			else
  			{
  				// Reflect velocity
  				if ( damp != 0 )
  				{
  					proj = ((Vector)m_vecTempEntVelocity).Dot(traceNormal);
  					VectorMA( m_vecTempEntVelocity, -proj*2, traceNormal, m_vecTempEntVelocity );
  					// Reflect rotation (fake)
  					SetLocalAnglesDim( Y_INDEX, -GetLocalAnglesDim( Y_INDEX ) );
  				}
  				
  				if ( damp != 1 )
  				{
  					VectorScale( m_vecTempEntVelocity, damp, m_vecTempEntVelocity );
  					SetLocalAngles( GetLocalAngles() * 0.9 );
  				}
  			}
  		}
  	}
  
  
  	if ( (flags & FTENT_FLICKER) && framenumber == m_nFlickerFrame )
  	{
  		dlight_t *dl = effects->CL_AllocDlight (LIGHT_INDEX_TE_DYNAMIC);
  		VectorCopy (GetLocalOrigin(), dl->origin);
  		dl->radius = 60;
  		dl->color.r = 255;
  		dl->color.g = 120;
  		dl->color.b = 0;
  		dl->die = gpGlobals->curtime + 0.01;
  	}
  
  	if ( flags & FTENT_SMOKETRAIL )
  	{
  		 Assert( !"FIXME:  Rework smoketrail to be client side\n" );
  	}
  
  	// add gravity if we didn't collide in this frame
  	if ( traceFraction == 1 )
  	{
  		if ( flags & FTENT_GRAVITY )
  			m_vecTempEntVelocity[2] += gravity;
  		else if ( flags & FTENT_SLOWGRAVITY )
  			m_vecTempEntVelocity[2] += gravitySlow;
  	}
  
  	if ( flags & FTENT_WINDBLOWN )
  	{
  		Vector vecWind;
  		GetWindspeedAtTime( gpGlobals->curtime, vecWind );
  
  		for ( int i = 0 ; i < 2 ; i++ )
  		{
  			if ( m_vecTempEntVelocity[i] < vecWind[i] )
  			{
  				m_vecTempEntVelocity[i] += ( frametime * TENT_WIND_ACCEL );
  
  				// clamp
  				if ( m_vecTempEntVelocity[i] > vecWind[i] )
  					m_vecTempEntVelocity[i] = vecWind[i];
  			}
  			else if (m_vecTempEntVelocity[i] > vecWind[i] )
  			{
  				m_vecTempEntVelocity[i] -= ( frametime * TENT_WIND_ACCEL );
  
  				// clamp.
  				if ( m_vecTempEntVelocity[i] < vecWind[i] )
  					m_vecTempEntVelocity[i] = vecWind[i];
  			}
  		}
  	}
  
  	return true;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Attach a particle effect to a temp entity.
  //-----------------------------------------------------------------------------
  CNewParticleEffect* C_LocalTempEntity::AddParticleEffect( const char *pszParticleEffect )
  {
  	// Do we have a valid particle effect.
  	if ( !pszParticleEffect || ( pszParticleEffect[0] == '\0' ) )
  		return NULL;
  
  	// Check to see that we don't already have a particle effect.
  	if ( ( flags & FTENT_CLIENTSIDEPARTICLES ) != 0 )
  		return NULL;
  
  	// Add the entity to the ClientEntityList and create the particle system.
  	ClientEntityList().AddNonNetworkableEntity( this );
  	CNewParticleEffect* pEffect = ParticleProp()->Create( pszParticleEffect, PATTACH_ABSORIGIN_FOLLOW );
  
  	// Set the particle flag on the temp entity and save the name of the particle effect.
  	flags |= FTENT_CLIENTSIDEPARTICLES;
  	SetParticleEffect( pszParticleEffect );
  
  	return pEffect;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: This helper keeps track of batches of "breakmodels" so that they can all share the lighting origin
  //  of the first of the group (because the server sends down 15 chunks at a time, and rebuilding 15 light cache
  //  entries for a map with a lot of worldlights is really slow).
  //-----------------------------------------------------------------------------
  class CBreakableHelper
  {
  public:
  	void	Insert( C_LocalTempEntity *entity, bool isSlave );
  	void	Remove( C_LocalTempEntity *entity );
  
  	void	Clear();
  
  	const Vector *GetLightingOrigin( C_LocalTempEntity *entity );
  
  private:
  
  	// A context is the first master until the next one, which starts a new context
  	struct BreakableList_t
  	{
  		unsigned int		context;
  		C_LocalTempEntity	*entity;
  	};
  
  	CUtlLinkedList< BreakableList_t, unsigned short >	m_Breakables;
  	unsigned int			m_nCurrentContext;
  };
  
  //-----------------------------------------------------------------------------
  // Purpose: Adds brekable to list, starts new context if needed
  // Input  : *entity - 
  //			isSlave - 
  //-----------------------------------------------------------------------------
  void CBreakableHelper::Insert( C_LocalTempEntity *entity, bool isSlave )
  {
  	// A master signifies the start of a new run of broken objects
  	if ( !isSlave )
  	{
  		++m_nCurrentContext;
  	}
  	
  	BreakableList_t entry;
  	entry.context = m_nCurrentContext;
  	entry.entity = entity;
  
  	m_Breakables.AddToTail( entry );
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Removes all instances of entity in the list
  // Input  : *entity - 
  //-----------------------------------------------------------------------------
  void CBreakableHelper::Remove( C_LocalTempEntity *entity )
  {
  	for ( unsigned short i = m_Breakables.Head(); i != m_Breakables.InvalidIndex() ; )
  	{
  		unsigned short n = m_Breakables.Next( i );
  
  		if ( m_Breakables[ i ].entity == entity )
  		{
  			m_Breakables.Remove( i );
  		}
  
  		i = n;
  	}
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: For a given breakable, find the "first" or head object and use it's current
  //  origin as the lighting origin for the entire group of objects
  // Input  : *entity - 
  // Output : const Vector
  //-----------------------------------------------------------------------------
  const Vector *CBreakableHelper::GetLightingOrigin( C_LocalTempEntity *entity )
  {
  	unsigned int nCurContext = 0;
  	C_LocalTempEntity *head = NULL;
  	FOR_EACH_LL( m_Breakables, i )
  	{
  		BreakableList_t& e = m_Breakables[ i ];
  
  		if ( e.context != nCurContext )
  		{
  			nCurContext = e.context;
  			head = e.entity;
  		}
  
  		if ( e.entity == entity )
  		{
  			Assert( head );
  			return head ? &head->GetAbsOrigin() : NULL;
  		}
  	}
  	return NULL;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Wipe breakable helper list
  // Input  :  - 
  //-----------------------------------------------------------------------------
  void CBreakableHelper::Clear()
  {
  	m_Breakables.RemoveAll();
  	m_nCurrentContext = 0;
  }
  
  static CBreakableHelper g_BreakableHelper;
  
  //-----------------------------------------------------------------------------
  // Purpose: See if it's in the breakable helper list and, if so, remove
  // Input  :  - 
  //-----------------------------------------------------------------------------
  void C_LocalTempEntity::OnRemoveTempEntity()
  {
  	g_BreakableHelper.Remove( this );
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  //-----------------------------------------------------------------------------
  CTempEnts::CTempEnts( void ) :
  	m_TempEntsPool( ( MAX_TEMP_ENTITIES / 20 ), CUtlMemoryPool::GROW_SLOW )
  {
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  //-----------------------------------------------------------------------------
  CTempEnts::~CTempEnts( void )
  {
  	m_TempEntsPool.Clear();
  	m_TempEnts.RemoveAll();
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Create a fizz effect
  // Input  : *pent - 
  //			modelIndex - 
  //			density - 
  //-----------------------------------------------------------------------------
  void CTempEnts::FizzEffect( C_BaseEntity *pent, int modelIndex, int density, int current )
  {
  	C_LocalTempEntity		*pTemp;
  	const model_t	*model;
  	int				i, width, depth, count, frameCount;
  	float			maxHeight, speed, xspeed, yspeed;
  	Vector			origin;
  	Vector			mins, maxs;
  
  	if ( !pent->GetModel() || !modelIndex ) 
  		return;
  
  	model = modelinfo->GetModel( modelIndex );
  	if ( !model )
  		return;
  
  	count = density + 1;
  	density = count * 3 + 6;
  
  	modelinfo->GetModelBounds( pent->GetModel(), mins, maxs );
  
  	maxHeight = maxs[2] - mins[2];
  	width = maxs[0] - mins[0];
  	depth = maxs[1] - mins[1];
  	speed = current;
  
  	SinCos( pent->GetLocalAngles()[1]*M_PI/180, &yspeed, &xspeed );
  	xspeed *= speed;
  	yspeed *= speed;
  	frameCount = modelinfo->GetModelFrameCount( model );
  
  	for (i=0 ; i<count ; i++)
  	{
  		origin[0] = mins[0] + random->RandomInt(0,width-1);
  		origin[1] = mins[1] + random->RandomInt(0,depth-1);
  		origin[2] = mins[2];
  		pTemp = TempEntAlloc( origin, model );
  		if (!pTemp)
  			return;
  
  		pTemp->flags |= FTENT_SINEWAVE;
  
  		pTemp->x = origin[0];
  		pTemp->y = origin[1];
  
  		float zspeed = random->RandomInt(80,140);
  		pTemp->SetVelocity( Vector(xspeed, yspeed, zspeed) );
  		pTemp->die = gpGlobals->curtime + (maxHeight / zspeed) - 0.1;
  		pTemp->m_flFrame = random->RandomInt(0,frameCount-1);
  		// Set sprite scale
  		pTemp->m_flSpriteScale = 1.0 / random->RandomFloat(2,5);
  		pTemp->SetRenderMode( kRenderTransAlpha );
  		pTemp->SetRenderColorA( 255 );
  	}
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Create bubbles
  // Input  : *mins - 
  //			*maxs - 
  //			height - 
  //			modelIndex - 
  //			count - 
  //			speed - 
  //-----------------------------------------------------------------------------
  void CTempEnts::Bubbles( const Vector &mins, const Vector &maxs, float height, int modelIndex, int count, float speed )
  {
  	C_LocalTempEntity			*pTemp;
  	const model_t		*model;
  	int					i, frameCount;
  	float				sine, cosine;
  	Vector				origin;
  
  	if ( !modelIndex ) 
  		return;
  
  	model = modelinfo->GetModel( modelIndex );
  	if ( !model )
  		return;
  
  	frameCount = modelinfo->GetModelFrameCount( model );
  
  	for (i=0 ; i<count ; i++)
  	{
  		origin[0] = random->RandomInt( mins[0], maxs[0] );
  		origin[1] = random->RandomInt( mins[1], maxs[1] );
  		origin[2] = random->RandomInt( mins[2], maxs[2] );
  		pTemp = TempEntAlloc( origin, model );
  		if (!pTemp)
  			return;
  
  		pTemp->flags |= FTENT_SINEWAVE;
  
  		pTemp->x = origin[0];
  		pTemp->y = origin[1];
  		SinCos( random->RandomInt( -3, 3 ), &sine, &cosine );
  		
  		float zspeed = random->RandomInt(80,140);
  		pTemp->SetVelocity( Vector(speed * cosine, speed * sine, zspeed) );
  		pTemp->die = gpGlobals->curtime + ((height - (origin[2] - mins[2])) / zspeed) - 0.1;
  		pTemp->m_flFrame = random->RandomInt( 0, frameCount-1 );
  		
  		// Set sprite scale
  		pTemp->m_flSpriteScale = 1.0 / random->RandomFloat(4,16);
  		pTemp->SetRenderMode( kRenderTransAlpha );
  		
  		pTemp->SetRenderColor( 255, 255, 255, 192 );
  	}
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Create bubble trail
  // Input  : *start - 
  //			*end - 
  //			height - 
  //			modelIndex - 
  //			count - 
  //			speed - 
  //-----------------------------------------------------------------------------
  void CTempEnts::BubbleTrail( const Vector &start, const Vector &end, float flWaterZ, int modelIndex, int count, float speed )
  {
  	C_LocalTempEntity			*pTemp;
  	const model_t		*model;
  	int					i, frameCount;
  	float				dist, angle;
  	Vector				origin;
  
  	if ( !modelIndex ) 
  		return;
  
  	model = modelinfo->GetModel( modelIndex );
  	if ( !model )
  		return;
  
  	frameCount = modelinfo->GetModelFrameCount( model );
  
  	for (i=0 ; i<count ; i++)
  	{
  		dist = random->RandomFloat( 0, 1.0 );
  		VectorLerp( start, end, dist, origin );
  		pTemp = TempEntAlloc( origin, model );
  		if (!pTemp)
  			return;
  
  		pTemp->flags |= FTENT_SINEWAVE;
  
  		pTemp->x = origin[0];
  		pTemp->y = origin[1];
  		angle = random->RandomInt( -3, 3 );
  
  		float zspeed = random->RandomInt(80,140);
  		pTemp->SetVelocity( Vector(speed * cos(angle), speed * sin(angle), zspeed) );
  		pTemp->die = gpGlobals->curtime + ((flWaterZ - origin[2]) / zspeed) - 0.1;
  		pTemp->m_flFrame = random->RandomInt(0,frameCount-1);
  		// Set sprite scale
  		pTemp->m_flSpriteScale = 1.0 / random->RandomFloat(4,8);
  		pTemp->SetRenderMode( kRenderTransAlpha );
  		
  		pTemp->SetRenderColor( 255, 255, 255, 192 );
  	}
  }
  
  #define SHARD_VOLUME 12.0	// on shard ever n^3 units
  
  //-----------------------------------------------------------------------------
  // Purpose: Only used by BreakModel temp ents for now.  Allows them to share a single
  //  lighting origin amongst a group of objects.  If the master object goes away, the next object
  //  in the group becomes the new lighting origin, etc.
  // Input  : *entity - 
  //			flags - 
  // Output : int
  //-----------------------------------------------------------------------------
  int BreakModelDrawHelper( C_LocalTempEntity *entity, int flags )
  {
  	ModelRenderInfo_t sInfo;
  	sInfo.flags = flags;
  	sInfo.pRenderable = entity;
  	sInfo.instance = MODEL_INSTANCE_INVALID;
  	sInfo.entity_index = entity->index;
  	sInfo.pModel = entity->GetModel();
  	sInfo.origin = entity->GetRenderOrigin();
  	sInfo.angles = entity->GetRenderAngles();
  	sInfo.skin = entity->m_nSkin;
  	sInfo.body = entity->m_nBody;
  	sInfo.hitboxset = entity->m_nHitboxSet;
  
  	// This is the main change, look up a lighting origin from the helper singleton
  	const Vector *pLightingOrigin = g_BreakableHelper.GetLightingOrigin( entity );
  	if ( pLightingOrigin )
  	{
  		sInfo.pLightingOrigin = pLightingOrigin;
  	}
  
  	int drawn = modelrender->DrawModelEx( sInfo );
  	return drawn;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Create model shattering shards
  // Input  : *pos - 
  //			*size - 
  //			*dir - 
  //			random - 
  //			life - 
  //			count - 
  //			modelIndex - 
  //			flags - 
  //-----------------------------------------------------------------------------
  void CTempEnts::BreakModel( const Vector &pos, const QAngle &angles, const Vector &size, const Vector &dir, 
  						   float randRange, float life, int count, int modelIndex, char flags)
  {
  	int					i, frameCount;
  	C_LocalTempEntity			*pTemp;
  	const model_t		*pModel;
  
  	if (!modelIndex) 
  		return;
  
  	pModel = modelinfo->GetModel( modelIndex );
  	if ( !pModel )
  		return;
  
  	// See g_BreakableHelper above for notes...
  	bool isSlave = ( flags & BREAK_SLAVE ) ? true : false;
  
  	frameCount = modelinfo->GetModelFrameCount( pModel );
  
  	if (count == 0)
  	{
  		// assume surface (not volume)
  		count = (size[0] * size[1] + size[1] * size[2] + size[2] * size[0])/(3 * SHARD_VOLUME * SHARD_VOLUME);
  	}
  
  	if ( count > func_break_max_pieces.GetInt() )
  	{
  		count = func_break_max_pieces.GetInt();
  	}
  
  	matrix3x4_t transform;
  	AngleMatrix( angles, pos, transform );
  	for ( i = 0; i < count; i++ ) 
  	{
  		Vector vecLocalSpot, vecSpot;
  
  		// fill up the box with stuff
  		vecLocalSpot[0] = random->RandomFloat(-0.5,0.5) * size[0];
  		vecLocalSpot[1] = random->RandomFloat(-0.5,0.5) * size[1];
  		vecLocalSpot[2] = random->RandomFloat(-0.5,0.5) * size[2];
  		VectorTransform( vecLocalSpot, transform, vecSpot );
  
  		pTemp = TempEntAlloc(vecSpot, pModel);
  		
  		if (!pTemp)
  			return;
  
  		// keep track of break_type, so we know how to play sound on collision
  		pTemp->hitSound = flags;
  		
  		if ( modelinfo->GetModelType( pModel ) == mod_sprite )
  		{
  			pTemp->m_flFrame = random->RandomInt(0,frameCount-1);
  		}
  		else if ( modelinfo->GetModelType( pModel ) == mod_studio )
  		{
  			pTemp->m_nBody = random->RandomInt(0,frameCount-1);
  		}
  
  		pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_SLOWGRAVITY;
  
  		if ( random->RandomInt(0,255) < 200 ) 
  		{
  			pTemp->flags |= FTENT_ROTATE;
  			pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-256,255);
  			pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-256,255);
  			pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat(-256,255);
  		}
  
  		if ( (random->RandomInt(0,255) < 100 ) && (flags & BREAK_SMOKE) )
  		{
  			pTemp->flags |= FTENT_SMOKETRAIL;
  		}
  
  		if ((flags & BREAK_GLASS) || (flags & BREAK_TRANS))
  		{
  			pTemp->SetRenderMode( kRenderTransTexture );
  			pTemp->SetRenderColorA( 128 );
  			pTemp->tempent_renderamt = 128;
  			pTemp->bounceFactor = 0.3f;
  		}
  		else
  		{
  			pTemp->SetRenderMode( kRenderNormal );
  			pTemp->tempent_renderamt = 255;		// Set this for fadeout
  		}
  
  		pTemp->SetVelocity( Vector( dir[0] + random->RandomFloat(-randRange,randRange),
  							dir[1] + random->RandomFloat(-randRange,randRange),
  							dir[2] + random->RandomFloat(   0,randRange) ) );
  
  		pTemp->die = gpGlobals->curtime + life + random->RandomFloat(0,1);	// Add an extra 0-1 secs of life
  
  		// We use a special rendering function because these objects will want to share their lighting
  		//  origin with the first/master object.  Prevents a huge spike in Light Cache building in maps
  		//  with many worldlights.
  		pTemp->SetDrawHelper( BreakModelDrawHelper );
  		g_BreakableHelper.Insert( pTemp, isSlave );
  	}
  }
  
  void CTempEnts::PhysicsProp( int modelindex, int skin, const Vector& pos, const QAngle &angles, const Vector& vel, int flags, int effects )
  {
  	C_PhysPropClientside *pEntity = C_PhysPropClientside::CreateNew();
  	
  	if ( !pEntity )
  		return;
  
  	const model_t *model = modelinfo->GetModel( modelindex );
  
  	if ( !model )
  	{
  		DevMsg("CTempEnts::PhysicsProp: model index %i not found\n", modelindex );
  		return;
  	}
  
  	pEntity->SetModelName( modelinfo->GetModelName(model) );
  	pEntity->m_nSkin = skin;
  	pEntity->SetAbsOrigin( pos );
  	pEntity->SetAbsAngles( angles );
  	pEntity->SetPhysicsMode( PHYSICS_MULTIPLAYER_CLIENTSIDE );
  	pEntity->SetEffects( effects );
  
  	if ( !pEntity->Initialize() )
  	{
  		pEntity->Release();
  		return;
  	}
  
  	IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject();
  
  	if( pPhysicsObject )
  	{
  		pPhysicsObject->AddVelocity( &vel, NULL );
  	}
  	else
  	{
  		// failed to create a physics object
  		pEntity->Release();
  		return;
  	}
  
  	if ( flags & 1 )
  	{
  		pEntity->SetHealth( 0 );
  		pEntity->Break();
  	}
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Create a clientside projectile
  // Input  : vecOrigin - 
  //			vecVelocity - 
  //			modelindex - 
  //			lifetime - 
  //			*pOwner - 
  //-----------------------------------------------------------------------------
  C_LocalTempEntity *CTempEnts::ClientProjectile( const Vector& vecOrigin, const Vector& vecVelocity, const Vector& vecAcceleration, int modelIndex, int lifetime, CBaseEntity *pOwner, const char *pszImpactEffect, const char *pszParticleEffect )
  {
  	C_LocalTempEntity	*pTemp;
  	const model_t		*model;
  
  	if ( !modelIndex ) 
  		return NULL;
  
  	model = modelinfo->GetModel( modelIndex );
  	if ( !model )
  	{
  		Warning("ClientProjectile: No model %d!\n", modelIndex);
  		return NULL;
  	}
  
  	pTemp = TempEntAlloc( vecOrigin, model );
  	if (!pTemp)
  		return NULL;
  
  	pTemp->SetVelocity( vecVelocity );
  	pTemp->SetAcceleration( vecAcceleration );
  	QAngle angles;
  	VectorAngles( vecVelocity, angles );
  	pTemp->SetAbsAngles( angles );
  	pTemp->SetAbsOrigin( vecOrigin );
  	pTemp->die = gpGlobals->curtime + lifetime;
  	pTemp->flags = FTENT_COLLIDEALL | FTENT_ATTACHTOTARGET | FTENT_ALIGNTOMOTION;
  	pTemp->clientIndex = ( pOwner != NULL ) ? pOwner->entindex() : 0; 
  	pTemp->SetOwnerEntity( pOwner );
  	pTemp->SetImpactEffect( pszImpactEffect );
  	if ( pszParticleEffect )
  	{
  		// Add the entity to the ClientEntityList and create the particle system.
  		ClientEntityList().AddNonNetworkableEntity( pTemp );
  		pTemp->ParticleProp()->Create( pszParticleEffect, PATTACH_ABSORIGIN_FOLLOW );
  
  		// Set the particle flag on the temp entity and save the name of the particle effect.
  		pTemp->flags |= FTENT_CLIENTSIDEPARTICLES;
  	 	pTemp->SetParticleEffect( pszParticleEffect );
  	}
  	return pTemp;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Create sprite TE
  // Input  : *pos - 
  //			*dir - 
  //			scale - 
  //			modelIndex - 
  //			rendermode - 
  //			renderfx - 
  //			a - 
  //			life - 
  //			flags - 
  // Output : C_LocalTempEntity
  //-----------------------------------------------------------------------------
  C_LocalTempEntity *CTempEnts::TempSprite( const Vector &pos, const Vector &dir, float scale, int modelIndex, int rendermode, int renderfx, float a, float life, int flags, const Vector &normal )
  {
  	C_LocalTempEntity			*pTemp;
  	const model_t		*model;
  	int					frameCount;
  
  	if ( !modelIndex ) 
  		return NULL;
  
  	model = modelinfo->GetModel( modelIndex );
  	if ( !model )
  	{
  		Warning("No model %d!\n", modelIndex);
  		return NULL;
  	}
  
  	frameCount = modelinfo->GetModelFrameCount( model );
  
  	pTemp = TempEntAlloc( pos, model );
  	if (!pTemp)
  		return NULL;
  
  	pTemp->m_flFrameMax = frameCount - 1;
  	pTemp->m_flFrameRate = 10;
  	pTemp->SetRenderMode( (RenderMode_t)rendermode );
  	pTemp->m_nRenderFX = renderfx;
  	pTemp->m_flSpriteScale = scale;
  	pTemp->tempent_renderamt = a * 255;
  	pTemp->m_vecNormal = normal;
  	pTemp->SetRenderColor( 255, 255, 255, a * 255 );
  
  	pTemp->flags |= flags;
  
  	pTemp->SetVelocity( dir );
  	pTemp->SetLocalOrigin( pos );
  	if ( life )
  		pTemp->die = gpGlobals->curtime + life;
  	else
  		pTemp->die = gpGlobals->curtime + (frameCount * 0.1) + 1;
  
  	pTemp->m_flFrame = 0;
  	return pTemp;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Spray sprite
  // Input  : *pos - 
  //			*dir - 
  //			modelIndex - 
  //			count - 
  //			speed - 
  //			iRand - 
  //-----------------------------------------------------------------------------
  void CTempEnts::Sprite_Spray( const Vector &pos, const Vector &dir, int modelIndex, int count, int speed, int iRand )
  {
  	C_LocalTempEntity			*pTemp;
  	const model_t		*pModel;
  	float				noise;
  	float				znoise;
  	int					frameCount;
  	int					i;
  
  	noise = (float)iRand / 100;
  
  	// more vertical displacement
  	znoise = noise * 1.5;
  	
  	if ( znoise > 1 )
  	{
  		znoise = 1;
  	}
  
  	pModel = modelinfo->GetModel( modelIndex );
  	
  	if ( !pModel )
  	{
  		Warning("No model %d!\n", modelIndex);
  		return;
  	}
  
  	frameCount = modelinfo->GetModelFrameCount( pModel ) - 1;
  
  	for ( i = 0; i < count; i++ )
  	{
  		pTemp = TempEntAlloc( pos, pModel );
  		if (!pTemp)
  			return;
  
  		pTemp->SetRenderMode( kRenderTransAlpha );
  		pTemp->SetRenderColor( 255, 255, 255, 255 );
  		pTemp->tempent_renderamt = 255;
  		pTemp->m_nRenderFX = kRenderFxNoDissipation;
  		//pTemp->scale = random->RandomFloat( 0.1, 0.25 );
  		pTemp->m_flSpriteScale = 0.5;
  		pTemp->flags |= FTENT_FADEOUT | FTENT_SLOWGRAVITY;
  		pTemp->fadeSpeed = 2.0;
  
  		// make the spittle fly the direction indicated, but mix in some noise.
  		Vector velocity;
  		velocity.x = dir[ 0 ] + random->RandomFloat ( -noise, noise );
  		velocity.y = dir[ 1 ] + random->RandomFloat ( -noise, noise );
  		velocity.z = dir[ 2 ] + random->RandomFloat ( 0, znoise );
  		velocity *= random->RandomFloat( (speed * 0.8), (speed * 1.2) );
  		pTemp->SetVelocity( velocity );
  
  		pTemp->SetLocalOrigin( pos );
  
  		pTemp->die = gpGlobals->curtime + 0.35;
  
  		pTemp->m_flFrame = random->RandomInt( 0, frameCount );
  	}
  }
  
  void CTempEnts::Sprite_Trail( const Vector &vecStart, const Vector &vecEnd, int modelIndex, int nCount, float flLife, float flSize, float flAmplitude, int nRenderamt, float flSpeed )
  {
  	C_LocalTempEntity	*pTemp;
  	const model_t		*pModel;
  	int					flFrameCount;
  
  	pModel = modelinfo->GetModel( modelIndex );
  	
  	if ( !pModel )
  	{
  		Warning("No model %d!\n", modelIndex);
  		return;
  	}
  
  	flFrameCount = modelinfo->GetModelFrameCount( pModel );
  
  	Vector vecDelta;
  	VectorSubtract( vecEnd, vecStart, vecDelta );
  
  	Vector vecDir;
  	VectorCopy( vecDelta, vecDir );
  	VectorNormalize( vecDir );
  
  	flAmplitude /= 256.0;
  
  	for ( int i = 0 ; i < nCount; i++ )
  	{
  		Vector vecPos;
  
  		// Be careful of divide by 0 when using 'count' here...
  		if ( i == 0 )
  		{
  			VectorMA( vecStart, 0, vecDelta, vecPos );
  		}
  		else
  		{
  			VectorMA( vecStart, i / (nCount - 1.0), vecDelta, vecPos );
  		}
  
  		pTemp = TempEntAlloc( vecPos, pModel );
  		if (!pTemp)
  			return;
  
  		pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_SPRCYCLE | FTENT_FADEOUT | FTENT_SLOWGRAVITY;
  
  		Vector vecVel = vecDir * flSpeed;
  		vecVel.x += random->RandomInt( -127,128 ) * flAmplitude;
  		vecVel.y += random->RandomInt( -127,128 ) * flAmplitude;
  		vecVel.z += random->RandomInt( -127,128 ) * flAmplitude;
  		pTemp->SetVelocity( vecVel );
  		pTemp->SetLocalOrigin( vecPos );
  
  		pTemp->m_flSpriteScale		= flSize;
  		pTemp->SetRenderMode( kRenderGlow );
  		pTemp->m_nRenderFX			= kRenderFxNoDissipation;
  		pTemp->tempent_renderamt	= nRenderamt;
  		pTemp->SetRenderColor( 255, 255, 255 );
  
  		pTemp->m_flFrame	= random->RandomInt( 0, flFrameCount - 1 );
  		pTemp->m_flFrameMax	= flFrameCount - 1;
  		pTemp->die			= gpGlobals->curtime + flLife + random->RandomFloat( 0, 4 );
  	}
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Attaches entity to player
  // Input  : client - 
  //			modelIndex - 
  //			zoffset - 
  //			life - 
  //-----------------------------------------------------------------------------
  void CTempEnts::AttachTentToPlayer( int client, int modelIndex, float zoffset, float life )
  {
  	C_LocalTempEntity			*pTemp;
  	const model_t		*pModel;
  	Vector				position;
  	int					frameCount;
  
  	if ( client <= 0 || client > gpGlobals->maxClients )
  	{
  		Warning("Bad client in AttachTentToPlayer()!\n");
  		return;
  	}
  
  	IClientEntity *clientClass = cl_entitylist->GetClientEntity( client );
  	if ( !clientClass )
  	{
  		Warning("Couldn't get IClientEntity for %i\n", client );
  		return;
  	}
  
  	pModel = modelinfo->GetModel( modelIndex );
  	
  	if ( !pModel )
  	{
  		Warning("No model %d!\n", modelIndex);
  		return;
  	}
  
  	VectorCopy( clientClass->GetAbsOrigin(), position );
  	position[ 2 ] += zoffset;
  
  	pTemp = TempEntAllocHigh( position, pModel );
  	if (!pTemp)
  	{
  		Warning("No temp ent.\n");
  		return;
  	}
  
  	pTemp->SetRenderMode( kRenderNormal );
  	pTemp->SetRenderColorA( 255 );
  	pTemp->tempent_renderamt = 255;
  	pTemp->m_nRenderFX = kRenderFxNoDissipation;
  	
  	pTemp->clientIndex = client;
  	pTemp->tentOffset[ 0 ] = 0;
  	pTemp->tentOffset[ 1 ] = 0;
  	pTemp->tentOffset[ 2 ] = zoffset;
  	pTemp->die = gpGlobals->curtime + life;
  	pTemp->flags |= FTENT_PLYRATTACHMENT | FTENT_PERSIST;
  
  	// is the model a sprite?
  	if ( modelinfo->GetModelType( pTemp->GetModel() ) == mod_sprite )
  	{
  		frameCount = modelinfo->GetModelFrameCount( pModel );
  		pTemp->m_flFrameMax = frameCount - 1;
  		pTemp->flags |= FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP;
  		pTemp->m_flFrameRate = 10;
  	}
  	else
  	{
  		// no animation support for attached clientside studio models.
  		pTemp->m_flFrameMax = 0;
  	}
  
  	pTemp->m_flFrame = 0;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Detach entity from player
  //-----------------------------------------------------------------------------
  void CTempEnts::KillAttachedTents( int client )
  {
  	if ( client <= 0 || client > gpGlobals->maxClients )
  	{
  		Warning("Bad client in KillAttachedTents()!\n");
  		return;
  	}
  
  	FOR_EACH_LL( m_TempEnts, i )
  	{
  		C_LocalTempEntity *pTemp = m_TempEnts[ i ];
  
  		if ( pTemp->flags & FTENT_PLYRATTACHMENT )
  		{
  			// this TENT is player attached.
  			// if it is attached to this client, set it to die instantly.
  			if ( pTemp->clientIndex == client )
  			{
  				pTemp->die = gpGlobals->curtime;// good enough, it will die on next tent update. 
  			}
  		}
  	}
  }
  
  
  
  //-----------------------------------------------------------------------------
  // Purpose: Create ricochet sprite
  // Input  : *pos - 
  //			*pmodel - 
  //			duration - 
  //			scale - 
  //-----------------------------------------------------------------------------
  void CTempEnts::RicochetSprite( const Vector &pos, model_t *pmodel, float duration, float scale )
  {
  	C_LocalTempEntity	*pTemp;
  
  	pTemp = TempEntAlloc( pos, pmodel );
  	if (!pTemp)
  		return;
  
  	pTemp->SetRenderMode( kRenderGlow );
  	pTemp->m_nRenderFX = kRenderFxNoDissipation;
  	pTemp->SetRenderColorA( 200 );
  	pTemp->tempent_renderamt = 200;
  	pTemp->m_flSpriteScale = scale;
  	pTemp->flags = FTENT_FADEOUT;
  
  	pTemp->SetVelocity( vec3_origin );
  
  	pTemp->SetLocalOrigin( pos );
  	
  	pTemp->fadeSpeed = 8;
  	pTemp->die = gpGlobals->curtime;
  
  	pTemp->m_flFrame = 0;
  	pTemp->SetLocalAnglesDim( Z_INDEX, 45 * random->RandomInt( 0, 7 ) );
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Create blood sprite
  // Input  : *org - 
  //			colorindex - 
  //			modelIndex - 
  //			modelIndex2 - 
  //			size - 
  //-----------------------------------------------------------------------------
  void CTempEnts::BloodSprite( const Vector &org, int r, int g, int b, int a, int modelIndex, int modelIndex2, float size )
  {
  	const model_t			*model;
  
  	//Validate the model first
  	if ( modelIndex && (model = modelinfo->GetModel( modelIndex ) ) != NULL )
  	{
  		C_LocalTempEntity		*pTemp;
  		int						frameCount = modelinfo->GetModelFrameCount( model );
  		color32					impactcolor = { r, g, b, a };
  
  		//Large, single blood sprite is a high-priority tent
  		if ( ( pTemp = TempEntAllocHigh( org, model ) ) != NULL )
  		{
  			pTemp->SetRenderMode( kRenderTransTexture );
  			pTemp->m_nRenderFX		= kRenderFxClampMinScale;
  			pTemp->m_flSpriteScale	= random->RandomFloat( size / 25, size / 35);
  			pTemp->flags			= FTENT_SPRANIMATE;
   
  			pTemp->m_clrRender		= impactcolor;
  			pTemp->tempent_renderamt= pTemp->m_clrRender->a;
  
  			pTemp->SetVelocity( vec3_origin );
  
  			pTemp->m_flFrameRate	= frameCount * 4; // Finish in 0.250 seconds
  			pTemp->die				= gpGlobals->curtime + (frameCount / pTemp->m_flFrameRate); // Play the whole thing Once
  
  			pTemp->m_flFrame		= 0;
  			pTemp->m_flFrameMax		= frameCount - 1;
  			pTemp->bounceFactor		= 0;
  			pTemp->SetLocalAnglesDim( Z_INDEX, random->RandomInt( 0, 360 ) );
  		}
  	}
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Create default sprite TE
  // Input  : *pos - 
  //			spriteIndex - 
  //			framerate - 
  // Output : C_LocalTempEntity
  //-----------------------------------------------------------------------------
  C_LocalTempEntity *CTempEnts::DefaultSprite( const Vector &pos, int spriteIndex, float framerate )
  {
  	C_LocalTempEntity		*pTemp;
  	int				frameCount;
  	const model_t	*pSprite;
  
  	// don't spawn while paused
  	if ( gpGlobals->frametime == 0.0 )
  		return NULL;
  
  	pSprite = modelinfo->GetModel( spriteIndex );
  	if ( !spriteIndex || !pSprite || modelinfo->GetModelType( pSprite ) != mod_sprite )
  	{
  		DevWarning( 1,"No Sprite %d!\n", spriteIndex);
  		return NULL;
  	}
  
  	frameCount = modelinfo->GetModelFrameCount( pSprite );
  
  	pTemp = TempEntAlloc( pos, pSprite );
  	if (!pTemp)
  		return NULL;
  
  	pTemp->m_flFrameMax = frameCount - 1;
  	pTemp->m_flSpriteScale = 1.0;
  	pTemp->flags |= FTENT_SPRANIMATE;
  	if ( framerate == 0 )
  		framerate = 10;
  
  	pTemp->m_flFrameRate = framerate;
  	pTemp->die = gpGlobals->curtime + (float)frameCount / framerate;
  	pTemp->m_flFrame = 0;
  	pTemp->SetLocalOrigin( pos );
  
  	return pTemp;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Create sprite smoke
  // Input  : *pTemp - 
  //			scale - 
  //-----------------------------------------------------------------------------
  void CTempEnts::Sprite_Smoke( C_LocalTempEntity *pTemp, float scale )
  {
  	if ( !pTemp )
  		return;
  
  	pTemp->SetRenderMode( kRenderTransAlpha );
  	pTemp->m_nRenderFX = kRenderFxNone;
  	pTemp->SetVelocity( Vector( 0, 0, 30 ) );
  	int iColor = random->RandomInt(20,35);
  	pTemp->SetRenderColor( iColor,
  		iColor,
  		iColor,
  		255 );
  	pTemp->SetLocalOriginDim( Z_INDEX, pTemp->GetLocalOriginDim( Z_INDEX ) + 20 );
  	pTemp->m_flSpriteScale = scale;
  	pTemp->flags = FTENT_WINDBLOWN;
  
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  // Input  : pos1 - 
  //			angles - 
  //			type - 
  //-----------------------------------------------------------------------------
  void CTempEnts::EjectBrass( const Vector &pos1, const QAngle &angles, const QAngle &gunAngles, int type )
  {
  	if ( cl_ejectbrass.GetBool() == false )
  		return;
  
  	const model_t *pModel = m_pShells[type];
  	
  	if ( pModel == NULL )
  		return;
  
  	C_LocalTempEntity	*pTemp = TempEntAlloc( pos1, pModel );
  
  	if ( pTemp == NULL )
  		return;
  
  	//Keep track of shell type
  	if ( type == 2 )
  	{
  		pTemp->hitSound = BOUNCE_SHOTSHELL;
  	}
  	else
  	{
  		pTemp->hitSound = BOUNCE_SHELL;
  	}
  
  	pTemp->m_nBody	= 0;
  
  	pTemp->flags |= ( FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE );
  
  	pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-1024,1024);
  	pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-1024,1024);
  	pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat(-1024,1024);
  
  	//Face forward
  	pTemp->SetAbsAngles( gunAngles );
  
  	pTemp->SetRenderMode( kRenderNormal );
  	pTemp->tempent_renderamt = 255;		// Set this for fadeout
  
  	Vector	dir;
  
  	AngleVectors( angles, &dir );
  
  	dir *= random->RandomFloat( 150.0f, 200.0f );
  
  	pTemp->SetVelocity( Vector(dir[0] + random->RandomFloat(-64,64),
  						dir[1] + random->RandomFloat(-64,64),
  						dir[2] + random->RandomFloat(  0,64) ) );
  
  	pTemp->die = gpGlobals->curtime + 1.0f + random->RandomFloat( 0.0f, 1.0f );	// Add an extra 0-1 secs of life	
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Create some simple physically simulated models
  //-----------------------------------------------------------------------------
  C_LocalTempEntity * CTempEnts::SpawnTempModel( const model_t *pModel, const Vector &vecOrigin, const QAngle &vecAngles, const Vector &vecVelocity, float flLifeTime, int iFlags )
  {
  	Assert( pModel );
  
  	// Alloc a new tempent
  	C_LocalTempEntity *pTemp = TempEntAlloc( vecOrigin, pModel );
  	if ( !pTemp )
  		return NULL;
  
  	pTemp->SetAbsAngles( vecAngles );
  	pTemp->m_nBody	= 0;
  	pTemp->flags |= iFlags;
  	pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-255,255);
  	pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-255,255);
  	pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat(-255,255);
  	pTemp->SetRenderMode( kRenderNormal );
  	pTemp->tempent_renderamt = 255;
  	pTemp->SetVelocity( vecVelocity );
  	pTemp->die = gpGlobals->curtime + flLifeTime;
  
  	return pTemp;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  // Input  : type - 
  //			entityIndex - 
  //			attachmentIndex - 
  //			firstPerson - 
  //-----------------------------------------------------------------------------
  void CTempEnts::MuzzleFlash( int type, ClientEntityHandle_t hEntity, int attachmentIndex, bool firstPerson )
  {
  	switch( type )
  	{
  	case MUZZLEFLASH_COMBINE:
  		if ( firstPerson )
  		{
  			MuzzleFlash_Combine_Player( hEntity, attachmentIndex );
  		}
  		else
  		{
  			MuzzleFlash_Combine_NPC( hEntity, attachmentIndex );
  		}
  		break;
  
  	case MUZZLEFLASH_SMG1:
  		if ( firstPerson )
  		{
  			MuzzleFlash_SMG1_Player( hEntity, attachmentIndex );
  		}
  		else
  		{
  			MuzzleFlash_SMG1_NPC( hEntity, attachmentIndex );
  		}
  		break;
  
  	case MUZZLEFLASH_PISTOL:
  		if ( firstPerson )
  		{
  			MuzzleFlash_Pistol_Player( hEntity, attachmentIndex );
  		}
  		else
  		{
  			MuzzleFlash_Pistol_NPC( hEntity, attachmentIndex );
  		}
  		break;
  	case MUZZLEFLASH_SHOTGUN:
  		if ( firstPerson )
  		{
  			MuzzleFlash_Shotgun_Player( hEntity, attachmentIndex );
  		}
  		else
  		{
  			MuzzleFlash_Shotgun_NPC( hEntity, attachmentIndex );
  		}
  		break;
  	case MUZZLEFLASH_357:
  		if ( firstPerson )
  		{
  			MuzzleFlash_357_Player( hEntity, attachmentIndex );
  		}
  		break;
  	case MUZZLEFLASH_RPG:
  		if ( firstPerson )
  		{
  			// MuzzleFlash_RPG_Player( hEntity, attachmentIndex );
  		}
  		else
  		{
  			MuzzleFlash_RPG_NPC( hEntity, attachmentIndex );
  		}
  		break;
  		break;
  	default:
  		{
  			//NOTENOTE: This means you specified an invalid muzzleflash type, check your spelling?
  			Assert( 0 );
  		}
  		break;
  	}
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Play muzzle flash
  // Input  : *pos1 - 
  //			type - 
  //-----------------------------------------------------------------------------
  void CTempEnts::MuzzleFlash( const Vector& pos1, const QAngle& angles, int type, ClientEntityHandle_t hEntity, bool firstPerson )
  {
  #ifdef CSTRIKE_DLL
  
  	return;
  
  #else
  
  	//NOTENOTE: This function is becoming obsolete as the muzzles are moved over to being local to attachments
  
  	switch ( type )
  	{
  	//
  	// Shotgun
  	//
  	case MUZZLEFLASH_SHOTGUN:
  		if ( firstPerson )
  		{
  			MuzzleFlash_Shotgun_Player( hEntity, 1 );
  		}
  		else
  		{
  			MuzzleFlash_Shotgun_NPC( hEntity, 1 );
  		}
  		break;
  
  	// UNDONE: These need their own effects/sprites.  For now use the pistol
  	// SMG1
  	case MUZZLEFLASH_SMG1:
  		if ( firstPerson )
  		{
  			MuzzleFlash_SMG1_Player( hEntity, 1 );
  		}
  		else
  		{
  			MuzzleFlash_SMG1_NPC( hEntity, 1 );
  		}
  		break;
  
  	// SMG2
  	case MUZZLEFLASH_SMG2:
  	case MUZZLEFLASH_PISTOL:
  		if ( firstPerson )
  		{
  			MuzzleFlash_Pistol_Player( hEntity, 1 );
  		}
  		else
  		{
  			MuzzleFlash_Pistol_NPC( hEntity, 1 );
  		}
  		break;
  
  	case MUZZLEFLASH_COMBINE:
  		if ( firstPerson )
  		{
  			//FIXME: These should go away
  			MuzzleFlash_Combine_Player( hEntity, 1 );
  		}
  		else
  		{
  			//FIXME: These should go away
  			MuzzleFlash_Combine_NPC( hEntity, 1 );
  		}
  		break;
  	
  	default:
  		// There's no supported muzzle flash for the type specified!
  		Assert(0);
  		break;
  	}
  
  #endif
  
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Create explosion sprite
  // Input  : *pTemp - 
  //			scale - 
  //			flags - 
  //-----------------------------------------------------------------------------
  void CTempEnts::Sprite_Explode( C_LocalTempEntity *pTemp, float scale, int flags )
  {
  	if ( !pTemp )
  		return;
  
  	if ( flags & TE_EXPLFLAG_NOADDITIVE )
  	{
  		// solid sprite
  		pTemp->SetRenderMode( kRenderNormal );
  		pTemp->SetRenderColorA( 255 ); 
  	}
  	else if( flags & TE_EXPLFLAG_DRAWALPHA )
  	{
  		// alpha sprite
  		pTemp->SetRenderMode( kRenderTransAlpha ); 
  		pTemp->SetRenderColorA( 180 );
  	}
  	else
  	{
  		// additive sprite
  		pTemp->SetRenderMode( kRenderTransAdd );
  		pTemp->SetRenderColorA( 180 );
  	}
  
  	if ( flags & TE_EXPLFLAG_ROTATE )
  	{
  		pTemp->SetLocalAnglesDim( Z_INDEX, random->RandomInt( 0, 360 ) );
  	}
  
  	pTemp->m_nRenderFX = kRenderFxNone;
  	pTemp->SetVelocity( Vector( 0, 0, 8 ) );
  	pTemp->SetRenderColor( 255, 255, 255 );
  	pTemp->SetLocalOriginDim( Z_INDEX, pTemp->GetLocalOriginDim( Z_INDEX ) + 10 );
  	pTemp->m_flSpriteScale = scale;
  }
  
  enum
  {
  	SHELL_NONE = 0,
  	SHELL_SMALL,
  	SHELL_BIG,
  	SHELL_SHOTGUN,
  };
  
  //-----------------------------------------------------------------------------
  // Purpose: Clear existing temp entities
  //-----------------------------------------------------------------------------
  void CTempEnts::Clear( void )
  {
  	FOR_EACH_LL( m_TempEnts, i )
  	{
  		C_LocalTempEntity *p = m_TempEnts[ i ];
  
  		m_TempEntsPool.Free( p );
  	}
  
  	m_TempEnts.RemoveAll();
  	g_BreakableHelper.Clear();
  }
  
  C_LocalTempEntity *CTempEnts::FindTempEntByID( int nID, int nSubID )
  {
  	// HACK HACK: We're using skin and hitsounds as a hacky way to store an ID and sub-ID for later identification
  	FOR_EACH_LL( m_TempEnts, i )
  	{
  		C_LocalTempEntity *p = m_TempEnts[ i ];
  		if ( p && p->m_nSkin == nID && p->hitSound == nSubID )
  		{
  			return p;
  		}
  	}
  
  	return NULL;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Allocate temp entity ( normal/low priority )
  // Input  : *org - 
  //			*model - 
  // Output : C_LocalTempEntity
  //-----------------------------------------------------------------------------
  C_LocalTempEntity *CTempEnts::TempEntAlloc( const Vector& org, const model_t *model )
  {
  	C_LocalTempEntity		*pTemp;
  
  	if ( !model )
  	{
  		DevWarning( 1, "Can't create temporary entity with NULL model!\n" );
  		return NULL;
  	}
  
  	pTemp = TempEntAlloc();
  
  	if ( !pTemp )
  	{
  		DevWarning( 1, "Overflow %d temporary ents!\n", MAX_TEMP_ENTITIES );
  		return NULL;
  	}
  
  	m_TempEnts.AddToTail( pTemp );
  
  	pTemp->Prepare( model, gpGlobals->curtime );
  
  	pTemp->priority = TENTPRIORITY_LOW;
  	pTemp->SetAbsOrigin( org );
  
  	pTemp->m_RenderGroup = RENDER_GROUP_OTHER;
  	pTemp->AddToLeafSystem( pTemp->m_RenderGroup );
  
  	if ( CommandLine()->CheckParm( "-tools" ) != NULL )
  	{
  #ifdef _DEBUG
  		static bool first = true;
  		if ( first )
  		{
  			Msg( "Currently not recording tempents, since recording them as entites causes them to be deleted as entities, even though they were allocated through the tempent pool. (crash)\n" );
  			first = false;
  		}
  #endif
  //		ClientEntityList().AddNonNetworkableEntity(	pTemp );
  	}
  
  	return pTemp;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  // Output : C_LocalTempEntity
  //-----------------------------------------------------------------------------
  C_LocalTempEntity *CTempEnts::TempEntAlloc()
  {
  	if ( m_TempEnts.Count() >= MAX_TEMP_ENTITIES )
  		return NULL;
  
  	C_LocalTempEntity *pTemp = m_TempEntsPool.AllocZero();
  	return pTemp;
  }
  
  void CTempEnts::TempEntFree( int index )
  {
  	C_LocalTempEntity *pTemp = m_TempEnts[ index ];
  	if ( pTemp )
  	{
  		// Remove from the active list.
  		m_TempEnts.Remove( index );
  
  		// Cleanup its data.
  		pTemp->RemoveFromLeafSystem();
  
  		// Remove the tempent from the ClientEntityList before removing it from the pool.
  		if ( ( pTemp->flags & FTENT_CLIENTSIDEPARTICLES ) )
  		{			
  			// Stop the particle emission if this hasn't happened already - collision or system timing out on its own.
  			if ( !pTemp->m_bParticleCollision )
  			{
  				pTemp->ParticleProp()->StopEmission();
  			}
  			ClientEntityList().RemoveEntity( pTemp->GetRefEHandle() );
  		}
  
  		pTemp->OnRemoveTempEntity();
  	
  		m_TempEntsPool.Free( pTemp );
  	}
  }
  
  
  // Free the first low priority tempent it finds.
  bool CTempEnts::FreeLowPriorityTempEnt()
  {
  	int next = 0;
  	for( int i = m_TempEnts.Head(); i != m_TempEnts.InvalidIndex(); i = next )
  	{
  		next = m_TempEnts.Next( i );
  
  		C_LocalTempEntity *pActive = m_TempEnts[ i ];
  
  		if ( pActive->priority == TENTPRIORITY_LOW )
  		{
  			TempEntFree( i );
  			return true;
  		}
  	}
  
  	return false;
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: Allocate a temp entity, if there are no slots, kick out a low priority
  //  one if possible
  // Input  : *org - 
  //			*model - 
  // Output : C_LocalTempEntity
  //-----------------------------------------------------------------------------
  C_LocalTempEntity *CTempEnts::TempEntAllocHigh( const Vector& org, const model_t *model )
  {
  	C_LocalTempEntity		*pTemp;
  
  	if ( !model )
  	{
  		DevWarning( 1, "temporary ent model invalid\n" );
  		return NULL;
  	}
  
  	pTemp = TempEntAlloc();
  	if ( !pTemp )
  	{
  		// no temporary ents free, so find the first active low-priority temp ent 
  		// and overwrite it.
  		FreeLowPriorityTempEnt();
  
  		pTemp = TempEntAlloc();
  	}
  
  	
  	if ( !pTemp )
  	{
  		// didn't find anything? The tent list is either full of high-priority tents
  		// or all tents in the list are still due to live for > 10 seconds. 
  		DevWarning( 1,"Couldn't alloc a high priority TENT (max %i)!\n", MAX_TEMP_ENTITIES );
  		return NULL;
  	}
  
  	m_TempEnts.AddToTail( pTemp );
  
  	pTemp->Prepare( model, gpGlobals->curtime );
  
  	pTemp->priority = TENTPRIORITY_HIGH;
  	pTemp->SetLocalOrigin( org );
  
  	pTemp->m_RenderGroup = RENDER_GROUP_OTHER;
  	pTemp->AddToLeafSystem( pTemp->m_RenderGroup );
  
  	if ( CommandLine()->CheckParm( "-tools" ) != NULL )
  	{
  		ClientEntityList().AddNonNetworkableEntity(	pTemp );
  	}
  
  	return pTemp;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Play sound when temp ent collides with something
  // Input  : *pTemp - 
  //			damp - 
  //-----------------------------------------------------------------------------
  void CTempEnts::PlaySound ( C_LocalTempEntity *pTemp, float damp )
  {
  	const char	*soundname = NULL;
  	float fvol;
  	bool isshellcasing = false;
  	int zvel;
  
  	switch ( pTemp->hitSound )
  	{
  	default:
  		return;	// null sound
  
  	case BOUNCE_GLASS:
  		{
  			soundname = "Bounce.Glass";
  		}
  		break;
  
  	case BOUNCE_METAL:
  		{
  			soundname = "Bounce.Metal";
  		}
  		break;
  
  	case BOUNCE_FLESH:
  		{
  			soundname = "Bounce.Flesh";
  		}
  		break;
  
  	case BOUNCE_WOOD:
  		{
  			soundname = "Bounce.Wood";
  		}
  		break;
  
  	case BOUNCE_SHRAP:
  		{
  			soundname = "Bounce.Shrapnel";
  		}
  		break;
  
  	case BOUNCE_SHOTSHELL:
  		{
  			soundname = "Bounce.ShotgunShell";
  			isshellcasing = true; // shell casings have different playback parameters
  		}
  		break;
  
  	case BOUNCE_SHELL:
  		{
  			soundname = "Bounce.Shell";
  			isshellcasing = true; // shell casings have different playback parameters
  		}
  		break;
  
  	case BOUNCE_CONCRETE:
  		{
  			soundname = "Bounce.Concrete";
  		}
  		break;
  
  //#ifdef CSTRIKE_DLL
  
  		case TE_PISTOL_SHELL:
  		{
  			soundname = "Bounce.PistolShell";
  		}
  		break;
  
  		case TE_RIFLE_SHELL:
  		{
  			soundname = "Bounce.RifleShell";
  		}
  		break;
  
  		case TE_SHOTGUN_SHELL:
  		{
  			soundname = "Bounce.ShotgunShell";
  		}
  		break;
  //#endif
  	}
  
  	zvel = abs( pTemp->GetVelocity()[2] );
  		
  	// only play one out of every n
  
  	if ( isshellcasing )
  	{	
  		// play first bounce, then 1 out of 3		
  		if ( zvel < 200 && random->RandomInt(0,3) )
  			return;
  	}
  	else
  	{
  		if ( random->RandomInt(0,5) ) 
  			return;
  	}
  
  	CSoundParameters params;
  	if ( !C_BaseEntity::GetParametersForSound( soundname, params, NULL ) )
  		return;
  
  	fvol = params.volume;
  
  	if ( damp > 0.0 )
  	{
  		int pitch;
  		
  		if ( isshellcasing )
  		{
  			fvol *= MIN (1.0, ((float)zvel) / 350.0); 
  		}
  		else
  		{
  			fvol *= MIN (1.0, ((float)zvel) / 450.0); 
  		}
  		
  		if ( !random->RandomInt(0,3) && !isshellcasing )
  		{
  			pitch = random->RandomInt( params.pitchlow, params.pitchhigh );
  		}
  		else
  		{
  			pitch = params.pitch;
  		}
  
  		CLocalPlayerFilter filter;
  
  		EmitSound_t ep;
  		ep.m_nChannel = params.channel;
  		ep.m_pSoundName =  params.soundname;
  		ep.m_flVolume = fvol;
  		ep.m_SoundLevel = params.soundlevel;
  		ep.m_nPitch = pitch;
  		ep.m_pOrigin = &pTemp->GetAbsOrigin();
  
  		C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, ep );
  	}
  }
  					
  //-----------------------------------------------------------------------------
  // Purpose: Add temp entity to visible entities list of it's in PVS
  // Input  : *pEntity - 
  // Output : int
  //-----------------------------------------------------------------------------
  int CTempEnts::AddVisibleTempEntity( C_LocalTempEntity *pEntity )
  {
  	int i;
  	Vector mins, maxs;
  	Vector model_mins, model_maxs;
  
  	if ( !pEntity->GetModel() )
  		return 0;
  
  	modelinfo->GetModelBounds( pEntity->GetModel(), model_mins, model_maxs );
  
  	for (i=0 ; i<3 ; i++)
  	{
  		mins[i] = pEntity->GetAbsOrigin()[i] + model_mins[i];
  		maxs[i] = pEntity->GetAbsOrigin()[i] + model_maxs[i];
  	}
  
  	// FIXME: Vis isn't setup by the time we get here, so this call fails if 
  	//		  you try to add a tempent before the first frame is drawn, and it's
  	//		  one frame behind the rest of the time. Fix this.
  	// does the box intersect a visible leaf?
  	//if ( engine->IsBoxInViewCluster( mins, maxs ) )
  	{
  		// Temporary entities have no corresponding element in cl_entitylist
  		pEntity->index = -1;
  		
  		// Add to list
  		if( pEntity->m_RenderGroup == RENDER_GROUP_OTHER )
  		{
  			pEntity->AddToLeafSystem();
  		}
  		else
  		{
  			pEntity->AddToLeafSystem( pEntity->m_RenderGroup );
  		}
  
  		return 1;
  	}
  	return 0;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Runs Temp Ent simulation routines
  //-----------------------------------------------------------------------------
  void CTempEnts::Update(void)
  {
  	VPROF_("CTempEnts::Update", 1, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT);
  	static int gTempEntFrame = 0;
  	float		frametime;
  
  	// Don't simulate while loading
  	if ( ( m_TempEnts.Count() == 0 ) || !engine->IsInGame() )		
  	{
  		return;
  	}
  
  	// !!!BUGBUG	-- This needs to be time based
  	gTempEntFrame = (gTempEntFrame+1) & 31;
  
  	frametime = gpGlobals->frametime;
  
  	// in order to have tents collide with players, we have to run the player prediction code so
  	// that the client has the player list. We run this code once when we detect any COLLIDEALL 
  	// tent, then set this BOOL to true so the code doesn't get run again if there's more than
  	// one COLLIDEALL ent for this update. (often are).
  
  	// !!! Don't simulate while paused....  This is sort of a hack, revisit.
  	if ( frametime == 0 )
  	{
  		FOR_EACH_LL( m_TempEnts, i )
  		{
  			C_LocalTempEntity *current = m_TempEnts[ i ];
  
  			AddVisibleTempEntity( current );
  		}
  	}
  	else
  	{
  		int next = 0;
  		for( int i = m_TempEnts.Head(); i != m_TempEnts.InvalidIndex(); i = next )
  		{
  			next = m_TempEnts.Next( i );
  
  			C_LocalTempEntity *current = m_TempEnts[ i ];
  
  			// Kill it
  			if ( !current->IsActive() || !current->Frame( frametime, gTempEntFrame ) )
  			{
  				TempEntFree( i );
  			}
  			else
  			{
  				// Cull to PVS (not frustum cull, just PVS)
  				if ( !AddVisibleTempEntity( current ) )
  				{
  					if ( !( current->flags & FTENT_PERSIST ) ) 
  					{
  						// If we can't draw it this frame, just dump it.
  						current->die = gpGlobals->curtime;
  						// Don't fade out, just die
  						current->flags &= ~FTENT_FADEOUT;
  
  						TempEntFree( i );
  					}
  				}
  			}
  		}
  	}
  }
  
  // Recache tempents which might have been flushed
  void CTempEnts::LevelInit()
  {
  #ifndef TF_CLIENT_DLL
  	m_pSpriteMuzzleFlash[0] = (model_t *)engine->LoadModel( "sprites/ar2_muzzle1.vmt" );
  	m_pSpriteMuzzleFlash[1] = (model_t *)engine->LoadModel( "sprites/muzzleflash4.vmt" );
  	m_pSpriteMuzzleFlash[2] = (model_t *)engine->LoadModel( "sprites/muzzleflash4.vmt" );
  
  	m_pSpriteAR2Flash[0] = (model_t *)engine->LoadModel( "sprites/ar2_muzzle1b.vmt" );
  	m_pSpriteAR2Flash[1] = (model_t *)engine->LoadModel( "sprites/ar2_muzzle2b.vmt" );
  	m_pSpriteAR2Flash[2] = (model_t *)engine->LoadModel( "sprites/ar2_muzzle3b.vmt" );
  	m_pSpriteAR2Flash[3] = (model_t *)engine->LoadModel( "sprites/ar2_muzzle4b.vmt" );
  
  	m_pSpriteCombineFlash[0] = (model_t *)engine->LoadModel( "effects/combinemuzzle1.vmt" );
  	m_pSpriteCombineFlash[1] = (model_t *)engine->LoadModel( "effects/combinemuzzle2.vmt" );
  
  	m_pShells[0] = (model_t *) engine->LoadModel( "models/weapons/shell.mdl" );
  	m_pShells[1] = (model_t *) engine->LoadModel( "models/weapons/rifleshell.mdl" );
  	m_pShells[2] = (model_t *) engine->LoadModel( "models/weapons/shotgun_shell.mdl" );
  #endif
  
  #if defined( HL1_CLIENT_DLL )
  	m_pHL1Shell			= (model_t *)engine->LoadModel( "models/shell.mdl" );
  	m_pHL1ShotgunShell	= (model_t *)engine->LoadModel( "models/shotgunshell.mdl" );
  #endif
  
  //#if defined( CSTRIKE_DLL ) || defined ( SDK_DLL )
  	m_pCS_9MMShell		= (model_t *)engine->LoadModel( "models/Shells/shell_9mm.mdl" );
  	m_pCS_57Shell		= (model_t *)engine->LoadModel( "models/Shells/shell_57.mdl" );
  	m_pCS_12GaugeShell	= (model_t *)engine->LoadModel( "models/Shells/shell_12gauge.mdl" );
  	m_pCS_556Shell		= (model_t *)engine->LoadModel( "models/Shells/shell_556.mdl" );
  	m_pCS_762NATOShell	= (model_t *)engine->LoadModel( "models/Shells/shell_762nato.mdl" );
  	m_pCS_338MAGShell	= (model_t *)engine->LoadModel( "models/Shells/shell_338mag.mdl" );
  //#endif
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: Initialize TE system
  //-----------------------------------------------------------------------------
  void CTempEnts::Init (void)
  {
  	m_pSpriteMuzzleFlash[0] = NULL;
  	m_pSpriteMuzzleFlash[1] = NULL;
  	m_pSpriteMuzzleFlash[2] = NULL;
  
  	m_pSpriteAR2Flash[0] = NULL;
  	m_pSpriteAR2Flash[1] = NULL;
  	m_pSpriteAR2Flash[2] = NULL;
  	m_pSpriteAR2Flash[3] = NULL;
  
  	m_pSpriteCombineFlash[0] = NULL;
  	m_pSpriteCombineFlash[1] = NULL;
  
  	m_pShells[0] = NULL;
  	m_pShells[1] = NULL;
  	m_pShells[2] = NULL;
  
  #if defined( HL1_CLIENT_DLL )
  	m_pHL1Shell			= NULL;
  	m_pHL1ShotgunShell	= NULL;
  #endif
  
  //#if defined( CSTRIKE_DLL ) || defined ( SDK_DLL )
  	m_pCS_9MMShell		= NULL;
  	m_pCS_57Shell		= NULL;
  	m_pCS_12GaugeShell	= NULL;
  	m_pCS_556Shell		= NULL;
  	m_pCS_762NATOShell	= NULL;
  	m_pCS_338MAGShell	= NULL;
  //#endif
  
  	// Clear out lists to start
  	Clear();
  }
  
  
  void CTempEnts::LevelShutdown()
  {
  	// Free all active tempents.
  	Clear();
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  //-----------------------------------------------------------------------------
  void CTempEnts::Shutdown()
  {
  	LevelShutdown();
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: Cache off all material references
  // Input  : *pEmitter - Emitter used for material lookup
  //-----------------------------------------------------------------------------
  inline void CTempEnts::CacheMuzzleFlashes( void )
  {
  	int i;
  	for ( i = 0; i < 4; i++ )
  	{
  		if ( m_Material_MuzzleFlash_Player[i] == NULL )
  		{
  			m_Material_MuzzleFlash_Player[i] = ParticleMgr()->GetPMaterial( VarArgs( "effects/muzzleflash%d_noz", i+1 ) );
  		}
  	}
  
  	for ( i = 0; i < 4; i++ )
  	{
  		if ( m_Material_MuzzleFlash_NPC[i] == NULL )
  		{
  			m_Material_MuzzleFlash_NPC[i] = ParticleMgr()->GetPMaterial( VarArgs( "effects/muzzleflash%d", i+1 ) );
  		}
  	}
  
  	for ( i = 0; i < 2; i++ )
  	{
  		if ( m_Material_Combine_MuzzleFlash_Player[i] == NULL )
  		{
  			m_Material_Combine_MuzzleFlash_Player[i] = ParticleMgr()->GetPMaterial( VarArgs( "effects/combinemuzzle%d_noz", i+1 ) );
  		}
  	}
  
  	for ( i = 0; i < 2; i++ )
  	{
  		if ( m_Material_Combine_MuzzleFlash_NPC[i] == NULL )
  		{
  			m_Material_Combine_MuzzleFlash_NPC[i] = ParticleMgr()->GetPMaterial( VarArgs( "effects/combinemuzzle%d", i+1 ) );
  		}
  	}
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  // Input  : entityIndex - 
  //			attachmentIndex - 
  //-----------------------------------------------------------------------------
  void CTempEnts::MuzzleFlash_Combine_Player( ClientEntityHandle_t hEntity, int attachmentIndex )
  {
  	VPROF_BUDGET( "MuzzleFlash_Combine_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  	CSmartPtr<CLocalSpaceEmitter> pSimple = CLocalSpaceEmitter::Create( "MuzzleFlash", hEntity, attachmentIndex, FLE_VIEWMODEL );
  
  	CacheMuzzleFlashes();
  
  	SimpleParticle *pParticle;
  	Vector			forward(1,0,0), offset; //NOTENOTE: All coords are in local space
  
  	float flScale = random->RandomFloat( 2.0f, 2.25f );
  
  	pSimple->SetDrawBeforeViewModel( true );
  
  	// Flash
  	for ( int i = 1; i < 6; i++ )
  	{
  		offset = (forward * (i*8.0f*flScale));
  
  		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_Combine_MuzzleFlash_Player[random->RandomInt(0,1)], offset );
  			
  		if ( pParticle == NULL )
  			return;
  
  		pParticle->m_flLifetime		= 0.0f;
  		pParticle->m_flDieTime		= 0.025f;
  
  		pParticle->m_vecVelocity.Init();
  
  		pParticle->m_uchColor[0]	= 255;
  		pParticle->m_uchColor[1]	= 255;
  		pParticle->m_uchColor[2]	= 200+random->RandomInt(0,55);
  
  		pParticle->m_uchStartAlpha	= 255;
  		pParticle->m_uchEndAlpha	= 255;
  
  		pParticle->m_uchStartSize	= ( (random->RandomFloat( 6.0f, 8.0f ) * (12-(i))/12) * flScale );
  		pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
  		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  		pParticle->m_flRollDelta	= 0.0f;
  	}
  
  	// Tack on the smoke
  	pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_Combine_MuzzleFlash_Player[random->RandomInt(0,1)], vec3_origin );
  		
  	if ( pParticle == NULL )
  		return;
  
  	pParticle->m_flLifetime		= 0.0f;
  	pParticle->m_flDieTime		= 0.025f;
  
  	pParticle->m_vecVelocity.Init();
  
  	pParticle->m_uchColor[0]	= 255;
  	pParticle->m_uchColor[1]	= 255;
  	pParticle->m_uchColor[2]	= 255;
  
  	pParticle->m_uchStartAlpha	= random->RandomInt( 64, 128 );
  	pParticle->m_uchEndAlpha	= 32;
  
  	pParticle->m_uchStartSize	= random->RandomFloat( 10.0f, 16.0f );
  	pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
  	
  	pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  	pParticle->m_flRollDelta	= 0.0f;
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  // Input  : &origin - 
  //			&angles - 
  //			entityIndex - 
  //-----------------------------------------------------------------------------
  void CTempEnts::MuzzleFlash_Combine_NPC( ClientEntityHandle_t hEntity, int attachmentIndex )
  {
  	VPROF_BUDGET( "MuzzleFlash_Combine_NPC", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  
  	// If the material isn't available, let's not do anything.
  	if ( g_Mat_Combine_Muzzleflash[0] == NULL )
  	{
  		return;
  	}
  
  	CSmartPtr<CLocalSpaceEmitter> pSimple = CLocalSpaceEmitter::Create( "MuzzleFlash_Combine_NPC", hEntity, attachmentIndex );
  
  	SimpleParticle *pParticle;
  	Vector			forward(1,0,0), offset; //NOTENOTE: All coords are in local space
  
  	float flScale = random->RandomFloat( 1.0f, 1.5f );
  
  	float burstSpeed = random->RandomFloat( 50.0f, 150.0f );
  
  #define	FRONT_LENGTH 6
  
  	// Front flash
  	for ( int i = 1; i < FRONT_LENGTH; i++ )
  	{
  		offset = (forward * (i*2.0f*flScale));
  
  		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_Combine_Muzzleflash[random->RandomInt(0,1)], offset );
  		if ( pParticle == NULL )
  			return;
  
  		pParticle->m_flLifetime		= 0.0f;
  		pParticle->m_flDieTime		= 0.1f;
  
  		pParticle->m_vecVelocity = forward * burstSpeed;
  
  		pParticle->m_uchColor[0]	= 255;
  		pParticle->m_uchColor[1]	= 255;
  		pParticle->m_uchColor[2]	= 255;
  
  		pParticle->m_uchStartAlpha	= 255.0f;
  		pParticle->m_uchEndAlpha	= 0;
  
  		pParticle->m_uchStartSize	= ( (random->RandomFloat( 6.0f, 8.0f ) * (FRONT_LENGTH*1.25f-(i))/(FRONT_LENGTH)) * flScale );
  		pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
  		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  		pParticle->m_flRollDelta	= 0.0f;
  	}
  	
  	Vector right(0,1,0), up(0,0,1);
  	Vector dir = right - up;
  
  #define	SIDE_LENGTH	6
  
  	burstSpeed = random->RandomFloat( 50.0f, 150.0f );
  
  	// Diagonal flash
  	for ( int i = 1; i < SIDE_LENGTH; i++ )
  	{
  		offset = (dir * (i*flScale));
  
  		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_Combine_Muzzleflash[random->RandomInt(0,1)], offset );
  			
  		if ( pParticle == NULL )
  			return;
  
  		pParticle->m_flLifetime		= 0.0f;
  		pParticle->m_flDieTime		= 0.2f;
  
  		pParticle->m_vecVelocity = dir * burstSpeed * 0.25f;
  
  		pParticle->m_uchColor[0]	= 255;
  		pParticle->m_uchColor[1]	= 255;
  		pParticle->m_uchColor[2]	= 255;
  
  		pParticle->m_uchStartAlpha	= 255;
  		pParticle->m_uchEndAlpha	= 0;
  
  		pParticle->m_uchStartSize	= ( (random->RandomFloat( 2.0f, 4.0f ) * (SIDE_LENGTH-(i))/(SIDE_LENGTH*0.5f)) * flScale );
  		pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
  		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  		pParticle->m_flRollDelta	= 0.0f;
  	}
  
  	dir = right + up;
  	burstSpeed = random->RandomFloat( 50.0f, 150.0f );
  
  	// Diagonal flash
  	for ( int i = 1; i < SIDE_LENGTH; i++ )
  	{
  		offset = (-dir * (i*flScale));
  
  		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_Combine_Muzzleflash[random->RandomInt(0,1)], offset );
  		if ( pParticle == NULL )
  			return;
  
  		pParticle->m_flLifetime		= 0.0f;
  		pParticle->m_flDieTime		= 0.2f;
  
  		pParticle->m_vecVelocity = dir * -burstSpeed * 0.25f;
  
  		pParticle->m_uchColor[0]	= 255;
  		pParticle->m_uchColor[1]	= 255;
  		pParticle->m_uchColor[2]	= 255;
  
  		pParticle->m_uchStartAlpha	= 255;
  		pParticle->m_uchEndAlpha	= 0;
  
  		pParticle->m_uchStartSize	= ( (random->RandomFloat( 2.0f, 4.0f ) * (SIDE_LENGTH-(i))/(SIDE_LENGTH*0.5f)) * flScale );
  		pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
  		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  		pParticle->m_flRollDelta	= 0.0f;
  	}
  
  	dir = up;
  	burstSpeed = random->RandomFloat( 50.0f, 150.0f );
  
  	// Top flash
  	for ( int i = 1; i < SIDE_LENGTH; i++ )
  	{
  		offset = (dir * (i*flScale));
  
  		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_Combine_Muzzleflash[random->RandomInt(0,1)], offset );
  		if ( pParticle == NULL )
  			return;
  
  		pParticle->m_flLifetime		= 0.0f;
  		pParticle->m_flDieTime		= 0.2f;
  
  		pParticle->m_vecVelocity = dir * burstSpeed * 0.25f;
  
  		pParticle->m_uchColor[0]	= 255;
  		pParticle->m_uchColor[1]	= 255;
  		pParticle->m_uchColor[2]	= 255;
  
  		pParticle->m_uchStartAlpha	= 255;
  		pParticle->m_uchEndAlpha	= 0;
  
  		pParticle->m_uchStartSize	= ( (random->RandomFloat( 2.0f, 4.0f ) * (SIDE_LENGTH-(i))/(SIDE_LENGTH*0.5f)) * flScale );
  		pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
  		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  		pParticle->m_flRollDelta	= 0.0f;
  	}
  
  	pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_Combine_Muzzleflash[2], vec3_origin );
  	if ( pParticle == NULL )
  		return;
  
  	pParticle->m_flLifetime		= 0.0f;
  	pParticle->m_flDieTime		= random->RandomFloat( 0.3f, 0.4f );
  
  	pParticle->m_vecVelocity.Init();
  
  	pParticle->m_uchColor[0]	= 255;
  	pParticle->m_uchColor[1]	= 255;
  	pParticle->m_uchColor[2]	= 255;
  
  	pParticle->m_uchStartAlpha	= 255;
  	pParticle->m_uchEndAlpha	= 0;
  
  	pParticle->m_uchStartSize	= flScale * random->RandomFloat( 12.0f, 16.0f );
  	pParticle->m_uchEndSize		= 0.0f;
  	pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  	pParticle->m_flRollDelta	= 0.0f;
  
  	matrix3x4_t	matAttachment;
  	Vector		origin;
  	
  	// Grab the origin out of the transform for the attachment
  	if ( FX_GetAttachmentTransform( hEntity, attachmentIndex, matAttachment ) )
  	{
  		origin.x = matAttachment[0][3];
  		origin.y = matAttachment[1][3];
  		origin.z = matAttachment[2][3];
  	}
  	else
  	{
  		//NOTENOTE: If you're here, you've specified an entity or an attachment that is invalid
  		Assert(0);
  		return;
  	}
  
  	if ( muzzleflash_light.GetBool() )
  	{
  		C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( hEntity );
  		if ( pEnt )
  		{
  			dlight_t *el = effects->CL_AllocElight( LIGHT_INDEX_MUZZLEFLASH + pEnt->entindex() );
  
  			el->origin	= origin;
  
  			el->color.r = 64;
  			el->color.g = 128;
  			el->color.b = 255;
  			el->color.exponent = 5;
  
  			el->radius	= random->RandomInt( 32, 128 );
  			el->decay	= el->radius / 0.05f;
  			el->die		= gpGlobals->curtime + 0.05f;
  		}
  	}
  }
  
  //==================================================
  // Purpose: 
  // Input: 
  //==================================================
  
  void CTempEnts::MuzzleFlash_AR2_NPC( const Vector &origin, const QAngle &angles, ClientEntityHandle_t hEntity )
  {
  	//Draw the cloud of fire
  	FX_MuzzleEffect( origin, angles, 1.0f, hEntity );
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  //-----------------------------------------------------------------------------
  void CTempEnts::MuzzleFlash_SMG1_NPC( ClientEntityHandle_t hEntity, int attachmentIndex )
  {
  	//Draw the cloud of fire
  	FX_MuzzleEffectAttached( 1.0f, hEntity, attachmentIndex, NULL, true );
  }
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  //-----------------------------------------------------------------------------
  void CTempEnts::MuzzleFlash_SMG1_Player( ClientEntityHandle_t hEntity, int attachmentIndex )
  {
  	VPROF_BUDGET( "MuzzleFlash_SMG1_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  	CSmartPtr<CLocalSpaceEmitter> pSimple = CLocalSpaceEmitter::Create( "MuzzleFlash_SMG1_Player", hEntity, attachmentIndex, FLE_VIEWMODEL );
  
  	CacheMuzzleFlashes();
  
  	SimpleParticle *pParticle;
  	Vector			forward(1,0,0), offset; //NOTENOTE: All coords are in local space
  
  	float flScale = random->RandomFloat( 1.25f, 1.5f );
  
  	pSimple->SetDrawBeforeViewModel( true );
  
  	// Flash
  	for ( int i = 1; i < 6; i++ )
  	{
  		offset = (forward * (i*8.0f*flScale));
  
  		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_MuzzleFlash_Player[random->RandomInt(0,3)], offset );
  			
  		if ( pParticle == NULL )
  			return;
  
  		pParticle->m_flLifetime		= 0.0f;
  		pParticle->m_flDieTime		= 0.025f;
  
  		pParticle->m_vecVelocity.Init();
  
  		pParticle->m_uchColor[0]	= 255;
  		pParticle->m_uchColor[1]	= 255;
  		pParticle->m_uchColor[2]	= 200+random->RandomInt(0,55);
  
  		pParticle->m_uchStartAlpha	= 255;
  		pParticle->m_uchEndAlpha	= 255;
  
  		pParticle->m_uchStartSize	= ( (random->RandomFloat( 6.0f, 8.0f ) * (8-(i))/6) * flScale );
  		pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
  		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  		pParticle->m_flRollDelta	= 0.0f;
  	}
  }
  
  //==================================================
  // Purpose: 
  // Input: 
  //==================================================
  
  void CTempEnts::MuzzleFlash_Shotgun_Player( ClientEntityHandle_t hEntity, int attachmentIndex )
  {
  	VPROF_BUDGET( "MuzzleFlash_Shotgun_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  	CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "MuzzleFlash_Shotgun_Player" );
  
  	pSimple->SetDrawBeforeViewModel( true );
  
  	CacheMuzzleFlashes();
  
  	Vector origin;
  	QAngle angles;
  
  	// Get our attachment's transformation matrix
  	FX_GetAttachmentTransform( hEntity, attachmentIndex, &origin, &angles );
  
  	pSimple->GetBinding().SetBBox( origin - Vector( 4, 4, 4 ), origin + Vector( 4, 4, 4 ) );
  
  	Vector forward;
  	AngleVectors( angles, &forward, NULL, NULL );
  
  	SimpleParticle *pParticle;
  	Vector offset;
  
  	float flScale = random->RandomFloat( 1.25f, 1.5f );
  
  	// Flash
  	for ( int i = 1; i < 6; i++ )
  	{
  		offset = origin + (forward * (i*8.0f*flScale));
  
  		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_MuzzleFlash_Player[random->RandomInt(0,3)], offset );
  			
  		if ( pParticle == NULL )
  			return;
  
  		pParticle->m_flLifetime		= 0.0f;
  		pParticle->m_flDieTime		= 0.0001f;
  
  		pParticle->m_vecVelocity.Init();
  
  		pParticle->m_uchColor[0]	= 255;
  		pParticle->m_uchColor[1]	= 255;
  		pParticle->m_uchColor[2]	= 200+random->RandomInt(0,55);
  
  		pParticle->m_uchStartAlpha	= 255;
  		pParticle->m_uchEndAlpha	= 255;
  
  		pParticle->m_uchStartSize	= ( (random->RandomFloat( 6.0f, 8.0f ) * (8-(i))/6) * flScale );
  		pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
  		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  		pParticle->m_flRollDelta	= 0.0f;
  	}
  }
  
  //==================================================
  // Purpose: 
  // Input: 
  //==================================================
  
  void CTempEnts::MuzzleFlash_Shotgun_NPC( ClientEntityHandle_t hEntity, int attachmentIndex )
  {
  	//Draw the cloud of fire
  	FX_MuzzleEffectAttached( 0.75f, hEntity, attachmentIndex );
  
  	// If the material isn't available, let's not do anything else.
  	if ( g_Mat_SMG_Muzzleflash[0] == NULL )
  	{
  		return;
  	}
  
  	QAngle	angles;
  
  	Vector	forward;
  	int		i;
  
  	// Setup the origin.
  	Vector	origin;
  	IClientRenderable *pRenderable = ClientEntityList().GetClientRenderableFromHandle( hEntity );
  	if ( !pRenderable )
  		return;
  
  	pRenderable->GetAttachment( attachmentIndex, origin, angles );
  	AngleVectors( angles, &forward );
  
  	//Embers less often
  	if ( random->RandomInt( 0, 2 ) == 0 )
  	{
  		//Embers
  		CSmartPtr<CEmberEffect> pEmbers = CEmberEffect::Create( "muzzle_embers" );
  		pEmbers->SetSortOrigin( origin );
  
  		SimpleParticle	*pParticle;
  
  		int	numEmbers = random->RandomInt( 0, 4 );
  
  		for ( int i = 0; i < numEmbers; i++ )
  		{
  			pParticle = (SimpleParticle *) pEmbers->AddParticle( sizeof( SimpleParticle ), g_Mat_SMG_Muzzleflash[0], origin );
  				
  			if ( pParticle == NULL )
  				return;
  
  			pParticle->m_flLifetime		= 0.0f;
  			pParticle->m_flDieTime		= random->RandomFloat( 0.2f, 0.4f );
  
  			pParticle->m_vecVelocity.Random( -0.05f, 0.05f );
  			pParticle->m_vecVelocity += forward;
  			VectorNormalize( pParticle->m_vecVelocity );
  
  			pParticle->m_vecVelocity	*= random->RandomFloat( 64.0f, 256.0f );
  
  			pParticle->m_uchColor[0]	= 255;
  			pParticle->m_uchColor[1]	= 128;
  			pParticle->m_uchColor[2]	= 64;
  
  			pParticle->m_uchStartAlpha	= 255;
  			pParticle->m_uchEndAlpha	= 0;
  
  			pParticle->m_uchStartSize	= 1;
  			pParticle->m_uchEndSize		= 0;
  
  			pParticle->m_flRoll			= 0;
  			pParticle->m_flRollDelta	= 0;
  		}
  	}
  
  	//
  	// Trails
  	//
  	
  	CSmartPtr<CTrailParticles> pTrails = CTrailParticles::Create( "MuzzleFlash_Shotgun_NPC" );
  	pTrails->SetSortOrigin( origin );
  
  	TrailParticle	*pTrailParticle;
  
  	pTrails->SetFlag( bitsPARTICLE_TRAIL_FADE );
  	pTrails->m_ParticleCollision.SetGravity( 0.0f );
  
  	int	numEmbers = random->RandomInt( 4, 8 );
  
  	for ( i = 0; i < numEmbers; i++ )
  	{
  		pTrailParticle = (TrailParticle *) pTrails->AddParticle( sizeof( TrailParticle ), g_Mat_SMG_Muzzleflash[0], origin );
  			
  		if ( pTrailParticle == NULL )
  			return;
  
  		pTrailParticle->m_flLifetime		= 0.0f;
  		pTrailParticle->m_flDieTime		= random->RandomFloat( 0.1f, 0.2f );
  
  		float spread = 0.05f;
  
  		pTrailParticle->m_vecVelocity.Random( -spread, spread );
  		pTrailParticle->m_vecVelocity += forward;
  		
  		VectorNormalize( pTrailParticle->m_vecVelocity );
  		VectorNormalize( forward );
  
  		float dot = forward.Dot( pTrailParticle->m_vecVelocity );
  
  		dot = (1.0f-fabs(dot)) / spread;
  		pTrailParticle->m_vecVelocity *= (random->RandomFloat( 256.0f, 1024.0f ) * (1.0f-dot));
  
  		Color32Init( pTrailParticle->m_color, 255, 242, 191, 255 );
  
  		pTrailParticle->m_flLength	= 0.05f;
  		pTrailParticle->m_flWidth	= random->RandomFloat( 0.25f, 0.5f );
  	}
  }
  
  //==================================================
  // Purpose: 
  //==================================================
  void CTempEnts::MuzzleFlash_357_Player( ClientEntityHandle_t hEntity, int attachmentIndex )
  {
  	VPROF_BUDGET( "MuzzleFlash_357_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  	CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "MuzzleFlash_357_Player" );
  
  	pSimple->SetDrawBeforeViewModel( true );
  
  	CacheMuzzleFlashes();
  
  	Vector origin;
  	QAngle angles;
  
  	// Get our attachment's transformation matrix
  	FX_GetAttachmentTransform( hEntity, attachmentIndex, &origin, &angles );
  
  	pSimple->GetBinding().SetBBox( origin - Vector( 4, 4, 4 ), origin + Vector( 4, 4, 4 ) );
  
  	Vector forward;
  	AngleVectors( angles, &forward, NULL, NULL );
  
  	SimpleParticle *pParticle;
  	Vector			offset;
  
  	// Smoke
  	offset = origin + forward * 8.0f;
  
  	pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], offset );
  		
  	if ( pParticle == NULL )
  		return;
  
  	pParticle->m_flLifetime		= 0.0f;
  	pParticle->m_flDieTime		= random->RandomFloat( 0.5f, 1.0f );
  
  	pParticle->m_vecVelocity.Init();
  	pParticle->m_vecVelocity = forward * random->RandomFloat( 8.0f, 64.0f );
  	pParticle->m_vecVelocity[2] += random->RandomFloat( 4.0f, 16.0f );
  
  	int color = random->RandomInt( 200, 255 );
  	pParticle->m_uchColor[0]	= color;
  	pParticle->m_uchColor[1]	= color;
  	pParticle->m_uchColor[2]	= color;
  
  	pParticle->m_uchStartAlpha	= random->RandomInt( 64, 128 );
  	pParticle->m_uchEndAlpha	= 0;
  
  	pParticle->m_uchStartSize	= random->RandomInt( 2, 4 );
  	pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 8.0f;
  	pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  	pParticle->m_flRollDelta	= random->RandomFloat( -0.5f, 0.5f );
  
  	float flScale = random->RandomFloat( 1.25f, 1.5f );
  
  	// Flash
  	for ( int i = 1; i < 6; i++ )
  	{
  		offset = origin + (forward * (i*8.0f*flScale));
  
  		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_MuzzleFlash_Player[random->RandomInt(0,3)], offset );
  			
  		if ( pParticle == NULL )
  			return;
  
  		pParticle->m_flLifetime		= 0.0f;
  		pParticle->m_flDieTime		= 0.01f;
  
  		pParticle->m_vecVelocity.Init();
  
  		pParticle->m_uchColor[0]	= 255;
  		pParticle->m_uchColor[1]	= 255;
  		pParticle->m_uchColor[2]	= 200+random->RandomInt(0,55);
  
  		pParticle->m_uchStartAlpha	= 255;
  		pParticle->m_uchEndAlpha	= 255;
  
  		pParticle->m_uchStartSize	= ( (random->RandomFloat( 6.0f, 8.0f ) * (8-(i))/6) * flScale );
  		pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
  		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  		pParticle->m_flRollDelta	= 0.0f;
  	}
  }
  
  //==================================================
  // Purpose: 
  // Input: 
  //==================================================
  
  void CTempEnts::MuzzleFlash_Pistol_Player( ClientEntityHandle_t hEntity, int attachmentIndex )
  {
  	VPROF_BUDGET( "MuzzleFlash_Pistol_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  	CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "MuzzleFlash_Pistol_Player" );
  	pSimple->SetDrawBeforeViewModel( true );
  
  	CacheMuzzleFlashes();
  
  	Vector origin;
  	QAngle angles;
  
  	// Get our attachment's transformation matrix
  	FX_GetAttachmentTransform( hEntity, attachmentIndex, &origin, &angles );
  
  	pSimple->GetBinding().SetBBox( origin - Vector( 4, 4, 4 ), origin + Vector( 4, 4, 4 ) );
  
  	Vector forward;
  	AngleVectors( angles, &forward, NULL, NULL );
  
  	SimpleParticle *pParticle;
  	Vector			offset;
  
  	// Smoke
  	offset = origin + forward * 8.0f;
  
  	if ( random->RandomInt( 0, 3 ) != 0 )
  	{
  		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], offset );
  			
  		if ( pParticle == NULL )
  			return;
  
  		pParticle->m_flLifetime		= 0.0f;
  		pParticle->m_flDieTime		= random->RandomFloat( 0.25f, 0.5f );
  
  		pParticle->m_vecVelocity.Init();
  		pParticle->m_vecVelocity = forward * random->RandomFloat( 48.0f, 64.0f );
  		pParticle->m_vecVelocity[2] += random->RandomFloat( 4.0f, 16.0f );
  
  		int color = random->RandomInt( 200, 255 );
  		pParticle->m_uchColor[0]	= color;
  		pParticle->m_uchColor[1]	= color;
  		pParticle->m_uchColor[2]	= color;
  
  		pParticle->m_uchStartAlpha	= random->RandomInt( 64, 128 );
  		pParticle->m_uchEndAlpha	= 0;
  
  		pParticle->m_uchStartSize	= random->RandomInt( 2, 4 );
  		pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4.0f;
  		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  		pParticle->m_flRollDelta	= random->RandomFloat( -0.1f, 0.1f );
  	}
  
  	float flScale = random->RandomFloat( 1.0f, 1.25f );
  
  	// Flash
  	for ( int i = 1; i < 6; i++ )
  	{
  		offset = origin + (forward * (i*4.0f*flScale));
  
  		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_MuzzleFlash_Player[random->RandomInt(0,3)], offset );
  			
  		if ( pParticle == NULL )
  			return;
  
  		pParticle->m_flLifetime		= 0.0f;
  		pParticle->m_flDieTime		= 0.01f;
  
  		pParticle->m_vecVelocity.Init();
  
  		pParticle->m_uchColor[0]	= 255;
  		pParticle->m_uchColor[1]	= 255;
  		pParticle->m_uchColor[2]	= 200+random->RandomInt(0,55);
  
  		pParticle->m_uchStartAlpha	= 255;
  		pParticle->m_uchEndAlpha	= 255;
  
  		pParticle->m_uchStartSize	= ( (random->RandomFloat( 6.0f, 8.0f ) * (8-(i))/6) * flScale );
  		pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
  		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
  		pParticle->m_flRollDelta	= 0.0f;
  	}
  }
  
  //==================================================
  // Purpose: 
  // Input: 
  //==================================================
  
  void CTempEnts::MuzzleFlash_Pistol_NPC( ClientEntityHandle_t hEntity, int attachmentIndex )
  {
  	FX_MuzzleEffectAttached( 0.5f, hEntity, attachmentIndex, NULL, true );
  }
  
  
  
  
  //==================================================
  // Purpose: 
  // Input: 
  //==================================================
  
  void CTempEnts::MuzzleFlash_RPG_NPC( ClientEntityHandle_t hEntity, int attachmentIndex )
  {
  	//Draw the cloud of fire
  	FX_MuzzleEffectAttached( 1.5f, hEntity, attachmentIndex );
  
  }
  
  
  
  void CTempEnts::RocketFlare( const Vector& pos )
  {
  	C_LocalTempEntity	*pTemp;
  	const model_t		*model;
  	int					nframeCount;
  
  	model = (model_t *)engine->LoadModel( "sprites/animglow01.vmt" );
  	if ( !model )
  	{
  		return;
  	}
  
  	nframeCount = modelinfo->GetModelFrameCount( model );
  
  	pTemp = TempEntAlloc( pos, model );
  	if ( !pTemp )
  		return;
  
  	pTemp->m_flFrameMax = nframeCount - 1;
  	pTemp->SetRenderMode( kRenderGlow );
  	pTemp->m_nRenderFX = kRenderFxNoDissipation;
  	pTemp->tempent_renderamt = 255;
  	pTemp->m_flFrameRate = 1.0;
  	pTemp->m_flFrame = random->RandomInt( 0, nframeCount - 1);
  	pTemp->m_flSpriteScale = 1.0;
  	pTemp->SetAbsOrigin( pos );
  	pTemp->die = gpGlobals->curtime + 0.01;
  }
  
  
  void CTempEnts::HL1EjectBrass( const Vector &vecPosition, const QAngle &angAngles, const Vector &vecVelocity, int nType )
  {
  	const model_t *pModel = NULL;
  
  #if defined( HL1_CLIENT_DLL )
  	switch ( nType )
  	{
  	case 0:
  	default:
  		pModel = m_pHL1Shell;
  		break;
  	case 1:
  		pModel = m_pHL1ShotgunShell;
  		break;
  	}
  #endif
  	if ( pModel == NULL )
  		return;
  
  	C_LocalTempEntity	*pTemp = TempEntAlloc( vecPosition, pModel );
  
  	if ( pTemp == NULL )
  		return;
  
  	switch ( nType )
  	{
  	case 0:
  	default:
  		pTemp->hitSound = BOUNCE_SHELL;
  		break;
  	case 1:
  		pTemp->hitSound = BOUNCE_SHOTSHELL;
  		break;
  	}
  
  	pTemp->m_nBody	= 0;
  	pTemp->flags |= ( FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE );
  
  	pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat( -512,511 );
  	pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat( -256,255 );
  	pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat( -256,255 );
  
  	//Face forward
  	pTemp->SetAbsAngles( angAngles );
  
  	pTemp->SetRenderMode( kRenderNormal );
  	pTemp->tempent_renderamt	= 255;		// Set this for fadeout
  
  	pTemp->SetVelocity( vecVelocity );
  
  	pTemp->die = gpGlobals->curtime + 2.5;
  }
  
  #define SHELLTYPE_PISTOL	0
  #define SHELLTYPE_RIFLE		1
  #define SHELLTYPE_SHOTGUN	2
  
  
  void CTempEnts::CSEjectBrass( const Vector &vecPosition, const QAngle &angVelocity, int nVelocity, int shellType, CBasePlayer *pShooter )
  {
  	if (cl_ejectbrass.GetBool() == false)
  		return;
  
  	const model_t *pModel = NULL;
  	int hitsound = TE_BOUNCE_SHELL;
  
  	switch( shellType )
  	{
  	default:
  	case CS_SHELL_9MM:
  		hitsound = TE_PISTOL_SHELL;
  		pModel = m_pCS_9MMShell;
  		break;
  	case CS_SHELL_57:
  		hitsound = TE_PISTOL_SHELL;
  		pModel = m_pCS_57Shell;
  		break;
  	case CS_SHELL_12GAUGE:
  		hitsound = TE_SHOTGUN_SHELL;
  		pModel = m_pCS_12GaugeShell;
  		break;
  	case CS_SHELL_556:
  		hitsound = TE_RIFLE_SHELL;
  		pModel = m_pCS_556Shell;
  		break;
  	case CS_SHELL_762NATO:
  		hitsound = TE_RIFLE_SHELL;
  		pModel = m_pCS_762NATOShell;
  		break;
  	case CS_SHELL_338MAG:
  		hitsound = TE_RIFLE_SHELL;
  		pModel = m_pCS_338MAGShell;
  		break;
  	}
  
  	if ( pModel == NULL )
  		return;
  
  	Vector forward, right, up;
  	Vector velocity;
  	Vector origin;
  	QAngle angle;
  	
  	// Add some randomness to the velocity
  
  	AngleVectors( angVelocity, &forward, &right, &up );
  	
  	velocity = forward * nVelocity * random->RandomFloat( 1.2, 2.8 ) +
  			   up * random->RandomFloat( -10, 10 ) +
  			   right * random->RandomFloat( -20, 20 );
  
  	if( pShooter )
  		velocity += pShooter->GetAbsVelocity();
  
  	C_LocalTempEntity *pTemp = TempEntAlloc( vecPosition, pModel );
  	if ( !pTemp )
  		return;
  
  	if( pShooter )
  		pTemp->SetAbsAngles( pShooter->EyeAngles() );
  	else
  		pTemp->SetAbsAngles( vec3_angle );
  
  	pTemp->SetVelocity( velocity );
  
  	pTemp->hitSound = hitsound;
  
  	pTemp->SetGravity( 0.4 );
  
  	pTemp->m_nBody	= 0;
  	pTemp->flags = FTENT_FADEOUT | FTENT_GRAVITY | FTENT_COLLIDEALL | FTENT_HITSOUND | FTENT_ROTATE | FTENT_CHANGERENDERONCOLLIDE;
  
  	pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-256,256);
  	pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-256,256);
  	pTemp->m_vecTempEntAngVelocity[2] = 0;
  	pTemp->SetRenderMode( kRenderNormal );
  	pTemp->tempent_renderamt = 255;
  	
  	pTemp->die = gpGlobals->curtime + 10;
  
  	bool bViewModelBrass = false;
  
  	if ( pShooter && pShooter->GetObserverMode() == OBS_MODE_IN_EYE )
  	{
  		// we are spectating the shooter in first person view
  		pShooter = ToBasePlayer( pShooter->GetObserverTarget() );
  		bViewModelBrass = true;
  	}
  
  	if ( pShooter )
  	{
  		pTemp->clientIndex = pShooter->entindex();
  		bViewModelBrass |= pShooter->IsLocalPlayer();
  	}
  	else
  	{
  		pTemp->clientIndex = 0;
  	}
  
  	if ( bViewModelBrass )
  	{
  		// for viewmodel brass put it in the viewmodel renderer group
  		pTemp->m_RenderGroup = RENDER_GROUP_VIEW_MODEL_OPAQUE;
  	}
  
  	
  }
  
  