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.

288 lines
9.0 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "cbase.h"
  8. #include "c_entityfreezing.h"
  9. #include "studio.h"
  10. #include "bone_setup.h"
  11. #include "c_surfacerender.h"
  12. #include "engine/ivdebugoverlay.h"
  13. #include "dt_utlvector_recv.h"
  14. #include "debugoverlay_shared.h"
  15. #include "animation.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. ConVar cl_blobulator_freezing_max_metaball_radius( "cl_blobulator_freezing_max_metaball_radius",
  19. #ifdef INFESTED_DLL
  20. "25.0", // Don't need as much precision in Alien swarm because everything is zoomed out
  21. #else
  22. "12.0",
  23. #endif
  24. FCVAR_NONE, "Setting this can create more complex surfaces on large hitboxes at the cost of performance.", true, 12.0f, true, 100.0f );
  25. //PRECACHE_REGISTER_BEGIN( GLOBAL, PrecacheEffectFreezing )
  26. // PRECACHE( MATERIAL,"effects/tesla_glow_noz" )
  27. // PRECACHE( MATERIAL,"effects/spark" )
  28. // PRECACHE( MATERIAL,"effects/combinemuzzle2" )
  29. //PRECACHE_REGISTER_END()
  30. //-----------------------------------------------------------------------------
  31. // Networking
  32. //-----------------------------------------------------------------------------
  33. IMPLEMENT_CLIENTCLASS_DT( C_EntityFreezing, DT_EntityFreezing, CEntityFreezing )
  34. RecvPropVector( RECVINFO(m_vFreezingOrigin) ),
  35. RecvPropArray3( RECVINFO_ARRAY(m_flFrozenPerHitbox), RecvPropFloat( RECVINFO( m_flFrozenPerHitbox[0] ) ) ),
  36. RecvPropFloat( RECVINFO(m_flFrozen) ),
  37. RecvPropBool( RECVINFO(m_bFinishFreezing) ),
  38. END_RECV_TABLE()
  39. //-----------------------------------------------------------------------------
  40. // Purpose:
  41. //-----------------------------------------------------------------------------
  42. void C_EntityFreezing::GetRenderBounds( Vector& theMins, Vector& theMaxs )
  43. {
  44. if ( GetMoveParent() )
  45. {
  46. GetMoveParent()->GetRenderBounds( theMins, theMaxs );
  47. }
  48. else
  49. {
  50. theMins = GetAbsOrigin();
  51. theMaxs = theMaxs;
  52. }
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Yes we bloody are
  56. //-----------------------------------------------------------------------------
  57. RenderableTranslucencyType_t C_EntityFreezing::ComputeTranslucencyType( )
  58. {
  59. return RENDERABLE_IS_TRANSLUCENT;
  60. }
  61. //-----------------------------------------------------------------------------
  62. // On data changed
  63. //-----------------------------------------------------------------------------
  64. void C_EntityFreezing::OnDataChanged( DataUpdateType_t updateType )
  65. {
  66. BaseClass::OnDataChanged( updateType );
  67. if ( updateType == DATA_UPDATE_CREATED )
  68. {
  69. SetNextClientThink( CLIENT_THINK_ALWAYS );
  70. }
  71. }
  72. //-----------------------------------------------------------------------------
  73. // Purpose:
  74. //-----------------------------------------------------------------------------
  75. void C_EntityFreezing::ClientThink( void )
  76. {
  77. #ifdef _PS3
  78. __nop();
  79. #elif defined(LINUX)
  80. #elif defined( __clang__ )
  81. asm("nop");
  82. #elif defined( _WIN32 ) && !defined( WIN64 )
  83. __asm nop;
  84. #endif
  85. //C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
  86. //if (!pAnimating)
  87. // return;
  88. //color32 color = pAnimating->GetRenderColor();
  89. //color.r = color.g = ( 1.0f - m_flFrozen ) * 255.0f;
  90. //// Setup the entity fade
  91. //pAnimating->SetRenderMode( kRenderTransColor );
  92. //pAnimating->SetRenderColor( color.r, color.g, color.b, color.a );
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Purpose:
  96. // Input : flags -
  97. // Output : int
  98. //-----------------------------------------------------------------------------
  99. int C_EntityFreezing::DrawModel( int flags, const RenderableInstance_t &instance )
  100. {
  101. #ifdef USE_BLOBULATOR
  102. // See if we should draw
  103. if ( m_bReadyToDraw == false )
  104. return 0;
  105. // The parent needs to be a base animating
  106. C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
  107. if ( pAnimating == NULL )
  108. return 0;
  109. // Make sure we have hitboxes
  110. matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
  111. if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) == false )
  112. return 0;
  113. studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
  114. if ( pStudioHdr == NULL )
  115. return 0;
  116. int nEffectsHitboxSet = FindHitboxSetByName( pAnimating->GetModelPtr(), "effects" );
  117. mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( nEffectsHitboxSet != -1 ? nEffectsHitboxSet : pAnimating->GetHitboxSet() );
  118. if ( !set )
  119. return 0;
  120. // FIXME: No idea how many particles we'll need, so let's start with 1000
  121. g_SurfaceRenderParticles.SetCount( 1000 );
  122. int iNumParticles = 0;
  123. for ( int i = 0; i < set->numhitboxes; ++i )
  124. {
  125. mstudiobbox_t *pBox = set->pHitbox(i);
  126. matrix3x4_t matBone = *hitboxbones[ pBox->bone ];
  127. Vector vecHorizontal = pBox->bbmax - pBox->bbmin;
  128. // Get the particle radius
  129. float flShortestAxis = MIN( MIN( vecHorizontal.x, vecHorizontal.y ), vecHorizontal.z );
  130. float flDiameter = clamp( flShortestAxis, 1.0f, cl_blobulator_freezing_max_metaball_radius.GetFloat() );
  131. float flRadius = flDiameter * 0.5f;
  132. float flVarience = flRadius * 0.25f;
  133. float flRadiusIsoSurface = flRadius / 12.0f;
  134. // Get the hitbox data
  135. EntityFreezingHitboxBlobData_t *pHitboxBlobData = NULL;
  136. if ( m_HitboxBlobData.Count() <= i )
  137. {
  138. // We don't have data for this hitbox yet, so build need relative point positions that are along its faces
  139. int nNewHitboxBlobData = m_HitboxBlobData.AddToTail();
  140. pHitboxBlobData = &(m_HitboxBlobData[ nNewHitboxBlobData ]);
  141. // Start in the min corner
  142. Vector vecStartPoint = pBox->bbmin + ReplicateToVector( flRadius * 0.5f );
  143. Vector vecEndPoint = pBox->bbmax - ReplicateToVector( flRadius * 0.5f );
  144. Vector vecPoint;
  145. bool bEdgeX = true;
  146. vecPoint.x = vecStartPoint.x;
  147. // Loop across each axis
  148. while ( vecPoint.x <= vecEndPoint.x )
  149. {
  150. bool bEdgeY = true;
  151. vecPoint.y = vecStartPoint.y;
  152. while ( vecPoint.y <= vecEndPoint.y )
  153. {
  154. bool bEdgeZ = true;
  155. vecPoint.z = vecStartPoint.z;
  156. while ( vecPoint.z <= vecEndPoint.z )
  157. {
  158. // Only add particles not in the middle of the box
  159. if ( bEdgeX || bEdgeY || bEdgeZ )
  160. {
  161. int nNewPoint = pHitboxBlobData->m_vPoints.AddToTail();
  162. pHitboxBlobData->m_vPoints[ nNewPoint ] = vecPoint + RandomVector( -flVarience, flVarience );
  163. }
  164. // Make sure the final particles don't stick out past the edge
  165. bEdgeZ = ( vecPoint.z < vecEndPoint.z && ( ( !bEdgeX && !bEdgeY ) || vecPoint.z + flRadius >= vecEndPoint.z ) );
  166. if ( bEdgeZ )
  167. {
  168. vecPoint.z = vecEndPoint.z;
  169. }
  170. else
  171. {
  172. vecPoint.z += flRadius;
  173. }
  174. }
  175. // Make sure the final particles don't stick out past the edge
  176. bEdgeY = ( vecPoint.y < vecEndPoint.y && vecPoint.y + flRadius >= vecEndPoint.y );
  177. if ( bEdgeY )
  178. {
  179. vecPoint.y = vecEndPoint.y;
  180. }
  181. else
  182. {
  183. vecPoint.y += flRadius;
  184. }
  185. }
  186. // Make sure the final particles don't stick out past the edge
  187. bEdgeX = ( vecPoint.x < vecEndPoint.x && vecPoint.x + flRadius >= vecEndPoint.x );
  188. if ( bEdgeX )
  189. {
  190. vecPoint.x = vecEndPoint.x;
  191. }
  192. else
  193. {
  194. vecPoint.x += flRadius;
  195. }
  196. }
  197. }
  198. else
  199. {
  200. pHitboxBlobData = &(m_HitboxBlobData[ i ]);
  201. }
  202. // Decide which of the hitbox points to draw based on how frozen the hitbox is and transform them into worldspace
  203. for ( int nPoint = 0; nPoint < pHitboxBlobData->m_vPoints.Count() && iNumParticles < 1000; ++nPoint )
  204. {
  205. // Fast out if the min Z surrounding this hitbox is above the cut off height
  206. Vector vecBoxAbsMins, vecBoxAbsMaxs;
  207. TransformAABB( matBone, pBox->bbmin, pBox->bbmax, vecBoxAbsMins, vecBoxAbsMaxs );
  208. if ( m_bFinishFreezing )
  209. {
  210. m_flFrozenPerHitbox[ i ] = MIN( 1.0f, m_flFrozenPerHitbox[ i ] + gpGlobals->frametime * 0.75f );
  211. }
  212. if ( m_flFrozenPerHitbox[ i ] <= 0.0f )
  213. {
  214. // No particles will be below the freezing line, skip this hitbox
  215. continue;
  216. }
  217. float fCutOffHeight = vecBoxAbsMins.z + ( vecBoxAbsMaxs.z - vecBoxAbsMins.z ) * m_flFrozenPerHitbox[ i ];
  218. // Get the point in worldspace
  219. Vector vecTransformedPoint;
  220. VectorTransform( pHitboxBlobData->m_vPoints[ nPoint ], matBone, vecTransformedPoint );
  221. // Only add particles below this height and if it's not in the middle of the box
  222. if ( vecTransformedPoint.z < fCutOffHeight )
  223. {
  224. ImpParticleWithOneInterpolant* imp_particle = &(g_SurfaceRenderParticles[ iNumParticles ]);
  225. imp_particle->center = vecTransformedPoint;
  226. imp_particle->setFieldScale( flRadiusIsoSurface );
  227. imp_particle->interpolants1.set( 1.0f, 1.0f, 1.0f );
  228. imp_particle->interpolants1[ 3 ] = 0.0f;
  229. ++iNumParticles;
  230. }
  231. }
  232. }
  233. g_SurfaceRenderParticles.SetCountNonDestructively( iNumParticles );
  234. // Set up lighting
  235. modelrender->SetupLighting( GetRenderOrigin() );
  236. Surface_Draw( GetClientRenderable(), GetRenderOrigin(), materials->FindMaterial( "models/weapons/w_icegun/ice_surface", TEXTURE_GROUP_OTHER, true ), 6.5f );
  237. #endif
  238. return 1;
  239. }