mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-05-06 03:49:32 +03:00
This function is used to color impact particles. On Linux I've noticed that this function sometimes is not successful on retrieving the surface color, leaving an odd color to render the particles with. The engine function TraceLineMaterialAndLighting() even has a boolean return value indicating success. GetModelMaterialColorAndLighting() does not though, but I still observe failures (the color parameter is not modified). The color is initialized with an invalid value. If it detects that retrieving the color failed (engine function said so or the invalid value was left in place), this now hamfistedly assumes a lightish grey color, but at least still correctly (presumably) incorporates lighting information. When this situation is detected, a warning is also printed to the console. Because why not.
1441 lines
45 KiB
C++
1441 lines
45 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "fx.h"
|
|
#include "fx_sparks.h"
|
|
#include "clienteffectprecachesystem.h"
|
|
#include "particle_simple3d.h"
|
|
#include "decals.h"
|
|
#include "engine/IEngineSound.h"
|
|
#include "c_te_particlesystem.h"
|
|
#include "engine/ivmodelinfo.h"
|
|
#include "particles_ez.h"
|
|
#include "c_impact_effects.h"
|
|
#include "engine/IStaticPropMgr.h"
|
|
#include "tier0/vprof.h"
|
|
#include "c_te_effect_dispatch.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
//Precahce the effects
|
|
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectImpacts )
|
|
CLIENTEFFECT_MATERIAL( "effects/fleck_cement1" )
|
|
CLIENTEFFECT_MATERIAL( "effects/fleck_cement2" )
|
|
CLIENTEFFECT_MATERIAL( "effects/fleck_antlion1" )
|
|
CLIENTEFFECT_MATERIAL( "effects/fleck_antlion2" )
|
|
CLIENTEFFECT_MATERIAL( "effects/fleck_wood1" )
|
|
CLIENTEFFECT_MATERIAL( "effects/fleck_wood2" )
|
|
CLIENTEFFECT_MATERIAL( "effects/blood" )
|
|
CLIENTEFFECT_MATERIAL( "effects/blood2" )
|
|
CLIENTEFFECT_MATERIAL( "sprites/bloodspray" )
|
|
CLIENTEFFECT_MATERIAL( "particle/particle_noisesphere" )
|
|
CLIENTEFFECT_REGISTER_END()
|
|
|
|
// Cached handles to commonly used materials
|
|
PMaterialHandle g_Mat_Fleck_Wood[2] = { NULL, NULL };
|
|
PMaterialHandle g_Mat_Fleck_Cement[2] = { NULL, NULL };
|
|
PMaterialHandle g_Mat_Fleck_Antlion[2] = { NULL, NULL };
|
|
PMaterialHandle g_Mat_Fleck_Glass[2] = { NULL, NULL };
|
|
PMaterialHandle g_Mat_Fleck_Tile[2] = { NULL, NULL };
|
|
PMaterialHandle g_Mat_DustPuff[2] = { NULL, NULL };
|
|
PMaterialHandle g_Mat_BloodPuff[2] = { NULL, NULL };
|
|
PMaterialHandle g_Mat_SMG_Muzzleflash[4] = { NULL, NULL, NULL, NULL };
|
|
PMaterialHandle g_Mat_Combine_Muzzleflash[3] = { NULL, NULL, NULL };
|
|
|
|
static ConVar fx_drawimpactdebris( "fx_drawimpactdebris", "1", FCVAR_DEVELOPMENTONLY, "Draw impact debris effects." );
|
|
static ConVar fx_drawimpactdust( "fx_drawimpactdust", "1", FCVAR_DEVELOPMENTONLY, "Draw impact dust effects." );
|
|
|
|
void FX_CacheMaterialHandles( void )
|
|
{
|
|
g_Mat_Fleck_Wood[0] = ParticleMgr()->GetPMaterial( "effects/fleck_wood1" );
|
|
g_Mat_Fleck_Wood[1] = ParticleMgr()->GetPMaterial( "effects/fleck_wood2" );
|
|
|
|
g_Mat_Fleck_Cement[0] = ParticleMgr()->GetPMaterial( "effects/fleck_cement1");
|
|
g_Mat_Fleck_Cement[1] = ParticleMgr()->GetPMaterial( "effects/fleck_cement2" );
|
|
|
|
g_Mat_Fleck_Antlion[0] = ParticleMgr()->GetPMaterial( "effects/fleck_antlion1" );
|
|
g_Mat_Fleck_Antlion[1] = ParticleMgr()->GetPMaterial( "effects/fleck_antlion2" );
|
|
|
|
g_Mat_Fleck_Glass[0] = ParticleMgr()->GetPMaterial( "effects/fleck_glass1" );
|
|
g_Mat_Fleck_Glass[1] = ParticleMgr()->GetPMaterial( "effects/fleck_glass2" );
|
|
|
|
g_Mat_Fleck_Tile[0] = ParticleMgr()->GetPMaterial( "effects/fleck_tile1" );
|
|
g_Mat_Fleck_Tile[1] = ParticleMgr()->GetPMaterial( "effects/fleck_tile2" );
|
|
|
|
g_Mat_DustPuff[0] = ParticleMgr()->GetPMaterial( "particle/particle_smokegrenade" );
|
|
g_Mat_DustPuff[1] = ParticleMgr()->GetPMaterial( "particle/particle_noisesphere" );
|
|
|
|
g_Mat_BloodPuff[0] = ParticleMgr()->GetPMaterial( "effects/blood" );
|
|
g_Mat_BloodPuff[1] = ParticleMgr()->GetPMaterial( "effects/blood2" );
|
|
|
|
#ifndef TF_CLIENT_DLL
|
|
g_Mat_SMG_Muzzleflash[0] = ParticleMgr()->GetPMaterial( "effects/muzzleflash1" );
|
|
g_Mat_SMG_Muzzleflash[1] = ParticleMgr()->GetPMaterial( "effects/muzzleflash2" );
|
|
g_Mat_SMG_Muzzleflash[2] = ParticleMgr()->GetPMaterial( "effects/muzzleflash3" );
|
|
g_Mat_SMG_Muzzleflash[3] = ParticleMgr()->GetPMaterial( "effects/muzzleflash4" );
|
|
#ifndef CSTRIKE_DLL
|
|
g_Mat_Combine_Muzzleflash[0] = ParticleMgr()->GetPMaterial( "effects/combinemuzzle1" );
|
|
g_Mat_Combine_Muzzleflash[1] = ParticleMgr()->GetPMaterial( "effects/combinemuzzle2" );
|
|
g_Mat_Combine_Muzzleflash[2] = ParticleMgr()->GetPMaterial( "effects/strider_muzzle" );
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
extern PMaterialHandle g_Material_Spark;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Returns the color given trace information
|
|
// Input : *trace - trace to get results for
|
|
// *color - return color, gamma corrected (0.0f to 1.0f)
|
|
//-----------------------------------------------------------------------------
|
|
void GetColorForSurface( trace_t *trace, Vector *color )
|
|
{
|
|
Vector baseColor = vec3_invalid, diffuseColor;
|
|
const char *kind;
|
|
|
|
if ( trace->DidHitWorld() )
|
|
{
|
|
if ( trace->hitbox == 0 )
|
|
{
|
|
kind = "World";
|
|
Vector end = trace->startpos + ( trace->endpos - trace->startpos ) * 1.1f;
|
|
// If we hit the world, then ask the world for the fleck color
|
|
if ( !engine->TraceLineMaterialAndLighting( trace->startpos, end, diffuseColor, baseColor ) ) {
|
|
baseColor = vec3_invalid; // Make sure this wasn't modified
|
|
}
|
|
}
|
|
else
|
|
{
|
|
kind = "Static Prop";
|
|
// In this case we hit a static prop.
|
|
staticpropmgr->GetStaticPropMaterialColorAndLighting( trace, trace->hitbox - 1, diffuseColor, baseColor );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// In this case, we hit an entity. Find out the model associated with it
|
|
C_BaseEntity *pEnt = trace->m_pEnt;
|
|
if ( !pEnt )
|
|
{
|
|
kind = "Null-Entity";
|
|
} else {
|
|
kind = "Entity";
|
|
ICollideable *pCollide = pEnt->GetCollideable();
|
|
int modelIndex = pCollide->GetCollisionModelIndex();
|
|
model_t* pModel = const_cast<model_t*>(modelinfo->GetModel( modelIndex ));
|
|
|
|
// Ask the model info about what we need to know
|
|
modelinfo->GetModelMaterialColorAndLighting( pModel, pCollide->GetCollisionOrigin(),
|
|
pCollide->GetCollisionAngles(), trace, diffuseColor, baseColor );
|
|
}
|
|
}
|
|
|
|
if ( baseColor == vec3_invalid )
|
|
{
|
|
Warning( "Couldn't find surface color of %s\n", kind );
|
|
baseColor = Vector( .5f, .5f, .5f );
|
|
diffuseColor = engine->GetLightForPoint( trace->endpos, true );
|
|
}
|
|
|
|
//Get final light value
|
|
color->x = pow( diffuseColor[0], 1.0f/2.2f ) * baseColor[0];
|
|
color->y = pow( diffuseColor[1], 1.0f/2.2f ) * baseColor[1];
|
|
color->z = pow( diffuseColor[2], 1.0f/2.2f ) * baseColor[2];
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// This does the actual debris flecks
|
|
//-----------------------------------------------------------------------------
|
|
#define FLECK_MIN_SPEED 64.0f
|
|
#define FLECK_MAX_SPEED 128.0f
|
|
#define FLECK_GRAVITY 800.0f
|
|
#define FLECK_DAMPEN 0.3f
|
|
#define FLECK_ANGULAR_SPRAY 0.6f
|
|
|
|
#ifndef _XBOX
|
|
|
|
//
|
|
// PC ONLY!
|
|
//
|
|
|
|
static void CreateFleckParticles( const Vector& origin, const Vector &color, trace_t *trace, char materialType, int iScale )
|
|
{
|
|
Vector spawnOffset = trace->endpos + ( trace->plane.normal * 1.0f );
|
|
|
|
CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create( "FX_DebrisFlecks", spawnOffset, Vector(5,5,5) );
|
|
|
|
if ( !fleckEmitter )
|
|
return;
|
|
|
|
// Handle increased scale
|
|
float flMaxSpeed = FLECK_MAX_SPEED * iScale;
|
|
float flAngularSpray = MAX( 0.2, FLECK_ANGULAR_SPRAY - ( (float)iScale * 0.2f) ); // More power makes the spray more controlled
|
|
// Setup our collision information
|
|
fleckEmitter->m_ParticleCollision.Setup( spawnOffset, &trace->plane.normal, flAngularSpray, FLECK_MIN_SPEED, flMaxSpeed, FLECK_GRAVITY, FLECK_DAMPEN );
|
|
|
|
PMaterialHandle *hMaterial;
|
|
switch ( materialType )
|
|
{
|
|
case CHAR_TEX_WOOD:
|
|
hMaterial = g_Mat_Fleck_Wood;
|
|
break;
|
|
|
|
case CHAR_TEX_CONCRETE:
|
|
case CHAR_TEX_TILE:
|
|
default:
|
|
hMaterial = g_Mat_Fleck_Cement;
|
|
break;
|
|
}
|
|
|
|
Vector dir, end;
|
|
|
|
float colorRamp;
|
|
|
|
float fScale = g_pParticleSystemMgr->ParticleThrottleScaling() * (float)iScale;
|
|
int numFlecks = (int)( 0.5f + fScale * (float)( random->RandomInt( 4, 16 ) ) );
|
|
|
|
FleckParticle *pFleckParticle;
|
|
|
|
//Dump out flecks
|
|
int i;
|
|
for ( i = 0; i < numFlecks; i++ )
|
|
{
|
|
pFleckParticle = (FleckParticle *) fleckEmitter->AddParticle( sizeof(FleckParticle), hMaterial[random->RandomInt(0,1)], spawnOffset );
|
|
|
|
if ( pFleckParticle == NULL )
|
|
break;
|
|
|
|
pFleckParticle->m_flLifetime = 0.0f;
|
|
pFleckParticle->m_flDieTime = 3.0f;
|
|
|
|
dir[0] = trace->plane.normal[0] + random->RandomFloat( -flAngularSpray, flAngularSpray );
|
|
dir[1] = trace->plane.normal[1] + random->RandomFloat( -flAngularSpray, flAngularSpray );
|
|
dir[2] = trace->plane.normal[2] + random->RandomFloat( -flAngularSpray, flAngularSpray );
|
|
|
|
pFleckParticle->m_uchSize = random->RandomInt( 1, 2 );
|
|
|
|
pFleckParticle->m_vecVelocity = dir * ( random->RandomFloat( FLECK_MIN_SPEED, flMaxSpeed) * ( 3 - pFleckParticle->m_uchSize ) );
|
|
|
|
pFleckParticle->m_flRoll = random->RandomFloat( 0, 360 );
|
|
pFleckParticle->m_flRollDelta = random->RandomFloat( 0, 360 );
|
|
|
|
colorRamp = random->RandomFloat( 0.75f, 1.25f );
|
|
|
|
pFleckParticle->m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
|
|
pFleckParticle->m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
|
|
pFleckParticle->m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
|
|
}
|
|
}
|
|
|
|
#endif // _XBOX
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Debris flecks caused by impacts
|
|
// Input : origin - start
|
|
// *trace - trace information
|
|
// *materialName - material hit
|
|
// materialType - type of material hit
|
|
//-----------------------------------------------------------------------------
|
|
void FX_DebrisFlecks( const Vector& origin, trace_t *tr, char materialType, int iScale, bool bNoFlecks )
|
|
{
|
|
VPROF_BUDGET( "FX_DebrisFlecks", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
|
|
|
|
if ( !fx_drawimpactdebris.GetBool() )
|
|
return;
|
|
|
|
#ifdef _XBOX
|
|
|
|
//
|
|
// XBox version
|
|
//
|
|
|
|
Vector offset;
|
|
float spread = 0.2f;
|
|
|
|
CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" );
|
|
pSimple->SetSortOrigin( origin );
|
|
|
|
// Lock the bbox
|
|
pSimple->GetBinding().SetBBox( origin - ( Vector( 16, 16, 16 ) * iScale ), origin + ( Vector( 16, 16, 16 ) * iScale ) );
|
|
|
|
// Get the color of the surface we've impacted
|
|
Vector color;
|
|
float colorRamp;
|
|
GetColorForSurface( tr, &color );
|
|
|
|
int i;
|
|
SimpleParticle *pParticle;
|
|
for ( i = 0; i < 4; i++ )
|
|
{
|
|
if ( i == 3 )
|
|
{
|
|
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );
|
|
}
|
|
else
|
|
{
|
|
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );
|
|
}
|
|
|
|
if ( pParticle != NULL )
|
|
{
|
|
pParticle->m_flLifetime = 0.0f;
|
|
pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f );
|
|
|
|
pParticle->m_vecVelocity.Random( -spread, spread );
|
|
pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );
|
|
|
|
VectorNormalize( pParticle->m_vecVelocity );
|
|
|
|
float fForce = random->RandomFloat( 250, 500 ) * i * 0.5f;
|
|
|
|
// scaled
|
|
pParticle->m_vecVelocity *= fForce * iScale;
|
|
|
|
// Ramp the color
|
|
colorRamp = random->RandomFloat( 0.5f, 1.25f );
|
|
pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
|
|
|
|
// scaled
|
|
pParticle->m_uchStartSize = (iScale*0.5f) * random->RandomInt( 3, 4 ) * (i+1);
|
|
|
|
// scaled
|
|
pParticle->m_uchEndSize = (iScale*0.5f) * pParticle->m_uchStartSize * 4;
|
|
|
|
pParticle->m_uchStartAlpha = random->RandomInt( 200, 255 );
|
|
pParticle->m_uchEndAlpha = 0;
|
|
|
|
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
pParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f );
|
|
}
|
|
}
|
|
|
|
// Covers the impact spot with flecks
|
|
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff2, origin );
|
|
|
|
if ( pParticle != NULL )
|
|
{
|
|
offset = origin;
|
|
offset[0] += random->RandomFloat( -8.0f, 8.0f );
|
|
offset[1] += random->RandomFloat( -8.0f, 8.0f );
|
|
|
|
pParticle->m_flLifetime = 0.0f;
|
|
pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f );
|
|
|
|
spread = 1.0f;
|
|
|
|
pParticle->m_vecVelocity.Init();
|
|
|
|
colorRamp = random->RandomFloat( 0.5f, 1.25f );
|
|
|
|
pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
|
|
|
|
pParticle->m_uchStartSize = random->RandomInt( 4, 8 );
|
|
pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4;
|
|
|
|
pParticle->m_uchStartAlpha = random->RandomInt( 64, 128 );
|
|
pParticle->m_uchEndAlpha = 0;
|
|
|
|
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
pParticle->m_flRollDelta = random->RandomFloat( -0.1f, 0.1f );
|
|
}
|
|
|
|
#else
|
|
|
|
//
|
|
// PC version
|
|
//
|
|
|
|
Vector color;
|
|
GetColorForSurface( tr, &color );
|
|
|
|
if ( !bNoFlecks )
|
|
{
|
|
CreateFleckParticles( origin, color, tr, materialType, iScale );
|
|
}
|
|
|
|
//
|
|
// Dust trail
|
|
//
|
|
Vector offset = tr->endpos + ( tr->plane.normal * 2.0f );
|
|
|
|
SimpleParticle newParticle;
|
|
|
|
int i;
|
|
for ( i = 0; i < 2; i++ )
|
|
{
|
|
newParticle.m_Pos = offset;
|
|
|
|
newParticle.m_flLifetime = 0.0f;
|
|
newParticle.m_flDieTime = 1.0f;
|
|
|
|
Vector dir;
|
|
dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );
|
|
|
|
newParticle.m_uchStartSize = random->RandomInt( 2, 4 ) * iScale;
|
|
newParticle.m_uchEndSize = newParticle.m_uchStartSize * 8 * iScale;
|
|
|
|
newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f )*(i+1);
|
|
newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 32.0f )*(i+1);
|
|
|
|
newParticle.m_uchStartAlpha = random->RandomInt( 100, 200 );
|
|
newParticle.m_uchEndAlpha = 0;
|
|
|
|
newParticle.m_flRoll = random->RandomFloat( 0, 360 );
|
|
newParticle.m_flRollDelta = random->RandomFloat( -1, 1 );
|
|
|
|
float colorRamp = random->RandomFloat( 0.5f, 1.25f );
|
|
|
|
newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
|
|
newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
|
|
newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
|
|
|
|
AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );
|
|
}
|
|
|
|
|
|
for ( i = 0; i < 4; i++ )
|
|
{
|
|
newParticle.m_Pos = offset;
|
|
|
|
newParticle.m_flLifetime = 0.0f;
|
|
newParticle.m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
|
|
|
|
Vector dir;
|
|
dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );
|
|
|
|
newParticle.m_uchStartSize = random->RandomInt( 1, 4 );
|
|
newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4;
|
|
|
|
newParticle.m_vecVelocity = dir * random->RandomFloat( 8.0f, 32.0f );
|
|
newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 64.0f );
|
|
|
|
newParticle.m_uchStartAlpha = 255;
|
|
newParticle.m_uchEndAlpha = 0;
|
|
|
|
newParticle.m_flRoll = random->RandomFloat( 0, 360 );
|
|
newParticle.m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
|
|
|
|
float colorRamp = random->RandomFloat( 0.5f, 1.25f );
|
|
|
|
newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
|
|
newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
|
|
newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
|
|
|
|
AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] );
|
|
}
|
|
|
|
//
|
|
// Bullet hole capper
|
|
//
|
|
newParticle.m_Pos = offset;
|
|
|
|
newParticle.m_flLifetime = 0.0f;
|
|
newParticle.m_flDieTime = random->RandomFloat( 1.0f, 1.5f );
|
|
|
|
Vector dir;
|
|
dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );
|
|
|
|
newParticle.m_uchStartSize = random->RandomInt( 4, 8 );
|
|
newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4.0f;
|
|
|
|
newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f );
|
|
newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f );
|
|
|
|
newParticle.m_uchStartAlpha = random->RandomInt( 100, 200 );
|
|
newParticle.m_uchEndAlpha = 0;
|
|
|
|
newParticle.m_flRoll = random->RandomFloat( 0, 360 );
|
|
newParticle.m_flRollDelta = random->RandomFloat( -2, 2 );
|
|
|
|
float colorRamp = random->RandomFloat( 0.5f, 1.25f );
|
|
|
|
newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
|
|
newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
|
|
newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
|
|
|
|
AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );
|
|
|
|
#endif
|
|
}
|
|
|
|
#define GLASS_SHARD_MIN_LIFE 2.5f
|
|
#define GLASS_SHARD_MAX_LIFE 5.0f
|
|
#define GLASS_SHARD_NOISE 0.8
|
|
#define GLASS_SHARD_GRAVITY 800
|
|
#define GLASS_SHARD_DAMPING 0.3
|
|
#define GLASS_SHARD_MIN_SPEED 1
|
|
#define GLASS_SHARD_MAX_SPEED 300
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void FX_GlassImpact( const Vector &pos, const Vector &normal )
|
|
{
|
|
VPROF_BUDGET( "FX_GlassImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
|
|
CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "FX_GlassImpact" );
|
|
pGlassEmitter->SetSortOrigin( pos );
|
|
|
|
Vector vecColor;
|
|
engine->ComputeLighting( pos, NULL, true, vecColor );
|
|
|
|
// HACK: Blend a little toward white to match the materials...
|
|
VectorLerp( vecColor, Vector( 1, 1, 1 ), 0.3, vecColor );
|
|
|
|
float flShardSize = random->RandomFloat( 2.0f, 6.0f );
|
|
|
|
unsigned char color[3] = { 200, 200, 210 };
|
|
|
|
// ---------------------
|
|
// Create glass shards
|
|
// ----------------------
|
|
|
|
int numShards = random->RandomInt( 2, 4 );
|
|
|
|
for ( int i = 0; i < numShards; i++ )
|
|
{
|
|
Particle3D *pParticle;
|
|
|
|
pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Glass[random->RandomInt(0,1)], pos );
|
|
|
|
if ( pParticle )
|
|
{
|
|
pParticle->m_flLifeRemaining = random->RandomFloat(GLASS_SHARD_MIN_LIFE,GLASS_SHARD_MAX_LIFE);
|
|
|
|
pParticle->m_vecVelocity[0] = ( normal[0] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
|
|
pParticle->m_vecVelocity[1] = ( normal[1] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
|
|
pParticle->m_vecVelocity[2] = ( normal[2] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
|
|
|
|
pParticle->m_uchSize = flShardSize + random->RandomFloat(-0.5*flShardSize,0.5*flShardSize);
|
|
pParticle->m_vAngles = RandomAngle( 0, 360 );
|
|
pParticle->m_flAngSpeed = random->RandomFloat(-800,800);
|
|
|
|
pParticle->m_uchFrontColor[0] = (byte)(color[0] * vecColor.x);
|
|
pParticle->m_uchFrontColor[1] = (byte)(color[1] * vecColor.y);
|
|
pParticle->m_uchFrontColor[2] = (byte)(color[2] * vecColor.z);
|
|
pParticle->m_uchBackColor[0] = (byte)(color[0] * vecColor.x);
|
|
pParticle->m_uchBackColor[1] = (byte)(color[1] * vecColor.y);
|
|
pParticle->m_uchBackColor[2] = (byte)(color[2] * vecColor.z);
|
|
}
|
|
}
|
|
|
|
pGlassEmitter->m_ParticleCollision.Setup( pos, &normal, GLASS_SHARD_NOISE, GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED, GLASS_SHARD_GRAVITY, GLASS_SHARD_DAMPING );
|
|
|
|
color[0] = 64;
|
|
color[1] = 64;
|
|
color[2] = 92;
|
|
|
|
// ---------------------------
|
|
// Dust
|
|
// ---------------------------
|
|
|
|
Vector dir;
|
|
Vector offset = pos + ( normal * 2.0f );
|
|
float colorRamp;
|
|
|
|
SimpleParticle newParticle;
|
|
|
|
for ( int i = 0; i < 4; i++ )
|
|
{
|
|
newParticle.m_Pos = offset;
|
|
|
|
newParticle.m_flLifetime= 0.0f;
|
|
newParticle.m_flDieTime = random->RandomFloat( 0.1f, 0.25f );
|
|
|
|
dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f );
|
|
|
|
newParticle.m_uchStartSize = random->RandomInt( 1, 4 );
|
|
newParticle.m_uchEndSize = newParticle.m_uchStartSize * 8;
|
|
|
|
newParticle.m_vecVelocity = dir * random->RandomFloat( 8.0f, 16.0f )*(i+1);
|
|
newParticle.m_vecVelocity[2] -= random->RandomFloat( 16.0f, 32.0f )*(i+1);
|
|
|
|
newParticle.m_uchStartAlpha = random->RandomInt( 128, 255 );
|
|
newParticle.m_uchEndAlpha = 0;
|
|
|
|
newParticle.m_flRoll = random->RandomFloat( 0, 360 );
|
|
newParticle.m_flRollDelta = random->RandomFloat( -1, 1 );
|
|
|
|
colorRamp = random->RandomFloat( 0.5f, 1.25f );
|
|
|
|
newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
|
|
newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
|
|
newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
|
|
|
|
AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] );
|
|
}
|
|
|
|
//
|
|
// Bullet hole capper
|
|
//
|
|
newParticle.m_Pos = offset;
|
|
|
|
newParticle.m_flLifetime = 0.0f;
|
|
newParticle.m_flDieTime = random->RandomFloat( 1.0f, 1.5f );
|
|
|
|
dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f );
|
|
|
|
newParticle.m_uchStartSize = random->RandomInt( 4, 8 );
|
|
newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4.0f;
|
|
|
|
newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 8.0f );
|
|
newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f );
|
|
|
|
newParticle.m_uchStartAlpha = random->RandomInt( 32, 64 );
|
|
newParticle.m_uchEndAlpha = 0;
|
|
|
|
newParticle.m_flRoll = random->RandomFloat( 0, 360 );
|
|
newParticle.m_flRollDelta = random->RandomFloat( -2, 2 );
|
|
|
|
colorRamp = random->RandomFloat( 0.5f, 1.25f );
|
|
|
|
newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
|
|
newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
|
|
newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
|
|
|
|
AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );
|
|
}
|
|
|
|
void GlassImpactCallback( const CEffectData &data )
|
|
{
|
|
FX_GlassImpact( data.m_vOrigin, data.m_vNormal );
|
|
}
|
|
|
|
DECLARE_CLIENT_EFFECT( "GlassImpact", GlassImpactCallback );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : &pos -
|
|
// *tr -
|
|
//-----------------------------------------------------------------------------
|
|
void FX_AntlionImpact( const Vector &pos, trace_t *trace )
|
|
{
|
|
#if defined( _X360 )
|
|
return;
|
|
#endif // _X360
|
|
|
|
VPROF_BUDGET( "FX_AntlionImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
|
|
|
|
CSmartPtr<CSimple3DEmitter> fleckEmitter = CSimple3DEmitter::Create( "FX_DebrisFlecks" );
|
|
if ( fleckEmitter == NULL )
|
|
return;
|
|
|
|
Vector shotDir = ( trace->startpos - trace->endpos );
|
|
VectorNormalize( shotDir );
|
|
|
|
Vector spawnOffset = trace->endpos + ( shotDir * 2.0f );
|
|
|
|
Vector vWorldMins, vWorldMaxs;
|
|
if ( trace->m_pEnt )
|
|
{
|
|
float scale = trace->m_pEnt->CollisionProp()->BoundingRadius();
|
|
vWorldMins[0] = spawnOffset[0] - scale;
|
|
vWorldMins[1] = spawnOffset[1] - scale;
|
|
vWorldMins[2] = spawnOffset[2] - scale;
|
|
vWorldMaxs[0] = spawnOffset[0] + scale;
|
|
vWorldMaxs[1] = spawnOffset[1] + scale;
|
|
vWorldMaxs[2] = spawnOffset[2] + scale;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
fleckEmitter->SetSortOrigin( spawnOffset );
|
|
fleckEmitter->GetBinding().SetBBox( spawnOffset-Vector(32,32,32), spawnOffset+Vector(32,32,32), true );
|
|
|
|
// Handle increased scale
|
|
float flMaxSpeed = 256.0f;
|
|
float flAngularSpray = 1.0f;
|
|
|
|
// Setup our collision information
|
|
fleckEmitter->m_ParticleCollision.Setup( spawnOffset, &shotDir, flAngularSpray, 8.0f, flMaxSpeed, FLECK_GRAVITY, FLECK_DAMPEN );
|
|
|
|
Vector dir, end;
|
|
Vector color = Vector( 1, 0.9, 0.75 );
|
|
float colorRamp;
|
|
|
|
int numFlecks = random->RandomInt( 8, 16 );
|
|
|
|
Particle3D *pFleckParticle;
|
|
|
|
// Dump out flecks
|
|
int i;
|
|
for ( i = 0; i < numFlecks; i++ )
|
|
{
|
|
pFleckParticle = (Particle3D *) fleckEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Antlion[random->RandomInt(0,1)], spawnOffset );
|
|
if ( pFleckParticle == NULL )
|
|
break;
|
|
|
|
pFleckParticle->m_flLifeRemaining = 3.0f;
|
|
|
|
dir[0] = shotDir[0] + random->RandomFloat( -flAngularSpray, flAngularSpray );
|
|
dir[1] = shotDir[1] + random->RandomFloat( -flAngularSpray, flAngularSpray );
|
|
dir[2] = shotDir[2] + random->RandomFloat( -flAngularSpray, flAngularSpray );
|
|
|
|
pFleckParticle->m_uchSize = random->RandomInt( 1, 6 );
|
|
|
|
pFleckParticle->m_vecVelocity = dir * random->RandomFloat( FLECK_MIN_SPEED, flMaxSpeed);
|
|
pFleckParticle->m_vAngles.Random( 0, 360 );
|
|
pFleckParticle->m_flAngSpeed = random->RandomFloat(-800,800);
|
|
|
|
pFleckParticle->m_uchFrontColor[0] = 255;
|
|
pFleckParticle->m_uchFrontColor[1] = 255;
|
|
pFleckParticle->m_uchFrontColor[2] = 255;
|
|
|
|
pFleckParticle->m_uchBackColor[0] = 128;
|
|
pFleckParticle->m_uchBackColor[1] = 128;
|
|
pFleckParticle->m_uchBackColor[2] = 128;
|
|
}
|
|
|
|
//
|
|
// Dust trail
|
|
//
|
|
|
|
SimpleParticle *pParticle;
|
|
|
|
CSmartPtr<CSimpleEmitter> dustEmitter = CSimpleEmitter::Create( "FX_DebrisFlecks" );
|
|
if ( !dustEmitter )
|
|
return;
|
|
|
|
Vector offset = trace->endpos + ( shotDir * 4.0f );
|
|
|
|
dustEmitter->SetSortOrigin( offset );
|
|
dustEmitter->GetBinding().SetBBox( spawnOffset-Vector(32,32,32), spawnOffset+Vector(32,32,32), true );
|
|
|
|
for ( i = 0; i < 4; i++ )
|
|
{
|
|
pParticle = (SimpleParticle *) dustEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[0], offset );
|
|
|
|
if ( pParticle == NULL )
|
|
break;
|
|
|
|
pParticle->m_flLifetime = 0.0f;
|
|
pParticle->m_flDieTime = 1.0f;
|
|
|
|
dir[0] = shotDir[0] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[1] = shotDir[1] + random->RandomFloat( -0.8f, 0.8f );
|
|
dir[2] = shotDir[2] + random->RandomFloat( -0.8f, 0.8f );
|
|
|
|
pParticle->m_uchStartSize = random->RandomInt( 8, 16 );
|
|
pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4.0f;
|
|
|
|
pParticle->m_vecVelocity = dir * random->RandomFloat( 4.0f, 64.0f );
|
|
|
|
pParticle->m_uchStartAlpha = random->RandomInt( 32, 64);
|
|
pParticle->m_uchEndAlpha = 0;
|
|
|
|
pParticle->m_flRoll = random->RandomFloat( 0, 2.0f*M_PI );
|
|
pParticle->m_flRollDelta = random->RandomFloat( -0.5f, 0.5f );
|
|
|
|
colorRamp = random->RandomFloat( 0.5f, 1.0f );
|
|
|
|
pParticle->m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
|
|
pParticle->m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
|
|
pParticle->m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
|
|
}
|
|
|
|
|
|
CLocalPlayerFilter filter;
|
|
C_BaseEntity::EmitSound( filter, 0, "FX_AntlionImpact.ShellImpact", &trace->endpos );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Spurt out bug blood
|
|
// Input : &pos -
|
|
// &dir -
|
|
//-----------------------------------------------------------------------------
|
|
#if defined( _XBOX )
|
|
#define NUM_BUG_BLOOD 16
|
|
#define NUM_BUG_BLOOD2 8
|
|
#define NUM_BUG_SPLATS 8
|
|
#else
|
|
#define NUM_BUG_BLOOD 32
|
|
#define NUM_BUG_BLOOD2 16
|
|
#define NUM_BUG_SPLATS 16
|
|
#endif
|
|
void FX_BugBlood( Vector &pos, Vector &dir, Vector &vWorldMins, Vector &vWorldMaxs )
|
|
{
|
|
VPROF_BUDGET( "FX_BugBlood", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
|
|
|
|
CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_BugBlood" );
|
|
if ( !pSimple )
|
|
return;
|
|
|
|
pSimple->SetSortOrigin( pos );
|
|
pSimple->GetBinding().SetBBox( vWorldMins, vWorldMaxs, true );
|
|
pSimple->GetBinding().SetBBox( pos-Vector(32,32,32), pos+Vector(32,32,32), true );
|
|
|
|
Vector vDir;
|
|
vDir[0] = dir[0] + random->RandomFloat( -2.0f, 2.0f );
|
|
vDir[1] = dir[1] + random->RandomFloat( -2.0f, 2.0f );
|
|
vDir[2] = dir[2] + random->RandomFloat( -2.0f, 2.0f );
|
|
|
|
VectorNormalize( vDir );
|
|
|
|
int i;
|
|
for ( i = 0; i < NUM_BUG_BLOOD; i++ )
|
|
{
|
|
SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], pos );
|
|
|
|
if ( sParticle == NULL )
|
|
return;
|
|
|
|
sParticle->m_flLifetime = 0.0f;
|
|
sParticle->m_flDieTime = 0.25f;
|
|
|
|
float speed = random->RandomFloat( 32.0f, 150.0f );
|
|
|
|
sParticle->m_vecVelocity = vDir * -speed;
|
|
sParticle->m_vecVelocity[2] -= 32.0f;
|
|
|
|
sParticle->m_uchColor[0] = 255;
|
|
sParticle->m_uchColor[1] = 200;
|
|
sParticle->m_uchColor[2] = 32;
|
|
sParticle->m_uchStartAlpha = 255;
|
|
sParticle->m_uchEndAlpha = 0;
|
|
sParticle->m_uchStartSize = random->RandomInt( 1, 2 );
|
|
sParticle->m_uchEndSize = sParticle->m_uchStartSize*random->RandomInt( 1, 4 );
|
|
sParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
sParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
|
|
}
|
|
|
|
for ( i = 0; i < NUM_BUG_BLOOD2; i++ )
|
|
{
|
|
SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], pos );
|
|
|
|
if ( sParticle == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
sParticle->m_flLifetime = 0.0f;
|
|
sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
|
|
|
|
float speed = random->RandomFloat( 8.0f, 255.0f );
|
|
|
|
sParticle->m_vecVelocity = vDir * -speed;
|
|
sParticle->m_vecVelocity[2] -= 16.0f;
|
|
|
|
sParticle->m_uchColor[0] = 255;
|
|
sParticle->m_uchColor[1] = 200;
|
|
sParticle->m_uchColor[2] = 32;
|
|
sParticle->m_uchStartAlpha = random->RandomInt( 16, 32 );
|
|
sParticle->m_uchEndAlpha = 0;
|
|
sParticle->m_uchStartSize = random->RandomInt( 1, 3 );
|
|
sParticle->m_uchEndSize = sParticle->m_uchStartSize*random->RandomInt( 1, 4 );
|
|
sParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
sParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
|
|
}
|
|
|
|
Vector offset;
|
|
|
|
for ( i = 0; i < NUM_BUG_SPLATS; i++ )
|
|
{
|
|
offset.Random( -2, 2 );
|
|
offset += pos;
|
|
|
|
SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], offset );
|
|
|
|
if ( sParticle == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
sParticle->m_flLifetime = 0.0f;
|
|
sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
|
|
|
|
float speed = 75.0f * ((i/(float)NUM_BUG_SPLATS)+1);
|
|
|
|
sParticle->m_vecVelocity.Random( -16.0f, 16.0f );
|
|
|
|
sParticle->m_vecVelocity += vDir * -speed;
|
|
sParticle->m_vecVelocity[2] -= ( 64.0f * ((i/(float)NUM_BUG_SPLATS)+1) );
|
|
|
|
sParticle->m_uchColor[0] = 255;
|
|
sParticle->m_uchColor[1] = 200;
|
|
sParticle->m_uchColor[2] = 32;
|
|
sParticle->m_uchStartAlpha = 255;
|
|
sParticle->m_uchEndAlpha = 0;
|
|
sParticle->m_uchStartSize = random->RandomInt( 1, 2 );
|
|
sParticle->m_uchEndSize = sParticle->m_uchStartSize*4;
|
|
sParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
sParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Blood puff
|
|
//-----------------------------------------------------------------------------
|
|
void FX_Blood( Vector &pos, Vector &dir, float r, float g, float b, float a )
|
|
{
|
|
VPROF_BUDGET( "FX_Blood", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
|
|
|
|
// Cloud
|
|
CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_Blood" );
|
|
if ( !pSimple )
|
|
return;
|
|
pSimple->SetSortOrigin( pos );
|
|
|
|
Vector vDir;
|
|
|
|
vDir[0] = dir[0] + random->RandomFloat( -1.0f, 1.0f );
|
|
vDir[1] = dir[1] + random->RandomFloat( -1.0f, 1.0f );
|
|
vDir[2] = dir[2] + random->RandomFloat( -1.0f, 1.0f );
|
|
|
|
VectorNormalize( vDir );
|
|
|
|
int i;
|
|
for ( i = 0; i < 2; i++ )
|
|
{
|
|
SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], pos );
|
|
|
|
if ( sParticle == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
sParticle->m_flLifetime = 0.0f;
|
|
sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
|
|
|
|
float speed = random->RandomFloat( 2.0f, 8.0f );
|
|
|
|
sParticle->m_vecVelocity = vDir * (speed*i);
|
|
sParticle->m_vecVelocity[2] += random->RandomFloat( -32.0f, -16.0f );
|
|
|
|
sParticle->m_uchColor[0] = r;
|
|
sParticle->m_uchColor[1] = g;
|
|
sParticle->m_uchColor[2] = b;
|
|
sParticle->m_uchStartAlpha = a;
|
|
sParticle->m_uchEndAlpha = 0;
|
|
sParticle->m_uchStartSize = 2;
|
|
sParticle->m_uchEndSize = sParticle->m_uchStartSize*4;
|
|
sParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
sParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
|
|
}
|
|
|
|
for ( i = 0; i < 2; i++ )
|
|
{
|
|
SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], pos );
|
|
|
|
if ( sParticle == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
sParticle->m_flLifetime = 0.0f;
|
|
sParticle->m_flDieTime = 0.5f;
|
|
|
|
float speed = random->RandomFloat( 4.0f, 16.0f );
|
|
|
|
sParticle->m_vecVelocity = vDir * (speed*i);
|
|
|
|
sParticle->m_uchColor[0] = r;
|
|
sParticle->m_uchColor[1] = g;
|
|
sParticle->m_uchColor[2] = b;
|
|
sParticle->m_uchStartAlpha = 128;
|
|
sParticle->m_uchEndAlpha = 0;
|
|
sParticle->m_uchStartSize = 2;
|
|
sParticle->m_uchEndSize = sParticle->m_uchStartSize*4;
|
|
sParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
sParticle->m_flRollDelta = random->RandomFloat( -4.0f, 4.0f );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Dust impact
|
|
// Input : &origin - position
|
|
// &tr - trace information
|
|
//-----------------------------------------------------------------------------
|
|
void FX_DustImpact( const Vector &origin, trace_t *tr, int iScale )
|
|
{
|
|
if ( !fx_drawimpactdust.GetBool() )
|
|
return;
|
|
|
|
#ifdef _XBOX
|
|
|
|
//
|
|
// XBox version
|
|
//
|
|
|
|
VPROF_BUDGET( "FX_DustImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
|
|
Vector offset;
|
|
float spread = 0.2f;
|
|
|
|
CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" );
|
|
pSimple->SetSortOrigin( origin );
|
|
pSimple->GetBinding().SetBBox( origin - ( Vector( 32, 32, 32 ) * iScale ), origin + ( Vector( 32, 32, 32 ) * iScale ) );
|
|
|
|
Vector color;
|
|
float colorRamp;
|
|
GetColorForSurface( tr, &color );
|
|
|
|
int i;
|
|
SimpleParticle *pParticle;
|
|
for ( i = 0; i < 4; i++ )
|
|
{
|
|
// Last puff is gritty (hides end)
|
|
if ( i == 3 )
|
|
{
|
|
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );
|
|
}
|
|
else
|
|
{
|
|
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );
|
|
}
|
|
|
|
if ( pParticle != NULL )
|
|
{
|
|
pParticle->m_flLifetime = 0.0f;
|
|
|
|
pParticle->m_vecVelocity.Random( -spread, spread );
|
|
pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );
|
|
|
|
VectorNormalize( pParticle->m_vecVelocity );
|
|
|
|
float fForce = random->RandomFloat( 250, 500 ) * i;
|
|
|
|
// scaled
|
|
pParticle->m_vecVelocity *= fForce * iScale;
|
|
|
|
colorRamp = random->RandomFloat( 0.75f, 1.25f );
|
|
|
|
pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
|
|
|
|
// scaled
|
|
pParticle->m_uchStartSize = iScale * random->RandomInt( 3, 4 ) * (i+1);
|
|
|
|
// scaled
|
|
pParticle->m_uchEndSize = iScale * pParticle->m_uchStartSize * 4;
|
|
|
|
pParticle->m_uchStartAlpha = random->RandomInt( 32, 255 );
|
|
pParticle->m_uchEndAlpha = 0;
|
|
|
|
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
|
|
if ( i == 3 )
|
|
{
|
|
pParticle->m_flRollDelta = random->RandomFloat( -0.1f, 0.1f );
|
|
pParticle->m_flDieTime = 0.5f;
|
|
}
|
|
else
|
|
{
|
|
pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f );
|
|
pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f );
|
|
}
|
|
}
|
|
}
|
|
|
|
//Impact hit
|
|
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff, origin );
|
|
|
|
if ( pParticle != NULL )
|
|
{
|
|
offset = origin;
|
|
offset[0] += random->RandomFloat( -8.0f, 8.0f );
|
|
offset[1] += random->RandomFloat( -8.0f, 8.0f );
|
|
|
|
pParticle->m_flLifetime = 0.0f;
|
|
pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f );
|
|
|
|
pParticle->m_vecVelocity.Init();
|
|
|
|
colorRamp = random->RandomFloat( 0.75f, 1.25f );
|
|
pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
|
|
|
|
pParticle->m_uchStartSize = random->RandomInt( 4, 8 );
|
|
pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4;
|
|
|
|
pParticle->m_uchStartAlpha = random->RandomInt( 32, 64 );
|
|
pParticle->m_uchEndAlpha = 0;
|
|
|
|
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
pParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f );
|
|
}
|
|
|
|
#else
|
|
FX_DustImpact( origin, tr, (float)iScale );
|
|
#endif // _XBOX
|
|
}
|
|
|
|
void FX_DustImpact( const Vector &origin, trace_t *tr, float flScale )
|
|
{
|
|
//
|
|
// PC version
|
|
//
|
|
|
|
VPROF_BUDGET( "FX_DustImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
|
|
Vector offset;
|
|
float spread = 0.2f;
|
|
|
|
CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" );
|
|
pSimple->SetSortOrigin( origin );
|
|
|
|
// Three types of particle, ideally we want 4 of each.
|
|
float fNumParticles = 4.0f * g_pParticleSystemMgr->ParticleThrottleScaling();
|
|
int nParticles1 = (int)( 0.50f + fNumParticles );
|
|
int nParticles2 = (int)( 0.83f + fNumParticles ); // <-- most visible particle type.
|
|
int nParticles3 = (int)( 0.17f + fNumParticles );
|
|
|
|
SimpleParticle *pParticle;
|
|
|
|
Vector color;
|
|
float colorRamp;
|
|
|
|
GetColorForSurface( tr, &color );
|
|
|
|
// To get a decent spread even when scaling down the number of particles...
|
|
const static int nParticleIdArray[4] = {3,1,2,0};
|
|
|
|
int i;
|
|
for ( i = 0; i < nParticles1; i++ )
|
|
{
|
|
int nId = nParticleIdArray[i];
|
|
|
|
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );
|
|
|
|
if ( pParticle != NULL )
|
|
{
|
|
pParticle->m_flLifetime = 0.0f;
|
|
pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f );
|
|
|
|
pParticle->m_vecVelocity.Random( -spread, spread );
|
|
pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );
|
|
|
|
VectorNormalize( pParticle->m_vecVelocity );
|
|
|
|
float fForce = random->RandomFloat( 250, 500 ) * nId;
|
|
|
|
// scaled
|
|
pParticle->m_vecVelocity *= fForce * flScale;
|
|
|
|
colorRamp = random->RandomFloat( 0.75f, 1.25f );
|
|
|
|
pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
|
|
|
|
// scaled
|
|
pParticle->m_uchStartSize = ( unsigned char )( flScale * random->RandomInt( 3, 4 ) * (nId+1) );
|
|
|
|
// scaled
|
|
pParticle->m_uchEndSize = ( unsigned char )( flScale * pParticle->m_uchStartSize * 4 );
|
|
|
|
pParticle->m_uchStartAlpha = random->RandomInt( 32, 255 );
|
|
pParticle->m_uchEndAlpha = 0;
|
|
|
|
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f );
|
|
}
|
|
}
|
|
|
|
//Dust specs
|
|
for ( i = 0; i < nParticles2; i++ )
|
|
{
|
|
int nId = nParticleIdArray[i];
|
|
|
|
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );
|
|
|
|
if ( pParticle != NULL )
|
|
{
|
|
pParticle->m_flLifetime = 0.0f;
|
|
pParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.75f );
|
|
|
|
pParticle->m_vecVelocity.Random( -spread, spread );
|
|
pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );
|
|
|
|
VectorNormalize( pParticle->m_vecVelocity );
|
|
|
|
float fForce = random->RandomFloat( 250, 500 ) * nId;
|
|
|
|
pParticle->m_vecVelocity *= fForce;
|
|
|
|
colorRamp = random->RandomFloat( 0.75f, 1.25f );
|
|
|
|
pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
|
|
|
|
pParticle->m_uchStartSize = random->RandomInt( 2, 4 ) * (nId+1);
|
|
pParticle->m_uchEndSize = pParticle->m_uchStartSize * 2;
|
|
|
|
pParticle->m_uchStartAlpha = 255;
|
|
pParticle->m_uchEndAlpha = 0;
|
|
|
|
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
pParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
|
|
}
|
|
}
|
|
|
|
//Impact hit
|
|
for ( i = 0; i < nParticles3; i++ )
|
|
{
|
|
//int nId = nParticleIdArray[i];
|
|
|
|
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );
|
|
|
|
if ( pParticle != NULL )
|
|
{
|
|
offset = origin;
|
|
offset[0] += random->RandomFloat( -8.0f, 8.0f );
|
|
offset[1] += random->RandomFloat( -8.0f, 8.0f );
|
|
|
|
pParticle->m_flLifetime = 0.0f;
|
|
pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f );
|
|
|
|
spread = 1.0f;
|
|
|
|
pParticle->m_vecVelocity.Random( -spread, spread );
|
|
pParticle->m_vecVelocity += tr->plane.normal;
|
|
|
|
VectorNormalize( pParticle->m_vecVelocity );
|
|
|
|
float fForce = random->RandomFloat( 0, 50 );
|
|
|
|
pParticle->m_vecVelocity *= fForce;
|
|
|
|
colorRamp = random->RandomFloat( 0.75f, 1.25f );
|
|
|
|
pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
|
|
pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
|
|
|
|
pParticle->m_uchStartSize = random->RandomInt( 1, 4 );
|
|
pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4;
|
|
|
|
pParticle->m_uchStartAlpha = random->RandomInt( 32, 64 );
|
|
pParticle->m_uchEndAlpha = 0;
|
|
|
|
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
|
pParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.0f );
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef _XBOX
|
|
extern PMaterialHandle g_Material_Spark;
|
|
#endif // _XBOX
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : &pos -
|
|
// &dir -
|
|
// type -
|
|
//-----------------------------------------------------------------------------
|
|
void FX_GaussExplosion( const Vector &pos, const Vector &dir, int type )
|
|
{
|
|
Vector vDir;
|
|
|
|
vDir[0] = dir[0] + random->RandomFloat( -1.0f, 1.0f );
|
|
vDir[1] = dir[1] + random->RandomFloat( -1.0f, 1.0f );
|
|
vDir[2] = dir[2] + random->RandomFloat( -1.0f, 1.0f );
|
|
|
|
VectorNormalize( vDir );
|
|
|
|
int i;
|
|
|
|
#if defined(_XBOX) || defined(_X360)
|
|
|
|
//
|
|
// XBox version
|
|
//
|
|
CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "FX_GaussExplosion" );
|
|
if ( pSparkEmitter == NULL )
|
|
{
|
|
Assert(0);
|
|
return;
|
|
}
|
|
|
|
if ( g_Material_Spark == NULL )
|
|
{
|
|
g_Material_Spark = pSparkEmitter->GetPMaterial( "effects/spark" );
|
|
}
|
|
|
|
pSparkEmitter->SetSortOrigin( pos );
|
|
pSparkEmitter->m_ParticleCollision.SetGravity( 800.0f );
|
|
pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN );
|
|
pSparkEmitter->GetBinding().SetBBox( pos - Vector( 32, 32, 32 ), pos + Vector( 32, 32, 32 ) );
|
|
|
|
int numSparks = random->RandomInt( 8, 16 );
|
|
TrailParticle *pParticle;
|
|
|
|
// Dump out sparks
|
|
for ( i = 0; i < numSparks; i++ )
|
|
{
|
|
pParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), g_Material_Spark, pos );
|
|
|
|
if ( pParticle == NULL )
|
|
return;
|
|
|
|
pParticle->m_flLifetime = 0.0f;
|
|
|
|
vDir.Random( -0.6f, 0.6f );
|
|
vDir += dir;
|
|
VectorNormalize( vDir );
|
|
|
|
pParticle->m_flWidth = random->RandomFloat( 1.0f, 4.0f );
|
|
pParticle->m_flLength = random->RandomFloat( 0.01f, 0.1f );
|
|
pParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
|
|
|
|
pParticle->m_vecVelocity = vDir * random->RandomFloat( 128, 512 );
|
|
|
|
Color32Init( pParticle->m_color, 255, 255, 255, 255 );
|
|
}
|
|
|
|
// End cap
|
|
SimpleParticle particle;
|
|
|
|
particle.m_Pos = pos;
|
|
particle.m_flLifetime = 0.0f;
|
|
particle.m_flDieTime = 0.1f;
|
|
particle.m_vecVelocity.Init();
|
|
particle.m_flRoll = random->RandomInt( 0, 360 );
|
|
particle.m_flRollDelta = 0.0f;
|
|
particle.m_uchColor[0] = 255;
|
|
particle.m_uchColor[1] = 255;
|
|
particle.m_uchColor[2] = 255;
|
|
particle.m_uchStartAlpha = 255;
|
|
particle.m_uchEndAlpha = 255;
|
|
particle.m_uchStartSize = random->RandomInt( 24, 32 );
|
|
particle.m_uchEndSize = 0;
|
|
|
|
AddSimpleParticle( &particle, ParticleMgr()->GetPMaterial( "effects/yellowflare" ) );
|
|
|
|
#else
|
|
|
|
//
|
|
// PC version
|
|
//
|
|
CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "FX_ElectricSpark" );
|
|
|
|
if ( !pSparkEmitter )
|
|
{
|
|
Assert(0);
|
|
return;
|
|
}
|
|
|
|
PMaterialHandle hMaterial = pSparkEmitter->GetPMaterial( "effects/spark" );
|
|
|
|
pSparkEmitter->SetSortOrigin( pos );
|
|
|
|
pSparkEmitter->m_ParticleCollision.SetGravity( 800.0f );
|
|
pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN|bitsPARTICLE_TRAIL_COLLIDE );
|
|
|
|
//Setup our collision information
|
|
pSparkEmitter->m_ParticleCollision.Setup( pos, &vDir, 0.8f, 128, 512, 800, 0.3f );
|
|
|
|
int numSparks = random->RandomInt( 16, 32 );
|
|
TrailParticle *pParticle;
|
|
|
|
// Dump out sparks
|
|
for ( i = 0; i < numSparks; i++ )
|
|
{
|
|
pParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), hMaterial, pos );
|
|
|
|
if ( pParticle == NULL )
|
|
return;
|
|
|
|
pParticle->m_flLifetime = 0.0f;
|
|
|
|
vDir.Random( -0.6f, 0.6f );
|
|
vDir += dir;
|
|
VectorNormalize( vDir );
|
|
|
|
pParticle->m_flWidth = random->RandomFloat( 1.0f, 4.0f );
|
|
pParticle->m_flLength = random->RandomFloat( 0.01f, 0.1f );
|
|
pParticle->m_flDieTime = random->RandomFloat( 0.25f, 1.0f );
|
|
|
|
pParticle->m_vecVelocity = vDir * random->RandomFloat( 128, 512 );
|
|
|
|
Color32Init( pParticle->m_color, 255, 255, 255, 255 );
|
|
}
|
|
|
|
|
|
FX_ElectricSpark( pos, 1, 1, &vDir );
|
|
#endif
|
|
}
|
|
|
|
class C_TEGaussExplosion : public C_TEParticleSystem
|
|
{
|
|
public:
|
|
DECLARE_CLASS( C_TEGaussExplosion, C_TEParticleSystem );
|
|
DECLARE_CLIENTCLASS();
|
|
|
|
C_TEGaussExplosion();
|
|
virtual ~C_TEGaussExplosion();
|
|
|
|
public:
|
|
virtual void PostDataUpdate( DataUpdateType_t updateType );
|
|
virtual bool ShouldDraw() { return true; }
|
|
|
|
public:
|
|
|
|
int m_nType;
|
|
Vector m_vecDirection;
|
|
};
|
|
|
|
IMPLEMENT_CLIENTCLASS_EVENT_DT( C_TEGaussExplosion, DT_TEGaussExplosion, CTEGaussExplosion )
|
|
RecvPropInt(RECVINFO(m_nType)),
|
|
RecvPropVector(RECVINFO(m_vecDirection)),
|
|
END_RECV_TABLE()
|
|
|
|
//==================================================
|
|
// C_TEGaussExplosion
|
|
//==================================================
|
|
|
|
C_TEGaussExplosion::C_TEGaussExplosion()
|
|
{
|
|
}
|
|
|
|
C_TEGaussExplosion::~C_TEGaussExplosion()
|
|
{
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : bNewEntity - whether or not to start a new entity
|
|
//-----------------------------------------------------------------------------
|
|
void C_TEGaussExplosion::PostDataUpdate( DataUpdateType_t updateType )
|
|
{
|
|
FX_GaussExplosion( m_vecOrigin, m_vecDirection, m_nType );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : filter -
|
|
// delay -
|
|
// &pos -
|
|
// &dir -
|
|
// type -
|
|
//-----------------------------------------------------------------------------
|
|
void TE_GaussExplosion( IRecipientFilter& filter, float delay, const Vector &pos, const Vector &dir, int type )
|
|
{
|
|
FX_GaussExplosion( pos, dir, type );
|
|
}
|
|
|