//========= Copyright 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)), #ifdef MAPBASE SendPropBool(SENDINFO(m_bDestroyImmediately)), #endif SendPropFloat(SENDINFO(m_flStartTime)), SendPropArray3(SENDINFO_ARRAY3(m_hControlPointEnts), SendPropEHandle(SENDINFO_ARRAY(m_hControlPointEnts))), SendPropArray3(SENDINFO_ARRAY3(m_vControlPointVecs), SendPropVector(SENDINFO_ARRAY(m_vControlPointVecs))), SendPropArray3(SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt(SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED)), SendPropBool(SENDINFO(m_bWeatherEffect)), END_SEND_TABLE() BEGIN_DATADESC(CParticleSystem) DEFINE_KEYFIELD(m_bStartActive, FIELD_BOOLEAN, "start_active"), DEFINE_KEYFIELD(m_bWeatherEffect, FIELD_BOOLEAN, "flag_as_weather"), DEFINE_FIELD(m_bActive, FIELD_BOOLEAN), #ifdef MAPBASE DEFINE_FIELD(m_bDestroyImmediately, FIELD_BOOLEAN), #endif DEFINE_FIELD(m_flStartTime, FIELD_TIME), DEFINE_KEYFIELD(m_iszEffectName, FIELD_STRING, "effect_name"), //DEFINE_FIELD( m_iEffectIndex, FIELD_INTEGER ), // Don't save. Refind after loading. 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[0], FIELD_CHARACTER, "cpoint1_parent"), DEFINE_KEYFIELD(m_iControlPointParents[1], FIELD_CHARACTER, "cpoint2_parent"), DEFINE_KEYFIELD(m_iControlPointParents[2], FIELD_CHARACTER, "cpoint3_parent"), DEFINE_KEYFIELD(m_iControlPointParents[3], FIELD_CHARACTER, "cpoint4_parent"), DEFINE_KEYFIELD(m_iControlPointParents[4], FIELD_CHARACTER, "cpoint5_parent"), DEFINE_KEYFIELD(m_iControlPointParents[5], FIELD_CHARACTER, "cpoint6_parent"), DEFINE_KEYFIELD(m_iControlPointParents[6], FIELD_CHARACTER, "cpoint7_parent"), DEFINE_AUTO_ARRAY(m_hControlPointEnts, FIELD_EHANDLE), DEFINE_AUTO_ARRAY(m_vControlPointVecs, FIELD_VECTOR), DEFINE_INPUTFUNC(FIELD_VOID, "Start", InputStart), DEFINE_INPUTFUNC(FIELD_VOID, "Stop", InputStop), #ifdef MAPBASE DEFINE_INPUTFUNC(FIELD_VOID, "DestroyImmediately", InputDestroyImmediately), #endif DEFINE_THINKFUNC(StartParticleSystemThink), END_DATADESC() LINK_ENTITY_TO_CLASS(info_particle_system, CParticleSystem); LINK_ENTITY_TO_CLASS(info_particle_system_coordinate, CParticleSystemCoordinate); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CParticleSystem::CParticleSystem() { m_bWeatherEffect = false; } //----------------------------------------------------------------------------- // 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: //----------------------------------------------------------------------------- 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; #ifdef MAPBASE m_bDestroyImmediately = false; #endif // Setup our control points at this time (in case our targets weren't around at spawn time) ReadControlPointEnts(); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CParticleSystem::StopParticleSystem(void) { m_bActive = false; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CParticleSystem::InputStart(inputdata_t &inputdata) { StartParticleSystem(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CParticleSystem::InputStop(inputdata_t &inputdata) { StopParticleSystem(); } #ifdef MAPBASE //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CParticleSystem::InputDestroyImmediately(inputdata_t &inputdata) { m_bDestroyImmediately = true; StopParticleSystem(); } #endif //----------------------------------------------------------------------------- // Purpose: Find each entity referred to by m_iszControlPointNames and // resolve it into the corresponding slot in m_vControlPointVecs //----------------------------------------------------------------------------- void CParticleSystem::ReadControlPointEnts(void) { for (int i = 0; i < kMAXCONTROLPOINTS; ++i) { if (UsesCoordinates()) { float vecCoords[3]; // cast str to vector, add vector to array const char* pszVector = STRING(m_iszControlPointNames[i]); UTIL_StringToVector(vecCoords, pszVector); m_vControlPointVecs.Set(i, Vector(vecCoords[0], vecCoords[1], vecCoords[2])); } else{ 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); } } }