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.
651 lines
21 KiB
651 lines
21 KiB
//========= 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() ); |
|
}
|
|
|