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.

487 lines
12 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "particles_simple.h"
  9. #include "tempent.h"
  10. #include "iefx.h"
  11. #include "decals.h"
  12. #include "iviewrender.h"
  13. #include "engine/ivmodelinfo.h"
  14. #include "view.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. #define NUM_CHILD_FLAMES 6
  18. #define CHILD_SPREAD 40
  19. //==================================================
  20. // C_Plasma
  21. //==================================================
  22. //NOTENOTE: Mirrored in dlls/fire_smoke.h
  23. #define bitsFIRESMOKE_NONE 0x00000000
  24. #define bitsFIRESMOKE_ACTIVE 0x00000001
  25. class C_PlasmaSprite : public C_Sprite
  26. {
  27. DECLARE_CLASS( C_PlasmaSprite, C_Sprite );
  28. public:
  29. Vector m_vecMoveDir;
  30. };
  31. class C_Plasma : public C_BaseEntity
  32. {
  33. public:
  34. DECLARE_CLIENTCLASS();
  35. DECLARE_CLASS( C_Plasma, C_BaseEntity );
  36. C_Plasma();
  37. ~C_Plasma();
  38. bool Simulate( void );
  39. protected:
  40. void Update( void );
  41. void UpdateAnimation( void );
  42. void UpdateScale( void );
  43. void UpdateFlames( void );
  44. void AddFlames( void );
  45. void Start( void );
  46. float GetFlickerScale( void );
  47. //C_BaseEntity
  48. public:
  49. virtual void OnDataChanged( DataUpdateType_t updateType );
  50. virtual bool ShouldDraw();
  51. //From the server
  52. public:
  53. float m_flStartScale;
  54. float m_flScale;
  55. float m_flScaleTime;
  56. int m_nFlags;
  57. int m_nPlasmaModelIndex;
  58. int m_nPlasmaModelIndex2;
  59. int m_nGlowModelIndex;
  60. //Client-side only
  61. public:
  62. float m_flScaleRegister;
  63. float m_flScaleStart;
  64. float m_flScaleEnd;
  65. float m_flScaleTimeStart;
  66. float m_flScaleTimeEnd;
  67. VPlane m_planeClip;
  68. bool m_bClipTested;
  69. protected:
  70. C_PlasmaSprite m_entFlames[NUM_CHILD_FLAMES];
  71. float m_entFlameScales[NUM_CHILD_FLAMES];
  72. C_Sprite m_entGlow;
  73. float m_flGlowScale;
  74. TimedEvent m_tParticleSpawn;
  75. TimedEvent m_tDecalSpawn;
  76. private:
  77. C_Plasma( const C_Plasma & );
  78. };
  79. //-----------------------------------------------------------------------------
  80. // Purpose:
  81. // Input : *pRecvProp -
  82. // *pStruct -
  83. // *pVarData -
  84. // *pIn -
  85. // objectID -
  86. //-----------------------------------------------------------------------------
  87. void RecvProxy_PlasmaScale( const CRecvProxyData *pData, void *pStruct, void *pOut )
  88. {
  89. C_Plasma *pPlasmaSmoke = (C_Plasma *) pStruct;
  90. float scale = pData->m_Value.m_Float;
  91. //If changed, update our internal information
  92. if ( pPlasmaSmoke->m_flScale != scale )
  93. {
  94. pPlasmaSmoke->m_flScaleStart = pPlasmaSmoke->m_flScaleRegister;
  95. pPlasmaSmoke->m_flScaleEnd = scale;
  96. pPlasmaSmoke->m_flScale = scale;
  97. }
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Purpose:
  101. // Input : *pRecvProp -
  102. // *pStruct -
  103. // *pVarData -
  104. // *pIn -
  105. // objectID -
  106. //-----------------------------------------------------------------------------
  107. void RecvProxy_PlasmaScaleTime( const CRecvProxyData *pData, void *pStruct, void *pOut )
  108. {
  109. C_Plasma *pPlasmaSmoke = (C_Plasma *) pStruct;
  110. float time = pData->m_Value.m_Float;
  111. //If changed, update our internal information
  112. if ( pPlasmaSmoke->m_flScaleTime != time )
  113. {
  114. if ( time == -1.0f )
  115. {
  116. pPlasmaSmoke->m_flScaleTimeStart = gpGlobals->curtime-1.0f;
  117. pPlasmaSmoke->m_flScaleTimeEnd = pPlasmaSmoke->m_flScaleTimeStart;
  118. }
  119. else
  120. {
  121. pPlasmaSmoke->m_flScaleTimeStart = gpGlobals->curtime;
  122. pPlasmaSmoke->m_flScaleTimeEnd = gpGlobals->curtime + time;
  123. }
  124. pPlasmaSmoke->m_flScaleTime = time;
  125. }
  126. }
  127. //Receive datatable
  128. IMPLEMENT_CLIENTCLASS_DT( C_Plasma, DT_Plasma, CPlasma )
  129. RecvPropFloat( RECVINFO( m_flStartScale )),
  130. RecvPropFloat( RECVINFO( m_flScale ), 0, RecvProxy_PlasmaScale ),
  131. RecvPropFloat( RECVINFO( m_flScaleTime ), 0, RecvProxy_PlasmaScaleTime ),
  132. RecvPropInt( RECVINFO( m_nFlags ) ),
  133. RecvPropInt( RECVINFO( m_nPlasmaModelIndex ) ),
  134. RecvPropInt( RECVINFO( m_nPlasmaModelIndex2 ) ),
  135. RecvPropInt( RECVINFO( m_nGlowModelIndex ) ),
  136. END_RECV_TABLE()
  137. //==================================================
  138. // C_Plasma
  139. //==================================================
  140. C_Plasma::C_Plasma()
  141. {
  142. //Server-side
  143. m_flStartScale = 0.0f;
  144. m_flScale = 0.0f;
  145. m_flScaleTime = 0.0f;
  146. m_nFlags = bitsFIRESMOKE_NONE;
  147. m_nPlasmaModelIndex = 0;
  148. m_nPlasmaModelIndex2 = 0;
  149. m_nGlowModelIndex = 0;
  150. //Client-side
  151. m_flScaleRegister = 0.0f;
  152. m_flScaleStart = 0.0f;
  153. m_flScaleEnd = 0.0f;
  154. m_flScaleTimeStart = 0.0f;
  155. m_flScaleTimeEnd = 0.0f;
  156. m_flGlowScale = 0.0f;
  157. m_bClipTested = false;
  158. m_entGlow.Clear();
  159. //Clear all child flames
  160. for ( int i = 0; i < NUM_CHILD_FLAMES; i++ )
  161. {
  162. m_entFlames[i].Clear();
  163. }
  164. AddToEntityList(ENTITY_LIST_SIMULATE);
  165. }
  166. C_Plasma::~C_Plasma()
  167. {
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Purpose:
  171. // Output : float
  172. //-----------------------------------------------------------------------------
  173. float C_Plasma::GetFlickerScale( void )
  174. {
  175. float result = 0.0f;
  176. result = sin( gpGlobals->curtime * 10000.0f );
  177. result += 0.5f * sin( gpGlobals->curtime * 2000.0f );
  178. result -= 0.5f * cos( gpGlobals->curtime * 8000.0f );
  179. return result * 0.1f;
  180. }
  181. //-----------------------------------------------------------------------------
  182. // Purpose:
  183. //-----------------------------------------------------------------------------
  184. bool C_Plasma::Simulate( void )
  185. {
  186. //Only do this if we're active
  187. if ( ( m_nFlags & bitsFIRESMOKE_ACTIVE ) == false )
  188. return false;
  189. Update();
  190. AddFlames();
  191. float dScale = m_flScaleRegister - m_flGlowScale;
  192. m_flGlowScale = m_flScaleRegister;
  193. // Note: Sprite renderer assumes scale of 0.0 is 1.0
  194. m_entGlow.SetScale( MAX( 0.0000001f, (m_flScaleRegister*1.5f) + GetFlickerScale() ) );
  195. m_entGlow.SetLocalOriginDim( Z_INDEX, m_entGlow.GetLocalOriginDim( Z_INDEX ) + ( dScale * 32.0f ) );
  196. return true;
  197. }
  198. #define FLAME_ALPHA_START 0.8f
  199. #define FLAME_ALPHA_END 1.0f
  200. #define FLAME_TRANS_START 0.75f
  201. //-----------------------------------------------------------------------------
  202. // Purpose:
  203. //-----------------------------------------------------------------------------
  204. void C_Plasma::AddFlames( void )
  205. {
  206. Vector viewDir = GetAbsOrigin() - CurrentViewOrigin();
  207. VectorNormalize(viewDir);
  208. float dot = viewDir.Dot( Vector( 0, 0, 1 ) ); //NOTENOTE: Flames always point up
  209. float alpha = 1.0f;
  210. dot = fabs( dot );
  211. if ( dot < FLAME_ALPHA_START )
  212. {
  213. alpha = 1.0f;
  214. }
  215. for ( int i = 0; i < NUM_CHILD_FLAMES; i++ )
  216. {
  217. if ( m_entFlames[i].GetScale() > 0.0f )
  218. {
  219. m_entFlames[i].SetRenderColor( ( 255.0f * alpha ), ( 255.0f * alpha ), ( 255.0f * alpha ) );
  220. m_entFlames[i].SetBrightness( 255.0f * alpha );
  221. }
  222. m_entFlames[i].AddToLeafSystem( false );
  223. }
  224. }
  225. //-----------------------------------------------------------------------------
  226. // Purpose:
  227. // Input : bnewentity -
  228. //-----------------------------------------------------------------------------
  229. void C_Plasma::OnDataChanged( DataUpdateType_t updateType )
  230. {
  231. C_BaseEntity::OnDataChanged( updateType );
  232. if ( updateType == DATA_UPDATE_CREATED )
  233. {
  234. Start();
  235. }
  236. if ( m_nFlags & bitsFIRESMOKE_ACTIVE )
  237. {
  238. AddToEntityList(ENTITY_LIST_SIMULATE);
  239. }
  240. }
  241. //-----------------------------------------------------------------------------
  242. // Purpose:
  243. // Output : Returns true on success, false on failure.
  244. //-----------------------------------------------------------------------------
  245. bool C_Plasma::ShouldDraw()
  246. {
  247. return true;
  248. }
  249. //-----------------------------------------------------------------------------
  250. // Purpose:
  251. //-----------------------------------------------------------------------------
  252. void C_Plasma::Start( void )
  253. {
  254. //Various setup info
  255. m_tParticleSpawn.Init( 10.0f );
  256. m_tDecalSpawn.Init( 20.0f);
  257. QAngle offset;
  258. int maxFrames;
  259. // Setup the child flames
  260. int i;
  261. for ( i = 0; i < NUM_CHILD_FLAMES; i++ )
  262. {
  263. //Setup our offset angles
  264. offset[0] = 0.0f;
  265. offset[1] = random->RandomFloat( 0, 360 );
  266. offset[2] = 0.0f;
  267. AngleVectors( offset, &m_entFlames[i].m_vecMoveDir );
  268. int nModelIndex = ( i % 2 ) ? m_nPlasmaModelIndex : m_nPlasmaModelIndex2;
  269. model_t *pModel = (model_t *) modelinfo->GetModel( nModelIndex );
  270. maxFrames = modelinfo->GetModelFrameCount( pModel );
  271. // Setup all the information for the client entity
  272. m_entFlames[i].SetModelByIndex( nModelIndex );
  273. m_entFlames[i].SetLocalOrigin( GetLocalOrigin() );
  274. m_entFlames[i].m_flFrame = random->RandomInt( 0.0f, maxFrames );
  275. m_entFlames[i].m_flSpriteFramerate = (float) random->RandomInt( 15, 20 );
  276. m_entFlames[i].SetScale( m_flStartScale );
  277. m_entFlames[i].SetRenderMode( kRenderTransAddFrameBlend );
  278. m_entFlames[i].SetRenderFX( kRenderFxNone );
  279. m_entFlames[i].SetRenderColor( 255, 255, 255 );
  280. m_entFlames[i].SetRenderAlpha( 255 );
  281. m_entFlames[i].SetBrightness( 255 );
  282. m_entFlames[i].index = -1;
  283. if ( i == 0 )
  284. {
  285. m_entFlameScales[i] = 1.0f;
  286. }
  287. else
  288. {
  289. //Keep a scale offset
  290. m_entFlameScales[i] = 1.0f - ( ( (float) i / (float) NUM_CHILD_FLAMES ) );
  291. }
  292. }
  293. // Setup the glow
  294. m_entGlow.SetModelByIndex( m_nGlowModelIndex );
  295. m_entGlow.SetLocalOrigin( GetLocalOrigin() );
  296. m_entGlow.SetScale( m_flStartScale );
  297. m_entGlow.SetRenderMode( kRenderTransAdd );
  298. m_entGlow.SetRenderFX( kRenderFxNone );
  299. m_entGlow.SetRenderColor( 255, 255, 255 );
  300. m_entGlow.SetRenderAlpha( 255 );
  301. m_entGlow.SetBrightness( 255 );
  302. m_entGlow.index = -1;
  303. m_flGlowScale = m_flStartScale;
  304. m_entGlow.AddToLeafSystem( false );
  305. for( i=0; i < NUM_CHILD_FLAMES; i++ )
  306. {
  307. m_entFlames[i].AddToLeafSystem( false );
  308. }
  309. }
  310. //-----------------------------------------------------------------------------
  311. // Purpose:
  312. //-----------------------------------------------------------------------------
  313. void C_Plasma::UpdateAnimation( void )
  314. {
  315. int numFrames;
  316. float frametime = gpGlobals->frametime;
  317. for ( int i = 0; i < NUM_CHILD_FLAMES; i++ )
  318. {
  319. m_entFlames[i].m_flFrame += m_entFlames[i].m_flSpriteFramerate * frametime;
  320. numFrames = modelinfo->GetModelFrameCount( m_entFlames[i].GetModel() );
  321. if ( m_entFlames[i].m_flFrame >= numFrames )
  322. {
  323. m_entFlames[i].m_flFrame = m_entFlames[i].m_flFrame - (int)(m_entFlames[i].m_flFrame);
  324. }
  325. }
  326. }
  327. //-----------------------------------------------------------------------------
  328. // Purpose:
  329. //-----------------------------------------------------------------------------
  330. void C_Plasma::UpdateFlames( void )
  331. {
  332. for ( int i = 0; i < NUM_CHILD_FLAMES; i++ )
  333. {
  334. float newScale = m_flScaleRegister * m_entFlameScales[i];
  335. float dScale = newScale - m_entFlames[i].GetScale();
  336. Vector dir;
  337. dir[2] = 0.0f;
  338. VectorNormalize( dir );
  339. dir[2] = 0.0f;
  340. Vector offset = GetAbsOrigin();
  341. offset[2] = m_entFlames[i].GetAbsOrigin()[2];
  342. // Note: Sprite render assumes 0 scale means 1.0
  343. m_entFlames[i].SetScale ( MAX(0.000001,newScale) );
  344. if ( i != 0 )
  345. {
  346. m_entFlames[i].SetLocalOrigin( offset + ( m_entFlames[i].m_vecMoveDir * ((m_entFlames[i].GetScale())*CHILD_SPREAD) ) );
  347. }
  348. Assert( !m_entFlames[i].GetMoveParent() );
  349. m_entFlames[i].SetLocalOriginDim( Z_INDEX, m_entFlames[i].GetLocalOriginDim( Z_INDEX ) + ( dScale * 64.0f ) );
  350. }
  351. }
  352. //-----------------------------------------------------------------------------
  353. // Purpose:
  354. //-----------------------------------------------------------------------------
  355. void C_Plasma::UpdateScale( void )
  356. {
  357. float time = gpGlobals->curtime;
  358. if ( m_flScaleRegister != m_flScaleEnd )
  359. {
  360. //See if we're done scaling
  361. if ( time > m_flScaleTimeEnd )
  362. {
  363. m_flScaleRegister = m_flStartScale = m_flScaleEnd;
  364. }
  365. else
  366. {
  367. //Lerp the scale and set it
  368. float timeFraction = 1.0f - ( m_flScaleTimeEnd - time ) / ( m_flScaleTimeEnd - m_flScaleTimeStart );
  369. float newScale = m_flScaleStart + ( ( m_flScaleEnd - m_flScaleStart ) * timeFraction );
  370. m_flScaleRegister = m_flStartScale = newScale;
  371. }
  372. }
  373. }
  374. //-----------------------------------------------------------------------------
  375. // Purpose:
  376. // Input : fTimeDelta -
  377. //-----------------------------------------------------------------------------
  378. void C_Plasma::Update( void )
  379. {
  380. //Update all our parts
  381. UpdateScale();
  382. UpdateAnimation();
  383. UpdateFlames();
  384. if (m_flScaleRegister > 0.1)
  385. {
  386. float tempDelta = gpGlobals->frametime;
  387. while( m_tDecalSpawn.NextEvent( tempDelta ) )
  388. {
  389. // Add decal to floor
  390. C_BaseEntity *ent = cl_entitylist->GetEnt( 0 );
  391. if ( ent )
  392. {
  393. int index = decalsystem->GetDecalIndexForName( "PlasmaGlowFade" );
  394. if ( index >= 0 )
  395. {
  396. effects->DecalShoot( index, 0, ent->GetModel(), ent->GetAbsOrigin(), ent->GetAbsAngles(), GetAbsOrigin(), 0, 0 );
  397. }
  398. }
  399. }
  400. }
  401. }