You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
652 lines
21 KiB
652 lines
21 KiB
![]()
4 years ago
|
//========= 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() );
|
||
|
}
|