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/c_gasoline_blob.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/c_gasoline_blob.cpp')
| -rw-r--r-- | game/client/tf2/c_gasoline_blob.cpp | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/game/client/tf2/c_gasoline_blob.cpp b/game/client/tf2/c_gasoline_blob.cpp new file mode 100644 index 0000000..800ee89 --- /dev/null +++ b/game/client/tf2/c_gasoline_blob.cpp @@ -0,0 +1,350 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "c_gasoline_blob.h" +#include "gasoline_shared.h" +#include "engine/IEngineSound.h" +#include "clienteffectprecachesystem.h" + +static CUtlLinkedList<C_GasolineBlob*, int> g_GasolineBlobs; + +// If multiple blobs are within this distance to each other, then only one will +// play a sound. +#define BLOB_SOUND_RELATED_DISTANCE 600 + + +#define PUDDLE_START_SIZE 35 +#define PUDDLE_END_SIZE 65 +#define PUDDLE_GROW_TIME 0.5 + +#define PUDDLE_FADE_TIME 1.0 + + +CLIENTEFFECT_REGISTER_BEGIN( PrecacheGasolineBlob ) +CLIENTEFFECT_MATERIAL( "decals/puddle" ) +CLIENTEFFECT_REGISTER_END() + +// ------------------------------------------------------------------------------------------------ // +// CGasolineEmitter. +// ------------------------------------------------------------------------------------------------ // + +CSmartPtr<CGasolineEmitter> CGasolineEmitter::Create( C_GasolineBlob *pBlob ) +{ + CGasolineEmitter *pEmitter = new CGasolineEmitter; + + pEmitter->m_pBlob = pBlob; + + pEmitter->m_hFireMaterial = pEmitter->GetPMaterial( "particle/fire" ); + pEmitter->m_hUnlitMaterial = pEmitter->GetPMaterial( "sprites/env_particles" ); + + pEmitter->m_Timer.Init( 40 ); + + return pEmitter; +} + + +void CGasolineEmitter::UpdateFire( float frametime ) +{ + float flLifetime = gpGlobals->curtime - m_pBlob->m_flCreateTime; + + float litPercent = 1; + if ( m_pBlob->IsLit() ) + { + litPercent = 1 - (flLifetime / m_pBlob->m_flMaxLifetime); + if ( litPercent <= 0 ) + return; + } + else + { + return; + } + + // Don't show a burn effect for a blob that hasn't hit anything yet. + // If you do, it tends to make the flamethrower effect look weird. + if ( !m_pBlob->IsStopped() ) + return; + + // Make a coordinate system in which to spawn the particles. It + Vector vUp, vRight; + vUp.Init(); + vRight.Init(); + if ( m_pBlob->IsStopped() ) + { + QAngle angles; + VectorAngles( m_pBlob->GetSurfaceNormal(), angles ); + AngleVectors( angles, NULL, &vRight, &vUp ); + } + + PMaterialHandle hMaterial = m_hFireMaterial; + float flParticleLifetime = 1; + float flRadius = 7; + unsigned char uchColor[4] = { 255, 128, 0, 128 }; + float flMaxZVel = 29; + + + float curDelta = frametime; + while ( m_Timer.NextEvent( curDelta ) ) + { + // Based on how close we are to expiring, show less particles. + if ( RandomFloat( 0, 1 ) > litPercent ) + continue; + + Vector vPos = m_pBlob->GetAbsOrigin(); + if ( m_pBlob->IsStopped() ) + { + float flAngle = RandomFloat( 0, M_PI * 2 ); + float flDist = RandomFloat( 0, GASOLINE_BLOB_RADIUS ); + vPos += vRight * (cos( flAngle ) * flDist); + vPos += vUp * ( sin( flAngle ) * flDist ); + } + else + { + vPos += RandomVector( -GASOLINE_BLOB_RADIUS, GASOLINE_BLOB_RADIUS ); + } + + SimpleParticle *pParticle = AddSimpleParticle( hMaterial, vPos, flParticleLifetime, flRadius ); + if ( pParticle ) + { + pParticle->m_uchColor[0] = uchColor[0]; + pParticle->m_uchColor[1] = uchColor[1]; + pParticle->m_uchColor[2] = uchColor[2]; + + pParticle->m_uchEndAlpha = 0; + pParticle->m_uchStartAlpha = uchColor[3]; + + pParticle->m_vecVelocity.x = RandomFloat( -2, 2 ); + pParticle->m_vecVelocity.y = RandomFloat( -2, 2 ); + pParticle->m_vecVelocity.z = RandomFloat( 3, flMaxZVel ); + } + } +} + + +// ------------------------------------------------------------------------------------------------ // +// C_GasolineBlob. +// ------------------------------------------------------------------------------------------------ // + +IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_GasolineBlob, DT_GasolineBlob, CGasolineBlob ) + RecvPropInt( RECVINFO( m_BlobFlags ) ), + RecvPropVector( RECVINFO_NAME( m_vecNetworkOrigin, m_vecOrigin ) ), + RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ), + RecvPropFloat( RECVINFO( m_flLitStartTime ) ), + RecvPropFloat( RECVINFO( m_flCreateTime ) ), + RecvPropFloat( RECVINFO( m_flMaxLifetime ) ), + RecvPropInt( RECVINFO( m_iTeamNum ) ), + RecvPropVector( RECVINFO( m_vSurfaceNormal ) ) +END_RECV_TABLE() + + +C_GasolineBlob::C_GasolineBlob() +{ + m_pEmitter = CGasolineEmitter::Create( this ); + m_vSurfaceNormal.Init(); + m_flLitStartTime = 0; + m_bSoundOn = false; + g_GasolineBlobs.AddToTail( this ); + m_flPuddleSize = PUDDLE_START_SIZE; + m_flPuddleFade = 1; +} + + +C_GasolineBlob::~C_GasolineBlob() +{ + g_GasolineBlobs.FindAndRemove( this ); + StopSound(); + + // If a bunch of nearby blobs weren't playing a sound because we were, have them start their sound now. + FOR_EACH_LL( g_GasolineBlobs, i ) + { + C_GasolineBlob *pBlob = g_GasolineBlobs[i]; + + if ( pBlob->IsSoundRelatedTo( this ) ) + pBlob->CheckStartSound(); + } +} + + +bool C_GasolineBlob::IsLit() const +{ + return (m_BlobFlags & BLOBFLAG_LIT) != 0; +} + + +bool C_GasolineBlob::IsStopped() const +{ + return (m_BlobFlags & BLOBFLAG_STOPPED) != 0; +} + + +const Vector& C_GasolineBlob::GetSurfaceNormal() const +{ + return m_vSurfaceNormal; +} + + +float C_GasolineBlob::GetLitStartTime() const +{ + return m_flLitStartTime; +} + + +void C_GasolineBlob::OnDataChanged( DataUpdateType_t type ) +{ + BaseClass::OnDataChanged( type ); + + if ( type == DATA_UPDATE_CREATED ) + { + SetNextClientThink( CLIENT_THINK_ALWAYS ); + } + + CheckStartSound(); +} + + +void C_GasolineBlob::ClientThink() +{ + if ( m_pEmitter.IsValid() ) + m_pEmitter->UpdateFire( gpGlobals->frametime ); + + // Grow the puddle a little. + if ( IsStopped() ) + { + if ( IsLit() ) + { + // Fade out after we get lit. + m_flPuddleFade -= gpGlobals->frametime / PUDDLE_FADE_TIME; + m_flPuddleFade = MAX( m_flPuddleFade, 0 ); + } + else + { + // Grow the puddle until it's at its max size. + m_flPuddleSize += gpGlobals->frametime * ( PUDDLE_END_SIZE - PUDDLE_START_SIZE ) / PUDDLE_GROW_TIME; + m_flPuddleSize = MIN( m_flPuddleSize, PUDDLE_END_SIZE ); + } + } +} + + +bool C_GasolineBlob::ShouldDraw() +{ + return IsStopped() && (m_flPuddleFade > 0); +} + + +int C_GasolineBlob::DrawModel( int flags ) +{ + // Generate a basis. + QAngle angles; + VectorAngles( m_vSurfaceNormal, angles ); + + Vector vRight, vUp; + AngleVectors( angles, NULL, &vRight, &vUp ); + + + float flAlpha = m_flPuddleFade * RemapVal( m_flPuddleSize, PUDDLE_START_SIZE, PUDDLE_END_SIZE, 0, 1 ); + if ( flAlpha <= 0 ) + return 0; + + + // Draw the puddle. + IMaterial *pMat = materials->FindMaterial( "decals/puddle", TEXTURE_GROUP_DECAL ); + IMesh *pMesh = materials->GetDynamicMesh( true, NULL, NULL, pMat ); + CMeshBuilder mb; + mb.Begin( pMesh, MATERIAL_QUADS, 1 ); + + Vector v; + + v = GetAbsOrigin() + m_vSurfaceNormal + vRight*m_flPuddleSize - vUp*m_flPuddleSize; + mb.Position3f( v.x, v.y, v.z ); + mb.Color4f( 1, 1, 1, flAlpha ); + mb.Normal3f( VectorExpand( m_vSurfaceNormal ) ); + mb.TexCoord2f( 0, 1, 0 ); + mb.AdvanceVertex(); + + v = GetAbsOrigin() + m_vSurfaceNormal + vRight*m_flPuddleSize + vUp*m_flPuddleSize; + mb.Position3f( v.x, v.y, v.z ); + mb.Color4f( 1, 1, 1, flAlpha ); + mb.Normal3f( VectorExpand( m_vSurfaceNormal ) ); + mb.TexCoord2f( 0, 1, 1 ); + mb.AdvanceVertex(); + + v = GetAbsOrigin() + m_vSurfaceNormal - vRight*m_flPuddleSize + vUp*m_flPuddleSize; + mb.Position3f( v.x, v.y, v.z ); + mb.Color4f( 1, 1, 1, flAlpha ); + mb.Normal3f( VectorExpand( m_vSurfaceNormal ) ); + mb.TexCoord2f( 0, 0, 1 ); + mb.AdvanceVertex(); + + v = GetAbsOrigin() + m_vSurfaceNormal - vRight*m_flPuddleSize - vUp*m_flPuddleSize; + mb.Position3f( v.x, v.y, v.z ); + mb.Color4f( 1, 1, 1, flAlpha ); + mb.Normal3f( VectorExpand( m_vSurfaceNormal ) ); + mb.TexCoord2f( 0, 0, 0 ); + mb.AdvanceVertex(); + + mb.End( false, true ); + + return 0; +} + + +bool C_GasolineBlob::IsSoundRelatedTo( const C_GasolineBlob *pBlob ) const +{ + return pBlob->GetAbsOrigin().DistTo( GetAbsOrigin() ) < BLOB_SOUND_RELATED_DISTANCE; +} + + +bool C_GasolineBlob::IsPlayingBurningSound() const +{ + return m_bSoundOn; +} + + +void C_GasolineBlob::CheckStartSound() +{ + if ( IsPlayingBurningSound() || (m_BlobFlags & BLOBFLAG_STOPPED) == 0 || !IsLit() ) + return; + + + // First, make sure no nearby blob is playing the sound. + FOR_EACH_LL( g_GasolineBlobs, i ) + { + C_GasolineBlob *pBlob = g_GasolineBlobs[i]; + + if ( pBlob != this && pBlob->IsSoundRelatedTo( this ) ) + { + // If it's already playing a sound, then don't start our sound. + if ( pBlob->IsPlayingBurningSound() ) + return; + } + } + + + StartSound(); +} + + +void C_GasolineBlob::StartSound() +{ + if ( !m_bSoundOn ) + { + EmitSound( "GasolineBlob.FlameSound" ); + + m_bSoundOn = true; + } +} + + +void C_GasolineBlob::StopSound() +{ + if ( m_bSoundOn ) + { + BaseClass::StopSound( "GasolineBlob.FlameSound" ); + m_bSoundOn = false; + } +} + |