//----------------------------------------------------------------------------- // Purpose: Trail smoke //----------------------------------------------------------------------------- void CASW_Shotgun_Pellet_Predicted::ClientThink( void ) { return; CSmartPtr<CSimpleEmitter> pEmitter = CSimpleEmitter::Create( "CASW_Shotgun_Pellet_Predicted::Effect" ); PMaterialHandle hSphereMaterial = pEmitter->GetPMaterial( "sprites/chargeball" ); // Add particles at the target. float flCur = gpGlobals->frametime; while ( m_ParticleEvent.NextEvent( flCur ) ) { Vector vecOrigin = GetAbsOrigin() + RandomVector( -2,2 ); pEmitter->SetSortOrigin( vecOrigin ); SimpleParticle *pParticle = (SimpleParticle *) pEmitter->AddParticle( sizeof(SimpleParticle), hSphereMaterial, vecOrigin ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.1f, 0.3f ); pParticle->m_uchStartSize = random->RandomFloat(2,4); pParticle->m_uchEndSize = pParticle->m_uchStartSize + 2; pParticle->m_vecVelocity = vec3_origin; pParticle->m_uchStartAlpha = 128; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomFloat( 180, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -1, 1 ); pParticle->m_uchColor[0] = 128; pParticle->m_uchColor[1] = 128; pParticle->m_uchColor[2] = 128; } }
//----------------------------------------------------------------------------- // Purpose: // Input : &origin - // &velocity - // scale - // numParticles - // *pColor - // iAlpha - // *pMaterial - // flRoll - // flRollDelta - //----------------------------------------------------------------------------- CSmartPtr<CSimpleEmitter> FX_Smoke( const Vector &origin, const Vector &velocity, float scale, int numParticles, float flDietime, unsigned char *pColor, int iAlpha, const char *pMaterial, float flRoll, float flRollDelta ) { VPROF_BUDGET( "FX_Smoke", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_Smoke" ); pSimple->SetSortOrigin( origin ); SimpleParticle *pParticle; // Smoke for ( int i = 0; i < numParticles; i++ ) { PMaterialHandle hMaterial = pSimple->GetPMaterial( pMaterial ); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial, origin ); if ( pParticle == NULL ) return NULL; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = flDietime; pParticle->m_vecVelocity = velocity; for( int i = 0; i < 3; ++i ) { pParticle->m_uchColor[i] = pColor[i]; } pParticle->m_uchStartAlpha = iAlpha; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = scale; pParticle->m_uchEndSize = pParticle->m_uchStartSize*2; pParticle->m_flRoll = flRoll; pParticle->m_flRollDelta = flRollDelta; } return pSimple; }
//----------------------------------------------------------------------------- // Purpose: Spawn effects if I'm sapping //----------------------------------------------------------------------------- void C_GrenadeAntiPersonnel::ClientThink( void ) { // Fire smoke puffs out the side CSmartPtr<CSimpleEmitter> pSmokeEmitter = CSimpleEmitter::Create( "AntipersonnelGrenade::Effect" ); pSmokeEmitter->SetSortOrigin( GetAbsOrigin() ); int iSmokeClouds = random->RandomInt(1,2); for ( int i = 0; i < iSmokeClouds; i++ ) { SimpleParticle *pParticle = (SimpleParticle *) pSmokeEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[1], GetAbsOrigin() ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.1f, 0.3f ); pParticle->m_uchStartSize = random->RandomFloat(2,5); pParticle->m_uchEndSize = pParticle->m_uchStartSize + 2; pParticle->m_vecVelocity = vec3_origin; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 64; pParticle->m_flRoll = random->RandomFloat( 180, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -1, 1 ); pParticle->m_uchColor[0] = 50; pParticle->m_uchColor[1] = 250; pParticle->m_uchColor[2] = 50; } }
//----------------------------------------------------------------------------- // Purpose: // Input : &origin - // &normal - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- void FX_CreateImpactDust( Vector &origin, Vector &normal ) { VPROF_BUDGET( "FX_CreateImpactDust", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); Vector offset = origin + ( normal * 4.0f );; float totalScale = random->RandomFloat( 0.5f, 1.25f ); float scale = random->RandomFloat( 3.0f, 4.0f ) * totalScale; CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_CreateImpactDust" ); pSimple->SetSortOrigin( origin ); SimpleParticle *pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof(SimpleParticle), pSimple->GetPMaterial( "particle/particle_sphere" ), offset ); if (pParticle) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.1f; pParticle->m_uchColor[0] = pParticle->m_uchColor[1] = pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = random->RandomInt( 32, 64 );; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = scale; pParticle->m_uchEndSize = scale*4.0f; } }
void C_EnvPortalPathTrack::UpdateParticles_Active ( void ) { // Emitters must be valid if ( SetupEmitters() == false ) return; // Reset our sort origin m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() ); SimpleParticle *sParticle; // Do the charging particles m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() ); Vector forward, right, up; AngleVectors( GetAbsAngles(), &forward, &right, &up ); Vector offset; float dist; int numParticles = floor( 4.0f ); for ( int i = 0; i < numParticles; i++ ) { dist = random->RandomFloat( 4.0f, 64.0f ); offset = forward * dist; dist = RemapValClamped( dist, 4.0f, 64.0f, 6.0f, 1.0f ); offset += right * random->RandomFloat( -4.0f * dist, 4.0f * dist ); offset += up * random->RandomFloat( -4.0f * dist, 4.0f * dist ); offset += GetAbsOrigin(); sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( "effects/strider_muzzle" ), offset ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = Vector(0,0,8); sParticle->m_flDieTime = 0.5f; sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); sParticle->m_flRollDelta = 0.0f; float alpha = 255; sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = random->RandomFloat( 1, 2 ); sParticle->m_uchEndSize = 0; } }
void FX_MetalScrape(Vector &position, Vector &normal) { VPROF_BUDGET("FX_MetalScrape", VPROF_BUDGETGROUP_PARTICLE_RENDERING); Vector offset = position + (normal * 1.0f); CSmartPtr<CTrailParticles> sparkEmitter = CTrailParticles::Create("FX_MetalScrape 1"); if (!sparkEmitter) return; sparkEmitter->SetSortOrigin(offset); //Setup our collision information sparkEmitter->Setup(offset, &normal, METAL_SCRAPE_SPREAD, METAL_SCRAPE_MINSPEED, METAL_SCRAPE_MAXSPEED, METAL_SCRAPE_GRAVITY, METAL_SCRAPE_DAMPEN, bitsPARTICLE_TRAIL_VELOCITY_DAMPEN); int numSparks = random->RandomInt(4, 8); if (g_Material_Spark == NULL) { g_Material_Spark = sparkEmitter->GetPMaterial("effects/spark"); } Vector dir; TrailParticle *pParticle; float length = 0.06f; //Dump out sparks for (int i = 0; i < numSparks; i++) { pParticle = (TrailParticle *) sparkEmitter->AddParticle(sizeof(TrailParticle), g_Material_Spark, offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; float spreadOfs = random->RandomFloat(0.0f, 2.0f); dir[0] = normal[0] + random->RandomFloat(-(METAL_SCRAPE_SPREAD*spreadOfs), (METAL_SCRAPE_SPREAD*spreadOfs)); dir[1] = normal[1] + random->RandomFloat(-(METAL_SCRAPE_SPREAD*spreadOfs), (METAL_SCRAPE_SPREAD*spreadOfs)); dir[2] = normal[2] + random->RandomFloat(-(METAL_SCRAPE_SPREAD*spreadOfs), (METAL_SCRAPE_SPREAD*spreadOfs)); pParticle->m_flWidth = random->RandomFloat(2.0f, 5.0f); pParticle->m_flLength = random->RandomFloat(length*0.25f, length); pParticle->m_flDieTime = random->RandomFloat(2.0f, 2.0f); pParticle->m_vecVelocity = dir * random->RandomFloat((METAL_SCRAPE_MINSPEED*(2.0f - spreadOfs)), (METAL_SCRAPE_MAXSPEED*(2.0f - spreadOfs))); Color32Init(pParticle->m_color, 255, 255, 255, 255); } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void HunterDamageCallback( const CEffectData &data ) { CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "HunterDamage" ); if ( pGlassEmitter == NULL ) return; pGlassEmitter->SetSortOrigin( data.m_vOrigin ); // Handle increased scale const float flMaxSpeed = 400.0f; const float flMinSpeed = 50.0f; float flAngularSpray = 1.0f; // Setup our collision information pGlassEmitter->m_ParticleCollision.Setup( data.m_vOrigin, &data.m_vNormal, flAngularSpray, flMinSpeed, flMaxSpeed, 600.0f, 0.2f ); Vector dir, end; int numFlecks = 32; Particle3D *pFleckParticle; Vector spawnOffset; //Dump out flecks for ( int i = 0; i < numFlecks; i++ ) { spawnOffset = data.m_vOrigin + RandomVector( -32.0f, 32.0f ); pFleckParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Antlion[random->RandomInt(0,1)], spawnOffset ); if ( pFleckParticle == NULL ) break; pFleckParticle->m_flLifeRemaining = random->RandomFloat( 2.0f, 3.0f ); dir[0] = data.m_vNormal[0] + random->RandomFloat( -flAngularSpray, flAngularSpray ); dir[1] = data.m_vNormal[1] + random->RandomFloat( -flAngularSpray, flAngularSpray ); dir[2] = data.m_vNormal[2] + random->RandomFloat( -flAngularSpray, flAngularSpray ); pFleckParticle->m_uchSize = random->RandomInt( 3, 8 ); pFleckParticle->m_vecVelocity = dir * random->RandomFloat( flMinSpeed, flMaxSpeed); pFleckParticle->m_vAngles = RandomAngle( 0, 360 ); pFleckParticle->m_flAngSpeed = random->RandomFloat( -800, 800 ); unsigned char color = 255; pFleckParticle->m_uchFrontColor[0] = color; pFleckParticle->m_uchFrontColor[1] = color; pFleckParticle->m_uchFrontColor[2] = color; pFleckParticle->m_uchBackColor[0] = color * 0.25f; pFleckParticle->m_uchBackColor[1] = color * 0.25f; pFleckParticle->m_uchBackColor[2] = color * 0.25f; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_EntityFlame::Simulate( void ) { if (m_bAttachedToHitboxes) { UpdateHitBoxFlames(); } else { m_pEmitter->SetSortOrigin( GetAbsOrigin() ); float tempDelta = gpGlobals->frametime; SimpleParticle *pParticle; Vector offset; while( m_ParticleSpawn.NextEvent( tempDelta ) ) { offset.Random( -m_flSize, m_flSize ); pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle[random->RandomInt( 0, NUM_FLAMELETS-1 )], GetAbsOrigin() + offset ); if ( pParticle ) { pParticle->m_flDieTime = 0.4f; pParticle->m_flLifetime = 0.0f; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta= random->RandomFloat( -2.0f, 2.0f ); pParticle->m_uchStartSize = random->RandomInt( 4, 6 ); pParticle->m_uchEndSize = random->RandomInt( 12, 16 ); pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; int cScale = 255;//random->RandomInt( 192, 255 ); pParticle->m_uchColor[0] = cScale; pParticle->m_uchColor[1] = cScale; pParticle->m_uchColor[2] = cScale; Vector dir; dir.x = random->RandomFloat( -1.0f, 1.0f ); dir.y = random->RandomFloat( -1.0f, 1.0f ); dir.z = random->RandomFloat( 0.5f, 1.0f ); pParticle->m_vecVelocity = dir * random->RandomInt( 4, 32 ); pParticle->m_vecVelocity[2] = random->RandomInt( 32, 64 ); } } } }
//----------------------------------------------------------------------------- // Chopper muzzle flashes //----------------------------------------------------------------------------- void MuzzleFlash_Chopper( ClientEntityHandle_t hEntity, int attachmentIndex ) { VPROF_BUDGET( "MuzzleFlash_Chopper", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); matrix3x4_t matAttachment; // If the client hasn't seen this entity yet, bail. if ( !FX_GetAttachmentTransform( hEntity, attachmentIndex, matAttachment ) ) return; CSmartPtr<CLocalSpaceEmitter> pSimple = CLocalSpaceEmitter::Create( "MuzzleFlash", hEntity, attachmentIndex ); SimpleParticle *pParticle; Vector forward(1,0,0), offset; //NOTENOTE: All coords are in local space float flScale = random->RandomFloat( 2.5f, 4.5f ); // Flash for ( int i = 1; i < 7; i++ ) { offset = (forward * (i*2.0f*flScale)); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( VarArgs( "effects/combinemuzzle%d", random->RandomInt(1,2) ) ), offset ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.05f, 0.1f ); pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 128; pParticle->m_uchStartSize = ( (random->RandomFloat( 6.0f, 8.0f ) * (10-(i))/7) * flScale ); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = 0.0f; } // Grab the origin out of the transform for the attachment Vector origin; MatrixGetColumn( matAttachment, 3, &origin ); CreateMuzzleflashELight( origin, 6, 128, 256, hEntity ); }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ void C_PlasmaBeamNode::ClientThink(void) { if (!m_bSprayOn) { return; } trace_t trace; Vector vEndTrace = GetAbsOrigin() + (0.3*GetAbsVelocity()); UTIL_TraceLine( GetAbsOrigin(), vEndTrace, MASK_SHOT, NULL, COLLISION_GROUP_NONE, &trace ); if ( trace.fraction != 1.0f || trace.startsolid) { m_bSprayOn = false; return; } PMaterialHandle handle = m_pFirePlasmaSpray->GetPMaterial( "sprites/plasmaember" ); for (int i=0;i<SPRAYS_PER_THINK;i++) { SimpleParticle *sParticle; //Make a new particle if ( random->RandomInt( 0, 2 ) == 0 ) { float ranx = random->RandomFloat( -28.0f, 28.0f ); float rany = random->RandomFloat( -28.0f, 28.0f ); float ranz = random->RandomFloat( -28.0f, 28.0f ); Vector vNewPos = GetAbsOrigin(); Vector vAdd = Vector(GetAbsAngles().x,GetAbsAngles().y,GetAbsAngles().z)*random->RandomFloat(-60,120); vNewPos += vAdd; sParticle = (SimpleParticle *) m_pFirePlasmaSpray->AddParticle( sizeof(SimpleParticle), handle, vNewPos ); sParticle->m_flLifetime = 0.0f; sParticle->m_flDieTime = PLASMASPARK_LIFETIME; sParticle->m_vecVelocity = GetAbsVelocity(); sParticle->m_vecVelocity.x += ranx; sParticle->m_vecVelocity.y += rany; sParticle->m_vecVelocity.z += ranz; m_pFirePlasmaSpray->m_pOwner = this; } } SetNextClientThink(gpGlobals->curtime + 0.05); }
//----------------------------------------------------------------------------- // Purpose: // Input : &data - //----------------------------------------------------------------------------- void WheelDustCallback( const CEffectData &data ) { CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" ); pSimple->SetSortOrigin( data.m_vOrigin ); pSimple->SetNearClip( 32, 64 ); SimpleParticle *pParticle; Vector offset; //FIXME: Better sampling area offset = data.m_vOrigin + ( data.m_vNormal * data.m_flScale ); //Find area ambient light color and use it to tint smoke Vector worldLight = WorldGetLightForPoint( offset, true ); //Throw puffs offset.Random( -(data.m_flScale*16.0f), data.m_flScale*16.0f ); offset.z = 0.0f; offset += data.m_vOrigin + ( data.m_vNormal * data.m_flScale ); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[0], offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); pParticle->m_vecVelocity = RandomVector( -1.0f, 1.0f ); VectorNormalize( pParticle->m_vecVelocity ); pParticle->m_vecVelocity[2] += random->RandomFloat( 16.0f, 32.0f ) * (data.m_flScale*2.0f); int color = random->RandomInt( 100, 150 ); pParticle->m_uchColor[0] = 16 + ( worldLight[0] * (float) color ); pParticle->m_uchColor[1] = 8 + ( worldLight[1] * (float) color ); pParticle->m_uchColor[2] = ( worldLight[2] * (float) color ); pParticle->m_uchStartAlpha = random->RandomInt( 64.0f*data.m_flScale, 128.0f*data.m_flScale ); pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = random->RandomInt( 16, 24 ) * data.m_flScale; pParticle->m_uchEndSize = random->RandomInt( 32, 48 ) * data.m_flScale; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f ); } }
//----------------------------------------------------------------------------- // Purpose: // Input : flPerc - //----------------------------------------------------------------------------- void C_MortarShell::AddRisingParticles( float flPerc ) { SimpleParticle *sParticle; Vector offset; float radius = m_flRadius * 0.25f * flPerc; float val = RemapValClamped( gpGlobals->curtime, m_flStarttime, m_flStarttime + m_flLifespan, 0.0f, 1.0f ); float flCur = gpGlobals->frametime; // Anime ground effects while ( m_ParticleEvent.NextEvent( flCur ) ) { offset.x = random->RandomFloat( -radius, radius ); offset.y = random->RandomFloat( -radius, radius ); offset.z = random->RandomFloat( -8.0f, 8.0f ); offset += GetAbsOrigin(); sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/spark" ), offset ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( 32.0f, 256.0f ) * Bias( val, 0.25f ) ); sParticle->m_uchStartSize = random->RandomFloat( 4, 8 ) * flPerc; sParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); float alpha = 255 * flPerc; sParticle->m_flRollDelta = Helper_RandomFloat( -8.0f * flPerc, 8.0f * flPerc ); sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchEndSize = 0; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_EnvStarfield::ClientThink( void ) { if ( !m_bOn || !m_flDensity ) return; PMaterialHandle hParticleMaterial = m_pEmitter->GetPMaterial( "effects/spark_noz" ); // Find a start & end point for the particle // Start particles straight ahead of the client Vector vecViewOrigin = MainViewOrigin(engine->GetActiveSplitScreenPlayerSlot()); // Determine the number of particles m_flNumParticles += 1.0 * (m_flDensity); int iNumParticles = floor(m_flNumParticles); m_flNumParticles -= iNumParticles; // Add particles for ( int i = 0; i < iNumParticles; i++ ) { float flDiameter = cl_starfield_diameter.GetFloat(); Vector vecStart = vecViewOrigin + (MainViewForward(engine->GetActiveSplitScreenPlayerSlot()) * cl_starfield_distance.GetFloat() ); Vector vecEnd = vecViewOrigin + (MainViewRight(engine->GetActiveSplitScreenPlayerSlot()) * RandomFloat(-flDiameter,flDiameter)) + (MainViewUp(engine->GetActiveSplitScreenPlayerSlot()) * RandomFloat(-flDiameter,flDiameter)); Vector vecDir = (vecEnd - vecStart); float flDistance = VectorNormalize( vecDir ); float flTravelTime = 2.0; // Start a random amount along the path vecStart += vecDir * ( RandomFloat(0.1,0.3) * flDistance ); TrailParticle *pParticle = (TrailParticle *) m_pEmitter->AddParticle( sizeof(TrailParticle), hParticleMaterial, vecStart ); if ( pParticle ) { pParticle->m_vecVelocity = vecDir * (flDistance / flTravelTime); pParticle->m_flDieTime = flTravelTime; pParticle->m_flLifetime = 0; pParticle->m_flWidth = RandomFloat( 1, 3 ); pParticle->m_flLength = RandomFloat( 0.05, 0.4 ); pParticle->m_color.r = 255; pParticle->m_color.g = 255; pParticle->m_color.b = 255; pParticle->m_color.a = 255; } } }
//----------------------------------------------------------------------------- // Purpose: // Input : flPerc - //----------------------------------------------------------------------------- void C_MortarShell::AddExplodingParticles( float flPerc ) { SimpleParticle *sParticle; Vector offset; float radius = 48.0f * flPerc; float flCur = gpGlobals->frametime; // Anime ground effects while ( m_ParticleEvent.NextEvent( flCur ) ) { offset.x = random->RandomFloat( -radius, radius ); offset.y = random->RandomFloat( -radius, radius ); offset.z = random->RandomFloat( -8.0f, 8.0f ); offset += GetAbsOrigin(); sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/spark" ), offset ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = RandomVector( -1.0f, 1.0f ) + Vector( 0, 0, 1 ); sParticle->m_vecVelocity *= ( 750.0f * flPerc ); sParticle->m_uchStartSize = random->RandomFloat( 2, 4 ) * flPerc; sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); float alpha = 255 * flPerc; sParticle->m_flRollDelta = Helper_RandomFloat( -8.0f * flPerc, 8.0f * flPerc ); sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchEndSize = 0; } }
//----------------------------------------------------------------------------- // Purpose: // Input : bool - //----------------------------------------------------------------------------- void C_TEShowLine::PostDataUpdate( DataUpdateType_t updateType ) { Vector vec; float len; StandardParticle_t *p; int dec; static int tracercount; VectorSubtract (m_vecEnd, m_vecOrigin, vec); len = VectorNormalize (vec); dec = 3; VectorScale(vec, dec, vec); CSmartPtr<CTEParticleRenderer> pRen = CTEParticleRenderer::Create( "TEShowLine", m_vecOrigin ); if( !pRen ) return; while (len > 0) { len -= dec; p = pRen->AddParticle(); if ( p ) { p->m_Velocity.Init(); pRen->SetParticleLifetime(p, 30); p->SetColor(0, 1, 1); p->SetAlpha(1); pRen->SetParticleType(p, pt_static); p->m_Pos = m_vecOrigin; m_vecOrigin += vec; } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void FX_GunshipMuzzleEffect( const Vector &origin, const QAngle &angles, float scale, ClientEntityHandle_t hEntity, unsigned char *pFlashColor ) { VPROF_BUDGET( "FX_GunshipMuzzleEffect", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "MuzzleFlash" ); pSimple->SetSortOrigin( origin ); SimpleParticle *pParticle; Vector forward, offset; AngleVectors( angles, &forward ); // // Flash // offset = origin; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/gunshipmuzzle" ), offset ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.15f; pParticle->m_vecVelocity.Init(); pParticle->m_uchStartSize = random->RandomFloat( 40.0, 50.0 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = 0.15f; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 255; }
//----------------------------------------------------------------------------- // Purpose: Warp effect that looks like it's sucking things to it //----------------------------------------------------------------------------- void FX_BuildWarpSuck( Vector &vecOrigin, QAngle &vecAngles, float flScale ) { CSmartPtr<CTrailParticles> pEmitter = CTrailParticles::Create( "BuildWarpSuck" ); PMaterialHandle hParticleMaterial = pEmitter->GetPMaterial( "effects/bluespark" ); pEmitter->Setup( (Vector &) vecOrigin, NULL, 0.0, 0, 64, 0, 0, bitsPARTICLE_TRAIL_VELOCITY_DAMPEN | bitsPARTICLE_TRAIL_FADE ); // Add particles int iNumParticles = 60; for ( int i = 0; i < iNumParticles; i++ ) { Vector vOffset = RandomVector( -1, 1 ); VectorNormalize( vOffset ); float flDistance = RandomFloat( 16, 64 ) * flScale; Vector vPos = vecOrigin + (vOffset * flDistance); TrailParticle *pParticle = (TrailParticle *) pEmitter->AddParticle( sizeof(TrailParticle), hParticleMaterial, vPos ); if ( pParticle ) { float flSpeed = RandomFloat(8,16) * (flScale * flScale * flScale); pParticle->m_vecVelocity = vOffset * -flSpeed; pParticle->m_flDieTime = min( 3, (flDistance / flSpeed) + RandomFloat(0.0, 0.2) ); pParticle->m_flLifetime = 0; pParticle->m_flWidth = RandomFloat( 2, 3 ) * flScale; pParticle->m_flLength = RandomFloat( 1, 2 ) * flScale; pParticle->m_color.r = 1.0f; pParticle->m_color.g = 1.0f; pParticle->m_color.b = 1.0f; pParticle->m_color.a = 1.0f; } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_RotorWashEmitter::ClientThink( void ) { SetNextClientThink( gpGlobals->curtime + ROTORWASH_THINK_INTERVAL ); trace_t tr; UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin()+(Vector(0, 0, -1024)), (MASK_SOLID_BRUSHONLY|CONTENTS_WATER|CONTENTS_SLIME), NULL, COLLISION_GROUP_NONE, &tr ); if ( /*!m_bIgnoreSolid && */(tr.fraction == 1.0f || tr.startsolid || tr.allsolid) ) return; // If we hit the skybox, don't do it either if ( tr.surface.flags & SURF_SKY ) return; float heightScale = RemapValClamped( tr.fraction * 1024, 512, 1024, 1.0f, 0.0f ); Vector vecDustColor; if ( tr.contents & CONTENTS_WATER ) { vecDustColor.x = 0.8f; vecDustColor.y = 0.8f; vecDustColor.z = 0.75f; } else if ( tr.contents & CONTENTS_SLIME ) { vecDustColor.x = 0.6f; vecDustColor.y = 0.5f; vecDustColor.z = 0.15f; } else { vecDustColor.x = 0.35f; vecDustColor.y = 0.3f; vecDustColor.z = 0.25f; } #ifndef _XBOX InitSpawner(); if ( m_pSimple.IsValid() == false ) return; m_pSimple->SetSortOrigin( GetAbsOrigin() ); PMaterialHandle *hMaterial; // Cache and set our material based on the surface we're over (ie. water) if ( tr.contents & (CONTENTS_WATER|CONTENTS_SLIME) ) { if ( m_hWaterMaterial[0] == NULL ) { m_hWaterMaterial[0] = m_pSimple->GetPMaterial("effects/splash1"); m_hWaterMaterial[1] = m_pSimple->GetPMaterial("effects/splash2"); } hMaterial = m_hWaterMaterial; } else { hMaterial = g_Mat_DustPuff; } #endif // !XBOX // If we're above water, make ripples if ( tr.contents & (CONTENTS_WATER|CONTENTS_SLIME) ) { float flScale = random->RandomFloat( 7.5f, 8.5f ); Vector color = Vector( 0.8f, 0.8f, 0.75f ); Vector startPos = tr.endpos + Vector(0,0,8); Vector endPos = tr.endpos + Vector(0,0,-64); if ( tr.fraction < 1.0f ) { //Add a ripple quad to the surface FX_AddQuad( tr.endpos + ( tr.plane.normal * 0.5f ), tr.plane.normal, 64.0f * flScale, 128.0f * flScale, 0.8f, 0.75f * heightScale, 0.0f, 0.75f, random->RandomFloat( 0, 360 ), random->RandomFloat( -2.0f, 2.0f ), vecDustColor, 0.2f, "effects/splashwake3", (FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) ); } } #ifndef _XBOX int numRingSprites = 32; float yaw = random->RandomFloat( 0, 2*M_PI ); // Randomly placed on the unit circle float yawIncr = (2*M_PI) / numRingSprites; Vector vecForward; Vector offset; SimpleParticle *pParticle; // Draw the rings for ( int i = 0; i < numRingSprites; i++ ) { // Get our x,y on the unit circle SinCos( yaw, &vecForward.y, &vecForward.x ); // Increment ahead yaw += yawIncr; // @NOTE toml (3-28-07): broke out following expression because vc2005 optimizer was screwing up in presence of SinCos inline assembly. Would also // go away if offset were referenced below as in the AddLineOverlay() //offset = ( RandomVector( -4.0f, 4.0f ) + tr.endpos ) + ( vecForward * 128.0f ); offset = vecForward * 128.0f; offset += tr.endpos + RandomVector( -4.0f, 4.0f ); pParticle = (SimpleParticle *) m_pSimple->AddParticle( sizeof(SimpleParticle), hMaterial[random->RandomInt(0,1)], offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.25f, 1.0f ); pParticle->m_vecVelocity = vecForward * random->RandomFloat( 1000, 1500 ); #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif if ( tr.contents & CONTENTS_SLIME ) { vecDustColor.x = random->RandomFloat( 0.4f, 0.6f ); vecDustColor.y = random->RandomFloat( 0.3f, 0.5f ); vecDustColor.z = random->RandomFloat( 0.1f, 0.2f ); } pParticle->m_uchColor[0] = vecDustColor.x * 255.0f; pParticle->m_uchColor[1] = vecDustColor.y * 255.0f; pParticle->m_uchColor[2] = vecDustColor.z * 255.0f; pParticle->m_uchStartSize = random->RandomInt( 16, 64 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomFloat( 16, 32 ) * heightScale; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.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: 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 ); }
void FX_DustImpact( const Vector &origin, trace_t *tr, float flScale ) { // // PC version // VPROF_BUDGET( "FX_DustImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); Vector offset; float spread = 0.2f; CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" ); pSimple->SetSortOrigin( origin ); // Three types of particle, ideally we want 4 of each. float fNumParticles = 4.0f * g_pParticleSystemMgr->ParticleThrottleScaling(); int nParticles1 = (int)( 0.50f + fNumParticles ); int nParticles2 = (int)( 0.83f + fNumParticles ); // <-- most visible particle type. int nParticles3 = (int)( 0.17f + fNumParticles ); SimpleParticle *pParticle; Vector color; float colorRamp; GetColorForSurface( tr, &color ); // To get a decent spread even when scaling down the number of particles... const static int nParticleIdArray[4] = {3,1,2,0}; int i; for ( i = 0; i < nParticles1; i++ ) { int nId = nParticleIdArray[i]; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 250, 500 ) * nId; // scaled pParticle->m_vecVelocity *= fForce * flScale; colorRamp = random->RandomFloat( 0.75f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; // scaled pParticle->m_uchStartSize = ( unsigned char )( flScale * random->RandomInt( 3, 4 ) * (nId+1) ); // scaled pParticle->m_uchEndSize = ( unsigned char )( flScale * pParticle->m_uchStartSize * 4 ); pParticle->m_uchStartAlpha = random->RandomInt( 32, 255 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f ); } } //Dust specs for ( i = 0; i < nParticles2; i++ ) { int nId = nParticleIdArray[i]; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.75f ); pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 250, 500 ) * nId; pParticle->m_vecVelocity *= fForce; colorRamp = random->RandomFloat( 0.75f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = random->RandomInt( 2, 4 ) * (nId+1); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 2; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f ); } } //Impact hit for ( i = 0; i < nParticles3; i++ ) { //int nId = nParticleIdArray[i]; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin ); if ( pParticle != NULL ) { offset = origin; offset[0] += random->RandomFloat( -8.0f, 8.0f ); offset[1] += random->RandomFloat( -8.0f, 8.0f ); pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); spread = 1.0f; pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += tr->plane.normal; VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 0, 50 ); pParticle->m_vecVelocity *= fForce; colorRamp = random->RandomFloat( 0.75f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = random->RandomInt( 1, 4 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomInt( 32, 64 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.0f ); } } }
//----------------------------------------------------------------------------- // Purpose: Blood puff //----------------------------------------------------------------------------- void FX_Blood( Vector &pos, Vector &dir, float r, float g, float b, float a ) { VPROF_BUDGET( "FX_Blood", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); // Cloud CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_Blood" ); if ( !pSimple ) return; pSimple->SetSortOrigin( pos ); Vector vDir; vDir[0] = dir[0] + random->RandomFloat( -1.0f, 1.0f ); vDir[1] = dir[1] + random->RandomFloat( -1.0f, 1.0f ); vDir[2] = dir[2] + random->RandomFloat( -1.0f, 1.0f ); VectorNormalize( vDir ); int i; for ( i = 0; i < 2; i++ ) { SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], pos ); if ( sParticle == NULL ) { return; } sParticle->m_flLifetime = 0.0f; sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); float speed = random->RandomFloat( 2.0f, 8.0f ); sParticle->m_vecVelocity = vDir * (speed*i); sParticle->m_vecVelocity[2] += random->RandomFloat( -32.0f, -16.0f ); sParticle->m_uchColor[0] = r; sParticle->m_uchColor[1] = g; sParticle->m_uchColor[2] = b; sParticle->m_uchStartAlpha = a; sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = 2; sParticle->m_uchEndSize = sParticle->m_uchStartSize*4; sParticle->m_flRoll = random->RandomInt( 0, 360 ); sParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f ); } for ( i = 0; i < 2; i++ ) { SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], pos ); if ( sParticle == NULL ) { return; } sParticle->m_flLifetime = 0.0f; sParticle->m_flDieTime = 0.5f; float speed = random->RandomFloat( 4.0f, 16.0f ); sParticle->m_vecVelocity = vDir * (speed*i); sParticle->m_uchColor[0] = r; sParticle->m_uchColor[1] = g; sParticle->m_uchColor[2] = b; sParticle->m_uchStartAlpha = 128; sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = 2; sParticle->m_uchEndSize = sParticle->m_uchStartSize*4; sParticle->m_flRoll = random->RandomInt( 0, 360 ); sParticle->m_flRollDelta = random->RandomFloat( -4.0f, 4.0f ); } }
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: //----------------------------------------------------------------------------- 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 }
static void CreateFleckParticles( const Vector& origin, const Vector &color, trace_t *trace, char materialType, int iScale ) { Vector spawnOffset = trace->endpos + ( trace->plane.normal * 1.0f ); CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create( "FX_DebrisFlecks", spawnOffset, Vector(5,5,5) ); if ( !fleckEmitter ) return; // Handle increased scale float flMaxSpeed = FLECK_MAX_SPEED * iScale; float flAngularSpray = MAX( 0.2, FLECK_ANGULAR_SPRAY - ( (float)iScale * 0.2f) ); // More power makes the spray more controlled // Setup our collision information fleckEmitter->m_ParticleCollision.Setup( spawnOffset, &trace->plane.normal, flAngularSpray, FLECK_MIN_SPEED, flMaxSpeed, FLECK_GRAVITY, FLECK_DAMPEN ); PMaterialHandle *hMaterial; switch ( materialType ) { case CHAR_TEX_WOOD: hMaterial = g_Mat_Fleck_Wood; break; case CHAR_TEX_CONCRETE: case CHAR_TEX_TILE: default: hMaterial = g_Mat_Fleck_Cement; break; } Vector dir, end; float colorRamp; float fScale = g_pParticleSystemMgr->ParticleThrottleScaling() * (float)iScale; int numFlecks = (int)( 0.5f + fScale * (float)( random->RandomInt( 4, 16 ) ) ); FleckParticle *pFleckParticle; //Dump out flecks int i; for ( i = 0; i < numFlecks; i++ ) { pFleckParticle = (FleckParticle *) fleckEmitter->AddParticle( sizeof(FleckParticle), hMaterial[random->RandomInt(0,1)], spawnOffset ); if ( pFleckParticle == NULL ) break; pFleckParticle->m_flLifetime = 0.0f; pFleckParticle->m_flDieTime = 3.0f; dir[0] = trace->plane.normal[0] + random->RandomFloat( -flAngularSpray, flAngularSpray ); dir[1] = trace->plane.normal[1] + random->RandomFloat( -flAngularSpray, flAngularSpray ); dir[2] = trace->plane.normal[2] + random->RandomFloat( -flAngularSpray, flAngularSpray ); pFleckParticle->m_uchSize = random->RandomInt( 1, 2 ); pFleckParticle->m_vecVelocity = dir * ( random->RandomFloat( FLECK_MIN_SPEED, flMaxSpeed) * ( 3 - pFleckParticle->m_uchSize ) ); pFleckParticle->m_flRoll = random->RandomFloat( 0, 360 ); pFleckParticle->m_flRollDelta = random->RandomFloat( 0, 360 ); colorRamp = random->RandomFloat( 0.75f, 1.25f ); pFleckParticle->m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f; pFleckParticle->m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f; pFleckParticle->m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f; } }
//----------------------------------------------------------------------------- // 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: Tesla effect //----------------------------------------------------------------------------- void C_EntityDissolve::BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset ) { Vector vecOrigin; QAngle vecAngles; MatrixGetColumn( hitboxToWorld, 3, vecOrigin ); MatrixAngles( hitboxToWorld, vecAngles.Base() ); C_BaseEntity *pEntity = GetMoveParent(); // Make a couple of tries at it int iTries = -1; Vector vecForward; trace_t tr; do { iTries++; // Some beams are deliberatly aimed around the point, the rest are random. if ( !bRandom ) { QAngle vecTemp = vecAngles; vecTemp[YAW] += flYawOffset; AngleVectors( vecTemp, &vecForward ); // Randomly angle it up or down vecForward.z = RandomFloat( -1, 1 ); } else { vecForward = RandomVector( -1, 1 ); } UTIL_TraceLine( vecOrigin, vecOrigin + (vecForward * 192), MASK_SHOT, pEntity, COLLISION_GROUP_NONE, &tr ); } while ( tr.fraction >= 1.0 && iTries < 3 ); Vector vecEnd = tr.endpos - (vecForward * 8); // Only spark & glow if we hit something if ( tr.fraction < 1.0 ) { if ( !EffectOccluded( tr.endpos ) ) { // Move it towards the camera Vector vecFlash = tr.endpos; Vector vecForward; AngleVectors( MainViewAngles(), &vecForward ); vecFlash -= (vecForward * 8); g_pEffects->EnergySplash( vecFlash, -vecForward, false ); // End glow CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" ); pSimple->SetSortOrigin( vecFlash ); SimpleParticle *pParticle; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/tesla_glow_noz" ), vecFlash ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = RandomFloat( 0.5, 1 ); pParticle->m_vecVelocity = vec3_origin; Vector color( 1,1,1 ); float colorRamp = 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 = RandomFloat( 6,13 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize - 2; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 10; pParticle->m_flRoll = RandomFloat( 0,360 ); pParticle->m_flRollDelta = 0; } } } // Build the tesla FX_BuildTesla( pEntity, vecOrigin, tr.endpos ); }
//----------------------------------------------------------------------------- // 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 }