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.

679 lines
18 KiB

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