aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/client/hl2/c_rotorwash.cpp
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /sp/src/game/client/hl2/c_rotorwash.cpp
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'sp/src/game/client/hl2/c_rotorwash.cpp')
-rw-r--r--sp/src/game/client/hl2/c_rotorwash.cpp306
1 files changed, 306 insertions, 0 deletions
diff --git a/sp/src/game/client/hl2/c_rotorwash.cpp b/sp/src/game/client/hl2/c_rotorwash.cpp
new file mode 100644
index 00000000..18655ea7
--- /dev/null
+++ b/sp/src/game/client/hl2/c_rotorwash.cpp
@@ -0,0 +1,306 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "particlemgr.h"
+#include "particle_prototype.h"
+#include "particle_util.h"
+#include "c_te_particlesystem.h"
+#include "fx.h"
+#include "fx_quad.h"
+#include "clienteffectprecachesystem.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+// ==============================================
+// Rotorwash particle emitter
+// ==============================================
+
+#ifndef _XBOX
+
+class WashEmitter : public CSimpleEmitter
+{
+public:
+
+ WashEmitter( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {}
+
+ static WashEmitter *Create( const char *pDebugName )
+ {
+ return new WashEmitter( pDebugName );
+ }
+
+ void UpdateVelocity( SimpleParticle *pParticle, float timeDelta )
+ {
+ // Float up when lifetime is half gone.
+ pParticle->m_vecVelocity[ 2 ] += 64 * timeDelta;
+
+ // FIXME: optimize this....
+ pParticle->m_vecVelocity *= ExponentialDecay( 0.8, 0.05, timeDelta );
+ }
+
+ virtual float UpdateRoll( SimpleParticle *pParticle, float timeDelta )
+ {
+ pParticle->m_flRoll += pParticle->m_flRollDelta * timeDelta;
+
+ pParticle->m_flRollDelta += pParticle->m_flRollDelta * ( timeDelta * -2.0f );
+
+ //Cap the minimum roll
+ if ( fabs( pParticle->m_flRollDelta ) < 0.5f )
+ {
+ pParticle->m_flRollDelta = ( pParticle->m_flRollDelta > 0.0f ) ? 0.5f : -0.5f;
+ }
+
+ return pParticle->m_flRoll;
+ }
+
+ virtual float UpdateAlpha( const SimpleParticle *pParticle )
+ {
+ return ( ((float)pParticle->m_uchStartAlpha/255.0f) * sin( M_PI * (pParticle->m_flLifetime / pParticle->m_flDieTime) ) );
+ }
+
+private:
+ WashEmitter( const WashEmitter & );
+};
+
+#endif // !_XBOX
+
+// ==============================================
+// Rotorwash entity
+// ==============================================
+
+#define ROTORWASH_THINK_INTERVAL 0.1f
+
+class C_RotorWashEmitter : public C_BaseEntity
+{
+public:
+
+ DECLARE_CLASS( C_RotorWashEmitter, C_BaseEntity );
+ DECLARE_CLIENTCLASS();
+
+ C_RotorWashEmitter( void );
+
+ virtual void OnDataChanged( DataUpdateType_t updateType );
+ virtual void ClientThink( void );
+
+protected:
+
+ float m_flAltitude;
+
+ PMaterialHandle m_hWaterMaterial[2];
+
+#ifndef _XBOX
+ void InitSpawner( void );
+ CSmartPtr<WashEmitter> m_pSimple;
+#endif // !XBOX
+};
+
+IMPLEMENT_CLIENTCLASS_DT( C_RotorWashEmitter, DT_RotorWashEmitter, CRotorWashEmitter)
+ RecvPropFloat(RECVINFO(m_flAltitude)),
+END_RECV_TABLE()
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+C_RotorWashEmitter::C_RotorWashEmitter( void )
+{
+#ifndef _XBOX
+ m_pSimple = NULL;
+ m_hWaterMaterial[0] = NULL;
+ m_hWaterMaterial[1] = NULL;
+#endif // !_XBOX
+}
+
+#ifndef _XBOX
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void C_RotorWashEmitter::InitSpawner( void )
+{
+ if ( m_pSimple.IsValid() )
+ return;
+
+ m_pSimple = WashEmitter::Create( "wash" );
+ m_pSimple->SetNearClip( 128, 256 );
+}
+#endif // !XBOX
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : updateType -
+//-----------------------------------------------------------------------------
+void C_RotorWashEmitter::OnDataChanged( DataUpdateType_t updateType )
+{
+ BaseClass::OnDataChanged( updateType );
+
+ if ( updateType == DATA_UPDATE_CREATED )
+ {
+ SetNextClientThink( gpGlobals->curtime + ROTORWASH_THINK_INTERVAL );
+
+#ifndef _XBOX
+ InitSpawner();
+#endif // !XBOX
+ }
+}
+
+//-----------------------------------------------------------------------------
+// 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
+}