summaryrefslogtreecommitdiff
path: root/game/shared/cstrike/flashbang_projectile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/cstrike/flashbang_projectile.cpp')
-rw-r--r--game/shared/cstrike/flashbang_projectile.cpp316
1 files changed, 316 insertions, 0 deletions
diff --git a/game/shared/cstrike/flashbang_projectile.cpp b/game/shared/cstrike/flashbang_projectile.cpp
new file mode 100644
index 0000000..aeb9830
--- /dev/null
+++ b/game/shared/cstrike/flashbang_projectile.cpp
@@ -0,0 +1,316 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "flashbang_projectile.h"
+#include "shake.h"
+#include "engine/IEngineSound.h"
+#include "cs_player.h"
+#include "dlight.h"
+#include "KeyValues.h"
+#include "weapon_csbase.h"
+#include "collisionutils.h"
+#include "particle_smokegrenade.h"
+#include "smoke_fog_overlay_shared.h"
+
+#define GRENADE_MODEL "models/Weapons/w_eq_flashbang_thrown.mdl"
+
+
+LINK_ENTITY_TO_CLASS( flashbang_projectile, CFlashbangProjectile );
+PRECACHE_WEAPON_REGISTER( flashbang_projectile );
+
+float PercentageOfFlashForPlayer(CBaseEntity *player, Vector flashPos, CBaseEntity *pevInflictor)
+{
+ float retval = 0.0f;
+
+ trace_t tr;
+
+ Vector pos = player->EyePosition();
+ Vector vecRight, vecUp, vecForward;
+ AngleVectors( player->EyeAngles(), &vecForward );
+
+ QAngle tempAngle;
+ VectorAngles(player->EyePosition() - flashPos, tempAngle);
+ AngleVectors(tempAngle, NULL, &vecRight, &vecUp);
+
+ vecRight.NormalizeInPlace();
+ vecUp.NormalizeInPlace();
+
+ UTIL_TraceLine( flashPos, pos,
+ (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_DEBRIS|CONTENTS_MONSTER),
+ pevInflictor, COLLISION_GROUP_NONE, &tr );
+
+ if ((tr.fraction == 1.0) || (tr.m_pEnt == player))
+ {
+ retval = 1.0;
+ }
+ else
+ {
+ return 0.0;
+ }
+
+ CBaseEntity *pSGren;
+
+ for( pSGren = gEntList.FindEntityByClassname( NULL, "env_particlesmokegrenade" );
+ pSGren;
+ pSGren = gEntList.FindEntityByClassname( pSGren, "env_particlesmokegrenade" ) )
+ {
+ ParticleSmokeGrenade *pPSG =( ParticleSmokeGrenade* ) pSGren;
+
+ if ( gpGlobals->curtime > pPSG->m_flSpawnTime + pPSG->m_FadeStartTime ) // ignore the smoke grenade if it's fading.
+ continue;
+
+ float flHit1, flHit2;
+
+ float flInnerRadius = SMOKEGRENADE_PARTICLERADIUS;
+// float flOutterRadius = flInnerRadius + ( 0.5 * SMOKEPARTICLE_SIZE );
+
+ Vector vPos = pSGren->GetAbsOrigin();
+
+ /*debugoverlay->AddBoxOverlay( pSGren->GetAbsOrigin(), Vector( flInnerRadius, flInnerRadius, flInnerRadius ),
+ Vector( -flInnerRadius, -flInnerRadius, -flInnerRadius ), QAngle( 0, 0, 0 ), 0, 255, 0, 30, 10 );
+ debugoverlay->AddBoxOverlay( pSGren->GetAbsOrigin(), Vector( flOutterRadius, flOutterRadius, flOutterRadius ),
+ Vector( -flOutterRadius, -flOutterRadius, -flOutterRadius ), QAngle( 0, 0, 0 ), 255, 0, 0, 30, 10 ); */
+
+ if ( IntersectInfiniteRayWithSphere( pos, vecForward, vPos, flInnerRadius, &flHit1, &flHit2 ) )
+ {
+ retval *= 0.8;
+ }
+/* else if ( IntersectInfiniteRayWithSphere( pos, vecForward, vPos, flOutterRadius, &flHit1, &flHit2 ) )
+ {
+ retval *= 0.9;
+ }
+*/
+ }
+
+ return retval;
+
+}
+
+// --------------------------------------------------------------------------------------------------- //
+//
+// RadiusDamage - this entity is exploding, or otherwise needs to inflict damage upon entities within a certain range.
+//
+// only damage ents that can clearly be seen by the explosion!
+// --------------------------------------------------------------------------------------------------- //
+
+void RadiusFlash(
+ Vector vecSrc,
+ CBaseEntity *pevInflictor,
+ CBaseEntity *pevAttacker,
+ float flDamage,
+ int iClassIgnore,
+ int bitsDamageType )
+{
+ vecSrc.z += 1;// in case grenade is lying on the ground
+
+ if ( !pevAttacker )
+ pevAttacker = pevInflictor;
+
+ trace_t tr;
+ float flAdjustedDamage;
+ variant_t var;
+ Vector vecEyePos;
+ float fadeTime, fadeHold;
+ Vector vForward;
+ Vector vecLOS;
+ float flDot;
+
+ CBaseEntity *pEntity = NULL;
+ static float flRadius = 1500;
+ float falloff = flDamage / flRadius;
+
+ bool bInWater = (UTIL_PointContents( vecSrc ) == CONTENTS_WATER);
+
+ // iterate on all entities in the vicinity.
+ while ((pEntity = gEntList.FindEntityInSphere( pEntity, vecSrc, flRadius )) != NULL)
+ {
+ bool bPlayer = pEntity->IsPlayer();
+ bool bHostage = ( Q_stricmp( pEntity->GetClassname(), "hostage_entity" ) == 0 );
+
+ if( !bPlayer && !bHostage )
+ continue;
+
+ vecEyePos = pEntity->EyePosition();
+
+ // blasts don't travel into or out of water
+ if ( bInWater && pEntity->GetWaterLevel() == 0)
+ continue;
+ if (!bInWater && pEntity->GetWaterLevel() == 3)
+ continue;
+
+ float percentageOfFlash = PercentageOfFlashForPlayer(pEntity, vecSrc, pevInflictor);
+
+ if ( percentageOfFlash > 0.0 )
+ {
+ // decrease damage for an ent that's farther from the grenade
+ flAdjustedDamage = flDamage - ( vecSrc - pEntity->EyePosition() ).Length() * falloff;
+
+ if ( flAdjustedDamage > 0 )
+ {
+ // See if we were facing the flash
+ AngleVectors( pEntity->EyeAngles(), &vForward );
+
+ vecLOS = ( vecSrc - vecEyePos );
+
+ float flDistance = vecLOS.Length();
+
+ // Normalize both vectors so the dotproduct is in the range -1.0 <= x <= 1.0
+ vecLOS.NormalizeInPlace();
+
+ flDot = DotProduct (vecLOS, vForward);
+
+ float startingAlpha = 255;
+
+ // if target is facing the bomb, the effect lasts longer
+ if( flDot >= 0.5 )
+ {
+ // looking at the flashbang
+ fadeTime = flAdjustedDamage * 2.5f;
+ fadeHold = flAdjustedDamage * 1.25f;
+ }
+ else if( flDot >= -0.5 )
+ {
+ // looking to the side
+ fadeTime = flAdjustedDamage * 1.75f;
+ fadeHold = flAdjustedDamage * 0.8f;
+ }
+ else
+ {
+ // facing away
+ fadeTime = flAdjustedDamage * 1.0f;
+ fadeHold = flAdjustedDamage * 0.75f;
+ startingAlpha = 200;
+ }
+
+ fadeTime *= percentageOfFlash;
+ fadeHold *= percentageOfFlash;
+
+ if ( bPlayer )
+ {
+ // blind players and bots
+ CCSPlayer *player = static_cast< CCSPlayer * >( pEntity );
+
+ //=============================================================================
+ // HPE_BEGIN:
+ // [tj] Store who was responsible for the most recent flashbang blinding.
+ //=============================================================================
+
+ CCSPlayer *attacker = ToCSPlayer (pevAttacker);
+ if (attacker && player)
+ {
+ player->SetLastFlashbangAttacker(attacker);
+ }
+
+ //=============================================================================
+ // HPE_END
+ //=============================================================================
+
+
+
+ player->Blind( fadeHold, fadeTime, startingAlpha );
+
+ // deafen players and bots
+ player->Deafen( flDistance );
+ }
+ else if ( bHostage )
+ {
+ variant_t val;
+ val.SetFloat( fadeTime );
+ pEntity->AcceptInput( "flashbang", pevInflictor, pevAttacker, val, 0 );
+ }
+ }
+ }
+ }
+
+ CPVSFilter filter(vecSrc);
+ te->DynamicLight( filter, 0.0, &vecSrc, 255, 255, 255, 2, 400, 0.1, 768 );
+}
+
+// --------------------------------------------------------------------------------------------------- //
+// CFlashbangProjectile implementation.
+// --------------------------------------------------------------------------------------------------- //
+
+CFlashbangProjectile* CFlashbangProjectile::Create(
+ const Vector &position,
+ const QAngle &angles,
+ const Vector &velocity,
+ const AngularImpulse &angVelocity,
+ CBaseCombatCharacter *pOwner )
+{
+ CFlashbangProjectile *pGrenade = (CFlashbangProjectile*)CBaseEntity::Create( "flashbang_projectile", position, angles, pOwner );
+
+ // Set the timer for 1 second less than requested. We're going to issue a SOUND_DANGER
+ // one second before detonation.
+ pGrenade->SetAbsVelocity( velocity );
+ pGrenade->SetupInitialTransmittedGrenadeVelocity( velocity );
+ pGrenade->SetThrower( pOwner );
+ pGrenade->m_flDamage = 100;
+ pGrenade->ChangeTeam( pOwner->GetTeamNumber() );
+
+ pGrenade->SetTouch( &CBaseGrenade::BounceTouch );
+
+ pGrenade->SetThink( &CBaseCSGrenadeProjectile::DangerSoundThink );
+ pGrenade->SetNextThink( gpGlobals->curtime );
+
+ pGrenade->SetDetonateTimerLength( 1.5 );
+
+ pGrenade->ApplyLocalAngularVelocityImpulse( angVelocity );
+
+ pGrenade->SetGravity( BaseClass::GetGrenadeGravity() );
+ pGrenade->SetFriction( BaseClass::GetGrenadeFriction() );
+ pGrenade->SetElasticity( BaseClass::GetGrenadeElasticity() );
+
+ pGrenade->m_pWeaponInfo = GetWeaponInfo( WEAPON_FLASHBANG );
+
+
+ return pGrenade;
+}
+
+void CFlashbangProjectile::Spawn()
+{
+ SetModel( GRENADE_MODEL );
+ BaseClass::Spawn();
+}
+
+void CFlashbangProjectile::Precache()
+{
+ PrecacheModel( GRENADE_MODEL );
+
+ PrecacheScriptSound( "Flashbang.Explode" );
+ PrecacheScriptSound( "Flashbang.Bounce" );
+
+ BaseClass::Precache();
+}
+
+void CFlashbangProjectile::Detonate()
+{
+ RadiusFlash ( GetAbsOrigin(), this, GetThrower(), 4, CLASS_NONE, DMG_BLAST );
+ EmitSound( "Flashbang.Explode" );
+
+ // tell the bots a flashbang grenade has exploded
+ CCSPlayer *player = ToCSPlayer(GetThrower());
+ if ( player )
+ {
+ IGameEvent * event = gameeventmanager->CreateEvent( "flashbang_detonate" );
+ if ( event )
+ {
+ event->SetInt( "userid", player->GetUserID() );
+ event->SetFloat( "x", GetAbsOrigin().x );
+ event->SetFloat( "y", GetAbsOrigin().y );
+ event->SetFloat( "z", GetAbsOrigin().z );
+ gameeventmanager->FireEvent( event );
+ }
+ }
+
+ UTIL_Remove( this );
+}
+
+//TODO: Let physics handle the sound!
+void CFlashbangProjectile::BounceSound( void )
+{
+ EmitSound( "Flashbang.Bounce" );
+}