diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/client/c_impact_effects.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/client/c_impact_effects.cpp')
| -rw-r--r-- | mp/src/game/client/c_impact_effects.cpp | 1431 |
1 files changed, 1431 insertions, 0 deletions
diff --git a/mp/src/game/client/c_impact_effects.cpp b/mp/src/game/client/c_impact_effects.cpp new file mode 100644 index 00000000..43d0b740 --- /dev/null +++ b/mp/src/game/client/c_impact_effects.cpp @@ -0,0 +1,1431 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "fx.h"
+#include "fx_sparks.h"
+#include "clienteffectprecachesystem.h"
+#include "particle_simple3d.h"
+#include "decals.h"
+#include "engine/IEngineSound.h"
+#include "c_te_particlesystem.h"
+#include "engine/ivmodelinfo.h"
+#include "particles_ez.h"
+#include "c_impact_effects.h"
+#include "engine/IStaticPropMgr.h"
+#include "tier0/vprof.h"
+#include "c_te_effect_dispatch.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//Precahce the effects
+CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectImpacts )
+CLIENTEFFECT_MATERIAL( "effects/fleck_cement1" )
+CLIENTEFFECT_MATERIAL( "effects/fleck_cement2" )
+CLIENTEFFECT_MATERIAL( "effects/fleck_antlion1" )
+CLIENTEFFECT_MATERIAL( "effects/fleck_antlion2" )
+CLIENTEFFECT_MATERIAL( "effects/fleck_wood1" )
+CLIENTEFFECT_MATERIAL( "effects/fleck_wood2" )
+CLIENTEFFECT_MATERIAL( "effects/blood" )
+CLIENTEFFECT_MATERIAL( "effects/blood2" )
+CLIENTEFFECT_MATERIAL( "sprites/bloodspray" )
+CLIENTEFFECT_MATERIAL( "particle/particle_noisesphere" )
+CLIENTEFFECT_REGISTER_END()
+
+// Cached handles to commonly used materials
+PMaterialHandle g_Mat_Fleck_Wood[2] = { NULL, NULL };
+PMaterialHandle g_Mat_Fleck_Cement[2] = { NULL, NULL };
+PMaterialHandle g_Mat_Fleck_Antlion[2] = { NULL, NULL };
+PMaterialHandle g_Mat_Fleck_Glass[2] = { NULL, NULL };
+PMaterialHandle g_Mat_Fleck_Tile[2] = { NULL, NULL };
+PMaterialHandle g_Mat_DustPuff[2] = { NULL, NULL };
+PMaterialHandle g_Mat_BloodPuff[2] = { NULL, NULL };
+PMaterialHandle g_Mat_SMG_Muzzleflash[4] = { NULL, NULL, NULL, NULL };
+PMaterialHandle g_Mat_Combine_Muzzleflash[3] = { NULL, NULL, NULL };
+
+static ConVar fx_drawimpactdebris( "fx_drawimpactdebris", "1", FCVAR_DEVELOPMENTONLY, "Draw impact debris effects." );
+static ConVar fx_drawimpactdust( "fx_drawimpactdust", "1", FCVAR_DEVELOPMENTONLY, "Draw impact dust effects." );
+
+void FX_CacheMaterialHandles( void )
+{
+ g_Mat_Fleck_Wood[0] = ParticleMgr()->GetPMaterial( "effects/fleck_wood1" );
+ g_Mat_Fleck_Wood[1] = ParticleMgr()->GetPMaterial( "effects/fleck_wood2" );
+
+ g_Mat_Fleck_Cement[0] = ParticleMgr()->GetPMaterial( "effects/fleck_cement1");
+ g_Mat_Fleck_Cement[1] = ParticleMgr()->GetPMaterial( "effects/fleck_cement2" );
+
+ g_Mat_Fleck_Antlion[0] = ParticleMgr()->GetPMaterial( "effects/fleck_antlion1" );
+ g_Mat_Fleck_Antlion[1] = ParticleMgr()->GetPMaterial( "effects/fleck_antlion2" );
+
+ g_Mat_Fleck_Glass[0] = ParticleMgr()->GetPMaterial( "effects/fleck_glass1" );
+ g_Mat_Fleck_Glass[1] = ParticleMgr()->GetPMaterial( "effects/fleck_glass2" );
+
+ g_Mat_Fleck_Tile[0] = ParticleMgr()->GetPMaterial( "effects/fleck_tile1" );
+ g_Mat_Fleck_Tile[1] = ParticleMgr()->GetPMaterial( "effects/fleck_tile2" );
+
+ g_Mat_DustPuff[0] = ParticleMgr()->GetPMaterial( "particle/particle_smokegrenade" );
+ g_Mat_DustPuff[1] = ParticleMgr()->GetPMaterial( "particle/particle_noisesphere" );
+
+ g_Mat_BloodPuff[0] = ParticleMgr()->GetPMaterial( "effects/blood" );
+ g_Mat_BloodPuff[1] = ParticleMgr()->GetPMaterial( "effects/blood2" );
+
+#ifndef TF_CLIENT_DLL
+ g_Mat_SMG_Muzzleflash[0] = ParticleMgr()->GetPMaterial( "effects/muzzleflash1" );
+ g_Mat_SMG_Muzzleflash[1] = ParticleMgr()->GetPMaterial( "effects/muzzleflash2" );
+ g_Mat_SMG_Muzzleflash[2] = ParticleMgr()->GetPMaterial( "effects/muzzleflash3" );
+ g_Mat_SMG_Muzzleflash[3] = ParticleMgr()->GetPMaterial( "effects/muzzleflash4" );
+#ifndef CSTRIKE_DLL
+ g_Mat_Combine_Muzzleflash[0] = ParticleMgr()->GetPMaterial( "effects/combinemuzzle1" );
+ g_Mat_Combine_Muzzleflash[1] = ParticleMgr()->GetPMaterial( "effects/combinemuzzle2" );
+ g_Mat_Combine_Muzzleflash[2] = ParticleMgr()->GetPMaterial( "effects/strider_muzzle" );
+#endif
+#endif
+}
+
+extern PMaterialHandle g_Material_Spark;
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the color given trace information
+// Input : *trace - trace to get results for
+// *color - return color, gamma corrected (0.0f to 1.0f)
+//-----------------------------------------------------------------------------
+void GetColorForSurface( trace_t *trace, Vector *color )
+{
+ Vector baseColor, diffuseColor;
+ Vector end = trace->startpos + ( ( Vector )trace->endpos - ( Vector )trace->startpos ) * 1.1f;
+
+ if ( trace->DidHitWorld() )
+ {
+ if ( trace->hitbox == 0 )
+ {
+ // If we hit the world, then ask the world for the fleck color
+ engine->TraceLineMaterialAndLighting( trace->startpos, end, diffuseColor, baseColor );
+ }
+ else
+ {
+ // In this case we hit a static prop.
+ staticpropmgr->GetStaticPropMaterialColorAndLighting( trace, trace->hitbox - 1, diffuseColor, baseColor );
+ }
+ }
+ else
+ {
+ // In this case, we hit an entity. Find out the model associated with it
+ C_BaseEntity *pEnt = trace->m_pEnt;
+ if ( !pEnt )
+ {
+ Msg("Couldn't find surface in GetColorForSurface()\n");
+ color->x = 255;
+ color->y = 255;
+ color->z = 255;
+ return;
+ }
+
+ ICollideable *pCollide = pEnt->GetCollideable();
+ int modelIndex = pCollide->GetCollisionModelIndex();
+ model_t* pModel = const_cast<model_t*>(modelinfo->GetModel( modelIndex ));
+
+ // Ask the model info about what we need to know
+ modelinfo->GetModelMaterialColorAndLighting( pModel, pCollide->GetCollisionOrigin(),
+ pCollide->GetCollisionAngles(), trace, diffuseColor, baseColor );
+ }
+
+ //Get final light value
+ color->x = pow( diffuseColor[0], 1.0f/2.2f ) * baseColor[0];
+ color->y = pow( diffuseColor[1], 1.0f/2.2f ) * baseColor[1];
+ color->z = pow( diffuseColor[2], 1.0f/2.2f ) * baseColor[2];
+}
+
+
+//-----------------------------------------------------------------------------
+// This does the actual debris flecks
+//-----------------------------------------------------------------------------
+#define FLECK_MIN_SPEED 64.0f
+#define FLECK_MAX_SPEED 128.0f
+#define FLECK_GRAVITY 800.0f
+#define FLECK_DAMPEN 0.3f
+#define FLECK_ANGULAR_SPRAY 0.6f
+
+#ifndef _XBOX
+
+//
+// PC ONLY!
+//
+
+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;
+ }
+}
+
+#endif // _XBOX
+
+//-----------------------------------------------------------------------------
+// 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
+}
+
+#define GLASS_SHARD_MIN_LIFE 2.5f
+#define GLASS_SHARD_MAX_LIFE 5.0f
+#define GLASS_SHARD_NOISE 0.8
+#define GLASS_SHARD_GRAVITY 800
+#define GLASS_SHARD_DAMPING 0.3
+#define GLASS_SHARD_MIN_SPEED 1
+#define GLASS_SHARD_MAX_SPEED 300
+
+//-----------------------------------------------------------------------------
+// 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] );
+}
+
+void GlassImpactCallback( const CEffectData &data )
+{
+ FX_GlassImpact( data.m_vOrigin, data.m_vNormal );
+}
+
+DECLARE_CLIENT_EFFECT( "GlassImpact", GlassImpactCallback );
+
+//-----------------------------------------------------------------------------
+// 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: Spurt out bug blood
+// Input : &pos -
+// &dir -
+//-----------------------------------------------------------------------------
+#if defined( _XBOX )
+#define NUM_BUG_BLOOD 16
+#define NUM_BUG_BLOOD2 8
+#define NUM_BUG_SPLATS 8
+#else
+#define NUM_BUG_BLOOD 32
+#define NUM_BUG_BLOOD2 16
+#define NUM_BUG_SPLATS 16
+#endif
+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: 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 );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// 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
+}
+
+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 );
+ }
+ }
+}
+
+#ifdef _XBOX
+extern PMaterialHandle g_Material_Spark;
+#endif // _XBOX
+
+//-----------------------------------------------------------------------------
+// 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
+}
+
+class C_TEGaussExplosion : public C_TEParticleSystem
+{
+public:
+ DECLARE_CLASS( C_TEGaussExplosion, C_TEParticleSystem );
+ DECLARE_CLIENTCLASS();
+
+ C_TEGaussExplosion();
+ virtual ~C_TEGaussExplosion();
+
+public:
+ virtual void PostDataUpdate( DataUpdateType_t updateType );
+ virtual bool ShouldDraw() { return true; }
+
+public:
+
+ int m_nType;
+ Vector m_vecDirection;
+};
+
+IMPLEMENT_CLIENTCLASS_EVENT_DT( C_TEGaussExplosion, DT_TEGaussExplosion, CTEGaussExplosion )
+ RecvPropInt(RECVINFO(m_nType)),
+ RecvPropVector(RECVINFO(m_vecDirection)),
+END_RECV_TABLE()
+
+//==================================================
+// C_TEGaussExplosion
+//==================================================
+
+C_TEGaussExplosion::C_TEGaussExplosion()
+{
+}
+
+C_TEGaussExplosion::~C_TEGaussExplosion()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : bNewEntity - whether or not to start a new entity
+//-----------------------------------------------------------------------------
+void C_TEGaussExplosion::PostDataUpdate( DataUpdateType_t updateType )
+{
+ FX_GaussExplosion( m_vecOrigin, m_vecDirection, m_nType );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : filter -
+// delay -
+// &pos -
+// &dir -
+// type -
+//-----------------------------------------------------------------------------
+void TE_GaussExplosion( IRecipientFilter& filter, float delay, const Vector &pos, const Vector &dir, int type )
+{
+ FX_GaussExplosion( pos, dir, type );
+}
+
|