예제 #1
0
//-----------------------------------------------------------------------------
// 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 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 );
		}
	}
}
예제 #3
0
//-----------------------------------------------------------------------------
// 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 );
		}
	}
}
예제 #4
0
CNewParticleEffect *CParticleProperty::Create( CParticleSystemDefinition *pDef, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset, matrix3x4_t *matOffset )
{
	int nBatchMode = cl_particle_batch_mode.GetInt();
	bool bRequestedBatch = ( nBatchMode == 2 ) || ( ( nBatchMode == 1 ) && pDef && pDef->ShouldBatch() ); 
	if ( ( iAttachType == PATTACH_CUSTOMORIGIN ) && bRequestedBatch )
	{
		int iIndex = FindEffect( pDef->GetName() );
		if ( iIndex >= 0 )
		{
			CNewParticleEffect *pEffect = m_ParticleEffects[iIndex].pParticleEffect.GetObject();
			pEffect->Restart();
			return pEffect;
		}
	}

	int iIndex = m_ParticleEffects.AddToTail();
	ParticleEffectList_t *newEffect = &m_ParticleEffects[iIndex];
	newEffect->pParticleEffect = CNewParticleEffect::Create( m_pOuter, pDef, pDef->GetName() );

	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, matOffset );

	if ( m_pOuter )
	{
		m_pOuter->OnNewParticleEffect( pDef->GetName(), newEffect->pParticleEffect.GetObject() );
	}

	return newEffect->pParticleEffect.GetObject();
}
void CClientTools::SetRecording( ParticleSystemSearchResult sr, bool bRecord )
{
	Assert( sr );
	if ( sr == NULL )
		return;

	CNewParticleEffect *pParticleEffect = reinterpret_cast< CNewParticleEffect* >( sr );
	pParticleEffect->SetToolRecording( bRecord );
}
예제 #6
0
CNewParticleEffect *CNewParticleEffect::CreateOrAggregate( CBaseEntity *pOwner, CParticleSystemDefinition *pDef,
																	 Vector const &vecAggregatePosition, const char *pDebugName,
																	 int nSplitScreenSlot )
{
	CNewParticleEffect *pAggregateTarget = NULL;
	// see if we should aggregate
	bool bCanAggregate = ( pOwner == NULL ) && ( pDef->m_flAggregateRadius > 0.0 ) && ( cl_aggregate_particles.GetInt() != 0 );
	if ( bCanAggregate )
	{
		CParticleSystemDefinition *pDefFallback = pDef;
		do
		{
			float flAggregateDistSqr =  ( pDefFallback->m_flAggregateRadius * pDefFallback->m_flAggregateRadius ) + 0.1;
			for( CParticleCollection *pSystem = pDefFallback->FirstCollection(); pSystem; pSystem = pSystem->GetNextCollectionUsingSameDef() )
			{
				CNewParticleEffect *pEffectCheck = static_cast<CNewParticleEffect *>( pSystem );
				if ( ! pEffectCheck->m_bDisableAggregation )
				{
					float flDistSQ = vecAggregatePosition.DistToSqr( pEffectCheck->m_vecAggregationCenter );
					if ( ( flDistSQ < flAggregateDistSqr ) && 
						 ( pSystem->m_nMaxAllowedParticles - pSystem->m_nActiveParticles > pDefFallback->m_nAggregationMinAvailableParticles ) &&
						 ( pEffectCheck->m_nSplitScreenUser == nSplitScreenSlot ) )
					{
						flAggregateDistSqr = flDistSQ;
						pAggregateTarget = pEffectCheck;
					}
				}
			}
			pDefFallback = pDefFallback->GetFallbackReplacementDefinition();
		} while ( pDefFallback );
	}
	if ( ! pAggregateTarget )
	{
		// we need a new one
		pAggregateTarget = new CNewParticleEffect( pOwner, pDef );
		pAggregateTarget->SetDrawOnlyForSplitScreenUser( nSplitScreenSlot );
		pAggregateTarget->SetDynamicallyAllocated( true );
	}
	else
	{
		// just reset the old one
		pAggregateTarget->Restart( RESTART_RESET_AND_MAKE_SURE_EMITS_HAPPEN );
	}
	if ( bCanAggregate )
	{
		pAggregateTarget->m_vecAggregationCenter = vecAggregatePosition;
	}
	pAggregateTarget->m_pDebugName = pDebugName;
	pAggregateTarget->m_bDisableAggregation = false;
	return pAggregateTarget;

}
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();
}
예제 #8
0
void CNewParticleEffect::RemoveParticleEffect( int nPrecacheIndex )
{
	CParticleSystemDefinition* pDef = g_pParticleSystemMgr->FindPrecachedParticleSystem( nPrecacheIndex );

	if ( pDef == NULL )
		return;

	for( CParticleCollection *pSystem = pDef->FirstCollection(); pSystem; pSystem = pSystem->GetNextCollectionUsingSameDef() )
	{
		CNewParticleEffect *pEffectCheck = static_cast<CNewParticleEffect *>( pSystem );

		if ( pEffectCheck )
		{
			pEffectCheck->SetRemoveFlag();
		}
	}
}
예제 #9
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_ParticleSystem::ClientThink( void )
{
	if ( m_bActive )
	{
		const char *pszName = GetParticleSystemNameFromIndex( m_iEffectIndex );
		if ( pszName && pszName[0] )
		{
			CNewParticleEffect *pEffect = ParticleProp()->Create( pszName, PATTACH_ABSORIGIN_FOLLOW );
			AssertMsg1( pEffect, "Particle system couldn't make %s", pszName );
			if (pEffect)
			{
				for ( int i = 0 ; i < kMAXCONTROLPOINTS ; ++i )
				{
					CBaseEntity *pOnEntity = m_hControlPointEnts[i].Get();
					if ( pOnEntity )
					{
						ParticleProp()->AddControlPoint( pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW );
					}

					AssertMsg2( m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS ,
						"Particle system specified bogus control point parent (%d) for point %d.",
						m_iControlPointParents[i], i );

					if (m_iControlPointParents[i] != 0)
					{
						pEffect->SetControlPointParent(i+1, m_iControlPointParents[i]);
					}
				}

				// NOTE: What we really want here is to compare our lifetime and that of our children and see if this delta is
				//		 already past the end of it, denoting that we're finished.  In that case, just destroy us and be done. -- jdw

				// TODO: This can go when the SkipToTime code below goes
				ParticleProp()->OnParticleSystemUpdated( pEffect, 0.0f );

				// Skip the effect ahead if we're restarting it
				float flTimeDelta = gpGlobals->curtime - m_flStartTime;
				if ( flTimeDelta > 0.01f )
				{
					VPROF_BUDGET( "C_ParticleSystem::ClientThink SkipToTime", "Particle Simulation" );
					pEffect->SkipToTime( flTimeDelta );
				}
			}
		}
	}
}
//-----------------------------------------------------------------------------
// 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" );
	}
}
예제 #11
0
//-----------------------------------------------------------------------------
// Bounding box
//-----------------------------------------------------------------------------
CNewParticleEffect* CNewParticleEffect::ReplaceWith( const char *pParticleSystemName )
{
	StopEmission( false, true, true );
	if ( !pParticleSystemName || !pParticleSystemName[0] )
		return NULL;

	CNewParticleEffect *pNewEffect = CNewParticleEffect::Create( GetOwner(), pParticleSystemName, pParticleSystemName );
	if ( !pNewEffect )
		return NULL;

	// Copy over the control point data
	for ( int i = 0; i < MAX_PARTICLE_CONTROL_POINTS; ++i )
	{
		if ( !ReadsControlPoint( i ) )
			continue;

		Vector vecForward, vecRight, vecUp;
		pNewEffect->SetControlPoint( i, GetControlPointAtCurrentTime( i ) );
		GetControlPointOrientationAtCurrentTime( i, &vecForward, &vecRight, &vecUp );
		pNewEffect->SetControlPointOrientation( i, vecForward, vecRight, vecUp );
		pNewEffect->SetControlPointParent( i, GetControlPointParent( i ) );
	}

	if ( m_hOwner )
	{
		m_hOwner->ParticleProp()->ReplaceParticleEffect( this, pNewEffect );
	}

	// fixup any other references to the old system, to point to the new system
	while( m_References.m_pHead )
	{
		// this will remove the reference from m_References
		m_References.m_pHead->Set( pNewEffect );
	}

	// At this point any references should have been redirected,
	// but we may still be running with some stray particles, so we
	// might not be flagged for removal - force the issue!
	Assert( m_RefCount == 0 );
	SetRemoveFlag();

	return pNewEffect;
}
예제 #12
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_ParticleSystem::ClientThink( void )
{
	if ( m_bActive )
	{
		const char *pszName = GetParticleSystemNameFromIndex( m_iEffectIndex );
		if ( pszName && pszName[0] )
		{
			CNewParticleEffect *pEffect = ParticleProp()->Create( pszName, PATTACH_ABSORIGIN_FOLLOW );
			m_pEffect = pEffect;
	
			if (pEffect)
			{
				for ( int i = 0 ; i < kMAXCONTROLPOINTS ; ++i )
				{
					CBaseEntity *pOnEntity = m_hControlPointEnts[i].Get();
					if ( pOnEntity )
					{
						ParticleProp()->AddControlPoint( pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW );
					}

					AssertMsg2( m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS ,
						"Particle system specified bogus control point parent (%d) for point %d.",
						m_iControlPointParents[i], i );

					if (m_iControlPointParents[i] != 0)
					{
						pEffect->SetControlPointParent(i+1, m_iControlPointParents[i]);
					}
				}

				//server controlled control points (variables in particle effects instead of literal follow points)
				for( int i = 0; i != ARRAYSIZE( m_iServerControlPointAssignments ); ++i )
				{
					if( m_iServerControlPointAssignments[i] != 255 )
					{
						pEffect->SetControlPoint( m_iServerControlPointAssignments[i], m_vServerControlPoints[i] );
					}
					else
					{
						break;
					}
				}

				// Attach our particle snapshot if we have one
				Assert( m_pSnapshot || !m_szSnapshotFileName[0] ); // m_szSnapshotFileName shouldn't change after the create update
				if ( m_pSnapshot )
				{
					pEffect->SetControlPointSnapshot( 0, m_pSnapshot );
				}

				// NOTE: What we really want here is to compare our lifetime and that of our children and see if this delta is
				//		 already past the end of it, denoting that we're finished.  In that case, just destroy us and be done. -- jdw

				// TODO: This can go when the SkipToTime code below goes
				ParticleProp()->OnParticleSystemUpdated( pEffect, 0.0f );

				// Skip the effect ahead if we're restarting it
				float flTimeDelta = gpGlobals->curtime - m_flStartTime;
				if ( flTimeDelta > 0.01f )
				{
					VPROF_BUDGET( "C_ParticleSystem::ClientThink SkipToTime", "Particle Simulation" );
					pEffect->SkipToTime( flTimeDelta );
				}
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Reload particle definitions
//-----------------------------------------------------------------------------
void CClientTools::ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen )
{
	MDLCACHE_CRITICAL_SECTION(); // Copying particle attachment control points may end up needing to evaluate skeletons

	//////////////
	// Find any systems that depend on any system in the buffer
	// slow, but necessary if we want live reloads to work - and doesn't happen too often
	CUtlVector<CUtlString> systemNamesToReload;

	g_pParticleSystemMgr->GetParticleSystemsInBuffer( CUtlBuffer(pBufData, nLen, CUtlBuffer::READ_ONLY), &systemNamesToReload );

	CUtlVector<CNewParticleEffect*> toReplaceEffects;
	CUtlVector<CUtlString> toReplaceNames;

	for( CNewParticleEffect *pEffect = ParticleMgr()->FirstNewEffect(); pEffect; pEffect = ParticleMgr()->NextNewEffect(pEffect) )
	{
		for( int i = 0; i < systemNamesToReload.Count(); ++i )
		{
			if ( pEffect->DependsOnSystem( systemNamesToReload[i] ) )
			{
				// only reload a given effect once
				if ( -1 == toReplaceEffects.Find(pEffect) )
				{
					toReplaceNames.AddToTail( pEffect->GetName() );
					toReplaceEffects.AddToTail( pEffect );
				}
			}
		}
	}

	CUtlVector<CNonDrawingParticleSystem*> toReplaceEffectsNonDrawing;
	CUtlVector<CUtlString> toReplaceNamesNonDrawing;
	for( CNonDrawingParticleSystem *i = ParticleMgr()->m_NonDrawingParticleSystems.Head(); i ; i = i->m_pNext )
	{
		for( int j = 0; j < systemNamesToReload.Count(); ++j )
		{
			if ( i->Get()->DependsOnSystem( systemNamesToReload[j] ) )
			{
				if ( -1 == toReplaceEffectsNonDrawing.Find( i ) )
				{
					toReplaceNamesNonDrawing.AddToTail( i->Get()->GetName() );
					toReplaceEffectsNonDrawing.AddToTail( i );
				}
			}
		}
	}

	//////////////
	// Load the data and stomp the old definitions
	g_pParticleSystemMgr->ReadParticleConfigFile( CUtlBuffer(pBufData, nLen, CUtlBuffer::READ_ONLY), true );

	//////////////
	// Now replace all of the systems with their new versions
	Assert( toReplaceEffects.Count() == toReplaceNames.Count() );

	for( int i = 0; i < toReplaceNames.Count(); ++i )
	{
		CNewParticleEffect *pEffect = toReplaceEffects[i];
		pEffect->ReplaceWith( toReplaceNames[i] );
	}

	// update all the non-drawings ones
	for( int i = 0; i < toReplaceNamesNonDrawing.Count(); i++ )
	{
		CNonDrawingParticleSystem *pEffect = toReplaceEffectsNonDrawing[i];
		delete pEffect->m_pSystem;
		pEffect->m_pSystem = g_pParticleSystemMgr->CreateParticleCollection( toReplaceNamesNonDrawing[i] );
	}
}
//-----------------------------------------------------------------------------
// Purpose: Message handler for ASWOrderUseItemFX message
//-----------------------------------------------------------------------------
void CASW_Hud_Squad_Hotbar::MsgFunc_ASWOrderUseItemFX( bf_read &msg )
{
	int iMarine = msg.ReadShort();	
	C_ASW_Marine *pMarine = dynamic_cast<C_ASW_Marine*>(ClientEntityList().GetEnt(iMarine));		// turn iMarine ent index into the marine
	if ( !pMarine )
		return;

	int iOrderType = msg.ReadShort();
	int iInventorySlot = msg.ReadShort();

	Vector vecPosition;
	vecPosition.x = msg.ReadFloat();
	vecPosition.y = msg.ReadFloat();
	vecPosition.z = msg.ReadFloat();

	// loops through to see if we already have an order effect for this marine
	StopItemFX( pMarine );

	const char *pszClassName = NULL;

	switch( iOrderType )
	{
	case ASW_USE_ORDER_WITH_ITEM:
		{
			// check we have an item in that slot
			CASW_Weapon* pWeapon = pMarine->GetASWWeapon( iInventorySlot );
			if ( !pWeapon || !pWeapon->GetWeaponInfo() || !pWeapon->GetWeaponInfo()->m_bOffhandActivate )
				return;

			pszClassName = pWeapon->GetClassname();
		}
		break;

	case ASW_USE_ORDER_HACK:
		{
			pszClassName = "asw_weapon_t75";	// for now, we're using the t75 icon for hacking
		}
		break;

	default:
		{
			Assert( false ); // unspecified order type
			return;
		}
		break;
	}

	//CNewParticleEffect *pEffect = pMarine->ParticleProp()->Create( "order_use_item", PATTACH_CUSTOMORIGIN, -1, vecPosition - pMarine->GetAbsOrigin() );
	CNewParticleEffect *pEffect = pMarine->ParticleProp()->Create( "order_use_item", PATTACH_ABSORIGIN );
	if ( pEffect )
	{
		pMarine->ParticleProp()->AddControlPoint( pEffect, 1, pMarine, PATTACH_CUSTOMORIGIN );
		pEffect->SetControlPoint( 1, vecPosition );//vecPosition - pMarine->GetAbsOrigin()
		for ( int i = 0; i < NUM_USE_ITEM_ORDER_CLASSES; i++ )
		{
			if ( pszUseItemOrderClasses[i] && !Q_strcmp (  pszUseItemOrderClasses[i]  ,  pszClassName )  )
			{
				pEffect->SetControlPoint( 2, Vector( i, 0, 0 ) );
				break;
			}
		}

		HotbarOrderEffectsList_t::IndexLocalType_t iIndex = m_hHotbarOrderEffects.AddToTail();
		m_hHotbarOrderEffects[iIndex].iEffectID = iMarine;
		m_hHotbarOrderEffects[iIndex].pEffect = pEffect;
	}
}