diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf2/fx_tf2_blood.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/tf2/fx_tf2_blood.cpp')
| -rw-r--r-- | game/client/tf2/fx_tf2_blood.cpp | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/game/client/tf2/fx_tf2_blood.cpp b/game/client/tf2/fx_tf2_blood.cpp new file mode 100644 index 0000000..6b7e13a --- /dev/null +++ b/game/client/tf2/fx_tf2_blood.cpp @@ -0,0 +1,347 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A blood spray effect to expose successful hits. +// +//=============================================================================// + +#include "cbase.h" +#include "clienteffectprecachesystem.h" +#include "fx_sparks.h" +#include "iefx.h" +#include "c_te_effect_dispatch.h" +#include "particles_ez.h" +#include "decals.h" +#include "engine/IEngineSound.h" +#include "fx_quad.h" +#include "engine/ivdebugoverlay.h" +#include "shareddefs.h" +#include "fx_blood.h" +#include "tf_shareddefs.h" +#include "view.h" +#include "c_basetfplayer.h" + +CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectTF2BloodSpray ) +CLIENTEFFECT_MATERIAL( "effects/blood_gore" ) +CLIENTEFFECT_MATERIAL( "effects/blood_drop" ) +CLIENTEFFECT_MATERIAL( "effects/blood_puff" ) +CLIENTEFFECT_REGISTER_END() + +//----------------------------------------------------------------------------- +// Purpose: +// Input : origin - +// normal - +// scale - +//----------------------------------------------------------------------------- +void FX_TF2_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 ); + + float spread = 0.2f; + Vector color = Vector( r / 255.0f, g / 255.0f, b / 255.0f ); + float colorRamp; + Vector offset; + int i; + + Vector offDir; + Vector right; + Vector up; + Vector vecNormal = normal; + + // Get the distance to the view + float flDistance = (origin - MainViewOrigin()).Length(); + float flLODDistance = 0.25 * (flDistance / 512); + float flDistanceScale = 1.0 + flLODDistance; + + if (vecNormal != Vector(0, 0, 1) ) + { + right = vecNormal.Cross( Vector(0, 0, 1) ); + up = right.Cross( vecNormal ); + } + else + { + right = Vector(0, 0, 1); + up = right.Cross( vecNormal ); + } + + // If the normal's too close to being along the view, push it out + Vector vecForward, vecRight; + AngleVectors( MainViewAngles(), &vecForward, &vecRight, NULL ); + float flDot = DotProduct( vecNormal, vecForward ); + if ( fabs(flDot) > 0.5 ) + { + float flPush = random->RandomFloat(0.5, 1.5) + flLODDistance; + float flRightDot = DotProduct( vecNormal, vecRight ); + // If we're up close, randomly move it around. If we're at a distance, always push it to the side + // Up close, this can move it back towards the view, but the random chance still looks better + if ( ( flDistance >= 512 && flRightDot > 0 ) || ( flDistance < 512 && RandomFloat(0,1) > 0.5 ) ) + { + // Turn it to the right + vecNormal += (vecRight * flPush); + } + else + { + // Turn it to the left + vecNormal -= (vecRight * flPush); + } + } + + // + // Dump out drops + // + // Don't bother with these over midrange distance + if (flags & FX_BLOODSPRAY_DROPS && ( flDistance < 1500 ) ) + { + TrailParticle *tParticle; + + CSmartPtr<CTrailParticles> pTrailEmitter = CTrailParticles::Create( "blooddrops" ); + if ( !pTrailEmitter ) + return; + + pTrailEmitter->SetSortOrigin( origin ); + + // Partial gravity on blood drops. + pTrailEmitter->SetGravity( 600.0 ); + + // Enable simple collisions with nearby surfaces. + pTrailEmitter->Setup(origin, &vecNormal, 1, 10, 100, 600, 0.2, 0 ); + + PMaterialHandle hMaterial = ParticleMgr()->GetPMaterial( "effects/blood_drop" ); + + // + // Long stringy drops of blood. + // + for ( i = 0; i < 7; 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 = vecNormal + 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.5f, 1.0f ) * scale * (flDistanceScale * 1.25); + tParticle->m_flLength = random->RandomFloat( 0.02f, 0.03f ) * scale * (flDistanceScale * 1.25); + tParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); + + // Ramp up the brightness as it gets farther away + colorRamp = random->RandomFloat( 0.5f, 0.75f ) + flLODDistance; + FloatToColor32( tParticle->m_color, MIN( 1.0, color[0] * colorRamp ), MIN( 1.0, color[1] * colorRamp ), MIN( 1.0, color[2] * colorRamp ), 1.0f ); + } + + // + // Shorter droplets. + // + // Only do these at short range + if ( flDistance < 512 ) + { + for ( i = 0; i < 10; 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 = vecNormal + 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 * flDistanceScale; + tParticle->m_flLength = random->RandomFloat( 0.0025f, 0.005f ) * scale * flDistanceScale; + tParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); + + colorRamp = random->RandomFloat( 0.5f, 0.75f ) + flLODDistance; + FloatToColor32( tParticle->m_color, MIN( 1.0, color[0] * colorRamp ), MIN( 1.0, color[1] * colorRamp ), MIN( 1.0, color[2] * colorRamp ), 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 * vecNormal ); + 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 += vecNormal * random->RandomInt( 10, 100 ); + //VectorNormalize( pParticle->m_vecVelocity ); + + colorRamp = random->RandomFloat( 0.75f, 1.0f ) + flLODDistance; + + 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, scale * 4 ) * flDistanceScale; + pParticle->m_uchEndSize = pParticle->m_uchStartSize * 2 * flDistanceScale; + + pParticle->m_uchStartAlpha = random->RandomInt( 200, 255 ); + pParticle->m_uchEndAlpha = 0; + + pParticle->m_flRoll = random->RandomInt( 0, 360 ); + pParticle->m_flRollDelta = random->RandomFloat( -4.0f, 4.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 * vecNormal * 0.5 ); + 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 += vecNormal * random->RandomInt( 100, 200 ); + + colorRamp = random->RandomFloat( 0.5f, 0.75f ) + flLODDistance; + + 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.5, scale ) * flDistanceScale; + pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4 * flDistanceScale; + + pParticle->m_uchStartAlpha = random->RandomInt( 80, 128 ); + pParticle->m_uchEndAlpha = 0; + + pParticle->m_flRoll = random->RandomInt( 0, 360 ); + pParticle->m_flRollDelta = random->RandomFloat( -4.0f, 4.0f ); + } + } + } + } + + // TODO: Play a sound? + //CLocalPlayerFilter filter; + //C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, CHAN_VOICE, "Physics.WaterSplash", 1.0, ATTN_NORM, 0, 100, &origin ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : bloodtype - +// r - +// g - +// b - +//----------------------------------------------------------------------------- +void GetBloodColorForTeam( int iTeam, unsigned char &r, unsigned char &g, unsigned char &b ) +{ + if ( iTeam == TEAM_ALIENS ) + { + r = 0; + g = 255; + b = 0; + } + else if ( iTeam == TEAM_HUMANS ) + { + // Humans + r = 255; + g = 0; + b = 0; + } + else + { + // NPCs? + r = 200; + g = 0; + b = 0; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Intercepts the blood spray message. +//----------------------------------------------------------------------------- +void TF2BloodSprayCallback( const CEffectData &data ) +{ + unsigned char r = 0; + unsigned char g = 0; + unsigned char b = 0; + + // Get the entity we've hit + C_BaseEntity *pEntity = ClientEntityList().GetEnt( data.m_nEntIndex ); + if ( pEntity ) + { + GetBloodColorForTeam( pEntity->GetTeamNumber(), r, g, b ); + if ( pEntity->IsPlayer() ) + { + C_BaseTFPlayer *pPlayer = (C_BaseTFPlayer *)pEntity; + pPlayer->PainSound(); + } + } + else + { + GetBloodColorForTeam( 0, r, g, b ); + } + FX_TF2_BloodSpray( data.m_vOrigin, data.m_vNormal, data.m_flScale, r, g, b, data.m_fFlags ); +} + +DECLARE_CLIENT_EFFECT( "tf2blood", TF2BloodSprayCallback ); |