diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/shared/particle_property.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/shared/particle_property.cpp')
| -rw-r--r-- | mp/src/game/shared/particle_property.cpp | 1322 |
1 files changed, 661 insertions, 661 deletions
diff --git a/mp/src/game/shared/particle_property.cpp b/mp/src/game/shared/particle_property.cpp index 18d278ad..e5a5487d 100644 --- a/mp/src/game/shared/particle_property.cpp +++ b/mp/src/game/shared/particle_property.cpp @@ -1,661 +1,661 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================
-
-#include "cbase.h"
-#include "particle_property.h"
-#include "utlvector.h"
-
-#ifdef CLIENT_DLL
-
-#include "c_baseentity.h"
-#include "c_baseanimating.h"
-#include "recvproxy.h"
-#include "particles_new.h"
-#include "engine/ivdebugoverlay.h"
-#include "bone_setup.h"
-#else
-
-#include "baseentity.h"
-#include "baseanimating.h"
-#include "sendproxy.h"
-#endif
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-#ifdef STAGING_ONLY
-#ifdef TF_CLIENT_DLL
-extern ConVar tf_unusual_effect_offset;
-#endif
-#endif
-
-//-----------------------------------------------------------------------------
-// Save/load
-//-----------------------------------------------------------------------------
-BEGIN_DATADESC_NO_BASE( CParticleProperty )
- // DEFINE_FIELD( m_pOuter, FIELD_CLASSPTR ),
-END_DATADESC()
-
-#ifdef CLIENT_DLL
-//-----------------------------------------------------------------------------
-// Prediction
-//-----------------------------------------------------------------------------
-BEGIN_PREDICTION_DATA_NO_BASE( CParticleProperty )
- //DEFINE_PRED_FIELD( m_vecMins, FIELD_VECTOR, FTYPEDESC_INSENDTABLE ),
-END_PREDICTION_DATA()
-#endif
-
-//-----------------------------------------------------------------------------
-// Networking
-//-----------------------------------------------------------------------------
-BEGIN_NETWORK_TABLE_NOBASE( CParticleProperty, DT_ParticleProperty )
-#ifdef CLIENT_DLL
-//RecvPropVector( RECVINFO(m_vecMins), 0, RecvProxy_OBBMins ),
-#else
-//SendPropVector( SENDINFO(m_vecMins), 0, SPROP_NOSCALE),
-#endif
-END_NETWORK_TABLE()
-
-
-//-----------------------------------------------------------------------------
-// Constructor, destructor
-//-----------------------------------------------------------------------------
-CParticleProperty::CParticleProperty()
-{
- Init( NULL );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-CParticleProperty::~CParticleProperty()
-{
- // We're being removed. Call StopEmission() on any particle system
- // that has an unlimited number of particles to emit.
- StopEmission( NULL, false, true );
-}
-
-//-----------------------------------------------------------------------------
-// Initialization
-//-----------------------------------------------------------------------------
-void CParticleProperty::Init( CBaseEntity *pEntity )
-{
- m_pOuter = pEntity;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-int CParticleProperty::GetParticleAttachment( C_BaseEntity *pEntity, const char *pszAttachmentName, const char *pszParticleName )
-{
- Assert( pEntity && pEntity->GetBaseAnimating() );
- if ( !pEntity || !pEntity->GetBaseAnimating() )
- return INVALID_PARTICLE_ATTACHMENT;
-
- // Find the attachment point index
- int iAttachment = pEntity->GetBaseAnimating()->LookupAttachment( pszAttachmentName );
- if ( iAttachment == INVALID_PARTICLE_ATTACHMENT )
- {
- Warning("Model '%s' doesn't have attachment '%s' to attach particle system '%s' to.\n", STRING(pEntity->GetBaseAnimating()->GetModelName()), pszAttachmentName, pszParticleName );
- }
-
- return iAttachment;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Create a new particle system and attach it to our owner
-//-----------------------------------------------------------------------------
-CNewParticleEffect *CParticleProperty::Create( const char *pszParticleName, ParticleAttachment_t iAttachType, const char *pszAttachmentName )
-{
- int iAttachment = GetParticleAttachment( GetOuter(), pszAttachmentName, pszParticleName );
- if ( iAttachment == INVALID_PARTICLE_ATTACHMENT )
- return NULL;
-
- // Create the system
- return Create( pszParticleName, iAttachType, iAttachment );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Create a new particle system and attach it to our owner
-//-----------------------------------------------------------------------------
-static ConVar cl_particle_batch_mode( "cl_particle_batch_mode", "1" );
-CNewParticleEffect *CParticleProperty::Create( const char *pszParticleName, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset )
-{
- if ( GameRules() )
- {
- pszParticleName = GameRules()->TranslateEffectForVisionFilter( "particles", pszParticleName );
- }
-
- int nBatchMode = cl_particle_batch_mode.GetInt();
- CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszParticleName );
- bool bRequestedBatch = ( nBatchMode == 2 ) || ( ( nBatchMode == 1 ) && pDef && pDef->ShouldBatch() );
- if ( ( iAttachType == PATTACH_CUSTOMORIGIN ) && bRequestedBatch )
- {
- int iIndex = FindEffect( pszParticleName );
- if ( iIndex >= 0 )
- {
- CNewParticleEffect *pEffect = m_ParticleEffects[iIndex].pParticleEffect.GetObject();
- pEffect->Restart();
- return pEffect;
- }
- }
-
- if ( !pDef )
- {
- AssertMsg( 0, "Attempting to create unknown particle system" );
- Warning( "Attempting to create unknown particle system '%s' \n", pszParticleName );
- return NULL;
- }
-
- int iIndex = m_ParticleEffects.AddToTail();
- ParticleEffectList_t *newEffect = &m_ParticleEffects[iIndex];
- newEffect->pParticleEffect = CNewParticleEffect::Create( m_pOuter, pDef );
-
- if ( !newEffect->pParticleEffect->IsValid() )
- {
- // Caused by trying to spawn an unregistered particle effect. Remove it.
- ParticleMgr()->RemoveEffect( newEffect->pParticleEffect.GetObject() );
- return NULL;
- }
-
- AddControlPoint( iIndex, 0, GetOuter(), iAttachType, iAttachmentPoint, vecOriginOffset );
-
- if ( m_pOuter )
- {
- m_pOuter->OnNewParticleEffect( pszParticleName, newEffect->pParticleEffect.GetObject() );
- }
-
- return newEffect->pParticleEffect.GetObject();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CParticleProperty::AddControlPoint( CNewParticleEffect *pEffect, int iPoint, C_BaseEntity *pEntity, ParticleAttachment_t iAttachType, const char *pszAttachmentName, Vector vecOriginOffset )
-{
- int iAttachment = INVALID_PARTICLE_ATTACHMENT;
- if ( pszAttachmentName )
- {
- iAttachment = GetParticleAttachment( pEntity, pszAttachmentName, pEffect->GetEffectName() );
- }
-
- for ( int i = 0; i < m_ParticleEffects.Count(); i++ )
- {
- if ( m_ParticleEffects[i].pParticleEffect == pEffect )
- {
- AddControlPoint( i, iPoint, pEntity, iAttachType, iAttachment, vecOriginOffset );
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CParticleProperty::AddControlPoint( int iEffectIndex, int iPoint, C_BaseEntity *pEntity, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset )
-{
- Assert( iEffectIndex >= 0 && iEffectIndex < m_ParticleEffects.Count() );
- ParticleEffectList_t *pEffect = &m_ParticleEffects[iEffectIndex];
- Assert( pEffect->pControlPoints.Count() < MAX_PARTICLE_CONTROL_POINTS );
-
- int iIndex = pEffect->pControlPoints.AddToTail();
- ParticleControlPoint_t *pNewPoint = &pEffect->pControlPoints[iIndex];
- pNewPoint->iControlPoint = iPoint;
- pNewPoint->hEntity = pEntity;
- pNewPoint->iAttachType = iAttachType;
- pNewPoint->iAttachmentPoint = iAttachmentPoint;
- pNewPoint->vecOriginOffset = vecOriginOffset;
-
- UpdateParticleEffect( pEffect, true, iIndex );
-}
-
-
-//-----------------------------------------------------------------------------
-// Used to replace a particle effect with a different one; attaches the control point updating to the new one
-//-----------------------------------------------------------------------------
-void CParticleProperty::ReplaceParticleEffect( CNewParticleEffect *pOldEffect, CNewParticleEffect *pNewEffect )
-{
- int nCount = m_ParticleEffects.Count();
- for ( int i = 0; i < nCount; ++i )
- {
- if ( pOldEffect != m_ParticleEffects[i].pParticleEffect.GetObject() )
- continue;
-
- m_ParticleEffects[i].pParticleEffect = pNewEffect;
- UpdateParticleEffect( &m_ParticleEffects[i], true );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Set the parent of a given control point to the index of some other
-// control point.
-//-----------------------------------------------------------------------------
-void CParticleProperty::SetControlPointParent( int iEffectIndex, int whichControlPoint, int parentIdx )
-{
-
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Stop effects from emitting more particles. If no effect is
-// specified, all effects attached to this entity are stopped.
-//-----------------------------------------------------------------------------
-void CParticleProperty::StopEmission( CNewParticleEffect *pEffect, bool bWakeOnStop, bool bDestroyAsleepSystems )
-{
- // If we return from dormancy and are then told to stop emitting,
- // we should have died while dormant. Remove ourselves immediately.
- bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount);
-
- if ( pEffect )
- {
- if ( FindEffect( pEffect ) != -1 )
- {
- pEffect->StopEmission( false, bRemoveInstantly, bWakeOnStop );
- }
- }
- else
- {
- // Stop all effects
- float flNow = g_pParticleSystemMgr->GetLastSimulationTime();
- int nCount = m_ParticleEffects.Count();
- for ( int i = nCount-1; i >= 0; i-- )
- {
- CNewParticleEffect *pTmp = m_ParticleEffects[i].pParticleEffect.GetObject();
- bool bRemoveSystem = bRemoveInstantly || ( bDestroyAsleepSystems && ( flNow >= pTmp->m_flNextSleepTime ) );
- if ( bRemoveSystem )
- {
- m_ParticleEffects.Remove( i );
- pTmp->SetOwner( NULL );
- }
- pTmp->StopEmission( false, bRemoveSystem, !bRemoveSystem && bWakeOnStop );
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Remove effects immediately, including all current particles. If no
-// effect is specified, all effects attached to this entity are removed.
-//-----------------------------------------------------------------------------
-void CParticleProperty::StopEmissionAndDestroyImmediately( CNewParticleEffect *pEffect )
-{
- if ( pEffect )
- {
- int iIndex = FindEffect( pEffect );
- //Assert( iIndex != -1 );
- if ( iIndex != -1 )
- {
- m_ParticleEffects.Remove( iIndex );
-
- // Clear the owner so it doesn't try to call back to us on deletion
- pEffect->SetOwner( NULL );
- pEffect->StopEmission( false, true );
- }
- }
- else
- {
- // Immediately destroy all effects
- int nCount = m_ParticleEffects.Count();
- for ( int i = nCount-1; i >= 0; i-- )
- {
- CNewParticleEffect *pTmp = m_ParticleEffects[i].pParticleEffect.GetObject();
- m_ParticleEffects.Remove( i );
-
- // Clear the owner so it doesn't try to call back to us on deletion
- pTmp->SetOwner( NULL );
- pTmp->StopEmission( false, true );
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Stop all effects that have a control point associated with the given
-// entity.
-//-----------------------------------------------------------------------------
-void CParticleProperty::StopParticlesInvolving( CBaseEntity *pEntity )
-{
- Assert( pEntity );
-
- EHANDLE entHandle(pEntity);
-
- // If we return from dormancy and are then told to stop emitting,
- // we should have died while dormant. Remove ourselves immediately.
- bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount);
-
- int nCount = m_ParticleEffects.Count();
- for ( int i = 0; i < nCount; ++i )
- {
- // for each effect...
- ParticleEffectList_t &part = m_ParticleEffects[i];
- // look through all the control points to see if any mention the given object
- int cpCount = part.pControlPoints.Count();
- for (int j = 0; j < cpCount ; ++j )
- {
- // if any control points respond to the given handle...
- if (part.pControlPoints[j].hEntity == entHandle)
- {
- part.pParticleEffect->StopEmission( false, bRemoveInstantly );
- part.pControlPoints.Remove( j );
- break; // break out of the inner loop (to where it says BREAK TO HERE)
- }
- }
- // BREAK TO HERE
- }
-}
-
-//g_pParticleSystemMgr->FindParticleSystem( pParticleSystemName );
-
-//-----------------------------------------------------------------------------
-// Purpose: Stop all effects that were created using the given definition
-// name.
-//-----------------------------------------------------------------------------
-void CParticleProperty::StopParticlesNamed( const char *pszEffectName, bool bForceRemoveInstantly /* =false */ )
-{
- CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszEffectName );
- AssertMsg1(pDef, "Could not find particle definition %s", pszEffectName );
- if (!pDef)
- return;
-
-
- // If we return from dormancy and are then told to stop emitting,
- // we should have died while dormant. Remove ourselves immediately.
- bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount);
- // force remove particles instantly if caller specified
- bRemoveInstantly |= bForceRemoveInstantly;
-
- int nCount = m_ParticleEffects.Count();
- for ( int i = 0; i < nCount; ++i )
- {
- // for each effect...
- CNewParticleEffect *pParticleEffect = m_ParticleEffects[i].pParticleEffect.GetObject();
- if (pParticleEffect->m_pDef() == pDef)
- {
- pParticleEffect->StopEmission( false, bRemoveInstantly );
- }
- }
-}
-
-void CParticleProperty::StopParticlesWithNameAndAttachment( const char *pszEffectName, int iAttachmentPoint, bool bForceRemoveInstantly /* =false */ )
-{
- CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszEffectName );
- AssertMsg1(pDef, "Could not find particle definition %s", pszEffectName );
- if (!pDef)
- return;
-
-
- // If we return from dormancy and are then told to stop emitting,
- // we should have died while dormant. Remove ourselves immediately.
- bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount);
- // force remove particles instantly if caller specified
- bRemoveInstantly |= bForceRemoveInstantly;
-
- int nCount = m_ParticleEffects.Count();
- for ( int i = 0; i < nCount; ++i )
- {
- // for each effect...
- ParticleEffectList_t *pParticleEffectList = &m_ParticleEffects[i];
- CNewParticleEffect *pParticleEffect = pParticleEffectList->pParticleEffect.GetObject();
- if (pParticleEffect->m_pDef() == pDef)
- {
- int nControlPointCount = pParticleEffectList->pControlPoints.Count();
- for ( int j = 0; j < nControlPointCount; ++j )
- {
- if ( pParticleEffectList->pControlPoints[j].iAttachmentPoint == iAttachmentPoint )
- {
- pParticleEffect->StopEmission( false, bRemoveInstantly );
- break;
- }
- }
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CParticleProperty::OnParticleSystemUpdated( CNewParticleEffect *pEffect, float flTimeDelta )
-{
- int iIndex = FindEffect( pEffect );
- Assert( iIndex != -1 );
- if ( iIndex == -1 )
- return;
-
- // Enable FP exceptions here when FP_EXCEPTIONS_ENABLED is defined,
- // to help track down bad math.
- FPExceptionEnabler enableExceptions;
-
- UpdateParticleEffect( &m_ParticleEffects[iIndex] );
-
- /*
- // Display the bounding box of the particle effect
- Vector vecMins, vecMaxs;
- pEffect->GetRenderBounds( vecMins, vecMaxs );
- debugoverlay->AddBoxOverlay( pEffect->GetRenderOrigin(), vecMins, vecMaxs, QAngle( 0, 0, 0 ), 0, 255, 255, 0, 0 );
- */
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CParticleProperty::OnParticleSystemDeleted( CNewParticleEffect *pEffect )
-{
- int iIndex = FindEffect( pEffect );
- if ( iIndex == -1 )
- return;
-
- m_ParticleEffects[iIndex].pParticleEffect.MarkDeleted();
- m_ParticleEffects.Remove( iIndex );
-}
-
-#ifdef CLIENT_DLL
-//-----------------------------------------------------------------------------
-// Purpose: The entity we're attached to has change dormancy state on our client
-//-----------------------------------------------------------------------------
-void CParticleProperty::OwnerSetDormantTo( bool bDormant )
-{
- m_iDormancyChangedAtFrame = gpGlobals->framecount;
-
- int nCount = m_ParticleEffects.Count();
- for ( int i = 0; i < nCount; i++ )
- {
- //m_ParticleEffects[i].pParticleEffect->SetShouldSimulate( !bDormant );
- m_ParticleEffects[i].pParticleEffect->SetDormant( bDormant );
- }
-}
-#endif
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-int CParticleProperty::FindEffect( CNewParticleEffect *pEffect )
-{
- for ( int i = 0; i < m_ParticleEffects.Count(); i++ )
- {
- if ( m_ParticleEffects[i].pParticleEffect == pEffect )
- return i;
- }
-
- return -1;
-}
-
-int CParticleProperty::FindEffect( const char *pEffectName, int nStart /*= 0*/ )
-{
- for ( int i = nStart; i < m_ParticleEffects.Count(); i++ )
- {
- if ( !Q_stricmp( m_ParticleEffects[i].pParticleEffect->GetName(), pEffectName ) )
- return i;
- }
-
- return -1;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CParticleProperty::UpdateParticleEffect( ParticleEffectList_t *pEffect, bool bInitializing, int iOnlyThisControlPoint )
-{
- if ( iOnlyThisControlPoint != -1 )
- {
- UpdateControlPoint( pEffect, iOnlyThisControlPoint, bInitializing );
- return;
- }
-
- // Loop through our control points and update them all
- for ( int i = 0; i < pEffect->pControlPoints.Count(); i++ )
- {
- UpdateControlPoint( pEffect, i, bInitializing );
- }
-}
-
-extern void FormatViewModelAttachment( Vector &vOrigin, bool bInverse );
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int iPoint, bool bInitializing )
-{
- ParticleControlPoint_t *pPoint = &pEffect->pControlPoints[iPoint];
-
- if ( !pPoint->hEntity.Get() )
- {
- if ( pPoint->iAttachType == PATTACH_WORLDORIGIN && bInitializing )
- {
- pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) );
- pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, pPoint->vecOriginOffset );
- pEffect->pParticleEffect->SetSortOrigin( pPoint->vecOriginOffset );
- }
-
- pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, NULL );
- return;
- }
-
- // Only update non-follow particles when we're initializing,
- // unless we're parented to something, in which case we should always update
- if ( !bInitializing && !pPoint->hEntity->GetMoveParent() && (pPoint->iAttachType == PATTACH_ABSORIGIN || pPoint->iAttachType == PATTACH_POINT ) )
- return;
-
- if ( pPoint->iAttachType == PATTACH_CUSTOMORIGIN )
- return;
-
- Vector vecOrigin, vecForward, vecRight, vecUp;
-
- float flOffset = 0.0f;
- bool bUsingHeadOrigin = false;
-
-#ifdef TF_CLIENT_DLL
-
- CBaseEntity *pWearable = (CBaseEntity*) pPoint->hEntity.Get();
- if ( pWearable && dynamic_cast<IHasAttributes*>( pWearable ) && !pWearable->IsPlayer() )
- {
- C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating();
- if ( pAnimating )
- {
- int bUseHeadOrigin = 0;
- CALL_ATTRIB_HOOK_INT_ON_OTHER( pPoint->hEntity.Get(), bUseHeadOrigin, particle_effect_use_head_origin );
- if ( bUseHeadOrigin > 0 )
- {
- int iBone = Studio_BoneIndexByName( pAnimating->GetModelPtr(), "bip_head" );
- if ( iBone >= 0 )
- {
- bUsingHeadOrigin = true;
- const matrix3x4_t headBone = pAnimating->GetBone( iBone );
- MatrixVectors( headBone, &vecForward, &vecRight, &vecUp );
- MatrixPosition( headBone, vecOrigin );
-
- CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pPoint->hEntity.Get(), flOffset, particle_effect_vertical_offset );
- }
- }
- }
- }
-#endif
-
- if ( !bUsingHeadOrigin )
- {
- switch ( pPoint->iAttachType )
- {
- case PATTACH_POINT:
- case PATTACH_POINT_FOLLOW:
- {
- C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating();
-
- Assert( pAnimating );
- if ( pAnimating )
- {
- matrix3x4_t attachmentToWorld;
-
- if ( !pAnimating->GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) )
- {
- Warning( "Cannot update control point %d for effect '%s'.\n", pPoint->iAttachmentPoint, pEffect->pParticleEffect->GetEffectName() );
- attachmentToWorld = pAnimating->RenderableToWorldTransform();
- }
-
- MatrixVectors( attachmentToWorld, &vecForward, &vecRight, &vecUp );
- MatrixPosition( attachmentToWorld, vecOrigin );
-
- if ( pEffect->pParticleEffect->m_pDef->IsViewModelEffect() )
- {
- FormatViewModelAttachment( vecOrigin, true );
- }
-
- }
- }
- break;
-
- case PATTACH_ABSORIGIN:
- case PATTACH_ABSORIGIN_FOLLOW:
- default:
- {
- vecOrigin = pPoint->hEntity->GetAbsOrigin() + pPoint->vecOriginOffset;
- pPoint->hEntity->GetVectors( &vecForward, &vecRight, &vecUp );
- }
- break;
-
- case PATTACH_ROOTBONE_FOLLOW:
- {
- C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating();
-
- Assert( pAnimating );
- if ( pAnimating )
- {
- matrix3x4_t rootBone;
- if ( pAnimating->GetRootBone( rootBone ) )
- {
- MatrixVectors( rootBone, &vecForward, &vecRight, &vecUp );
- MatrixPosition( rootBone, vecOrigin );
- }
- }
- }
- break;
- }
- }
-
- Vector vecForcedOriginOffset( 0, 0, flOffset );
- pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, vecForward, vecRight, vecUp );
- pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, pPoint->hEntity );
- pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, vecOrigin + vecForcedOriginOffset );
- pEffect->pParticleEffect->SetSortOrigin( vecOrigin + vecForcedOriginOffset);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Output all active effects
-//-----------------------------------------------------------------------------
-void CParticleProperty::DebugPrintEffects( void )
-{
- int nCount = m_ParticleEffects.Count();
- for ( int i = 0; i < nCount; ++i )
- {
- // for each effect...
- CNewParticleEffect *pParticleEffect = m_ParticleEffects[i].pParticleEffect.GetObject();
-
- if ( !pParticleEffect )
- continue;
-
- Msg( "(%d) EffectName \"%s\" Dormant? %s Emission Stopped? %s \n",
- i,
- pParticleEffect->GetEffectName(),
- ( pParticleEffect->m_bDormant ) ? "yes" : "no",
- ( pParticleEffect->m_bEmissionStopped ) ? "yes" : "no" );
- }
-}
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "cbase.h" +#include "particle_property.h" +#include "utlvector.h" + +#ifdef CLIENT_DLL + +#include "c_baseentity.h" +#include "c_baseanimating.h" +#include "recvproxy.h" +#include "particles_new.h" +#include "engine/ivdebugoverlay.h" +#include "bone_setup.h" +#else + +#include "baseentity.h" +#include "baseanimating.h" +#include "sendproxy.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#ifdef STAGING_ONLY +#ifdef TF_CLIENT_DLL +extern ConVar tf_unusual_effect_offset; +#endif +#endif + +//----------------------------------------------------------------------------- +// Save/load +//----------------------------------------------------------------------------- +BEGIN_DATADESC_NO_BASE( CParticleProperty ) + // DEFINE_FIELD( m_pOuter, FIELD_CLASSPTR ), +END_DATADESC() + +#ifdef CLIENT_DLL +//----------------------------------------------------------------------------- +// Prediction +//----------------------------------------------------------------------------- +BEGIN_PREDICTION_DATA_NO_BASE( CParticleProperty ) + //DEFINE_PRED_FIELD( m_vecMins, FIELD_VECTOR, FTYPEDESC_INSENDTABLE ), +END_PREDICTION_DATA() +#endif + +//----------------------------------------------------------------------------- +// Networking +//----------------------------------------------------------------------------- +BEGIN_NETWORK_TABLE_NOBASE( CParticleProperty, DT_ParticleProperty ) +#ifdef CLIENT_DLL +//RecvPropVector( RECVINFO(m_vecMins), 0, RecvProxy_OBBMins ), +#else +//SendPropVector( SENDINFO(m_vecMins), 0, SPROP_NOSCALE), +#endif +END_NETWORK_TABLE() + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +CParticleProperty::CParticleProperty() +{ + Init( NULL ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CParticleProperty::~CParticleProperty() +{ + // We're being removed. Call StopEmission() on any particle system + // that has an unlimited number of particles to emit. + StopEmission( NULL, false, true ); +} + +//----------------------------------------------------------------------------- +// Initialization +//----------------------------------------------------------------------------- +void CParticleProperty::Init( CBaseEntity *pEntity ) +{ + m_pOuter = pEntity; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CParticleProperty::GetParticleAttachment( C_BaseEntity *pEntity, const char *pszAttachmentName, const char *pszParticleName ) +{ + Assert( pEntity && pEntity->GetBaseAnimating() ); + if ( !pEntity || !pEntity->GetBaseAnimating() ) + return INVALID_PARTICLE_ATTACHMENT; + + // Find the attachment point index + int iAttachment = pEntity->GetBaseAnimating()->LookupAttachment( pszAttachmentName ); + if ( iAttachment == INVALID_PARTICLE_ATTACHMENT ) + { + Warning("Model '%s' doesn't have attachment '%s' to attach particle system '%s' to.\n", STRING(pEntity->GetBaseAnimating()->GetModelName()), pszAttachmentName, pszParticleName ); + } + + return iAttachment; +} + +//----------------------------------------------------------------------------- +// Purpose: Create a new particle system and attach it to our owner +//----------------------------------------------------------------------------- +CNewParticleEffect *CParticleProperty::Create( const char *pszParticleName, ParticleAttachment_t iAttachType, const char *pszAttachmentName ) +{ + int iAttachment = GetParticleAttachment( GetOuter(), pszAttachmentName, pszParticleName ); + if ( iAttachment == INVALID_PARTICLE_ATTACHMENT ) + return NULL; + + // Create the system + return Create( pszParticleName, iAttachType, iAttachment ); +} + +//----------------------------------------------------------------------------- +// Purpose: Create a new particle system and attach it to our owner +//----------------------------------------------------------------------------- +static ConVar cl_particle_batch_mode( "cl_particle_batch_mode", "1" ); +CNewParticleEffect *CParticleProperty::Create( const char *pszParticleName, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset ) +{ + if ( GameRules() ) + { + pszParticleName = GameRules()->TranslateEffectForVisionFilter( "particles", pszParticleName ); + } + + int nBatchMode = cl_particle_batch_mode.GetInt(); + CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszParticleName ); + bool bRequestedBatch = ( nBatchMode == 2 ) || ( ( nBatchMode == 1 ) && pDef && pDef->ShouldBatch() ); + if ( ( iAttachType == PATTACH_CUSTOMORIGIN ) && bRequestedBatch ) + { + int iIndex = FindEffect( pszParticleName ); + if ( iIndex >= 0 ) + { + CNewParticleEffect *pEffect = m_ParticleEffects[iIndex].pParticleEffect.GetObject(); + pEffect->Restart(); + return pEffect; + } + } + + if ( !pDef ) + { + AssertMsg( 0, "Attempting to create unknown particle system" ); + Warning( "Attempting to create unknown particle system '%s' \n", pszParticleName ); + return NULL; + } + + int iIndex = m_ParticleEffects.AddToTail(); + ParticleEffectList_t *newEffect = &m_ParticleEffects[iIndex]; + newEffect->pParticleEffect = CNewParticleEffect::Create( m_pOuter, pDef ); + + if ( !newEffect->pParticleEffect->IsValid() ) + { + // Caused by trying to spawn an unregistered particle effect. Remove it. + ParticleMgr()->RemoveEffect( newEffect->pParticleEffect.GetObject() ); + return NULL; + } + + AddControlPoint( iIndex, 0, GetOuter(), iAttachType, iAttachmentPoint, vecOriginOffset ); + + if ( m_pOuter ) + { + m_pOuter->OnNewParticleEffect( pszParticleName, newEffect->pParticleEffect.GetObject() ); + } + + return newEffect->pParticleEffect.GetObject(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CParticleProperty::AddControlPoint( CNewParticleEffect *pEffect, int iPoint, C_BaseEntity *pEntity, ParticleAttachment_t iAttachType, const char *pszAttachmentName, Vector vecOriginOffset ) +{ + int iAttachment = INVALID_PARTICLE_ATTACHMENT; + if ( pszAttachmentName ) + { + iAttachment = GetParticleAttachment( pEntity, pszAttachmentName, pEffect->GetEffectName() ); + } + + for ( int i = 0; i < m_ParticleEffects.Count(); i++ ) + { + if ( m_ParticleEffects[i].pParticleEffect == pEffect ) + { + AddControlPoint( i, iPoint, pEntity, iAttachType, iAttachment, vecOriginOffset ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CParticleProperty::AddControlPoint( int iEffectIndex, int iPoint, C_BaseEntity *pEntity, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset ) +{ + Assert( iEffectIndex >= 0 && iEffectIndex < m_ParticleEffects.Count() ); + ParticleEffectList_t *pEffect = &m_ParticleEffects[iEffectIndex]; + Assert( pEffect->pControlPoints.Count() < MAX_PARTICLE_CONTROL_POINTS ); + + int iIndex = pEffect->pControlPoints.AddToTail(); + ParticleControlPoint_t *pNewPoint = &pEffect->pControlPoints[iIndex]; + pNewPoint->iControlPoint = iPoint; + pNewPoint->hEntity = pEntity; + pNewPoint->iAttachType = iAttachType; + pNewPoint->iAttachmentPoint = iAttachmentPoint; + pNewPoint->vecOriginOffset = vecOriginOffset; + + UpdateParticleEffect( pEffect, true, iIndex ); +} + + +//----------------------------------------------------------------------------- +// Used to replace a particle effect with a different one; attaches the control point updating to the new one +//----------------------------------------------------------------------------- +void CParticleProperty::ReplaceParticleEffect( CNewParticleEffect *pOldEffect, CNewParticleEffect *pNewEffect ) +{ + int nCount = m_ParticleEffects.Count(); + for ( int i = 0; i < nCount; ++i ) + { + if ( pOldEffect != m_ParticleEffects[i].pParticleEffect.GetObject() ) + continue; + + m_ParticleEffects[i].pParticleEffect = pNewEffect; + UpdateParticleEffect( &m_ParticleEffects[i], true ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Set the parent of a given control point to the index of some other +// control point. +//----------------------------------------------------------------------------- +void CParticleProperty::SetControlPointParent( int iEffectIndex, int whichControlPoint, int parentIdx ) +{ + +} + +//----------------------------------------------------------------------------- +// Purpose: Stop effects from emitting more particles. If no effect is +// specified, all effects attached to this entity are stopped. +//----------------------------------------------------------------------------- +void CParticleProperty::StopEmission( CNewParticleEffect *pEffect, bool bWakeOnStop, bool bDestroyAsleepSystems ) +{ + // If we return from dormancy and are then told to stop emitting, + // we should have died while dormant. Remove ourselves immediately. + bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount); + + if ( pEffect ) + { + if ( FindEffect( pEffect ) != -1 ) + { + pEffect->StopEmission( false, bRemoveInstantly, bWakeOnStop ); + } + } + else + { + // Stop all effects + float flNow = g_pParticleSystemMgr->GetLastSimulationTime(); + int nCount = m_ParticleEffects.Count(); + for ( int i = nCount-1; i >= 0; i-- ) + { + CNewParticleEffect *pTmp = m_ParticleEffects[i].pParticleEffect.GetObject(); + bool bRemoveSystem = bRemoveInstantly || ( bDestroyAsleepSystems && ( flNow >= pTmp->m_flNextSleepTime ) ); + if ( bRemoveSystem ) + { + m_ParticleEffects.Remove( i ); + pTmp->SetOwner( NULL ); + } + pTmp->StopEmission( false, bRemoveSystem, !bRemoveSystem && bWakeOnStop ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Remove effects immediately, including all current particles. If no +// effect is specified, all effects attached to this entity are removed. +//----------------------------------------------------------------------------- +void CParticleProperty::StopEmissionAndDestroyImmediately( CNewParticleEffect *pEffect ) +{ + if ( pEffect ) + { + int iIndex = FindEffect( pEffect ); + //Assert( iIndex != -1 ); + if ( iIndex != -1 ) + { + m_ParticleEffects.Remove( iIndex ); + + // Clear the owner so it doesn't try to call back to us on deletion + pEffect->SetOwner( NULL ); + pEffect->StopEmission( false, true ); + } + } + else + { + // Immediately destroy all effects + int nCount = m_ParticleEffects.Count(); + for ( int i = nCount-1; i >= 0; i-- ) + { + CNewParticleEffect *pTmp = m_ParticleEffects[i].pParticleEffect.GetObject(); + m_ParticleEffects.Remove( i ); + + // Clear the owner so it doesn't try to call back to us on deletion + pTmp->SetOwner( NULL ); + pTmp->StopEmission( false, true ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Stop all effects that have a control point associated with the given +// entity. +//----------------------------------------------------------------------------- +void CParticleProperty::StopParticlesInvolving( CBaseEntity *pEntity ) +{ + Assert( pEntity ); + + EHANDLE entHandle(pEntity); + + // If we return from dormancy and are then told to stop emitting, + // we should have died while dormant. Remove ourselves immediately. + bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount); + + int nCount = m_ParticleEffects.Count(); + for ( int i = 0; i < nCount; ++i ) + { + // for each effect... + ParticleEffectList_t &part = m_ParticleEffects[i]; + // look through all the control points to see if any mention the given object + int cpCount = part.pControlPoints.Count(); + for (int j = 0; j < cpCount ; ++j ) + { + // if any control points respond to the given handle... + if (part.pControlPoints[j].hEntity == entHandle) + { + part.pParticleEffect->StopEmission( false, bRemoveInstantly ); + part.pControlPoints.Remove( j ); + break; // break out of the inner loop (to where it says BREAK TO HERE) + } + } + // BREAK TO HERE + } +} + +//g_pParticleSystemMgr->FindParticleSystem( pParticleSystemName ); + +//----------------------------------------------------------------------------- +// Purpose: Stop all effects that were created using the given definition +// name. +//----------------------------------------------------------------------------- +void CParticleProperty::StopParticlesNamed( const char *pszEffectName, bool bForceRemoveInstantly /* =false */ ) +{ + CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszEffectName ); + AssertMsg1(pDef, "Could not find particle definition %s", pszEffectName ); + if (!pDef) + return; + + + // If we return from dormancy and are then told to stop emitting, + // we should have died while dormant. Remove ourselves immediately. + bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount); + // force remove particles instantly if caller specified + bRemoveInstantly |= bForceRemoveInstantly; + + int nCount = m_ParticleEffects.Count(); + for ( int i = 0; i < nCount; ++i ) + { + // for each effect... + CNewParticleEffect *pParticleEffect = m_ParticleEffects[i].pParticleEffect.GetObject(); + if (pParticleEffect->m_pDef() == pDef) + { + pParticleEffect->StopEmission( false, bRemoveInstantly ); + } + } +} + +void CParticleProperty::StopParticlesWithNameAndAttachment( const char *pszEffectName, int iAttachmentPoint, bool bForceRemoveInstantly /* =false */ ) +{ + CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszEffectName ); + AssertMsg1(pDef, "Could not find particle definition %s", pszEffectName ); + if (!pDef) + return; + + + // If we return from dormancy and are then told to stop emitting, + // we should have died while dormant. Remove ourselves immediately. + bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount); + // force remove particles instantly if caller specified + bRemoveInstantly |= bForceRemoveInstantly; + + int nCount = m_ParticleEffects.Count(); + for ( int i = 0; i < nCount; ++i ) + { + // for each effect... + ParticleEffectList_t *pParticleEffectList = &m_ParticleEffects[i]; + CNewParticleEffect *pParticleEffect = pParticleEffectList->pParticleEffect.GetObject(); + if (pParticleEffect->m_pDef() == pDef) + { + int nControlPointCount = pParticleEffectList->pControlPoints.Count(); + for ( int j = 0; j < nControlPointCount; ++j ) + { + if ( pParticleEffectList->pControlPoints[j].iAttachmentPoint == iAttachmentPoint ) + { + pParticleEffect->StopEmission( false, bRemoveInstantly ); + break; + } + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CParticleProperty::OnParticleSystemUpdated( CNewParticleEffect *pEffect, float flTimeDelta ) +{ + int iIndex = FindEffect( pEffect ); + Assert( iIndex != -1 ); + if ( iIndex == -1 ) + return; + + // Enable FP exceptions here when FP_EXCEPTIONS_ENABLED is defined, + // to help track down bad math. + FPExceptionEnabler enableExceptions; + + UpdateParticleEffect( &m_ParticleEffects[iIndex] ); + + /* + // Display the bounding box of the particle effect + Vector vecMins, vecMaxs; + pEffect->GetRenderBounds( vecMins, vecMaxs ); + debugoverlay->AddBoxOverlay( pEffect->GetRenderOrigin(), vecMins, vecMaxs, QAngle( 0, 0, 0 ), 0, 255, 255, 0, 0 ); + */ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CParticleProperty::OnParticleSystemDeleted( CNewParticleEffect *pEffect ) +{ + int iIndex = FindEffect( pEffect ); + if ( iIndex == -1 ) + return; + + m_ParticleEffects[iIndex].pParticleEffect.MarkDeleted(); + m_ParticleEffects.Remove( iIndex ); +} + +#ifdef CLIENT_DLL +//----------------------------------------------------------------------------- +// Purpose: The entity we're attached to has change dormancy state on our client +//----------------------------------------------------------------------------- +void CParticleProperty::OwnerSetDormantTo( bool bDormant ) +{ + m_iDormancyChangedAtFrame = gpGlobals->framecount; + + int nCount = m_ParticleEffects.Count(); + for ( int i = 0; i < nCount; i++ ) + { + //m_ParticleEffects[i].pParticleEffect->SetShouldSimulate( !bDormant ); + m_ParticleEffects[i].pParticleEffect->SetDormant( bDormant ); + } +} +#endif + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CParticleProperty::FindEffect( CNewParticleEffect *pEffect ) +{ + for ( int i = 0; i < m_ParticleEffects.Count(); i++ ) + { + if ( m_ParticleEffects[i].pParticleEffect == pEffect ) + return i; + } + + return -1; +} + +int CParticleProperty::FindEffect( const char *pEffectName, int nStart /*= 0*/ ) +{ + for ( int i = nStart; i < m_ParticleEffects.Count(); i++ ) + { + if ( !Q_stricmp( m_ParticleEffects[i].pParticleEffect->GetName(), pEffectName ) ) + return i; + } + + return -1; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CParticleProperty::UpdateParticleEffect( ParticleEffectList_t *pEffect, bool bInitializing, int iOnlyThisControlPoint ) +{ + if ( iOnlyThisControlPoint != -1 ) + { + UpdateControlPoint( pEffect, iOnlyThisControlPoint, bInitializing ); + return; + } + + // Loop through our control points and update them all + for ( int i = 0; i < pEffect->pControlPoints.Count(); i++ ) + { + UpdateControlPoint( pEffect, i, bInitializing ); + } +} + +extern void FormatViewModelAttachment( Vector &vOrigin, bool bInverse ); + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int iPoint, bool bInitializing ) +{ + ParticleControlPoint_t *pPoint = &pEffect->pControlPoints[iPoint]; + + if ( !pPoint->hEntity.Get() ) + { + if ( pPoint->iAttachType == PATTACH_WORLDORIGIN && bInitializing ) + { + pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) ); + pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, pPoint->vecOriginOffset ); + pEffect->pParticleEffect->SetSortOrigin( pPoint->vecOriginOffset ); + } + + pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, NULL ); + return; + } + + // Only update non-follow particles when we're initializing, + // unless we're parented to something, in which case we should always update + if ( !bInitializing && !pPoint->hEntity->GetMoveParent() && (pPoint->iAttachType == PATTACH_ABSORIGIN || pPoint->iAttachType == PATTACH_POINT ) ) + return; + + if ( pPoint->iAttachType == PATTACH_CUSTOMORIGIN ) + return; + + Vector vecOrigin, vecForward, vecRight, vecUp; + + float flOffset = 0.0f; + bool bUsingHeadOrigin = false; + +#ifdef TF_CLIENT_DLL + + CBaseEntity *pWearable = (CBaseEntity*) pPoint->hEntity.Get(); + if ( pWearable && dynamic_cast<IHasAttributes*>( pWearable ) && !pWearable->IsPlayer() ) + { + C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating(); + if ( pAnimating ) + { + int bUseHeadOrigin = 0; + CALL_ATTRIB_HOOK_INT_ON_OTHER( pPoint->hEntity.Get(), bUseHeadOrigin, particle_effect_use_head_origin ); + if ( bUseHeadOrigin > 0 ) + { + int iBone = Studio_BoneIndexByName( pAnimating->GetModelPtr(), "bip_head" ); + if ( iBone >= 0 ) + { + bUsingHeadOrigin = true; + const matrix3x4_t headBone = pAnimating->GetBone( iBone ); + MatrixVectors( headBone, &vecForward, &vecRight, &vecUp ); + MatrixPosition( headBone, vecOrigin ); + + CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pPoint->hEntity.Get(), flOffset, particle_effect_vertical_offset ); + } + } + } + } +#endif + + if ( !bUsingHeadOrigin ) + { + switch ( pPoint->iAttachType ) + { + case PATTACH_POINT: + case PATTACH_POINT_FOLLOW: + { + C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating(); + + Assert( pAnimating ); + if ( pAnimating ) + { + matrix3x4_t attachmentToWorld; + + if ( !pAnimating->GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) ) + { + Warning( "Cannot update control point %d for effect '%s'.\n", pPoint->iAttachmentPoint, pEffect->pParticleEffect->GetEffectName() ); + attachmentToWorld = pAnimating->RenderableToWorldTransform(); + } + + MatrixVectors( attachmentToWorld, &vecForward, &vecRight, &vecUp ); + MatrixPosition( attachmentToWorld, vecOrigin ); + + if ( pEffect->pParticleEffect->m_pDef->IsViewModelEffect() ) + { + FormatViewModelAttachment( vecOrigin, true ); + } + + } + } + break; + + case PATTACH_ABSORIGIN: + case PATTACH_ABSORIGIN_FOLLOW: + default: + { + vecOrigin = pPoint->hEntity->GetAbsOrigin() + pPoint->vecOriginOffset; + pPoint->hEntity->GetVectors( &vecForward, &vecRight, &vecUp ); + } + break; + + case PATTACH_ROOTBONE_FOLLOW: + { + C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating(); + + Assert( pAnimating ); + if ( pAnimating ) + { + matrix3x4_t rootBone; + if ( pAnimating->GetRootBone( rootBone ) ) + { + MatrixVectors( rootBone, &vecForward, &vecRight, &vecUp ); + MatrixPosition( rootBone, vecOrigin ); + } + } + } + break; + } + } + + Vector vecForcedOriginOffset( 0, 0, flOffset ); + pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, vecForward, vecRight, vecUp ); + pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, pPoint->hEntity ); + pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, vecOrigin + vecForcedOriginOffset ); + pEffect->pParticleEffect->SetSortOrigin( vecOrigin + vecForcedOriginOffset); +} + +//----------------------------------------------------------------------------- +// Purpose: Output all active effects +//----------------------------------------------------------------------------- +void CParticleProperty::DebugPrintEffects( void ) +{ + int nCount = m_ParticleEffects.Count(); + for ( int i = 0; i < nCount; ++i ) + { + // for each effect... + CNewParticleEffect *pParticleEffect = m_ParticleEffects[i].pParticleEffect.GetObject(); + + if ( !pParticleEffect ) + continue; + + Msg( "(%d) EffectName \"%s\" Dormant? %s Emission Stopped? %s \n", + i, + pParticleEffect->GetEffectName(), + ( pParticleEffect->m_bDormant ) ? "yes" : "no", + ( pParticleEffect->m_bEmissionStopped ) ? "yes" : "no" ); + } +} |