Exemplo n.º 1
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 );
}
Exemplo n.º 2
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_WaterExplosionEffect::CreateMisc( void )
{
	Vector	offset;
	float	colorRamp;
	
	int i;
	float	flScale = 2.0f;

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

#ifndef _XBOX

	int		numDrops = 32;
	float	length = 0.1f;
	Vector	vForward, vRight, vUp;
	Vector	offDir;

	TrailParticle	*tParticle;

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

	if ( !sparkEmitter )
		return;

	sparkEmitter->SetSortOrigin( m_vecWaterSurface );
	sparkEmitter->m_ParticleCollision.SetGravity( 800.0f );
	sparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN );
	sparkEmitter->SetVelocityDampen( 2.0f );

	//Dump out drops
	for ( i = 0; i < numDrops; i++ )
	{
		offset = m_vecWaterSurface;
		offset[0] += random->RandomFloat( -16.0f, 16.0f ) * flScale;
		offset[1] += random->RandomFloat( -16.0f, 16.0f ) * flScale;

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

		if ( tParticle == NULL )
			break;

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

		offDir = Vector(0,0,1) + RandomVector( -1.0f, 1.0f );

		tParticle->m_vecVelocity = offDir * random->RandomFloat( 50.0f * flScale * 2.0f, 100.0f * flScale * 2.0f );
		tParticle->m_vecVelocity[2] += random->RandomFloat( 32.0f, 128.0f ) * flScale;

		tParticle->m_flWidth		= clamp( random->RandomFloat( 1.0f, 3.0f ) * flScale, 0.1f, 4.0f );
		tParticle->m_flLength		= random->RandomFloat( length*0.25f, length )/* * flScale*/;

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

		FloatToColor32( tParticle->m_color, min( 1.0f, m_vecColor[0] * colorRamp ), min( 1.0f, m_vecColor[1] * colorRamp ), min( 1.0f, m_vecColor[2] * colorRamp ), m_flLuminosity );
	}

	//Dump out drops
	for ( i = 0; i < 4; i++ )
	{
		offset = m_vecWaterSurface;
		offset[0] += random->RandomFloat( -16.0f, 16.0f ) * flScale;
		offset[1] += random->RandomFloat( -16.0f, 16.0f ) * flScale;

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

		if ( tParticle == NULL )
			break;

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

		offDir = Vector(0,0,1) + RandomVector( -0.2f, 0.2f );

		tParticle->m_vecVelocity = offDir * random->RandomFloat( 50 * flScale * 3.0f, 100 * flScale * 3.0f );
		tParticle->m_vecVelocity[2] += random->RandomFloat( 32.0f, 128.0f ) * flScale;

		tParticle->m_flWidth		= clamp( random->RandomFloat( 2.0f, 3.0f ) * flScale, 0.1f, 4.0f );
		tParticle->m_flLength		= random->RandomFloat( length*0.25f, length )/* * flScale*/;

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

		FloatToColor32( tParticle->m_color, min( 1.0f, m_vecColor[0] * colorRamp ), min( 1.0f, m_vecColor[1] * colorRamp ), min( 1.0f, m_vecColor[2] * colorRamp ), m_flLuminosity );
	}

#endif

	CSmartPtr<CSplashParticle> pSimple = CSplashParticle::Create( "splish" );
	pSimple->SetSortOrigin( m_vecWaterSurface );
	pSimple->SetClipHeight( m_vecWaterSurface.z );
	pSimple->GetBinding().SetBBox( m_vecWaterSurface-(Vector(32.0f, 32.0f, 32.0f)*flScale), m_vecWaterSurface+(Vector(32.0f, 32.0f, 32.0f)*flScale) );

	SimpleParticle	*pParticle;

	for ( i = 0; i < 16; i++ )
	{
		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial, m_vecWaterSurface );

		if ( pParticle == NULL )
			break;

		pParticle->m_flLifetime = 0.0f;
		pParticle->m_flDieTime	= 2.0f;	//NOTENOTE: We use a clip plane to realistically control our lifespan

		pParticle->m_vecVelocity.Random( -0.2f, 0.2f );
		pParticle->m_vecVelocity += ( Vector( 0, 0, random->RandomFloat( 4.0f, 6.0f ) ) );
		
		VectorNormalize( pParticle->m_vecVelocity );

		pParticle->m_vecVelocity *= 50 * flScale * (8-i);
		
		colorRamp = random->RandomFloat( 0.75f, 1.25f );

		pParticle->m_uchColor[0]	= min( 1.0f, m_vecColor[0] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[1]	= min( 1.0f, m_vecColor[1] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[2]	= min( 1.0f, m_vecColor[2] * colorRamp ) * 255.0f;
		
		pParticle->m_uchStartSize	= 24 * flScale * RemapValClamped( i, 7, 0, 1, 0.5f );
		pParticle->m_uchEndSize		= min( 255, pParticle->m_uchStartSize * 2 );
		
		pParticle->m_uchStartAlpha	= RemapValClamped( i, 7, 0, 255, 32 ) * m_flLuminosity;
		pParticle->m_uchEndAlpha	= 0;
		
		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
		pParticle->m_flRollDelta	= random->RandomFloat( -4.0f, 4.0f );
	}
}
Exemplo n.º 3
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 );
}
Exemplo n.º 4
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : origin - 
//			normal - 
//-----------------------------------------------------------------------------
void FX_ConcussiveExplosion(Vector &origin, Vector &normal)
{
    VPROF_BUDGET("FX_ConcussiveExplosion", VPROF_BUDGETGROUP_PARTICLE_RENDERING);
    Vector	offset = origin + (normal * 2.0f);
    Vector	dir;
    int		i;

    // 
    // Smoke
    //

    CSmartPtr<CSimpleEmitter> pSmokeEmitter = CSimpleEmitter::Create("FX_ConcussiveExplosion 1");
    pSmokeEmitter->SetSortOrigin(offset);

    //Quick moving sprites
    for (i = 0; i < 16; i++)
    {
        SimpleParticle *pParticle = (SimpleParticle *) pSmokeEmitter->AddParticle(sizeof(SimpleParticle), g_Mat_DustPuff[1], offset);

        if (pParticle == NULL)
            return;

        pParticle->m_flLifetime = 0.0f;
        pParticle->m_flDieTime = random->RandomFloat(0.2f, 0.4f);
        pParticle->m_uchStartSize = random->RandomInt(4, 8);
        pParticle->m_uchEndSize = random->RandomInt(32, 64);

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

        pParticle->m_vecVelocity = dir * random->RandomFloat(64.0f, 128.0f);
        pParticle->m_uchStartAlpha = random->RandomInt(64, 128);
        pParticle->m_uchEndAlpha = 0;
        pParticle->m_flRoll = random->RandomFloat(180, 360);
        pParticle->m_flRollDelta = random->RandomFloat(-4, 4);

        int colorRamp = random->RandomFloat(235, 255);
        pParticle->m_uchColor[0] = colorRamp;
        pParticle->m_uchColor[1] = colorRamp;
        pParticle->m_uchColor[2] = colorRamp;
    }

    //Slow lingering sprites
    for (i = 0; i < 2; i++)
    {
        SimpleParticle *pParticle = (SimpleParticle *) pSmokeEmitter->AddParticle(sizeof(SimpleParticle), g_Mat_DustPuff[1], offset);
        if (pParticle == NULL)
            return;

        pParticle->m_flLifetime = 0.0f;
        pParticle->m_flDieTime = random->RandomFloat(1.0f, 2.0f);
        pParticle->m_uchStartSize = random->RandomInt(32, 64);
        pParticle->m_uchEndSize = random->RandomInt(100, 128);

        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);

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

        pParticle->m_uchStartAlpha = random->RandomInt(32, 64);
        pParticle->m_uchEndAlpha = 0;
        pParticle->m_flRoll = random->RandomFloat(180, 360);
        pParticle->m_flRollDelta = random->RandomFloat(-1, 1);

        int colorRamp = random->RandomFloat(235, 255);
        pParticle->m_uchColor[0] = colorRamp;
        pParticle->m_uchColor[1] = colorRamp;
        pParticle->m_uchColor[2] = colorRamp;
    }


    //	
    // Quick sphere
    //

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

    pSimple->SetSortOrigin(offset);

    SimpleParticle *pParticle = (SimpleParticle *) pSimple->AddParticle(sizeof(SimpleParticle), pSimple->GetPMaterial("effects/blueflare1"), offset);

    if (pParticle)
    {
        pParticle->m_flLifetime = 0.0f;
        pParticle->m_flDieTime = 0.1f;
        pParticle->m_vecVelocity.Init();
        pParticle->m_flRoll = random->RandomFloat(180, 360);
        pParticle->m_flRollDelta = random->RandomFloat(-1, 1);

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

        pParticle->m_uchStartAlpha = 255;
        pParticle->m_uchEndAlpha = 0;

        pParticle->m_uchStartSize = 16;
        pParticle->m_uchEndSize = 64;
    }

    pParticle = (SimpleParticle *) pSimple->AddParticle(sizeof(SimpleParticle), pSimple->GetPMaterial("effects/blueflare1"), offset);

    if (pParticle)
    {
        pParticle->m_flLifetime = 0.0f;
        pParticle->m_flDieTime = 0.2f;
        pParticle->m_vecVelocity.Init();
        pParticle->m_flRoll = random->RandomFloat(180, 360);
        pParticle->m_flRollDelta = random->RandomFloat(-1, 1);
        pParticle->m_uchColor[0] = pParticle->m_uchColor[1] = pParticle->m_uchColor[2] = 32;

        pParticle->m_uchStartAlpha = 64;
        pParticle->m_uchEndAlpha = 0;

        pParticle->m_uchStartSize = 64;
        pParticle->m_uchEndSize = 128;
    }


    //
    // Dlight
    //

    dlight_t *dl = effects->CL_AllocDlight(0);

    dl->origin = offset;
    dl->color.r = dl->color.g = dl->color.b = 64;
    dl->radius = random->RandomFloat(128, 256);
    dl->die = gpGlobals->curtime + 0.1;


    //
    // Moving lines
    //

    TrailParticle	*pTrailParticle;
    CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create("FX_ConcussiveExplosion 3");
    PMaterialHandle hMaterial;
    int				numSparks;

    if (pSparkEmitter.IsValid())
    {
        hMaterial = pSparkEmitter->GetPMaterial("effects/blueflare1");

        pSparkEmitter->SetSortOrigin(offset);
        pSparkEmitter->m_ParticleCollision.SetGravity(0.0f);

        numSparks = random->RandomInt(16, 32);

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

            if (pTrailParticle == NULL)
                return;

            pTrailParticle->m_flLifetime = 0.0f;

            dir.Random(-1.0f, 1.0f);

            pTrailParticle->m_flWidth = random->RandomFloat(1.0f, 2.0f);
            pTrailParticle->m_flLength = random->RandomFloat(0.01f, 0.1f);
            pTrailParticle->m_flDieTime = random->RandomFloat(0.1f, 0.2f);

            pTrailParticle->m_vecVelocity = dir * random->RandomFloat(800, 1000);

            float colorRamp = random->RandomFloat(0.75f, 1.0f);
            FloatToColor32(pTrailParticle->m_color, colorRamp, colorRamp, 1.0f, 1.0f);
        }
    }

    //Moving particles
    CSmartPtr<CTrailParticles> pCollisionEmitter = CTrailParticles::Create("FX_ConcussiveExplosion 4");

    if (pCollisionEmitter.IsValid())
    {
        //Setup our collision information
        pCollisionEmitter->Setup((Vector &) offset,
            NULL,
            SPARK_ELECTRIC_SPREAD,
            SPARK_ELECTRIC_MINSPEED * 6,
            SPARK_ELECTRIC_MAXSPEED * 6,
            -400,
            SPARK_ELECTRIC_DAMPEN,
            bitsPARTICLE_TRAIL_FADE);

        pCollisionEmitter->SetSortOrigin(offset);

        numSparks = random->RandomInt(8, 16);
        hMaterial = pCollisionEmitter->GetPMaterial("effects/blueflare1");

        //Dump out sparks
        for (i = 0; i < numSparks; i++)
        {
            pTrailParticle = (TrailParticle *) pCollisionEmitter->AddParticle(sizeof(TrailParticle), hMaterial, offset);

            if (pTrailParticle == NULL)
                return;

            pTrailParticle->m_flLifetime = 0.0f;

            dir.Random(-1.0f, 1.0f);
            dir[2] = random->RandomFloat(0.0f, 0.75f);

            pTrailParticle->m_flWidth = random->RandomFloat(1.0f, 2.0f);
            pTrailParticle->m_flLength = random->RandomFloat(0.01f, 0.1f);
            pTrailParticle->m_flDieTime = random->RandomFloat(0.2f, 1.0f);

            pTrailParticle->m_vecVelocity = dir * random->RandomFloat(128, 512);

            float colorRamp = random->RandomFloat(0.75f, 1.0f);
            FloatToColor32(pTrailParticle->m_color, colorRamp, colorRamp, 1.0f, 1.0f);
        }
    }
}