338 lines
15 KiB
C++
338 lines
15 KiB
C++
|
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
|
||
|
//
|
||
|
// Purpose: An entity that spawns and controls a particle system
|
||
|
//
|
||
|
//=============================================================================
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "particles/particles.h"
|
||
|
#include "networkstringtable_gamedll.h"
|
||
|
#include "particle_system.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID );
|
||
|
extern void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID );
|
||
|
|
||
|
|
||
|
// Stripped down CBaseEntity send table
|
||
|
IMPLEMENT_SERVERCLASS_ST_NOBASE(CParticleSystem, DT_ParticleSystem)
|
||
|
SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ),
|
||
|
SendPropEHandle (SENDINFO(m_hOwnerEntity)),
|
||
|
SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)),
|
||
|
SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED),
|
||
|
SendPropQAngles (SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles ),
|
||
|
|
||
|
SendPropInt( SENDINFO(m_iEffectIndex), MAX_PARTICLESYSTEMS_STRING_BITS, SPROP_UNSIGNED ),
|
||
|
SendPropBool( SENDINFO(m_bActive) ),
|
||
|
SendPropInt( SENDINFO( m_nStopType ), Q_log2(CParticleSystem::NUM_STOP_TYPES)+1, SPROP_UNSIGNED ),
|
||
|
SendPropFloat( SENDINFO(m_flStartTime) ),
|
||
|
SendPropString( SENDINFO(m_szSnapshotFileName) ),
|
||
|
SendPropArray3( SENDINFO_ARRAY3(m_vServerControlPoints), SendPropVector(SENDINFO_ARRAY(m_vServerControlPoints)) ),
|
||
|
SendPropArray3( SENDINFO_ARRAY3(m_iServerControlPointAssignments), SendPropInt(SENDINFO_ARRAY(m_iServerControlPointAssignments), -1, SPROP_UNSIGNED ) ),
|
||
|
|
||
|
SendPropArray3( SENDINFO_ARRAY3(m_hControlPointEnts), SendPropEHandle( SENDINFO_ARRAY(m_hControlPointEnts) ) ),
|
||
|
SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ),
|
||
|
END_SEND_TABLE()
|
||
|
|
||
|
BEGIN_DATADESC( CParticleSystem )
|
||
|
DEFINE_KEYFIELD( m_bStartActive, FIELD_BOOLEAN, "start_active" ),
|
||
|
DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ),
|
||
|
DEFINE_FIELD( m_flStartTime, FIELD_TIME ),
|
||
|
DEFINE_ARRAY( m_vServerControlPoints, FIELD_VECTOR, CParticleSystem::kSERVERCONTROLLEDPOINTS ),
|
||
|
DEFINE_ARRAY( m_iServerControlPointAssignments, FIELD_CHARACTER, CParticleSystem::kSERVERCONTROLLEDPOINTS ),
|
||
|
DEFINE_KEYFIELD( m_iszEffectName, FIELD_STRING, "effect_name" ),
|
||
|
//DEFINE_FIELD( m_iEffectIndex, FIELD_INTEGER ), // Don't save. Refind after loading.
|
||
|
DEFINE_AUTO_ARRAY_KEYFIELD( m_szSnapshotFileName, FIELD_CHARACTER, "snapshot_file" ),
|
||
|
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[0], FIELD_STRING, "cpoint1" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[1], FIELD_STRING, "cpoint2" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[2], FIELD_STRING, "cpoint3" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[3], FIELD_STRING, "cpoint4" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[4], FIELD_STRING, "cpoint5" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[5], FIELD_STRING, "cpoint6" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[6], FIELD_STRING, "cpoint7" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[7], FIELD_STRING, "cpoint8" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[8], FIELD_STRING, "cpoint9" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[9], FIELD_STRING, "cpoint10" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[10], FIELD_STRING, "cpoint11" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[11], FIELD_STRING, "cpoint12" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[12], FIELD_STRING, "cpoint13" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[13], FIELD_STRING, "cpoint14" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[14], FIELD_STRING, "cpoint15" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[15], FIELD_STRING, "cpoint16" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[16], FIELD_STRING, "cpoint17" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[17], FIELD_STRING, "cpoint18" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[18], FIELD_STRING, "cpoint19" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[19], FIELD_STRING, "cpoint20" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[20], FIELD_STRING, "cpoint21" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[21], FIELD_STRING, "cpoint22" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[22], FIELD_STRING, "cpoint23" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[23], FIELD_STRING, "cpoint24" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[24], FIELD_STRING, "cpoint25" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[25], FIELD_STRING, "cpoint26" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[26], FIELD_STRING, "cpoint27" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[27], FIELD_STRING, "cpoint28" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[28], FIELD_STRING, "cpoint29" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[29], FIELD_STRING, "cpoint30" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[30], FIELD_STRING, "cpoint31" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[31], FIELD_STRING, "cpoint32" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[32], FIELD_STRING, "cpoint33" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[33], FIELD_STRING, "cpoint34" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[34], FIELD_STRING, "cpoint35" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[35], FIELD_STRING, "cpoint36" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[36], FIELD_STRING, "cpoint37" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[37], FIELD_STRING, "cpoint38" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[38], FIELD_STRING, "cpoint39" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[39], FIELD_STRING, "cpoint40" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[40], FIELD_STRING, "cpoint41" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[41], FIELD_STRING, "cpoint42" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[42], FIELD_STRING, "cpoint43" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[43], FIELD_STRING, "cpoint44" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[44], FIELD_STRING, "cpoint45" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[45], FIELD_STRING, "cpoint46" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[46], FIELD_STRING, "cpoint47" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[47], FIELD_STRING, "cpoint48" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[48], FIELD_STRING, "cpoint49" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[49], FIELD_STRING, "cpoint50" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[50], FIELD_STRING, "cpoint51" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[51], FIELD_STRING, "cpoint52" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[52], FIELD_STRING, "cpoint53" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[53], FIELD_STRING, "cpoint54" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[54], FIELD_STRING, "cpoint55" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[55], FIELD_STRING, "cpoint56" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[56], FIELD_STRING, "cpoint57" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[57], FIELD_STRING, "cpoint58" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[58], FIELD_STRING, "cpoint59" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[59], FIELD_STRING, "cpoint60" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[60], FIELD_STRING, "cpoint61" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[61], FIELD_STRING, "cpoint62" ),
|
||
|
DEFINE_KEYFIELD( m_iszControlPointNames[62], FIELD_STRING, "cpoint63" ),
|
||
|
|
||
|
DEFINE_KEYFIELD( m_iControlPointParents.m_Value[0], FIELD_CHARACTER, "cpoint1_parent" ),
|
||
|
DEFINE_KEYFIELD( m_iControlPointParents.m_Value[1], FIELD_CHARACTER, "cpoint2_parent" ),
|
||
|
DEFINE_KEYFIELD( m_iControlPointParents.m_Value[2], FIELD_CHARACTER, "cpoint3_parent" ),
|
||
|
DEFINE_KEYFIELD( m_iControlPointParents.m_Value[3], FIELD_CHARACTER, "cpoint4_parent" ),
|
||
|
DEFINE_KEYFIELD( m_iControlPointParents.m_Value[4], FIELD_CHARACTER, "cpoint5_parent" ),
|
||
|
DEFINE_KEYFIELD( m_iControlPointParents.m_Value[5], FIELD_CHARACTER, "cpoint6_parent" ),
|
||
|
DEFINE_KEYFIELD( m_iControlPointParents.m_Value[6], FIELD_CHARACTER, "cpoint7_parent" ),
|
||
|
|
||
|
DEFINE_AUTO_ARRAY( m_hControlPointEnts, FIELD_EHANDLE ),
|
||
|
|
||
|
DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ),
|
||
|
DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ),
|
||
|
DEFINE_INPUTFUNC( FIELD_VOID, "StopPlayEndCap", InputStopEndCap ),
|
||
|
DEFINE_INPUTFUNC( FIELD_VOID, "DestroyImmediately", InputDestroy ),
|
||
|
|
||
|
|
||
|
DEFINE_THINKFUNC( StartParticleSystemThink ),
|
||
|
|
||
|
END_DATADESC()
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( info_particle_system, CParticleSystem );
|
||
|
|
||
|
CParticleSystem::CParticleSystem( void ) : m_bNoSave( false )
|
||
|
{
|
||
|
for( int i = 0; i != kSERVERCONTROLLEDPOINTS; ++i )
|
||
|
{
|
||
|
m_iServerControlPointAssignments.GetForModify(i) = 255;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Precache
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CParticleSystem::Precache( void )
|
||
|
{
|
||
|
const char *pParticleSystemName = STRING( m_iszEffectName );
|
||
|
if ( pParticleSystemName == NULL || pParticleSystemName[0] == 0 )
|
||
|
{
|
||
|
Warning( "info_particle_system (%s) has no particle system name specified!\n", GetEntityName().ToCStr() );
|
||
|
}
|
||
|
|
||
|
PrecacheParticleSystem( pParticleSystemName );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CParticleSystem::Spawn( void )
|
||
|
{
|
||
|
BaseClass::Spawn();
|
||
|
|
||
|
Precache();
|
||
|
m_iEffectIndex = -1;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CParticleSystem::Activate( void )
|
||
|
{
|
||
|
BaseClass::Activate();
|
||
|
|
||
|
// Find our particle effect index
|
||
|
m_iEffectIndex = GetParticleSystemIndex( STRING(m_iszEffectName) );
|
||
|
|
||
|
if ( m_bStartActive )
|
||
|
{
|
||
|
m_bStartActive = false;
|
||
|
StartParticleSystem();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CParticleSystem::KeyValue( const char *szKeyName, const char *szValue )
|
||
|
{
|
||
|
if ( FStrEq( szKeyName, "snapshot_file" ) )
|
||
|
{
|
||
|
Q_strncpy( m_szSnapshotFileName.GetForModify(), szValue, MAX_PATH );
|
||
|
return true;
|
||
|
}
|
||
|
return BaseClass::KeyValue( szKeyName, szValue );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CParticleSystem::GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen )
|
||
|
{
|
||
|
if ( FStrEq( szKeyName, "snapshot_file" ) )
|
||
|
{
|
||
|
Q_snprintf( szValue, iMaxLen, "%s", m_szSnapshotFileName.Get() );
|
||
|
return true;
|
||
|
}
|
||
|
return BaseClass::GetKeyValue( szKeyName, szValue, iMaxLen );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CParticleSystem::StartParticleSystemThink( void )
|
||
|
{
|
||
|
StartParticleSystem();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Always transmitted to clients
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CParticleSystem::UpdateTransmitState()
|
||
|
{
|
||
|
return SetTransmitState( FL_EDICT_ALWAYS );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CParticleSystem::StartParticleSystem( void )
|
||
|
{
|
||
|
if ( m_bActive == false )
|
||
|
{
|
||
|
m_flStartTime = gpGlobals->curtime;
|
||
|
m_bActive = true;
|
||
|
|
||
|
// Setup our control points at this time (in case our targets weren't around at spawn time)
|
||
|
ReadControlPointEnts();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CParticleSystem::StopParticleSystem( int nStopType )
|
||
|
{
|
||
|
m_bActive = false;
|
||
|
m_nStopType = nStopType;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CParticleSystem::InputStart( inputdata_t &inputdata )
|
||
|
{
|
||
|
StartParticleSystem();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CParticleSystem::InputStop( inputdata_t &inputdata )
|
||
|
{
|
||
|
StopParticleSystem( STOP_NORMAL );
|
||
|
}
|
||
|
|
||
|
void CParticleSystem::InputDestroy( inputdata_t &inputdata )
|
||
|
{
|
||
|
StopParticleSystem( STOP_DESTROY_IMMEDIATELY );
|
||
|
}
|
||
|
|
||
|
void CParticleSystem::InputStopEndCap( inputdata_t &inputdata )
|
||
|
{
|
||
|
StopParticleSystem( STOP_PLAY_ENDCAP );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Find each entity referred to by m_iszControlPointNames and
|
||
|
// resolve it into the corresponding slot in m_hControlPointEnts
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CParticleSystem::ReadControlPointEnts( void )
|
||
|
{
|
||
|
for ( int i = 0 ; i < kMAXCONTROLPOINTS; ++i )
|
||
|
{
|
||
|
if ( m_iszControlPointNames[i] == NULL_STRING )
|
||
|
continue;
|
||
|
|
||
|
CBaseEntity *pPointEnt = gEntList.FindEntityGeneric( NULL, STRING( m_iszControlPointNames[i] ), this );
|
||
|
Assert( pPointEnt != NULL );
|
||
|
if ( pPointEnt == NULL )
|
||
|
{
|
||
|
Warning("Particle system %s could not find control point entity (%s)\n", GetEntityName().ToCStr(), m_iszControlPointNames[i].ToCStr() );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
m_hControlPointEnts.Set( i, pPointEnt );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Try to allocate one of the server controlled control points to
|
||
|
// hold the value. Designed to let the server funnel some variables to
|
||
|
// particle systems (size, color, swirliness, ...)
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CParticleSystem::SetControlPointValue( int iControlPoint, const Vector &vValue )
|
||
|
{
|
||
|
for( int i = 0; i != kSERVERCONTROLLEDPOINTS; ++i )
|
||
|
{
|
||
|
if( m_iServerControlPointAssignments[i] == iControlPoint )
|
||
|
{
|
||
|
m_vServerControlPoints.GetForModify(i) = vValue;
|
||
|
return true;
|
||
|
}
|
||
|
if( m_iServerControlPointAssignments[i] == 255 )
|
||
|
{
|
||
|
m_iServerControlPointAssignments.GetForModify(i) = iControlPoint;
|
||
|
m_vServerControlPoints.GetForModify(i) = vValue;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Warning( "No free server controlled control points.\n" );
|
||
|
return false; //already using up all of our server control points
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Inline methods
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CParticleSystem::ObjectCaps( void )
|
||
|
{
|
||
|
int flags = 0;
|
||
|
if ( m_bNoSave )
|
||
|
flags = FCAP_DONT_SAVE;
|
||
|
|
||
|
return BaseClass::ObjectCaps() | flags;
|
||
|
}
|