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.

330 lines
11 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $NoKeywords: $
  7. //===========================================================================//
  8. #include "cbase.h"
  9. #include "c_basetempentity.h"
  10. #include "particle_simple3d.h"
  11. #include "tier1/keyvalues.h"
  12. #include "toolframework_client.h"
  13. #include "fx.h"
  14. #include "tier0/vprof.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. #define PI 3.14159265359
  18. #define GLASS_SHARD_MIN_LIFE 2
  19. #define GLASS_SHARD_MAX_LIFE 5
  20. #define GLASS_SHARD_NOISE 0.3
  21. #define GLASS_SHARD_GRAVITY 500
  22. #define GLASS_SHARD_DAMPING 0.3
  23. #include "precache_register.h"
  24. #ifndef DOTA_DLL
  25. PRECACHE_REGISTER_BEGIN( GLOBAL, PrecacheEffectGlassShatter )
  26. PRECACHE( MATERIAL, "effects/fleck_glass1" )
  27. PRECACHE( MATERIAL, "effects/fleck_glass2" )
  28. PRECACHE( MATERIAL, "effects/fleck_tile1" )
  29. PRECACHE( MATERIAL, "effects/fleck_tile2" )
  30. PRECACHE_REGISTER_END()
  31. #endif
  32. ConVar fx_glass_velocity_cap("fx_glass_velocity_cap", "0", 0, "Maximum downwards speed of shattered glass particles");
  33. //###################################################
  34. // > C_TEShatterSurface
  35. //###################################################
  36. class C_TEShatterSurface : public C_BaseTempEntity
  37. {
  38. public:
  39. DECLARE_CLASS( C_TEShatterSurface, C_BaseTempEntity );
  40. DECLARE_CLIENTCLASS();
  41. C_TEShatterSurface( void );
  42. ~C_TEShatterSurface( void );
  43. virtual void PostDataUpdate( DataUpdateType_t updateType );
  44. private:
  45. // Recording
  46. void RecordShatterSurface( );
  47. public:
  48. Vector m_vecOrigin;
  49. QAngle m_vecAngles;
  50. Vector m_vecForce;
  51. Vector m_vecForcePos;
  52. float m_flWidth;
  53. float m_flHeight;
  54. float m_flShardSize;
  55. PMaterialHandle m_pMaterialHandle;
  56. int m_nSurfaceType;
  57. byte m_uchFrontColor[3];
  58. byte m_uchBackColor[3];
  59. };
  60. //------------------------------------------------------------------------------
  61. // Networking
  62. //------------------------------------------------------------------------------
  63. IMPLEMENT_CLIENTCLASS_EVENT_DT(C_TEShatterSurface, DT_TEShatterSurface, CTEShatterSurface)
  64. RecvPropVector( RECVINFO(m_vecOrigin)),
  65. RecvPropVector( RECVINFO(m_vecAngles)),
  66. RecvPropVector( RECVINFO(m_vecForce)),
  67. RecvPropVector( RECVINFO(m_vecForcePos)),
  68. RecvPropFloat( RECVINFO(m_flWidth)),
  69. RecvPropFloat( RECVINFO(m_flHeight)),
  70. RecvPropFloat( RECVINFO(m_flShardSize)),
  71. RecvPropInt( RECVINFO(m_nSurfaceType)),
  72. RecvPropInt( RECVINFO(m_uchFrontColor[0])),
  73. RecvPropInt( RECVINFO(m_uchFrontColor[1])),
  74. RecvPropInt( RECVINFO(m_uchFrontColor[2])),
  75. RecvPropInt( RECVINFO(m_uchBackColor[0])),
  76. RecvPropInt( RECVINFO(m_uchBackColor[1])),
  77. RecvPropInt( RECVINFO(m_uchBackColor[2])),
  78. END_RECV_TABLE()
  79. //------------------------------------------------------------------------------
  80. // Constructor, destructor
  81. //------------------------------------------------------------------------------
  82. C_TEShatterSurface::C_TEShatterSurface( void )
  83. {
  84. m_vecOrigin.Init();
  85. m_vecAngles.Init();
  86. m_vecForce.Init();
  87. m_vecForcePos.Init();
  88. m_flWidth = 16.0;
  89. m_flHeight = 16.0;
  90. m_flShardSize = 3;
  91. m_nSurfaceType = SHATTERSURFACE_GLASS;
  92. m_uchFrontColor[0] = 255;
  93. m_uchFrontColor[1] = 255;
  94. m_uchFrontColor[2] = 255;
  95. m_uchBackColor[0] = 255;
  96. m_uchBackColor[1] = 255;
  97. m_uchBackColor[2] = 255;
  98. }
  99. C_TEShatterSurface::~C_TEShatterSurface()
  100. {
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Recording
  104. //-----------------------------------------------------------------------------
  105. void C_TEShatterSurface::RecordShatterSurface( )
  106. {
  107. if ( !ToolsEnabled() )
  108. return;
  109. if ( clienttools->IsInRecordingMode() )
  110. {
  111. Color front( m_uchFrontColor[0], m_uchFrontColor[1], m_uchFrontColor[2], 255 );
  112. Color back( m_uchBackColor[0], m_uchBackColor[1], m_uchBackColor[2], 255 );
  113. KeyValues *msg = new KeyValues( "TempEntity" );
  114. msg->SetInt( "te", TE_SHATTER_SURFACE );
  115. msg->SetString( "name", "TE_ShatterSurface" );
  116. msg->SetFloat( "time", gpGlobals->curtime );
  117. msg->SetFloat( "originx", m_vecOrigin.x );
  118. msg->SetFloat( "originy", m_vecOrigin.y );
  119. msg->SetFloat( "originz", m_vecOrigin.z );
  120. msg->SetFloat( "anglesx", m_vecAngles.x );
  121. msg->SetFloat( "anglesy", m_vecAngles.y );
  122. msg->SetFloat( "anglesz", m_vecAngles.z );
  123. msg->SetFloat( "forcex", m_vecForce.x );
  124. msg->SetFloat( "forcey", m_vecForce.y );
  125. msg->SetFloat( "forcez", m_vecForce.z );
  126. msg->SetFloat( "forceposx", m_vecForcePos.x );
  127. msg->SetFloat( "forceposy", m_vecForcePos.y );
  128. msg->SetFloat( "forceposz", m_vecForcePos.z );
  129. msg->SetColor( "frontcolor", front );
  130. msg->SetColor( "backcolor", back );
  131. msg->SetFloat( "width", m_flWidth );
  132. msg->SetFloat( "height", m_flHeight );
  133. msg->SetFloat( "size", m_flShardSize );
  134. msg->SetInt( "surfacetype", m_nSurfaceType );
  135. ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
  136. msg->deleteThis();
  137. }
  138. }
  139. //-----------------------------------------------------------------------------
  140. // Purpose:
  141. //-----------------------------------------------------------------------------
  142. void C_TEShatterSurface::PostDataUpdate( DataUpdateType_t updateType )
  143. {
  144. VPROF( "C_TEShatterSurface::PostDataUpdate" );
  145. RecordShatterSurface();
  146. CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "C_TEShatterSurface 1" );
  147. pGlassEmitter->SetSortOrigin( m_vecOrigin );
  148. Vector vecColor;
  149. engine->ComputeLighting( m_vecOrigin, NULL, true, vecColor );
  150. // HACK: Blend a little toward white to match the materials...
  151. VectorLerp( vecColor, Vector( 1, 1, 1 ), 0.3, vecColor );
  152. PMaterialHandle *hMaterial;
  153. if (m_nSurfaceType == SHATTERSURFACE_GLASS)
  154. {
  155. hMaterial = g_Mat_Fleck_Glass;
  156. }
  157. else
  158. {
  159. hMaterial = g_Mat_Fleck_Tile;
  160. }
  161. // ---------------------------------------------------
  162. // Figure out number of particles required to fill space
  163. // ---------------------------------------------------
  164. int nNumWide = m_flWidth / m_flShardSize;
  165. int nNumHigh = m_flHeight / m_flShardSize;
  166. Vector vWidthStep,vHeightStep;
  167. AngleVectors(m_vecAngles,NULL,&vWidthStep,&vHeightStep);
  168. vWidthStep *= m_flShardSize;
  169. vHeightStep *= m_flShardSize;
  170. // ---------------------
  171. // Create glass shards
  172. // ----------------------
  173. Vector vCurPos = m_vecOrigin;
  174. vCurPos.x += 0.5*m_flShardSize;
  175. vCurPos.z += 0.5*m_flShardSize;
  176. float flMinSpeed = 9999999999.0f;
  177. float flMaxSpeed = 0;
  178. Particle3D *pParticle = NULL;
  179. for (int width=0;width<nNumWide;width++)
  180. {
  181. for (int height=0;height<nNumHigh;height++)
  182. {
  183. pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), hMaterial[random->RandomInt(0,1)], vCurPos );
  184. Vector vForceVel = Vector(0,0,0);
  185. if (random->RandomInt(0, 3) != 0)
  186. {
  187. float flForceDistSqr = (vCurPos - m_vecForcePos).LengthSqr();
  188. vForceVel = m_vecForce;
  189. if (flForceDistSqr > 0 )
  190. {
  191. vForceVel *= ( 40.0f / flForceDistSqr );
  192. }
  193. }
  194. // cap the Z velocity of the shards
  195. if (fx_glass_velocity_cap.GetFloat() > 0 && vForceVel.z < -fx_glass_velocity_cap.GetFloat())
  196. {
  197. vForceVel.z = random->RandomFloat(-fx_glass_velocity_cap.GetFloat(), -(fx_glass_velocity_cap.GetFloat() * 0.66f));
  198. }
  199. if (pParticle)
  200. {
  201. pParticle->m_flLifeRemaining = random->RandomFloat(GLASS_SHARD_MIN_LIFE,GLASS_SHARD_MAX_LIFE);
  202. pParticle->m_vecVelocity = vForceVel;
  203. pParticle->m_vecVelocity += RandomVector(-25,25);
  204. pParticle->m_uchSize = m_flShardSize + random->RandomFloat(-0.5*m_flShardSize,0.5*m_flShardSize);
  205. pParticle->m_vAngles = m_vecAngles;
  206. pParticle->m_flAngSpeed = random->RandomFloat(-400,400);
  207. pParticle->m_uchFrontColor[0] = (byte)(m_uchFrontColor[0] * vecColor.x );
  208. pParticle->m_uchFrontColor[1] = (byte)(m_uchFrontColor[1] * vecColor.y );
  209. pParticle->m_uchFrontColor[2] = (byte)(m_uchFrontColor[2] * vecColor.z );
  210. pParticle->m_uchBackColor[0] = (byte)(m_uchBackColor[0] * vecColor.x );
  211. pParticle->m_uchBackColor[1] = (byte)(m_uchBackColor[1] * vecColor.y );
  212. pParticle->m_uchBackColor[2] = (byte)(m_uchBackColor[2] * vecColor.z );
  213. }
  214. // Keep track of min and max speed for collision detection
  215. float flForceSpeed = vForceVel.Length();
  216. if (flForceSpeed > flMaxSpeed)
  217. {
  218. flMaxSpeed = flForceSpeed;
  219. }
  220. if (flForceSpeed < flMinSpeed)
  221. {
  222. flMinSpeed = flForceSpeed;
  223. }
  224. vCurPos += vHeightStep;
  225. }
  226. vCurPos -= nNumHigh*vHeightStep;
  227. vCurPos += vWidthStep;
  228. }
  229. // --------------------------------------------------
  230. // Set collision parameters
  231. // --------------------------------------------------
  232. Vector vMoveDir = m_vecForce;
  233. VectorNormalize(vMoveDir);
  234. pGlassEmitter->m_ParticleCollision.Setup( m_vecOrigin, &vMoveDir, GLASS_SHARD_NOISE,
  235. flMinSpeed, flMaxSpeed, GLASS_SHARD_GRAVITY, GLASS_SHARD_DAMPING );
  236. }
  237. void TE_ShatterSurface( IRecipientFilter& filter, float delay,
  238. const Vector* pos, const QAngle* angle, const Vector* vForce, const Vector* vForcePos,
  239. float width, float height, float shardsize, ShatterSurface_t surfacetype,
  240. int front_r, int front_g, int front_b, int back_r, int back_g, int back_b)
  241. {
  242. // Major hack to simulate receiving network message
  243. __g_C_TEShatterSurface.m_vecOrigin = *pos;
  244. __g_C_TEShatterSurface.m_vecAngles = *angle;
  245. __g_C_TEShatterSurface.m_vecForce = *vForce;
  246. __g_C_TEShatterSurface.m_vecForcePos = *vForcePos;
  247. __g_C_TEShatterSurface.m_flWidth = width;
  248. __g_C_TEShatterSurface.m_flHeight = height;
  249. __g_C_TEShatterSurface.m_flShardSize = shardsize;
  250. __g_C_TEShatterSurface.m_nSurfaceType = surfacetype;
  251. __g_C_TEShatterSurface.m_uchFrontColor[0] = front_r;
  252. __g_C_TEShatterSurface.m_uchFrontColor[1] = front_g;
  253. __g_C_TEShatterSurface.m_uchFrontColor[2] = front_b;
  254. __g_C_TEShatterSurface.m_uchBackColor[0] = back_r;
  255. __g_C_TEShatterSurface.m_uchBackColor[1] = back_g;
  256. __g_C_TEShatterSurface.m_uchBackColor[2] = back_b;
  257. __g_C_TEShatterSurface.PostDataUpdate( DATA_UPDATE_CREATED );
  258. }
  259. void TE_ShatterSurface( IRecipientFilter& filter, float delay, KeyValues *pKeyValues )
  260. {
  261. Vector vecOrigin, vecForce, vecForcePos;
  262. QAngle angles;
  263. vecOrigin.x = pKeyValues->GetFloat( "originx" );
  264. vecOrigin.y = pKeyValues->GetFloat( "originy" );
  265. vecOrigin.z = pKeyValues->GetFloat( "originz" );
  266. angles.x = pKeyValues->GetFloat( "anglesx" );
  267. angles.y = pKeyValues->GetFloat( "anglesy" );
  268. angles.z = pKeyValues->GetFloat( "anglesz" );
  269. vecForce.x = pKeyValues->GetFloat( "forcex" );
  270. vecForce.y = pKeyValues->GetFloat( "forcey" );
  271. vecForce.z = pKeyValues->GetFloat( "forcez" );
  272. vecForcePos.x = pKeyValues->GetFloat( "forceposx" );
  273. vecForcePos.y = pKeyValues->GetFloat( "forceposy" );
  274. vecForcePos.z = pKeyValues->GetFloat( "forceposz" );
  275. Color front = pKeyValues->GetColor( "frontcolor" );
  276. Color back = pKeyValues->GetColor( "backcolor" );
  277. float flWidth = pKeyValues->GetFloat( "width" );
  278. float flHeight = pKeyValues->GetFloat( "height" );
  279. float flSize = pKeyValues->GetFloat( "size" );
  280. ShatterSurface_t nSurfaceType = (ShatterSurface_t)pKeyValues->GetInt( "surfacetype" );
  281. TE_ShatterSurface( filter, 0.0f, &vecOrigin, &angles, &vecForce, &vecForcePos,
  282. flWidth, flHeight, flSize, nSurfaceType, front.r(), front.g(), front.b(),
  283. back.r(), back.g(), back.b() );
  284. }