//----------------------------------------------------------------------------- // Spew out dust! //----------------------------------------------------------------------------- void FX_Dust( const Vector &vecOrigin, const Vector &vecDirection, float flSize, float flSpeed ) { VPROF_BUDGET( "FX_Dust", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); int numPuffs = (flSize*0.5f); if ( numPuffs < 1 ) numPuffs = 1; if ( numPuffs > 32 ) numPuffs = 32; float speed = flSpeed * 0.1f; if ( speed < 0 ) speed = 1.0f; if (speed > 48.0f ) speed = 48.0f; //FIXME: Better sampling area Vector offset = vecOrigin + ( vecDirection * flSize ); //Find area ambient light color and use it to tint smoke Vector worldLight = WorldGetLightForPoint( offset, true ); // Throw puffs SimpleParticle particle; for ( int i = 0; i < numPuffs; i++ ) { offset.Random( -(flSize*0.25f), flSize*0.25f ); offset += vecOrigin + ( vecDirection * flSize ); particle.m_Pos = offset; particle.m_flLifetime = 0.0f; particle.m_flDieTime = random->RandomFloat( 0.4f, 1.0f ); particle.m_vecVelocity = vecDirection * random->RandomFloat( speed*0.5f, speed ) * i; particle.m_vecVelocity[2] = 0.0f; int color = random->RandomInt( 48, 64 ); particle.m_uchColor[0] = (color+16) + ( worldLight[0] * (float) color ); particle.m_uchColor[1] = (color+8) + ( worldLight[1] * (float) color ); particle.m_uchColor[2] = color + ( worldLight[2] * (float) color ); particle.m_uchStartAlpha= random->RandomInt( 64, 128 ); particle.m_uchEndAlpha = 0; particle.m_uchStartSize = random->RandomInt( 2, 8 ); particle.m_uchEndSize = random->RandomInt( 24, 48 ); particle.m_flRoll = random->RandomInt( 0, 360 ); particle.m_flRollDelta = random->RandomFloat( -0.5f, 0.5f ); AddSimpleParticle( &particle, g_Mat_DustPuff[random->RandomInt(0,1)] ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void FX_GlassImpact( const Vector &pos, const Vector &normal ) { VPROF_BUDGET( "FX_GlassImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "FX_GlassImpact" ); pGlassEmitter->SetSortOrigin( pos ); Vector vecColor; engine->ComputeLighting( pos, NULL, true, vecColor ); // HACK: Blend a little toward white to match the materials... VectorLerp( vecColor, Vector( 1, 1, 1 ), 0.3, vecColor ); float flShardSize = random->RandomFloat( 2.0f, 6.0f ); unsigned char color[3] = { 200, 200, 210 }; // --------------------- // Create glass shards // ---------------------- int numShards = random->RandomInt( 2, 4 ); for ( int i = 0; i < numShards; i++ ) { Particle3D *pParticle; pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Glass[random->RandomInt(0,1)], pos ); if ( pParticle ) { pParticle->m_flLifeRemaining = random->RandomFloat(GLASS_SHARD_MIN_LIFE,GLASS_SHARD_MAX_LIFE); pParticle->m_vecVelocity[0] = ( normal[0] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED ); pParticle->m_vecVelocity[1] = ( normal[1] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED ); pParticle->m_vecVelocity[2] = ( normal[2] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED ); pParticle->m_uchSize = flShardSize + random->RandomFloat(-0.5*flShardSize,0.5*flShardSize); pParticle->m_vAngles = RandomAngle( 0, 360 ); pParticle->m_flAngSpeed = random->RandomFloat(-800,800); pParticle->m_uchFrontColor[0] = (byte)(color[0] * vecColor.x); pParticle->m_uchFrontColor[1] = (byte)(color[1] * vecColor.y); pParticle->m_uchFrontColor[2] = (byte)(color[2] * vecColor.z); pParticle->m_uchBackColor[0] = (byte)(color[0] * vecColor.x); pParticle->m_uchBackColor[1] = (byte)(color[1] * vecColor.y); pParticle->m_uchBackColor[2] = (byte)(color[2] * vecColor.z); } } pGlassEmitter->m_ParticleCollision.Setup( pos, &normal, GLASS_SHARD_NOISE, GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED, GLASS_SHARD_GRAVITY, GLASS_SHARD_DAMPING ); color[0] = 64; color[1] = 64; color[2] = 92; // --------------------------- // Dust // --------------------------- Vector dir; Vector offset = pos + ( normal * 2.0f ); float colorRamp; SimpleParticle newParticle; for ( int i = 0; i < 4; i++ ) { newParticle.m_Pos = offset; newParticle.m_flLifetime= 0.0f; newParticle.m_flDieTime = random->RandomFloat( 0.1f, 0.25f ); dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f ); newParticle.m_uchStartSize = random->RandomInt( 1, 4 ); newParticle.m_uchEndSize = newParticle.m_uchStartSize * 8; newParticle.m_vecVelocity = dir * random->RandomFloat( 8.0f, 16.0f )*(i+1); newParticle.m_vecVelocity[2] -= random->RandomFloat( 16.0f, 32.0f )*(i+1); newParticle.m_uchStartAlpha = random->RandomInt( 128, 255 ); newParticle.m_uchEndAlpha = 0; newParticle.m_flRoll = random->RandomFloat( 0, 360 ); newParticle.m_flRollDelta = random->RandomFloat( -1, 1 ); colorRamp = random->RandomFloat( 0.5f, 1.25f ); newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f; newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f; newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f; AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] ); } // // Bullet hole capper // newParticle.m_Pos = offset; newParticle.m_flLifetime = 0.0f; newParticle.m_flDieTime = random->RandomFloat( 1.0f, 1.5f ); dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f ); newParticle.m_uchStartSize = random->RandomInt( 4, 8 ); newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4.0f; newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 8.0f ); newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f ); newParticle.m_uchStartAlpha = random->RandomInt( 32, 64 ); newParticle.m_uchEndAlpha = 0; newParticle.m_flRoll = random->RandomFloat( 0, 360 ); newParticle.m_flRollDelta = random->RandomFloat( -2, 2 ); colorRamp = random->RandomFloat( 0.5f, 1.25f ); newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f; newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f; newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f; AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] ); }
//----------------------------------------------------------------------------- // Purpose: Debris flecks caused by impacts // Input : origin - start // *trace - trace information // *materialName - material hit // materialType - type of material hit //----------------------------------------------------------------------------- void FX_DebrisFlecks( const Vector& origin, trace_t *tr, char materialType, int iScale, bool bNoFlecks ) { VPROF_BUDGET( "FX_DebrisFlecks", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); if ( !fx_drawimpactdebris.GetBool() ) return; #ifdef _XBOX // // XBox version // Vector offset; float spread = 0.2f; CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" ); pSimple->SetSortOrigin( origin ); // Lock the bbox pSimple->GetBinding().SetBBox( origin - ( Vector( 16, 16, 16 ) * iScale ), origin + ( Vector( 16, 16, 16 ) * iScale ) ); // Get the color of the surface we've impacted Vector color; float colorRamp; GetColorForSurface( tr, &color ); int i; SimpleParticle *pParticle; for ( i = 0; i < 4; i++ ) { if ( i == 3 ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin ); } else { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin ); } if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 250, 500 ) * i * 0.5f; // scaled pParticle->m_vecVelocity *= fForce * iScale; // Ramp the color colorRamp = random->RandomFloat( 0.5f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; // scaled pParticle->m_uchStartSize = (iScale*0.5f) * random->RandomInt( 3, 4 ) * (i+1); // scaled pParticle->m_uchEndSize = (iScale*0.5f) * pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomInt( 200, 255 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f ); } } // Covers the impact spot with flecks pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff2, origin ); if ( pParticle != NULL ) { offset = origin; offset[0] += random->RandomFloat( -8.0f, 8.0f ); offset[1] += random->RandomFloat( -8.0f, 8.0f ); pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); spread = 1.0f; pParticle->m_vecVelocity.Init(); colorRamp = random->RandomFloat( 0.5f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = random->RandomInt( 4, 8 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomInt( 64, 128 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -0.1f, 0.1f ); } #else // // PC version // Vector color; GetColorForSurface( tr, &color ); if ( !bNoFlecks ) { CreateFleckParticles( origin, color, tr, materialType, iScale ); } // // Dust trail // Vector offset = tr->endpos + ( tr->plane.normal * 2.0f ); SimpleParticle newParticle; int i; for ( i = 0; i < 2; i++ ) { newParticle.m_Pos = offset; newParticle.m_flLifetime = 0.0f; newParticle.m_flDieTime = 1.0f; Vector dir; dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f ); newParticle.m_uchStartSize = random->RandomInt( 2, 4 ) * iScale; newParticle.m_uchEndSize = newParticle.m_uchStartSize * 8 * iScale; newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f )*(i+1); newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 32.0f )*(i+1); newParticle.m_uchStartAlpha = random->RandomInt( 100, 200 ); newParticle.m_uchEndAlpha = 0; newParticle.m_flRoll = random->RandomFloat( 0, 360 ); newParticle.m_flRollDelta = random->RandomFloat( -1, 1 ); float colorRamp = random->RandomFloat( 0.5f, 1.25f ); newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f; newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f; newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f; AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] ); } for ( i = 0; i < 4; i++ ) { newParticle.m_Pos = offset; newParticle.m_flLifetime = 0.0f; newParticle.m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); Vector dir; dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f ); newParticle.m_uchStartSize = random->RandomInt( 1, 4 ); newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4; newParticle.m_vecVelocity = dir * random->RandomFloat( 8.0f, 32.0f ); newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 64.0f ); newParticle.m_uchStartAlpha = 255; newParticle.m_uchEndAlpha = 0; newParticle.m_flRoll = random->RandomFloat( 0, 360 ); newParticle.m_flRollDelta = random->RandomFloat( -2.0f, 2.0f ); float colorRamp = random->RandomFloat( 0.5f, 1.25f ); newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f; newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f; newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f; AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] ); } // // Bullet hole capper // newParticle.m_Pos = offset; newParticle.m_flLifetime = 0.0f; newParticle.m_flDieTime = random->RandomFloat( 1.0f, 1.5f ); Vector dir; dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f ); newParticle.m_uchStartSize = random->RandomInt( 4, 8 ); newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4.0f; newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f ); newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f ); newParticle.m_uchStartAlpha = random->RandomInt( 100, 200 ); newParticle.m_uchEndAlpha = 0; newParticle.m_flRoll = random->RandomFloat( 0, 360 ); newParticle.m_flRollDelta = random->RandomFloat( -2, 2 ); float colorRamp = random->RandomFloat( 0.5f, 1.25f ); newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f; newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f; newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f; AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] ); #endif }
//----------------------------------------------------------------------------- // 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 }
//----------------------------------------------------------------------------- // 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; // // 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]); }
void C_TEAntlionDust::PostDataUpdate( DataUpdateType_t updateType ) { // This style of creating dust emitters is now deprecated; we use the simple particle singleton exclusively. /* CSmartPtr<CAntlionDustEmitter> pDustEmitter = CAntlionDustEmitter::Create( "TEAntlionDust" ); Assert( pDustEmitter ); if ( pDustEmitter == NULL ) return; pDustEmitter->SetSortOrigin( m_vecOrigin ); pDustEmitter->SetNearClip( 32, 64 ); pDustEmitter->GetBinding().SetBBox( m_vecOrigin - Vector( 32, 32, 32 ), m_vecOrigin + Vector( 32, 32, 32 ) ); */ Vector offset; Vector vecColor; GetDustColor( vecColor ); int iParticleCount = 16; if ( m_bBlockedSpawner == true ) { iParticleCount = 8; } //Spawn the dust SimpleParticle particle; for ( int i = 0; i < iParticleCount; i++ ) { //Offset this dust puff's origin offset[0] = random->RandomFloat( -DUST_RADIUS, DUST_RADIUS ); offset[1] = random->RandomFloat( -DUST_RADIUS, DUST_RADIUS ); offset[2] = random->RandomFloat( -16, 8 ); offset += m_vecOrigin; particle.m_Pos = offset; particle.m_flDieTime = random->RandomFloat( 0.75f, 1.25f ); particle.m_flLifetime = 0.0f; Vector dir = particle.m_Pos - m_vecOrigin; particle.m_vecVelocity = dir * random->RandomFloat( 0.5f, 1.0f ); dir.z = fabs(dir.z); float colorRamp = random->RandomFloat( 0.5f, 1.0f ); Vector color = vecColor*colorRamp; color[0] = clamp( color[0], 0.0f, 1.0f ); color[1] = clamp( color[1], 0.0f, 1.0f ); color[2] = clamp( color[2], 0.0f, 1.0f ); color *= 255; particle.m_uchColor[0] = color[0]; particle.m_uchColor[1] = color[1]; particle.m_uchColor[2] = color[2]; particle.m_uchStartAlpha= random->RandomFloat( 64, 128 ); particle.m_uchEndAlpha = 0; particle.m_uchStartSize = random->RandomInt( 16, 32 ); particle.m_uchEndSize = particle.m_uchStartSize * 3; particle.m_flRoll = random->RandomInt( 0, 360 ); particle.m_flRollDelta = random->RandomFloat( -0.2f, 0.2f ); // Though it appears there are two particle handle entries in g_Mat_DustPuff, in fact // only the one present at index 0 actually draws. Trying to spawn a particle with // the other material will give you no particle at all. Therefore while instead of this: // AddSimpleParticle( &particle, g_Mat_DustPuff[random->RandomInt(0,1) ); // we have to do this: AddSimpleParticle( &particle, g_Mat_DustPuff[0] ); } }
void CGasolineEmitter::UpdateFire( float frametime ) { float flLifetime = gpGlobals->curtime - m_pBlob->m_flCreateTime; float litPercent = 1; if ( m_pBlob->IsLit() ) { litPercent = 1 - (flLifetime / m_pBlob->m_flMaxLifetime); if ( litPercent <= 0 ) return; } else { return; } // Don't show a burn effect for a blob that hasn't hit anything yet. // If you do, it tends to make the flamethrower effect look weird. if ( !m_pBlob->IsStopped() ) return; // Make a coordinate system in which to spawn the particles. It Vector vUp, vRight; vUp.Init(); vRight.Init(); if ( m_pBlob->IsStopped() ) { QAngle angles; VectorAngles( m_pBlob->GetSurfaceNormal(), angles ); AngleVectors( angles, NULL, &vRight, &vUp ); } PMaterialHandle hMaterial = m_hFireMaterial; float flParticleLifetime = 1; float flRadius = 7; unsigned char uchColor[4] = { 255, 128, 0, 128 }; float flMaxZVel = 29; float curDelta = frametime; while ( m_Timer.NextEvent( curDelta ) ) { // Based on how close we are to expiring, show less particles. if ( RandomFloat( 0, 1 ) > litPercent ) continue; Vector vPos = m_pBlob->GetAbsOrigin(); if ( m_pBlob->IsStopped() ) { float flAngle = RandomFloat( 0, M_PI * 2 ); float flDist = RandomFloat( 0, GASOLINE_BLOB_RADIUS ); vPos += vRight * (cos( flAngle ) * flDist); vPos += vUp * ( sin( flAngle ) * flDist ); } else { vPos += RandomVector( -GASOLINE_BLOB_RADIUS, GASOLINE_BLOB_RADIUS ); } SimpleParticle *pParticle = AddSimpleParticle( hMaterial, vPos, flParticleLifetime, flRadius ); if ( pParticle ) { pParticle->m_uchColor[0] = uchColor[0]; pParticle->m_uchColor[1] = uchColor[1]; pParticle->m_uchColor[2] = uchColor[2]; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartAlpha = uchColor[3]; pParticle->m_vecVelocity.x = RandomFloat( -2, 2 ); pParticle->m_vecVelocity.y = RandomFloat( -2, 2 ); pParticle->m_vecVelocity.z = RandomFloat( 3, flMaxZVel ); } } }
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 ); } #ifdef _XBOX // // Cap // SimpleParticle sParticle; sParticle.m_Pos = pos; 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; AddSimpleParticle( &sParticle, ParticleMgr()->GetPMaterial( "effects/yellowflare" ) ); #else // // 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; */ #endif // !_XBOX }
void FX_DebrisFlecks( Vector& origin, trace_t *trace, char materialType, int iScale ) { VPROF_BUDGET( "FX_DebrisFlecks", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); Vector spawnOffset = trace->endpos + ( trace->plane.normal * 1.0f ); CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create( "FX_DebrisFlecks" ); 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_CONCRETE: default: hMaterial[0] = fleckEmitter->GetPMaterial( "effects/fleck_cement1" ); hMaterial[1] = fleckEmitter->GetPMaterial( "effects/fleck_cement2" ); break; } Vector dir, end; Vector color; float colorRamp; GetColorForSurface( trace, &color ); 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; } // // Dust trail // Vector offset = trace->endpos + ( trace->plane.normal * 2.0f ); SimpleParticle newParticle; hMaterial[0] = g_ParticleMgr.GetPMaterial( "particle/particle_smokegrenade" ); for ( i = 0; i < 2; i++ ) { newParticle.m_Pos = offset; newParticle.m_flLifetime = 0.0f; newParticle.m_flDieTime = 1.0f; dir[0] = trace->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = trace->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = trace->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 ); 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, hMaterial[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 ); dir[0] = trace->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = trace->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = trace->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 ); 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_ParticleMgr.GetPMaterial("effects/blood") ); } // // Bullet hole capper // newParticle.m_Pos = offset; newParticle.m_flLifetime = 0.0f; newParticle.m_flDieTime = random->RandomFloat( 1.0f, 1.5f ); dir[0] = trace->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = trace->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = trace->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 ); 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, hMaterial[0] ); }