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.

277 lines
7.6 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implements the server side of a steam jet particle system entity.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "smokestack.h"
  9. #include "particle_light.h"
  10. #include "filesystem.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. //Networking
  14. IMPLEMENT_SERVERCLASS_ST(CSmokeStack, DT_SmokeStack)
  15. SendPropFloat(SENDINFO(m_SpreadSpeed), 0, SPROP_NOSCALE),
  16. SendPropFloat(SENDINFO(m_Speed), 0, SPROP_NOSCALE),
  17. SendPropFloat(SENDINFO(m_StartSize), 0, SPROP_NOSCALE),
  18. SendPropFloat(SENDINFO(m_EndSize), 0, SPROP_NOSCALE),
  19. SendPropFloat(SENDINFO(m_Rate), 0, SPROP_NOSCALE),
  20. SendPropFloat(SENDINFO(m_JetLength), 0, SPROP_NOSCALE),
  21. SendPropInt(SENDINFO(m_bEmit), 1, SPROP_UNSIGNED),
  22. SendPropFloat(SENDINFO(m_flBaseSpread), 0, SPROP_NOSCALE),
  23. SendPropFloat(SENDINFO( m_flRollSpeed ), 0, SPROP_NOSCALE ),
  24. // Note: the base color is specified in the smokestack entity, but the directional
  25. // and ambient light must come from env_particlelight entities.
  26. SendPropVector( SENDINFO_NOCHECK(m_DirLight.m_vPos), 0, SPROP_NOSCALE ),
  27. SendPropVector( SENDINFO_NOCHECK(m_DirLight.m_vColor), 0, SPROP_NOSCALE ),
  28. SendPropFloat( SENDINFO_NOCHECK(m_DirLight.m_flIntensity), 0, SPROP_NOSCALE ),
  29. SendPropVector( SENDINFO_NOCHECK(m_AmbientLight.m_vPos), 0, SPROP_NOSCALE ),
  30. SendPropVector( SENDINFO_NOCHECK(m_AmbientLight.m_vColor), 0, SPROP_NOSCALE ),
  31. SendPropFloat( SENDINFO_NOCHECK(m_AmbientLight.m_flIntensity), 0, SPROP_NOSCALE ),
  32. SendPropVector(SENDINFO(m_vWind), 0, SPROP_NOSCALE),
  33. SendPropFloat(SENDINFO(m_flTwist), 0, SPROP_NOSCALE),
  34. SendPropIntWithMinusOneFlag( SENDINFO(m_iMaterialModel), 16 )
  35. END_SEND_TABLE()
  36. LINK_ENTITY_TO_CLASS( env_smokestack, CSmokeStack );
  37. //Save/restore
  38. BEGIN_SIMPLE_DATADESC( CSmokeStackLightInfo )
  39. DEFINE_FIELD( m_vPos, FIELD_POSITION_VECTOR ),
  40. DEFINE_FIELD( m_vColor, FIELD_VECTOR ),
  41. DEFINE_FIELD( m_flIntensity, FIELD_FLOAT ),
  42. END_DATADESC()
  43. BEGIN_DATADESC( CSmokeStack )
  44. //Keyvalue fields
  45. DEFINE_KEYFIELD( m_StartSize, FIELD_FLOAT, "StartSize" ),
  46. DEFINE_KEYFIELD( m_EndSize, FIELD_FLOAT, "EndSize" ),
  47. DEFINE_KEYFIELD( m_InitialState, FIELD_BOOLEAN, "InitialState" ),
  48. DEFINE_KEYFIELD( m_flBaseSpread, FIELD_FLOAT, "BaseSpread" ),
  49. DEFINE_KEYFIELD( m_flTwist, FIELD_FLOAT, "Twist" ),
  50. DEFINE_KEYFIELD( m_flRollSpeed, FIELD_FLOAT, "Roll" ),
  51. DEFINE_FIELD( m_strMaterialModel, FIELD_STRING ),
  52. DEFINE_FIELD( m_iMaterialModel,FIELD_INTEGER ),
  53. DEFINE_EMBEDDED( m_AmbientLight ),
  54. DEFINE_EMBEDDED( m_DirLight ),
  55. DEFINE_KEYFIELD( m_WindAngle, FIELD_INTEGER, "WindAngle" ),
  56. DEFINE_KEYFIELD( m_WindSpeed, FIELD_INTEGER, "WindSpeed" ),
  57. //Regular fields
  58. DEFINE_FIELD( m_vWind, FIELD_VECTOR ),
  59. DEFINE_FIELD( m_bEmit, FIELD_INTEGER ),
  60. // Inputs
  61. DEFINE_INPUT( m_JetLength, FIELD_FLOAT, "JetLength" ),
  62. DEFINE_INPUT( m_SpreadSpeed, FIELD_FLOAT, "SpreadSpeed" ),
  63. DEFINE_INPUT( m_Speed, FIELD_FLOAT, "Speed" ),
  64. DEFINE_INPUT( m_Rate, FIELD_FLOAT, "Rate" ),
  65. DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ),
  66. DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
  67. DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
  68. END_DATADESC()
  69. //-----------------------------------------------------------------------------
  70. // Purpose: Called before spawning, after key values have been set.
  71. //-----------------------------------------------------------------------------
  72. CSmokeStack::CSmokeStack()
  73. {
  74. memset( &m_AmbientLight, 0, sizeof(m_AmbientLight) );
  75. memset( &m_DirLight, 0, sizeof(m_DirLight) );
  76. IMPLEMENT_NETWORKVAR_CHAIN( &m_AmbientLight );
  77. IMPLEMENT_NETWORKVAR_CHAIN( &m_DirLight );
  78. m_flTwist = 0;
  79. SetRenderColor( 0, 0, 0 );
  80. SetRenderAlpha( 255 );
  81. m_vWind.GetForModify().Init();
  82. m_WindAngle = m_WindSpeed = 0;
  83. m_iMaterialModel = -1;
  84. m_flRollSpeed = 0.0f;
  85. }
  86. CSmokeStack::~CSmokeStack()
  87. {
  88. }
  89. void CSmokeStack::Spawn( void )
  90. {
  91. if ( m_InitialState )
  92. {
  93. m_bEmit = true;
  94. }
  95. }
  96. void CSmokeStack::Activate()
  97. {
  98. DetectInSkybox();
  99. bool bGotDirLight = false;
  100. // Find local lights.
  101. CBaseEntity *pTestEnt = NULL;
  102. while ( 1 )
  103. {
  104. pTestEnt = gEntList.FindEntityByClassname( pTestEnt, PARTICLELIGHT_ENTNAME );
  105. if ( !pTestEnt )
  106. break;
  107. CParticleLight *pLight = (CParticleLight*)pTestEnt;
  108. if( !FStrEq( STRING(GetEntityName()), STRING(pLight->m_PSName) ) )
  109. continue;
  110. CSmokeStackLightInfo *pInfo = &m_AmbientLight;
  111. if ( pLight->m_bDirectional )
  112. {
  113. bGotDirLight = true;
  114. pInfo = &m_DirLight;
  115. }
  116. pInfo->m_flIntensity = pLight->m_flIntensity;
  117. pInfo->m_vColor = pLight->m_vColor;
  118. pInfo->m_vPos = pLight->GetAbsOrigin();
  119. }
  120. // Put our light colors in 0-1 space.
  121. m_AmbientLight.m_vColor.GetForModify() /= 255.0f;
  122. m_DirLight.m_vColor.GetForModify() /= 255.0f;
  123. BaseClass::Activate();
  124. // Legacy support..
  125. if ( m_iMaterialModel == -1 )
  126. m_iMaterialModel = PrecacheModel( "particle/SmokeStack.vmt" );
  127. }
  128. bool CSmokeStack::KeyValue( const char *szKeyName, const char *szValue )
  129. {
  130. if( stricmp( szKeyName, "Wind" ) == 0 )
  131. {
  132. sscanf( szValue, "%f %f %f", &m_vWind.GetForModify().x, &m_vWind.GetForModify().y, &m_vWind.GetForModify().z );
  133. return true;
  134. }
  135. else if( stricmp( szKeyName, "WindAngle" ) == 0 )
  136. {
  137. m_WindAngle = atoi( szValue );
  138. RecalcWindVector();
  139. return true;
  140. }
  141. else if( stricmp( szKeyName, "WindSpeed" ) == 0 )
  142. {
  143. m_WindSpeed = atoi( szValue );
  144. RecalcWindVector();
  145. return true;
  146. }
  147. else if ( stricmp( szKeyName, "SmokeMaterial" ) == 0 )
  148. {
  149. // Make sure we have a vmt extension.
  150. if ( Q_stristr( szValue, ".vmt" ) )
  151. {
  152. m_strMaterialModel = AllocPooledString( szValue );
  153. }
  154. else
  155. {
  156. char str[512];
  157. Q_snprintf( str, sizeof( str ), "%s.vmt", szValue );
  158. m_strMaterialModel = AllocPooledString( str );
  159. }
  160. const char *pName = STRING( m_strMaterialModel );
  161. char szStrippedName[512];
  162. m_iMaterialModel = PrecacheModel( pName );
  163. Q_StripExtension( pName, szStrippedName, Q_strlen(pName)+1 );
  164. int iLength = Q_strlen( szStrippedName );
  165. szStrippedName[iLength-1] = '\0';
  166. int iCount = 1;
  167. char str[512];
  168. Q_snprintf( str, sizeof( str ), "%s%d.vmt", szStrippedName, iCount );
  169. while ( filesystem->FileExists( UTIL_VarArgs( "materials/%s", str ) ) )
  170. {
  171. PrecacheModel( str );
  172. iCount++;
  173. Q_snprintf( str, sizeof( str ), "%s%d.vmt", szStrippedName, iCount );
  174. }
  175. return true;
  176. }
  177. else
  178. {
  179. return BaseClass::KeyValue( szKeyName, szValue );
  180. }
  181. }
  182. void CSmokeStack::Precache()
  183. {
  184. m_iMaterialModel = PrecacheModel( STRING( m_strMaterialModel ) );
  185. BaseClass::Precache();
  186. }
  187. //-----------------------------------------------------------------------------
  188. // Purpose: Input handler for toggling the steam jet on/off.
  189. //-----------------------------------------------------------------------------
  190. void CSmokeStack::InputToggle( inputdata_t &inputdata )
  191. {
  192. m_bEmit = !m_bEmit;
  193. }
  194. //-----------------------------------------------------------------------------
  195. // Purpose: Input handler for turning on the steam jet.
  196. //-----------------------------------------------------------------------------
  197. void CSmokeStack::InputTurnOn( inputdata_t &inputdata )
  198. {
  199. m_bEmit = true;
  200. }
  201. //-----------------------------------------------------------------------------
  202. // Purpose: Input handler for turning off the steam jet.
  203. //-----------------------------------------------------------------------------
  204. void CSmokeStack::InputTurnOff( inputdata_t &inputdata )
  205. {
  206. m_bEmit = false;
  207. }
  208. void CSmokeStack::RecalcWindVector()
  209. {
  210. m_vWind = Vector(
  211. cos( DEG2RAD( (float)m_WindAngle ) ) * m_WindSpeed,
  212. sin( DEG2RAD( (float)m_WindAngle ) ) * m_WindSpeed,
  213. 0 );
  214. }