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.

316 lines
9.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "flashbang_projectile.h"
  8. #include "shake.h"
  9. #include "engine/IEngineSound.h"
  10. #include "cs_player.h"
  11. #include "dlight.h"
  12. #include "KeyValues.h"
  13. #include "weapon_csbase.h"
  14. #include "collisionutils.h"
  15. #include "particle_smokegrenade.h"
  16. #include "smoke_fog_overlay_shared.h"
  17. #define GRENADE_MODEL "models/Weapons/w_eq_flashbang_thrown.mdl"
  18. LINK_ENTITY_TO_CLASS( flashbang_projectile, CFlashbangProjectile );
  19. PRECACHE_WEAPON_REGISTER( flashbang_projectile );
  20. float PercentageOfFlashForPlayer(CBaseEntity *player, Vector flashPos, CBaseEntity *pevInflictor)
  21. {
  22. float retval = 0.0f;
  23. trace_t tr;
  24. Vector pos = player->EyePosition();
  25. Vector vecRight, vecUp, vecForward;
  26. AngleVectors( player->EyeAngles(), &vecForward );
  27. QAngle tempAngle;
  28. VectorAngles(player->EyePosition() - flashPos, tempAngle);
  29. AngleVectors(tempAngle, NULL, &vecRight, &vecUp);
  30. vecRight.NormalizeInPlace();
  31. vecUp.NormalizeInPlace();
  32. UTIL_TraceLine( flashPos, pos,
  33. (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_DEBRIS|CONTENTS_MONSTER),
  34. pevInflictor, COLLISION_GROUP_NONE, &tr );
  35. if ((tr.fraction == 1.0) || (tr.m_pEnt == player))
  36. {
  37. retval = 1.0;
  38. }
  39. else
  40. {
  41. return 0.0;
  42. }
  43. CBaseEntity *pSGren;
  44. for( pSGren = gEntList.FindEntityByClassname( NULL, "env_particlesmokegrenade" );
  45. pSGren;
  46. pSGren = gEntList.FindEntityByClassname( pSGren, "env_particlesmokegrenade" ) )
  47. {
  48. ParticleSmokeGrenade *pPSG =( ParticleSmokeGrenade* ) pSGren;
  49. if ( gpGlobals->curtime > pPSG->m_flSpawnTime + pPSG->m_FadeStartTime ) // ignore the smoke grenade if it's fading.
  50. continue;
  51. float flHit1, flHit2;
  52. float flInnerRadius = SMOKEGRENADE_PARTICLERADIUS;
  53. // float flOutterRadius = flInnerRadius + ( 0.5 * SMOKEPARTICLE_SIZE );
  54. Vector vPos = pSGren->GetAbsOrigin();
  55. /*debugoverlay->AddBoxOverlay( pSGren->GetAbsOrigin(), Vector( flInnerRadius, flInnerRadius, flInnerRadius ),
  56. Vector( -flInnerRadius, -flInnerRadius, -flInnerRadius ), QAngle( 0, 0, 0 ), 0, 255, 0, 30, 10 );
  57. debugoverlay->AddBoxOverlay( pSGren->GetAbsOrigin(), Vector( flOutterRadius, flOutterRadius, flOutterRadius ),
  58. Vector( -flOutterRadius, -flOutterRadius, -flOutterRadius ), QAngle( 0, 0, 0 ), 255, 0, 0, 30, 10 ); */
  59. if ( IntersectInfiniteRayWithSphere( pos, vecForward, vPos, flInnerRadius, &flHit1, &flHit2 ) )
  60. {
  61. retval *= 0.8;
  62. }
  63. /* else if ( IntersectInfiniteRayWithSphere( pos, vecForward, vPos, flOutterRadius, &flHit1, &flHit2 ) )
  64. {
  65. retval *= 0.9;
  66. }
  67. */
  68. }
  69. return retval;
  70. }
  71. // --------------------------------------------------------------------------------------------------- //
  72. //
  73. // RadiusDamage - this entity is exploding, or otherwise needs to inflict damage upon entities within a certain range.
  74. //
  75. // only damage ents that can clearly be seen by the explosion!
  76. // --------------------------------------------------------------------------------------------------- //
  77. void RadiusFlash(
  78. Vector vecSrc,
  79. CBaseEntity *pevInflictor,
  80. CBaseEntity *pevAttacker,
  81. float flDamage,
  82. int iClassIgnore,
  83. int bitsDamageType )
  84. {
  85. vecSrc.z += 1;// in case grenade is lying on the ground
  86. if ( !pevAttacker )
  87. pevAttacker = pevInflictor;
  88. trace_t tr;
  89. float flAdjustedDamage;
  90. variant_t var;
  91. Vector vecEyePos;
  92. float fadeTime, fadeHold;
  93. Vector vForward;
  94. Vector vecLOS;
  95. float flDot;
  96. CBaseEntity *pEntity = NULL;
  97. static float flRadius = 1500;
  98. float falloff = flDamage / flRadius;
  99. bool bInWater = (UTIL_PointContents( vecSrc ) == CONTENTS_WATER);
  100. // iterate on all entities in the vicinity.
  101. while ((pEntity = gEntList.FindEntityInSphere( pEntity, vecSrc, flRadius )) != NULL)
  102. {
  103. bool bPlayer = pEntity->IsPlayer();
  104. bool bHostage = ( Q_stricmp( pEntity->GetClassname(), "hostage_entity" ) == 0 );
  105. if( !bPlayer && !bHostage )
  106. continue;
  107. vecEyePos = pEntity->EyePosition();
  108. // blasts don't travel into or out of water
  109. if ( bInWater && pEntity->GetWaterLevel() == 0)
  110. continue;
  111. if (!bInWater && pEntity->GetWaterLevel() == 3)
  112. continue;
  113. float percentageOfFlash = PercentageOfFlashForPlayer(pEntity, vecSrc, pevInflictor);
  114. if ( percentageOfFlash > 0.0 )
  115. {
  116. // decrease damage for an ent that's farther from the grenade
  117. flAdjustedDamage = flDamage - ( vecSrc - pEntity->EyePosition() ).Length() * falloff;
  118. if ( flAdjustedDamage > 0 )
  119. {
  120. // See if we were facing the flash
  121. AngleVectors( pEntity->EyeAngles(), &vForward );
  122. vecLOS = ( vecSrc - vecEyePos );
  123. float flDistance = vecLOS.Length();
  124. // Normalize both vectors so the dotproduct is in the range -1.0 <= x <= 1.0
  125. vecLOS.NormalizeInPlace();
  126. flDot = DotProduct (vecLOS, vForward);
  127. float startingAlpha = 255;
  128. // if target is facing the bomb, the effect lasts longer
  129. if( flDot >= 0.5 )
  130. {
  131. // looking at the flashbang
  132. fadeTime = flAdjustedDamage * 2.5f;
  133. fadeHold = flAdjustedDamage * 1.25f;
  134. }
  135. else if( flDot >= -0.5 )
  136. {
  137. // looking to the side
  138. fadeTime = flAdjustedDamage * 1.75f;
  139. fadeHold = flAdjustedDamage * 0.8f;
  140. }
  141. else
  142. {
  143. // facing away
  144. fadeTime = flAdjustedDamage * 1.0f;
  145. fadeHold = flAdjustedDamage * 0.75f;
  146. startingAlpha = 200;
  147. }
  148. fadeTime *= percentageOfFlash;
  149. fadeHold *= percentageOfFlash;
  150. if ( bPlayer )
  151. {
  152. // blind players and bots
  153. CCSPlayer *player = static_cast< CCSPlayer * >( pEntity );
  154. //=============================================================================
  155. // HPE_BEGIN:
  156. // [tj] Store who was responsible for the most recent flashbang blinding.
  157. //=============================================================================
  158. CCSPlayer *attacker = ToCSPlayer (pevAttacker);
  159. if (attacker && player)
  160. {
  161. player->SetLastFlashbangAttacker(attacker);
  162. }
  163. //=============================================================================
  164. // HPE_END
  165. //=============================================================================
  166. player->Blind( fadeHold, fadeTime, startingAlpha );
  167. // deafen players and bots
  168. player->Deafen( flDistance );
  169. }
  170. else if ( bHostage )
  171. {
  172. variant_t val;
  173. val.SetFloat( fadeTime );
  174. pEntity->AcceptInput( "flashbang", pevInflictor, pevAttacker, val, 0 );
  175. }
  176. }
  177. }
  178. }
  179. CPVSFilter filter(vecSrc);
  180. te->DynamicLight( filter, 0.0, &vecSrc, 255, 255, 255, 2, 400, 0.1, 768 );
  181. }
  182. // --------------------------------------------------------------------------------------------------- //
  183. // CFlashbangProjectile implementation.
  184. // --------------------------------------------------------------------------------------------------- //
  185. CFlashbangProjectile* CFlashbangProjectile::Create(
  186. const Vector &position,
  187. const QAngle &angles,
  188. const Vector &velocity,
  189. const AngularImpulse &angVelocity,
  190. CBaseCombatCharacter *pOwner )
  191. {
  192. CFlashbangProjectile *pGrenade = (CFlashbangProjectile*)CBaseEntity::Create( "flashbang_projectile", position, angles, pOwner );
  193. // Set the timer for 1 second less than requested. We're going to issue a SOUND_DANGER
  194. // one second before detonation.
  195. pGrenade->SetAbsVelocity( velocity );
  196. pGrenade->SetupInitialTransmittedGrenadeVelocity( velocity );
  197. pGrenade->SetThrower( pOwner );
  198. pGrenade->m_flDamage = 100;
  199. pGrenade->ChangeTeam( pOwner->GetTeamNumber() );
  200. pGrenade->SetTouch( &CBaseGrenade::BounceTouch );
  201. pGrenade->SetThink( &CBaseCSGrenadeProjectile::DangerSoundThink );
  202. pGrenade->SetNextThink( gpGlobals->curtime );
  203. pGrenade->SetDetonateTimerLength( 1.5 );
  204. pGrenade->ApplyLocalAngularVelocityImpulse( angVelocity );
  205. pGrenade->SetGravity( BaseClass::GetGrenadeGravity() );
  206. pGrenade->SetFriction( BaseClass::GetGrenadeFriction() );
  207. pGrenade->SetElasticity( BaseClass::GetGrenadeElasticity() );
  208. pGrenade->m_pWeaponInfo = GetWeaponInfo( WEAPON_FLASHBANG );
  209. return pGrenade;
  210. }
  211. void CFlashbangProjectile::Spawn()
  212. {
  213. SetModel( GRENADE_MODEL );
  214. BaseClass::Spawn();
  215. }
  216. void CFlashbangProjectile::Precache()
  217. {
  218. PrecacheModel( GRENADE_MODEL );
  219. PrecacheScriptSound( "Flashbang.Explode" );
  220. PrecacheScriptSound( "Flashbang.Bounce" );
  221. BaseClass::Precache();
  222. }
  223. void CFlashbangProjectile::Detonate()
  224. {
  225. RadiusFlash ( GetAbsOrigin(), this, GetThrower(), 4, CLASS_NONE, DMG_BLAST );
  226. EmitSound( "Flashbang.Explode" );
  227. // tell the bots a flashbang grenade has exploded
  228. CCSPlayer *player = ToCSPlayer(GetThrower());
  229. if ( player )
  230. {
  231. IGameEvent * event = gameeventmanager->CreateEvent( "flashbang_detonate" );
  232. if ( event )
  233. {
  234. event->SetInt( "userid", player->GetUserID() );
  235. event->SetFloat( "x", GetAbsOrigin().x );
  236. event->SetFloat( "y", GetAbsOrigin().y );
  237. event->SetFloat( "z", GetAbsOrigin().z );
  238. gameeventmanager->FireEvent( event );
  239. }
  240. }
  241. UTIL_Remove( this );
  242. }
  243. //TODO: Let physics handle the sound!
  244. void CFlashbangProjectile::BounceSound( void )
  245. {
  246. EmitSound( "Flashbang.Bounce" );
  247. }