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.

689 lines
19 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: A gib is a chunk of a body, or a piece of wood/metal/rocks/etc.
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //===========================================================================//
  9. #include "cbase.h"
  10. #include "gib.h"
  11. #include "soundent.h"
  12. #include "func_break.h" // For materials
  13. #include "player.h"
  14. #include "vstdlib/random.h"
  15. #include "ai_utils.h"
  16. #include "EntityFlame.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. extern Vector g_vecAttackDir; // In globals.cpp
  20. CUtlVector<EHANDLE> CGib::s_ExtantGibs;
  21. BEGIN_DATADESC( CGib )
  22. // gibs are not saved/restored
  23. // DEFINE_FIELD( m_bloodColor, FIELD_INTEGER ),
  24. // DEFINE_FIELD( m_hSprite, FIELD_EHANDLE ),
  25. // DEFINE_FIELD( m_cBloodDecals, FIELD_INTEGER ),
  26. // DEFINE_FIELD( m_material, FIELD_INTEGER ),
  27. // DEFINE_FIELD( m_lifeTime, FIELD_TIME ),
  28. // DEFINE_FIELD( m_pSprite, CSprite ),
  29. // DEFINE_FIELD( m_hFlame, FIELD_EHANDLE ),
  30. // DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ),
  31. // DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ),
  32. // DEFINE_FIELD( m_bForceRemove, FIELD_BOOLEAN ),
  33. // Function pointers
  34. DEFINE_ENTITYFUNC( BounceGibTouch ),
  35. DEFINE_ENTITYFUNC( StickyGibTouch ),
  36. DEFINE_THINKFUNC( WaitTillLand ),
  37. DEFINE_THINKFUNC( DieThink ),
  38. END_DATADESC()
  39. // HACKHACK -- The gib velocity equations don't work
  40. void CGib::LimitVelocity( void )
  41. {
  42. Vector vecNewVelocity = GetAbsVelocity();
  43. float length = VectorNormalize( vecNewVelocity );
  44. // ceiling at 1500. The gib velocity equation is not bounded properly. Rather than tune it
  45. // in 3 separate places again, I'll just limit it here.
  46. if ( length > 1500.0 )
  47. {
  48. vecNewVelocity *= 1500; // This should really be sv_maxvelocity * 0.75 or something
  49. SetAbsVelocity( vecNewVelocity );
  50. }
  51. }
  52. void CGib::SpawnStickyGibs( CBaseEntity *pVictim, Vector vecOrigin, int cGibs )
  53. {
  54. int i;
  55. if ( g_Language.GetInt() == LANGUAGE_GERMAN )
  56. {
  57. // no sticky gibs in germany right now!
  58. return;
  59. }
  60. for ( i = 0 ; i < cGibs ; i++ )
  61. {
  62. CGib *pGib = (CGib *)CreateEntityByName( "gib" );
  63. pGib->Spawn( "models/stickygib.mdl" );
  64. pGib->m_nBody = random->RandomInt(0,2);
  65. if ( pVictim )
  66. {
  67. pGib->SetLocalOrigin(
  68. Vector( vecOrigin.x + random->RandomFloat( -3, 3 ),
  69. vecOrigin.y + random->RandomFloat( -3, 3 ),
  70. vecOrigin.z + random->RandomFloat( -3, 3 ) ) );
  71. // make the gib fly away from the attack vector
  72. Vector vecNewVelocity = g_vecAttackDir * -1;
  73. // mix in some noise
  74. vecNewVelocity.x += random->RandomFloat ( -0.15, 0.15 );
  75. vecNewVelocity.y += random->RandomFloat ( -0.15, 0.15 );
  76. vecNewVelocity.z += random->RandomFloat ( -0.15, 0.15 );
  77. vecNewVelocity *= 900;
  78. QAngle vecAngVelocity( random->RandomFloat ( 250, 400 ), random->RandomFloat ( 250, 400 ), 0 );
  79. pGib->SetLocalAngularVelocity( vecAngVelocity );
  80. // copy owner's blood color
  81. pGib->SetBloodColor( pVictim->BloodColor() );
  82. pGib->AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity );
  83. pGib->SetAbsVelocity( vecNewVelocity );
  84. pGib->SetMoveType( MOVETYPE_FLYGRAVITY );
  85. pGib->RemoveSolidFlags( FSOLID_NOT_SOLID );
  86. pGib->SetCollisionBounds( vec3_origin, vec3_origin );
  87. pGib->SetTouch ( &CGib::StickyGibTouch );
  88. pGib->SetThink (NULL);
  89. }
  90. pGib->LimitVelocity();
  91. }
  92. }
  93. void CGib::SpawnHeadGib( CBaseEntity *pVictim )
  94. {
  95. CGib *pGib = CREATE_ENTITY( CGib, "gib" );
  96. if ( g_Language.GetInt() == LANGUAGE_GERMAN )
  97. {
  98. pGib->Spawn( "models/germangibs.mdl" );// throw one head
  99. pGib->m_nBody = 0;
  100. }
  101. else
  102. {
  103. pGib->Spawn( "models/gibs/hgibs.mdl" );// throw one head
  104. pGib->m_nBody = 0;
  105. }
  106. if ( pVictim )
  107. {
  108. Vector vecNewVelocity = pGib->GetAbsVelocity();
  109. pGib->SetLocalOrigin( pVictim->EyePosition() );
  110. edict_t *pentPlayer = UTIL_FindClientInPVS( pGib->edict() );
  111. if ( random->RandomInt ( 0, 100 ) <= 5 && pentPlayer )
  112. {
  113. // 5% chance head will be thrown at player's face.
  114. CBasePlayer *player = (CBasePlayer *)CBaseEntity::Instance( pentPlayer );
  115. if ( player )
  116. {
  117. vecNewVelocity = ( player->EyePosition() ) - pGib->GetAbsOrigin();
  118. VectorNormalize(vecNewVelocity);
  119. vecNewVelocity *= 300;
  120. vecNewVelocity.z += 100;
  121. }
  122. }
  123. else
  124. {
  125. vecNewVelocity = Vector (random->RandomFloat(-100,100), random->RandomFloat(-100,100), random->RandomFloat(200,300));
  126. }
  127. QAngle vecNewAngularVelocity = pGib->GetLocalAngularVelocity();
  128. vecNewAngularVelocity.x = random->RandomFloat ( 100, 200 );
  129. vecNewAngularVelocity.y = random->RandomFloat ( 100, 300 );
  130. pGib->SetLocalAngularVelocity( vecNewAngularVelocity );
  131. // copy owner's blood color
  132. pGib->SetBloodColor( pVictim->BloodColor() );
  133. pGib->AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity );
  134. pGib->SetAbsVelocity( vecNewVelocity );
  135. }
  136. pGib->LimitVelocity();
  137. }
  138. //-----------------------------------------------------------------------------
  139. // Blood color (see BLOOD_COLOR_* macros in baseentity.h)
  140. //-----------------------------------------------------------------------------
  141. void CGib::SetBloodColor( int nBloodColor )
  142. {
  143. m_bloodColor = nBloodColor;
  144. }
  145. //------------------------------------------------------------------------------
  146. // A little piece of duplicated code
  147. //------------------------------------------------------------------------------
  148. void CGib::AdjustVelocityBasedOnHealth( int nHealth, Vector &vecVelocity )
  149. {
  150. if ( nHealth > -50)
  151. {
  152. vecVelocity *= 0.7;
  153. }
  154. else if ( nHealth > -200)
  155. {
  156. vecVelocity *= 2;
  157. }
  158. else
  159. {
  160. vecVelocity *= 4;
  161. }
  162. }
  163. //------------------------------------------------------------------------------
  164. // Purpose : Initialize a gibs position and velocity
  165. // Input :
  166. // Output :
  167. //------------------------------------------------------------------------------
  168. void CGib::InitGib( CBaseEntity *pVictim, float fMinVelocity, float fMaxVelocity )
  169. {
  170. // ------------------------------------------------------------------------
  171. // If have a pVictim spawn the gib somewhere in the pVictim's bounding volume
  172. // ------------------------------------------------------------------------
  173. if ( pVictim )
  174. {
  175. // Find a random position within the bounding box (add 1 to Z to get it out of the ground)
  176. Vector vecOrigin;
  177. pVictim->CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecOrigin );
  178. vecOrigin.z += 1.0f;
  179. SetAbsOrigin( vecOrigin );
  180. // make the gib fly away from the attack vector
  181. Vector vecNewVelocity = g_vecAttackDir * -1;
  182. // mix in some noise
  183. vecNewVelocity.x += random->RandomFloat ( -0.25, 0.25 );
  184. vecNewVelocity.y += random->RandomFloat ( -0.25, 0.25 );
  185. vecNewVelocity.z += random->RandomFloat ( -0.25, 0.25 );
  186. vecNewVelocity *= random->RandomFloat ( fMaxVelocity, fMinVelocity );
  187. QAngle vecNewAngularVelocity = GetLocalAngularVelocity();
  188. vecNewAngularVelocity.x = random->RandomFloat ( 100, 200 );
  189. vecNewAngularVelocity.y = random->RandomFloat ( 100, 300 );
  190. SetLocalAngularVelocity( vecNewAngularVelocity );
  191. // copy owner's blood color
  192. SetBloodColor( pVictim->BloodColor() );
  193. AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity );
  194. // Attempt to be physical if we can
  195. if ( VPhysicsInitNormal( SOLID_BBOX, 0, false ) )
  196. {
  197. IPhysicsObject *pObj = VPhysicsGetObject();
  198. if ( pObj != NULL )
  199. {
  200. AngularImpulse angImpulse = RandomAngularImpulse( -500, 500 );
  201. pObj->AddVelocity( &vecNewVelocity, &angImpulse );
  202. }
  203. }
  204. else
  205. {
  206. SetSolid( SOLID_BBOX );
  207. SetCollisionBounds( vec3_origin, vec3_origin );
  208. SetAbsVelocity( vecNewVelocity );
  209. }
  210. SetCollisionGroup( COLLISION_GROUP_DEBRIS );
  211. }
  212. LimitVelocity();
  213. }
  214. //------------------------------------------------------------------------------
  215. // Purpose : Given an .mdl file with gibs and the number of gibs in the file
  216. // spawns them in pVictim's bounding box
  217. // Input :
  218. // Output :
  219. //------------------------------------------------------------------------------
  220. void CGib::SpawnSpecificGibs( CBaseEntity* pVictim,
  221. int nNumGibs,
  222. float vMinVelocity,
  223. float vMaxVelocity,
  224. const char* cModelName,
  225. float flLifetime)
  226. {
  227. for (int i=0;i<nNumGibs;i++)
  228. {
  229. CGib *pGib = CREATE_ENTITY( CGib, "gib" );
  230. pGib->Spawn( cModelName );
  231. pGib->m_nBody = i;
  232. pGib->InitGib( pVictim, vMinVelocity, vMaxVelocity );
  233. pGib->m_lifeTime = flLifetime;
  234. if ( pVictim != NULL )
  235. {
  236. pGib->SetOwnerEntity( pVictim );
  237. }
  238. }
  239. }
  240. //------------------------------------------------------------------------------
  241. // Purpose : Spawn random gibs of the given gib type
  242. // Input :
  243. // Output :
  244. //------------------------------------------------------------------------------
  245. void CGib::SpawnRandomGibs( CBaseEntity *pVictim, int cGibs, GibType_e eGibType )
  246. {
  247. int cSplat;
  248. for ( cSplat = 0 ; cSplat < cGibs ; cSplat++ )
  249. {
  250. CGib *pGib = CREATE_ENTITY( CGib, "gib" );
  251. if ( g_Language.GetInt() == LANGUAGE_GERMAN )
  252. {
  253. pGib->Spawn( "models/germangibs.mdl" );
  254. pGib->m_nBody = random->RandomInt(0,GERMAN_GIB_COUNT-1);
  255. }
  256. else
  257. {
  258. switch (eGibType)
  259. {
  260. case GIB_HUMAN:
  261. // human pieces
  262. pGib->Spawn( "models/gibs/hgibs.mdl" );
  263. pGib->m_nBody = random->RandomInt(1,HUMAN_GIB_COUNT-1);// start at one to avoid throwing random amounts of skulls (0th gib)
  264. break;
  265. case GIB_ALIEN:
  266. // alien pieces
  267. pGib->Spawn( "models/gibs/agibs.mdl" );
  268. pGib->m_nBody = random->RandomInt(0,ALIEN_GIB_COUNT-1);
  269. break;
  270. }
  271. }
  272. pGib->InitGib( pVictim, 300, 400);
  273. }
  274. }
  275. //=========================================================
  276. // WaitTillLand - in order to emit their meaty scent from
  277. // the proper location, gibs should wait until they stop
  278. // bouncing to emit their scent. That's what this function
  279. // does.
  280. //=========================================================
  281. void CGib::WaitTillLand ( void )
  282. {
  283. if (!IsInWorld())
  284. {
  285. UTIL_Remove( this );
  286. return;
  287. }
  288. if ( GetAbsVelocity() == vec3_origin )
  289. {
  290. SetRenderAlpha( 255 );
  291. m_nRenderMode = kRenderTransTexture;
  292. if ( GetMoveType() != MOVETYPE_VPHYSICS )
  293. {
  294. AddSolidFlags( FSOLID_NOT_SOLID );
  295. }
  296. SetLocalAngularVelocity( vec3_angle );
  297. SetNextThink( gpGlobals->curtime + m_lifeTime );
  298. SetThink ( &CGib::SUB_FadeOut );
  299. if ( GetSprite() )
  300. {
  301. CSprite *pSprite = dynamic_cast<CSprite*>( GetSprite() );
  302. if ( pSprite )
  303. {
  304. //Adrian - Why am I doing this? Check InitPointGib for the answer!
  305. if ( m_lifeTime == 0 )
  306. m_lifeTime = random->RandomFloat( 1, 3 );
  307. pSprite->FadeAndDie( m_lifeTime );
  308. }
  309. }
  310. if ( GetFlame() )
  311. {
  312. CEntityFlame *pFlame = dynamic_cast< CEntityFlame*>( GetFlame() );
  313. if ( pFlame )
  314. {
  315. pFlame->SetLifetime( 1.0f );
  316. }
  317. }
  318. // If you bleed, you stink!
  319. if ( m_bloodColor != DONT_BLEED )
  320. {
  321. // ok, start stinkin!
  322. // FIXME: It's too easy to fill up the sound queue with all these meat sounds
  323. // CSoundEnt::InsertSound ( SOUND_MEAT, GetAbsOrigin(), 384, 25 );
  324. }
  325. }
  326. else
  327. {
  328. // wait and check again in another half second.
  329. SetNextThink( gpGlobals->curtime + 0.5f );
  330. }
  331. }
  332. bool CGib::SUB_AllowedToFade( void )
  333. {
  334. if( VPhysicsGetObject() )
  335. {
  336. if( VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD || GetEFlags() & EFL_IS_BEING_LIFTED_BY_BARNACLE )
  337. return false;
  338. }
  339. CBasePlayer *pPlayer = ( AI_IsSinglePlayer() ) ? UTIL_GetLocalPlayer() : NULL;
  340. if ( pPlayer && pPlayer->FInViewCone( this ) && m_bForceRemove == false )
  341. {
  342. // We don't want Gibs to fade out while onscreen... but we also can't allow an infinite
  343. // number of gibs accumulate, so let the oldest ones fade out if we're over the limit.
  344. int nGibsToKill = s_ExtantGibs.Count() - MAX_CONCURRENT_GIBS;
  345. for ( int i = 0; i < nGibsToKill; i++ )
  346. {
  347. if ( this == s_ExtantGibs[ i ] )
  348. return true;
  349. }
  350. return false;
  351. }
  352. return true;
  353. }
  354. void CGib::DieThink ( void )
  355. {
  356. if ( GetSprite() )
  357. {
  358. CSprite *pSprite = dynamic_cast<CSprite*>( GetSprite() );
  359. if ( pSprite )
  360. {
  361. pSprite->FadeAndDie( 0.0 );
  362. }
  363. }
  364. if ( GetFlame() )
  365. {
  366. CEntityFlame *pFlame = dynamic_cast< CEntityFlame*>( GetFlame() );
  367. if ( pFlame )
  368. {
  369. pFlame->SetLifetime( 1.0f );
  370. }
  371. }
  372. if ( g_pGameRules->IsMultiplayer() )
  373. {
  374. UTIL_Remove( this );
  375. }
  376. else
  377. {
  378. SetThink ( &CGib::SUB_FadeOut );
  379. SetNextThink( gpGlobals->curtime );
  380. }
  381. }
  382. //-----------------------------------------------------------------------------
  383. // Purpose:
  384. //-----------------------------------------------------------------------------
  385. void CGib::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  386. {
  387. CBasePlayer *pPlayer = ToBasePlayer( pActivator );
  388. if ( pPlayer )
  389. {
  390. pPlayer->PickupObject( this );
  391. }
  392. }
  393. //-----------------------------------------------------------------------------
  394. // Physics Attacker
  395. //-----------------------------------------------------------------------------
  396. void CGib::SetPhysicsAttacker( CBasePlayer *pEntity, float flTime )
  397. {
  398. m_hPhysicsAttacker = pEntity;
  399. m_flLastPhysicsInfluenceTime = flTime;
  400. }
  401. //-----------------------------------------------------------------------------
  402. // Purpose: Keep track of physgun influence
  403. //-----------------------------------------------------------------------------
  404. void CGib::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason )
  405. {
  406. SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime );
  407. }
  408. //-----------------------------------------------------------------------------
  409. // Purpose:
  410. //-----------------------------------------------------------------------------
  411. void CGib::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason )
  412. {
  413. SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime );
  414. }
  415. //-----------------------------------------------------------------------------
  416. //-----------------------------------------------------------------------------
  417. CBasePlayer *CGib::HasPhysicsAttacker( float dt )
  418. {
  419. if (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime)
  420. {
  421. return m_hPhysicsAttacker;
  422. }
  423. return NULL;
  424. }
  425. //
  426. // Gib bounces on the ground or wall, sponges some blood down, too!
  427. //
  428. void CGib::BounceGibTouch ( CBaseEntity *pOther )
  429. {
  430. Vector vecSpot;
  431. trace_t tr;
  432. IPhysicsObject *pPhysics = VPhysicsGetObject();
  433. if ( pPhysics )
  434. return;
  435. //if ( random->RandomInt(0,1) )
  436. // return;// don't bleed everytime
  437. if (GetFlags() & FL_ONGROUND)
  438. {
  439. SetAbsVelocity( GetAbsVelocity() * 0.9 );
  440. QAngle angles = GetLocalAngles();
  441. angles.x = 0;
  442. angles.z = 0;
  443. SetLocalAngles( angles );
  444. QAngle angVel = GetLocalAngularVelocity();
  445. angVel.x = 0;
  446. angVel.z = 0;
  447. SetLocalAngularVelocity( vec3_angle );
  448. }
  449. else
  450. {
  451. if ( g_Language.GetInt() != LANGUAGE_GERMAN && m_cBloodDecals > 0 && m_bloodColor != DONT_BLEED )
  452. {
  453. vecSpot = GetAbsOrigin() + Vector ( 0 , 0 , 8 );//move up a bit, and trace down.
  454. UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -24 ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr);
  455. UTIL_BloodDecalTrace( &tr, m_bloodColor );
  456. m_cBloodDecals--;
  457. }
  458. if ( m_material != matNone && random->RandomInt(0,2) == 0 )
  459. {
  460. float volume;
  461. float zvel = fabs(GetAbsVelocity().z);
  462. volume = 0.8f * MIN(1.0, ((float)zvel) / 450.0f);
  463. CBreakable::MaterialSoundRandom( entindex(), (Materials)m_material, volume );
  464. }
  465. }
  466. }
  467. //
  468. // Sticky gib puts blood on the wall and stays put.
  469. //
  470. void CGib::StickyGibTouch ( CBaseEntity *pOther )
  471. {
  472. Vector vecSpot;
  473. trace_t tr;
  474. SetThink ( &CGib::SUB_Remove );
  475. SetNextThink( gpGlobals->curtime + 10 );
  476. if ( !FClassnameIs( pOther, "worldspawn" ) )
  477. {
  478. SetNextThink( gpGlobals->curtime );
  479. return;
  480. }
  481. UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity() * 32, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr);
  482. UTIL_BloodDecalTrace( &tr, m_bloodColor );
  483. Vector vecForward = tr.plane.normal * -1;
  484. QAngle angles;
  485. VectorAngles( vecForward, angles );
  486. SetLocalAngles( angles );
  487. SetAbsVelocity( vec3_origin );
  488. SetLocalAngularVelocity( vec3_angle );
  489. SetMoveType( MOVETYPE_NONE );
  490. }
  491. //-----------------------------------------------------------------------------
  492. // CGib destructor
  493. //-----------------------------------------------------------------------------
  494. CGib::~CGib( void )
  495. {
  496. // NOTE: this should not be slow, because MAX_CONCURRENT_GIBS should not be large
  497. int nIndex = s_ExtantGibs.Find( this );
  498. if ( nIndex >= 0 )
  499. s_ExtantGibs.Remove( nIndex );
  500. else
  501. ExecuteNTimes( 20, Warning( "CGibs are being created which circumvent Spawn() - this can result in a leak.\n" ) );
  502. }
  503. //-----------------------------------------------------------------------------
  504. // Spawn a gib with a finite lifetime, after which it will fade out.
  505. //-----------------------------------------------------------------------------
  506. void CGib::Spawn( const char *szGibModel, float flLifetime )
  507. {
  508. SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
  509. SetFriction(0.55); // deading the bounce a bit
  510. // sometimes an entity inherits the edict from a former piece of glass,
  511. // and will spawn using the same render FX or m_nRenderMode! bad!
  512. SetRenderAlpha( 255 );
  513. m_nRenderMode = kRenderNormal;
  514. m_nRenderFX = kRenderFxNone;
  515. // hopefully this will fix the VELOCITY TOO LOW crap
  516. m_takedamage = DAMAGE_EVENTS_ONLY;
  517. SetSolid( SOLID_BBOX );
  518. AddSolidFlags( FSOLID_NOT_STANDABLE );
  519. SetCollisionGroup( COLLISION_GROUP_DEBRIS );
  520. SetModel( szGibModel );
  521. SetNextThink( gpGlobals->curtime + 4 );
  522. m_lifeTime = flLifetime;
  523. SetTouch ( &CGib::BounceGibTouch );
  524. m_bForceRemove = false;
  525. m_material = matNone;
  526. m_cBloodDecals = 5;// how many blood decals this gib can place (1 per bounce until none remain).
  527. // Make sure the gib dies within its alotted lifetime
  528. s_ExtantGibs.AddToTail( this );
  529. SetThink ( &CGib::SUB_FadeOut );
  530. SetNextThink( gpGlobals->curtime + m_lifeTime );
  531. }
  532. LINK_ENTITY_TO_CLASS( gib, CGib );
  533. CBaseEntity *CreateRagGib( const char *szModel, const Vector &vecOrigin, const QAngle &vecAngles, const Vector &vecForce, float flFadeTime, bool bShouldIgnite )
  534. {
  535. CRagGib *pGib;
  536. pGib = (CRagGib*)CreateEntityByName( "raggib" );
  537. pGib->SetLocalAngles( vecAngles );
  538. if ( !pGib )
  539. {
  540. Msg( "**Can't create ragdoll gib!\n" );
  541. return NULL;
  542. }
  543. if ( bShouldIgnite )
  544. {
  545. CBaseAnimating *pAnimating = pGib->GetBaseAnimating();
  546. if (pAnimating != NULL )
  547. {
  548. pAnimating->Ignite( random->RandomFloat( 8.0, 12.0 ), false );
  549. }
  550. }
  551. pGib->Spawn( szModel, vecOrigin, vecForce, flFadeTime );
  552. return pGib;
  553. }
  554. void CRagGib::Spawn( const char *szModel, const Vector &vecOrigin, const Vector &vecForce, float flFadeTime = 0.0 )
  555. {
  556. SetSolid( SOLID_BBOX );
  557. AddSolidFlags( FSOLID_NOT_SOLID );
  558. SetModel( szModel );
  559. UTIL_SetSize(this, vec3_origin, vec3_origin);
  560. UTIL_SetOrigin( this, vecOrigin );
  561. if ( !BecomeRagdollOnClient( vecForce ) )
  562. {
  563. AddSolidFlags( FSOLID_NOT_STANDABLE );
  564. RemoveSolidFlags( FSOLID_NOT_SOLID );
  565. if( flFadeTime > 0.0 )
  566. {
  567. SUB_StartFadeOut( flFadeTime );
  568. }
  569. }
  570. }
  571. LINK_ENTITY_TO_CLASS( raggib, CRagGib );