mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
1
This commit is contained in:
@@ -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" );
|
||||
}
|
||||
Reference in New Issue
Block a user