aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/client/hl2/c_ar2_explosion.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/hl2/c_ar2_explosion.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/hl2/c_ar2_explosion.cpp')
-rw-r--r--mp/src/game/client/hl2/c_ar2_explosion.cpp950
1 files changed, 475 insertions, 475 deletions
diff --git a/mp/src/game/client/hl2/c_ar2_explosion.cpp b/mp/src/game/client/hl2/c_ar2_explosion.cpp
index 191eb8b4..e60343e6 100644
--- a/mp/src/game/client/hl2/c_ar2_explosion.cpp
+++ b/mp/src/game/client/hl2/c_ar2_explosion.cpp
@@ -1,475 +1,475 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "particlemgr.h"
-#include "particle_prototype.h"
-#include "particle_util.h"
-#include "surfinfo.h"
-#include "baseparticleentity.h"
-#include "materialsystem/imaterialsystemhardwareconfig.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-// ------------------------------------------------------------------------- //
-// Definitions
-// ------------------------------------------------------------------------- //
-
-#define NUM_AR2_EXPLOSION_PARTICLES 70
-#define AR2_DUST_RADIUS 240 // 340
-#define AR2_DUST_LIFETIME 4
-#define AR2_DUST_LIFETIME_DELTA 6
-#define AR2_DUST_SPEED 10000
-#define AR2_DUST_STARTSIZE 8
-#define AR2_DUST_ENDSIZE 32
-#define AR2_DUST_ALPHA 0.5f
-#define AR2_DUST_FADE_IN_TIME 0.25f
-
-static Vector g_AR2DustColor1(0.35, 0.345, 0.33 );
-static Vector g_AR2DustColor2(0.75, 0.75, 0.7);
-
-
-// ------------------------------------------------------------------------- //
-// Classes
-// ------------------------------------------------------------------------- //
-
-class C_AR2Explosion : public C_BaseParticleEntity, public IPrototypeAppEffect
-{
-public:
- DECLARE_CLASS( C_AR2Explosion, C_BaseParticleEntity );
- DECLARE_CLIENTCLASS();
-
- C_AR2Explosion();
- ~C_AR2Explosion();
-
-private:
-
- class AR2ExplosionParticle : public StandardParticle_t
- {
- public:
- float m_Dist;
- Vector m_Start;
- float m_Roll;
- float m_RollSpeed;
- float m_Dwell;
- };
-
-// C_BaseEntity.
-public:
- virtual void OnDataChanged(DataUpdateType_t updateType);
-
-// IPrototypeAppEffect.
-public:
- virtual void Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs);
-
-// IParticleEffect.
-public:
- virtual void Update(float fTimeDelta);
-
- virtual void RenderParticles( CParticleRenderIterator *pIterator );
- virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
-
-
-public:
- CParticleMgr *m_pParticleMgr;
- PMaterialHandle m_MaterialHandle;
-
-private:
-
- char m_szMaterialName[255];
-
- C_AR2Explosion( const C_AR2Explosion & );
-};
-
-// Expose to the particle app.
-EXPOSE_PROTOTYPE_EFFECT(AR2Explosion, C_AR2Explosion);
-
-IMPLEMENT_CLIENTCLASS_DT(C_AR2Explosion, DT_AR2Explosion, AR2Explosion)
- RecvPropString( RECVINFO( m_szMaterialName ) ),
-END_RECV_TABLE()
-
-
-
-// ------------------------------------------------------------------------- //
-// Helpers.
-// ------------------------------------------------------------------------- //
-
-// Given a line segment from vStart to vEnd
-// and a list of convex polygons in pSurfInfos and nSurfInfos,
-// fill in the list of which polygons the segment intersects.
-// Returns the number of intersected surfaces.
-static int IntersectSegmentWithSurfInfos(
- const Vector &vStart,
- const Vector &vEnd,
- SurfInfo *pSurfInfos,
- const int nSurfInfos,
- SurfInfo ** pIntersections,
- Vector *pIntersectionPositions,
- int nMaxIntersections)
-{
- if(nMaxIntersections == 0)
- return 0;
-
- int nIntersections = 0;
- for(int i=0; i < nSurfInfos; i++)
- {
- SurfInfo *pSurf = &pSurfInfos[i];
-
- // Does it intersect the plane?
- float dot1 = pSurf->m_Plane.DistTo(vStart);
- float dot2 = pSurf->m_Plane.DistTo(vEnd);
- if((dot1 > 0) != (dot2 > 0))
- {
- float t = dot1 / (dot1 - dot2);
- Vector vIntersection = vStart + (vEnd - vStart) * t;
-
- // If the intersection is behind any edge plane, then it's not inside the polygon.
- unsigned long iEdge;
- for(iEdge=0; iEdge < pSurf->m_nVerts; iEdge++)
- {
- VPlane edgePlane;
- edgePlane.m_Normal = pSurf->m_Plane.m_Normal.Cross(pSurf->m_Verts[iEdge] - pSurf->m_Verts[(iEdge+1)%pSurf->m_nVerts]);
- VectorNormalize( edgePlane.m_Normal );
- edgePlane.m_Dist = edgePlane.m_Normal.Dot(pSurf->m_Verts[iEdge]);
-
- if(edgePlane.DistTo(vIntersection) < 0.0f)
- break;
- }
-
- if(iEdge == pSurf->m_nVerts)
- {
- pIntersections[nIntersections] = pSurf;
- pIntersectionPositions[nIntersections] = vIntersection;
- ++nIntersections;
- if(nIntersections >= nMaxIntersections)
- break;
- }
- }
- }
-
- return nIntersections;
-}
-
-
-
-// ------------------------------------------------------------------------- //
-// C_AR2Explosion
-// ------------------------------------------------------------------------- //
-C_AR2Explosion::C_AR2Explosion()
-{
- m_pParticleMgr = NULL;
- m_MaterialHandle = INVALID_MATERIAL_HANDLE;
-}
-
-
-C_AR2Explosion::~C_AR2Explosion()
-{
-}
-
-
-void C_AR2Explosion::OnDataChanged(DataUpdateType_t updateType)
-{
- C_BaseEntity::OnDataChanged(updateType);
-
- if(updateType == DATA_UPDATE_CREATED)
- {
- Start(ParticleMgr(), NULL);
- }
-}
-
-static ConVar mat_reduceparticles( "mat_reduceparticles", "0" );
-
-void C_AR2Explosion::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
-{
- m_pParticleMgr = pParticleMgr;
- if(!pParticleMgr->AddEffect(&m_ParticleEffect, this))
- return;
-
- if (!m_szMaterialName[0])
- {
- Q_strncpy(m_szMaterialName, "particle/particle_noisesphere", sizeof( m_szMaterialName ) );
- }
-
- m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial(m_szMaterialName);
-
- // Precalculate stuff for the particle spawning..
- #define NUM_DUSTEMITTER_SURFINFOS 128
- SurfInfo surfInfos[NUM_DUSTEMITTER_SURFINFOS];
- int nSurfInfos;
-
- // Center of explosion.
- Vector vCenter = GetAbsOrigin(); // HACKHACK.. when the engine bug is fixed, use origin.
-
- if ( IsXbox() )
- {
- m_ParticleEffect.SetBBox( vCenter-Vector(300,300,300), vCenter+Vector(300,300,300) );
- }
-
- #ifdef PARTICLEPROTOTYPE_APP
- float surfSize = 10000;
- nSurfInfos = 1;
- surfInfos[0].m_Verts[0].Init(-surfSize,-surfSize,0);
- surfInfos[0].m_Verts[1].Init(-surfSize,surfSize,0);
- surfInfos[0].m_Verts[2].Init(surfSize, surfSize,0);
- surfInfos[0].m_Verts[3].Init(surfSize,-surfSize,0);
- surfInfos[0].m_nVerts = 4;
- surfInfos[0].m_Plane.m_Normal.Init(0,0,1);
- surfInfos[0].m_Plane.m_Dist = -3;
- #else
- {
- nSurfInfos = 0;
- C_BaseEntity *ent = cl_entitylist->GetEnt( 0 );
- if ( ent )
- {
- nSurfInfos = engine->GetIntersectingSurfaces(
- ent->GetModel(),
- vCenter,
- AR2_DUST_RADIUS,
- true,
- surfInfos,
- NUM_DUSTEMITTER_SURFINFOS);
- }
- }
- #endif
-
- int nParticles = 0;
-
- int iParticlesToSpawn = NUM_AR2_EXPLOSION_PARTICLES;
-
- // In DX7, much fewer particles
- if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 )
- {
- iParticlesToSpawn *= 0.25;
- }
- else if ( mat_reduceparticles.GetBool() )
- {
- iParticlesToSpawn *= 0.025;
- }
-
- if( nSurfInfos > 0 )
- {
- // For nParticles*N, generate a ray and cast it out. If it hits anything, spawn a particle there.
- int nTestsPerParticle=3;
- for(int i=0; i < iParticlesToSpawn; i++)
- {
- for(int iTest=0; iTest < nTestsPerParticle; iTest++)
- {
- Vector randVec = RandomVector(-1,1);
- VectorNormalize( randVec );
- Vector startPos = vCenter + randVec * AR2_DUST_RADIUS;
-
- randVec = RandomVector(-1,1);
- VectorNormalize( randVec );
- Vector endPos = vCenter + randVec * AR2_DUST_RADIUS;
-
- #define MAX_SURFINFO_INTERSECTIONS 4
- SurfInfo *pIntersected[MAX_SURFINFO_INTERSECTIONS];
- Vector vIntersections[MAX_SURFINFO_INTERSECTIONS];
- int nIntersections;
- nIntersections = IntersectSegmentWithSurfInfos(
- startPos,
- endPos,
- surfInfos,
- nSurfInfos,
- pIntersected,
- vIntersections,
- MAX_SURFINFO_INTERSECTIONS);
-
- if(nIntersections)
- {
- int iIntersection = rand() % nIntersections;
-
- Vector velocity;
- //velocity.Init(-1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f, -1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f, -1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f);
- //velocity = velocity * FRand(m_MinSpeed, m_MaxSpeed);
- Vector direction = (vIntersections[iIntersection] - vCenter );
- float dist = VectorNormalize( direction );
- if(dist > AR2_DUST_RADIUS)
- dist = AR2_DUST_RADIUS;
-
- static float power = 2.0f;
- float falloffMul = pow(1.0f - dist / AR2_DUST_RADIUS, power);
-
- Vector reflection = direction - 2 * DotProduct( direction, pIntersected[iIntersection]->m_Plane.m_Normal ) * pIntersected[iIntersection]->m_Plane.m_Normal;
- VectorNormalize( reflection );
-
- velocity = reflection * AR2_DUST_SPEED * falloffMul;
- // velocity = velocity + (vIntersections[iIntersection] - vCenter) * falloffMul;
-
-
- /*
- debugoverlay->AddLineOverlay( vIntersections[iIntersection],
- vIntersections[iIntersection] + reflection * 64,
- 128, 128, 255, false, 15.0 );
- */
-#if 1
- AR2ExplosionParticle *pParticle =
- (AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );
-
- if(pParticle)
- {
- pParticle->m_Pos = vIntersections[iIntersection];
- pParticle->m_Start = pParticle->m_Pos;
- pParticle->m_Dist = 8.0;
- pParticle->m_Velocity = velocity;
- // sound == 13031.496062992125984251968503937ips
- pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
- pParticle->m_Roll = FRand( 0, M_PI * 2 );
- pParticle->m_RollSpeed = FRand( -1, 1 ) * 0.4;
- pParticle->m_Dwell = AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA );
- nParticles++;
- break;
- }
-#endif
- }
- }
- }
- }
-
- // build interior smoke particles
- for(int i=nParticles; i < iParticlesToSpawn; i++)
- {
- Vector randVec = RandomVector(-1,1);
- VectorNormalize( randVec );
- Vector endPos = vCenter + randVec * AR2_DUST_RADIUS / 4.0;
-
- Vector direction = (endPos - vCenter );
- float dist = VectorNormalize( direction ) + random->RandomFloat( 0, AR2_DUST_RADIUS / 4.0 );
- if(dist > AR2_DUST_RADIUS)
- dist = AR2_DUST_RADIUS;
-
- static float power = 2.0f;
- float falloffMul = pow(1.0f - dist / (AR2_DUST_RADIUS / 2), power);
-
- Vector velocity = direction * AR2_DUST_SPEED * falloffMul;
- AR2ExplosionParticle *pParticle =
- (AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );
-
- if(pParticle)
- {
- pParticle->m_Pos = endPos;
- pParticle->m_Start = pParticle->m_Pos;
- pParticle->m_Dist = 8.0;
- pParticle->m_Velocity = velocity;
- // sound == 13031.496062992125984251968503937ips
- pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
- pParticle->m_Roll = FRand( 0, M_PI * 2 );
- pParticle->m_RollSpeed = FRand( -1, 1 ) * 4.0;
- pParticle->m_Dwell = 0.5 * (AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA ));
- }
- }
-}
-
-
-void C_AR2Explosion::Update(float fTimeDelta)
-{
- if(!m_pParticleMgr)
- return;
-}
-
-
-void C_AR2Explosion::SimulateParticles( CParticleSimulateIterator *pIterator )
-{
- float dt = pIterator->GetTimeDelta();
-
- AR2ExplosionParticle *pParticle = (AR2ExplosionParticle*)pIterator->GetFirst();
- while ( pParticle )
- {
- if (dt > 0.05)
- dt = 0.05; // yuck, air resistance function craps out at less then 20fps
-
- // Update its lifetime.
- pParticle->m_Lifetime += dt; // pDraw->GetTimeDelta();
- if(pParticle->m_Lifetime > pParticle->m_Dwell)
- {
- // faded to nothing....
- pIterator->RemoveParticle( pParticle );
- }
- else
- {
- // Spin the thing
- pParticle->m_Roll += pParticle->m_RollSpeed * pIterator->GetTimeDelta();
-
- // delayed?
- if ( pParticle->m_Lifetime >= 0.0f )
- {
- // Move it (this comes after rendering to make it clear that moving the particle here won't change
- // its rendering for this frame since m_TransformedPos has already been set).
- pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * dt;
-
- // keep track of distance traveled
- pParticle->m_Dist = pParticle->m_Dist + pParticle->m_Velocity.Length() * dt;
-
- // Dampen velocity.
- float dist = pParticle->m_Velocity.Length() * dt;
- float r = dist * dist;
- // FIXME: this is a really screwy air-resistance function....
- pParticle->m_Velocity = pParticle->m_Velocity * (100 / (100 + r ));
-
- // dampen roll
- static float dtime;
- static float decay;
- if (dtime != dt)
- {
- dtime = dt;
- decay = ExponentialDecay( 0.3, 1.0, dtime );
- }
- if (fabs(pParticle->m_RollSpeed) > 0.2)
- pParticle->m_RollSpeed = pParticle->m_RollSpeed * decay;
- }
- }
-
- pParticle = (AR2ExplosionParticle*)pIterator->GetNext();
- }
-}
-
-
-void C_AR2Explosion::RenderParticles( CParticleRenderIterator *pIterator )
-{
- const AR2ExplosionParticle *pParticle = (const AR2ExplosionParticle *)pIterator->GetFirst();
- while ( pParticle )
- {
- float sortKey = 0;
- if ( pParticle->m_Lifetime >= 0.0f )
- {
- // Draw.
- float lifetimePercent = ( pParticle->m_Lifetime - AR2_DUST_FADE_IN_TIME ) / pParticle->m_Dwell;
-
- // FIXME: base color should be a dirty version of the material color
- Vector color = g_AR2DustColor1 * (1.0 - lifetimePercent) + g_AR2DustColor2 * lifetimePercent;
-
- Vector tPos;
- TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos);
- sortKey = tPos.z;
-
- float alpha;
-
- if ( pParticle->m_Lifetime < AR2_DUST_FADE_IN_TIME )
- {
- alpha = AR2_DUST_ALPHA * ( pParticle->m_Lifetime / AR2_DUST_FADE_IN_TIME );
- }
- else
- {
- alpha = AR2_DUST_ALPHA * ( 1.0f - lifetimePercent );
- }
-
- alpha *= GetAlphaDistanceFade( tPos, IsXbox() ? 100 : 50, IsXbox() ? 200 : 150 );
-
- RenderParticle_ColorSizeAngle(
- pIterator->GetParticleDraw(),
- tPos,
- color,
- alpha,
- pParticle->m_Dist, // size based on how far it's traveled
- pParticle->m_Roll);
- }
-
- pParticle = (const AR2ExplosionParticle *)pIterator->GetNext( sortKey );
- }
-}
-
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "particlemgr.h"
+#include "particle_prototype.h"
+#include "particle_util.h"
+#include "surfinfo.h"
+#include "baseparticleentity.h"
+#include "materialsystem/imaterialsystemhardwareconfig.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+// ------------------------------------------------------------------------- //
+// Definitions
+// ------------------------------------------------------------------------- //
+
+#define NUM_AR2_EXPLOSION_PARTICLES 70
+#define AR2_DUST_RADIUS 240 // 340
+#define AR2_DUST_LIFETIME 4
+#define AR2_DUST_LIFETIME_DELTA 6
+#define AR2_DUST_SPEED 10000
+#define AR2_DUST_STARTSIZE 8
+#define AR2_DUST_ENDSIZE 32
+#define AR2_DUST_ALPHA 0.5f
+#define AR2_DUST_FADE_IN_TIME 0.25f
+
+static Vector g_AR2DustColor1(0.35, 0.345, 0.33 );
+static Vector g_AR2DustColor2(0.75, 0.75, 0.7);
+
+
+// ------------------------------------------------------------------------- //
+// Classes
+// ------------------------------------------------------------------------- //
+
+class C_AR2Explosion : public C_BaseParticleEntity, public IPrototypeAppEffect
+{
+public:
+ DECLARE_CLASS( C_AR2Explosion, C_BaseParticleEntity );
+ DECLARE_CLIENTCLASS();
+
+ C_AR2Explosion();
+ ~C_AR2Explosion();
+
+private:
+
+ class AR2ExplosionParticle : public StandardParticle_t
+ {
+ public:
+ float m_Dist;
+ Vector m_Start;
+ float m_Roll;
+ float m_RollSpeed;
+ float m_Dwell;
+ };
+
+// C_BaseEntity.
+public:
+ virtual void OnDataChanged(DataUpdateType_t updateType);
+
+// IPrototypeAppEffect.
+public:
+ virtual void Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs);
+
+// IParticleEffect.
+public:
+ virtual void Update(float fTimeDelta);
+
+ virtual void RenderParticles( CParticleRenderIterator *pIterator );
+ virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
+
+
+public:
+ CParticleMgr *m_pParticleMgr;
+ PMaterialHandle m_MaterialHandle;
+
+private:
+
+ char m_szMaterialName[255];
+
+ C_AR2Explosion( const C_AR2Explosion & );
+};
+
+// Expose to the particle app.
+EXPOSE_PROTOTYPE_EFFECT(AR2Explosion, C_AR2Explosion);
+
+IMPLEMENT_CLIENTCLASS_DT(C_AR2Explosion, DT_AR2Explosion, AR2Explosion)
+ RecvPropString( RECVINFO( m_szMaterialName ) ),
+END_RECV_TABLE()
+
+
+
+// ------------------------------------------------------------------------- //
+// Helpers.
+// ------------------------------------------------------------------------- //
+
+// Given a line segment from vStart to vEnd
+// and a list of convex polygons in pSurfInfos and nSurfInfos,
+// fill in the list of which polygons the segment intersects.
+// Returns the number of intersected surfaces.
+static int IntersectSegmentWithSurfInfos(
+ const Vector &vStart,
+ const Vector &vEnd,
+ SurfInfo *pSurfInfos,
+ const int nSurfInfos,
+ SurfInfo ** pIntersections,
+ Vector *pIntersectionPositions,
+ int nMaxIntersections)
+{
+ if(nMaxIntersections == 0)
+ return 0;
+
+ int nIntersections = 0;
+ for(int i=0; i < nSurfInfos; i++)
+ {
+ SurfInfo *pSurf = &pSurfInfos[i];
+
+ // Does it intersect the plane?
+ float dot1 = pSurf->m_Plane.DistTo(vStart);
+ float dot2 = pSurf->m_Plane.DistTo(vEnd);
+ if((dot1 > 0) != (dot2 > 0))
+ {
+ float t = dot1 / (dot1 - dot2);
+ Vector vIntersection = vStart + (vEnd - vStart) * t;
+
+ // If the intersection is behind any edge plane, then it's not inside the polygon.
+ unsigned long iEdge;
+ for(iEdge=0; iEdge < pSurf->m_nVerts; iEdge++)
+ {
+ VPlane edgePlane;
+ edgePlane.m_Normal = pSurf->m_Plane.m_Normal.Cross(pSurf->m_Verts[iEdge] - pSurf->m_Verts[(iEdge+1)%pSurf->m_nVerts]);
+ VectorNormalize( edgePlane.m_Normal );
+ edgePlane.m_Dist = edgePlane.m_Normal.Dot(pSurf->m_Verts[iEdge]);
+
+ if(edgePlane.DistTo(vIntersection) < 0.0f)
+ break;
+ }
+
+ if(iEdge == pSurf->m_nVerts)
+ {
+ pIntersections[nIntersections] = pSurf;
+ pIntersectionPositions[nIntersections] = vIntersection;
+ ++nIntersections;
+ if(nIntersections >= nMaxIntersections)
+ break;
+ }
+ }
+ }
+
+ return nIntersections;
+}
+
+
+
+// ------------------------------------------------------------------------- //
+// C_AR2Explosion
+// ------------------------------------------------------------------------- //
+C_AR2Explosion::C_AR2Explosion()
+{
+ m_pParticleMgr = NULL;
+ m_MaterialHandle = INVALID_MATERIAL_HANDLE;
+}
+
+
+C_AR2Explosion::~C_AR2Explosion()
+{
+}
+
+
+void C_AR2Explosion::OnDataChanged(DataUpdateType_t updateType)
+{
+ C_BaseEntity::OnDataChanged(updateType);
+
+ if(updateType == DATA_UPDATE_CREATED)
+ {
+ Start(ParticleMgr(), NULL);
+ }
+}
+
+static ConVar mat_reduceparticles( "mat_reduceparticles", "0" );
+
+void C_AR2Explosion::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
+{
+ m_pParticleMgr = pParticleMgr;
+ if(!pParticleMgr->AddEffect(&m_ParticleEffect, this))
+ return;
+
+ if (!m_szMaterialName[0])
+ {
+ Q_strncpy(m_szMaterialName, "particle/particle_noisesphere", sizeof( m_szMaterialName ) );
+ }
+
+ m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial(m_szMaterialName);
+
+ // Precalculate stuff for the particle spawning..
+ #define NUM_DUSTEMITTER_SURFINFOS 128
+ SurfInfo surfInfos[NUM_DUSTEMITTER_SURFINFOS];
+ int nSurfInfos;
+
+ // Center of explosion.
+ Vector vCenter = GetAbsOrigin(); // HACKHACK.. when the engine bug is fixed, use origin.
+
+ if ( IsXbox() )
+ {
+ m_ParticleEffect.SetBBox( vCenter-Vector(300,300,300), vCenter+Vector(300,300,300) );
+ }
+
+ #ifdef PARTICLEPROTOTYPE_APP
+ float surfSize = 10000;
+ nSurfInfos = 1;
+ surfInfos[0].m_Verts[0].Init(-surfSize,-surfSize,0);
+ surfInfos[0].m_Verts[1].Init(-surfSize,surfSize,0);
+ surfInfos[0].m_Verts[2].Init(surfSize, surfSize,0);
+ surfInfos[0].m_Verts[3].Init(surfSize,-surfSize,0);
+ surfInfos[0].m_nVerts = 4;
+ surfInfos[0].m_Plane.m_Normal.Init(0,0,1);
+ surfInfos[0].m_Plane.m_Dist = -3;
+ #else
+ {
+ nSurfInfos = 0;
+ C_BaseEntity *ent = cl_entitylist->GetEnt( 0 );
+ if ( ent )
+ {
+ nSurfInfos = engine->GetIntersectingSurfaces(
+ ent->GetModel(),
+ vCenter,
+ AR2_DUST_RADIUS,
+ true,
+ surfInfos,
+ NUM_DUSTEMITTER_SURFINFOS);
+ }
+ }
+ #endif
+
+ int nParticles = 0;
+
+ int iParticlesToSpawn = NUM_AR2_EXPLOSION_PARTICLES;
+
+ // In DX7, much fewer particles
+ if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 )
+ {
+ iParticlesToSpawn *= 0.25;
+ }
+ else if ( mat_reduceparticles.GetBool() )
+ {
+ iParticlesToSpawn *= 0.025;
+ }
+
+ if( nSurfInfos > 0 )
+ {
+ // For nParticles*N, generate a ray and cast it out. If it hits anything, spawn a particle there.
+ int nTestsPerParticle=3;
+ for(int i=0; i < iParticlesToSpawn; i++)
+ {
+ for(int iTest=0; iTest < nTestsPerParticle; iTest++)
+ {
+ Vector randVec = RandomVector(-1,1);
+ VectorNormalize( randVec );
+ Vector startPos = vCenter + randVec * AR2_DUST_RADIUS;
+
+ randVec = RandomVector(-1,1);
+ VectorNormalize( randVec );
+ Vector endPos = vCenter + randVec * AR2_DUST_RADIUS;
+
+ #define MAX_SURFINFO_INTERSECTIONS 4
+ SurfInfo *pIntersected[MAX_SURFINFO_INTERSECTIONS];
+ Vector vIntersections[MAX_SURFINFO_INTERSECTIONS];
+ int nIntersections;
+ nIntersections = IntersectSegmentWithSurfInfos(
+ startPos,
+ endPos,
+ surfInfos,
+ nSurfInfos,
+ pIntersected,
+ vIntersections,
+ MAX_SURFINFO_INTERSECTIONS);
+
+ if(nIntersections)
+ {
+ int iIntersection = rand() % nIntersections;
+
+ Vector velocity;
+ //velocity.Init(-1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f, -1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f, -1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f);
+ //velocity = velocity * FRand(m_MinSpeed, m_MaxSpeed);
+ Vector direction = (vIntersections[iIntersection] - vCenter );
+ float dist = VectorNormalize( direction );
+ if(dist > AR2_DUST_RADIUS)
+ dist = AR2_DUST_RADIUS;
+
+ static float power = 2.0f;
+ float falloffMul = pow(1.0f - dist / AR2_DUST_RADIUS, power);
+
+ Vector reflection = direction - 2 * DotProduct( direction, pIntersected[iIntersection]->m_Plane.m_Normal ) * pIntersected[iIntersection]->m_Plane.m_Normal;
+ VectorNormalize( reflection );
+
+ velocity = reflection * AR2_DUST_SPEED * falloffMul;
+ // velocity = velocity + (vIntersections[iIntersection] - vCenter) * falloffMul;
+
+
+ /*
+ debugoverlay->AddLineOverlay( vIntersections[iIntersection],
+ vIntersections[iIntersection] + reflection * 64,
+ 128, 128, 255, false, 15.0 );
+ */
+#if 1
+ AR2ExplosionParticle *pParticle =
+ (AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );
+
+ if(pParticle)
+ {
+ pParticle->m_Pos = vIntersections[iIntersection];
+ pParticle->m_Start = pParticle->m_Pos;
+ pParticle->m_Dist = 8.0;
+ pParticle->m_Velocity = velocity;
+ // sound == 13031.496062992125984251968503937ips
+ pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
+ pParticle->m_Roll = FRand( 0, M_PI * 2 );
+ pParticle->m_RollSpeed = FRand( -1, 1 ) * 0.4;
+ pParticle->m_Dwell = AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA );
+ nParticles++;
+ break;
+ }
+#endif
+ }
+ }
+ }
+ }
+
+ // build interior smoke particles
+ for(int i=nParticles; i < iParticlesToSpawn; i++)
+ {
+ Vector randVec = RandomVector(-1,1);
+ VectorNormalize( randVec );
+ Vector endPos = vCenter + randVec * AR2_DUST_RADIUS / 4.0;
+
+ Vector direction = (endPos - vCenter );
+ float dist = VectorNormalize( direction ) + random->RandomFloat( 0, AR2_DUST_RADIUS / 4.0 );
+ if(dist > AR2_DUST_RADIUS)
+ dist = AR2_DUST_RADIUS;
+
+ static float power = 2.0f;
+ float falloffMul = pow(1.0f - dist / (AR2_DUST_RADIUS / 2), power);
+
+ Vector velocity = direction * AR2_DUST_SPEED * falloffMul;
+ AR2ExplosionParticle *pParticle =
+ (AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );
+
+ if(pParticle)
+ {
+ pParticle->m_Pos = endPos;
+ pParticle->m_Start = pParticle->m_Pos;
+ pParticle->m_Dist = 8.0;
+ pParticle->m_Velocity = velocity;
+ // sound == 13031.496062992125984251968503937ips
+ pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
+ pParticle->m_Roll = FRand( 0, M_PI * 2 );
+ pParticle->m_RollSpeed = FRand( -1, 1 ) * 4.0;
+ pParticle->m_Dwell = 0.5 * (AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA ));
+ }
+ }
+}
+
+
+void C_AR2Explosion::Update(float fTimeDelta)
+{
+ if(!m_pParticleMgr)
+ return;
+}
+
+
+void C_AR2Explosion::SimulateParticles( CParticleSimulateIterator *pIterator )
+{
+ float dt = pIterator->GetTimeDelta();
+
+ AR2ExplosionParticle *pParticle = (AR2ExplosionParticle*)pIterator->GetFirst();
+ while ( pParticle )
+ {
+ if (dt > 0.05)
+ dt = 0.05; // yuck, air resistance function craps out at less then 20fps
+
+ // Update its lifetime.
+ pParticle->m_Lifetime += dt; // pDraw->GetTimeDelta();
+ if(pParticle->m_Lifetime > pParticle->m_Dwell)
+ {
+ // faded to nothing....
+ pIterator->RemoveParticle( pParticle );
+ }
+ else
+ {
+ // Spin the thing
+ pParticle->m_Roll += pParticle->m_RollSpeed * pIterator->GetTimeDelta();
+
+ // delayed?
+ if ( pParticle->m_Lifetime >= 0.0f )
+ {
+ // Move it (this comes after rendering to make it clear that moving the particle here won't change
+ // its rendering for this frame since m_TransformedPos has already been set).
+ pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * dt;
+
+ // keep track of distance traveled
+ pParticle->m_Dist = pParticle->m_Dist + pParticle->m_Velocity.Length() * dt;
+
+ // Dampen velocity.
+ float dist = pParticle->m_Velocity.Length() * dt;
+ float r = dist * dist;
+ // FIXME: this is a really screwy air-resistance function....
+ pParticle->m_Velocity = pParticle->m_Velocity * (100 / (100 + r ));
+
+ // dampen roll
+ static float dtime;
+ static float decay;
+ if (dtime != dt)
+ {
+ dtime = dt;
+ decay = ExponentialDecay( 0.3, 1.0, dtime );
+ }
+ if (fabs(pParticle->m_RollSpeed) > 0.2)
+ pParticle->m_RollSpeed = pParticle->m_RollSpeed * decay;
+ }
+ }
+
+ pParticle = (AR2ExplosionParticle*)pIterator->GetNext();
+ }
+}
+
+
+void C_AR2Explosion::RenderParticles( CParticleRenderIterator *pIterator )
+{
+ const AR2ExplosionParticle *pParticle = (const AR2ExplosionParticle *)pIterator->GetFirst();
+ while ( pParticle )
+ {
+ float sortKey = 0;
+ if ( pParticle->m_Lifetime >= 0.0f )
+ {
+ // Draw.
+ float lifetimePercent = ( pParticle->m_Lifetime - AR2_DUST_FADE_IN_TIME ) / pParticle->m_Dwell;
+
+ // FIXME: base color should be a dirty version of the material color
+ Vector color = g_AR2DustColor1 * (1.0 - lifetimePercent) + g_AR2DustColor2 * lifetimePercent;
+
+ Vector tPos;
+ TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos);
+ sortKey = tPos.z;
+
+ float alpha;
+
+ if ( pParticle->m_Lifetime < AR2_DUST_FADE_IN_TIME )
+ {
+ alpha = AR2_DUST_ALPHA * ( pParticle->m_Lifetime / AR2_DUST_FADE_IN_TIME );
+ }
+ else
+ {
+ alpha = AR2_DUST_ALPHA * ( 1.0f - lifetimePercent );
+ }
+
+ alpha *= GetAlphaDistanceFade( tPos, IsXbox() ? 100 : 50, IsXbox() ? 200 : 150 );
+
+ RenderParticle_ColorSizeAngle(
+ pIterator->GetParticleDraw(),
+ tPos,
+ color,
+ alpha,
+ pParticle->m_Dist, // size based on how far it's traveled
+ pParticle->m_Roll);
+ }
+
+ pParticle = (const AR2ExplosionParticle *)pIterator->GetNext( sortKey );
+ }
+}
+
+