Team Fortress 2 Source Code as on 22/4/2020
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.

334 lines
9.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "fx.h"
  8. #include "c_gib.h"
  9. #include "c_te_effect_dispatch.h"
  10. #include "iefx.h"
  11. #include "decals.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. PMaterialHandle g_Material_Blood[2] = { NULL, NULL };
  15. #ifdef _XBOX
  16. // XBox only uses a few gibs
  17. #define NUM_ANTLION_GIBS 3
  18. const char *pszAntlionGibs[NUM_ANTLION_GIBS] = {
  19. "models/gibs/antlion_gib_large_2.mdl", // Head
  20. "models/gibs/antlion_gib_medium_1.mdl", // Pincher
  21. "models/gibs/antlion_gib_medium_2.mdl", // Leg
  22. };
  23. #else
  24. // Use all the gibs
  25. #define NUM_ANTLION_GIBS_UNIQUE 3
  26. const char *pszAntlionGibs_Unique[NUM_ANTLION_GIBS_UNIQUE] = {
  27. "models/gibs/antlion_gib_large_1.mdl",
  28. "models/gibs/antlion_gib_large_2.mdl",
  29. "models/gibs/antlion_gib_large_3.mdl"
  30. };
  31. #define NUM_ANTLION_GIBS_MEDIUM 3
  32. const char *pszAntlionGibs_Medium[NUM_ANTLION_GIBS_MEDIUM] = {
  33. "models/gibs/antlion_gib_medium_1.mdl",
  34. "models/gibs/antlion_gib_medium_2.mdl",
  35. "models/gibs/antlion_gib_medium_3.mdl"
  36. };
  37. // XBox doesn't use the smaller gibs, so don't cache them
  38. #define NUM_ANTLION_GIBS_SMALL 3
  39. const char *pszAntlionGibs_Small[NUM_ANTLION_GIBS_SMALL] = {
  40. "models/gibs/antlion_gib_small_1.mdl",
  41. "models/gibs/antlion_gib_small_2.mdl",
  42. "models/gibs/antlion_gib_small_3.mdl"
  43. };
  44. #endif
  45. ConVar g_antlion_maxgibs( "g_antlion_maxgibs", "16", FCVAR_ARCHIVE );
  46. void CAntlionGibManager::LevelInitPreEntity( void )
  47. {
  48. m_LRU.Purge();
  49. }
  50. CAntlionGibManager s_AntlionGibManager( "CAntlionGibManager" );
  51. void CAntlionGibManager::AddGib( C_BaseEntity *pEntity )
  52. {
  53. m_LRU.AddToTail( pEntity );
  54. }
  55. void CAntlionGibManager::RemoveGib( C_BaseEntity *pEntity )
  56. {
  57. m_LRU.FindAndRemove( pEntity );
  58. }
  59. //-----------------------------------------------------------------------------
  60. // Methods of IGameSystem
  61. //-----------------------------------------------------------------------------
  62. void CAntlionGibManager::Update( float frametime )
  63. {
  64. if ( m_LRU.Count() < g_antlion_maxgibs.GetInt() )
  65. return;
  66. int i = 0;
  67. i = m_LRU.Head();
  68. if ( m_LRU[ i ].Get() )
  69. {
  70. m_LRU[ i ].Get()->SetNextClientThink( gpGlobals->curtime );
  71. }
  72. m_LRU.Remove(i);
  73. }
  74. // Antlion gib - marks surfaces when it bounces
  75. class C_AntlionGib : public C_Gib
  76. {
  77. typedef C_Gib BaseClass;
  78. public:
  79. static C_AntlionGib *CreateClientsideGib( const char *pszModelName, Vector vecOrigin, Vector vecForceDir, AngularImpulse vecAngularImp, float m_flLifetime = DEFAULT_GIB_LIFETIME )
  80. {
  81. C_AntlionGib *pGib = new C_AntlionGib;
  82. if ( pGib == NULL )
  83. return NULL;
  84. if ( pGib->InitializeGib( pszModelName, vecOrigin, vecForceDir, vecAngularImp, m_flLifetime ) == false )
  85. return NULL;
  86. s_AntlionGibManager.AddGib( pGib );
  87. return pGib;
  88. }
  89. // Decal the surface
  90. virtual void HitSurface( C_BaseEntity *pOther )
  91. {
  92. //JDW: Removed for the time being
  93. /*
  94. int index = decalsystem->GetDecalIndexForName( "YellowBlood" );
  95. if (index >= 0 )
  96. {
  97. effects->DecalShoot( index, pOther->entindex(), pOther->GetModel(), pOther->GetAbsOrigin(), pOther->GetAbsAngles(), GetAbsOrigin(), 0, 0 );
  98. }
  99. */
  100. }
  101. };
  102. //-----------------------------------------------------------------------------
  103. // Purpose:
  104. // Input : &origin -
  105. //-----------------------------------------------------------------------------
  106. void FX_AntlionGib( const Vector &origin, const Vector &direction, float scale )
  107. {
  108. Vector offset;
  109. #ifdef _XBOX
  110. // Throw less gibs for XBox
  111. for ( int i = 0; i < NUM_ANTLION_GIBS; i++ )
  112. {
  113. offset = RandomVector( -32, 32 ) + origin;
  114. C_AntlionGib::CreateClientsideGib( pszAntlionGibs[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 250 * scale ), RandomAngularImpulse( -32, 32 ), 1.0f );
  115. }
  116. #else
  117. int numGibs = random->RandomInt( 1, NUM_ANTLION_GIBS_UNIQUE );
  118. // Spawn all the unique gibs
  119. for ( int i = 0; i < numGibs; i++ )
  120. {
  121. offset = RandomVector( -16, 16 ) + origin;
  122. C_AntlionGib::CreateClientsideGib( pszAntlionGibs_Unique[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 150 * scale ), RandomAngularImpulse( -32, 32 ), 2.0f);
  123. }
  124. numGibs = random->RandomInt( 1, NUM_ANTLION_GIBS_MEDIUM );
  125. // Spawn all the medium gibs
  126. for ( int i = 0; i < numGibs; i++ )
  127. {
  128. offset = RandomVector( -16, 16 ) + origin;
  129. C_AntlionGib::CreateClientsideGib( pszAntlionGibs_Medium[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 250 * scale ), RandomAngularImpulse( -200, 200 ), 1.0f );
  130. }
  131. numGibs = random->RandomInt( 1, NUM_ANTLION_GIBS_SMALL );
  132. // Spawn all the small gibs
  133. for ( int i = 0; i < NUM_ANTLION_GIBS_SMALL; i++ )
  134. {
  135. offset = RandomVector( -16, 16 ) + origin;
  136. C_AntlionGib::CreateClientsideGib( pszAntlionGibs_Small[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 400 * scale ), RandomAngularImpulse( -300, 300 ), 0.5f );
  137. }
  138. #endif
  139. #ifdef _XBOX
  140. //
  141. // Throw some blood
  142. //
  143. CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_AntlionGib" );
  144. pSimple->SetSortOrigin( origin );
  145. pSimple->GetBinding().SetBBox( origin - Vector(64,64,64), origin + Vector(64,64,64) );
  146. // Cache this if we're not already
  147. if ( g_Material_Blood[0] == NULL )
  148. {
  149. g_Material_Blood[0] = g_Mat_BloodPuff[0];
  150. }
  151. if ( g_Material_Blood[1] == NULL )
  152. {
  153. g_Material_Blood[1] = g_Mat_BloodPuff[1];
  154. }
  155. Vector vDir;
  156. vDir.Random( -1.0f, 1.0f );
  157. // Gore bits
  158. for ( int i = 0; i < 4; i++ )
  159. {
  160. SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Material_Blood[0], origin + RandomVector(-16,16));
  161. if ( sParticle == NULL )
  162. return;
  163. sParticle->m_flLifetime = 0.0f;
  164. sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
  165. float speed = random->RandomFloat( 16.0f, 64.0f );
  166. sParticle->m_vecVelocity.Init();
  167. sParticle->m_uchColor[0] = 255;
  168. sParticle->m_uchColor[1] = 200;
  169. sParticle->m_uchColor[2] = 32;
  170. sParticle->m_uchStartAlpha = 255;
  171. sParticle->m_uchEndAlpha = 0;
  172. sParticle->m_uchStartSize = random->RandomInt( 4, 16 );
  173. sParticle->m_uchEndSize = sParticle->m_uchStartSize * 4;
  174. sParticle->m_flRoll = random->RandomInt( 0, 360 );
  175. sParticle->m_flRollDelta = 0.0f;
  176. }
  177. // Middle core
  178. SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Material_Blood[1], origin );
  179. if ( sParticle == NULL )
  180. return;
  181. sParticle->m_flLifetime = 0.0f;
  182. sParticle->m_flDieTime = random->RandomFloat( 0.5f, 0.75f );
  183. float speed = random->RandomFloat( 16.0f, 64.0f );
  184. sParticle->m_vecVelocity = vDir * -speed;
  185. sParticle->m_vecVelocity[2] += 16.0f;
  186. sParticle->m_uchColor[0] = 255;
  187. sParticle->m_uchColor[1] = 200;
  188. sParticle->m_uchColor[2] = 32;
  189. sParticle->m_uchStartAlpha = random->RandomInt( 64, 128 );
  190. sParticle->m_uchEndAlpha = 0;
  191. sParticle->m_uchStartSize = random->RandomInt( 16, 32 );
  192. sParticle->m_uchEndSize = sParticle->m_uchStartSize * 3;
  193. sParticle->m_flRoll = random->RandomInt( 0, 360 );
  194. sParticle->m_flRollDelta = random->RandomFloat( -0.2f, 0.2f );
  195. #else
  196. //
  197. // Non-XBox blood
  198. //
  199. CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_AntlionGib" );
  200. pSimple->SetSortOrigin( origin );
  201. Vector vDir;
  202. vDir.Random( -1.0f, 1.0f );
  203. for ( int i = 0; i < 4; i++ )
  204. {
  205. SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );
  206. if ( sParticle == NULL )
  207. return;
  208. sParticle->m_flLifetime = 0.0f;
  209. sParticle->m_flDieTime = random->RandomFloat( 0.5f, 0.75f );
  210. float speed = random->RandomFloat( 16.0f, 64.0f );
  211. sParticle->m_vecVelocity = vDir * -speed;
  212. sParticle->m_vecVelocity[2] += 16.0f;
  213. sParticle->m_uchColor[0] = 255;
  214. sParticle->m_uchColor[1] = 200;
  215. sParticle->m_uchColor[2] = 32;
  216. sParticle->m_uchStartAlpha = 255;
  217. sParticle->m_uchEndAlpha = 0;
  218. sParticle->m_uchStartSize = random->RandomInt( 16, 32 );
  219. sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2;
  220. sParticle->m_flRoll = random->RandomInt( 0, 360 );
  221. sParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f );
  222. }
  223. for ( int i = 0; i < 4; i++ )
  224. {
  225. SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], origin );
  226. if ( sParticle == NULL )
  227. {
  228. return;
  229. }
  230. sParticle->m_flLifetime = 0.0f;
  231. sParticle->m_flDieTime = random->RandomFloat( 0.5f, 0.75f );
  232. float speed = random->RandomFloat( 16.0f, 64.0f );
  233. sParticle->m_vecVelocity = vDir * -speed;
  234. sParticle->m_vecVelocity[2] += 16.0f;
  235. sParticle->m_uchColor[0] = 255;
  236. sParticle->m_uchColor[1] = 200;
  237. sParticle->m_uchColor[2] = 32;
  238. sParticle->m_uchStartAlpha = random->RandomInt( 64, 128 );
  239. sParticle->m_uchEndAlpha = 0;
  240. sParticle->m_uchStartSize = random->RandomInt( 16, 32 );
  241. sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2;
  242. sParticle->m_flRoll = random->RandomInt( 0, 360 );
  243. sParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f );
  244. }
  245. #endif
  246. }
  247. //-----------------------------------------------------------------------------
  248. // Purpose:
  249. // Input : &data -
  250. //-----------------------------------------------------------------------------
  251. void AntlionGibCallback( const CEffectData &data )
  252. {
  253. FX_AntlionGib( data.m_vOrigin, data.m_vNormal, data.m_flScale );
  254. }
  255. DECLARE_CLIENT_EFFECT( "AntlionGib", AntlionGibCallback );