void C_ASW_Snow_Volume::UpdateSnow(C_ASW_Player *pPlayer) { if (!pPlayer) return; if (g_hSnowEmitter.IsValid()) { C_ASW_Marine *pMarine = pPlayer->GetViewMarine(); Vector vecSnowPos; if (pMarine) vecSnowPos = pMarine->GetAbsOrigin(); else vecSnowPos = pPlayer->m_vecLastMarineOrigin; vecSnowPos += Vector(0,0,52); if (g_hSnowEmitter->m_hLastMarine.Get() != pMarine) { g_hSnowEmitter->SetSortOrigin(vecSnowPos); g_hSnowEmitter->GetBinding().DetectChanges(); //g_hSnowEmitter->DoPresimulate(vecSnowPos, QAngle(0,0,0)); //if (g_hSnowCloudEmitter.IsValid()) //g_hSnowCloudEmitter->DoPresimulate(vecSnowPos, QAngle(0,0,0)); } g_hSnowEmitter->m_hLastMarine = pMarine; g_hSnowEmitter->Think(gpGlobals->frametime, vecSnowPos, QAngle(0,0,0)); //if (g_hSnowCloudEmitter.IsValid()) //g_hSnowCloudEmitter->Think(gpGlobals->frametime, vecSnowPos, QAngle(0,0,0)); } }
CSmartPtr<T> InitSingleton( CSmartPtr<T> pEmitter ) { if ( !pEmitter ) { Error( "InitSingleton: pEmitter is NULL" ); } pEmitter->GetBinding().SetDrawThruLeafSystem( false ); // Draw in DrawSingletons instead. pEmitter->SetSortOrigin( Vector( 0, 0, 0 ) ); // Since we draw manually in DrawSingletons, we don't care about // the bbox, so don't waste cycles inserting it into the leaf system // when it's not going to draw through that anyway. // (TODO: SetDrawThruLeafSystem(false) should trigger this automatically // in CParticleMgr). pEmitter->GetBinding().SetBBox( Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) ); return pEmitter; }
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: // 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: 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: 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 }
//----------------------------------------------------------------------------- // Purpose: // Input : scale - // attachmentIndex - // bOneFrame - //----------------------------------------------------------------------------- void FX_MuzzleEffectAttached( float scale, ClientEntityHandle_t hEntity, int attachmentIndex, unsigned char *pFlashColor, bool bOneFrame ) { VPROF_BUDGET( "FX_MuzzleEffect", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); // If the material isn't available, let's not do anything. if ( g_Mat_SMG_Muzzleflash[0] == NULL ) { return; } CSmartPtr<CLocalSpaceEmitter> pSimple = CLocalSpaceEmitter::Create( "MuzzleFlash", hEntity, attachmentIndex ); Assert( pSimple ); if ( pSimple == NULL ) return; // Lock our bounding box pSimple->GetBinding().SetBBox( -( Vector( 16, 16, 16 ) * scale ), ( Vector( 16, 16, 16 ) * scale ) ); SimpleParticle *pParticle; Vector forward(1,0,0), offset; float flScale = random->RandomFloat( scale-0.25f, scale+0.25f ); if ( flScale < 0.5f ) { flScale = 0.5f; } else if ( flScale > 8.0f ) { flScale = 8.0f; } // // Flash // int i; for ( i = 1; i < 9; i++ ) { offset = (forward * (i*2.0f*scale)); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_SMG_Muzzleflash[random->RandomInt(0,3)], offset ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = bOneFrame ? 0.0001f : 0.1f; pParticle->m_vecVelocity.Init(); if ( !pFlashColor ) { pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; } else { pParticle->m_uchColor[0] = pFlashColor[0]; pParticle->m_uchColor[1] = pFlashColor[1]; pParticle->m_uchColor[2] = pFlashColor[2]; } pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 128; pParticle->m_uchStartSize = (random->RandomFloat( 6.0f, 9.0f ) * (12-(i))/9) * flScale; pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = 0.0f; } if ( !ToolsEnabled() ) return; if ( !clienttools->IsInRecordingMode() ) return; C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( hEntity ); if ( pEnt ) { pEnt->RecordToolMessage(); } // NOTE: Particle system destruction message will be sent by the particle effect itself. int nId = pSimple->AllocateToolParticleEffectId(); KeyValues *msg = new KeyValues( "OldParticleSystem_Create" ); msg->SetString( "name", "FX_MuzzleEffectAttached" ); msg->SetInt( "id", nId ); msg->SetFloat( "time", gpGlobals->curtime ); KeyValues *pEmitter = msg->FindKey( "DmeSpriteEmitter", true ); pEmitter->SetInt( "count", 9 ); pEmitter->SetFloat( "duration", 0 ); pEmitter->SetString( "material", "effects/muzzleflash2" ); // FIXME - create DmeMultiMaterialSpriteEmitter to support the 4 materials of muzzleflash pEmitter->SetInt( "active", true ); KeyValues *pInitializers = pEmitter->FindKey( "initializers", true ); KeyValues *pPosition = pInitializers->FindKey( "DmeLinearAttachedPositionInitializer", true ); pPosition->SetPtr( "entindex", (void*)pEnt->entindex() ); pPosition->SetInt( "attachmentIndex", attachmentIndex ); pPosition->SetFloat( "linearOffsetX", 2.0f * scale ); // TODO - create a DmeConstantLifetimeInitializer KeyValues *pLifetime = pInitializers->FindKey( "DmeRandomLifetimeInitializer", true ); pLifetime->SetFloat( "minLifetime", bOneFrame ? 1.0f / 24.0f : 0.1f ); pLifetime->SetFloat( "maxLifetime", bOneFrame ? 1.0f / 24.0f : 0.1f ); KeyValues *pVelocity = pInitializers->FindKey( "DmeConstantVelocityInitializer", true ); pVelocity->SetFloat( "velocityX", 0.0f ); pVelocity->SetFloat( "velocityY", 0.0f ); pVelocity->SetFloat( "velocityZ", 0.0f ); KeyValues *pRoll = pInitializers->FindKey( "DmeRandomRollInitializer", true ); pRoll->SetFloat( "minRoll", 0.0f ); pRoll->SetFloat( "maxRoll", 360.0f ); // TODO - create a DmeConstantRollSpeedInitializer KeyValues *pRollSpeed = pInitializers->FindKey( "DmeRandomRollSpeedInitializer", true ); pRollSpeed->SetFloat( "minRollSpeed", 0.0f ); pRollSpeed->SetFloat( "maxRollSpeed", 0.0f ); // TODO - create a DmeConstantColorInitializer KeyValues *pColor = pInitializers->FindKey( "DmeRandomInterpolatedColorInitializer", true ); Color color( pFlashColor ? pFlashColor[ 0 ] : 255, pFlashColor ? pFlashColor[ 1 ] : 255, pFlashColor ? pFlashColor[ 2 ] : 255, 255 ); pColor->SetColor( "color1", color ); pColor->SetColor( "color2", color ); // TODO - create a DmeConstantAlphaInitializer KeyValues *pAlpha = pInitializers->FindKey( "DmeRandomAlphaInitializer", true ); pAlpha->SetInt( "minStartAlpha", 255 ); pAlpha->SetInt( "maxStartAlpha", 255 ); pAlpha->SetInt( "minEndAlpha", 128 ); pAlpha->SetInt( "maxEndAlpha", 128 ); // size = rand(6..9) * indexed(12/9..4/9) * flScale = rand(6..9) * ( 4f + f * i ) KeyValues *pSize = pInitializers->FindKey( "DmeMuzzleFlashSizeInitializer", true ); float f = flScale / 9.0f; pSize->SetFloat( "indexedBase", 4.0f * f ); pSize->SetFloat( "indexedDelta", f ); pSize->SetFloat( "minRandomFactor", 6.0f ); pSize->SetFloat( "maxRandomFactor", 9.0f ); /* KeyValues *pUpdaters = pEmitter->FindKey( "updaters", true ); pUpdaters->FindKey( "DmePositionVelocityUpdater", true ); pUpdaters->FindKey( "DmeRollUpdater", true ); pUpdaters->FindKey( "DmeAlphaLinearUpdater", true ); pUpdaters->FindKey( "DmeSizeUpdater", true ); */ ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg ); msg->deleteThis(); }
void FX_MetalSpark(const Vector &position, const Vector &direction, const Vector &surfaceNormal, int iScale) { VPROF_BUDGET("FX_MetalSpark", VPROF_BUDGETGROUP_PARTICLE_RENDERING); if (!fx_drawmetalspark.GetBool()) return; // // Emitted particles // Vector offset = position + (surfaceNormal * 1.0f); CSmartPtr<CTrailParticles> sparkEmitter = CTrailParticles::Create("FX_MetalSpark 1"); if (sparkEmitter == NULL) return; //Setup our information sparkEmitter->SetSortOrigin(offset); sparkEmitter->SetFlag(bitsPARTICLE_TRAIL_VELOCITY_DAMPEN); sparkEmitter->SetVelocityDampen(8.0f); sparkEmitter->SetGravity(METAL_SPARK_GRAVITY); sparkEmitter->SetCollisionDamped(METAL_SPARK_DAMPEN); sparkEmitter->GetBinding().SetBBox(offset - Vector(32, 32, 32), offset + Vector(32, 32, 32)); int numSparks = random->RandomInt(4, 8) * (iScale * 2); numSparks = (int) (0.5f + (float) numSparks * g_pParticleSystemMgr->ParticleThrottleScaling()); if (g_Material_Spark == NULL) { g_Material_Spark = sparkEmitter->GetPMaterial("effects/spark"); } TrailParticle *pParticle; Vector dir; float length = 0.1f; //Dump out sparks for (int i = 0; i < numSparks; i++) { pParticle = (TrailParticle *) sparkEmitter->AddParticle(sizeof(TrailParticle), g_Material_Spark, offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; if (iScale > 1 && i % 3 == 0) { // Every third spark goes flying far if we're having a big batch of sparks. pParticle->m_flDieTime = random->RandomFloat(0.15f, 0.25f); } else { pParticle->m_flDieTime = random->RandomFloat(0.05f, 0.1f); } float spreadOfs = random->RandomFloat(0.0f, 2.0f); dir[0] = direction[0] + random->RandomFloat(-(METAL_SPARK_SPREAD*spreadOfs), (METAL_SPARK_SPREAD*spreadOfs)); dir[1] = direction[1] + random->RandomFloat(-(METAL_SPARK_SPREAD*spreadOfs), (METAL_SPARK_SPREAD*spreadOfs)); dir[2] = direction[2] + random->RandomFloat(-(METAL_SPARK_SPREAD*spreadOfs), (METAL_SPARK_SPREAD*spreadOfs)); VectorNormalize(dir); pParticle->m_flWidth = random->RandomFloat(1.0f, 4.0f); pParticle->m_flLength = random->RandomFloat(length*0.25f, length); pParticle->m_vecVelocity = dir * random->RandomFloat((METAL_SPARK_MINSPEED*(2.0f - spreadOfs)), (METAL_SPARK_MAXSPEED*(2.0f - spreadOfs))); Color32Init(pParticle->m_color, 255, 255, 255, 255); } // // Impact point glow // FXQuadData_t data; data.SetMaterial("effects/yellowflare"); data.SetColor(1.0f, 1.0f, 1.0f); data.SetOrigin(offset); data.SetNormal(surfaceNormal); data.SetAlpha(1.0f, 0.0f); data.SetLifeTime(0.1f); data.SetYaw(random->RandomInt(0, 360)); int scale = random->RandomInt(24, 28); data.SetScale(scale, 0); FX_AddQuad(data); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_BaseExplosionEffect::CreateCore( void ) { if ( m_fFlags & TE_EXPLFLAG_NOFIREBALL ) return; Vector offset; int i; //Spread constricts as force rises float force = m_flForce; //Cap our force if ( force < EXPLOSION_FORCE_MIN ) force = EXPLOSION_FORCE_MIN; if ( force > EXPLOSION_FORCE_MAX ) force = EXPLOSION_FORCE_MAX; float spread = 1.0f - (0.15f*force); SimpleParticle *pParticle; CSmartPtr<CExplosionParticle> pSimple = CExplosionParticle::Create( "exp_smoke" ); pSimple->SetSortOrigin( m_vecOrigin ); pSimple->SetNearClip( 64, 128 ); pSimple->GetBinding().SetBBox( m_vecOrigin - Vector( 128, 128, 128 ), m_vecOrigin + Vector( 128, 128, 128 ) ); if ( m_Material_Smoke == NULL ) { m_Material_Smoke = g_Mat_DustPuff[1]; } //FIXME: Better sampling area offset = m_vecOrigin + ( m_vecDirection * 32.0f ); //Find area ambient light color and use it to tint smoke Vector worldLight = WorldGetLightForPoint( offset, true ); Vector tint; float luminosity; if ( worldLight == vec3_origin ) { tint = vec3_origin; luminosity = 0.0f; } else { UTIL_GetNormalizedColorTintAndLuminosity( worldLight, &tint, &luminosity ); } // We only take a portion of the tint tint = (tint * 0.25f)+(Vector(0.75f,0.75f,0.75f)); // Rescale to a character range luminosity *= 255; if ( (m_fFlags & TE_EXPLFLAG_NOFIREBALLSMOKE) == 0 ) { // // Smoke - basic internal filler // for ( i = 0; i < 4; i++ ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_Smoke, m_vecOrigin ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; #ifdef INVASION_CLIENT_DLL pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); #endif #ifdef _XBOX pParticle->m_flDieTime = 1.0f; #else pParticle->m_flDieTime = random->RandomFloat( 2.0f, 3.0f ); #endif pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += ( m_vecDirection * random->RandomFloat( 1.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 1, 750 ) * force; //Scale the force down as we fall away from our main direction ScaleForceByDeviation( pParticle->m_vecVelocity, m_vecDirection, spread, &fForce ); pParticle->m_vecVelocity *= fForce; #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif int nColor = random->RandomInt( luminosity*0.5f, luminosity ); pParticle->m_uchColor[0] = ( worldLight[0] * nColor ); pParticle->m_uchColor[1] = ( worldLight[1] * nColor ); pParticle->m_uchColor[2] = ( worldLight[2] * nColor ); pParticle->m_uchStartSize = 72; 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 ); } } // // Inner core // #ifndef _XBOX for ( i = 0; i < 8; i++ ) { offset.Random( -16.0f, 16.0f ); offset += m_vecOrigin; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_Smoke, offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; #ifdef INVASION_CLIENT_DLL pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); #else pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); #endif pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += ( m_vecDirection * random->RandomFloat( 1.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 1, 2000 ) * force; //Scale the force down as we fall away from our main direction ScaleForceByDeviation( pParticle->m_vecVelocity, m_vecDirection, spread, &fForce ); pParticle->m_vecVelocity *= fForce; #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif int nColor = random->RandomInt( luminosity*0.5f, luminosity ); pParticle->m_uchColor[0] = ( worldLight[0] * nColor ); pParticle->m_uchColor[1] = ( worldLight[1] * nColor ); pParticle->m_uchColor[2] = ( worldLight[2] * nColor ); pParticle->m_uchStartSize = random->RandomInt( 32, 64 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 2; pParticle->m_uchStartAlpha = random->RandomFloat( 128, 255 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f ); } } #endif // !_XBOX // // Ground ring // Vector vRight, vUp; VectorVectors( m_vecDirection, vRight, vUp ); Vector forward; #ifndef INVASION_CLIENT_DLL #ifndef _XBOX int numRingSprites = 32; #else int numRingSprites = 8; #endif float flIncr = (2*M_PI) / (float) numRingSprites; // Radians float flYaw = 0.0f; for ( i = 0; i < numRingSprites; i++ ) { flYaw += flIncr; SinCos( flYaw, &forward.y, &forward.x ); forward.z = 0.0f; offset = ( RandomVector( -4.0f, 4.0f ) + m_vecOrigin ) + ( forward * random->RandomFloat( 8.0f, 16.0f ) ); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_Smoke, offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.5f ); pParticle->m_vecVelocity = forward; float fForce = random->RandomFloat( 500, 2000 ) * force; //Scale the force down as we fall away from our main direction ScaleForceByDeviation( pParticle->m_vecVelocity, pParticle->m_vecVelocity, spread, &fForce ); pParticle->m_vecVelocity *= fForce; #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif int nColor = random->RandomInt( luminosity*0.5f, luminosity ); pParticle->m_uchColor[0] = ( worldLight[0] * nColor ); pParticle->m_uchColor[1] = ( worldLight[1] * nColor ); pParticle->m_uchColor[2] = ( worldLight[2] * nColor ); pParticle->m_uchStartSize = random->RandomInt( 16, 32 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomFloat( 16, 32 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f ); } } #endif } #ifndef _XBOX // // Embers // if ( m_Material_Embers[0] == NULL ) { m_Material_Embers[0] = pSimple->GetPMaterial( "effects/fire_embers1" ); } if ( m_Material_Embers[1] == NULL ) { m_Material_Embers[1] = pSimple->GetPMaterial( "effects/fire_embers2" ); } for ( i = 0; i < 16; i++ ) { offset.Random( -32.0f, 32.0f ); offset += m_vecOrigin; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_Embers[random->RandomInt(0,1)], offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 2.0f, 3.0f ); pParticle->m_vecVelocity.Random( -spread*2, spread*2 ); pParticle->m_vecVelocity += m_vecDirection; VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 1.0f, 400.0f ); //Scale the force down as we fall away from our main direction float vDev = ScaleForceByDeviation( pParticle->m_vecVelocity, m_vecDirection, spread ); pParticle->m_vecVelocity *= fForce * ( 16.0f * (vDev*vDev*0.5f) ); #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif int nColor = random->RandomInt( 192, 255 ); pParticle->m_uchColor[0] = pParticle->m_uchColor[1] = pParticle->m_uchColor[2] = nColor; pParticle->m_uchStartSize = random->RandomInt( 8, 16 ) * vDev; pParticle->m_uchStartSize = clamp( pParticle->m_uchStartSize, 4, 32 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f ); } } #endif // !_XBOX // // Fireballs // if ( m_Material_FireCloud == NULL ) { m_Material_FireCloud = pSimple->GetPMaterial( "effects/fire_cloud2" ); } #ifndef _XBOX int numFireballs = 32; #else int numFireballs = 16; #endif for ( i = 0; i < numFireballs; i++ ) { offset.Random( -48.0f, 48.0f ); offset += m_vecOrigin; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_FireCloud, offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.2f, 0.4f ); pParticle->m_vecVelocity.Random( -spread*0.75f, spread*0.75f ); pParticle->m_vecVelocity += m_vecDirection; VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 400.0f, 800.0f ); //Scale the force down as we fall away from our main direction float vDev = ScaleForceByDeviation( pParticle->m_vecVelocity, m_vecDirection, spread ); pParticle->m_vecVelocity *= fForce * ( 16.0f * (vDev*vDev*0.5f) ); #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif int nColor = random->RandomInt( 128, 255 ); pParticle->m_uchColor[0] = pParticle->m_uchColor[1] = pParticle->m_uchColor[2] = nColor; pParticle->m_uchStartSize = random->RandomInt( 32, 85 ) * vDev; pParticle->m_uchStartSize = clamp( pParticle->m_uchStartSize, 32, 85 ); pParticle->m_uchEndSize = (int)((float)pParticle->m_uchStartSize * 1.5f); pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.0f ); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_WaterExplosionEffect::CreateMisc( void ) { Vector offset; float colorRamp; int i; float flScale = 2.0f; PMaterialHandle hMaterial = ParticleMgr()->GetPMaterial( "effects/splash2" ); #ifndef _XBOX int numDrops = 32; float length = 0.1f; Vector vForward, vRight, vUp; Vector offDir; TrailParticle *tParticle; CSmartPtr<CTrailParticles> sparkEmitter = CTrailParticles::Create( "splash" ); if ( !sparkEmitter ) return; sparkEmitter->SetSortOrigin( m_vecWaterSurface ); sparkEmitter->m_ParticleCollision.SetGravity( 800.0f ); sparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN ); sparkEmitter->SetVelocityDampen( 2.0f ); //Dump out drops for ( i = 0; i < numDrops; i++ ) { offset = m_vecWaterSurface; offset[0] += random->RandomFloat( -16.0f, 16.0f ) * flScale; offset[1] += random->RandomFloat( -16.0f, 16.0f ) * flScale; tParticle = (TrailParticle *) sparkEmitter->AddParticle( sizeof(TrailParticle), hMaterial, offset ); if ( tParticle == NULL ) break; tParticle->m_flLifetime = 0.0f; tParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); offDir = Vector(0,0,1) + RandomVector( -1.0f, 1.0f ); tParticle->m_vecVelocity = offDir * random->RandomFloat( 50.0f * flScale * 2.0f, 100.0f * flScale * 2.0f ); tParticle->m_vecVelocity[2] += random->RandomFloat( 32.0f, 128.0f ) * flScale; tParticle->m_flWidth = clamp( random->RandomFloat( 1.0f, 3.0f ) * flScale, 0.1f, 4.0f ); tParticle->m_flLength = random->RandomFloat( length*0.25f, length )/* * flScale*/; colorRamp = random->RandomFloat( 1.5f, 2.0f ); FloatToColor32( tParticle->m_color, min( 1.0f, m_vecColor[0] * colorRamp ), min( 1.0f, m_vecColor[1] * colorRamp ), min( 1.0f, m_vecColor[2] * colorRamp ), m_flLuminosity ); } //Dump out drops for ( i = 0; i < 4; i++ ) { offset = m_vecWaterSurface; offset[0] += random->RandomFloat( -16.0f, 16.0f ) * flScale; offset[1] += random->RandomFloat( -16.0f, 16.0f ) * flScale; tParticle = (TrailParticle *) sparkEmitter->AddParticle( sizeof(TrailParticle), hMaterial, offset ); if ( tParticle == NULL ) break; tParticle->m_flLifetime = 0.0f; tParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); offDir = Vector(0,0,1) + RandomVector( -0.2f, 0.2f ); tParticle->m_vecVelocity = offDir * random->RandomFloat( 50 * flScale * 3.0f, 100 * flScale * 3.0f ); tParticle->m_vecVelocity[2] += random->RandomFloat( 32.0f, 128.0f ) * flScale; tParticle->m_flWidth = clamp( random->RandomFloat( 2.0f, 3.0f ) * flScale, 0.1f, 4.0f ); tParticle->m_flLength = random->RandomFloat( length*0.25f, length )/* * flScale*/; colorRamp = random->RandomFloat( 1.5f, 2.0f ); FloatToColor32( tParticle->m_color, min( 1.0f, m_vecColor[0] * colorRamp ), min( 1.0f, m_vecColor[1] * colorRamp ), min( 1.0f, m_vecColor[2] * colorRamp ), m_flLuminosity ); } #endif CSmartPtr<CSplashParticle> pSimple = CSplashParticle::Create( "splish" ); pSimple->SetSortOrigin( m_vecWaterSurface ); pSimple->SetClipHeight( m_vecWaterSurface.z ); pSimple->GetBinding().SetBBox( m_vecWaterSurface-(Vector(32.0f, 32.0f, 32.0f)*flScale), m_vecWaterSurface+(Vector(32.0f, 32.0f, 32.0f)*flScale) ); SimpleParticle *pParticle; for ( i = 0; i < 16; i++ ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial, m_vecWaterSurface ); if ( pParticle == NULL ) break; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 2.0f; //NOTENOTE: We use a clip plane to realistically control our lifespan pParticle->m_vecVelocity.Random( -0.2f, 0.2f ); pParticle->m_vecVelocity += ( Vector( 0, 0, random->RandomFloat( 4.0f, 6.0f ) ) ); VectorNormalize( pParticle->m_vecVelocity ); pParticle->m_vecVelocity *= 50 * flScale * (8-i); colorRamp = random->RandomFloat( 0.75f, 1.25f ); pParticle->m_uchColor[0] = min( 1.0f, m_vecColor[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = min( 1.0f, m_vecColor[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = min( 1.0f, m_vecColor[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = 24 * flScale * RemapValClamped( i, 7, 0, 1, 0.5f ); pParticle->m_uchEndSize = min( 255, pParticle->m_uchStartSize * 2 ); pParticle->m_uchStartAlpha = RemapValClamped( i, 7, 0, 255, 32 ) * m_flLuminosity; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -4.0f, 4.0f ); } }
void FX_ThumperDust( const CEffectData &data ) { Vector vecDustColor; vecDustColor.x = 0.85f; vecDustColor.y = 0.75f; vecDustColor.z = 0.52f; CSmartPtr<ThumperDustEmitter> pSimple = ThumperDustEmitter::Create( "thumperdust" ); C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); if ( pEnt ) { Vector vWorldMins, vWorldMaxs; float scale = pEnt->CollisionProp()->BoundingRadius(); vWorldMins[0] = data.m_vOrigin[0] - scale; vWorldMins[1] = data.m_vOrigin[1] - scale; vWorldMins[2] = data.m_vOrigin[2] - scale; vWorldMaxs[0] = data.m_vOrigin[0] + scale; vWorldMaxs[1] = data.m_vOrigin[1] + scale; vWorldMaxs[2] = data.m_vOrigin[2] + scale; pSimple->GetBinding().SetBBox( vWorldMins, vWorldMaxs, true ); } pSimple->SetSortOrigin( data.m_vOrigin ); pSimple->SetNearClip( 32, 64 ); SimpleParticle *pParticle = NULL; Vector offset; //int numPuffs = IsXbox() ? THUMPER_MAX_PARTICLES/2 : THUMPER_MAX_PARTICLES; int numPuffs = THUMPER_MAX_PARTICLES; float flYaw = 0; float flIncr = (2*M_PI) / (float) numPuffs; // Radians Vector forward; Vector vecColor; int i = 0; float flScale = min( data.m_flScale, 255 ); // Setup the color for these particles engine->ComputeLighting( data.m_vOrigin, NULL, true, vecColor ); VectorLerp( vecColor, vecDustColor, 0.5, vecColor ); vecColor *= 255; for ( i = 0; i < numPuffs; i++ ) { flYaw += flIncr; SinCos( flYaw, &forward.y, &forward.x ); forward.z = 0.0f; offset = ( RandomVector( -4.0f, 4.0f ) + data.m_vOrigin ) + ( forward * 128.0f ); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[random->RandomInt(0,1)], offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 1.5f; Vector dir = (offset - data.m_vOrigin); float length = dir.Length(); VectorNormalize( dir ); pParticle->m_vecVelocity = dir * ( length * 2.0f ); pParticle->m_vecVelocity[2] = data.m_flScale / 3; pParticle->m_uchColor[0] = vecColor[0]; pParticle->m_uchColor[1] = vecColor[1]; pParticle->m_uchColor[2] = vecColor[2]; pParticle->m_uchStartAlpha = random->RandomInt( 64, 96 ); pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = flScale * 0.25f; pParticle->m_uchEndSize = flScale * 0.5f; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -6.0f, 6.0f ); } } }
//----------------------------------------------------------------------------- // Purpose: // Input : &origin - //----------------------------------------------------------------------------- void FX_AntlionGib( const Vector &origin, const Vector &direction, float scale ) { Vector offset; #ifdef _XBOX // Throw less gibs for XBox for ( int i = 0; i < NUM_ANTLION_GIBS; i++ ) { offset = RandomVector( -32, 32 ) + origin; C_AntlionGib::CreateClientsideGib( pszAntlionGibs[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 250 * scale ), RandomAngularImpulse( -32, 32 ), 1.0f ); } #else int numGibs = random->RandomInt( 1, NUM_ANTLION_GIBS_UNIQUE ); // Spawn all the unique gibs for ( int i = 0; i < numGibs; i++ ) { offset = RandomVector( -16, 16 ) + origin; C_AntlionGib::CreateClientsideGib( pszAntlionGibs_Unique[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 150 * scale ), RandomAngularImpulse( -32, 32 ), 2.0f); } numGibs = random->RandomInt( 1, NUM_ANTLION_GIBS_MEDIUM ); // Spawn all the medium gibs for ( int i = 0; i < numGibs; i++ ) { offset = RandomVector( -16, 16 ) + origin; C_AntlionGib::CreateClientsideGib( pszAntlionGibs_Medium[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 250 * scale ), RandomAngularImpulse( -200, 200 ), 1.0f ); } numGibs = random->RandomInt( 1, NUM_ANTLION_GIBS_SMALL ); // Spawn all the small gibs for ( int i = 0; i < NUM_ANTLION_GIBS_SMALL; i++ ) { offset = RandomVector( -16, 16 ) + origin; C_AntlionGib::CreateClientsideGib( pszAntlionGibs_Small[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 400 * scale ), RandomAngularImpulse( -300, 300 ), 0.5f ); } #endif #ifdef _XBOX // // Throw some blood // CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_AntlionGib" ); pSimple->SetSortOrigin( origin ); pSimple->GetBinding().SetBBox( origin - Vector(64,64,64), origin + Vector(64,64,64) ); // Cache this if we're not already if ( g_Material_Blood[0] == NULL ) { g_Material_Blood[0] = g_Mat_BloodPuff[0]; } if ( g_Material_Blood[1] == NULL ) { g_Material_Blood[1] = g_Mat_BloodPuff[1]; } Vector vDir; vDir.Random( -1.0f, 1.0f ); // Gore bits for ( int i = 0; i < 4; i++ ) { SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Material_Blood[0], origin + RandomVector(-16,16)); if ( sParticle == NULL ) return; sParticle->m_flLifetime = 0.0f; sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); float speed = random->RandomFloat( 16.0f, 64.0f ); sParticle->m_vecVelocity.Init(); 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( 4, 16 ); sParticle->m_uchEndSize = sParticle->m_uchStartSize * 4; sParticle->m_flRoll = random->RandomInt( 0, 360 ); sParticle->m_flRollDelta = 0.0f; } // Middle core SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Material_Blood[1], origin ); if ( sParticle == NULL ) return; sParticle->m_flLifetime = 0.0f; sParticle->m_flDieTime = random->RandomFloat( 0.5f, 0.75f ); float speed = random->RandomFloat( 16.0f, 64.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( 64, 128 ); sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = random->RandomInt( 16, 32 ); sParticle->m_uchEndSize = sParticle->m_uchStartSize * 3; sParticle->m_flRoll = random->RandomInt( 0, 360 ); sParticle->m_flRollDelta = random->RandomFloat( -0.2f, 0.2f ); #else // // Non-XBox blood // CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_AntlionGib" ); pSimple->SetSortOrigin( origin ); Vector vDir; vDir.Random( -1.0f, 1.0f ); for ( int i = 0; i < 4; i++ ) { SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin ); if ( sParticle == NULL ) return; sParticle->m_flLifetime = 0.0f; sParticle->m_flDieTime = random->RandomFloat( 0.5f, 0.75f ); float speed = random->RandomFloat( 16.0f, 64.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 = 255; sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = random->RandomInt( 16, 32 ); sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2; sParticle->m_flRoll = random->RandomInt( 0, 360 ); sParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f ); } for ( int i = 0; i < 4; i++ ) { SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], origin ); if ( sParticle == NULL ) { return; } sParticle->m_flLifetime = 0.0f; sParticle->m_flDieTime = random->RandomFloat( 0.5f, 0.75f ); float speed = random->RandomFloat( 16.0f, 64.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( 64, 128 ); sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = random->RandomInt( 16, 32 ); sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2; sParticle->m_flRoll = random->RandomInt( 0, 360 ); sParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f ); } #endif }
//----------------------------------------------------------------------------- // Purpose: // Input : &origin - // &normal - // scale - //----------------------------------------------------------------------------- void FX_AirboatGunImpact( const Vector &origin, const Vector &normal, float scale ) { #ifdef _XBOX Vector offset = origin + ( normal * 1.0f ); CSmartPtr<CTrailParticles> sparkEmitter = CTrailParticles::Create( "FX_MetalSpark 1" ); if ( sparkEmitter == NULL ) return; //Setup our information sparkEmitter->SetSortOrigin( offset ); sparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN ); sparkEmitter->SetVelocityDampen( 8.0f ); sparkEmitter->SetGravity( 800.0f ); sparkEmitter->SetCollisionDamped( 0.25f ); sparkEmitter->GetBinding().SetBBox( offset - Vector( 32, 32, 32 ), offset + Vector( 32, 32, 32 ) ); int numSparks = random->RandomInt( 4, 8 ); TrailParticle *pParticle; PMaterialHandle hMaterial = sparkEmitter->GetPMaterial( "effects/spark" ); Vector dir; float length = 0.1f; //Dump out sparks for ( int i = 0; i < numSparks; i++ ) { pParticle = (TrailParticle *) sparkEmitter->AddParticle( sizeof(TrailParticle), hMaterial, offset ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.05f, 0.1f ); float spreadOfs = random->RandomFloat( 0.0f, 2.0f ); dir[0] = normal[0] + random->RandomFloat( -(0.5f*spreadOfs), (0.5f*spreadOfs) ); dir[1] = normal[1] + random->RandomFloat( -(0.5f*spreadOfs), (0.5f*spreadOfs) ); dir[2] = normal[2] + random->RandomFloat( -(0.5f*spreadOfs), (0.5f*spreadOfs) ); VectorNormalize( dir ); pParticle->m_flWidth = random->RandomFloat( 1.0f, 4.0f ); pParticle->m_flLength = random->RandomFloat( length*0.25f, length ); pParticle->m_vecVelocity = dir * random->RandomFloat( (128.0f*(2.0f-spreadOfs)), (512.0f*(2.0f-spreadOfs)) ); Color32Init( pParticle->m_color, 255, 255, 255, 255 ); } #else // Normal metal spark FX_MetalSpark( origin, normal, normal, (int) scale ); #endif // _XBOX // Add a quad to highlite the hit point FX_AddQuad( origin, normal, random->RandomFloat( 16, 32 ), random->RandomFloat( 32, 48 ), 0.75f, 1.0f, 0.0f, 0.4f, random->RandomInt( 0, 360 ), 0, Vector( 1.0f, 1.0f, 1.0f ), 0.05f, "effects/combinemuzzle2_nocull", (FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) ); }
//----------------------------------------------------------------------------- // Purpose: Used for bullets hitting bleeding surfaces // Input : origin - // normal - // scale - This parameter is not currently used //----------------------------------------------------------------------------- void FX_BloodBulletImpact( const Vector &origin, const Vector &normal, float scale /*NOTE: Unused!*/, unsigned char r, unsigned char g, unsigned char b ) { if ( UTIL_IsLowViolence() ) return; Vector offset; //Find area ambient light color and use it to tint smoke Vector worldLight = WorldGetLightForPoint( origin, true ); if ( gpGlobals->maxClients > 1 ) { worldLight = Vector( 1.0, 1.0, 1.0 ); r = 96; g = 0; b = 10; } Vector color = Vector( (float)(worldLight[0] * r) / 255.0f, (float)(worldLight[1] * g) / 255.0f, (float)(worldLight[2] * b) / 255.0f ); float colorRamp; Vector offDir; CSmartPtr<CBloodSprayEmitter> pSimple = CBloodSprayEmitter::Create( "bloodgore" ); if ( !pSimple ) return; pSimple->SetSortOrigin( origin ); pSimple->SetGravity( 200 ); // Setup a bounding box to contain the particles without (stops auto-updating) pSimple->GetBinding().SetBBox( origin - Vector( 16, 16, 16 ), origin + Vector( 16, 16, 16 ) ); // Cache the material if we haven't already if ( g_Blood_Core == NULL ) { g_Blood_Core = ParticleMgr()->GetPMaterial( "effects/blood_core" ); } SimpleParticle *pParticle; Vector dir = normal * RandomVector( -0.5f, 0.5f ); offset = origin + ( 2.0f * normal ); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Blood_Core, offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f); pParticle->m_vecVelocity = dir * random->RandomFloat( 16.0f, 32.0f ); pParticle->m_vecVelocity[2] -= random->RandomFloat( 8.0f, 16.0f ); colorRamp = random->RandomFloat( 0.75f, 2.0f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = random->RandomInt( 2, 4 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 8; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = 0.0f; } // Cache the material if we haven't already if ( g_Blood_Gore == NULL ) { g_Blood_Gore = ParticleMgr()->GetPMaterial( "effects/blood_gore" ); } for ( int i = 0; i < 4; i++ ) { offset = origin + ( 2.0f * normal ); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Blood_Gore, offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 0.75f); pParticle->m_vecVelocity = dir * random->RandomFloat( 16.0f, 32.0f )*(i+1); pParticle->m_vecVelocity[2] -= random->RandomFloat( 32.0f, 64.0f )*(i+1); colorRamp = random->RandomFloat( 0.75f, 2.0f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = random->RandomInt( 2, 4 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = 0.0f; } } // // Dump out drops // TrailParticle *tParticle; CSmartPtr<CTrailParticles> pTrailEmitter = CTrailParticles::Create( "blooddrops" ); if ( !pTrailEmitter ) return; pTrailEmitter->SetSortOrigin( origin ); // Partial gravity on blood drops pTrailEmitter->SetGravity( 400.0 ); // Enable simple collisions with nearby surfaces pTrailEmitter->Setup(origin, &normal, 1, 10, 100, 400, 0.2, 0 ); if ( g_Blood_Drops == NULL ) { g_Blood_Drops = ParticleMgr()->GetPMaterial( "effects/blood_drop" ); } // // Shorter droplets // for ( int i = 0; i < 8; i++ ) { // Originate from within a circle 'scale' inches in diameter offset = origin; tParticle = (TrailParticle *) pTrailEmitter->AddParticle( sizeof(TrailParticle), g_Blood_Drops, offset ); if ( tParticle == NULL ) break; tParticle->m_flLifetime = 0.0f; offDir = RandomVector( -1.0f, 1.0f ); tParticle->m_vecVelocity = offDir * random->RandomFloat( 64.0f, 128.0f ); tParticle->m_flWidth = random->RandomFloat( 0.5f, 2.0f ); tParticle->m_flLength = random->RandomFloat( 0.05f, 0.15f ); tParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); FloatToColor32( tParticle->m_color, color[0], color[1], color[2], 1.0f ); } // TODO: Play a sound? //CLocalPlayerFilter filter; //C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, CHAN_VOICE, "Physics.WaterSplash", 1.0, ATTN_NORM, 0, 100, &origin ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_BaseExplosionEffect::CreateDebris( void ) { if ( m_fFlags & TE_EXPLFLAG_NOPARTICLES ) return; // // Sparks // CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "CreateDebris 1" ); if ( pSparkEmitter == NULL ) { assert(0); return; } if ( m_Material_FireCloud == NULL ) { m_Material_FireCloud = pSparkEmitter->GetPMaterial( "effects/fire_cloud2" ); } pSparkEmitter->SetSortOrigin( m_vecOrigin ); pSparkEmitter->m_ParticleCollision.SetGravity( 200.0f ); pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN ); pSparkEmitter->SetVelocityDampen( 8.0f ); // Set our bbox, don't auto-calculate it! pSparkEmitter->GetBinding().SetBBox( m_vecOrigin - Vector( 128, 128, 128 ), m_vecOrigin + Vector( 128, 128, 128 ) ); #ifndef _XBOX int numSparks = random->RandomInt( 8, 16 ); #else int numSparks = random->RandomInt( 2, 4 ); #endif Vector dir; float spread = 1.0f; TrailParticle *tParticle; // Dump out sparks int i; for ( i = 0; i < numSparks; i++ ) { tParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), m_Material_FireCloud, m_vecOrigin ); if ( tParticle == NULL ) break; tParticle->m_flLifetime = 0.0f; tParticle->m_flDieTime = random->RandomFloat( 0.1f, 0.15f ); dir.Random( -spread, spread ); dir += m_vecDirection; VectorNormalize( dir ); tParticle->m_flWidth = random->RandomFloat( 2.0f, 16.0f ); tParticle->m_flLength = random->RandomFloat( 0.05f, 0.1f ); tParticle->m_vecVelocity = dir * random->RandomFloat( 1500, 2500 ); Color32Init( tParticle->m_color, 255, 255, 255, 255 ); } #ifndef _XBOX // // Chunks // Vector offset; CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create( "CreateDebris 2", m_vecOrigin, Vector(128,128,128) ); if ( !fleckEmitter ) return; // Setup our collision information fleckEmitter->m_ParticleCollision.Setup( m_vecOrigin, &m_vecDirection, 0.9f, 512, 1024, 800, 0.5f ); #ifdef _XBOX int numFlecks = random->RandomInt( 8, 16 ); #else int numFlecks = random->RandomInt( 16, 32 ); #endif // _XBOX // Dump out flecks for ( i = 0; i < numFlecks; i++ ) { offset = m_vecOrigin + ( m_vecDirection * 16.0f ); offset[0] += random->RandomFloat( -8.0f, 8.0f ); offset[1] += random->RandomFloat( -8.0f, 8.0f ); offset[2] += random->RandomFloat( -8.0f, 8.0f ); FleckParticle *pParticle = (FleckParticle *) fleckEmitter->AddParticle( sizeof(FleckParticle), g_Mat_Fleck_Cement[random->RandomInt(0,1)], offset ); if ( pParticle == NULL ) break; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 3.0f; dir[0] = m_vecDirection[0] + random->RandomFloat( -1.0f, 1.0f ); dir[1] = m_vecDirection[1] + random->RandomFloat( -1.0f, 1.0f ); dir[2] = m_vecDirection[2] + random->RandomFloat( -1.0f, 1.0f ); pParticle->m_uchSize = random->RandomInt( 1, 3 ); VectorNormalize( dir ); float fForce = ( random->RandomFloat( 64, 256 ) * ( 4 - pParticle->m_uchSize ) ); float fDev = ScaleForceByDeviation( dir, m_vecDirection, 0.8f ); pParticle->m_vecVelocity = dir * ( fForce * ( 16.0f * (fDev*fDev*0.5f) ) ); pParticle->m_flRoll = random->RandomFloat( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( 0, 360 ); float colorRamp = random->RandomFloat( 0.5f, 1.5f ); pParticle->m_uchColor[0] = min( 1.0f, 0.25f*colorRamp )*255.0f; pParticle->m_uchColor[1] = min( 1.0f, 0.25f*colorRamp )*255.0f; pParticle->m_uchColor[2] = min( 1.0f, 0.25f*colorRamp )*255.0f; } #endif // !_XBOX }
//----------------------------------------------------------------------------- // Purpose: // Input : &origin - // &normal - // scale - // r - // g - // b - // flags - //----------------------------------------------------------------------------- void FX_BloodSpray( const Vector &origin, const Vector &normal, float scale, unsigned char r, unsigned char g, unsigned char b, int flags ) { if ( UTIL_IsLowViolence() ) return; //debugoverlay->AddLineOverlay( origin, origin + normal * 72, 255, 255, 255, true, 10 ); Vector offset; float spread = 0.2f; //Find area ambient light color and use it to tint smoke Vector worldLight = WorldGetLightForPoint( origin, true ); Vector color = Vector( (float)(worldLight[0] * r) / 255.0f, (float)(worldLight[1] * g) / 255.0f, (float)(worldLight[2] * b) / 255.0f ); float colorRamp; int i; Vector offDir; Vector right; Vector up; if (normal != Vector(0, 0, 1) ) { right = normal.Cross( Vector(0, 0, 1) ); up = right.Cross( normal ); } else { right = Vector(0, 0, 1); up = right.Cross( normal ); } // // Dump out drops // if (flags & FX_BLOODSPRAY_DROPS) { TrailParticle *tParticle; CSmartPtr<CTrailParticles> pTrailEmitter = CTrailParticles::Create( "blooddrops" ); if ( !pTrailEmitter ) return; pTrailEmitter->SetSortOrigin( origin ); // Partial gravity on blood drops. pTrailEmitter->SetGravity( 600.0 ); pTrailEmitter->GetBinding().SetBBox( origin - Vector( 32, 32, 32 ), origin + Vector( 32, 32, 32 ) ); pTrailEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN ); pTrailEmitter->SetVelocityDampen( 0.2f ); PMaterialHandle hMaterial = ParticleMgr()->GetPMaterial( "effects/blood_drop" ); // // Long stringy drops of blood. // for ( i = 0; i < 14; i++ ) { // Originate from within a circle 'scale' inches in diameter. offset = origin; offset += right * random->RandomFloat( -0.5f, 0.5f ) * scale; offset += up * random->RandomFloat( -0.5f, 0.5f ) * scale; tParticle = (TrailParticle *) pTrailEmitter->AddParticle( sizeof(TrailParticle), hMaterial, offset ); if ( tParticle == NULL ) break; tParticle->m_flLifetime = 0.0f; offDir = normal + RandomVector( -0.3f, 0.3f ); tParticle->m_vecVelocity = offDir * random->RandomFloat( 4.0f * scale, 40.0f * scale ); tParticle->m_vecVelocity[2] += random->RandomFloat( 4.0f, 16.0f ) * scale; tParticle->m_flWidth = random->RandomFloat( 0.125f, 0.275f ) * scale; tParticle->m_flLength = random->RandomFloat( 0.02f, 0.03f ) * scale; tParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); FloatToColor32( tParticle->m_color, color[0], color[1], color[2], 1.0f ); } // // Shorter droplets. // for ( i = 0; i < 24; i++ ) { // Originate from within a circle 'scale' inches in diameter. offset = origin; offset += right * random->RandomFloat( -0.5f, 0.5f ) * scale; offset += up * random->RandomFloat( -0.5f, 0.5f ) * scale; tParticle = (TrailParticle *) pTrailEmitter->AddParticle( sizeof(TrailParticle), hMaterial, offset ); if ( tParticle == NULL ) break; tParticle->m_flLifetime = 0.0f; offDir = normal + RandomVector( -1.0f, 1.0f ); offDir[2] += random->RandomFloat(0, 1.0f); tParticle->m_vecVelocity = offDir * random->RandomFloat( 2.0f * scale, 25.0f * scale ); tParticle->m_vecVelocity[2] += random->RandomFloat( 4.0f, 16.0f ) * scale; tParticle->m_flWidth = random->RandomFloat( 0.25f, 0.375f ) * scale; tParticle->m_flLength = random->RandomFloat( 0.0025f, 0.005f ) * scale; tParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); FloatToColor32( tParticle->m_color, color[0], color[1], color[2], 1.0f ); } } if ((flags & FX_BLOODSPRAY_GORE) || (flags & FX_BLOODSPRAY_CLOUD)) { CSmartPtr<CBloodSprayEmitter> pSimple = CBloodSprayEmitter::Create( "bloodgore" ); if ( !pSimple ) return; pSimple->SetSortOrigin( origin ); pSimple->SetGravity( 0 ); PMaterialHandle hMaterial; // // Tight blossom of blood at the center. // if (flags & FX_BLOODSPRAY_GORE) { hMaterial = ParticleMgr()->GetPMaterial( "effects/blood_gore" ); SimpleParticle *pParticle; for ( i = 0; i < 6; i++ ) { // Originate from within a circle 'scale' inches in diameter. offset = origin + ( 0.5 * scale * normal ); offset += right * random->RandomFloat( -0.5f, 0.5f ) * scale; offset += up * random->RandomFloat( -0.5f, 0.5f ) * scale; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial, offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.3f; spread = 0.2f; pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += normal * random->RandomInt( 10, 100 ); //VectorNormalize( pParticle->m_vecVelocity ); colorRamp = random->RandomFloat( 0.75f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = random->RandomFloat( scale * 0.25, scale ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 2; pParticle->m_uchStartAlpha = random->RandomInt( 200, 255 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = 0.0f; } } } // // Diffuse cloud just in front of the exit wound. // if (flags & FX_BLOODSPRAY_CLOUD) { hMaterial = ParticleMgr()->GetPMaterial( "effects/blood_puff" ); SimpleParticle *pParticle; for ( i = 0; i < 6; i++ ) { // Originate from within a circle '2 * scale' inches in diameter. offset = origin + ( scale * normal ); offset += right * random->RandomFloat( -1, 1 ) * scale; offset += up * random->RandomFloat( -1, 1 ) * scale; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial, offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 0.8f); spread = 0.5f; pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += normal * random->RandomInt( 100, 200 ); colorRamp = random->RandomFloat( 0.75f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = random->RandomFloat( scale * 1.5f, scale * 2.0f ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomInt( 80, 128 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = 0.0f; } } } } // TODO: Play a sound? //CLocalPlayerFilter filter; //C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, CHAN_VOICE, "Physics.WaterSplash", 1.0, ATTN_NORM, 0, 100, &origin ); }
//----------------------------------------------------------------------------- // Purpose: // Input : &origin - // &normal - // scale - // *pColor - //----------------------------------------------------------------------------- void FX_GunshotSlimeSplash( const Vector &origin, const Vector &normal, float scale ) { if ( cl_show_splashes.GetBool() == false ) return; VPROF_BUDGET( "FX_GunshotSlimeSplash", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); float colorRamp; float flScale = MIN( 1.0f, scale / 8.0f ); PMaterialHandle hMaterial = ParticleMgr()->GetPMaterial( "effects/slime1" ); PMaterialHandle hMaterial2 = ParticleMgr()->GetPMaterial( "effects/splash4" ); Vector color; float luminosity; // Get our lighting information FX_GetSplashLighting( origin + ( normal * scale ), &color, &luminosity ); Vector offDir; Vector offset; TrailParticle *tParticle; CSmartPtr<CTrailParticles> sparkEmitter = CTrailParticles::Create( "splash" ); if ( !sparkEmitter ) return; sparkEmitter->SetSortOrigin( origin ); sparkEmitter->m_ParticleCollision.SetGravity( 800.0f ); sparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN ); sparkEmitter->SetVelocityDampen( 2.0f ); if ( IsXbox() ) { sparkEmitter->GetBinding().SetBBox( origin - Vector( 32, 32, 64 ), origin + Vector( 32, 32, 64 ) ); } //Dump out drops for ( int i = 0; i < 24; i++ ) { offset = origin; offset[0] += random->RandomFloat( -16.0f, 16.0f ) * flScale; offset[1] += random->RandomFloat( -16.0f, 16.0f ) * flScale; tParticle = (TrailParticle *) sparkEmitter->AddParticle( sizeof(TrailParticle), hMaterial, offset ); if ( tParticle == NULL ) break; tParticle->m_flLifetime = 0.0f; tParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); offDir = normal + RandomVector( -0.6f, 0.6f ); tParticle->m_vecVelocity = offDir * random->RandomFloat( SPLASH_MIN_SPEED * flScale * 3.0f, SPLASH_MAX_SPEED * flScale * 3.0f ); tParticle->m_vecVelocity[2] += random->RandomFloat( 32.0f, 64.0f ) * flScale; tParticle->m_flWidth = random->RandomFloat( 3.0f, 6.0f ) * flScale; tParticle->m_flLength = random->RandomFloat( 0.025f, 0.05f ) * flScale; colorRamp = random->RandomFloat( 0.75f, 1.25f ); tParticle->m_color.r = MIN( 1.0f, color.x * colorRamp ) * 255; tParticle->m_color.g = MIN( 1.0f, color.y * colorRamp ) * 255; tParticle->m_color.b = MIN( 1.0f, color.z * colorRamp ) * 255; tParticle->m_color.a = 255 * luminosity; } // Setup splash emitter CSmartPtr<CSplashParticle> pSimple = CSplashParticle::Create( "splish" ); pSimple->SetSortOrigin( origin ); pSimple->SetClipHeight( origin.z ); pSimple->SetParticleCullRadius( scale * 2.0f ); if ( IsXbox() ) { pSimple->GetBinding().SetBBox( origin - Vector( 32, 32, 64 ), origin + Vector( 32, 32, 64 ) ); } SimpleParticle *pParticle; // Tint colorRamp = random->RandomFloat( 0.75f, 1.0f ); color = Vector( 1.0f, 0.8f, 0.0f ) * color * colorRamp; //Main gout for ( int i = 0; i < 8; i++ ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial2, origin ); if ( pParticle == NULL ) break; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 2.0f; //NOTENOTE: We use a clip plane to realistically control our lifespan pParticle->m_vecVelocity.Random( -0.2f, 0.2f ); pParticle->m_vecVelocity += ( normal * random->RandomFloat( 4.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); pParticle->m_vecVelocity *= 50 * flScale * (8-i); colorRamp = random->RandomFloat( 0.75f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, 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 = 24 * flScale * RemapValClamped( i, 7, 0, 1, 0.5f ); pParticle->m_uchEndSize = MIN( 255, pParticle->m_uchStartSize * 2 ); pParticle->m_uchStartAlpha = RemapValClamped( i, 7, 0, 255, 32 ) * luminosity; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -4.0f, 4.0f ); } //Play a sound CLocalPlayerFilter filter; EmitSound_t ep; ep.m_nChannel = CHAN_VOICE; ep.m_pSoundName = "Physics.WaterSplash"; ep.m_flVolume = 1.0f; ep.m_SoundLevel = SNDLVL_NORM; ep.m_pOrigin = &origin; C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, ep ); }