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.

696 lines
19 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Grenade used by the city scanner
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "grenade_homer.h"
  9. #include "weapon_ar2.h"
  10. #include "soundent.h"
  11. #include "decals.h"
  12. #include "shake.h"
  13. #include "smoke_trail.h"
  14. #include "ar2_explosion.h"
  15. #include "mathlib/mathlib.h"
  16. #include "game.h"
  17. #include "ndebugoverlay.h"
  18. #include "hl2_shareddefs.h"
  19. #include "vstdlib/random.h"
  20. #include "engine/IEngineSound.h"
  21. #include "movevars_shared.h"
  22. // memdbgon must be the last include file in a .cpp file!!!
  23. #include "tier0/memdbgon.h"
  24. #define HOMER_TRAIL0_LIFE 0.1
  25. #define HOMER_TRAIL1_LIFE 0.2
  26. #define HOMER_TRAIL2_LIFE 3.0// 1.0
  27. extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the smoke cloud
  28. ConVar sk_dmg_homer_grenade( "sk_dmg_homer_grenade","0" );
  29. ConVar sk_homer_grenade_radius( "sk_homer_grenade_radius","0" );
  30. BEGIN_DATADESC( CGrenadeHomer )
  31. DEFINE_ARRAY( m_hRocketTrail, FIELD_EHANDLE, 3 ),
  32. DEFINE_FIELD( m_sFlySound, FIELD_STRING),
  33. DEFINE_FIELD( m_flNextFlySoundTime, FIELD_TIME),
  34. DEFINE_FIELD( m_flHomingStrength, FIELD_FLOAT),
  35. DEFINE_FIELD( m_flHomingDelay, FIELD_FLOAT),
  36. DEFINE_FIELD( m_flHomingRampUp, FIELD_FLOAT),
  37. DEFINE_FIELD( m_flHomingDuration, FIELD_FLOAT),
  38. DEFINE_FIELD( m_flHomingRampDown, FIELD_FLOAT),
  39. DEFINE_FIELD( m_flHomingSpeed, FIELD_FLOAT),
  40. DEFINE_FIELD( m_flSpinMagnitude, FIELD_FLOAT),
  41. DEFINE_FIELD( m_flSpinSpeed, FIELD_FLOAT),
  42. DEFINE_FIELD( m_nRocketTrailType, FIELD_INTEGER),
  43. // DEFINE_FIELD( m_spriteTexture, FIELD_INTEGER),
  44. DEFINE_FIELD( m_flHomingLaunchTime, FIELD_TIME),
  45. DEFINE_FIELD( m_flHomingStartTime, FIELD_TIME ),
  46. DEFINE_FIELD( m_flHomingEndTime, FIELD_TIME ),
  47. DEFINE_FIELD( m_flSpinOffset, FIELD_FLOAT),
  48. DEFINE_FIELD( m_hTarget, FIELD_EHANDLE),
  49. // Function pointers
  50. DEFINE_THINKFUNC( AimThink ),
  51. DEFINE_ENTITYFUNC( GrenadeHomerTouch ),
  52. END_DATADESC()
  53. LINK_ENTITY_TO_CLASS( grenade_homer, CGrenadeHomer );
  54. ///------------------------------------------------------------------------------
  55. // Purpose :
  56. // Input :
  57. // Output :
  58. //------------------------------------------------------------------------------
  59. CGrenadeHomer* CGrenadeHomer::CreateGrenadeHomer( string_t sModelName, string_t sFlySound, const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner )
  60. {
  61. CGrenadeHomer *pGrenade = (CGrenadeHomer*)CreateEntityByName( "grenade_homer" );
  62. if ( !pGrenade )
  63. {
  64. Warning( "NULL Ent in Create!\n" );
  65. return NULL;
  66. }
  67. if ( pGrenade->edict() )
  68. {
  69. pGrenade->m_sFlySound = sFlySound;
  70. pGrenade->SetOwnerEntity( Instance( pentOwner ) );
  71. pGrenade->SetLocalOrigin( vecOrigin );
  72. pGrenade->SetLocalAngles( vecAngles );
  73. pGrenade->SetModel( STRING(sModelName) );
  74. }
  75. return pGrenade;
  76. }
  77. void CGrenadeHomer::Precache( void )
  78. {
  79. m_spriteTexture = PrecacheModel( "sprites/lgtning.vmt" );
  80. PrecacheScriptSound( "GrenadeHomer.StopSounds" );
  81. if ( NULL_STRING != m_sFlySound )
  82. {
  83. PrecacheScriptSound( STRING(m_sFlySound) );
  84. }
  85. }
  86. //------------------------------------------------------------------------------
  87. // Purpose :
  88. // Input :
  89. // Output :
  90. //------------------------------------------------------------------------------
  91. void CGrenadeHomer::Spawn( void )
  92. {
  93. Precache( );
  94. SetSolid( SOLID_BBOX );
  95. SetMoveType( MOVETYPE_FLY );
  96. UTIL_SetSize(this, Vector(0, 0, 0), Vector(0, 0, 0));
  97. m_flDamage = sk_dmg_homer_grenade.GetFloat();
  98. m_DmgRadius = sk_homer_grenade_radius.GetFloat();
  99. m_takedamage = DAMAGE_YES;
  100. m_iHealth = 1;
  101. SetGravity( 1.0 );
  102. SetFriction( 0.8 );
  103. SetSequence( 1 );
  104. m_flHomingStrength = 0;
  105. m_flHomingDelay = 0;
  106. m_flHomingDuration = 0;
  107. SetCollisionGroup( HL2COLLISION_GROUP_HOMING_MISSILE );
  108. }
  109. //------------------------------------------------------------------------------
  110. // Purpose :
  111. // Input :
  112. // Output :
  113. //------------------------------------------------------------------------------
  114. void CGrenadeHomer::SetSpin(float flSpinMagnitude, float flSpinSpeed)
  115. {
  116. m_flSpinMagnitude = flSpinMagnitude;
  117. m_flSpinSpeed = flSpinSpeed;
  118. m_flSpinOffset = random->RandomInt(-m_flSpinSpeed,m_flSpinSpeed);
  119. }
  120. //------------------------------------------------------------------------------
  121. // Purpose :
  122. // Input :
  123. // Output :
  124. //------------------------------------------------------------------------------
  125. void CGrenadeHomer::SetHoming(float flStrength, float flDelay, float flRampUp, float flDuration, float flRampDown)
  126. {
  127. m_flHomingStrength = flStrength;
  128. m_flHomingDelay = flDelay;
  129. m_flHomingRampUp = flRampUp;
  130. m_flHomingDuration = flDuration;
  131. m_flHomingRampDown = flRampDown;
  132. }
  133. //------------------------------------------------------------------------------
  134. // Purpose :
  135. // Input :
  136. // Output :
  137. //------------------------------------------------------------------------------
  138. void CGrenadeHomer::StartRocketTrail(void)
  139. {
  140. RocketTrail *pRocketTrail = RocketTrail::CreateRocketTrail();
  141. if(pRocketTrail)
  142. {
  143. pRocketTrail->m_SpawnRate = 80;
  144. pRocketTrail->m_ParticleLifetime = 2;
  145. if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN )
  146. {
  147. pRocketTrail->m_StartColor.Init(0.5, 0.0, 0.5);
  148. }
  149. else
  150. {
  151. pRocketTrail->m_StartColor.Init(0.75, 0.75, 0.75);
  152. }
  153. pRocketTrail->m_Opacity = 0.35f;
  154. pRocketTrail->m_EndColor.Init(0.4,0.4,0.4);
  155. pRocketTrail->m_StartSize = 8;
  156. pRocketTrail->m_EndSize = 16;
  157. pRocketTrail->m_SpawnRadius = 3;
  158. pRocketTrail->m_MinSpeed = 2;
  159. pRocketTrail->m_MaxSpeed = 10;
  160. pRocketTrail->SetLifetime(120);
  161. pRocketTrail->FollowEntity(this);
  162. m_hRocketTrail[0] = pRocketTrail;
  163. }
  164. /*
  165. pRocketTrail = RocketTrail::CreateRocketTrail();
  166. if(pRocketTrail)
  167. {
  168. pRocketTrail->m_SpawnRate = 100;
  169. pRocketTrail->m_ParticleLifetime = HOMER_TRAIL1_LIFE;
  170. if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN )
  171. {
  172. pRocketTrail->m_StartColor.Init(0.0, 0.0, 0.5);
  173. }
  174. else
  175. {
  176. pRocketTrail->m_StartColor.Init(0.5, 0.5, 0.0);
  177. }
  178. pRocketTrail->m_EndColor.Init(0.5,0.5,0.5);
  179. pRocketTrail->m_StartSize = 3;
  180. pRocketTrail->m_EndSize = 6;
  181. pRocketTrail->m_SpawnRadius = 1;
  182. pRocketTrail->m_MinSpeed = 15;
  183. pRocketTrail->m_MaxSpeed = 25;
  184. pRocketTrail->SetLifetime(120);
  185. pRocketTrail->FollowEntity(this);
  186. m_hRocketTrail[1] = pRocketTrail;
  187. }
  188. pRocketTrail = RocketTrail::CreateRocketTrail();
  189. if(pRocketTrail)
  190. {
  191. pRocketTrail->m_SpawnRate = 50;
  192. pRocketTrail->m_ParticleLifetime = HOMER_TRAIL2_LIFE;
  193. if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN )
  194. {
  195. pRocketTrail->m_StartColor.Init(0.1, 0.0, 0.1);
  196. }
  197. else
  198. {
  199. pRocketTrail->m_StartColor.Init(0.1, 0.1, 0.1);
  200. }
  201. pRocketTrail->m_EndColor.Init(0.5,0.5,0.5);
  202. pRocketTrail->m_StartSize = 8;
  203. pRocketTrail->m_EndSize = 20;
  204. pRocketTrail->m_SpawnRadius = 1;
  205. pRocketTrail->m_MinSpeed = 15;
  206. pRocketTrail->m_MaxSpeed = 25;
  207. pRocketTrail->SetLifetime(120);
  208. pRocketTrail->FollowEntity(this);
  209. m_hRocketTrail[2] = pRocketTrail;
  210. }
  211. */
  212. }
  213. //------------------------------------------------------------------------------
  214. // Purpose :
  215. // Input :
  216. // Output :
  217. //------------------------------------------------------------------------------
  218. void CGrenadeHomer::UpdateRocketTrail(float fScale)
  219. {
  220. if (m_hRocketTrail[0] == NULL)
  221. {
  222. StartRocketTrail();
  223. }
  224. if (m_hRocketTrail[0])
  225. {
  226. m_hRocketTrail[0]->m_ParticleLifetime = fScale*HOMER_TRAIL0_LIFE;
  227. }
  228. if (m_hRocketTrail[1])
  229. {
  230. m_hRocketTrail[1]->m_ParticleLifetime = fScale*HOMER_TRAIL1_LIFE;
  231. }
  232. if (m_hRocketTrail[2])
  233. {
  234. m_hRocketTrail[2]->m_ParticleLifetime = fScale*HOMER_TRAIL2_LIFE;
  235. }
  236. }
  237. void CGrenadeHomer::StopRocketTrail()
  238. {
  239. // Stop emitting smoke
  240. for (int i=0;i<3;i++)
  241. {
  242. if(m_hRocketTrail[i])
  243. {
  244. m_hRocketTrail[i]->SetEmit(false);
  245. UTIL_Remove( m_hRocketTrail[i] );
  246. m_hRocketTrail[i] = NULL;
  247. }
  248. }
  249. }
  250. //------------------------------------------------------------------------------
  251. // Purpose :
  252. // Input :
  253. // Output :
  254. //------------------------------------------------------------------------------
  255. void CGrenadeHomer::Launch( CBaseEntity* pOwner,
  256. CBaseEntity* pTarget,
  257. const Vector& vInitVelocity,
  258. float flHomingSpeed,
  259. float flGravity,
  260. int nRocketTrailType)
  261. {
  262. SetOwnerEntity( pOwner );
  263. m_hTarget = pTarget;
  264. SetAbsVelocity( vInitVelocity );
  265. m_flHomingSpeed = flHomingSpeed;
  266. SetGravity( flGravity );
  267. m_nRocketTrailType = nRocketTrailType;
  268. // ----------------------------
  269. // Initialize homing parameters
  270. // ----------------------------
  271. m_flHomingLaunchTime = gpGlobals->curtime;
  272. // -------------
  273. // Smoke trail.
  274. // -------------
  275. if ( (m_nRocketTrailType == HOMER_SMOKE_TRAIL_ON) || (m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN) )
  276. {
  277. StartRocketTrail();
  278. }
  279. SetUse( &CGrenadeHomer::DetonateUse );
  280. SetTouch( &CGrenadeHomer::GrenadeHomerTouch );
  281. SetThink( &CGrenadeHomer::AimThink );
  282. AimThink();
  283. SetNextThink( gpGlobals->curtime );
  284. // Issue danger!
  285. if ( pTarget )
  286. {
  287. // Figure out how long it'll take for me to reach the target.
  288. float flDist = ( pTarget->WorldSpaceCenter() - WorldSpaceCenter() ).Length();
  289. float flTime = MAX( 0.5, flDist / GetAbsVelocity().Length() );
  290. CSoundEnt::InsertSound ( SOUND_DANGER, m_hTarget->GetAbsOrigin(), 300, flTime, pOwner );
  291. }
  292. }
  293. //------------------------------------------------------------------------------
  294. // Purpose :
  295. // Input :
  296. // Output :
  297. //------------------------------------------------------------------------------
  298. void CGrenadeHomer::Event_Killed( const CTakeDamageInfo &info )
  299. {
  300. Detonate( );
  301. }
  302. void CGrenadeHomer::GrenadeHomerTouch( CBaseEntity *pOther )
  303. {
  304. Assert( pOther );
  305. // Don't take damage from other homing grenades so can shoot in vollies
  306. if (FClassnameIs( pOther, "grenade_homer") || !pOther->IsSolid() )
  307. {
  308. return;
  309. }
  310. // ----------------------------------
  311. // If I hit the sky, don't explode
  312. // ----------------------------------
  313. trace_t tr;
  314. UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity(), MASK_SOLID_BRUSHONLY,
  315. this, COLLISION_GROUP_NONE, &tr);
  316. if (tr.surface.flags & SURF_SKY)
  317. {
  318. StopRocketTrail();
  319. UTIL_Remove( this );
  320. }
  321. else
  322. {
  323. Detonate();
  324. }
  325. }
  326. void CGrenadeHomer::Detonate(void)
  327. {
  328. StopRocketTrail();
  329. StopSound(entindex(), CHAN_BODY, STRING(m_sFlySound));
  330. m_takedamage = DAMAGE_NO;
  331. CPASFilter filter( GetAbsOrigin() );
  332. te->Explosion( filter, 0.0,
  333. &GetAbsOrigin(),
  334. g_sModelIndexFireball,
  335. 2.0,
  336. 15,
  337. TE_EXPLFLAG_NONE,
  338. m_DmgRadius,
  339. m_flDamage );
  340. // int magnitude = 1.0;
  341. // int colorRamp = random->RandomInt( 128, 255 );
  342. if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN )
  343. {
  344. // Add a shockring
  345. CBroadcastRecipientFilter filter3;
  346. te->BeamRingPoint( filter3, 0,
  347. GetAbsOrigin(), //origin
  348. 16, //start radius
  349. 1000, //end radius
  350. m_spriteTexture, //texture
  351. 0, //halo index
  352. 0, //start frame
  353. 2, //framerate
  354. 0.3f, //life
  355. 128, //width
  356. 16, //spread
  357. 0, //amplitude
  358. 100, //r
  359. 0, //g
  360. 200, //b
  361. 50, //a
  362. 128 //speed
  363. );
  364. // Add a shockring
  365. CBroadcastRecipientFilter filter4;
  366. te->BeamRingPoint( filter4, 0,
  367. GetAbsOrigin(), //origin
  368. 16, //start radius
  369. 500, //end radius
  370. m_spriteTexture, //texture
  371. 0, //halo index
  372. 0, //start frame
  373. 2, //framerate
  374. 0.3f, //life
  375. 128, //width
  376. 16, //spread
  377. 0, //amplitude
  378. 200, //r
  379. 0, //g
  380. 100, //b
  381. 50, //a
  382. 128 //speed
  383. );
  384. }
  385. Vector vecForward = GetAbsVelocity();
  386. VectorNormalize(vecForward);
  387. trace_t tr;
  388. UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + 60*vecForward, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, & tr);
  389. UTIL_DecalTrace( &tr, "Scorch" );
  390. UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START );
  391. RadiusDamage ( CTakeDamageInfo( this, GetOwnerEntity(), m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL );
  392. CPASAttenuationFilter filter2( this, "GrenadeHomer.StopSounds" );
  393. EmitSound( filter2, entindex(), "GrenadeHomer.StopSounds" );
  394. UTIL_Remove( this );
  395. }
  396. //-----------------------------------------------------------------------------
  397. // Purpose:
  398. // Input :
  399. // Output :
  400. //-----------------------------------------------------------------------------
  401. void CGrenadeHomer::PlayFlySound(void)
  402. {
  403. if (gpGlobals->curtime > m_flNextFlySoundTime)
  404. {
  405. CPASAttenuationFilter filter( this, 0.8 );
  406. EmitSound_t ep;
  407. ep.m_nChannel = CHAN_BODY;
  408. ep.m_pSoundName = STRING(m_sFlySound);
  409. ep.m_flVolume = 1.0f;
  410. ep.m_SoundLevel = SNDLVL_NORM;
  411. ep.m_nPitch = 100;
  412. EmitSound( filter, entindex(), ep );
  413. m_flNextFlySoundTime = gpGlobals->curtime + 1.0;
  414. }
  415. }
  416. //------------------------------------------------------------------------------
  417. // Purpose : Move toward targetmap
  418. // Input :
  419. // Output :
  420. //------------------------------------------------------------------------------
  421. void CGrenadeHomer::AimThink( void )
  422. {
  423. // Blow up the missile if we have an explicit detonate time that
  424. // has been reached
  425. if (m_flDetonateTime != 0 &&
  426. gpGlobals->curtime > m_flDetonateTime)
  427. {
  428. Detonate();
  429. return;
  430. }
  431. PlayFlySound();
  432. Vector vTargetPos = vec3_origin;
  433. Vector vTargetDir;
  434. float flCurHomingStrength = 0;
  435. // ------------------------------------------------
  436. // If I'm homing
  437. // ------------------------------------------------
  438. if (m_hTarget != NULL)
  439. {
  440. vTargetPos = m_hTarget->EyePosition();
  441. vTargetDir = vTargetPos - GetAbsOrigin();
  442. VectorNormalize(vTargetDir);
  443. // --------------------------------------------------
  444. // If my target is far away do some primitive
  445. // obstacle avoidance
  446. // --------------------------------------------------
  447. if ((vTargetPos - GetAbsOrigin()).Length() > 200)
  448. {
  449. Vector vTravelDir = GetAbsVelocity();
  450. VectorNormalize(vTravelDir);
  451. vTravelDir *= 50;
  452. trace_t tr;
  453. UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vTravelDir, MASK_SHOT, m_hTarget, COLLISION_GROUP_NONE, &tr );
  454. if (tr.fraction != 1.0)
  455. {
  456. // Head off in normal
  457. float dotPr = DotProduct(vTravelDir,tr.plane.normal);
  458. Vector vBounce = -dotPr * tr.plane.normal;
  459. vBounce.z = 0;
  460. VectorNormalize(vBounce);
  461. vTargetDir += vBounce;
  462. VectorNormalize(vTargetDir);
  463. // DEBUG TOOL
  464. //NDebugOverlay::Line(GetOrigin(), GetOrigin()+vTravelDir, 255,0,0, true, 20);
  465. //NDebugOverlay::Line(GetOrigin(), GetOrigin()+(12*tr.plane.normal), 0,0,255, true, 20);
  466. //NDebugOverlay::Line(GetOrigin(), GetOrigin()+(vTargetDir), 0,255,0, true, 20);
  467. }
  468. }
  469. float flTargetSpeed = GetAbsVelocity().Length();
  470. float flHomingRampUpStartTime = m_flHomingLaunchTime + m_flHomingDelay;
  471. float flHomingSustainStartTime = flHomingRampUpStartTime + m_flHomingRampUp;
  472. float flHomingRampDownStartTime = flHomingSustainStartTime + m_flHomingDuration;
  473. float flHomingEndHomingTime = flHomingRampDownStartTime + m_flHomingRampDown;
  474. // ---------
  475. // Delay
  476. // ---------
  477. if (gpGlobals->curtime < flHomingRampUpStartTime)
  478. {
  479. flCurHomingStrength = 0;
  480. flTargetSpeed = 0;
  481. }
  482. // ----------
  483. // Ramp Up
  484. // ----------
  485. else if (gpGlobals->curtime < flHomingSustainStartTime)
  486. {
  487. float flAge = gpGlobals->curtime - flHomingRampUpStartTime;
  488. flCurHomingStrength = m_flHomingStrength * (flAge/m_flHomingRampUp);
  489. flTargetSpeed = flCurHomingStrength * m_flHomingSpeed;
  490. }
  491. // ----------
  492. // Sustain
  493. // ----------
  494. else if (gpGlobals->curtime < flHomingRampDownStartTime)
  495. {
  496. flCurHomingStrength = m_flHomingStrength;
  497. flTargetSpeed = m_flHomingSpeed;
  498. }
  499. // -----------
  500. // Ramp Down
  501. // -----------
  502. else if (gpGlobals->curtime < flHomingEndHomingTime)
  503. {
  504. float flAge = gpGlobals->curtime - flHomingRampDownStartTime;
  505. flCurHomingStrength = m_flHomingStrength * (1-(flAge/m_flHomingRampDown));
  506. flTargetSpeed = m_flHomingSpeed;
  507. }
  508. // ---------------
  509. // Set Homing
  510. // ---------------
  511. if (flCurHomingStrength > 0)
  512. {
  513. // -------------
  514. // Smoke trail.
  515. // -------------
  516. if (m_nRocketTrailType == HOMER_SMOKE_TRAIL_ON_HOMING)
  517. {
  518. UpdateRocketTrail(flCurHomingStrength);
  519. }
  520. // Extract speed and direction
  521. Vector vCurDir = GetAbsVelocity();
  522. float flCurSpeed = VectorNormalize(vCurDir);
  523. flTargetSpeed = MAX(flTargetSpeed, flCurSpeed);
  524. // Add in homing direction
  525. Vector vecNewVelocity = GetAbsVelocity();
  526. float flTimeToUse = gpGlobals->frametime;
  527. while (flTimeToUse > 0)
  528. {
  529. vecNewVelocity = (flCurHomingStrength * vTargetDir) + ((1 - flCurHomingStrength) * vCurDir);
  530. flTimeToUse = -0.1;
  531. }
  532. VectorNormalize(vecNewVelocity);
  533. vecNewVelocity *= flTargetSpeed;
  534. SetAbsVelocity( vecNewVelocity );
  535. }
  536. }
  537. // ----------------------------------------------------------------------------------------
  538. // Add time-coherent noise to the current velocity
  539. // ----------------------------------------------------------------------------------------
  540. Vector vecImpulse( 0, 0, 0 );
  541. if (m_flSpinMagnitude > 0)
  542. {
  543. vecImpulse.x += m_flSpinMagnitude*sin(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset);
  544. vecImpulse.y += m_flSpinMagnitude*cos(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset);
  545. vecImpulse.z -= m_flSpinMagnitude*cos(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset);
  546. }
  547. // Add in gravity
  548. vecImpulse.z -= GetGravity() * GetCurrentGravity() * gpGlobals->frametime;
  549. ApplyAbsVelocityImpulse( vecImpulse );
  550. QAngle angles;
  551. VectorAngles( GetAbsVelocity(), angles );
  552. SetLocalAngles( angles );
  553. #if 0 // BUBBLE
  554. if( gpGlobals->curtime > m_flNextWarnTime )
  555. {
  556. // Make a bubble of warning sound in front of me.
  557. const float WARN_INTERVAL = 0.25f;
  558. float flSpeed = GetAbsVelocity().Length();
  559. Vector vecWarnLocation;
  560. // warn a little bit ahead of us, please.
  561. vecWarnLocation = GetAbsOrigin() + GetAbsVelocity() * 0.75;
  562. // Make a bubble of warning ahead of the missile.
  563. CSoundEnt::InsertSound ( SOUND_DANGER, vecWarnLocation, flSpeed * WARN_INTERVAL, 0.5 );
  564. #if 0
  565. Vector vecRight, vecForward;
  566. AngleVectors( GetAbsAngles(), &vecForward, &vecRight, NULL );
  567. NDebugOverlay::Line( vecWarnLocation, vecWarnLocation + vecForward * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10);
  568. NDebugOverlay::Line( vecWarnLocation, vecWarnLocation - vecForward * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10);
  569. NDebugOverlay::Line( vecWarnLocation, vecWarnLocation + vecRight * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10);
  570. NDebugOverlay::Line( vecWarnLocation, vecWarnLocation - vecRight * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10);
  571. #endif
  572. m_flNextWarnTime = gpGlobals->curtime + WARN_INTERVAL;
  573. }
  574. #endif // BUBBLE
  575. SetNextThink( gpGlobals->curtime + 0.1f );
  576. }
  577. //------------------------------------------------------------------------------
  578. // Purpose :
  579. // Input :
  580. // Output :
  581. //------------------------------------------------------------------------------
  582. int CGrenadeHomer::OnTakeDamage( const CTakeDamageInfo &info )
  583. {
  584. // Don't take damage from other homing grenades so can shoot in vollies
  585. if (FClassnameIs( info.GetInflictor(), "grenade_homer"))
  586. {
  587. return 0;
  588. }
  589. return BaseClass::OnTakeDamage( info );
  590. }
  591. //------------------------------------------------------------------------------
  592. // Purpose :
  593. // Input :
  594. // Output :
  595. //------------------------------------------------------------------------------
  596. CGrenadeHomer::CGrenadeHomer(void)
  597. {
  598. for (int i=0;i<3;i++)
  599. {
  600. m_hRocketTrail[i] = NULL;
  601. }
  602. }