diff options
Diffstat (limited to 'game/client/episodic/c_weapon_hopwire.cpp')
| -rw-r--r-- | game/client/episodic/c_weapon_hopwire.cpp | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/game/client/episodic/c_weapon_hopwire.cpp b/game/client/episodic/c_weapon_hopwire.cpp new file mode 100644 index 0000000..942ef0c --- /dev/null +++ b/game/client/episodic/c_weapon_hopwire.cpp @@ -0,0 +1,421 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "cbase.h" +#include "basegrenade_shared.h" +#include "fx_interpvalue.h" +#include "fx_envelope.h" +#include "materialsystem/imaterialvar.h" +#include "particles_simple.h" +#include "particles_attractor.h" + +// FIXME: Move out +extern void DrawSpriteTangentSpace( const Vector &vecOrigin, float flWidth, float flHeight, color32 color ); + +#define EXPLOSION_DURATION 3.0f + +//----------------------------------------------------------------------------- +// Explosion effect for hopwire +//----------------------------------------------------------------------------- + +class C_HopwireExplosion : public C_EnvelopeFX +{ + typedef C_EnvelopeFX BaseClass; + +public: + C_HopwireExplosion( void ) : + m_hOwner( NULL ) + { + m_FXCoreScale.SetAbsolute( 0.0f ); + m_FXCoreAlpha.SetAbsolute( 0.0f ); + } + + virtual void Update( void ); + virtual int DrawModel( int flags ); + virtual void GetRenderBounds( Vector& mins, Vector& maxs ); + + bool SetupEmitters( void ); + void AddParticles( void ); + void SetOwner( C_BaseEntity *pOwner ); + void StartExplosion( void ); + void StopExplosion( void ); + void StartPreExplosion( void ); + +private: + CInterpolatedValue m_FXCoreScale; + CInterpolatedValue m_FXCoreAlpha; + + CSmartPtr<CSimpleEmitter> m_pSimpleEmitter; + CSmartPtr<CParticleAttractor> m_pAttractorEmitter; + + TimedEvent m_ParticleTimer; + + CHandle<C_BaseEntity> m_hOwner; +}; + +//----------------------------------------------------------------------------- +// Purpose: Setup the emitters we'll be using +//----------------------------------------------------------------------------- +bool C_HopwireExplosion::SetupEmitters( void ) +{ + // Setup the basic core emitter + if ( m_pSimpleEmitter.IsValid() == false ) + { + m_pSimpleEmitter = CSimpleEmitter::Create( "hopwirecore" ); + + if ( m_pSimpleEmitter.IsValid() == false ) + return false; + } + + // Setup the attractor emitter + if ( m_pAttractorEmitter.IsValid() == false ) + { + m_pAttractorEmitter = CParticleAttractor::Create( GetRenderOrigin(), "hopwireattractor" ); + + if ( m_pAttractorEmitter.IsValid() == false ) + return false; + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_HopwireExplosion::AddParticles( void ) +{ + // Make sure the emitters are setup properly + if ( SetupEmitters() == false ) + return; + + float tempDelta = gpGlobals->frametime; + while( m_ParticleTimer.NextEvent( tempDelta ) ) + { + // ======================== + // Attracted dust particles + // ======================== + + // Update our attractor point + m_pAttractorEmitter->SetAttractorOrigin( GetRenderOrigin() ); + + Vector offset; + SimpleParticle *sParticle; + + offset = GetRenderOrigin() + RandomVector( -256.0f, 256.0f ); + + sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_Fleck_Cement[0], 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 = 1.0f; + + float alpha = random->RandomFloat( 128.0f, 200.0f ); + + sParticle->m_uchColor[0] = alpha; + sParticle->m_uchColor[1] = alpha; + sParticle->m_uchColor[2] = alpha; + sParticle->m_uchStartAlpha = alpha; + sParticle->m_uchEndAlpha = alpha; + + sParticle->m_uchStartSize = random->RandomInt( 1, 4 ); + sParticle->m_uchEndSize = 0; + + // ======================== + // Core effects + // ======================== + + // Reset our sort origin + m_pSimpleEmitter->SetSortOrigin( GetRenderOrigin() ); + + // Base of the core effect + sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( "effects/strider_muzzle" ), GetRenderOrigin() ); + + if ( sParticle == NULL ) + return; + + sParticle->m_vecVelocity = vec3_origin; + sParticle->m_flDieTime = 0.2f; + sParticle->m_flLifetime = 0.0f; + + sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); + sParticle->m_flRollDelta = 4.0f; + + alpha = random->RandomInt( 32, 200 ); + + sParticle->m_uchColor[0] = alpha; + sParticle->m_uchColor[1] = alpha; + sParticle->m_uchColor[2] = alpha; + sParticle->m_uchStartAlpha = 0; + sParticle->m_uchEndAlpha = alpha; + + sParticle->m_uchStartSize = 255; + sParticle->m_uchEndSize = 0; + + // Make sure we encompass the complete particle here! + m_pSimpleEmitter->SetParticleCullRadius( sParticle->m_uchEndSize ); + + // ========================= + // Dust ring effect + // ========================= + + if ( random->RandomInt( 0, 5 ) != 1 ) + return; + + Vector vecDustColor; + vecDustColor.x = 0.35f; + vecDustColor.y = 0.3f; + vecDustColor.z = 0.25f; + + Vector color; + + int numRingSprites = 8; + float yaw; + Vector forward, vRight, vForward; + + vForward = Vector( 0, 1, 0 ); + vRight = Vector( 1, 0, 0 ); + + float yawOfs = random->RandomFloat( 0, 359 ); + + for ( int i = 0; i < numRingSprites; i++ ) + { + yaw = ( (float) i / (float) numRingSprites ) * 360.0f; + yaw += yawOfs; + + forward = ( vRight * sin( DEG2RAD( yaw) ) ) + ( vForward * cos( DEG2RAD( yaw ) ) ); + VectorNormalize( forward ); + + trace_t tr; + + UTIL_TraceLine( GetRenderOrigin(), GetRenderOrigin()+(Vector(0, 0, -1024)), MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); + + offset = ( RandomVector( -4.0f, 4.0f ) + tr.endpos ) + ( forward * 512.0f ); + + sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[random->RandomInt(0,1)], offset ); + + if ( sParticle != NULL ) + { + sParticle->m_flLifetime = 0.0f; + sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); + + sParticle->m_vecVelocity = forward * -random->RandomFloat( 1000, 1500 ); + sParticle->m_vecVelocity[2] += 128.0f; + + #if __EXPLOSION_DEBUG + debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + sParticle->m_vecVelocity, 255, 0, 0, false, 3 ); + #endif + + sParticle->m_uchColor[0] = vecDustColor.x * 255.0f; + sParticle->m_uchColor[1] = vecDustColor.y * 255.0f; + sParticle->m_uchColor[2] = vecDustColor.z * 255.0f; + + sParticle->m_uchStartSize = random->RandomInt( 32, 128 ); + sParticle->m_uchEndSize = 200; + + sParticle->m_uchStartAlpha = random->RandomFloat( 16, 64 ); + sParticle->m_uchEndAlpha = 0; + + sParticle->m_flRoll = random->RandomInt( 0, 360 ); + sParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.0f ); + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pOwner - +//----------------------------------------------------------------------------- +void C_HopwireExplosion::SetOwner( C_BaseEntity *pOwner ) +{ + m_hOwner = pOwner; +} + +//----------------------------------------------------------------------------- +// Purpose: Updates the internal values for the effect +//----------------------------------------------------------------------------- +void C_HopwireExplosion::Update( void ) +{ + if ( m_hOwner ) + { + SetRenderOrigin( m_hOwner->GetRenderOrigin() ); + } + + BaseClass::Update(); +} + +//----------------------------------------------------------------------------- +// Purpose: Updates and renders all effects +//----------------------------------------------------------------------------- +int C_HopwireExplosion::DrawModel( int flags ) +{ + AddParticles(); + + CMatRenderContextPtr pRenderContext( materials ); + pRenderContext->Flush(); + UpdateRefractTexture(); + + IMaterial *pMat = materials->FindMaterial( "effects/strider_pinch_dudv", TEXTURE_GROUP_CLIENT_EFFECTS ); + + float refract = m_FXCoreAlpha.Interp( gpGlobals->curtime ); + float scale = m_FXCoreScale.Interp( gpGlobals->curtime ); + + IMaterialVar *pVar = pMat->FindVar( "$refractamount", NULL ); + pVar->SetFloatValue( refract ); + + pRenderContext->Bind( pMat, (IClientRenderable*)this ); + + float sin1 = sinf( gpGlobals->curtime * 10 ); + float sin2 = sinf( gpGlobals->curtime ); + + float scaleY = ( sin1 * sin2 ) * 32.0f; + float scaleX = (sin2 * sin2) * 32.0f; + + // FIXME: The ball needs to sort properly at all times + static color32 white = {255,255,255,255}; + DrawSpriteTangentSpace( GetRenderOrigin() + ( CurrentViewForward() * 128.0f ), scale+scaleX, scale+scaleY, white ); + + return 1; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns the bounds relative to the origin (render bounds) +//----------------------------------------------------------------------------- +void C_HopwireExplosion::GetRenderBounds( Vector& mins, Vector& maxs ) +{ + float scale = m_FXCoreScale.Interp( gpGlobals->curtime ); + + mins.Init( -scale, -scale, -scale ); + maxs.Init( scale, scale, scale ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_HopwireExplosion::StartExplosion( void ) +{ + m_FXCoreScale.Init( 300.0f, 500.0f, 2.0f, INTERP_SPLINE ); + m_FXCoreAlpha.Init( 0.0f, 0.1f, 1.5f, INTERP_SPLINE ); + + // Particle timer + m_ParticleTimer.Init( 60 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_HopwireExplosion::StopExplosion( void ) +{ + m_FXCoreAlpha.InitFromCurrent( 0.0f, 1.0f, INTERP_SPLINE ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_HopwireExplosion::StartPreExplosion( void ) +{ +} + +//----------------------------------------------------------------------------- +// Hopwire client class +//----------------------------------------------------------------------------- + +class C_GrenadeHopwire : public C_BaseGrenade +{ + DECLARE_CLASS( C_GrenadeHopwire, C_BaseGrenade ); + DECLARE_CLIENTCLASS(); + +public: + C_GrenadeHopwire( void ); + + virtual int DrawModel( int flags ); + + virtual void OnDataChanged( DataUpdateType_t updateType ); + virtual void ReceiveMessage( int classID, bf_read &msg ); + +private: + + C_HopwireExplosion m_ExplosionEffect; // Explosion effect information and drawing +}; + +IMPLEMENT_CLIENTCLASS_DT( C_GrenadeHopwire, DT_GrenadeHopwire, CGrenadeHopwire ) +END_RECV_TABLE() + +#define HOPWIRE_START_EXPLOSION 0 +#define HOPWIRE_STOP_EXPLOSION 1 +#define HOPWIRE_START_PRE_EXPLOSION 2 + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +C_GrenadeHopwire::C_GrenadeHopwire( void ) +{ + m_ExplosionEffect.SetActive( false ); +} + +//----------------------------------------------------------------------------- +// Purpose: Receive messages from the server +// Input : classID - class to receive the message +// &msg - message in question +//----------------------------------------------------------------------------- +void C_GrenadeHopwire::ReceiveMessage( int classID, bf_read &msg ) +{ + if ( classID != GetClientClass()->m_ClassID ) + { + // Message is for subclass + BaseClass::ReceiveMessage( classID, msg ); + return; + } + + int messageType = msg.ReadByte(); + switch( messageType ) + { + case HOPWIRE_START_EXPLOSION: + { + m_ExplosionEffect.SetActive(); + m_ExplosionEffect.SetOwner( this ); + m_ExplosionEffect.StartExplosion(); + } + break; + case HOPWIRE_STOP_EXPLOSION: + { + m_ExplosionEffect.StopExplosion(); + } + break; + default: + break; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : updateType - +//----------------------------------------------------------------------------- +void C_GrenadeHopwire::OnDataChanged( DataUpdateType_t updateType ) +{ + BaseClass::OnDataChanged( updateType ); + + m_ExplosionEffect.Update(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : flags - +//----------------------------------------------------------------------------- +int C_GrenadeHopwire::DrawModel( int flags ) +{ + if ( m_ExplosionEffect.IsActive() ) + return 1; + + return BaseClass::DrawModel( flags ); +} + |