//-----------------------------------------------------------------------------
// Purpose: Trail smoke
//-----------------------------------------------------------------------------
void CASW_Shotgun_Pellet_Predicted::ClientThink( void )
{
return;

	CSmartPtr<CSimpleEmitter> pEmitter = CSimpleEmitter::Create( "CASW_Shotgun_Pellet_Predicted::Effect" );
	PMaterialHandle	hSphereMaterial = pEmitter->GetPMaterial( "sprites/chargeball" );

	// Add particles at the target.
	float flCur = gpGlobals->frametime;
	while ( m_ParticleEvent.NextEvent( flCur ) )
	{
		Vector vecOrigin = GetAbsOrigin() + RandomVector( -2,2 );
		pEmitter->SetSortOrigin( vecOrigin );

		SimpleParticle *pParticle = (SimpleParticle *) pEmitter->AddParticle( sizeof(SimpleParticle), hSphereMaterial, vecOrigin );
		if ( pParticle == NULL )
			return;

		pParticle->m_flLifetime	= 0.0f;
		pParticle->m_flDieTime	= random->RandomFloat( 0.1f, 0.3f );

		pParticle->m_uchStartSize	= random->RandomFloat(2,4);
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize + 2;

		pParticle->m_vecVelocity = vec3_origin;
		pParticle->m_uchStartAlpha = 128;
		pParticle->m_uchEndAlpha = 0;
		pParticle->m_flRoll	= random->RandomFloat( 180, 360 );
		pParticle->m_flRollDelta = random->RandomFloat( -1, 1 );

		pParticle->m_uchColor[0] = 128;
		pParticle->m_uchColor[1] = 128;
		pParticle->m_uchColor[2] = 128;
	}
}
Beispiel #2
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &origin - 
//			&velocity - 
//			scale - 
//			numParticles - 
//			*pColor - 
//			iAlpha - 
//			*pMaterial - 
//			flRoll - 
//			flRollDelta - 
//-----------------------------------------------------------------------------
CSmartPtr<CSimpleEmitter> FX_Smoke( const Vector &origin, const Vector &velocity, float scale, int numParticles, float flDietime, unsigned char *pColor, int iAlpha, const char *pMaterial, float flRoll, float flRollDelta )
{
	VPROF_BUDGET( "FX_Smoke", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_Smoke" );
	pSimple->SetSortOrigin( origin );

	SimpleParticle *pParticle;

	// Smoke
	for ( int i = 0; i < numParticles; i++ )
	{
		PMaterialHandle hMaterial = pSimple->GetPMaterial( pMaterial );
		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial, origin );			
		if ( pParticle == NULL )
			return NULL;

		pParticle->m_flLifetime = 0.0f;
		pParticle->m_flDieTime = flDietime;
		pParticle->m_vecVelocity = velocity;
		for( int i = 0; i < 3; ++i )
		{
			pParticle->m_uchColor[i] = pColor[i];
		}
		pParticle->m_uchStartAlpha	= iAlpha;
		pParticle->m_uchEndAlpha	= 0;
		pParticle->m_uchStartSize	= scale;
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize*2;
		pParticle->m_flRoll	= flRoll;
		pParticle->m_flRollDelta = flRollDelta;
	}

	return pSimple;
}
//-----------------------------------------------------------------------------
// Purpose: Spawn effects if I'm sapping
//-----------------------------------------------------------------------------
void C_GrenadeAntiPersonnel::ClientThink( void )
{
	// Fire smoke puffs out the side
	CSmartPtr<CSimpleEmitter> pSmokeEmitter = CSimpleEmitter::Create( "AntipersonnelGrenade::Effect" );
	pSmokeEmitter->SetSortOrigin( GetAbsOrigin() );
	int iSmokeClouds = random->RandomInt(1,2);
	for ( int i = 0; i < iSmokeClouds; i++ )
	{
		SimpleParticle *pParticle = (SimpleParticle *) pSmokeEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[1], GetAbsOrigin() );
		if ( pParticle == NULL )
			return;

		pParticle->m_flLifetime	= 0.0f;
		pParticle->m_flDieTime	= random->RandomFloat( 0.1f, 0.3f );

		pParticle->m_uchStartSize	= random->RandomFloat(2,5);
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize + 2;

		pParticle->m_vecVelocity = vec3_origin;
		pParticle->m_uchStartAlpha = 255;
		pParticle->m_uchEndAlpha = 64;
		pParticle->m_flRoll	= random->RandomFloat( 180, 360 );
		pParticle->m_flRollDelta = random->RandomFloat( -1, 1 );

		pParticle->m_uchColor[0] = 50;
		pParticle->m_uchColor[1] = 250;
		pParticle->m_uchColor[2] = 50;
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &origin - 
//			&normal - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
void FX_CreateImpactDust( Vector &origin, Vector &normal )
{
	VPROF_BUDGET( "FX_CreateImpactDust", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	Vector	offset		= origin + ( normal * 4.0f );;

	float	totalScale	= random->RandomFloat( 0.5f, 1.25f );
	float	scale		= random->RandomFloat( 3.0f, 4.0f ) * totalScale;

	CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_CreateImpactDust" );

	pSimple->SetSortOrigin( origin );
	
	SimpleParticle *pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof(SimpleParticle), pSimple->GetPMaterial( "particle/particle_sphere" ), offset );
	
	if (pParticle)
	{
		pParticle->m_flLifetime	= 0.0f;
		pParticle->m_flDieTime	= 0.1f;
		
		pParticle->m_uchColor[0] = pParticle->m_uchColor[1] = pParticle->m_uchColor[2] = 255;
		
		pParticle->m_uchStartAlpha	= random->RandomInt( 32, 64 );;
		pParticle->m_uchEndAlpha	= 0;

		pParticle->m_uchStartSize	= scale;
		pParticle->m_uchEndSize		= scale*4.0f;
	}
}
void C_EnvPortalPathTrack::UpdateParticles_Active ( void )
{
	// Emitters must be valid
	if ( SetupEmitters() == false )
		return;

	// Reset our sort origin
	m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() );

	SimpleParticle *sParticle;

	// Do the charging particles
	m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() );

	Vector forward, right, up;
	AngleVectors( GetAbsAngles(), &forward, &right, &up );

	Vector	offset;
	float	dist;

	int numParticles = floor( 4.0f );

	for ( int i = 0; i < numParticles; i++ )
	{
		dist = random->RandomFloat( 4.0f, 64.0f );

		offset = forward * dist;

		dist = RemapValClamped( dist, 4.0f, 64.0f, 6.0f, 1.0f );
		offset += right * random->RandomFloat( -4.0f * dist, 4.0f * dist );
		offset += up * random->RandomFloat( -4.0f * dist, 4.0f * dist );

		offset += GetAbsOrigin();

		sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( "effects/strider_muzzle" ), offset );

		if ( sParticle == NULL )
			return;
		
		sParticle->m_vecVelocity	= Vector(0,0,8);
		sParticle->m_flDieTime		= 0.5f;
		sParticle->m_flLifetime		= 0.0f;

		sParticle->m_flRoll			= Helper_RandomInt( 0, 360 );
		sParticle->m_flRollDelta	= 0.0f;

		float alpha = 255;

		sParticle->m_uchColor[0]	= alpha;
		sParticle->m_uchColor[1]	= alpha;
		sParticle->m_uchColor[2]	= alpha;
		sParticle->m_uchStartAlpha	= alpha;
		sParticle->m_uchEndAlpha	= 0;

		sParticle->m_uchStartSize	= random->RandomFloat( 1, 2 );
		sParticle->m_uchEndSize		= 0;
	}
}
Beispiel #6
0
void FX_MetalScrape(Vector &position, Vector &normal)
{
    VPROF_BUDGET("FX_MetalScrape", VPROF_BUDGETGROUP_PARTICLE_RENDERING);
    Vector	offset = position + (normal * 1.0f);

    CSmartPtr<CTrailParticles> sparkEmitter = CTrailParticles::Create("FX_MetalScrape 1");

    if (!sparkEmitter)
        return;

    sparkEmitter->SetSortOrigin(offset);

    //Setup our collision information
    sparkEmitter->Setup(offset,
        &normal,
        METAL_SCRAPE_SPREAD,
        METAL_SCRAPE_MINSPEED,
        METAL_SCRAPE_MAXSPEED,
        METAL_SCRAPE_GRAVITY,
        METAL_SCRAPE_DAMPEN,
        bitsPARTICLE_TRAIL_VELOCITY_DAMPEN);

    int	numSparks = random->RandomInt(4, 8);

    if (g_Material_Spark == NULL)
    {
        g_Material_Spark = sparkEmitter->GetPMaterial("effects/spark");
    }

    Vector	dir;
    TrailParticle *pParticle;
    float	length = 0.06f;

    //Dump out sparks
    for (int i = 0; i < numSparks; i++)
    {
        pParticle = (TrailParticle *) sparkEmitter->AddParticle(sizeof(TrailParticle), g_Material_Spark, offset);

        if (pParticle == NULL)
            return;

        pParticle->m_flLifetime = 0.0f;

        float	spreadOfs = random->RandomFloat(0.0f, 2.0f);

        dir[0] = normal[0] + random->RandomFloat(-(METAL_SCRAPE_SPREAD*spreadOfs), (METAL_SCRAPE_SPREAD*spreadOfs));
        dir[1] = normal[1] + random->RandomFloat(-(METAL_SCRAPE_SPREAD*spreadOfs), (METAL_SCRAPE_SPREAD*spreadOfs));
        dir[2] = normal[2] + random->RandomFloat(-(METAL_SCRAPE_SPREAD*spreadOfs), (METAL_SCRAPE_SPREAD*spreadOfs));

        pParticle->m_flWidth = random->RandomFloat(2.0f, 5.0f);
        pParticle->m_flLength = random->RandomFloat(length*0.25f, length);
        pParticle->m_flDieTime = random->RandomFloat(2.0f, 2.0f);

        pParticle->m_vecVelocity = dir * random->RandomFloat((METAL_SCRAPE_MINSPEED*(2.0f - spreadOfs)), (METAL_SCRAPE_MAXSPEED*(2.0f - spreadOfs)));

        Color32Init(pParticle->m_color, 255, 255, 255, 255);
    }
}
Beispiel #7
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void HunterDamageCallback( const CEffectData &data )
{
	CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "HunterDamage" );
	if ( pGlassEmitter == NULL )
		return;

	pGlassEmitter->SetSortOrigin( data.m_vOrigin );

	// Handle increased scale
	const float flMaxSpeed = 400.0f;
	const float flMinSpeed = 50.0f;
	float flAngularSpray = 1.0f;

	// Setup our collision information
	pGlassEmitter->m_ParticleCollision.Setup( data.m_vOrigin, &data.m_vNormal, flAngularSpray, flMinSpeed, flMaxSpeed, 600.0f, 0.2f );

	Vector	dir, end;

	int	numFlecks = 32;

	Particle3D *pFleckParticle;
	Vector spawnOffset;

	//Dump out flecks
	for ( int i = 0; i < numFlecks; i++ )
	{
		spawnOffset = data.m_vOrigin + RandomVector( -32.0f, 32.0f );
		pFleckParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Antlion[random->RandomInt(0,1)], spawnOffset );

		if ( pFleckParticle == NULL )
			break;

		pFleckParticle->m_flLifeRemaining	= random->RandomFloat( 2.0f, 3.0f );

		dir[0] = data.m_vNormal[0] + random->RandomFloat( -flAngularSpray, flAngularSpray );
		dir[1] = data.m_vNormal[1] + random->RandomFloat( -flAngularSpray, flAngularSpray );
		dir[2] = data.m_vNormal[2] + random->RandomFloat( -flAngularSpray, flAngularSpray );

		pFleckParticle->m_uchSize		= random->RandomInt( 3, 8 );

		pFleckParticle->m_vecVelocity	= dir * random->RandomFloat( flMinSpeed, flMaxSpeed);

		pFleckParticle->m_vAngles		= RandomAngle( 0, 360 );
		pFleckParticle->m_flAngSpeed	= random->RandomFloat( -800, 800 );

		unsigned char color = 255;
		pFleckParticle->m_uchFrontColor[0]	= color;
		pFleckParticle->m_uchFrontColor[1]	= color;
		pFleckParticle->m_uchFrontColor[2]	= color;
		pFleckParticle->m_uchBackColor[0]	= color * 0.25f;
		pFleckParticle->m_uchBackColor[1]	= color * 0.25f;
		pFleckParticle->m_uchBackColor[2]	= color * 0.25f;
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_EntityFlame::Simulate( void )
{
	if (m_bAttachedToHitboxes)
	{
		UpdateHitBoxFlames();
	}
	else
	{
		m_pEmitter->SetSortOrigin( GetAbsOrigin() );

		float tempDelta = gpGlobals->frametime;
		
		SimpleParticle *pParticle;

		Vector	offset;

		while( m_ParticleSpawn.NextEvent( tempDelta ) )
		{
			offset.Random( -m_flSize, m_flSize );

			pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle[random->RandomInt( 0, NUM_FLAMELETS-1 )], GetAbsOrigin() + offset );

			if ( pParticle )
			{
				pParticle->m_flDieTime	= 0.4f;
				pParticle->m_flLifetime	= 0.0f;
				
				pParticle->m_flRoll		= random->RandomInt( 0, 360 );
				pParticle->m_flRollDelta= random->RandomFloat( -2.0f, 2.0f );
				
				pParticle->m_uchStartSize	= random->RandomInt( 4, 6 );
				pParticle->m_uchEndSize		= random->RandomInt( 12, 16 );
				pParticle->m_uchStartAlpha	= 255;
				pParticle->m_uchEndAlpha	= 0;
				
				int	cScale = 255;//random->RandomInt( 192, 255 );
				pParticle->m_uchColor[0]	= cScale;
				pParticle->m_uchColor[1]	= cScale;
				pParticle->m_uchColor[2]	= cScale;
				
				Vector dir;

				dir.x = random->RandomFloat( -1.0f, 1.0f );
				dir.y = random->RandomFloat( -1.0f, 1.0f );
				dir.z = random->RandomFloat( 0.5f, 1.0f );

				pParticle->m_vecVelocity	= dir * random->RandomInt( 4, 32 );
				pParticle->m_vecVelocity[2] = random->RandomInt( 32, 64 );
			}
		}
	}
}
Beispiel #9
0
//-----------------------------------------------------------------------------
// Chopper muzzle flashes
//-----------------------------------------------------------------------------
void MuzzleFlash_Chopper( ClientEntityHandle_t hEntity, int attachmentIndex )
{
	VPROF_BUDGET( "MuzzleFlash_Chopper", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	matrix3x4_t	matAttachment;
	// If the client hasn't seen this entity yet, bail.
	if ( !FX_GetAttachmentTransform( hEntity, attachmentIndex, matAttachment ) )
		return;
	
	CSmartPtr<CLocalSpaceEmitter> pSimple = CLocalSpaceEmitter::Create( "MuzzleFlash", hEntity, attachmentIndex );

	SimpleParticle *pParticle;
	Vector			forward(1,0,0), offset; //NOTENOTE: All coords are in local space

	float flScale = random->RandomFloat( 2.5f, 4.5f );

	// Flash
	for ( int i = 1; i < 7; i++ )
	{
		offset = (forward * (i*2.0f*flScale));

		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( VarArgs( "effects/combinemuzzle%d", random->RandomInt(1,2) ) ), offset );
			
		if ( pParticle == NULL )
			return;

		pParticle->m_flLifetime		= 0.0f;
		pParticle->m_flDieTime		= random->RandomFloat( 0.05f, 0.1f );

		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	= 128;

		pParticle->m_uchStartSize	= ( (random->RandomFloat( 6.0f, 8.0f ) * (10-(i))/7) * flScale );
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
		pParticle->m_flRollDelta	= 0.0f;
	}
	
	// Grab the origin out of the transform for the attachment
	Vector		origin;
	MatrixGetColumn( matAttachment, 3, &origin );	
	CreateMuzzleflashELight( origin, 6, 128, 256, hEntity );
}
//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void C_PlasmaBeamNode::ClientThink(void)
{
	if (!m_bSprayOn)
	{
		return;
	}
	
	trace_t trace;
	Vector vEndTrace = GetAbsOrigin() + (0.3*GetAbsVelocity());
	UTIL_TraceLine( GetAbsOrigin(), vEndTrace, MASK_SHOT, NULL, COLLISION_GROUP_NONE, &trace );
	if ( trace.fraction != 1.0f || trace.startsolid)
	{
		m_bSprayOn = false;
		return;
	}

	PMaterialHandle handle = m_pFirePlasmaSpray->GetPMaterial( "sprites/plasmaember" );
	for (int i=0;i<SPRAYS_PER_THINK;i++)
	{
		SimpleParticle	*sParticle;

		//Make a new particle
		if ( random->RandomInt( 0, 2 ) == 0 )
		{
			float ranx = random->RandomFloat( -28.0f, 28.0f );
			float rany = random->RandomFloat( -28.0f, 28.0f );
			float ranz = random->RandomFloat( -28.0f, 28.0f );

			Vector vNewPos	=  GetAbsOrigin();
			Vector vAdd		=  Vector(GetAbsAngles().x,GetAbsAngles().y,GetAbsAngles().z)*random->RandomFloat(-60,120);
			vNewPos			+= vAdd;

			sParticle = (SimpleParticle *) m_pFirePlasmaSpray->AddParticle( sizeof(SimpleParticle), handle, vNewPos );
			
			sParticle->m_flLifetime		= 0.0f;
			sParticle->m_flDieTime		= PLASMASPARK_LIFETIME;

			sParticle->m_vecVelocity	= GetAbsVelocity();
			sParticle->m_vecVelocity.x	+= ranx;
			sParticle->m_vecVelocity.y	+= rany;
			sParticle->m_vecVelocity.z	+= ranz;
			m_pFirePlasmaSpray->m_pOwner	=  this;
		}
	}

	SetNextClientThink(gpGlobals->curtime + 0.05);
}
Beispiel #11
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &data - 
//-----------------------------------------------------------------------------
void WheelDustCallback( const CEffectData &data )
{
	CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" );
	pSimple->SetSortOrigin( data.m_vOrigin );
	pSimple->SetNearClip( 32, 64 );

	SimpleParticle	*pParticle;

	Vector	offset;

	//FIXME: Better sampling area
	offset = data.m_vOrigin + ( data.m_vNormal * data.m_flScale );
	
	//Find area ambient light color and use it to tint smoke
	Vector	worldLight = WorldGetLightForPoint( offset, true );

	//Throw puffs
	offset.Random( -(data.m_flScale*16.0f), data.m_flScale*16.0f );
	offset.z = 0.0f;
	offset += data.m_vOrigin + ( data.m_vNormal * data.m_flScale );

	pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[0], offset );

	if ( pParticle != NULL )
	{			
		pParticle->m_flLifetime		= 0.0f;
		pParticle->m_flDieTime		= random->RandomFloat( 0.25f, 0.5f );
		
		pParticle->m_vecVelocity = RandomVector( -1.0f, 1.0f );
		VectorNormalize( pParticle->m_vecVelocity );
		pParticle->m_vecVelocity[2] += random->RandomFloat( 16.0f, 32.0f ) * (data.m_flScale*2.0f);

		int	color = random->RandomInt( 100, 150 );

		pParticle->m_uchColor[0] = 16 + ( worldLight[0] * (float) color );
		pParticle->m_uchColor[1] = 8 + ( worldLight[1] * (float) color );
		pParticle->m_uchColor[2] = ( worldLight[2] * (float) color );

		pParticle->m_uchStartAlpha	= random->RandomInt( 64.0f*data.m_flScale, 128.0f*data.m_flScale );
		pParticle->m_uchEndAlpha	= 0;
		pParticle->m_uchStartSize	= random->RandomInt( 16, 24 ) * data.m_flScale;
		pParticle->m_uchEndSize		= random->RandomInt( 32, 48 ) * data.m_flScale;
		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
		pParticle->m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : flPerc - 
//-----------------------------------------------------------------------------
void C_MortarShell::AddRisingParticles( float flPerc )
{
	SimpleParticle *sParticle;

	Vector offset;
	float radius = m_flRadius * 0.25f * flPerc;

	float val = RemapValClamped( gpGlobals->curtime, m_flStarttime, m_flStarttime + m_flLifespan, 0.0f, 1.0f );

	float flCur = gpGlobals->frametime;

	// Anime ground effects
	while ( m_ParticleEvent.NextEvent( flCur ) )
	{
		offset.x = random->RandomFloat( -radius, radius );
		offset.y = random->RandomFloat( -radius, radius );
		offset.z = random->RandomFloat( -8.0f, 8.0f );

		offset += GetAbsOrigin();

		sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/spark" ), offset );
		
		if ( sParticle == NULL )
			return;

		sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( 32.0f, 256.0f ) * Bias( val, 0.25f ) );
		
		sParticle->m_uchStartSize	= random->RandomFloat( 4, 8 ) * flPerc;

		sParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f );
		
		sParticle->m_flLifetime		= 0.0f;

		sParticle->m_flRoll			= Helper_RandomInt( 0, 360 );

		float alpha = 255 * flPerc;

		sParticle->m_flRollDelta	= Helper_RandomFloat( -8.0f * flPerc, 8.0f * flPerc );
		sParticle->m_uchColor[0]	= alpha;
		sParticle->m_uchColor[1]	= alpha;
		sParticle->m_uchColor[2]	= alpha;
		sParticle->m_uchStartAlpha	= alpha;
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchEndSize		= 0;
	}
}
Beispiel #13
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_EnvStarfield::ClientThink( void )
{
	if ( !m_bOn || !m_flDensity ) 
		return;

	PMaterialHandle	hParticleMaterial = m_pEmitter->GetPMaterial( "effects/spark_noz" );

	// Find a start & end point for the particle
	// Start particles straight ahead of the client
	Vector vecViewOrigin = MainViewOrigin(engine->GetActiveSplitScreenPlayerSlot());

	// Determine the number of particles
	m_flNumParticles += 1.0 * (m_flDensity);
	int iNumParticles = floor(m_flNumParticles);
	m_flNumParticles -= iNumParticles;

	// Add particles
	for ( int i = 0; i < iNumParticles; i++ )
	{
		float flDiameter = cl_starfield_diameter.GetFloat();

		Vector vecStart = vecViewOrigin + (MainViewForward(engine->GetActiveSplitScreenPlayerSlot()) * cl_starfield_distance.GetFloat() );
		Vector vecEnd = vecViewOrigin + (MainViewRight(engine->GetActiveSplitScreenPlayerSlot()) * RandomFloat(-flDiameter,flDiameter)) + (MainViewUp(engine->GetActiveSplitScreenPlayerSlot()) * RandomFloat(-flDiameter,flDiameter));
		Vector vecDir = (vecEnd - vecStart);
		float flDistance = VectorNormalize( vecDir );
		float flTravelTime = 2.0;
		
		// Start a random amount along the path
		vecStart += vecDir * ( RandomFloat(0.1,0.3) * flDistance );

		TrailParticle *pParticle = (TrailParticle *) m_pEmitter->AddParticle( sizeof(TrailParticle), hParticleMaterial, vecStart );
		if ( pParticle )
		{
			pParticle->m_vecVelocity = vecDir * (flDistance / flTravelTime);
			pParticle->m_flDieTime = flTravelTime;
			pParticle->m_flLifetime = 0;
			pParticle->m_flWidth = RandomFloat( 1, 3 );
			pParticle->m_flLength = RandomFloat( 0.05, 0.4 );
			pParticle->m_color.r	= 255;
			pParticle->m_color.g	= 255;
			pParticle->m_color.b	= 255;
			pParticle->m_color.a	= 255;
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : flPerc - 
//-----------------------------------------------------------------------------
void C_MortarShell::AddExplodingParticles( float flPerc )
{
	SimpleParticle *sParticle;

	Vector offset;
	float radius = 48.0f * flPerc;

	float flCur = gpGlobals->frametime;

	// Anime ground effects
	while ( m_ParticleEvent.NextEvent( flCur ) )
	{
		offset.x = random->RandomFloat( -radius, radius );
		offset.y = random->RandomFloat( -radius, radius );
		offset.z = random->RandomFloat( -8.0f, 8.0f );

		offset += GetAbsOrigin();

		sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/spark" ), offset );
		
		if ( sParticle == NULL )
			return;

		sParticle->m_vecVelocity = RandomVector( -1.0f, 1.0f ) + Vector( 0, 0, 1 );
		sParticle->m_vecVelocity *= ( 750.0f * flPerc );
		
		sParticle->m_uchStartSize	= random->RandomFloat( 2, 4 ) * flPerc;

		sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
		
		sParticle->m_flLifetime		= 0.0f;

		sParticle->m_flRoll			= Helper_RandomInt( 0, 360 );

		float alpha = 255 * flPerc;

		sParticle->m_flRollDelta	= Helper_RandomFloat( -8.0f * flPerc, 8.0f * flPerc );
		sParticle->m_uchColor[0]	= alpha;
		sParticle->m_uchColor[1]	= alpha;
		sParticle->m_uchColor[2]	= alpha;
		sParticle->m_uchStartAlpha	= alpha;
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchEndSize		= 0;
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : bool - 
//-----------------------------------------------------------------------------
void C_TEShowLine::PostDataUpdate( DataUpdateType_t updateType )
{
	Vector		vec;
	float		len;
	StandardParticle_t	*p;
	int			dec;
	static int	tracercount;

	VectorSubtract (m_vecEnd, m_vecOrigin, vec);
	len = VectorNormalize (vec);

	dec = 3;

	VectorScale(vec, dec, vec);

	CSmartPtr<CTEParticleRenderer> pRen = CTEParticleRenderer::Create( "TEShowLine", m_vecOrigin );
	if( !pRen )
		return;
	
	while (len > 0)
	{
		len -= dec;

		p = pRen->AddParticle();
		if ( p )
		{
			p->m_Velocity.Init();

			pRen->SetParticleLifetime(p, 30);
			
			p->SetColor(0, 1, 1);
			p->SetAlpha(1);
			pRen->SetParticleType(p, pt_static);

			p->m_Pos = m_vecOrigin;
			
			m_vecOrigin += vec;
		}
	}
}
Beispiel #16
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void FX_GunshipMuzzleEffect( const Vector &origin, const QAngle &angles, float scale, ClientEntityHandle_t hEntity, unsigned char *pFlashColor )
{
	VPROF_BUDGET( "FX_GunshipMuzzleEffect", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "MuzzleFlash" );
	pSimple->SetSortOrigin( origin );
	
	SimpleParticle *pParticle;
	Vector			forward, offset;

	AngleVectors( angles, &forward );

	//
	// Flash
	//
	offset = origin;

	pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/gunshipmuzzle" ), offset );
		
	if ( pParticle == NULL )
		return;

	pParticle->m_flLifetime		= 0.0f;
	pParticle->m_flDieTime		= 0.15f;

	pParticle->m_vecVelocity.Init();

	pParticle->m_uchStartSize	= random->RandomFloat( 40.0, 50.0 );
	pParticle->m_uchEndSize		= pParticle->m_uchStartSize;

	pParticle->m_flRoll			= random->RandomInt( 0, 360 );
	pParticle->m_flRollDelta	= 0.15f;

	pParticle->m_uchColor[0]	= 255;
	pParticle->m_uchColor[1]	= 255;
	pParticle->m_uchColor[2]	= 255;

	pParticle->m_uchStartAlpha	= 255;
	pParticle->m_uchEndAlpha	= 255;
}
//-----------------------------------------------------------------------------
// Purpose: Warp effect that looks like it's sucking things to it
//-----------------------------------------------------------------------------
void FX_BuildWarpSuck( Vector &vecOrigin, QAngle &vecAngles, float flScale )
{
	CSmartPtr<CTrailParticles> pEmitter = CTrailParticles::Create( "BuildWarpSuck" );
	PMaterialHandle	hParticleMaterial = pEmitter->GetPMaterial( "effects/bluespark" );
	pEmitter->Setup( (Vector &) vecOrigin, 
						NULL, 
						0.0, 
						0, 
						64, 
						0, 
						0, 
						bitsPARTICLE_TRAIL_VELOCITY_DAMPEN | bitsPARTICLE_TRAIL_FADE );

	// Add particles
	int iNumParticles = 60;
	for ( int i = 0; i < iNumParticles; i++ )
	{
		Vector vOffset = RandomVector( -1, 1 );
		VectorNormalize( vOffset );
		float flDistance = RandomFloat( 16, 64 ) * flScale;
		Vector vPos = vecOrigin + (vOffset * flDistance);
		
		TrailParticle *pParticle = (TrailParticle *) pEmitter->AddParticle( sizeof(TrailParticle), hParticleMaterial, vPos );
		if ( pParticle )
		{
			float flSpeed = RandomFloat(8,16) * (flScale * flScale * flScale);
			pParticle->m_vecVelocity = vOffset * -flSpeed;
			pParticle->m_flDieTime = min( 3, (flDistance / flSpeed) + RandomFloat(0.0, 0.2) );
			pParticle->m_flLifetime = 0;
			pParticle->m_flWidth = RandomFloat( 2, 3 ) * flScale;
			pParticle->m_flLength = RandomFloat( 1, 2 ) * flScale;
			pParticle->m_color.r	= 1.0f;
			pParticle->m_color.g	= 1.0f;
			pParticle->m_color.b	= 1.0f;
			pParticle->m_color.a	= 1.0f;
		}
	}
}
Beispiel #18
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_RotorWashEmitter::ClientThink( void )
{
	SetNextClientThink( gpGlobals->curtime + ROTORWASH_THINK_INTERVAL );

	trace_t	tr;
	UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin()+(Vector(0, 0, -1024)), (MASK_SOLID_BRUSHONLY|CONTENTS_WATER|CONTENTS_SLIME), NULL, COLLISION_GROUP_NONE, &tr );

	if ( /*!m_bIgnoreSolid && */(tr.fraction == 1.0f || tr.startsolid || tr.allsolid) )
		return;

	// If we hit the skybox, don't do it either
	if ( tr.surface.flags & SURF_SKY )
		return;

	float heightScale = RemapValClamped( tr.fraction * 1024, 512, 1024, 1.0f, 0.0f );

	Vector vecDustColor;

	if ( tr.contents & CONTENTS_WATER )
	{
		vecDustColor.x = 0.8f;
		vecDustColor.y = 0.8f;
		vecDustColor.z = 0.75f;
	}
	else if ( tr.contents & CONTENTS_SLIME )
	{
		vecDustColor.x = 0.6f;
		vecDustColor.y = 0.5f;
		vecDustColor.z = 0.15f;
	}
	else
	{
		vecDustColor.x = 0.35f;
		vecDustColor.y = 0.3f;
		vecDustColor.z = 0.25f;
	}

#ifndef _XBOX

	InitSpawner();

	if ( m_pSimple.IsValid() == false )
		return;

	m_pSimple->SetSortOrigin( GetAbsOrigin() );

	PMaterialHandle	*hMaterial;
	
	// Cache and set our material based on the surface we're over (ie. water)
	if ( tr.contents & (CONTENTS_WATER|CONTENTS_SLIME) )
	{
		if ( m_hWaterMaterial[0] == NULL )
		{
			m_hWaterMaterial[0] = m_pSimple->GetPMaterial("effects/splash1");
			m_hWaterMaterial[1] = m_pSimple->GetPMaterial("effects/splash2");
		}
		hMaterial = m_hWaterMaterial;
	}
	else
	{
		hMaterial = g_Mat_DustPuff;
	}

#endif // !XBOX

	// If we're above water, make ripples
	if ( tr.contents & (CONTENTS_WATER|CONTENTS_SLIME) )
	{
		float flScale = random->RandomFloat( 7.5f, 8.5f );

		Vector	color = Vector( 0.8f, 0.8f, 0.75f );
		Vector startPos = tr.endpos + Vector(0,0,8);
		Vector endPos = tr.endpos + Vector(0,0,-64);

		if ( tr.fraction < 1.0f )
		{
			//Add a ripple quad to the surface
			FX_AddQuad( tr.endpos + ( tr.plane.normal * 0.5f ), 
						tr.plane.normal, 
						64.0f * flScale, 
						128.0f * flScale, 
						0.8f,
						0.75f * heightScale, 
						0.0f,
						0.75f,
						random->RandomFloat( 0, 360 ),
						random->RandomFloat( -2.0f, 2.0f ),
						vecDustColor, 
						0.2f,  
						"effects/splashwake3",
						(FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) );
		}
	}

#ifndef _XBOX
	int		numRingSprites = 32;
	float	yaw = random->RandomFloat( 0, 2*M_PI ); // Randomly placed on the unit circle
	float	yawIncr = (2*M_PI) / numRingSprites;
	Vector	vecForward;
	Vector	offset;
	SimpleParticle	*pParticle;

	// Draw the rings
	for ( int i = 0; i < numRingSprites; i++ )
	{
		// Get our x,y on the unit circle
		SinCos( yaw, &vecForward.y, &vecForward.x );
		
		// Increment ahead
		yaw += yawIncr;

		// @NOTE toml (3-28-07): broke out following expression because vc2005 optimizer was screwing up in presence of SinCos inline assembly. Would also
		// go away if offset were referenced below as in the AddLineOverlay()
		//offset = ( RandomVector( -4.0f, 4.0f ) + tr.endpos ) + ( vecForward * 128.0f );

		offset = vecForward * 128.0f;
		offset += tr.endpos + RandomVector( -4.0f, 4.0f );


		pParticle = (SimpleParticle *) m_pSimple->AddParticle( sizeof(SimpleParticle), hMaterial[random->RandomInt(0,1)], offset );

		if ( pParticle != NULL )
		{
			pParticle->m_flLifetime = 0.0f;
			pParticle->m_flDieTime	= random->RandomFloat( 0.25f, 1.0f );

			pParticle->m_vecVelocity = vecForward * random->RandomFloat( 1000, 1500 );
		
			#if __EXPLOSION_DEBUG
			debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 );
			#endif

			if ( tr.contents & CONTENTS_SLIME )
			{
				vecDustColor.x = random->RandomFloat( 0.4f, 0.6f );
				vecDustColor.y = random->RandomFloat( 0.3f, 0.5f );
				vecDustColor.z = random->RandomFloat( 0.1f, 0.2f );
			}

			pParticle->m_uchColor[0] = vecDustColor.x * 255.0f;
			pParticle->m_uchColor[1] = vecDustColor.y * 255.0f;
			pParticle->m_uchColor[2] = vecDustColor.z * 255.0f;

			pParticle->m_uchStartSize	= random->RandomInt( 16, 64 );
			pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4;

			pParticle->m_uchStartAlpha	= random->RandomFloat( 16, 32 ) * heightScale;
			pParticle->m_uchEndAlpha	= 0;
			
			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= random->RandomFloat( -16.0f, 16.0f );
		}
	}
#endif // !XBOX
}
Beispiel #19
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &origin - 
//			&normal - 
//			scale - 
//			r - 
//			g - 
//			b - 
//			flags - 
//-----------------------------------------------------------------------------
void FX_BloodSpray( const Vector &origin, const Vector &normal, float scale, unsigned char r, unsigned char g, unsigned char b, int flags )
{
	if ( UTIL_IsLowViolence() )
		return;

	//debugoverlay->AddLineOverlay( origin, origin + normal * 72, 255, 255, 255, true, 10 ); 

	Vector offset;
	float spread	= 0.2f;
	
	//Find area ambient light color and use it to tint smoke
	Vector worldLight = WorldGetLightForPoint( origin, true );
	Vector color = Vector( (float)(worldLight[0] * r) / 255.0f, (float)(worldLight[1] * g) / 255.0f, (float)(worldLight[2] * b) / 255.0f );
	float colorRamp;

	int i;

	Vector	offDir;

	Vector right;
	Vector up;

	if (normal != Vector(0, 0, 1) )
	{
		right = normal.Cross( Vector(0, 0, 1) );
		up = right.Cross( normal );
	}
	else
	{
		right = Vector(0, 0, 1);
		up = right.Cross( normal );
	}

	//
	// Dump out drops
	//
	if (flags & FX_BLOODSPRAY_DROPS)
	{
		TrailParticle *tParticle;

		CSmartPtr<CTrailParticles> pTrailEmitter = CTrailParticles::Create( "blooddrops" );
		if ( !pTrailEmitter )
			return;

		pTrailEmitter->SetSortOrigin( origin );

		// Partial gravity on blood drops.
		pTrailEmitter->SetGravity( 600.0 ); 

		pTrailEmitter->GetBinding().SetBBox( origin - Vector( 32, 32, 32 ), origin + Vector( 32, 32, 32 ) );
		pTrailEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN );
		pTrailEmitter->SetVelocityDampen( 0.2f );

		PMaterialHandle	hMaterial = ParticleMgr()->GetPMaterial( "effects/blood_drop" );

		//
		// Long stringy drops of blood.
		//
		for ( i = 0; i < 14; i++ )
		{
			// Originate from within a circle 'scale' inches in diameter.
			offset = origin;
			offset += right * random->RandomFloat( -0.5f, 0.5f ) * scale;
			offset += up * random->RandomFloat( -0.5f, 0.5f ) * scale;

			tParticle = (TrailParticle *) pTrailEmitter->AddParticle( sizeof(TrailParticle), hMaterial, offset );

			if ( tParticle == NULL )
				break;

			tParticle->m_flLifetime	= 0.0f;

			offDir = normal + RandomVector( -0.3f, 0.3f );

			tParticle->m_vecVelocity = offDir * random->RandomFloat( 4.0f * scale, 40.0f * scale );
			tParticle->m_vecVelocity[2] += random->RandomFloat( 4.0f, 16.0f ) * scale;

			tParticle->m_flWidth		= random->RandomFloat( 0.125f, 0.275f ) * scale;
			tParticle->m_flLength		= random->RandomFloat( 0.02f, 0.03f ) * scale;
			tParticle->m_flDieTime		= random->RandomFloat( 0.5f, 1.0f );

			FloatToColor32( tParticle->m_color, color[0], color[1], color[2], 1.0f );
		}

		//
		// Shorter droplets.
		//
		for ( i = 0; i < 24; i++ )
		{
			// Originate from within a circle 'scale' inches in diameter.
			offset = origin;
			offset += right * random->RandomFloat( -0.5f, 0.5f ) * scale;
			offset += up * random->RandomFloat( -0.5f, 0.5f ) * scale;

			tParticle = (TrailParticle *) pTrailEmitter->AddParticle( sizeof(TrailParticle), hMaterial, offset );

			if ( tParticle == NULL )
				break;

			tParticle->m_flLifetime	= 0.0f;

			offDir = normal + RandomVector( -1.0f, 1.0f );
			offDir[2] += random->RandomFloat(0, 1.0f);

			tParticle->m_vecVelocity = offDir * random->RandomFloat( 2.0f * scale, 25.0f * scale );
			tParticle->m_vecVelocity[2] += random->RandomFloat( 4.0f, 16.0f ) * scale;

			tParticle->m_flWidth		= random->RandomFloat( 0.25f, 0.375f ) * scale;
			tParticle->m_flLength		= random->RandomFloat( 0.0025f, 0.005f ) * scale;
			tParticle->m_flDieTime		= random->RandomFloat( 0.5f, 1.0f );

			FloatToColor32( tParticle->m_color, color[0], color[1], color[2], 1.0f );
		}
	}

	if ((flags & FX_BLOODSPRAY_GORE) || (flags & FX_BLOODSPRAY_CLOUD))
	{
		CSmartPtr<CBloodSprayEmitter> pSimple = CBloodSprayEmitter::Create( "bloodgore" );
		if ( !pSimple )
			return;

		pSimple->SetSortOrigin( origin );
		pSimple->SetGravity( 0 );

		PMaterialHandle	hMaterial;

		//
		// Tight blossom of blood at the center.
		//
		if (flags & FX_BLOODSPRAY_GORE)
		{
			hMaterial = ParticleMgr()->GetPMaterial( "effects/blood_gore" );

			SimpleParticle *pParticle;

			for ( i = 0; i < 6; i++ )
			{
				// Originate from within a circle 'scale' inches in diameter.
				offset = origin + ( 0.5 * scale * normal );
				offset += right * random->RandomFloat( -0.5f, 0.5f ) * scale;
				offset += up * random->RandomFloat( -0.5f, 0.5f ) * scale;

				pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial, offset );

				if ( pParticle != NULL )
				{
					pParticle->m_flLifetime = 0.0f;
					pParticle->m_flDieTime	= 0.3f;

					spread = 0.2f;
					pParticle->m_vecVelocity.Random( -spread, spread );
					pParticle->m_vecVelocity += normal * random->RandomInt( 10, 100 );
					//VectorNormalize( pParticle->m_vecVelocity );

					colorRamp = random->RandomFloat( 0.75f, 1.25f );

					pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
					pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
					pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
					
					pParticle->m_uchStartSize	= random->RandomFloat( scale * 0.25, scale );
					pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 2;
					
					pParticle->m_uchStartAlpha	= random->RandomInt( 200, 255 );
					pParticle->m_uchEndAlpha	= 0;
					
					pParticle->m_flRoll			= random->RandomInt( 0, 360 );
					pParticle->m_flRollDelta	= 0.0f;
				}
			}
		}

		//
		// Diffuse cloud just in front of the exit wound.
		//
		if (flags & FX_BLOODSPRAY_CLOUD)
		{
			hMaterial = ParticleMgr()->GetPMaterial( "effects/blood_puff" );

			SimpleParticle *pParticle;

			for ( i = 0; i < 6; i++ )
			{
				// Originate from within a circle '2 * scale' inches in diameter.
				offset = origin + ( scale * normal );
				offset += right * random->RandomFloat( -1, 1 ) * scale;
				offset += up * random->RandomFloat( -1, 1 ) * scale;

				pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial, offset );

				if ( pParticle != NULL )
				{
					pParticle->m_flLifetime = 0.0f;
					pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 0.8f);

					spread = 0.5f;
					pParticle->m_vecVelocity.Random( -spread, spread );
					pParticle->m_vecVelocity += normal * random->RandomInt( 100, 200 );

					colorRamp = random->RandomFloat( 0.75f, 1.25f );

					pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
					pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
					pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
					
					pParticle->m_uchStartSize	= random->RandomFloat( scale * 1.5f, scale * 2.0f );
					pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4;
					
					pParticle->m_uchStartAlpha	= random->RandomInt( 80, 128 );
					pParticle->m_uchEndAlpha	= 0;
					
					pParticle->m_flRoll			= random->RandomInt( 0, 360 );
					pParticle->m_flRollDelta	= 0.0f;
				}
			}
		}
	}

	// TODO: Play a sound?
	//CLocalPlayerFilter filter;
	//C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, CHAN_VOICE, "Physics.WaterSplash", 1.0, ATTN_NORM, 0, 100, &origin );
}
Beispiel #20
0
//-----------------------------------------------------------------------------
// Purpose: Used for bullets hitting bleeding surfaces
// Input  : origin - 
//			normal - 
//			scale - This parameter is not currently used
//-----------------------------------------------------------------------------
void FX_BloodBulletImpact( const Vector &origin, const Vector &normal, float scale /*NOTE: Unused!*/, unsigned char r, unsigned char g, unsigned char b )
{
	if ( UTIL_IsLowViolence() )
		return;

	Vector offset;
	
	//Find area ambient light color and use it to tint smoke
	Vector worldLight = WorldGetLightForPoint( origin, true );
	
	if ( gpGlobals->maxClients > 1 )
	{
		worldLight = Vector( 1.0, 1.0, 1.0 );
		r = 96;
		g = 0;
		b = 10;
	}

	Vector color = Vector( (float)(worldLight[0] * r) / 255.0f, (float)(worldLight[1] * g) / 255.0f, (float)(worldLight[2] * b) / 255.0f );
	float colorRamp;

	Vector	offDir;

	CSmartPtr<CBloodSprayEmitter> pSimple = CBloodSprayEmitter::Create( "bloodgore" );
	if ( !pSimple )
		return;

	pSimple->SetSortOrigin( origin );
	pSimple->SetGravity( 200 );
	
	// Setup a bounding box to contain the particles without (stops auto-updating)
	pSimple->GetBinding().SetBBox( origin - Vector( 16, 16, 16 ), origin + Vector( 16, 16, 16 ) );

	// Cache the material if we haven't already
	if ( g_Blood_Core == NULL )
	{
		g_Blood_Core = ParticleMgr()->GetPMaterial( "effects/blood_core" );
	}

	SimpleParticle *pParticle;

	Vector	dir = normal * RandomVector( -0.5f, 0.5f );

	offset = origin + ( 2.0f * normal );

	pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Blood_Core, offset );

	if ( pParticle != NULL )
	{
		pParticle->m_flLifetime = 0.0f;
		pParticle->m_flDieTime	= random->RandomFloat( 0.25f, 0.5f);

		pParticle->m_vecVelocity	= dir * random->RandomFloat( 16.0f, 32.0f );
		pParticle->m_vecVelocity[2] -= random->RandomFloat( 8.0f, 16.0f );

		colorRamp = random->RandomFloat( 0.75f, 2.0f );

		pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
		
		pParticle->m_uchStartSize	= random->RandomInt( 2, 4 );
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 8;
	
		pParticle->m_uchStartAlpha	= 255;
		pParticle->m_uchEndAlpha	= 0;
		
		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
		pParticle->m_flRollDelta	= 0.0f;
	}

	// Cache the material if we haven't already
	if ( g_Blood_Gore == NULL )
	{
		g_Blood_Gore = ParticleMgr()->GetPMaterial( "effects/blood_gore" );
	}

	for ( int i = 0; i < 4; i++ )
	{
		offset = origin + ( 2.0f * normal );

		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Blood_Gore, offset );

		if ( pParticle != NULL )
		{
			pParticle->m_flLifetime = 0.0f;
			pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 0.75f);

			pParticle->m_vecVelocity	= dir * random->RandomFloat( 16.0f, 32.0f )*(i+1);
			pParticle->m_vecVelocity[2] -= random->RandomFloat( 32.0f, 64.0f )*(i+1);

			colorRamp = random->RandomFloat( 0.75f, 2.0f );

			pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
			
			pParticle->m_uchStartSize	= random->RandomInt( 2, 4 );
			pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4;
		
			pParticle->m_uchStartAlpha	= 255;
			pParticle->m_uchEndAlpha	= 0;
			
			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= 0.0f;
		}
	}

	//
	// Dump out drops
	//
	TrailParticle *tParticle;

	CSmartPtr<CTrailParticles> pTrailEmitter = CTrailParticles::Create( "blooddrops" );
	if ( !pTrailEmitter )
		return;

	pTrailEmitter->SetSortOrigin( origin );

	// Partial gravity on blood drops
	pTrailEmitter->SetGravity( 400.0 ); 
	
	// Enable simple collisions with nearby surfaces
	pTrailEmitter->Setup(origin, &normal, 1, 10, 100, 400, 0.2, 0 );

	if ( g_Blood_Drops == NULL )
	{
		g_Blood_Drops = ParticleMgr()->GetPMaterial( "effects/blood_drop" );
	}

	//
	// Shorter droplets
	//
	for ( int i = 0; i < 8; i++ )
	{
		// Originate from within a circle 'scale' inches in diameter
		offset = origin;

		tParticle = (TrailParticle *) pTrailEmitter->AddParticle( sizeof(TrailParticle), g_Blood_Drops, offset );

		if ( tParticle == NULL )
			break;

		tParticle->m_flLifetime	= 0.0f;

		offDir = RandomVector( -1.0f, 1.0f );

		tParticle->m_vecVelocity = offDir * random->RandomFloat( 64.0f, 128.0f );

		tParticle->m_flWidth		= random->RandomFloat( 0.5f, 2.0f );
		tParticle->m_flLength		= random->RandomFloat( 0.05f, 0.15f );
		tParticle->m_flDieTime		= random->RandomFloat( 0.25f, 0.5f );

		FloatToColor32( tParticle->m_color, color[0], color[1], color[2], 1.0f );
	}

	// TODO: Play a sound?
	//CLocalPlayerFilter filter;
	//C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, CHAN_VOICE, "Physics.WaterSplash", 1.0, ATTN_NORM, 0, 100, &origin );
}
void FX_DustImpact( const Vector &origin, trace_t *tr, float flScale )
{
	//
	// PC version
	//

	VPROF_BUDGET( "FX_DustImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	Vector	offset;
	float	spread = 0.2f;
	
	CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" );
	pSimple->SetSortOrigin( origin );

	// Three types of particle, ideally we want 4 of each.
	float fNumParticles = 4.0f * g_pParticleSystemMgr->ParticleThrottleScaling();
	int nParticles1 = (int)( 0.50f + fNumParticles );
	int nParticles2 = (int)( 0.83f + fNumParticles );		// <-- most visible particle type.
	int nParticles3 = (int)( 0.17f + fNumParticles );

	SimpleParticle	*pParticle;

	Vector	color;
	float	colorRamp;

	GetColorForSurface( tr, &color );

	// To get a decent spread even when scaling down the number of particles...
	const static int nParticleIdArray[4] = {3,1,2,0};

	int i;
	for ( i = 0; i < nParticles1; i++ )
	{
		int nId = nParticleIdArray[i];

		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );

		if ( pParticle != NULL )
		{
			pParticle->m_flLifetime = 0.0f;
			pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );

			pParticle->m_vecVelocity.Random( -spread, spread );
			pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );
			
			VectorNormalize( pParticle->m_vecVelocity );

			float	fForce = random->RandomFloat( 250, 500 ) * nId;

			// scaled
			pParticle->m_vecVelocity *= fForce * flScale;
			
			colorRamp = random->RandomFloat( 0.75f, 1.25f );

			pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
			
			// scaled
			pParticle->m_uchStartSize	= ( unsigned char )( flScale * random->RandomInt( 3, 4 ) * (nId+1) );

			// scaled
			pParticle->m_uchEndSize		= ( unsigned char )( flScale * pParticle->m_uchStartSize * 4 );
			
			pParticle->m_uchStartAlpha	= random->RandomInt( 32, 255 );
			pParticle->m_uchEndAlpha	= 0;
			
			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= random->RandomFloat( -8.0f, 8.0f );
		}
	}			

	//Dust specs
	for ( i = 0; i < nParticles2; i++ )
	{
		int nId = nParticleIdArray[i];

		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );

		if ( pParticle != NULL )
		{
			pParticle->m_flLifetime = 0.0f;
			pParticle->m_flDieTime	= random->RandomFloat( 0.25f, 0.75f );

			pParticle->m_vecVelocity.Random( -spread, spread );
			pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );
			
			VectorNormalize( pParticle->m_vecVelocity );

			float	fForce = random->RandomFloat( 250, 500 ) * nId;

			pParticle->m_vecVelocity *= fForce;
			
			colorRamp = random->RandomFloat( 0.75f, 1.25f );

			pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
			
			pParticle->m_uchStartSize	= random->RandomInt( 2, 4 ) * (nId+1);
			pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 2;
			
			pParticle->m_uchStartAlpha	= 255;
			pParticle->m_uchEndAlpha	= 0;
			
			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );
		}
	}

	//Impact hit
	for ( i = 0; i < nParticles3; i++ )
	{
		//int nId = nParticleIdArray[i];

		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );

		if ( pParticle != NULL )
		{
			offset = origin;
			offset[0] += random->RandomFloat( -8.0f, 8.0f );
			offset[1] += random->RandomFloat( -8.0f, 8.0f );

			pParticle->m_flLifetime = 0.0f;
			pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );

			spread = 1.0f;

			pParticle->m_vecVelocity.Random( -spread, spread );
			pParticle->m_vecVelocity += tr->plane.normal;
			
			VectorNormalize( pParticle->m_vecVelocity );

			float	fForce = random->RandomFloat( 0, 50 );

			pParticle->m_vecVelocity *= fForce;
			
			colorRamp = random->RandomFloat( 0.75f, 1.25f );

			pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
			
			pParticle->m_uchStartSize	= random->RandomInt( 1, 4 );
			pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4;
			
			pParticle->m_uchStartAlpha	= random->RandomInt( 32, 64 );
			pParticle->m_uchEndAlpha	= 0;
			
			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= random->RandomFloat( -16.0f, 16.0f );
		}
	}			
}
//-----------------------------------------------------------------------------
// Purpose: Blood puff
//-----------------------------------------------------------------------------
void FX_Blood( Vector &pos, Vector &dir, float r, float g, float b, float a )
{
	VPROF_BUDGET( "FX_Blood", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	// Cloud
	CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_Blood" );
	if ( !pSimple )
		return;
	pSimple->SetSortOrigin( pos );

	Vector	vDir;

	vDir[0] = dir[0] + random->RandomFloat( -1.0f, 1.0f );
	vDir[1] = dir[1] + random->RandomFloat( -1.0f, 1.0f );
	vDir[2] = dir[2] + random->RandomFloat( -1.0f, 1.0f );

	VectorNormalize( vDir );

	int i;
	for ( i = 0; i < 2; i++ )
	{
		SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], pos );
			
		if ( sParticle == NULL )
		{
			return;
		}

		sParticle->m_flLifetime		= 0.0f;
		sParticle->m_flDieTime		= random->RandomFloat( 0.25f, 0.5f );
			
		float	speed = random->RandomFloat( 2.0f, 8.0f );

		sParticle->m_vecVelocity	= vDir * (speed*i);
		sParticle->m_vecVelocity[2] += random->RandomFloat( -32.0f, -16.0f );

		sParticle->m_uchColor[0]	= r;
		sParticle->m_uchColor[1]	= g;
		sParticle->m_uchColor[2]	= b;
		sParticle->m_uchStartAlpha	= a;
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchStartSize	= 2;
		sParticle->m_uchEndSize		= sParticle->m_uchStartSize*4;
		sParticle->m_flRoll			= random->RandomInt( 0, 360 );
		sParticle->m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );
	}

	for ( i = 0; i < 2; i++ )
	{
		SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], pos );
			
		if ( sParticle == NULL )
		{
			return;
		}

		sParticle->m_flLifetime		= 0.0f;
		sParticle->m_flDieTime		= 0.5f;
			
		float	speed = random->RandomFloat( 4.0f, 16.0f );

		sParticle->m_vecVelocity	= vDir * (speed*i);

		sParticle->m_uchColor[0]	= r;
		sParticle->m_uchColor[1]	= g;
		sParticle->m_uchColor[2]	= b;
		sParticle->m_uchStartAlpha	= 128;
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchStartSize	= 2;
		sParticle->m_uchEndSize		= sParticle->m_uchStartSize*4;
		sParticle->m_flRoll			= random->RandomInt( 0, 360 );
		sParticle->m_flRollDelta	= random->RandomFloat( -4.0f, 4.0f );
	}
}
void FX_BugBlood( Vector &pos, Vector &dir, Vector &vWorldMins, Vector &vWorldMaxs )
{
	VPROF_BUDGET( "FX_BugBlood", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_BugBlood" );
	if ( !pSimple )
		return;

	pSimple->SetSortOrigin( pos );
	pSimple->GetBinding().SetBBox( vWorldMins, vWorldMaxs, true );
	pSimple->GetBinding().SetBBox( pos-Vector(32,32,32), pos+Vector(32,32,32), true );

	Vector	vDir;
	vDir[0] = dir[0] + random->RandomFloat( -2.0f, 2.0f );
	vDir[1] = dir[1] + random->RandomFloat( -2.0f, 2.0f );
	vDir[2] = dir[2] + random->RandomFloat( -2.0f, 2.0f );

	VectorNormalize( vDir );

	int i;
	for ( i = 0; i < NUM_BUG_BLOOD; i++ )
	{
		SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], pos );
			
		if ( sParticle == NULL )
			return;

		sParticle->m_flLifetime		= 0.0f;
		sParticle->m_flDieTime		= 0.25f;
			
		float	speed = random->RandomFloat( 32.0f, 150.0f );

		sParticle->m_vecVelocity	= vDir * -speed;
		sParticle->m_vecVelocity[2] -= 32.0f;

		sParticle->m_uchColor[0]	= 255;
		sParticle->m_uchColor[1]	= 200;
		sParticle->m_uchColor[2]	= 32;
		sParticle->m_uchStartAlpha	= 255;
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchStartSize	= random->RandomInt( 1, 2 );
		sParticle->m_uchEndSize		= sParticle->m_uchStartSize*random->RandomInt( 1, 4 );
		sParticle->m_flRoll			= random->RandomInt( 0, 360 );
		sParticle->m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );
	}

	for ( i = 0; i < NUM_BUG_BLOOD2; i++ )
	{
		SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], pos );
			
		if ( sParticle == NULL )
		{
			return;
		}

		sParticle->m_flLifetime		= 0.0f;
		sParticle->m_flDieTime		= random->RandomFloat( 0.25f, 0.5f );
			
		float	speed = random->RandomFloat( 8.0f, 255.0f );

		sParticle->m_vecVelocity	= vDir * -speed;
		sParticle->m_vecVelocity[2] -= 16.0f;

		sParticle->m_uchColor[0]	= 255;
		sParticle->m_uchColor[1]	= 200;
		sParticle->m_uchColor[2]	= 32;
		sParticle->m_uchStartAlpha	= random->RandomInt( 16, 32 );
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchStartSize	= random->RandomInt( 1, 3 );
		sParticle->m_uchEndSize		= sParticle->m_uchStartSize*random->RandomInt( 1, 4 );
		sParticle->m_flRoll			= random->RandomInt( 0, 360 );
		sParticle->m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );
	}

	Vector	offset;

	for ( i = 0; i < NUM_BUG_SPLATS; i++ )
	{
		offset.Random( -2, 2 );
		offset += pos;

		SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], offset );
			
		if ( sParticle == NULL )
		{
			return;
		}
		
		sParticle->m_flLifetime		= 0.0f;
		sParticle->m_flDieTime		= random->RandomFloat( 0.25f, 0.5f );
			
		float speed = 75.0f * ((i/(float)NUM_BUG_SPLATS)+1);

		sParticle->m_vecVelocity.Random( -16.0f, 16.0f );

		sParticle->m_vecVelocity	+= vDir * -speed;
		sParticle->m_vecVelocity[2] -= ( 64.0f * ((i/(float)NUM_BUG_SPLATS)+1) );

		sParticle->m_uchColor[0]	= 255;
		sParticle->m_uchColor[1]	= 200;
		sParticle->m_uchColor[2]	= 32;
		sParticle->m_uchStartAlpha	= 255;
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchStartSize	= random->RandomInt( 1, 2 );
		sParticle->m_uchEndSize		= sParticle->m_uchStartSize*4;
		sParticle->m_flRoll			= random->RandomInt( 0, 360 );
		sParticle->m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &pos - 
//			*tr - 
//-----------------------------------------------------------------------------
void FX_AntlionImpact( const Vector &pos, trace_t *trace )
{
#if defined( _X360 )
	return;
#endif // _X360

	VPROF_BUDGET( "FX_AntlionImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	CSmartPtr<CSimple3DEmitter> fleckEmitter = CSimple3DEmitter::Create( "FX_DebrisFlecks" );
	if ( fleckEmitter == NULL )
		return;

	Vector	shotDir = ( trace->startpos - trace->endpos );
	VectorNormalize( shotDir );

	Vector	spawnOffset	= trace->endpos + ( shotDir * 2.0f );

	Vector vWorldMins, vWorldMaxs;
	if ( trace->m_pEnt )
	{
		float scale = trace->m_pEnt->CollisionProp()->BoundingRadius();
		vWorldMins[0] = spawnOffset[0] - scale;
		vWorldMins[1] = spawnOffset[1] - scale;
		vWorldMins[2] = spawnOffset[2] - scale;
		vWorldMaxs[0] = spawnOffset[0] + scale;
		vWorldMaxs[1] = spawnOffset[1] + scale;
		vWorldMaxs[2] = spawnOffset[2] + scale;
	}
	else
	{
		return;
	}

	fleckEmitter->SetSortOrigin( spawnOffset );
	fleckEmitter->GetBinding().SetBBox( spawnOffset-Vector(32,32,32), spawnOffset+Vector(32,32,32), true );

	// Handle increased scale
	float flMaxSpeed = 256.0f;
	float flAngularSpray = 1.0f;

	// Setup our collision information
	fleckEmitter->m_ParticleCollision.Setup( spawnOffset, &shotDir, flAngularSpray, 8.0f, flMaxSpeed, FLECK_GRAVITY, FLECK_DAMPEN );

	Vector	dir, end;
	Vector	color = Vector( 1, 0.9, 0.75 );
	float	colorRamp;

	int	numFlecks = random->RandomInt( 8, 16 );

	Particle3D *pFleckParticle;

	// Dump out flecks
	int i;
	for ( i = 0; i < numFlecks; i++ )
	{
		pFleckParticle = (Particle3D *) fleckEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Antlion[random->RandomInt(0,1)], spawnOffset );
		if ( pFleckParticle == NULL )
			break;

		pFleckParticle->m_flLifeRemaining = 3.0f;

		dir[0] = shotDir[0] + random->RandomFloat( -flAngularSpray, flAngularSpray );
		dir[1] = shotDir[1] + random->RandomFloat( -flAngularSpray, flAngularSpray );
		dir[2] = shotDir[2] + random->RandomFloat( -flAngularSpray, flAngularSpray );

		pFleckParticle->m_uchSize		= random->RandomInt( 1, 6 );

		pFleckParticle->m_vecVelocity	= dir * random->RandomFloat( FLECK_MIN_SPEED, flMaxSpeed);
		pFleckParticle->m_vAngles.Random( 0, 360 );
		pFleckParticle->m_flAngSpeed	= random->RandomFloat(-800,800);

		pFleckParticle->m_uchFrontColor[0] = 255;
		pFleckParticle->m_uchFrontColor[1] = 255;
		pFleckParticle->m_uchFrontColor[2] = 255;

		pFleckParticle->m_uchBackColor[0] = 128;
		pFleckParticle->m_uchBackColor[1] = 128;
		pFleckParticle->m_uchBackColor[2] = 128;
	}

	//
	// Dust trail
	//

	SimpleParticle	*pParticle;

	CSmartPtr<CSimpleEmitter> dustEmitter = CSimpleEmitter::Create( "FX_DebrisFlecks" );					
	if ( !dustEmitter )
		return;

	Vector	offset = trace->endpos + ( shotDir * 4.0f );

	dustEmitter->SetSortOrigin( offset );
	dustEmitter->GetBinding().SetBBox( spawnOffset-Vector(32,32,32), spawnOffset+Vector(32,32,32), true );

	for ( i = 0; i < 4; i++ )
	{
		pParticle = (SimpleParticle *) dustEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[0], offset );

		if ( pParticle == NULL )
			break;

		pParticle->m_flLifetime	= 0.0f;
		pParticle->m_flDieTime	= 1.0f;
		
		dir[0] = shotDir[0] + random->RandomFloat( -0.8f, 0.8f );
		dir[1] = shotDir[1] + random->RandomFloat( -0.8f, 0.8f );
		dir[2] = shotDir[2] + random->RandomFloat( -0.8f, 0.8f );

		pParticle->m_uchStartSize	= random->RandomInt( 8, 16 );
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4.0f;

		pParticle->m_vecVelocity = dir * random->RandomFloat( 4.0f, 64.0f );

		pParticle->m_uchStartAlpha	= random->RandomInt( 32, 64);
		pParticle->m_uchEndAlpha	= 0;
		
		pParticle->m_flRoll			= random->RandomFloat( 0, 2.0f*M_PI );
		pParticle->m_flRollDelta	= random->RandomFloat( -0.5f, 0.5f );

		colorRamp = random->RandomFloat( 0.5f, 1.0f );

		pParticle->m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
		pParticle->m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
		pParticle->m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
	}


	CLocalPlayerFilter filter;
	C_BaseEntity::EmitSound( filter, 0, "FX_AntlionImpact.ShellImpact", &trace->endpos );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void FX_GlassImpact( const Vector &pos, const Vector &normal )
{
	VPROF_BUDGET( "FX_GlassImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "FX_GlassImpact" );
	pGlassEmitter->SetSortOrigin( pos );

	Vector vecColor;
	engine->ComputeLighting( pos, NULL, true, vecColor );

	// HACK: Blend a little toward white to match the materials...
	VectorLerp( vecColor, Vector( 1, 1, 1 ), 0.3, vecColor );

	float flShardSize	= random->RandomFloat( 2.0f, 6.0f );

	unsigned char color[3] = { 200, 200, 210 };

	// ---------------------
	// Create glass shards
	// ----------------------

	int numShards = random->RandomInt( 2, 4 );

	for ( int i = 0; i < numShards; i++ )
	{
		Particle3D *pParticle;
		
		pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Glass[random->RandomInt(0,1)], pos );

		if ( pParticle )
		{
			pParticle->m_flLifeRemaining	= random->RandomFloat(GLASS_SHARD_MIN_LIFE,GLASS_SHARD_MAX_LIFE);

			pParticle->m_vecVelocity[0]		= ( normal[0] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
			pParticle->m_vecVelocity[1]		= ( normal[1] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
			pParticle->m_vecVelocity[2]		= ( normal[2] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );

			pParticle->m_uchSize			= flShardSize + random->RandomFloat(-0.5*flShardSize,0.5*flShardSize);
			pParticle->m_vAngles			= RandomAngle( 0, 360 );
			pParticle->m_flAngSpeed			= random->RandomFloat(-800,800);

			pParticle->m_uchFrontColor[0]	= (byte)(color[0] * vecColor.x);
			pParticle->m_uchFrontColor[1]	= (byte)(color[1] * vecColor.y);
			pParticle->m_uchFrontColor[2]	= (byte)(color[2] * vecColor.z);
			pParticle->m_uchBackColor[0]	= (byte)(color[0] * vecColor.x);
			pParticle->m_uchBackColor[1]	= (byte)(color[1] * vecColor.y);
			pParticle->m_uchBackColor[2]	= (byte)(color[2] * vecColor.z);
		}
	}

	pGlassEmitter->m_ParticleCollision.Setup( pos, &normal, GLASS_SHARD_NOISE, GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED, GLASS_SHARD_GRAVITY, GLASS_SHARD_DAMPING );

	color[0] = 64;
	color[1] = 64;
	color[2] = 92;

	// ---------------------------
	// Dust
	// ---------------------------

	Vector	dir;
	Vector	offset = pos + ( normal * 2.0f );
	float	colorRamp;

	SimpleParticle newParticle;

	for ( int i = 0; i < 4; i++ )
	{
		newParticle.m_Pos = offset;

		newParticle.m_flLifetime= 0.0f;
		newParticle.m_flDieTime	= random->RandomFloat( 0.1f, 0.25f );
		
		dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f );
		dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f );
		dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f );

		newParticle.m_uchStartSize	= random->RandomInt( 1, 4 );
		newParticle.m_uchEndSize	= newParticle.m_uchStartSize * 8;

		newParticle.m_vecVelocity	= dir * random->RandomFloat( 8.0f, 16.0f )*(i+1);
		newParticle.m_vecVelocity[2] -= random->RandomFloat( 16.0f, 32.0f )*(i+1);

		newParticle.m_uchStartAlpha	= random->RandomInt( 128, 255 );
		newParticle.m_uchEndAlpha	= 0;
		
		newParticle.m_flRoll		= random->RandomFloat( 0, 360 );
		newParticle.m_flRollDelta	= random->RandomFloat( -1, 1 );

		colorRamp = random->RandomFloat( 0.5f, 1.25f );

		newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
		newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
		newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

		AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] );
	}

	//
	// Bullet hole capper
	//
	newParticle.m_Pos = offset;

	newParticle.m_flLifetime		= 0.0f;
	newParticle.m_flDieTime		= random->RandomFloat( 1.0f, 1.5f );

	dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f );
	dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f );
	dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f );

	newParticle.m_uchStartSize	= random->RandomInt( 4, 8 );
	newParticle.m_uchEndSize		= newParticle.m_uchStartSize * 4.0f;

	newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 8.0f );
	newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f );

	newParticle.m_uchStartAlpha	= random->RandomInt( 32, 64 );
	newParticle.m_uchEndAlpha	= 0;
	
	newParticle.m_flRoll			= random->RandomFloat( 0, 360 );
	newParticle.m_flRollDelta	= random->RandomFloat( -2, 2 );

	colorRamp = random->RandomFloat( 0.5f, 1.25f );

	newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
	newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
	newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

	AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );
}
//-----------------------------------------------------------------------------
// Purpose: Debris flecks caused by impacts
// Input  : origin - start
//			*trace - trace information
//			*materialName - material hit
//			materialType - type of material hit
//-----------------------------------------------------------------------------
void FX_DebrisFlecks( const Vector& origin, trace_t *tr, char materialType, int iScale, bool bNoFlecks )
{
	VPROF_BUDGET( "FX_DebrisFlecks", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	if ( !fx_drawimpactdebris.GetBool() )
		return;

#ifdef _XBOX

	//
	// XBox version
	//

	Vector	offset;
	float	spread = 0.2f;

	CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" );
	pSimple->SetSortOrigin( origin );
	
	// Lock the bbox
	pSimple->GetBinding().SetBBox( origin - ( Vector( 16, 16, 16 ) * iScale ), origin + ( Vector( 16, 16, 16 ) * iScale ) );

	// Get the color of the surface we've impacted
	Vector	color;
	float	colorRamp;
	GetColorForSurface( tr, &color );

	int i;
	SimpleParticle	*pParticle;
	for ( i = 0; i < 4; i++ )
	{
		if ( i == 3 )
		{
			pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );
		}
		else
		{
			pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );
		}

		if ( pParticle != NULL )
		{
			pParticle->m_flLifetime = 0.0f;
			pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );

			pParticle->m_vecVelocity.Random( -spread, spread );
			pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );

			VectorNormalize( pParticle->m_vecVelocity );

			float	fForce = random->RandomFloat( 250, 500 ) * i * 0.5f;

			// scaled
			pParticle->m_vecVelocity *= fForce * iScale;

			// Ramp the color
			colorRamp = random->RandomFloat( 0.5f, 1.25f );
			pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;

			// scaled
			pParticle->m_uchStartSize	= (iScale*0.5f) * random->RandomInt( 3, 4 ) * (i+1);

			// scaled
			pParticle->m_uchEndSize		= (iScale*0.5f) * pParticle->m_uchStartSize * 4;

			pParticle->m_uchStartAlpha	= random->RandomInt( 200, 255 );
			pParticle->m_uchEndAlpha	= 0;

			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= random->RandomFloat( -1.0f, 1.0f );
		}
	}			

	// Covers the impact spot with flecks
	pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff2, origin );

	if ( pParticle != NULL )
	{
		offset = origin;
		offset[0] += random->RandomFloat( -8.0f, 8.0f );
		offset[1] += random->RandomFloat( -8.0f, 8.0f );

		pParticle->m_flLifetime = 0.0f;
		pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );

		spread = 1.0f;

		pParticle->m_vecVelocity.Init();

		colorRamp = random->RandomFloat( 0.5f, 1.25f );

		pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;

		pParticle->m_uchStartSize	= random->RandomInt( 4, 8 );
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4;

		pParticle->m_uchStartAlpha	= random->RandomInt( 64, 128 );
		pParticle->m_uchEndAlpha	= 0;

		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
		pParticle->m_flRollDelta	= random->RandomFloat( -0.1f, 0.1f );
	}

#else

	//
	// PC version
	//

	Vector	color;
	GetColorForSurface( tr, &color );

	if ( !bNoFlecks )
	{
		CreateFleckParticles( origin, color, tr, materialType, iScale );
	}

	//
	// Dust trail
	//
	Vector	offset = tr->endpos + ( tr->plane.normal * 2.0f );

	SimpleParticle newParticle;

	int i;
	for ( i = 0; i < 2; i++ )
	{
		newParticle.m_Pos = offset;

		newParticle.m_flLifetime	= 0.0f;
		newParticle.m_flDieTime	= 1.0f;

		Vector dir;
		dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
		dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
		dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );

		newParticle.m_uchStartSize	= random->RandomInt( 2, 4 ) * iScale;
		newParticle.m_uchEndSize	= newParticle.m_uchStartSize * 8 * iScale;

		newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f )*(i+1);
		newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 32.0f )*(i+1);

		newParticle.m_uchStartAlpha	= random->RandomInt( 100, 200 );
		newParticle.m_uchEndAlpha	= 0;

		newParticle.m_flRoll			= random->RandomFloat( 0, 360 );
		newParticle.m_flRollDelta	= random->RandomFloat( -1, 1 );

		float colorRamp = random->RandomFloat( 0.5f, 1.25f );

		newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
		newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
		newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

		AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );
	}


	for ( i = 0; i < 4; i++ )
	{
		newParticle.m_Pos = offset;

		newParticle.m_flLifetime	= 0.0f;
		newParticle.m_flDieTime	= random->RandomFloat( 0.25f, 0.5f );

		Vector dir;
		dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
		dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
		dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );

		newParticle.m_uchStartSize	= random->RandomInt( 1, 4 );
		newParticle.m_uchEndSize	= newParticle.m_uchStartSize * 4;

		newParticle.m_vecVelocity = dir * random->RandomFloat( 8.0f, 32.0f );
		newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 64.0f );

		newParticle.m_uchStartAlpha	= 255;
		newParticle.m_uchEndAlpha	= 0;

		newParticle.m_flRoll			= random->RandomFloat( 0, 360 );
		newParticle.m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );

		float colorRamp = random->RandomFloat( 0.5f, 1.25f );

		newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
		newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
		newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

		AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] );
	}

	//
	// Bullet hole capper
	//
	newParticle.m_Pos = offset;

	newParticle.m_flLifetime		= 0.0f;
	newParticle.m_flDieTime		= random->RandomFloat( 1.0f, 1.5f );

	Vector dir;
	dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
	dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
	dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );

	newParticle.m_uchStartSize	= random->RandomInt( 4, 8 );
	newParticle.m_uchEndSize		= newParticle.m_uchStartSize * 4.0f;

	newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f );
	newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f );

	newParticle.m_uchStartAlpha	= random->RandomInt( 100, 200 );
	newParticle.m_uchEndAlpha	= 0;

	newParticle.m_flRoll			= random->RandomFloat( 0, 360 );
	newParticle.m_flRollDelta	= random->RandomFloat( -2, 2 );

	float colorRamp = random->RandomFloat( 0.5f, 1.25f );

	newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
	newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
	newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

	AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );

#endif
}
static void CreateFleckParticles( const Vector& origin, const Vector &color, trace_t *trace, char materialType, int iScale )
{
	Vector	spawnOffset	= trace->endpos + ( trace->plane.normal * 1.0f );

	CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create( "FX_DebrisFlecks", spawnOffset, Vector(5,5,5) );

	if ( !fleckEmitter )
		return;

	// Handle increased scale
	float flMaxSpeed = FLECK_MAX_SPEED * iScale;
	float flAngularSpray = MAX( 0.2, FLECK_ANGULAR_SPRAY - ( (float)iScale * 0.2f) ); // More power makes the spray more controlled
	// Setup our collision information
	fleckEmitter->m_ParticleCollision.Setup( spawnOffset, &trace->plane.normal, flAngularSpray, FLECK_MIN_SPEED, flMaxSpeed, FLECK_GRAVITY, FLECK_DAMPEN );

	PMaterialHandle	*hMaterial;
	switch ( materialType )
	{
	case CHAR_TEX_WOOD:
		hMaterial = g_Mat_Fleck_Wood;
		break;
	case CHAR_TEX_CONCRETE:
	case CHAR_TEX_TILE:
	default:
		hMaterial = g_Mat_Fleck_Cement;
		break;
	}

	Vector	dir, end;

	float	colorRamp;

	float fScale = g_pParticleSystemMgr->ParticleThrottleScaling() * (float)iScale;
	int	numFlecks = (int)( 0.5f + fScale * (float)( random->RandomInt( 4, 16 ) ) );

	FleckParticle	*pFleckParticle;

	//Dump out flecks
	int i;
	for ( i = 0; i < numFlecks; i++ )
	{
		pFleckParticle = (FleckParticle *) fleckEmitter->AddParticle( sizeof(FleckParticle), hMaterial[random->RandomInt(0,1)], spawnOffset );

		if ( pFleckParticle == NULL )
			break;

		pFleckParticle->m_flLifetime	= 0.0f;
		pFleckParticle->m_flDieTime		= 3.0f;

		dir[0] = trace->plane.normal[0] + random->RandomFloat( -flAngularSpray, flAngularSpray );
		dir[1] = trace->plane.normal[1] + random->RandomFloat( -flAngularSpray, flAngularSpray );
		dir[2] = trace->plane.normal[2] + random->RandomFloat( -flAngularSpray, flAngularSpray );

		pFleckParticle->m_uchSize		= random->RandomInt( 1, 2 );

		pFleckParticle->m_vecVelocity	= dir * ( random->RandomFloat( FLECK_MIN_SPEED, flMaxSpeed) * ( 3 - pFleckParticle->m_uchSize ) );

		pFleckParticle->m_flRoll		= random->RandomFloat( 0, 360 );
		pFleckParticle->m_flRollDelta	= random->RandomFloat( 0, 360 );

		colorRamp = random->RandomFloat( 0.75f, 1.25f );

		pFleckParticle->m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
		pFleckParticle->m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
		pFleckParticle->m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &pos - 
//			&dir - 
//			type - 
//-----------------------------------------------------------------------------
void FX_GaussExplosion( const Vector &pos, const Vector &dir, int type )
{
	Vector	vDir;

	vDir[0] = dir[0] + random->RandomFloat( -1.0f, 1.0f );
	vDir[1] = dir[1] + random->RandomFloat( -1.0f, 1.0f );
	vDir[2] = dir[2] + random->RandomFloat( -1.0f, 1.0f );

	VectorNormalize( vDir );

	int i;

#if defined(_XBOX) || defined(_X360)

	//
	// XBox version
	//
	CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "FX_GaussExplosion" );
	if ( pSparkEmitter == NULL )
	{
		Assert(0);
		return;
	}

	if ( g_Material_Spark == NULL )
	{
		g_Material_Spark = pSparkEmitter->GetPMaterial( "effects/spark" );
	}

	pSparkEmitter->SetSortOrigin( pos );
	pSparkEmitter->m_ParticleCollision.SetGravity( 800.0f );
	pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN );
	pSparkEmitter->GetBinding().SetBBox( pos - Vector( 32, 32, 32 ), pos + Vector( 32, 32, 32 ) );

	int numSparks = random->RandomInt( 8, 16 );
	TrailParticle	*pParticle;
	
	// Dump out sparks
	for ( i = 0; i < numSparks; i++ )
	{
		pParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), g_Material_Spark, pos );

		if ( pParticle == NULL )
			return;

		pParticle->m_flLifetime	= 0.0f;

		vDir.Random( -0.6f, 0.6f );
		vDir += dir;
		VectorNormalize( vDir );
		
		pParticle->m_flWidth		= random->RandomFloat( 1.0f, 4.0f );
		pParticle->m_flLength		= random->RandomFloat( 0.01f, 0.1f );
		pParticle->m_flDieTime		= random->RandomFloat( 0.25f, 0.5f );
		
		pParticle->m_vecVelocity	= vDir * random->RandomFloat( 128, 512 );

		Color32Init( pParticle->m_color, 255, 255, 255, 255 );
	}

	// End cap
	SimpleParticle particle;

	particle.m_Pos = pos;
	particle.m_flLifetime = 0.0f;
	particle.m_flDieTime = 0.1f;
	particle.m_vecVelocity.Init();
	particle.m_flRoll = random->RandomInt( 0, 360 );
	particle.m_flRollDelta = 0.0f;
	particle.m_uchColor[0] = 255;
	particle.m_uchColor[1] = 255;
	particle.m_uchColor[2] = 255;
	particle.m_uchStartAlpha = 255;
	particle.m_uchEndAlpha = 255;
	particle.m_uchStartSize = random->RandomInt( 24, 32 );
	particle.m_uchEndSize = 0;

	AddSimpleParticle( &particle, ParticleMgr()->GetPMaterial( "effects/yellowflare" ) );

#else
	
	//
	// PC version
	//
	CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "FX_ElectricSpark" );

	if ( !pSparkEmitter )
	{
		Assert(0);
		return;
	}

	PMaterialHandle	hMaterial	= pSparkEmitter->GetPMaterial( "effects/spark" );

	pSparkEmitter->SetSortOrigin( pos );

	pSparkEmitter->m_ParticleCollision.SetGravity( 800.0f );
	pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN|bitsPARTICLE_TRAIL_COLLIDE );

	//Setup our collision information
	pSparkEmitter->m_ParticleCollision.Setup( pos, &vDir, 0.8f, 128, 512, 800, 0.3f );

	int numSparks = random->RandomInt( 16, 32 );
	TrailParticle	*pParticle;

	// Dump out sparks
	for ( i = 0; i < numSparks; i++ )
	{
		pParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), hMaterial, pos );

		if ( pParticle == NULL )
			return;

		pParticle->m_flLifetime	= 0.0f;

		vDir.Random( -0.6f, 0.6f );
		vDir += dir;
		VectorNormalize( vDir );

		pParticle->m_flWidth		= random->RandomFloat( 1.0f, 4.0f );
		pParticle->m_flLength		= random->RandomFloat( 0.01f, 0.1f );
		pParticle->m_flDieTime		= random->RandomFloat( 0.25f, 1.0f );

		pParticle->m_vecVelocity	= vDir * random->RandomFloat( 128, 512 );

		Color32Init( pParticle->m_color, 255, 255, 255, 255 );
	}


	FX_ElectricSpark( pos, 1, 1, &vDir );
#endif
}
Beispiel #29
0
//-----------------------------------------------------------------------------
// Purpose: Tesla effect
//-----------------------------------------------------------------------------
void C_EntityDissolve::BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset )
{
	Vector vecOrigin;
	QAngle vecAngles;
	MatrixGetColumn( hitboxToWorld, 3, vecOrigin );
	MatrixAngles( hitboxToWorld, vecAngles.Base() );
	C_BaseEntity *pEntity = GetMoveParent();

	// Make a couple of tries at it
	int iTries = -1;
	Vector vecForward;
	trace_t tr;
	do
	{
		iTries++;

		// Some beams are deliberatly aimed around the point, the rest are random.
		if ( !bRandom )
		{
			QAngle vecTemp = vecAngles;
			vecTemp[YAW] += flYawOffset;
			AngleVectors( vecTemp, &vecForward );

			// Randomly angle it up or down
			vecForward.z = RandomFloat( -1, 1 );
		}
		else
		{
			vecForward = RandomVector( -1, 1 );
		}

		UTIL_TraceLine( vecOrigin, vecOrigin + (vecForward * 192), MASK_SHOT, pEntity, COLLISION_GROUP_NONE, &tr );
	} while ( tr.fraction >= 1.0 && iTries < 3 );

	Vector vecEnd = tr.endpos - (vecForward * 8);

	// Only spark & glow if we hit something
	if ( tr.fraction < 1.0 )
	{
		if ( !EffectOccluded( tr.endpos ) )
		{
			// Move it towards the camera
			Vector vecFlash = tr.endpos;
			Vector vecForward;
			AngleVectors( MainViewAngles(), &vecForward );
			vecFlash -= (vecForward * 8);

			g_pEffects->EnergySplash( vecFlash, -vecForward, false );

			// End glow
			CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" );
			pSimple->SetSortOrigin( vecFlash );
			SimpleParticle *pParticle;
			pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/tesla_glow_noz" ), vecFlash );
			if ( pParticle != NULL )
			{
				pParticle->m_flLifetime = 0.0f;
				pParticle->m_flDieTime	= RandomFloat( 0.5, 1 );
				pParticle->m_vecVelocity = vec3_origin;
				Vector color( 1,1,1 );
				float  colorRamp = RandomFloat( 0.75f, 1.25f );
				pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
				pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
				pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
				pParticle->m_uchStartSize	= RandomFloat( 6,13 );
				pParticle->m_uchEndSize		= pParticle->m_uchStartSize - 2;
				pParticle->m_uchStartAlpha	= 255;
				pParticle->m_uchEndAlpha	= 10;
				pParticle->m_flRoll			= RandomFloat( 0,360 );
				pParticle->m_flRollDelta	= 0;
			}
		}
	}

	// Build the tesla
	FX_BuildTesla( pEntity, vecOrigin, tr.endpos );
}
//-----------------------------------------------------------------------------
// Purpose: Dust impact
// Input  : &origin - position
//			&tr - trace information
//-----------------------------------------------------------------------------
void FX_DustImpact( const Vector &origin, trace_t *tr, int iScale )
{
	if ( !fx_drawimpactdust.GetBool() )
		return;

#ifdef _XBOX

	//
	// XBox version
	//

	VPROF_BUDGET( "FX_DustImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	Vector	offset;
	float	spread = 0.2f;

	CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" );
	pSimple->SetSortOrigin( origin );
	pSimple->GetBinding().SetBBox( origin - ( Vector( 32, 32, 32 ) * iScale ), origin + ( Vector( 32, 32, 32 ) * iScale ) );

	Vector	color;
	float	colorRamp;
	GetColorForSurface( tr, &color );

	int i;
	SimpleParticle *pParticle;
	for ( i = 0; i < 4; i++ )
	{
		// Last puff is gritty (hides end)
		if ( i == 3 )
		{
			pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );
		}
		else
		{
			pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );
		}

		if ( pParticle != NULL )
		{
			pParticle->m_flLifetime = 0.0f;

			pParticle->m_vecVelocity.Random( -spread, spread );
			pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );

			VectorNormalize( pParticle->m_vecVelocity );

			float	fForce = random->RandomFloat( 250, 500 ) * i;

			// scaled
			pParticle->m_vecVelocity *= fForce * iScale;

			colorRamp = random->RandomFloat( 0.75f, 1.25f );

			pParticle->m_uchColor[0]	= min( 1.0f, color[0] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[1]	= min( 1.0f, color[1] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[2]	= min( 1.0f, color[2] * colorRamp ) * 255.0f;

			// scaled
			pParticle->m_uchStartSize	= iScale * random->RandomInt( 3, 4 ) * (i+1);

			// scaled
			pParticle->m_uchEndSize		= iScale * pParticle->m_uchStartSize * 4;

			pParticle->m_uchStartAlpha	= random->RandomInt( 32, 255 );
			pParticle->m_uchEndAlpha	= 0;

			pParticle->m_flRoll			= random->RandomInt( 0, 360 );

			if ( i == 3 )
			{
				pParticle->m_flRollDelta = random->RandomFloat( -0.1f, 0.1f );
				pParticle->m_flDieTime	= 0.5f;
			}
			else
			{
				pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f );
				pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );
			}
		}
	}			

	//Impact hit
	pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff, origin );

	if ( pParticle != NULL )
	{
		offset = origin;
		offset[0] += random->RandomFloat( -8.0f, 8.0f );
		offset[1] += random->RandomFloat( -8.0f, 8.0f );

		pParticle->m_flLifetime = 0.0f;
		pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );

		pParticle->m_vecVelocity.Init();

		colorRamp = random->RandomFloat( 0.75f, 1.25f );
		pParticle->m_uchColor[0]	= min( 1.0f, color[0] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[1]	= min( 1.0f, color[1] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[2]	= min( 1.0f, color[2] * colorRamp ) * 255.0f;

		pParticle->m_uchStartSize	= random->RandomInt( 4, 8 );
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4;

		pParticle->m_uchStartAlpha	= random->RandomInt( 32, 64 );
		pParticle->m_uchEndAlpha	= 0;

		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
		pParticle->m_flRollDelta	= random->RandomFloat( -1.0f, 1.0f );
	}

#else
	FX_DustImpact( origin, tr, (float)iScale );
#endif // _XBOX
}