Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

338 lines
15 KiB

  1. //====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose: An entity that spawns and controls a particle system
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "particles/particles.h"
  8. #include "networkstringtable_gamedll.h"
  9. #include "particle_system.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID );
  13. extern void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID );
  14. // Stripped down CBaseEntity send table
  15. IMPLEMENT_SERVERCLASS_ST_NOBASE(CParticleSystem, DT_ParticleSystem)
  16. SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ),
  17. SendPropInt (SENDINFO(m_fEffects), EF_MAX_BITS, SPROP_UNSIGNED), // need to network this so we get the appropriate render flags
  18. SendPropEHandle (SENDINFO(m_hOwnerEntity)),
  19. SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)),
  20. SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED),
  21. SendPropQAngles (SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles ),
  22. SendPropInt( SENDINFO(m_iEffectIndex), MAX_PARTICLESYSTEMS_STRING_BITS, SPROP_UNSIGNED ),
  23. SendPropBool( SENDINFO(m_bActive) ),
  24. SendPropInt( SENDINFO( m_nStopType ), Q_log2(CParticleSystem::NUM_STOP_TYPES)+1, SPROP_UNSIGNED ),
  25. SendPropFloat( SENDINFO(m_flStartTime) ),
  26. SendPropString( SENDINFO(m_szSnapshotFileName) ),
  27. SendPropArray3( SENDINFO_ARRAY3(m_vServerControlPoints), SendPropVector(SENDINFO_ARRAY(m_vServerControlPoints)) ),
  28. SendPropArray3( SENDINFO_ARRAY3(m_iServerControlPointAssignments), SendPropInt(SENDINFO_ARRAY(m_iServerControlPointAssignments), -1, SPROP_UNSIGNED ) ),
  29. SendPropArray3( SENDINFO_ARRAY3(m_hControlPointEnts), SendPropEHandle( SENDINFO_ARRAY(m_hControlPointEnts) ) ),
  30. SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ),
  31. END_SEND_TABLE()
  32. BEGIN_DATADESC( CParticleSystem )
  33. DEFINE_KEYFIELD( m_bStartActive, FIELD_BOOLEAN, "start_active" ),
  34. DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ),
  35. DEFINE_FIELD( m_flStartTime, FIELD_TIME ),
  36. DEFINE_ARRAY( m_vServerControlPoints, FIELD_VECTOR, CParticleSystem::kSERVERCONTROLLEDPOINTS ),
  37. DEFINE_ARRAY( m_iServerControlPointAssignments, FIELD_CHARACTER, CParticleSystem::kSERVERCONTROLLEDPOINTS ),
  38. DEFINE_KEYFIELD( m_iszEffectName, FIELD_STRING, "effect_name" ),
  39. //DEFINE_FIELD( m_iEffectIndex, FIELD_INTEGER ), // Don't save. Refind after loading.
  40. DEFINE_AUTO_ARRAY_KEYFIELD( m_szSnapshotFileName, FIELD_CHARACTER, "snapshot_file" ),
  41. DEFINE_KEYFIELD( m_iszControlPointNames[0], FIELD_STRING, "cpoint1" ),
  42. DEFINE_KEYFIELD( m_iszControlPointNames[1], FIELD_STRING, "cpoint2" ),
  43. DEFINE_KEYFIELD( m_iszControlPointNames[2], FIELD_STRING, "cpoint3" ),
  44. DEFINE_KEYFIELD( m_iszControlPointNames[3], FIELD_STRING, "cpoint4" ),
  45. DEFINE_KEYFIELD( m_iszControlPointNames[4], FIELD_STRING, "cpoint5" ),
  46. DEFINE_KEYFIELD( m_iszControlPointNames[5], FIELD_STRING, "cpoint6" ),
  47. DEFINE_KEYFIELD( m_iszControlPointNames[6], FIELD_STRING, "cpoint7" ),
  48. DEFINE_KEYFIELD( m_iszControlPointNames[7], FIELD_STRING, "cpoint8" ),
  49. DEFINE_KEYFIELD( m_iszControlPointNames[8], FIELD_STRING, "cpoint9" ),
  50. DEFINE_KEYFIELD( m_iszControlPointNames[9], FIELD_STRING, "cpoint10" ),
  51. DEFINE_KEYFIELD( m_iszControlPointNames[10], FIELD_STRING, "cpoint11" ),
  52. DEFINE_KEYFIELD( m_iszControlPointNames[11], FIELD_STRING, "cpoint12" ),
  53. DEFINE_KEYFIELD( m_iszControlPointNames[12], FIELD_STRING, "cpoint13" ),
  54. DEFINE_KEYFIELD( m_iszControlPointNames[13], FIELD_STRING, "cpoint14" ),
  55. DEFINE_KEYFIELD( m_iszControlPointNames[14], FIELD_STRING, "cpoint15" ),
  56. DEFINE_KEYFIELD( m_iszControlPointNames[15], FIELD_STRING, "cpoint16" ),
  57. DEFINE_KEYFIELD( m_iszControlPointNames[16], FIELD_STRING, "cpoint17" ),
  58. DEFINE_KEYFIELD( m_iszControlPointNames[17], FIELD_STRING, "cpoint18" ),
  59. DEFINE_KEYFIELD( m_iszControlPointNames[18], FIELD_STRING, "cpoint19" ),
  60. DEFINE_KEYFIELD( m_iszControlPointNames[19], FIELD_STRING, "cpoint20" ),
  61. DEFINE_KEYFIELD( m_iszControlPointNames[20], FIELD_STRING, "cpoint21" ),
  62. DEFINE_KEYFIELD( m_iszControlPointNames[21], FIELD_STRING, "cpoint22" ),
  63. DEFINE_KEYFIELD( m_iszControlPointNames[22], FIELD_STRING, "cpoint23" ),
  64. DEFINE_KEYFIELD( m_iszControlPointNames[23], FIELD_STRING, "cpoint24" ),
  65. DEFINE_KEYFIELD( m_iszControlPointNames[24], FIELD_STRING, "cpoint25" ),
  66. DEFINE_KEYFIELD( m_iszControlPointNames[25], FIELD_STRING, "cpoint26" ),
  67. DEFINE_KEYFIELD( m_iszControlPointNames[26], FIELD_STRING, "cpoint27" ),
  68. DEFINE_KEYFIELD( m_iszControlPointNames[27], FIELD_STRING, "cpoint28" ),
  69. DEFINE_KEYFIELD( m_iszControlPointNames[28], FIELD_STRING, "cpoint29" ),
  70. DEFINE_KEYFIELD( m_iszControlPointNames[29], FIELD_STRING, "cpoint30" ),
  71. DEFINE_KEYFIELD( m_iszControlPointNames[30], FIELD_STRING, "cpoint31" ),
  72. DEFINE_KEYFIELD( m_iszControlPointNames[31], FIELD_STRING, "cpoint32" ),
  73. DEFINE_KEYFIELD( m_iszControlPointNames[32], FIELD_STRING, "cpoint33" ),
  74. DEFINE_KEYFIELD( m_iszControlPointNames[33], FIELD_STRING, "cpoint34" ),
  75. DEFINE_KEYFIELD( m_iszControlPointNames[34], FIELD_STRING, "cpoint35" ),
  76. DEFINE_KEYFIELD( m_iszControlPointNames[35], FIELD_STRING, "cpoint36" ),
  77. DEFINE_KEYFIELD( m_iszControlPointNames[36], FIELD_STRING, "cpoint37" ),
  78. DEFINE_KEYFIELD( m_iszControlPointNames[37], FIELD_STRING, "cpoint38" ),
  79. DEFINE_KEYFIELD( m_iszControlPointNames[38], FIELD_STRING, "cpoint39" ),
  80. DEFINE_KEYFIELD( m_iszControlPointNames[39], FIELD_STRING, "cpoint40" ),
  81. DEFINE_KEYFIELD( m_iszControlPointNames[40], FIELD_STRING, "cpoint41" ),
  82. DEFINE_KEYFIELD( m_iszControlPointNames[41], FIELD_STRING, "cpoint42" ),
  83. DEFINE_KEYFIELD( m_iszControlPointNames[42], FIELD_STRING, "cpoint43" ),
  84. DEFINE_KEYFIELD( m_iszControlPointNames[43], FIELD_STRING, "cpoint44" ),
  85. DEFINE_KEYFIELD( m_iszControlPointNames[44], FIELD_STRING, "cpoint45" ),
  86. DEFINE_KEYFIELD( m_iszControlPointNames[45], FIELD_STRING, "cpoint46" ),
  87. DEFINE_KEYFIELD( m_iszControlPointNames[46], FIELD_STRING, "cpoint47" ),
  88. DEFINE_KEYFIELD( m_iszControlPointNames[47], FIELD_STRING, "cpoint48" ),
  89. DEFINE_KEYFIELD( m_iszControlPointNames[48], FIELD_STRING, "cpoint49" ),
  90. DEFINE_KEYFIELD( m_iszControlPointNames[49], FIELD_STRING, "cpoint50" ),
  91. DEFINE_KEYFIELD( m_iszControlPointNames[50], FIELD_STRING, "cpoint51" ),
  92. DEFINE_KEYFIELD( m_iszControlPointNames[51], FIELD_STRING, "cpoint52" ),
  93. DEFINE_KEYFIELD( m_iszControlPointNames[52], FIELD_STRING, "cpoint53" ),
  94. DEFINE_KEYFIELD( m_iszControlPointNames[53], FIELD_STRING, "cpoint54" ),
  95. DEFINE_KEYFIELD( m_iszControlPointNames[54], FIELD_STRING, "cpoint55" ),
  96. DEFINE_KEYFIELD( m_iszControlPointNames[55], FIELD_STRING, "cpoint56" ),
  97. DEFINE_KEYFIELD( m_iszControlPointNames[56], FIELD_STRING, "cpoint57" ),
  98. DEFINE_KEYFIELD( m_iszControlPointNames[57], FIELD_STRING, "cpoint58" ),
  99. DEFINE_KEYFIELD( m_iszControlPointNames[58], FIELD_STRING, "cpoint59" ),
  100. DEFINE_KEYFIELD( m_iszControlPointNames[59], FIELD_STRING, "cpoint60" ),
  101. DEFINE_KEYFIELD( m_iszControlPointNames[60], FIELD_STRING, "cpoint61" ),
  102. DEFINE_KEYFIELD( m_iszControlPointNames[61], FIELD_STRING, "cpoint62" ),
  103. DEFINE_KEYFIELD( m_iszControlPointNames[62], FIELD_STRING, "cpoint63" ),
  104. DEFINE_KEYFIELD( m_iControlPointParents.m_Value[0], FIELD_CHARACTER, "cpoint1_parent" ),
  105. DEFINE_KEYFIELD( m_iControlPointParents.m_Value[1], FIELD_CHARACTER, "cpoint2_parent" ),
  106. DEFINE_KEYFIELD( m_iControlPointParents.m_Value[2], FIELD_CHARACTER, "cpoint3_parent" ),
  107. DEFINE_KEYFIELD( m_iControlPointParents.m_Value[3], FIELD_CHARACTER, "cpoint4_parent" ),
  108. DEFINE_KEYFIELD( m_iControlPointParents.m_Value[4], FIELD_CHARACTER, "cpoint5_parent" ),
  109. DEFINE_KEYFIELD( m_iControlPointParents.m_Value[5], FIELD_CHARACTER, "cpoint6_parent" ),
  110. DEFINE_KEYFIELD( m_iControlPointParents.m_Value[6], FIELD_CHARACTER, "cpoint7_parent" ),
  111. DEFINE_AUTO_ARRAY( m_hControlPointEnts, FIELD_EHANDLE ),
  112. DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ),
  113. DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ),
  114. DEFINE_INPUTFUNC( FIELD_VOID, "StopPlayEndCap", InputStopEndCap ),
  115. DEFINE_INPUTFUNC( FIELD_VOID, "DestroyImmediately", InputDestroy ),
  116. DEFINE_THINKFUNC( StartParticleSystemThink ),
  117. END_DATADESC()
  118. LINK_ENTITY_TO_CLASS( info_particle_system, CParticleSystem );
  119. CParticleSystem::CParticleSystem( void ) : m_bNoSave( false )
  120. {
  121. for( int i = 0; i != kSERVERCONTROLLEDPOINTS; ++i )
  122. {
  123. m_iServerControlPointAssignments.GetForModify(i) = 255;
  124. }
  125. }
  126. //-----------------------------------------------------------------------------
  127. // Precache
  128. //-----------------------------------------------------------------------------
  129. void CParticleSystem::Precache( void )
  130. {
  131. const char *pParticleSystemName = STRING( m_iszEffectName );
  132. if ( pParticleSystemName == NULL || pParticleSystemName[0] == 0 )
  133. {
  134. Warning( "info_particle_system (%s) has no particle system name specified!\n", GetEntityName().ToCStr() );
  135. }
  136. PrecacheParticleSystem( pParticleSystemName );
  137. }
  138. //-----------------------------------------------------------------------------
  139. // Purpose:
  140. //-----------------------------------------------------------------------------
  141. void CParticleSystem::Spawn( void )
  142. {
  143. BaseClass::Spawn();
  144. Precache();
  145. m_iEffectIndex = -1;
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Purpose:
  149. //-----------------------------------------------------------------------------
  150. void CParticleSystem::Activate( void )
  151. {
  152. BaseClass::Activate();
  153. // Find our particle effect index
  154. m_iEffectIndex = GetParticleSystemIndex( STRING(m_iszEffectName) );
  155. if ( m_bStartActive )
  156. {
  157. m_bStartActive = false;
  158. StartParticleSystem();
  159. }
  160. }
  161. //-----------------------------------------------------------------------------
  162. // Purpose:
  163. //-----------------------------------------------------------------------------
  164. bool CParticleSystem::KeyValue( const char *szKeyName, const char *szValue )
  165. {
  166. if ( FStrEq( szKeyName, "snapshot_file" ) )
  167. {
  168. Q_strncpy( m_szSnapshotFileName.GetForModify(), szValue, MAX_PATH );
  169. return true;
  170. }
  171. return BaseClass::KeyValue( szKeyName, szValue );
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Purpose:
  175. //-----------------------------------------------------------------------------
  176. bool CParticleSystem::GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen )
  177. {
  178. if ( FStrEq( szKeyName, "snapshot_file" ) )
  179. {
  180. Q_snprintf( szValue, iMaxLen, "%s", m_szSnapshotFileName.Get() );
  181. return true;
  182. }
  183. return BaseClass::GetKeyValue( szKeyName, szValue, iMaxLen );
  184. }
  185. //-----------------------------------------------------------------------------
  186. // Purpose:
  187. //-----------------------------------------------------------------------------
  188. void CParticleSystem::StartParticleSystemThink( void )
  189. {
  190. StartParticleSystem();
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Purpose: Always transmitted to clients
  194. //-----------------------------------------------------------------------------
  195. int CParticleSystem::UpdateTransmitState()
  196. {
  197. return SetTransmitState( FL_EDICT_ALWAYS );
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Purpose:
  201. //-----------------------------------------------------------------------------
  202. void CParticleSystem::StartParticleSystem( void )
  203. {
  204. if ( m_bActive == false )
  205. {
  206. m_flStartTime = gpGlobals->curtime;
  207. m_bActive = true;
  208. // Setup our control points at this time (in case our targets weren't around at spawn time)
  209. ReadControlPointEnts();
  210. }
  211. }
  212. //-----------------------------------------------------------------------------
  213. // Purpose:
  214. //-----------------------------------------------------------------------------
  215. void CParticleSystem::StopParticleSystem( int nStopType )
  216. {
  217. m_bActive = false;
  218. m_nStopType = nStopType;
  219. }
  220. //-----------------------------------------------------------------------------
  221. // Purpose:
  222. //-----------------------------------------------------------------------------
  223. void CParticleSystem::InputStart( inputdata_t &inputdata )
  224. {
  225. StartParticleSystem();
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Purpose:
  229. //-----------------------------------------------------------------------------
  230. void CParticleSystem::InputStop( inputdata_t &inputdata )
  231. {
  232. StopParticleSystem( STOP_NORMAL );
  233. }
  234. void CParticleSystem::InputDestroy( inputdata_t &inputdata )
  235. {
  236. StopParticleSystem( STOP_DESTROY_IMMEDIATELY );
  237. }
  238. void CParticleSystem::InputStopEndCap( inputdata_t &inputdata )
  239. {
  240. StopParticleSystem( STOP_PLAY_ENDCAP );
  241. }
  242. //-----------------------------------------------------------------------------
  243. // Purpose: Find each entity referred to by m_iszControlPointNames and
  244. // resolve it into the corresponding slot in m_hControlPointEnts
  245. //-----------------------------------------------------------------------------
  246. void CParticleSystem::ReadControlPointEnts( void )
  247. {
  248. for ( int i = 0 ; i < kMAXCONTROLPOINTS; ++i )
  249. {
  250. if ( m_iszControlPointNames[i] == NULL_STRING )
  251. continue;
  252. CBaseEntity *pPointEnt = gEntList.FindEntityGeneric( NULL, STRING( m_iszControlPointNames[i] ), this );
  253. Assert( pPointEnt != NULL );
  254. if ( pPointEnt == NULL )
  255. {
  256. Warning("Particle system %s could not find control point entity (%s)\n", GetEntityName().ToCStr(), m_iszControlPointNames[i].ToCStr() );
  257. continue;
  258. }
  259. m_hControlPointEnts.Set( i, pPointEnt );
  260. }
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Purpose: Try to allocate one of the server controlled control points to
  264. // hold the value. Designed to let the server funnel some variables to
  265. // particle systems (size, color, swirliness, ...)
  266. //-----------------------------------------------------------------------------
  267. bool CParticleSystem::SetControlPointValue( int iControlPoint, const Vector &vValue )
  268. {
  269. for( int i = 0; i != kSERVERCONTROLLEDPOINTS; ++i )
  270. {
  271. if( m_iServerControlPointAssignments[i] == iControlPoint )
  272. {
  273. m_vServerControlPoints.GetForModify(i) = vValue;
  274. return true;
  275. }
  276. if( m_iServerControlPointAssignments[i] == 255 )
  277. {
  278. m_iServerControlPointAssignments.GetForModify(i) = iControlPoint;
  279. m_vServerControlPoints.GetForModify(i) = vValue;
  280. return true;
  281. }
  282. }
  283. Warning( "No free server controlled control points.\n" );
  284. return false; //already using up all of our server control points
  285. }
  286. //-----------------------------------------------------------------------------
  287. // Inline methods
  288. //-----------------------------------------------------------------------------
  289. int CParticleSystem::ObjectCaps( void )
  290. {
  291. int flags = 0;
  292. if ( m_bNoSave )
  293. flags = FCAP_DONT_SAVE;
  294. return BaseClass::ObjectCaps() | flags;
  295. }