Ejemplo n.º 1
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);
    }
}
//-----------------------------------------------------------------------------
// 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
}
Ejemplo n.º 3
0
//-----------------------------------------------------------------------------
// 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;

    //
    // 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);
}
Ejemplo n.º 4
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_BaseExplosionEffect::CreateDebris( void )
{
	if ( m_fFlags & TE_EXPLFLAG_NOPARTICLES )
		return;

	//
	// Sparks
	//

	CSmartPtr<CTrailParticles> pSparkEmitter	= CTrailParticles::Create( "CreateDebris 1" );
	if ( pSparkEmitter == NULL )
	{
		assert(0);
		return;
	}

	if ( m_Material_FireCloud == NULL )
	{
		m_Material_FireCloud = pSparkEmitter->GetPMaterial( "effects/fire_cloud2" );
	}

	pSparkEmitter->SetSortOrigin( m_vecOrigin );
	
	pSparkEmitter->m_ParticleCollision.SetGravity( 200.0f );
	pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN );
	pSparkEmitter->SetVelocityDampen( 8.0f );
	
	// Set our bbox, don't auto-calculate it!
	pSparkEmitter->GetBinding().SetBBox( m_vecOrigin - Vector( 128, 128, 128 ), m_vecOrigin + Vector( 128, 128, 128 ) );

#ifndef _XBOX
	int		numSparks = random->RandomInt( 8, 16 );
#else
	int		numSparks = random->RandomInt( 2, 4 );
#endif

	Vector	dir;
	float	spread = 1.0f;
	TrailParticle	*tParticle;

	// Dump out sparks
	int i;
	for ( i = 0; i < numSparks; i++ )
	{
		tParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), m_Material_FireCloud, m_vecOrigin );

		if ( tParticle == NULL )
			break;

		tParticle->m_flLifetime	= 0.0f;
		tParticle->m_flDieTime	= random->RandomFloat( 0.1f, 0.15f );

		dir.Random( -spread, spread );
		dir += m_vecDirection;
		VectorNormalize( dir );
		
		tParticle->m_flWidth		= random->RandomFloat( 2.0f, 16.0f );
		tParticle->m_flLength		= random->RandomFloat( 0.05f, 0.1f );
		
		tParticle->m_vecVelocity	= dir * random->RandomFloat( 1500, 2500 );

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

#ifndef _XBOX
	//
	// Chunks
	//

	Vector	offset;
	CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create( "CreateDebris 2", m_vecOrigin, Vector(128,128,128) );
	if ( !fleckEmitter )
		return;

	// Setup our collision information
	fleckEmitter->m_ParticleCollision.Setup( m_vecOrigin, &m_vecDirection, 0.9f, 512, 1024, 800, 0.5f );
	

#ifdef _XBOX
	int	numFlecks = random->RandomInt( 8, 16 );
#else	
	int	numFlecks = random->RandomInt( 16, 32 );
#endif // _XBOX


	// Dump out flecks
	for ( i = 0; i < numFlecks; i++ )
	{
		offset = m_vecOrigin + ( m_vecDirection * 16.0f );

		offset[0] += random->RandomFloat( -8.0f, 8.0f );
		offset[1] += random->RandomFloat( -8.0f, 8.0f );
		offset[2] += random->RandomFloat( -8.0f, 8.0f );

		FleckParticle *pParticle = (FleckParticle *) fleckEmitter->AddParticle( sizeof(FleckParticle), g_Mat_Fleck_Cement[random->RandomInt(0,1)], offset );

		if ( pParticle == NULL )
			break;

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

		pParticle->m_uchSize		= random->RandomInt( 1, 3 );

		VectorNormalize( dir );

		float	fForce = ( random->RandomFloat( 64, 256 ) * ( 4 - pParticle->m_uchSize ) );

		float	fDev = ScaleForceByDeviation( dir, m_vecDirection, 0.8f );

		pParticle->m_vecVelocity = dir * ( fForce * ( 16.0f * (fDev*fDev*0.5f) ) );

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

		float colorRamp = random->RandomFloat( 0.5f, 1.5f );
		pParticle->m_uchColor[0] = min( 1.0f, 0.25f*colorRamp )*255.0f;
		pParticle->m_uchColor[1] = min( 1.0f, 0.25f*colorRamp )*255.0f;
		pParticle->m_uchColor[2] = min( 1.0f, 0.25f*colorRamp )*255.0f;
	}
#endif // !_XBOX
}
Ejemplo n.º 5
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &origin - 
//			&normal - 
//			scale - 
//-----------------------------------------------------------------------------
void FX_AirboatGunImpact( const Vector &origin, const Vector &normal, float scale )
{
#ifdef _XBOX

	Vector offset = origin + ( normal * 1.0f );

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

	if ( sparkEmitter == NULL )
		return;

	//Setup our information
	sparkEmitter->SetSortOrigin( offset );
	sparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN );
	sparkEmitter->SetVelocityDampen( 8.0f );
	sparkEmitter->SetGravity( 800.0f );
	sparkEmitter->SetCollisionDamped( 0.25f );
	sparkEmitter->GetBinding().SetBBox( offset - Vector( 32, 32, 32 ), offset + Vector( 32, 32, 32 ) );

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

	TrailParticle	*pParticle;
	PMaterialHandle	hMaterial = sparkEmitter->GetPMaterial( "effects/spark" );
	Vector			dir;

	float	length	= 0.1f;

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

		if ( pParticle == NULL )
			return;

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

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

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

		VectorNormalize( dir );

		pParticle->m_flWidth		= random->RandomFloat( 1.0f, 4.0f );
		pParticle->m_flLength		= random->RandomFloat( length*0.25f, length );

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

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

#else

	// Normal metal spark
	FX_MetalSpark( origin, normal, normal, (int) scale );

#endif // _XBOX

	// Add a quad to highlite the hit point
	FX_AddQuad( origin, 
				normal, 
				random->RandomFloat( 16, 32 ),
				random->RandomFloat( 32, 48 ),
				0.75f, 
				1.0f,
				0.0f,
				0.4f,
				random->RandomInt( 0, 360 ), 
				0,
				Vector( 1.0f, 1.0f, 1.0f ), 
				0.05f, 
				"effects/combinemuzzle2_nocull",
				(FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CBasePlasmaProjectile::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
{
	m_pParticleMgr = pParticleMgr;
	m_pParticleMgr->AddEffect( &m_ParticleEffect, this );

	PMaterialHandle	HeadMaterial, TrailMaterial;

	// Load the projectile material
	if ( GetTeamNumber() == TEAM_HUMANS )
	{
		HeadMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/human_tracers/human_sparksprite_A1" );
		TrailMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/human_tracers/human_sparktracer_A_" );
	}
	else
	{
		HeadMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/alien_tracers/alien_pbsprite_A1" );
		TrailMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/alien_tracers/alien_pbtracer_A_" );
	}

	// Create the head & trail
	m_pHeadParticle = (SimpleParticle *)m_ParticleEffect.AddParticle(sizeof(SimpleParticle), HeadMaterial );
	m_pTrailParticle = (TrailParticle *)m_ParticleEffect.AddParticle(sizeof(TrailParticle), TrailMaterial );
	if ( !m_pHeadParticle || !m_pTrailParticle )
		return;

	// 3rd person particles are larger
	bool bFirst = (GetOwnerEntity() == C_BasePlayer::GetLocalPlayer());

	m_pHeadParticle->m_Pos = GetRenderOrigin();
	m_pHeadParticle->m_uchColor[0] = 255;
	m_pHeadParticle->m_uchColor[1] = 255;
	m_pHeadParticle->m_uchColor[2] = 255;
	if ( bFirst )
	{
		m_pHeadParticle->m_uchStartSize = 6;
	}
	else
	{
		m_pHeadParticle->m_uchStartSize = shot_head_size.GetInt();
	}
	m_pHeadParticle->m_uchEndSize	= m_pHeadParticle->m_uchStartSize;
	m_pHeadParticle->m_uchStartAlpha = 255;
	m_pHeadParticle->m_uchEndAlpha = 255;
	m_pHeadParticle->m_flRoll = 0;
	m_pHeadParticle->m_flRollDelta = 10;
	m_pHeadParticle->m_iFlags = 0;

	m_pTrailParticle->m_flLifetime = 0;
	m_pTrailParticle->m_Pos = GetRenderOrigin();
	if ( bFirst )
	{
		m_pTrailParticle->m_flWidth = 25;
		m_pTrailParticle->m_flLength = 140;
	}
	else
	{
		m_pTrailParticle->m_flWidth = shot_width.GetFloat();
		m_pTrailParticle->m_flLength = shot_length.GetFloat();
	}
	Color32Init( m_pTrailParticle->m_color, 255, 255, 255, 255 );

	m_flNextSparkEffect = gpGlobals->curtime + RandomFloat( 0.05, 0.4 );
}
Ejemplo n.º 7
0
void FX_MicroExplosion(Vector &position, Vector &normal)
{
    VPROF_BUDGET("FX_MicroExplosion", VPROF_BUDGETGROUP_PARTICLE_RENDERING);
    Vector	offset = position + (normal * 2.0f);

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

    if (!sparkEmitter)
        return;

    sparkEmitter->SetSortOrigin(offset);

    //Setup our collision information
    sparkEmitter->Setup(offset,
        &normal,
        MICRO_EXPLOSION_SPREAD,
        MICRO_EXPLOSION_MINSPEED,
        MICRO_EXPLOSION_MAXSPEED,
        MICRO_EXPLOSION_GRAVITY,
        MICRO_EXPLOSION_DAMPEN,
        bitsPARTICLE_TRAIL_VELOCITY_DAMPEN);

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

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

    TrailParticle	*pParticle;
    Vector	dir, vOfs;
    float	length = 0.2f;

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

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

            float	ramp = ((float) i / (float) numSparks);

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

            pParticle->m_flWidth = random->RandomFloat(5.0f, 10.0f);
            pParticle->m_flLength = (length*((1.0f - ramp)*(1.0f - ramp)*0.5f));
            pParticle->m_flDieTime = 0.2f;
            pParticle->m_vecVelocity = dir * random->RandomFloat(MICRO_EXPLOSION_MINSPEED*(1.5f - ramp), MICRO_EXPLOSION_MAXSPEED*(1.5f - ramp));

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

    //
    // Filler
    //

    CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create("FX_MicroExplosion 2");
    pSimple->SetSortOrigin(offset);

    SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle(sizeof(SimpleParticle), pSimple->GetPMaterial("sprites/rico1"), offset);

    if (sParticle)
    {
        sParticle->m_flLifetime = 0.0f;
        sParticle->m_flDieTime = 0.3f;

        sParticle->m_vecVelocity.Init();

        sParticle->m_uchColor[0] = 255;
        sParticle->m_uchColor[1] = 255;
        sParticle->m_uchColor[2] = 255;
        sParticle->m_uchStartAlpha = random->RandomInt(128, 255);
        sParticle->m_uchEndAlpha = 0;
        sParticle->m_uchStartSize = random->RandomInt(12, 16);
        sParticle->m_uchEndSize = sParticle->m_uchStartSize;
        sParticle->m_flRoll = random->RandomInt(0, 360);
        sParticle->m_flRollDelta = 0.0f;
    }
}
Ejemplo n.º 8
0
void FX_Sparks(const Vector &pos, int nMagnitude, int nTrailLength, const Vector &vecDir, float flWidth, float flMinSpeed, float flMaxSpeed, char *pSparkMaterial)
{
    VPROF_BUDGET("FX_Sparks", VPROF_BUDGETGROUP_PARTICLE_RENDERING);
    CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create("FX_Sparks 1");

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

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

        hMaterial = g_Material_Spark;
    }

    //Setup our collision information
    pSparkEmitter->Setup((Vector &) pos,
        NULL,
        SPARK_SPREAD,
        flMinSpeed,
        flMaxSpeed,
        SPARK_GRAVITY,
        SPARK_DAMPEN,
        bitsPARTICLE_TRAIL_VELOCITY_DAMPEN);

    pSparkEmitter->SetSortOrigin(pos);

    //
    // Big sparks.
    //
    Vector	dir;
    int		numSparks = nMagnitude * nMagnitude * random->RandomFloat(2, 4);

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

        if (pParticle == NULL)
            return;

        pParticle->m_flLifetime = 0.0f;
        pParticle->m_flDieTime = nMagnitude * random->RandomFloat(1.0f, 2.0f);

        float	spreadOfs = random->RandomFloat(0.0f, 2.0f);
        dir[0] = vecDir[0] + random->RandomFloat(-(SPARK_SPREAD*spreadOfs), (SPARK_SPREAD*spreadOfs));
        dir[1] = vecDir[1] + random->RandomFloat(-(SPARK_SPREAD*spreadOfs), (SPARK_SPREAD*spreadOfs));
        dir[2] = vecDir[2] + random->RandomFloat(-(SPARK_SPREAD*spreadOfs), (SPARK_SPREAD*spreadOfs));
        pParticle->m_vecVelocity = dir * random->RandomFloat((flMinSpeed*(2.0f - spreadOfs)), (flMaxSpeed*(2.0f - spreadOfs)));

        pParticle->m_flWidth = flWidth + random->RandomFloat(0.0f, 0.5f);
        pParticle->m_flLength = nTrailLength * random->RandomFloat(0.02, 0.05f);
        Color32Init(pParticle->m_color, 255, 255, 255, 255);
    }

    //
    // Little sparks
    //
    CSmartPtr<CTrailParticles> pSparkEmitter2 = CTrailParticles::Create("FX_ElectricSpark 2");

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

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

        hMaterial = g_Material_Spark;
    }

    pSparkEmitter2->SetSortOrigin(pos);

    pSparkEmitter2->m_ParticleCollision.SetGravity(400.0f);
    pSparkEmitter2->SetFlag(bitsPARTICLE_TRAIL_VELOCITY_DAMPEN);

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

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

        if (pParticle == NULL)
            return;

        pParticle->m_flLifetime = 0.0f;

        dir.Random(-1.0f, 1.0f);
        dir += vecDir;
        VectorNormalize(dir);

        pParticle->m_flWidth = (flWidth * 0.25) + random->RandomFloat(0.0f, 0.5f);
        pParticle->m_flLength = nTrailLength * random->RandomFloat(0.02f, 0.03f);
        pParticle->m_flDieTime = nMagnitude * random->RandomFloat(0.3f, 0.5f);

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

        Color32Init(pParticle->m_color, 255, 255, 255, 255);
    }
}
Ejemplo n.º 9
0
void FX_MetalSpark(const Vector &position, const Vector &direction, const Vector &surfaceNormal, int iScale)
{
    VPROF_BUDGET("FX_MetalSpark", VPROF_BUDGETGROUP_PARTICLE_RENDERING);

    if (!fx_drawmetalspark.GetBool())
        return;

    //
    // Emitted particles
    //

    Vector offset = position + (surfaceNormal * 1.0f);

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

    if (sparkEmitter == NULL)
        return;

    //Setup our information
    sparkEmitter->SetSortOrigin(offset);
    sparkEmitter->SetFlag(bitsPARTICLE_TRAIL_VELOCITY_DAMPEN);
    sparkEmitter->SetVelocityDampen(8.0f);
    sparkEmitter->SetGravity(METAL_SPARK_GRAVITY);
    sparkEmitter->SetCollisionDamped(METAL_SPARK_DAMPEN);
    sparkEmitter->GetBinding().SetBBox(offset - Vector(32, 32, 32), offset + Vector(32, 32, 32));

    int	numSparks = random->RandomInt(4, 8) * (iScale * 2);
    numSparks = (int) (0.5f + (float) numSparks * g_pParticleSystemMgr->ParticleThrottleScaling());

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

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

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

        if (iScale > 1 && i % 3 == 0)
        {
            // Every third spark goes flying far if we're having a big batch of sparks.
            pParticle->m_flDieTime = random->RandomFloat(0.15f, 0.25f);
        }
        else
        {
            pParticle->m_flDieTime = random->RandomFloat(0.05f, 0.1f);
        }

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

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

        VectorNormalize(dir);

        pParticle->m_flWidth = random->RandomFloat(1.0f, 4.0f);
        pParticle->m_flLength = random->RandomFloat(length*0.25f, length);

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

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

    //
    // Impact point glow
    //

    FXQuadData_t data;

    data.SetMaterial("effects/yellowflare");
    data.SetColor(1.0f, 1.0f, 1.0f);
    data.SetOrigin(offset);
    data.SetNormal(surfaceNormal);
    data.SetAlpha(1.0f, 0.0f);
    data.SetLifeTime(0.1f);
    data.SetYaw(random->RandomInt(0, 360));

    int scale = random->RandomInt(24, 28);
    data.SetScale(scale, 0);

    FX_AddQuad(data);
}
Ejemplo n.º 10
0
void FX_ElectricSpark(const Vector &pos, int nMagnitude, int nTrailLength, const Vector *vecDir)
{
    VPROF_BUDGET("FX_ElectricSpark", VPROF_BUDGETGROUP_PARTICLE_RENDERING);
    CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create("FX_ElectricSpark 1");

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

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

    //Setup our collision information
    pSparkEmitter->Setup((Vector &) pos,
        NULL,
        SPARK_ELECTRIC_SPREAD,
        SPARK_ELECTRIC_MINSPEED,
        SPARK_ELECTRIC_MAXSPEED,
        SPARK_ELECTRIC_GRAVITY,
        SPARK_ELECTRIC_DAMPEN,
        bitsPARTICLE_TRAIL_VELOCITY_DAMPEN);

    pSparkEmitter->SetSortOrigin(pos);

    //
    // Big sparks.
    //
    Vector	dir;
    int		numSparks = nMagnitude * nMagnitude * random->RandomFloat(2, 4);

    int i;
    TrailParticle	*pParticle;
    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;
        pParticle->m_flDieTime = nMagnitude * random->RandomFloat(1.0f, 2.0f);

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

        if (vecDir)
        {
            dir += 2 * (*vecDir);
            VectorNormalize(dir);
        }

        pParticle->m_flWidth = random->RandomFloat(2.0f, 5.0f);
        pParticle->m_flLength = nTrailLength * random->RandomFloat(0.02, 0.05f);

        pParticle->m_vecVelocity = dir * random->RandomFloat(SPARK_ELECTRIC_MINSPEED, SPARK_ELECTRIC_MAXSPEED);

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

    //
    // Little sparks
    //

    CSmartPtr<CTrailParticles> pSparkEmitter2	= CTrailParticles::Create( "FX_ElectricSpark 2" );

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

    pSparkEmitter2->SetSortOrigin( pos );

    pSparkEmitter2->m_ParticleCollision.SetGravity( 400.0f );
    pSparkEmitter2->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN );

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

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

        if ( pParticle == NULL )
            return;

        pParticle->m_flLifetime = 0.0f;

        dir.Random(-1.0f, 1.0f);
        if (vecDir)
        {
            dir += *vecDir;
            VectorNormalize(dir);
        }

        pParticle->m_flWidth = random->RandomFloat(2.0f, 4.0f);
        pParticle->m_flLength = nTrailLength * random->RandomFloat(0.02f, 0.03f);
        pParticle->m_flDieTime = nMagnitude * random->RandomFloat(0.1f, 0.2f);

        pParticle->m_vecVelocity = dir * random->RandomFloat(128, 256);

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

    //
    // Caps
    //
    CSmartPtr<CSimpleGlowEmitter> pSimple = CSimpleGlowEmitter::Create("FX_ElectricSpark 3", pos, gpGlobals->curtime + 0.2);

    // NOTE: None of these will render unless the effect is visible!
    //
    // Inner glow
    //
    SimpleParticle *sParticle;

    sParticle = (SimpleParticle *) pSimple->AddParticle(sizeof(SimpleParticle), pSimple->GetPMaterial("effects/yellowflare_noz"), pos);

    if (sParticle == NULL)
        return;

    sParticle->m_flLifetime = 0.0f;
    sParticle->m_flDieTime = 0.2f;

    sParticle->m_vecVelocity.Init();

    sParticle->m_uchColor[0] = 255;
    sParticle->m_uchColor[1] = 255;
    sParticle->m_uchColor[2] = 255;
    sParticle->m_uchStartAlpha = 255;
    sParticle->m_uchEndAlpha = 255;
    sParticle->m_uchStartSize = nMagnitude * random->RandomInt(4, 8);
    sParticle->m_uchEndSize = 0;
    sParticle->m_flRoll = random->RandomInt(0, 360);
    sParticle->m_flRollDelta = 0.0f;

    sParticle = (SimpleParticle *) pSimple->AddParticle(sizeof(SimpleParticle), pSimple->GetPMaterial("effects/yellowflare_noz"), pos);

    if (sParticle == NULL)
        return;

    sParticle->m_flLifetime = 0.0f;
    sParticle->m_flDieTime = 0.2f;

    sParticle->m_vecVelocity.Init();

    float	fColor = random->RandomInt(32, 64);
    sParticle->m_uchColor[0] = fColor;
    sParticle->m_uchColor[1] = fColor;
    sParticle->m_uchColor[2] = fColor;
    sParticle->m_uchStartAlpha = fColor;
    sParticle->m_uchEndAlpha = 0;
    sParticle->m_uchStartSize = nMagnitude * random->RandomInt(32, 64);
    sParticle->m_uchEndSize = 0;
    sParticle->m_flRoll = random->RandomInt(0, 360);
    sParticle->m_flRollDelta = random->RandomFloat(-1.0f, 1.0f);

    //
    // Smoke
    //
    Vector	sOffs;

    sOffs[0] = pos[0] + random->RandomFloat(-4.0f, 4.0f);
    sOffs[1] = pos[1] + random->RandomFloat(-4.0f, 4.0f);
    sOffs[2] = pos[2];

    sParticle = (SimpleParticle *) pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_DustPuff[1], sOffs);

    if (sParticle == NULL)
        return;

    sParticle->m_flLifetime = 0.0f;
    sParticle->m_flDieTime = 1.0f;

    sParticle->m_vecVelocity.Init();

    sParticle->m_vecVelocity[2] = 16.0f;

    sParticle->m_vecVelocity[0] = random->RandomFloat(-16.0f, 16.0f);
    sParticle->m_vecVelocity[1] = random->RandomFloat(-16.0f, 16.0f);

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

    //
    // Dlight
    //

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

    dl->origin	= pos;
    dl->color.r = dl->color.g = dl->color.b = 250;
    dl->radius	= random->RandomFloat(16,32);
    dl->die		= gpGlobals->curtime + 0.001;
    */

}
Ejemplo n.º 11
0
void FX_Explosion(Vector& origin, Vector& normal, char materialType)
{
    VPROF_BUDGET("FX_Explosion", VPROF_BUDGETGROUP_PARTICLE_RENDERING);
    Vector	offset = origin + (normal * 2.0f);

    CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create("FX_Explosion 1");
    if (!pSparkEmitter)
        return;

    // Get color data from our hit point
    IMaterial	*pTraceMaterial;
    Vector		diffuseColor, baseColor;
    pTraceMaterial = engine->TraceLineMaterialAndLighting(origin, normal * -16.0f, diffuseColor, baseColor);
    // Get final light value
    float r = pow(diffuseColor[0], 1.0f / 2.2f) * baseColor[0];
    float g = pow(diffuseColor[1], 1.0f / 2.2f) * baseColor[1];
    float b = pow(diffuseColor[2], 1.0f / 2.2f) * baseColor[2];

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

    // Setup our collision information
    pSparkEmitter->Setup(offset,
        &normal,
        EXPLOSION_SPREAD,
        EXPLOSION_MINSPEED,
        EXPLOSION_MAXSPEED,
        EXPLOSION_GRAVITY,
        EXPLOSION_DAMPEN,
        bitsPARTICLE_TRAIL_VELOCITY_DAMPEN);

    pSparkEmitter->SetSortOrigin(offset);

    Vector	dir;
    int		numSparks = random->RandomInt(8, 16);

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

        if (pParticle == NULL)
            break;

        pParticle->m_flLifetime = 0.0f;

        pParticle->m_flWidth = random->RandomFloat(5.0f, 10.0f);
        pParticle->m_flLength = random->RandomFloat(0.05, 0.1f);
        pParticle->m_flDieTime = random->RandomFloat(1.0f, 2.0f);

        dir[0] = normal[0] + random->RandomFloat(-EXPLOSION_SPREAD, EXPLOSION_SPREAD);
        dir[1] = normal[1] + random->RandomFloat(-EXPLOSION_SPREAD, EXPLOSION_SPREAD);
        dir[2] = normal[2] + random->RandomFloat(-EXPLOSION_SPREAD, EXPLOSION_SPREAD);
        pParticle->m_vecVelocity = dir * random->RandomFloat(EXPLOSION_MINSPEED, EXPLOSION_MAXSPEED);

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


    // Chunks o'dirt
    // Only create dirt chunks on concrete/world
    if (materialType == 'C' || materialType == 'W')
    {
        CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create("FX_Explosion 10", offset, Vector(5, 5, 5));
        if (!fleckEmitter)
            return;

        // Setup our collision information
        fleckEmitter->m_ParticleCollision.Setup(offset, &normal, EXPLOSION_FLECK_ANGULAR_SPRAY, EXPLOSION_FLECK_MIN_SPEED, EXPLOSION_FLECK_MAX_SPEED, EXPLOSION_FLECK_GRAVITY, EXPLOSION_FLECK_DAMPEN);

        PMaterialHandle	*hMaterialArray;

        switch (materialType)
        {
        case 'C':
        case 'c':
        default:
            hMaterialArray = g_Mat_Fleck_Cement;
            break;
        }

        int	numFlecks = random->RandomInt(48, 64);
        // Dump out flecks
        for (i = 0; i < numFlecks; i++)
        {
            FleckParticle *pParticle = (FleckParticle *) fleckEmitter->AddParticle(sizeof(FleckParticle), hMaterialArray[random->RandomInt(0, 1)], offset);

            if (pParticle == NULL)
                break;

            pParticle->m_flLifetime = 0.0f;
            pParticle->m_flDieTime = 3.0f;
            dir[0] = normal[0] + random->RandomFloat(-EXPLOSION_FLECK_ANGULAR_SPRAY, EXPLOSION_FLECK_ANGULAR_SPRAY);
            dir[1] = normal[1] + random->RandomFloat(-EXPLOSION_FLECK_ANGULAR_SPRAY, EXPLOSION_FLECK_ANGULAR_SPRAY);
            dir[2] = normal[2] + random->RandomFloat(-EXPLOSION_FLECK_ANGULAR_SPRAY, EXPLOSION_FLECK_ANGULAR_SPRAY);
            pParticle->m_uchSize = random->RandomInt(2, 6);
            pParticle->m_vecVelocity = dir * (random->RandomFloat(EXPLOSION_FLECK_MIN_SPEED, EXPLOSION_FLECK_MAX_SPEED) * (7 - pParticle->m_uchSize));
            pParticle->m_flRoll = random->RandomFloat(0, 360);
            pParticle->m_flRollDelta = random->RandomFloat(0, 360);

            float colorRamp = random->RandomFloat(0.75f, 1.5f);
            pParticle->m_uchColor[0] = MIN(1.0f, r*colorRamp)*255.0f;
            pParticle->m_uchColor[1] = MIN(1.0f, g*colorRamp)*255.0f;
            pParticle->m_uchColor[2] = MIN(1.0f, b*colorRamp)*255.0f;
        }
    }

    // Large sphere bursts
    CSmartPtr<CSimpleEmitter> pSimpleEmitter = CSimpleEmitter::Create("FX_Explosion 1");
    PMaterialHandle	hSphereMaterial = g_Mat_DustPuff[1];
    Vector vecBurstOrigin = offset + normal * 8.0;
    pSimpleEmitter->SetSortOrigin(vecBurstOrigin);
    SimpleParticle *pSphereParticle = (SimpleParticle *) pSimpleEmitter->AddParticle(sizeof(SimpleParticle), hSphereMaterial, vecBurstOrigin);
    if (pSphereParticle)
    {
        pSphereParticle->m_flLifetime = 0.0f;
        pSphereParticle->m_flDieTime = 0.3f;
        pSphereParticle->m_uchStartAlpha = 150.0;
        pSphereParticle->m_uchEndAlpha = 64.0;
        pSphereParticle->m_uchStartSize = 0.0;
        pSphereParticle->m_uchEndSize = 255.0;
        pSphereParticle->m_vecVelocity = Vector(0, 0, 0);

        float colorRamp = random->RandomFloat(0.75f, 1.5f);
        pSphereParticle->m_uchColor[0] = MIN(1.0f, r*colorRamp)*255.0f;
        pSphereParticle->m_uchColor[1] = MIN(1.0f, g*colorRamp)*255.0f;
        pSphereParticle->m_uchColor[2] = MIN(1.0f, b*colorRamp)*255.0f;
    }

    // Throw some smoke balls out around the normal
    int numBalls = 12;
    Vector vecRight, vecForward, vecUp;
    QAngle vecAngles;
    VectorAngles(normal, vecAngles);
    AngleVectors(vecAngles, NULL, &vecRight, &vecUp);
    for (i = 0; i < numBalls; i++)
    {
        SimpleParticle *pParticle = (SimpleParticle *) pSimpleEmitter->AddParticle(sizeof(SimpleParticle), hSphereMaterial, vecBurstOrigin);
        if (pParticle)
        {
            pParticle->m_flLifetime = 0.0f;
            pParticle->m_flDieTime = 0.25f;
            pParticle->m_uchStartAlpha = 128.0;
            pParticle->m_uchEndAlpha = 64.0;
            pParticle->m_uchStartSize = 16.0;
            pParticle->m_uchEndSize = 64.0;

            float flAngle = ((float) i * M_PI * 2) / numBalls;
            float x = cos(flAngle);
            float y = sin(flAngle);
            pParticle->m_vecVelocity = (vecRight*x + vecUp*y) * 1024.0;

            float colorRamp = random->RandomFloat(0.75f, 1.5f);
            pParticle->m_uchColor[0] = MIN(1.0f, r*colorRamp)*255.0f;
            pParticle->m_uchColor[1] = MIN(1.0f, g*colorRamp)*255.0f;
            pParticle->m_uchColor[2] = MIN(1.0f, b*colorRamp)*255.0f;
        }
    }

    // Create a couple of big, floating smoke clouds
    CSmartPtr<CSimpleEmitter> pSmokeEmitter = CSimpleEmitter::Create("FX_Explosion 2");
    pSmokeEmitter->SetSortOrigin(offset);
    for (i = 0; i < 2; i++)
    {
        SimpleParticle *pParticle = (SimpleParticle *) pSmokeEmitter->AddParticle(sizeof(SimpleParticle), g_Mat_DustPuff[1], offset);
        if (pParticle == NULL)
            break;

        pParticle->m_flLifetime = 0.0f;
        pParticle->m_flDieTime = random->RandomFloat(2.0f, 3.0f);
        pParticle->m_uchStartSize = 64;
        pParticle->m_uchEndSize = 255;
        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(2.0f, 24.0f)*(i + 1);
        pParticle->m_uchStartAlpha = 160;
        pParticle->m_uchEndAlpha = 0;
        pParticle->m_flRoll = random->RandomFloat(180, 360);
        pParticle->m_flRollDelta = random->RandomFloat(-1, 1);

        float colorRamp = random->RandomFloat(0.5f, 1.25f);
        pParticle->m_uchColor[0] = MIN(1.0f, r*colorRamp)*255.0f;
        pParticle->m_uchColor[1] = MIN(1.0f, g*colorRamp)*255.0f;
        pParticle->m_uchColor[2] = MIN(1.0f, b*colorRamp)*255.0f;
    }
}