//========= Copyright 1996-2005, 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_MATERIAL( "particle/particle_sphere" ) CLIENTEFFECT_REGISTER_END() #ifdef _XBOX PMaterialHandle g_Fleck_Wood[2] = { NULL, NULL }; PMaterialHandle g_Fleck_Cement[2] = { NULL, NULL }; PMaterialHandle g_DustPuff = NULL; PMaterialHandle g_DustPuff2 = NULL; #endif // _XBOX //----------------------------------------------------------------------------- // 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 ); if ( !fleckEmitter ) return; fleckEmitter->SetSortOrigin( spawnOffset ); // 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[2]; switch ( materialType ) { case CHAR_TEX_WOOD: hMaterial[0] = fleckEmitter->GetPMaterial( "effects/fleck_wood1" ); hMaterial[1] = fleckEmitter->GetPMaterial( "effects/fleck_wood2" ); break; case CHAR_TEX_CONCRETE: case CHAR_TEX_TILE: default: hMaterial[0] = fleckEmitter->GetPMaterial( "effects/fleck_cement1" ); hMaterial[1] = fleckEmitter->GetPMaterial( "effects/fleck_cement2" ); break; } Vector dir, end; float colorRamp; int numFlecks = random->RandomInt( 4, 16 ) * iScale; 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 ); #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 ); if ( g_DustPuff == NULL ) { g_DustPuff = ParticleMgr()->GetPMaterial( "particle/particle_smokegrenade" ); } if ( g_DustPuff2 == NULL ) { g_DustPuff2 = ParticleMgr()->GetPMaterial( "effects/blood" ); } int i; SimpleParticle *pParticle; for ( i = 0; i < 4; i++ ) { if ( i == 3 ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff2, origin ); } else { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff, 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; PMaterialHandle smokeMaterial = ParticleMgr()->GetPMaterial( "particle/particle_smokegrenade" ); 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, smokeMaterial ); } PMaterialHandle bloodMaterial = ParticleMgr()->GetPMaterial( "effects/blood" ); 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, bloodMaterial ); } // // 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, smokeMaterial ); #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 ); PMaterialHandle hMaterial1 = pGlassEmitter->GetPMaterial( "effects/fleck_glass1" ); PMaterialHandle hMaterial2 = pGlassEmitter->GetPMaterial( "effects/fleck_glass2" ); 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; if ( random->RandomInt( 0 , 1 ) ) { pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), hMaterial1, pos ); } else { pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), hMaterial2, 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; PMaterialHandle bloodMaterial = ParticleMgr()->GetPMaterial( "effects/blood" ); 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, bloodMaterial ); } // // 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, ParticleMgr()->GetPMaterial( "particle/particle_smokegrenade" ) ); } 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 ) { 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 ); PMaterialHandle antlionFleckMaterial[2]; antlionFleckMaterial[0] = fleckEmitter->GetPMaterial( "effects/fleck_antlion1" ); antlionFleckMaterial[1] = fleckEmitter->GetPMaterial( "effects/fleck_antlion2" ); 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), antlionFleckMaterial[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 ); PMaterialHandle smokeMaterial = dustEmitter->GetPMaterial( "particle/particle_smokegrenade" ); for ( i = 0; i < 4; i++ ) { pParticle = (SimpleParticle *) dustEmitter->AddParticle( sizeof(SimpleParticle), smokeMaterial, 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; } // Blood spurt FX_BugBlood( spawnOffset, shotDir, vWorldMins, vWorldMaxs ); 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 ); PMaterialHandle bloodMaterial = pSimple->GetPMaterial( "effects/blood" ); int i; for ( i = 0; i < NUM_BUG_BLOOD; i++ ) { SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), bloodMaterial, 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 ); } bloodMaterial = pSimple->GetPMaterial( "effects/blood2" ); for ( i = 0; i < NUM_BUG_BLOOD2; i++ ) { SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), bloodMaterial, 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 ), bloodMaterial, 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 ); PMaterialHandle bloodMaterial = pSimple->GetPMaterial( "effects/blood" ); int i; for ( i = 0; i < 2; i++ ) { SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), bloodMaterial, 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 ); } bloodMaterial = pSimple->GetPMaterial( "effects/blood2" ); for ( i = 0; i < 2; i++ ) { SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), bloodMaterial, 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 ) { #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 ); if ( g_DustPuff == NULL ) { g_DustPuff = ParticleMgr()->GetPMaterial( "particle/particle_smokegrenade" ); } if ( g_DustPuff2 == NULL ) { g_DustPuff2 = ParticleMgr()->GetPMaterial( "effects/blood" ); } 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_DustPuff2, origin ); } else { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff, 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 // // 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 ); SimpleParticle *pParticle; Vector color; float colorRamp; GetColorForSurface( tr, &color ); PMaterialHandle smokeMaterial = pSimple->GetPMaterial( "particle/particle_smokegrenade" ); int i; for ( i = 0; i < 4; i++ ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), smokeMaterial, 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; // 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 ); pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f ); } } PMaterialHandle bloodMaterial = pSimple->GetPMaterial( "effects/blood" ); //Dust specs for ( i = 0; i < 4; i++ ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), bloodMaterial, 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 ) * i; 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 ) * (i+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 < 4; i++ ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), smokeMaterial, 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 ); } } #endif // _XBOX } #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; #ifdef _XBOX // // 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 ); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 5821 | Knut Wikstrom |
Added Valve Source code. This is NOT to be commited to other than new code from Valve. |