mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-13 04:09:09 +00:00
1
This commit is contained in:
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user