diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf2/c_env_meteor.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/tf2/c_env_meteor.cpp')
| -rw-r--r-- | game/client/tf2/c_env_meteor.cpp | 651 |
1 files changed, 651 insertions, 0 deletions
diff --git a/game/client/tf2/c_env_meteor.cpp b/game/client/tf2/c_env_meteor.cpp new file mode 100644 index 0000000..e2ccf53 --- /dev/null +++ b/game/client/tf2/c_env_meteor.cpp @@ -0,0 +1,651 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "C_Env_Meteor.h" +#include "fx_explosion.h" +#include "tempentity.h" +#include "c_tracer.h" + +//============================================================================= +// +// Meteor Factory Functions +// + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_MeteorFactory::CreateMeteor( int nID, int iType, + const Vector &vecPosition, const Vector &vecDirection, + float flSpeed, float flStartTime, float flDamageRadius, + const Vector &vecTriggerMins, const Vector &vecTriggerMaxs ) +{ + C_EnvMeteor::Create( nID, iType, vecPosition, vecDirection, flSpeed, flStartTime, flDamageRadius, + vecTriggerMins, vecTriggerMaxs ); +} + + +//============================================================================= +// +// Meteor Spawner Functions +// + +void RecvProxy_MeteorTargetPositions( const CRecvProxyData *pData, void *pStruct, void *pOut ) +{ + CEnvMeteorSpawnerShared *pSpawner = ( CEnvMeteorSpawnerShared* )pStruct; + pSpawner->m_aTargets[pData->m_iElement].m_vecPosition.x = pData->m_Value.m_Vector[0]; + pSpawner->m_aTargets[pData->m_iElement].m_vecPosition.y = pData->m_Value.m_Vector[1]; + pSpawner->m_aTargets[pData->m_iElement].m_vecPosition.z = pData->m_Value.m_Vector[2]; +} + +void RecvProxy_MeteorTargetRadii( const CRecvProxyData *pData, void *pStruct, void *pOut ) +{ + CEnvMeteorSpawnerShared *pSpawner = ( CEnvMeteorSpawnerShared* )pStruct; + pSpawner->m_aTargets[pData->m_iElement].m_flRadius = pData->m_Value.m_Float; +} + +void RecvProxyArrayLength_MeteorTargets( void *pStruct, int objectID, int currentArrayLength ) +{ + CEnvMeteorSpawnerShared *pSpawner = ( CEnvMeteorSpawnerShared* )pStruct; + if ( pSpawner->m_aTargets.Count() < currentArrayLength ) + { + pSpawner->m_aTargets.SetSize( currentArrayLength ); + } +} + + +BEGIN_RECV_TABLE_NOBASE( CEnvMeteorSpawnerShared, DT_EnvMeteorSpawnerShared ) + // Setup (read from) Worldcraft. + RecvPropInt ( RECVINFO( m_iMeteorType ) ), + RecvPropInt ( RECVINFO( m_bSkybox ) ), + RecvPropFloat ( RECVINFO( m_flMinSpawnTime ) ), + RecvPropFloat ( RECVINFO( m_flMaxSpawnTime ) ), + RecvPropInt ( RECVINFO( m_nMinSpawnCount ) ), + RecvPropInt ( RECVINFO( m_nMaxSpawnCount ) ), + RecvPropFloat ( RECVINFO( m_flMinSpeed ) ), + RecvPropFloat ( RECVINFO( m_flMaxSpeed ) ), + + // Setup through Init. + RecvPropFloat ( RECVINFO( m_flStartTime ) ), + RecvPropInt ( RECVINFO( m_nRandomSeed ) ), + RecvPropVector ( RECVINFO( m_vecMinBounds ) ), + RecvPropVector ( RECVINFO( m_vecMaxBounds ) ), + RecvPropVector ( RECVINFO( m_vecTriggerMins ) ), + RecvPropVector ( RECVINFO( m_vecTriggerMaxs ) ), + + // Target List + RecvPropArray2( RecvProxyArrayLength_MeteorTargets, + RecvPropVector( "meteortargetposition_array_element", 0, 0, 0, RecvProxy_MeteorTargetPositions ), + 16, 0, "meteortargetposition_array" ), + + RecvPropArray2( RecvProxyArrayLength_MeteorTargets, + RecvPropFloat( "meteortargetradius_array_element", 0, 0, 0, RecvProxy_MeteorTargetRadii ), + 16, 0, "meteortargetradius_array" ) +END_RECV_TABLE() + +// This table encodes the CBaseEntity data. +IMPLEMENT_CLIENTCLASS_DT( C_EnvMeteorSpawner, DT_EnvMeteorSpawner, CEnvMeteorSpawner ) + RecvPropDataTable ( RECVINFO_DT( m_SpawnerShared ), 0, &REFERENCE_RECV_TABLE( DT_EnvMeteorSpawnerShared ) ), + RecvPropInt ( RECVINFO( m_fDisabled ) ), +END_RECV_TABLE() + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +C_EnvMeteorSpawner::C_EnvMeteorSpawner() +{ +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteorSpawner::OnDataChanged( DataUpdateType_t updateType ) +{ + // Initialize the client side spawner. + m_SpawnerShared.Init( &m_Factory, m_SpawnerShared.m_nRandomSeed, m_SpawnerShared.m_flStartTime, + m_SpawnerShared.m_vecMinBounds, m_SpawnerShared.m_vecMaxBounds, + m_SpawnerShared.m_vecTriggerMins, m_SpawnerShared.m_vecTriggerMaxs ); + + // Set the next think to be the next spawn interval. + if ( !m_fDisabled ) + { + SetNextClientThink( m_SpawnerShared.m_flNextSpawnTime ); + } +} + +#if 0 +// Will probably be used later!! +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteorSpawner::ReceiveMessage( int classID, bf_read &msg ) +{ + if ( classID != GetClientClass()->m_ClassID ) + { + // message is for subclass + BaseClass::ReceiveMessage( classID, msg ); + return; + } + + m_SpawnerShared.m_flStartTime = msg.ReadLong(); + m_SpawnerShared.m_flNextSpawnTime = msg.ReadLong(); + SetNextClientThink( m_SpawnerShared.m_flNextSpawnTime ); +} +#endif + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteorSpawner::ClientThink( void ) +{ + SetNextClientThink( m_SpawnerShared.MeteorThink( gpGlobals->curtime ) ); +} + +//============================================================================= +// +// Meteor Tail Functions +// + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +C_EnvMeteorHead::C_EnvMeteorHead() +{ + m_vecPos.Init(); + m_vecPrevPos.Init(); + + m_flParticleScale = 1.0f; + + m_pSmokeEmitter = NULL; + m_flSmokeSpawnInterval = 0.0f; + m_hSmokeMaterial = INVALID_MATERIAL_HANDLE; + m_flSmokeLifetime = 2.5f; + m_bEmitSmoke = true; + + m_hFlareMaterial = INVALID_MATERIAL_HANDLE; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +C_EnvMeteorHead::~C_EnvMeteorHead() +{ + Destroy(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteorHead::Start( const Vector &vecOrigin, const Vector &vecDirection ) +{ + // Emitters. + m_pSmokeEmitter = CSimpleEmitter::Create( "MeteorTrail" ); +// m_pFireEmitter = CSimpleEmitter::Create( "MeteorFire" ); + if ( !m_pSmokeEmitter /*|| !m_pFireEmitter*/ ) + return; + + // Smoke + m_pSmokeEmitter->SetSortOrigin( vecOrigin ); + m_hSmokeMaterial = m_pSmokeEmitter->GetPMaterial( "particle/SmokeStack" ); + Assert( m_hSmokeMaterial != INVALID_MATERIAL_HANDLE ); + + // Fire +// m_pFireEmitter->SetSortOrigin( vecOrigin ); +// m_hFireMaterial = m_pFireEmitter->GetPMaterial( "particle/particle_fire" ); +// Assert( m_hFireMaterial != INVALID_MATERIAL_HANDLE ); + + // Flare +// m_hFlareMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/redflare" ); + + VectorCopy( vecDirection, m_vecDirection ); + VectorCopy( vecOrigin, m_vecPos ); + + m_bInitThink = true; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteorHead::Destroy( void ) +{ + m_pSmokeEmitter = NULL; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteorHead::MeteorHeadThink( const Vector &vecOrigin, float flTime ) +{ + if ( m_bInitThink ) + { + VectorCopy( vecOrigin, m_vecPrevPos ); + m_bInitThink = false; + } + + // Update the position of the emitters. + VectorCopy( vecOrigin, m_vecPos ); + + // Update Smoke + if ( m_pSmokeEmitter.IsValid() && m_bEmitSmoke ) + { + m_pSmokeEmitter->SetSortOrigin( m_vecPos ); + + // Get distance covered + Vector vecDelta; + VectorSubtract( m_vecPos, m_vecPrevPos, vecDelta ); + float flLength = vecDelta.Length(); + + int nParticleCount = flLength / 35.0f; + if ( nParticleCount < 1 ) + { + nParticleCount = 1; + } + + flLength /= nParticleCount; + + Vector vecPos; + for( int iParticle = 0; iParticle < nParticleCount; ++iParticle ) + { + vecPos = m_vecPrevPos + ( m_vecDirection * ( flLength * iParticle ) ); + + // Add some noise to the position. + Vector vecPosOffset; + vecPosOffset.Random( -m_flSmokeSpawnRadius, m_flSmokeSpawnRadius ); + VectorAdd( vecPosOffset, vecPos, vecPosOffset ); + + + SimpleParticle *pParticle = ( SimpleParticle* )m_pSmokeEmitter->AddParticle( sizeof( SimpleParticle ), + m_hSmokeMaterial, + vecPosOffset ); + if ( pParticle ) + { + pParticle->m_flLifetime = 0.0f; + pParticle->m_flDieTime = m_flSmokeLifetime; + + // Add just a little movement. + pParticle->m_vecVelocity.Random( -5.0f, 5.0f ); + + pParticle->m_uchColor[0] = 255.0f; + pParticle->m_uchColor[1] = 255.0f; + pParticle->m_uchColor[2] = 255.0f; + + + pParticle->m_uchStartSize = 70 * m_flParticleScale; + pParticle->m_uchEndSize = 25 * m_flParticleScale; + + float flAlpha = random->RandomFloat( 0.5f, 1.0f ); + pParticle->m_uchStartAlpha = flAlpha * 255; + pParticle->m_uchEndAlpha = 0; + + pParticle->m_flRoll = random->RandomInt( 0, 360 ); + pParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f ); + } + } + } + + // Update Fire +// if ( m_pFireEmitter && m_bEmitFire ) +// { +// } + + // Flare + + // Save off position. + VectorCopy( m_vecPos, m_vecPrevPos ); +} + +//============================================================================= +// +// Meteor Tail Functions +// + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +C_EnvMeteorTail::C_EnvMeteorTail() +{ + m_TailMaterialHandle = INVALID_MATERIAL_HANDLE; + + m_pParticleMgr = NULL; + m_pParticle = NULL; + + m_flFadeTime = 0.5f; + m_flWidth = 3.0f; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +C_EnvMeteorTail::~C_EnvMeteorTail() +{ + Destroy(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteorTail::Start( const Vector &vecOrigin, const Vector &vecDirection, + float flSpeed ) +{ + // Set the particle manager. + m_pParticleMgr = ParticleMgr(); + m_pParticleMgr->AddEffect( &m_ParticleEffect, this ); + m_TailMaterialHandle = m_ParticleEffect.FindOrAddMaterial( "particle/guidedplasmaprojectile" ); + m_pParticle = m_ParticleEffect.AddParticle( sizeof( StandardParticle_t ), m_TailMaterialHandle ); + if ( m_pParticle ) + { + m_pParticle->m_Pos = vecOrigin; + } + + VectorCopy( vecDirection, m_vecDirection ); + m_flSpeed = flSpeed; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteorTail::Destroy( void ) +{ + if ( m_pParticleMgr ) + { + m_pParticleMgr->RemoveEffect( &m_ParticleEffect ); + m_pParticleMgr = NULL; + } +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteorTail::DrawFragment( ParticleDraw* pDraw, + const Vector &vecStart, const Vector &vecDelta, + const Vector4D &vecStartColor, const Vector4D &vecEndColor, + float flStartV, float flEndV ) +{ + if( !pDraw->GetMeshBuilder() ) + return; + + // Clip the fragment. + Vector vecVerts[4]; + if ( !Tracer_ComputeVerts( vecStart, vecDelta, m_flWidth, vecVerts ) ) + return; + + // NOTE: Gotta get the winding right so it's not backface culled + // (we need to turn of backface culling for these bad boys) + CMeshBuilder* pMeshBuilder = pDraw->GetMeshBuilder(); + + pMeshBuilder->Position3f( vecVerts[0].x, vecVerts[0].y, vecVerts[0].z ); + pMeshBuilder->TexCoord2f( 0, 0.0f, flStartV ); + pMeshBuilder->Color4fv( vecStartColor.Base() ); + pMeshBuilder->AdvanceVertex(); + + pMeshBuilder->Position3f( vecVerts[1].x, vecVerts[1].y, vecVerts[1].z ); + pMeshBuilder->TexCoord2f( 0, 1.0f, flStartV ); + pMeshBuilder->Color4fv( vecStartColor.Base() ); + pMeshBuilder->AdvanceVertex(); + + pMeshBuilder->Position3f( vecVerts[3].x, vecVerts[3].y, vecVerts[3].z ); + pMeshBuilder->TexCoord2f( 0, 1.0f, flEndV ); + pMeshBuilder->Color4fv( vecEndColor.Base() ); + pMeshBuilder->AdvanceVertex(); + + pMeshBuilder->Position3f( vecVerts[2].x, vecVerts[2].y, vecVerts[2].z ); + pMeshBuilder->TexCoord2f( 0, 0.0f, flEndV ); + pMeshBuilder->Color4fv( vecEndColor.Base() ); + pMeshBuilder->AdvanceVertex(); +} + +void C_EnvMeteorTail::SimulateParticles( CParticleSimulateIterator *pIterator ) +{ + Particle *pParticle = (Particle*)pIterator->GetFirst(); + while ( pParticle ) + { + // Update the particle position. + pParticle->m_Pos = GetLocalOrigin(); + + pParticle = (Particle*)pIterator->GetNext(); + } +} + + +void C_EnvMeteorTail::RenderParticles( CParticleRenderIterator *pIterator ) +{ + const Particle *pParticle = (const Particle *)pIterator->GetFirst(); + while ( pParticle ) + { + // Now draw the tail fragments... + Vector4D vecStartColor( 1.0f, 1.0f, 1.0f, 1.0f ); + Vector4D vecEndColor( 1.0f, 1.0f, 1.0f, 0.0f ); + Vector vecDelta, vecStartPos, vecEndPos; + + // Calculate the tail. + Vector vecTailEnd; + vecTailEnd = GetLocalOrigin() + ( m_vecDirection * -m_flSpeed ); + + // Transform particles into camera space. + TransformParticle( m_pParticleMgr->GetModelView(), GetLocalOrigin(), vecStartPos ); + TransformParticle( m_pParticleMgr->GetModelView(), vecTailEnd, vecEndPos ); + float sortKey = vecStartPos.z; + + // Draw the tail fragment. + VectorSubtract( vecStartPos, vecEndPos, vecDelta ); + DrawFragment( pIterator->GetParticleDraw(), vecEndPos, vecDelta, vecEndColor, vecStartColor, + 1.0f - vecEndColor[3], 1.0f - vecStartColor[3] ); + + pParticle = (const Particle *)pIterator->GetNext( sortKey ); + } +} + + +//============================================================================= +// +// Meteor Functions +// + +static g_MeteorCounter = 0; + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +C_EnvMeteor::C_EnvMeteor() +{ +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +C_EnvMeteor::~C_EnvMeteor() +{ +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteor::ClientThink( void ) +{ + // Get the current time. + float flTime = gpGlobals->curtime; + + // Update the meteor. + if ( m_Meteor.IsInSkybox( flTime ) ) + { + if ( m_Meteor.m_nLocation == METEOR_LOCATION_WORLD ) + { + WorldToSkyboxThink( flTime ); + } + else + { + SkyboxThink( flTime ); + } + } + else + { + if ( m_Meteor.m_nLocation == METEOR_LOCATION_SKYBOX ) + { + SkyboxToWorldThink( flTime ); + } + else + { + WorldThink( flTime ); + } + } +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteor::SkyboxThink( float flTime ) +{ + float flDeltaTime = flTime - m_Meteor.m_flStartTime; + if ( flDeltaTime > METEOR_MAX_LIFETIME ) + { + Destroy( this ); + return; + } + + // Check to see if the object is passive or not - act accordingly! + if ( !m_Meteor.IsPassive( flTime ) ) + { + // Update meteor position. + Vector origin; + m_Meteor.GetPositionAtTime( flTime, origin ); + SetLocalOrigin( origin ); + + // Update the position of the tail effect. + m_TailEffect.SetLocalOrigin( GetLocalOrigin() ); + m_HeadEffect.MeteorHeadThink( GetLocalOrigin(), flTime ); + } + + // Add the entity to the active list - update! + AddEntity(); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteor::WorldToSkyboxThink( float flTime ) +{ + // Move the meteor from the world into the skybox. + m_Meteor.ConvertFromWorldToSkybox(); + + // Destroy the head effect. Recreate it. + m_HeadEffect.Destroy(); + m_HeadEffect.Start( m_Meteor.m_vecStartPosition, m_vecTravelDir ); + m_HeadEffect.SetSmokeEmission( true ); + m_HeadEffect.SetParticleScale( 1.0f / 16.0f ); + m_HeadEffect.m_bInitThink = true; + + // Update to world model. + SetModel( "models/props/common/meteorites/meteor05.mdl" ); + + // Update the meteor position (move into the skybox!) + SetLocalOrigin( m_Meteor.m_vecStartPosition ); + + // Update (think). + SkyboxThink( flTime ); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteor::SkyboxToWorldThink( float flTime ) +{ + // Move the meteor from the skybox into the world. + m_Meteor.ConvertFromSkyboxToWorld(); + + // Destroy the head effect. Recreate it. + m_HeadEffect.Destroy(); + m_HeadEffect.Start( m_Meteor.m_vecStartPosition, m_vecTravelDir ); + m_HeadEffect.SetSmokeEmission( true ); + m_HeadEffect.SetParticleScale( 1.0f ); + m_HeadEffect.m_bInitThink = true; + + // Update to world model. + SetModel( "models/props/common/meteorites/meteor04.mdl" ); + + SetLocalOrigin( m_Meteor.m_vecStartPosition ); + + // Update (think). + WorldThink( flTime ); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteor::WorldThink( float flTime ) +{ + // Update meteor position. + Vector vecEndPosition; + m_Meteor.GetPositionAtTime( flTime, vecEndPosition ); + + // m_Meteor must return the end position in world space for the trace to work. + Assert( GetMoveParent() == NULL ); + +// Msg( "Client: Time = %lf, Position: %4.2f %4.2f %4.2f\n", flTime, vecEndPosition.x, vecEndPosition.y, vecEndPosition.z ); + + // Check to see if we struck the world. If so, cause an explosion. + trace_t trace; + + Vector vecMin, vecMax; + GetRenderBounds( vecMin, vecMax ); + + // NOTE: This code works only if we aren't in hierarchy!!! + Assert( !GetMoveParent() ); + + CTraceFilterWorldOnly traceFilter; + UTIL_TraceHull( GetAbsOrigin(), vecEndPosition, vecMin, vecMax, + MASK_SOLID_BRUSHONLY, &traceFilter, &trace ); + + // Collision. + if ( ( trace.fraction < 1.0f ) && !( trace.surface.flags & SURF_SKY ) ) + { + // Move up to the end. + Vector vecEnd = GetAbsOrigin() + ( ( vecEndPosition - GetAbsOrigin() ) * trace.fraction ); + + // Create an explosion effect! + BaseExplosionEffect().Create( vecEnd, 10, 32, TE_EXPLFLAG_NONE ); + + // Debugging Info!!!! +// debugoverlay->AddBoxOverlay( vecEnd, Vector( -10, -10, -10 ), Vector( 10, 10, 10 ), QAngle( 0.0f, 0.0f, 0.0f ), 255, 0, 0, 0, 100 ); + + Destroy( this ); + return; + } + else + { + // Move to the end. + SetLocalOrigin( vecEndPosition ); + } + + m_TailEffect.SetLocalOrigin( GetLocalOrigin() ); + m_HeadEffect.MeteorHeadThink( GetLocalOrigin(), flTime ); + + // Add the entity to the active list - update! + AddEntity(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +C_EnvMeteor *C_EnvMeteor::Create( int nID, int iMeteorType, const Vector &vecOrigin, + const Vector &vecDirection, float flSpeed, float flStartTime, + float flDamageRadius, + const Vector &vecTriggerMins, const Vector &vecTriggerMaxs ) +{ + C_EnvMeteor *pMeteor = new C_EnvMeteor; + if ( pMeteor ) + { + pMeteor->m_Meteor.Init( nID, flStartTime, METEOR_PASSIVE_TIME, vecOrigin, vecDirection, flSpeed, flDamageRadius, + vecTriggerMins, vecTriggerMaxs ); + + // Initialize the meteor. + pMeteor->InitializeAsClientEntity( "models/props/common/meteorites/meteor05.mdl", RENDER_GROUP_OPAQUE_ENTITY ); + + // Handle forward simulation. + if ( ( pMeteor->m_Meteor.m_flStartTime + METEOR_MAX_LIFETIME ) < gpGlobals->curtime ) + { + Destroy( pMeteor ); + } + + // Meteor Head and Tail + pMeteor->SetTravelDirection( vecDirection ); + + pMeteor->m_HeadEffect.SetSmokeEmission( true ); + pMeteor->m_HeadEffect.Start( vecOrigin, vecDirection ); + pMeteor->m_HeadEffect.SetParticleScale( 1.0f / 16.0f ); + + pMeteor->m_TailEffect.Start( vecOrigin, vecDirection, flSpeed ); + + pMeteor->SetNextClientThink( CLIENT_THINK_ALWAYS ); + } + + return pMeteor; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void C_EnvMeteor::Destroy( C_EnvMeteor *pMeteor ) +{ + Assert( pMeteor->GetClientHandle() != INVALID_CLIENTENTITY_HANDLE ); + ClientThinkList()->AddToDeleteList( pMeteor->GetClientHandle() ); +} |