aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/client/c_steamjet.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/client/c_steamjet.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/client/c_steamjet.cpp')
-rw-r--r--mp/src/game/client/c_steamjet.cpp1050
1 files changed, 525 insertions, 525 deletions
diff --git a/mp/src/game/client/c_steamjet.cpp b/mp/src/game/client/c_steamjet.cpp
index 09377908..f36ccc63 100644
--- a/mp/src/game/client/c_steamjet.cpp
+++ b/mp/src/game/client/c_steamjet.cpp
@@ -1,525 +1,525 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Implements a particle system steam jet.
-//
-// $NoKeywords: $
-//=============================================================================//
-#include "cbase.h"
-#include "particle_prototype.h"
-#include "particle_util.h"
-#include "baseparticleentity.h"
-#include "clienteffectprecachesystem.h"
-#include "fx.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-//NOTENOTE: Mirrored in dlls\steamjet.h
-#define STEAM_NORMAL 0
-#define STEAM_HEATWAVE 1
-
-#define STEAMJET_NUMRAMPS 5
-#define SF_EMISSIVE 0x00000001
-
-
-//==================================================
-// C_SteamJet
-//==================================================
-
-class C_SteamJet : public C_BaseParticleEntity, public IPrototypeAppEffect
-{
-public:
- DECLARE_CLIENTCLASS();
- DECLARE_CLASS( C_SteamJet, C_BaseParticleEntity );
-
- C_SteamJet();
- ~C_SteamJet();
-
- class SteamJetParticle : public Particle
- {
- public:
- Vector m_Velocity;
- float m_flRoll;
- float m_flRollDelta;
- float m_Lifetime;
- float m_DieTime;
- unsigned char m_uchStartSize;
- unsigned char m_uchEndSize;
- };
-
- int IsEmissive( void ) { return ( m_spawnflags & SF_EMISSIVE ); }
-
-//C_BaseEntity
-public:
-
- virtual void OnDataChanged( DataUpdateType_t updateType );
-
-
-//IPrototypeAppEffect
-public:
- virtual void Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs);
- virtual bool GetPropEditInfo(RecvTable **ppTable, void **ppObj);
-
-
-//IParticleEffect
-public:
- virtual void Update(float fTimeDelta);
- virtual void RenderParticles( CParticleRenderIterator *pIterator );
- virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
-
-
-//Stuff from the datatable
-public:
-
- float m_SpreadSpeed;
- float m_Speed;
- float m_StartSize;
- float m_EndSize;
- float m_Rate;
- float m_JetLength; // Length of the jet. Lifetime is derived from this.
-
- int m_bEmit; // Emit particles?
- int m_nType; // Type of particles to emit
- bool m_bFaceLeft; // For support of legacy env_steamjet entity, which faced left instead of forward.
-
- int m_spawnflags;
- float m_flRollSpeed;
-
-private:
-
- void UpdateLightingRamp();
-
-private:
-
- // Stored the last time it updates the lighting ramp, so it can cache the values.
- Vector m_vLastRampUpdatePos;
- QAngle m_vLastRampUpdateAngles;
-
- float m_Lifetime; // Calculated from m_JetLength / m_Speed;
-
- // We sample the world to get these colors and ramp the particles.
- Vector m_Ramps[STEAMJET_NUMRAMPS];
-
- CParticleMgr *m_pParticleMgr;
- PMaterialHandle m_MaterialHandle;
- TimedEvent m_ParticleSpawn;
-
-private:
- C_SteamJet( const C_SteamJet & );
-};
-
-
-// ------------------------------------------------------------------------- //
-// Tables.
-// ------------------------------------------------------------------------- //
-
-// Expose to the particle app.
-EXPOSE_PROTOTYPE_EFFECT(SteamJet, C_SteamJet);
-
-
-// Datatable..
-IMPLEMENT_CLIENTCLASS_DT(C_SteamJet, DT_SteamJet, CSteamJet)
- RecvPropFloat(RECVINFO(m_SpreadSpeed), 0),
- RecvPropFloat(RECVINFO(m_Speed), 0),
- RecvPropFloat(RECVINFO(m_StartSize), 0),
- RecvPropFloat(RECVINFO(m_EndSize), 0),
- RecvPropFloat(RECVINFO(m_Rate), 0),
- RecvPropFloat(RECVINFO(m_JetLength), 0),
- RecvPropInt(RECVINFO(m_bEmit), 0),
- RecvPropInt(RECVINFO(m_bFaceLeft), 0),
- RecvPropInt(RECVINFO(m_nType), 0),
- RecvPropInt( RECVINFO( m_spawnflags ) ),
- RecvPropFloat(RECVINFO(m_flRollSpeed), 0 ),
-END_RECV_TABLE()
-
-// ------------------------------------------------------------------------- //
-// C_SteamJet implementation.
-// ------------------------------------------------------------------------- //
-C_SteamJet::C_SteamJet()
-{
- m_pParticleMgr = NULL;
- m_MaterialHandle = INVALID_MATERIAL_HANDLE;
-
- m_SpreadSpeed = 15;
- m_Speed = 120;
- m_StartSize = 10;
- m_EndSize = 25;
- m_Rate = 26;
- m_JetLength = 80;
- m_bEmit = true;
- m_bFaceLeft = false;
- m_ParticleEffect.SetAlwaysSimulate( false ); // Don't simulate outside the PVS or frustum.
-
- m_vLastRampUpdatePos.Init( 1e24, 1e24, 1e24 );
- m_vLastRampUpdateAngles.Init( 1e24, 1e24, 1e24 );
-}
-
-
-C_SteamJet::~C_SteamJet()
-{
- if(m_pParticleMgr)
- m_pParticleMgr->RemoveEffect( &m_ParticleEffect );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Called after a data update has occured
-// Input : bnewentity -
-//-----------------------------------------------------------------------------
-void C_SteamJet::OnDataChanged(DataUpdateType_t updateType)
-{
- C_BaseEntity::OnDataChanged(updateType);
-
- if(updateType == DATA_UPDATE_CREATED)
- {
- Start(ParticleMgr(), NULL);
- }
-
- // Recalulate lifetime in case length or speed changed.
- m_Lifetime = m_JetLength / m_Speed;
- m_ParticleEffect.SetParticleCullRadius( MAX(m_StartSize, m_EndSize) );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Starts the effect
-// Input : *pParticleMgr -
-// *pArgs -
-//-----------------------------------------------------------------------------
-void C_SteamJet::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
-{
- pParticleMgr->AddEffect( &m_ParticleEffect, this );
-
- switch(m_nType)
- {
- case STEAM_NORMAL:
- default:
- m_MaterialHandle = g_Mat_DustPuff[0];
- break;
-
- case STEAM_HEATWAVE:
- m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial("sprites/heatwave");
- break;
- }
-
- m_ParticleSpawn.Init(m_Rate);
- m_Lifetime = m_JetLength / m_Speed;
- m_pParticleMgr = pParticleMgr;
-
- UpdateLightingRamp();
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : **ppTable -
-// **ppObj -
-// Output : Returns true on success, false on failure.
-//-----------------------------------------------------------------------------
-bool C_SteamJet::GetPropEditInfo( RecvTable **ppTable, void **ppObj )
-{
- *ppTable = &REFERENCE_RECV_TABLE(DT_SteamJet);
- *ppObj = this;
- return true;
-}
-
-
-// This might be useful someday.
-/*
-void CalcFastApproximateRenderBoundsAABB( C_BaseEntity *pEnt, float flBloatSize, Vector *pMin, Vector *pMax )
-{
- C_BaseEntity *pParent = pEnt->GetMoveParent();
- if ( pParent )
- {
- // Get the parent's abs space world bounds.
- CalcFastApproximateRenderBoundsAABB( pParent, 0, pMin, pMax );
-
- // Add the maximum of our local render bounds. This is making the assumption that we can be at any
- // point and at any angle within the parent's world space bounds.
- Vector vAddMins, vAddMaxs;
- pEnt->GetRenderBounds( vAddMins, vAddMaxs );
-
- flBloatSize += MAX( vAddMins.Length(), vAddMaxs.Length() );
- }
- else
- {
- // Start out with our own render bounds. Since we don't have a parent, this won't incur any nasty
- pEnt->GetRenderBoundsWorldspace( *pMin, *pMax );
- }
-
- // Bloat the box.
- if ( flBloatSize )
- {
- *pMin -= Vector( flBloatSize, flBloatSize, flBloatSize );
- *pMax += Vector( flBloatSize, flBloatSize, flBloatSize );
- }
-}
-*/
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : fTimeDelta -
-//-----------------------------------------------------------------------------
-
-void C_SteamJet::Update(float fTimeDelta)
-{
- if(!m_pParticleMgr)
- {
- assert(false);
- return;
- }
-
- if( m_bEmit )
- {
- // Add new particles.
- int nToEmit = 0;
- float tempDelta = fTimeDelta;
- while( m_ParticleSpawn.NextEvent(tempDelta) )
- ++nToEmit;
-
- if ( nToEmit > 0 )
- {
- Vector forward, right, up;
- AngleVectors(GetAbsAngles(), &forward, &right, &up);
-
- // Legacy env_steamjet entities faced left instead of forward.
- if (m_bFaceLeft)
- {
- Vector temp = forward;
- forward = -right;
- right = temp;
- }
-
- // EVIL: Ideally, we could tell the renderer our OBB, and let it build a big box that encloses
- // the entity with its parent so it doesn't have to setup its parent's bones here.
- Vector vEndPoint = GetAbsOrigin() + forward * m_Speed;
- Vector vMin, vMax;
- VectorMin( GetAbsOrigin(), vEndPoint, vMin );
- VectorMax( GetAbsOrigin(), vEndPoint, vMax );
- m_ParticleEffect.SetBBox( vMin, vMax );
-
- if ( m_ParticleEffect.WasDrawnPrevFrame() )
- {
- while ( nToEmit-- )
- {
- // Make a new particle.
- if( SteamJetParticle *pParticle = (SteamJetParticle*) m_ParticleEffect.AddParticle( sizeof(SteamJetParticle), m_MaterialHandle ) )
- {
- pParticle->m_Pos = GetAbsOrigin();
-
- pParticle->m_Velocity =
- FRand(-m_SpreadSpeed,m_SpreadSpeed) * right +
- FRand(-m_SpreadSpeed,m_SpreadSpeed) * up +
- m_Speed * forward;
-
- pParticle->m_Lifetime = 0;
- pParticle->m_DieTime = m_Lifetime;
-
- pParticle->m_uchStartSize = m_StartSize;
- pParticle->m_uchEndSize = m_EndSize;
-
- pParticle->m_flRoll = random->RandomFloat( 0, 360 );
- pParticle->m_flRollDelta = random->RandomFloat( -m_flRollSpeed, m_flRollSpeed );
- }
- }
- }
-
- UpdateLightingRamp();
- }
- }
-}
-
-
-// Render a quad on the screen where you pass in color and size.
-// Normal is random and "flutters"
-inline void RenderParticle_ColorSizePerturbNormal(
- ParticleDraw* pDraw,
- const Vector &pos,
- const Vector &color,
- const float alpha,
- const float size
- )
-{
- // Don't render totally transparent particles.
- if( alpha < 0.001f )
- return;
-
- CMeshBuilder *pBuilder = pDraw->GetMeshBuilder();
- if( !pBuilder )
- return;
-
- unsigned char ubColor[4];
- ubColor[0] = (unsigned char)RoundFloatToInt( color.x * 254.9f );
- ubColor[1] = (unsigned char)RoundFloatToInt( color.y * 254.9f );
- ubColor[2] = (unsigned char)RoundFloatToInt( color.z * 254.9f );
- ubColor[3] = (unsigned char)RoundFloatToInt( alpha * 254.9f );
-
- Vector vNorm;
-
- vNorm.Random( -1.0f, 1.0f );
-
- // Add the 4 corner vertices.
- pBuilder->Position3f( pos.x-size, pos.y-size, pos.z );
- pBuilder->Color4ubv( ubColor );
- pBuilder->Normal3fv( vNorm.Base() );
- pBuilder->TexCoord2f( 0, 0, 1.0f );
- pBuilder->AdvanceVertex();
-
- pBuilder->Position3f( pos.x-size, pos.y+size, pos.z );
- pBuilder->Color4ubv( ubColor );
- pBuilder->Normal3fv( vNorm.Base() );
- pBuilder->TexCoord2f( 0, 0, 0 );
- pBuilder->AdvanceVertex();
-
- pBuilder->Position3f( pos.x+size, pos.y+size, pos.z );
- pBuilder->Color4ubv( ubColor );
- pBuilder->Normal3fv( vNorm.Base() );
- pBuilder->TexCoord2f( 0, 1.0f, 0 );
- pBuilder->AdvanceVertex();
-
- pBuilder->Position3f( pos.x+size, pos.y-size, pos.z );
- pBuilder->Color4ubv( ubColor );
- pBuilder->Normal3fv( vNorm.Base() );
- pBuilder->TexCoord2f( 0, 1.0f, 1.0f );
- pBuilder->AdvanceVertex();
-}
-
-
-void C_SteamJet::RenderParticles( CParticleRenderIterator *pIterator )
-{
- const SteamJetParticle *pParticle = (const SteamJetParticle*)pIterator->GetFirst();
- while ( pParticle )
- {
- // Render.
- Vector tPos;
- TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos);
- float sortKey = tPos.z;
-
- float lifetimeT = pParticle->m_Lifetime / (pParticle->m_DieTime + 0.001);
- float fRamp = lifetimeT * (STEAMJET_NUMRAMPS-1);
- int iRamp = (int)fRamp;
- float fraction = fRamp - iRamp;
-
- Vector vRampColor = m_Ramps[iRamp] + (m_Ramps[iRamp+1] - m_Ramps[iRamp]) * fraction;
-
- vRampColor[0] = MIN( 1.0f, vRampColor[0] );
- vRampColor[1] = MIN( 1.0f, vRampColor[1] );
- vRampColor[2] = MIN( 1.0f, vRampColor[2] );
-
- float sinLifetime = sin(pParticle->m_Lifetime * 3.14159f / pParticle->m_DieTime);
-
- if ( m_nType == STEAM_HEATWAVE )
- {
- RenderParticle_ColorSizePerturbNormal(
- pIterator->GetParticleDraw(),
- tPos,
- vRampColor,
- sinLifetime * (m_clrRender->a/255.0f),
- FLerp(m_StartSize, m_EndSize, pParticle->m_Lifetime));
- }
- else
- {
- RenderParticle_ColorSizeAngle(
- pIterator->GetParticleDraw(),
- tPos,
- vRampColor,
- sinLifetime * (m_clrRender->a/255.0f),
- FLerp(pParticle->m_uchStartSize, pParticle->m_uchEndSize, pParticle->m_Lifetime),
- pParticle->m_flRoll );
- }
-
- pParticle = (const SteamJetParticle*)pIterator->GetNext( sortKey );
- }
-}
-
-
-void C_SteamJet::SimulateParticles( CParticleSimulateIterator *pIterator )
-{
- //Don't simulate if we're emiting particles...
- //This fixes the cases where looking away from a steam jet and then looking back would cause a break on the stream.
- if ( m_ParticleEffect.WasDrawnPrevFrame() == false && m_bEmit )
- return;
-
- SteamJetParticle *pParticle = (SteamJetParticle*)pIterator->GetFirst();
- while ( pParticle )
- {
- // Should this particle die?
- pParticle->m_Lifetime += pIterator->GetTimeDelta();
-
- if( pParticle->m_Lifetime > pParticle->m_DieTime )
- {
- pIterator->RemoveParticle( pParticle );
- }
- else
- {
- pParticle->m_flRoll += pParticle->m_flRollDelta * pIterator->GetTimeDelta();
- pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * pIterator->GetTimeDelta();
- }
-
- pParticle = (SteamJetParticle*)pIterator->GetNext();
- }
-}
-
-
-void C_SteamJet::UpdateLightingRamp()
-{
- if( VectorsAreEqual( m_vLastRampUpdatePos, GetAbsOrigin(), 0.1 ) &&
- QAnglesAreEqual( m_vLastRampUpdateAngles, GetAbsAngles(), 0.1 ) )
- {
- return;
- }
-
- m_vLastRampUpdatePos = GetAbsOrigin();
- m_vLastRampUpdateAngles = GetAbsAngles();
-
- // Sample the world lighting where we think the particles will be.
- Vector forward, right, up;
- AngleVectors(GetAbsAngles(), &forward, &right, &up);
-
- // Legacy env_steamjet entities faced left instead of forward.
- if (m_bFaceLeft)
- {
- Vector temp = forward;
- forward = -right;
- right = temp;
- }
-
- Vector startPos = GetAbsOrigin();
- Vector endPos = GetAbsOrigin() + forward * (m_Speed * m_Lifetime);
-
- for(int iRamp=0; iRamp < STEAMJET_NUMRAMPS; iRamp++)
- {
- float t = (float)iRamp / (STEAMJET_NUMRAMPS-1);
- Vector vTestPos = startPos + (endPos - startPos) * t;
-
- Vector *pRamp = &m_Ramps[iRamp];
- *pRamp = WorldGetLightForPoint(vTestPos, false);
-
- if ( IsEmissive() )
- {
- pRamp->x += (m_clrRender->r/255.0f);
- pRamp->y += (m_clrRender->g/255.0f);
- pRamp->z += (m_clrRender->b/255.0f);
-
- pRamp->x = clamp( pRamp->x, 0.0f, 1.0f );
- pRamp->y = clamp( pRamp->y, 0.0f, 1.0f );
- pRamp->z = clamp( pRamp->z, 0.0f, 1.0f );
- }
- else
- {
- pRamp->x *= (m_clrRender->r/255.0f);
- pRamp->y *= (m_clrRender->g/255.0f);
- pRamp->z *= (m_clrRender->b/255.0f);
- }
-
- // Renormalize?
- float maxVal = MAX(pRamp->x, MAX(pRamp->y, pRamp->z));
- if(maxVal > 1)
- {
- *pRamp = *pRamp / maxVal;
- }
- }
-}
-
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Implements a particle system steam jet.
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "particle_prototype.h"
+#include "particle_util.h"
+#include "baseparticleentity.h"
+#include "clienteffectprecachesystem.h"
+#include "fx.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//NOTENOTE: Mirrored in dlls\steamjet.h
+#define STEAM_NORMAL 0
+#define STEAM_HEATWAVE 1
+
+#define STEAMJET_NUMRAMPS 5
+#define SF_EMISSIVE 0x00000001
+
+
+//==================================================
+// C_SteamJet
+//==================================================
+
+class C_SteamJet : public C_BaseParticleEntity, public IPrototypeAppEffect
+{
+public:
+ DECLARE_CLIENTCLASS();
+ DECLARE_CLASS( C_SteamJet, C_BaseParticleEntity );
+
+ C_SteamJet();
+ ~C_SteamJet();
+
+ class SteamJetParticle : public Particle
+ {
+ public:
+ Vector m_Velocity;
+ float m_flRoll;
+ float m_flRollDelta;
+ float m_Lifetime;
+ float m_DieTime;
+ unsigned char m_uchStartSize;
+ unsigned char m_uchEndSize;
+ };
+
+ int IsEmissive( void ) { return ( m_spawnflags & SF_EMISSIVE ); }
+
+//C_BaseEntity
+public:
+
+ virtual void OnDataChanged( DataUpdateType_t updateType );
+
+
+//IPrototypeAppEffect
+public:
+ virtual void Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs);
+ virtual bool GetPropEditInfo(RecvTable **ppTable, void **ppObj);
+
+
+//IParticleEffect
+public:
+ virtual void Update(float fTimeDelta);
+ virtual void RenderParticles( CParticleRenderIterator *pIterator );
+ virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
+
+
+//Stuff from the datatable
+public:
+
+ float m_SpreadSpeed;
+ float m_Speed;
+ float m_StartSize;
+ float m_EndSize;
+ float m_Rate;
+ float m_JetLength; // Length of the jet. Lifetime is derived from this.
+
+ int m_bEmit; // Emit particles?
+ int m_nType; // Type of particles to emit
+ bool m_bFaceLeft; // For support of legacy env_steamjet entity, which faced left instead of forward.
+
+ int m_spawnflags;
+ float m_flRollSpeed;
+
+private:
+
+ void UpdateLightingRamp();
+
+private:
+
+ // Stored the last time it updates the lighting ramp, so it can cache the values.
+ Vector m_vLastRampUpdatePos;
+ QAngle m_vLastRampUpdateAngles;
+
+ float m_Lifetime; // Calculated from m_JetLength / m_Speed;
+
+ // We sample the world to get these colors and ramp the particles.
+ Vector m_Ramps[STEAMJET_NUMRAMPS];
+
+ CParticleMgr *m_pParticleMgr;
+ PMaterialHandle m_MaterialHandle;
+ TimedEvent m_ParticleSpawn;
+
+private:
+ C_SteamJet( const C_SteamJet & );
+};
+
+
+// ------------------------------------------------------------------------- //
+// Tables.
+// ------------------------------------------------------------------------- //
+
+// Expose to the particle app.
+EXPOSE_PROTOTYPE_EFFECT(SteamJet, C_SteamJet);
+
+
+// Datatable..
+IMPLEMENT_CLIENTCLASS_DT(C_SteamJet, DT_SteamJet, CSteamJet)
+ RecvPropFloat(RECVINFO(m_SpreadSpeed), 0),
+ RecvPropFloat(RECVINFO(m_Speed), 0),
+ RecvPropFloat(RECVINFO(m_StartSize), 0),
+ RecvPropFloat(RECVINFO(m_EndSize), 0),
+ RecvPropFloat(RECVINFO(m_Rate), 0),
+ RecvPropFloat(RECVINFO(m_JetLength), 0),
+ RecvPropInt(RECVINFO(m_bEmit), 0),
+ RecvPropInt(RECVINFO(m_bFaceLeft), 0),
+ RecvPropInt(RECVINFO(m_nType), 0),
+ RecvPropInt( RECVINFO( m_spawnflags ) ),
+ RecvPropFloat(RECVINFO(m_flRollSpeed), 0 ),
+END_RECV_TABLE()
+
+// ------------------------------------------------------------------------- //
+// C_SteamJet implementation.
+// ------------------------------------------------------------------------- //
+C_SteamJet::C_SteamJet()
+{
+ m_pParticleMgr = NULL;
+ m_MaterialHandle = INVALID_MATERIAL_HANDLE;
+
+ m_SpreadSpeed = 15;
+ m_Speed = 120;
+ m_StartSize = 10;
+ m_EndSize = 25;
+ m_Rate = 26;
+ m_JetLength = 80;
+ m_bEmit = true;
+ m_bFaceLeft = false;
+ m_ParticleEffect.SetAlwaysSimulate( false ); // Don't simulate outside the PVS or frustum.
+
+ m_vLastRampUpdatePos.Init( 1e24, 1e24, 1e24 );
+ m_vLastRampUpdateAngles.Init( 1e24, 1e24, 1e24 );
+}
+
+
+C_SteamJet::~C_SteamJet()
+{
+ if(m_pParticleMgr)
+ m_pParticleMgr->RemoveEffect( &m_ParticleEffect );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Called after a data update has occured
+// Input : bnewentity -
+//-----------------------------------------------------------------------------
+void C_SteamJet::OnDataChanged(DataUpdateType_t updateType)
+{
+ C_BaseEntity::OnDataChanged(updateType);
+
+ if(updateType == DATA_UPDATE_CREATED)
+ {
+ Start(ParticleMgr(), NULL);
+ }
+
+ // Recalulate lifetime in case length or speed changed.
+ m_Lifetime = m_JetLength / m_Speed;
+ m_ParticleEffect.SetParticleCullRadius( MAX(m_StartSize, m_EndSize) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Starts the effect
+// Input : *pParticleMgr -
+// *pArgs -
+//-----------------------------------------------------------------------------
+void C_SteamJet::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
+{
+ pParticleMgr->AddEffect( &m_ParticleEffect, this );
+
+ switch(m_nType)
+ {
+ case STEAM_NORMAL:
+ default:
+ m_MaterialHandle = g_Mat_DustPuff[0];
+ break;
+
+ case STEAM_HEATWAVE:
+ m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial("sprites/heatwave");
+ break;
+ }
+
+ m_ParticleSpawn.Init(m_Rate);
+ m_Lifetime = m_JetLength / m_Speed;
+ m_pParticleMgr = pParticleMgr;
+
+ UpdateLightingRamp();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : **ppTable -
+// **ppObj -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool C_SteamJet::GetPropEditInfo( RecvTable **ppTable, void **ppObj )
+{
+ *ppTable = &REFERENCE_RECV_TABLE(DT_SteamJet);
+ *ppObj = this;
+ return true;
+}
+
+
+// This might be useful someday.
+/*
+void CalcFastApproximateRenderBoundsAABB( C_BaseEntity *pEnt, float flBloatSize, Vector *pMin, Vector *pMax )
+{
+ C_BaseEntity *pParent = pEnt->GetMoveParent();
+ if ( pParent )
+ {
+ // Get the parent's abs space world bounds.
+ CalcFastApproximateRenderBoundsAABB( pParent, 0, pMin, pMax );
+
+ // Add the maximum of our local render bounds. This is making the assumption that we can be at any
+ // point and at any angle within the parent's world space bounds.
+ Vector vAddMins, vAddMaxs;
+ pEnt->GetRenderBounds( vAddMins, vAddMaxs );
+
+ flBloatSize += MAX( vAddMins.Length(), vAddMaxs.Length() );
+ }
+ else
+ {
+ // Start out with our own render bounds. Since we don't have a parent, this won't incur any nasty
+ pEnt->GetRenderBoundsWorldspace( *pMin, *pMax );
+ }
+
+ // Bloat the box.
+ if ( flBloatSize )
+ {
+ *pMin -= Vector( flBloatSize, flBloatSize, flBloatSize );
+ *pMax += Vector( flBloatSize, flBloatSize, flBloatSize );
+ }
+}
+*/
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : fTimeDelta -
+//-----------------------------------------------------------------------------
+
+void C_SteamJet::Update(float fTimeDelta)
+{
+ if(!m_pParticleMgr)
+ {
+ assert(false);
+ return;
+ }
+
+ if( m_bEmit )
+ {
+ // Add new particles.
+ int nToEmit = 0;
+ float tempDelta = fTimeDelta;
+ while( m_ParticleSpawn.NextEvent(tempDelta) )
+ ++nToEmit;
+
+ if ( nToEmit > 0 )
+ {
+ Vector forward, right, up;
+ AngleVectors(GetAbsAngles(), &forward, &right, &up);
+
+ // Legacy env_steamjet entities faced left instead of forward.
+ if (m_bFaceLeft)
+ {
+ Vector temp = forward;
+ forward = -right;
+ right = temp;
+ }
+
+ // EVIL: Ideally, we could tell the renderer our OBB, and let it build a big box that encloses
+ // the entity with its parent so it doesn't have to setup its parent's bones here.
+ Vector vEndPoint = GetAbsOrigin() + forward * m_Speed;
+ Vector vMin, vMax;
+ VectorMin( GetAbsOrigin(), vEndPoint, vMin );
+ VectorMax( GetAbsOrigin(), vEndPoint, vMax );
+ m_ParticleEffect.SetBBox( vMin, vMax );
+
+ if ( m_ParticleEffect.WasDrawnPrevFrame() )
+ {
+ while ( nToEmit-- )
+ {
+ // Make a new particle.
+ if( SteamJetParticle *pParticle = (SteamJetParticle*) m_ParticleEffect.AddParticle( sizeof(SteamJetParticle), m_MaterialHandle ) )
+ {
+ pParticle->m_Pos = GetAbsOrigin();
+
+ pParticle->m_Velocity =
+ FRand(-m_SpreadSpeed,m_SpreadSpeed) * right +
+ FRand(-m_SpreadSpeed,m_SpreadSpeed) * up +
+ m_Speed * forward;
+
+ pParticle->m_Lifetime = 0;
+ pParticle->m_DieTime = m_Lifetime;
+
+ pParticle->m_uchStartSize = m_StartSize;
+ pParticle->m_uchEndSize = m_EndSize;
+
+ pParticle->m_flRoll = random->RandomFloat( 0, 360 );
+ pParticle->m_flRollDelta = random->RandomFloat( -m_flRollSpeed, m_flRollSpeed );
+ }
+ }
+ }
+
+ UpdateLightingRamp();
+ }
+ }
+}
+
+
+// Render a quad on the screen where you pass in color and size.
+// Normal is random and "flutters"
+inline void RenderParticle_ColorSizePerturbNormal(
+ ParticleDraw* pDraw,
+ const Vector &pos,
+ const Vector &color,
+ const float alpha,
+ const float size
+ )
+{
+ // Don't render totally transparent particles.
+ if( alpha < 0.001f )
+ return;
+
+ CMeshBuilder *pBuilder = pDraw->GetMeshBuilder();
+ if( !pBuilder )
+ return;
+
+ unsigned char ubColor[4];
+ ubColor[0] = (unsigned char)RoundFloatToInt( color.x * 254.9f );
+ ubColor[1] = (unsigned char)RoundFloatToInt( color.y * 254.9f );
+ ubColor[2] = (unsigned char)RoundFloatToInt( color.z * 254.9f );
+ ubColor[3] = (unsigned char)RoundFloatToInt( alpha * 254.9f );
+
+ Vector vNorm;
+
+ vNorm.Random( -1.0f, 1.0f );
+
+ // Add the 4 corner vertices.
+ pBuilder->Position3f( pos.x-size, pos.y-size, pos.z );
+ pBuilder->Color4ubv( ubColor );
+ pBuilder->Normal3fv( vNorm.Base() );
+ pBuilder->TexCoord2f( 0, 0, 1.0f );
+ pBuilder->AdvanceVertex();
+
+ pBuilder->Position3f( pos.x-size, pos.y+size, pos.z );
+ pBuilder->Color4ubv( ubColor );
+ pBuilder->Normal3fv( vNorm.Base() );
+ pBuilder->TexCoord2f( 0, 0, 0 );
+ pBuilder->AdvanceVertex();
+
+ pBuilder->Position3f( pos.x+size, pos.y+size, pos.z );
+ pBuilder->Color4ubv( ubColor );
+ pBuilder->Normal3fv( vNorm.Base() );
+ pBuilder->TexCoord2f( 0, 1.0f, 0 );
+ pBuilder->AdvanceVertex();
+
+ pBuilder->Position3f( pos.x+size, pos.y-size, pos.z );
+ pBuilder->Color4ubv( ubColor );
+ pBuilder->Normal3fv( vNorm.Base() );
+ pBuilder->TexCoord2f( 0, 1.0f, 1.0f );
+ pBuilder->AdvanceVertex();
+}
+
+
+void C_SteamJet::RenderParticles( CParticleRenderIterator *pIterator )
+{
+ const SteamJetParticle *pParticle = (const SteamJetParticle*)pIterator->GetFirst();
+ while ( pParticle )
+ {
+ // Render.
+ Vector tPos;
+ TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos);
+ float sortKey = tPos.z;
+
+ float lifetimeT = pParticle->m_Lifetime / (pParticle->m_DieTime + 0.001);
+ float fRamp = lifetimeT * (STEAMJET_NUMRAMPS-1);
+ int iRamp = (int)fRamp;
+ float fraction = fRamp - iRamp;
+
+ Vector vRampColor = m_Ramps[iRamp] + (m_Ramps[iRamp+1] - m_Ramps[iRamp]) * fraction;
+
+ vRampColor[0] = MIN( 1.0f, vRampColor[0] );
+ vRampColor[1] = MIN( 1.0f, vRampColor[1] );
+ vRampColor[2] = MIN( 1.0f, vRampColor[2] );
+
+ float sinLifetime = sin(pParticle->m_Lifetime * 3.14159f / pParticle->m_DieTime);
+
+ if ( m_nType == STEAM_HEATWAVE )
+ {
+ RenderParticle_ColorSizePerturbNormal(
+ pIterator->GetParticleDraw(),
+ tPos,
+ vRampColor,
+ sinLifetime * (m_clrRender->a/255.0f),
+ FLerp(m_StartSize, m_EndSize, pParticle->m_Lifetime));
+ }
+ else
+ {
+ RenderParticle_ColorSizeAngle(
+ pIterator->GetParticleDraw(),
+ tPos,
+ vRampColor,
+ sinLifetime * (m_clrRender->a/255.0f),
+ FLerp(pParticle->m_uchStartSize, pParticle->m_uchEndSize, pParticle->m_Lifetime),
+ pParticle->m_flRoll );
+ }
+
+ pParticle = (const SteamJetParticle*)pIterator->GetNext( sortKey );
+ }
+}
+
+
+void C_SteamJet::SimulateParticles( CParticleSimulateIterator *pIterator )
+{
+ //Don't simulate if we're emiting particles...
+ //This fixes the cases where looking away from a steam jet and then looking back would cause a break on the stream.
+ if ( m_ParticleEffect.WasDrawnPrevFrame() == false && m_bEmit )
+ return;
+
+ SteamJetParticle *pParticle = (SteamJetParticle*)pIterator->GetFirst();
+ while ( pParticle )
+ {
+ // Should this particle die?
+ pParticle->m_Lifetime += pIterator->GetTimeDelta();
+
+ if( pParticle->m_Lifetime > pParticle->m_DieTime )
+ {
+ pIterator->RemoveParticle( pParticle );
+ }
+ else
+ {
+ pParticle->m_flRoll += pParticle->m_flRollDelta * pIterator->GetTimeDelta();
+ pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * pIterator->GetTimeDelta();
+ }
+
+ pParticle = (SteamJetParticle*)pIterator->GetNext();
+ }
+}
+
+
+void C_SteamJet::UpdateLightingRamp()
+{
+ if( VectorsAreEqual( m_vLastRampUpdatePos, GetAbsOrigin(), 0.1 ) &&
+ QAnglesAreEqual( m_vLastRampUpdateAngles, GetAbsAngles(), 0.1 ) )
+ {
+ return;
+ }
+
+ m_vLastRampUpdatePos = GetAbsOrigin();
+ m_vLastRampUpdateAngles = GetAbsAngles();
+
+ // Sample the world lighting where we think the particles will be.
+ Vector forward, right, up;
+ AngleVectors(GetAbsAngles(), &forward, &right, &up);
+
+ // Legacy env_steamjet entities faced left instead of forward.
+ if (m_bFaceLeft)
+ {
+ Vector temp = forward;
+ forward = -right;
+ right = temp;
+ }
+
+ Vector startPos = GetAbsOrigin();
+ Vector endPos = GetAbsOrigin() + forward * (m_Speed * m_Lifetime);
+
+ for(int iRamp=0; iRamp < STEAMJET_NUMRAMPS; iRamp++)
+ {
+ float t = (float)iRamp / (STEAMJET_NUMRAMPS-1);
+ Vector vTestPos = startPos + (endPos - startPos) * t;
+
+ Vector *pRamp = &m_Ramps[iRamp];
+ *pRamp = WorldGetLightForPoint(vTestPos, false);
+
+ if ( IsEmissive() )
+ {
+ pRamp->x += (m_clrRender->r/255.0f);
+ pRamp->y += (m_clrRender->g/255.0f);
+ pRamp->z += (m_clrRender->b/255.0f);
+
+ pRamp->x = clamp( pRamp->x, 0.0f, 1.0f );
+ pRamp->y = clamp( pRamp->y, 0.0f, 1.0f );
+ pRamp->z = clamp( pRamp->z, 0.0f, 1.0f );
+ }
+ else
+ {
+ pRamp->x *= (m_clrRender->r/255.0f);
+ pRamp->y *= (m_clrRender->g/255.0f);
+ pRamp->z *= (m_clrRender->b/255.0f);
+ }
+
+ // Renormalize?
+ float maxVal = MAX(pRamp->x, MAX(pRamp->y, pRamp->z));
+ if(maxVal > 1)
+ {
+ *pRamp = *pRamp / maxVal;
+ }
+ }
+}
+
+