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.
344 lines
10 KiB
344 lines
10 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
#include "cbase.h"
|
||
|
#include "basetfplayer_shared.h"
|
||
|
#include "basegrenade_shared.h"
|
||
|
#include "engine/IEngineSound.h"
|
||
|
#include "tf_shareddefs.h"
|
||
|
#include "Sprite.h"
|
||
|
#include "grenade_emp.h"
|
||
|
#include "tf_gamerules.h"
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
|
||
|
#include "particles_simple.h"
|
||
|
|
||
|
#else
|
||
|
|
||
|
#endif
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
|
||
|
int g_iEMPPulseEffectIndex = 0;
|
||
|
|
||
|
// Damage CVars
|
||
|
ConVar weapon_emp_grenade_duration( "weapon_emp_grenade_duration","5", FCVAR_REPLICATED, "Duration of the EMP grenade's effect." );
|
||
|
ConVar weapon_emp_grenade_object_duration( "weapon_emp_grenade_object_duration","5", FCVAR_REPLICATED, "Duration of the EMP grenade's effect on objects." );
|
||
|
ConVar weapon_emp_grenade_radius( "weapon_emp_grenade_radius","256", FCVAR_REPLICATED, "EMP grenade splash radius" );
|
||
|
|
||
|
IMPLEMENT_NETWORKCLASS_ALIASED( GrenadeEMP, DT_GrenadeEMP );
|
||
|
|
||
|
BEGIN_NETWORK_TABLE( CGrenadeEMP, DT_GrenadeEMP )
|
||
|
#if !defined( CLIENT_DLL )
|
||
|
SendPropEHandle( SENDINFO( m_hLiveSprite ) ),
|
||
|
#else
|
||
|
RecvPropEHandle( RECVINFO( m_hLiveSprite ) ),
|
||
|
#endif
|
||
|
END_NETWORK_TABLE()
|
||
|
|
||
|
BEGIN_PREDICTION_DATA( CGrenadeEMP )
|
||
|
DEFINE_PRED_FIELD( m_hLiveSprite, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
|
||
|
END_PREDICTION_DATA()
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( grenade_emp, CGrenadeEMP );
|
||
|
PRECACHE_REGISTER(grenade_emp);
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CGrenadeEMP::CGrenadeEMP()
|
||
|
{
|
||
|
SetPredictionEligible( true );
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
m_ParticleEvent.Init( 100 );
|
||
|
#else
|
||
|
UseClientSideAnimation();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CGrenadeEMP::Precache( void )
|
||
|
{
|
||
|
BaseClass::Precache( );
|
||
|
|
||
|
PrecacheModel( "models/weapons/w_grenade.mdl" );
|
||
|
PrecacheModel( "sprites/redglow1.vmt" );
|
||
|
g_iEMPPulseEffectIndex = PrecacheModel( "sprites/lgtning.spr" );
|
||
|
|
||
|
PrecacheScriptSound( "GrenadeEMP.Bounce" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CGrenadeEMP::Spawn( void )
|
||
|
{
|
||
|
Precache();
|
||
|
|
||
|
SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
|
||
|
SetSolid( SOLID_BBOX );
|
||
|
//m_flGravity = 1.0;
|
||
|
SetFriction( 0.75 );
|
||
|
SetModel( "models/weapons/w_grenade.mdl" );
|
||
|
SetSize( Vector( -4, -4, -4), Vector(4, 4, 4) );
|
||
|
SetTouch( BounceTouch );
|
||
|
SetCollisionGroup( TFCOLLISION_GROUP_GRENADE );
|
||
|
|
||
|
m_flDetonateTime = gpGlobals->curtime + 4.0;
|
||
|
SetThink( TumbleThink );
|
||
|
SetNextThink( gpGlobals->curtime + 0.1f );
|
||
|
|
||
|
// Set my damages to the cvar values
|
||
|
SetDamage( weapon_emp_grenade_duration.GetFloat() );
|
||
|
SetDamageRadius( weapon_emp_grenade_radius.GetFloat() );
|
||
|
|
||
|
// Create a white light
|
||
|
CBasePlayer *player = ToBasePlayer( GetOwnerEntity() );
|
||
|
if ( player )
|
||
|
{
|
||
|
m_hLiveSprite = SPRITE_CREATE_PREDICTABLE( "sprites/chargeball2.vmt", GetLocalOrigin() + Vector(0,0,1), false );
|
||
|
if ( m_hLiveSprite )
|
||
|
{
|
||
|
m_hLiveSprite->SetOwnerEntity( player );
|
||
|
m_hLiveSprite->SetPlayerSimulated( player );
|
||
|
m_hLiveSprite->SetTransparency( kRenderGlow, 255, 255, 255, 128, kRenderFxNoDissipation );
|
||
|
m_hLiveSprite->SetBrightness( 255 );
|
||
|
m_hLiveSprite->SetScale( 0.15, 5.0f );
|
||
|
m_hLiveSprite->SetAttachment( this, 0 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CGrenadeEMP::UpdateOnRemove( void )
|
||
|
{
|
||
|
// Remove our live sprite
|
||
|
if ( m_hLiveSprite )
|
||
|
{
|
||
|
m_hLiveSprite->Remove( );
|
||
|
m_hLiveSprite = NULL;
|
||
|
}
|
||
|
|
||
|
// Chain at end to mimic destructor unwind order
|
||
|
BaseClass::UpdateOnRemove();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CGrenadeEMP::Explode( trace_t *pTrace, int bitsDamageType )
|
||
|
{
|
||
|
#if !defined( CLIENT_DLL )
|
||
|
// While in scope, this will allow messages to pass through without being filtered.
|
||
|
CDisablePredictionFiltering dpf;
|
||
|
|
||
|
// Create EMP pulse effect
|
||
|
int iEmpRings = 4;
|
||
|
float fEmpDelay = 0.05f;
|
||
|
float delay = 0.0f;
|
||
|
float frac;
|
||
|
for ( int r = 0 ; r < iEmpRings; r++, delay += fEmpDelay )
|
||
|
{
|
||
|
frac = (float)( r )/(float)(iEmpRings - 1);
|
||
|
|
||
|
CBroadcastRecipientFilter filter;
|
||
|
|
||
|
// Since this doesn't fire on the client right now, ignore the culling of the local player
|
||
|
filter.SetIgnorePredictionCull( true );
|
||
|
|
||
|
te->BeamRingPoint( filter, delay,
|
||
|
GetAbsOrigin() + Vector(0,0,32) , // origin
|
||
|
64.0f, // start radius
|
||
|
weapon_emp_grenade_radius.GetFloat() * 2, // end radius
|
||
|
g_iEMPPulseEffectIndex,
|
||
|
0, // halo index
|
||
|
0, // start frame
|
||
|
2, // framerate
|
||
|
0.3f, // life
|
||
|
25.0, // width
|
||
|
50, // spread
|
||
|
2, // amplitude
|
||
|
50 + ( 1-frac ) * 200,
|
||
|
63,
|
||
|
63 + 127 * frac,
|
||
|
255 - frac * 127,
|
||
|
20 );
|
||
|
}
|
||
|
|
||
|
ApplyRadiusEMPEffect( GetThrower(), GetAbsOrigin() + Vector(0,0,16) );
|
||
|
Remove( );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: EMP enemies around the grenade
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CGrenadeEMP::ApplyRadiusEMPEffect( CBaseEntity *pOwner, const Vector& vecCenter )
|
||
|
{
|
||
|
// Oh oh, owner is gone...
|
||
|
if ( !pOwner )
|
||
|
return;
|
||
|
|
||
|
#if !defined( CLIENT_DLL )
|
||
|
CBaseEntity *pEntity = NULL;
|
||
|
|
||
|
for ( CEntitySphereQuery sphere( vecCenter, weapon_emp_grenade_radius.GetFloat() ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() )
|
||
|
{
|
||
|
// Ignore team members, and unaligned targets
|
||
|
if ( pOwner->InSameTeam( pEntity ) || pEntity->GetTeamNumber() == 0 )
|
||
|
continue;
|
||
|
|
||
|
if ( pEntity->IsSolidFlagSet( FSOLID_NOT_SOLID ) )
|
||
|
continue;
|
||
|
|
||
|
// Make sure it's not blocked by a shield or wall
|
||
|
trace_t tr;
|
||
|
if ( TFGameRules()->IsTraceBlockedByWorldOrShield( vecCenter, pEntity->WorldSpaceCenter(), this, DMG_PROBE, &tr ) )
|
||
|
continue;
|
||
|
|
||
|
if ( pEntity->CanBePoweredUp() )
|
||
|
{
|
||
|
// Is it an object?
|
||
|
if ( pEntity->Classify() == CLASS_MILITARY )
|
||
|
{
|
||
|
pEntity->AttemptToPowerup( POWERUP_EMP, weapon_emp_grenade_object_duration.GetFloat() );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pEntity->AttemptToPowerup( POWERUP_EMP, weapon_emp_grenade_duration.GetFloat() );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Allow shield parry's
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CGrenadeEMP::BounceTouch( CBaseEntity *pOther )
|
||
|
{
|
||
|
Assert( pOther );
|
||
|
if ( !pOther->IsSolid() )
|
||
|
return;
|
||
|
|
||
|
BaseClass::BounceTouch( pOther );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Play a distinctive grenade bounce sound to warn nearby players
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CGrenadeEMP::BounceSound( void )
|
||
|
{
|
||
|
CPASAttenuationFilter filter( this, "GrenadeEMP.Bounce" );
|
||
|
filter.UsePredictionRules();
|
||
|
EmitSound( filter, entindex(), "GrenadeEMP.Bounce" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Return the amplitude for the screenshake
|
||
|
//-----------------------------------------------------------------------------
|
||
|
float CGrenadeEMP::GetShakeAmplitude( void )
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Create a missile
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CGrenadeEMP *CGrenadeEMP::Create( const Vector &vecOrigin, const Vector &vecForward, CBasePlayer *pOwner )
|
||
|
{
|
||
|
CGrenadeEMP *pGrenade = (CGrenadeEMP*)CREATE_PREDICTED_ENTITY( "grenade_emp" );
|
||
|
if ( pGrenade )
|
||
|
{
|
||
|
UTIL_SetOrigin( pGrenade, vecOrigin );
|
||
|
pGrenade->SetOwnerEntity( pOwner );
|
||
|
pGrenade->Spawn();
|
||
|
pGrenade->SetPlayerSimulated( pOwner );
|
||
|
pGrenade->ChangeTeam( pOwner->GetTeamNumber() );
|
||
|
|
||
|
pGrenade->SetThrower( pOwner );
|
||
|
|
||
|
pGrenade->SetAbsVelocity( vecForward );
|
||
|
|
||
|
QAngle angles;
|
||
|
VectorAngles( vecForward, angles );
|
||
|
pGrenade->SetLocalAngles( angles );
|
||
|
|
||
|
pGrenade->SetLocalAngularVelocity( SHARED_RANDOMANGLE( -500, 500 ) );
|
||
|
}
|
||
|
|
||
|
return pGrenade;
|
||
|
}
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CGrenadeEMP::OnDataChanged( DataUpdateType_t updateType )
|
||
|
{
|
||
|
BaseClass::OnDataChanged( updateType );
|
||
|
|
||
|
// Only think when sapping
|
||
|
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Trail smoke
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CGrenadeEMP::ClientThink( void )
|
||
|
{
|
||
|
return;
|
||
|
|
||
|
CSmartPtr<CSimpleEmitter> pEmitter = CSimpleEmitter::Create( "EMPGrenade::Effect" );
|
||
|
PMaterialHandle hSphereMaterial = pEmitter->GetPMaterial( "sprites/chargeball" );
|
||
|
|
||
|
// Add particles at the target.
|
||
|
float flCur = gpGlobals->frametime;
|
||
|
while ( m_ParticleEvent.NextEvent( flCur ) )
|
||
|
{
|
||
|
Vector vecOrigin = GetAbsOrigin() + RandomVector( -2,2 );
|
||
|
pEmitter->SetSortOrigin( vecOrigin );
|
||
|
|
||
|
SimpleParticle *pParticle = (SimpleParticle *) pEmitter->AddParticle( sizeof(SimpleParticle), hSphereMaterial, vecOrigin );
|
||
|
if ( pParticle == NULL )
|
||
|
return;
|
||
|
|
||
|
pParticle->m_flLifetime = 0.0f;
|
||
|
pParticle->m_flDieTime = random->RandomFloat( 0.1f, 0.3f );
|
||
|
|
||
|
pParticle->m_uchStartSize = random->RandomFloat(2,4);
|
||
|
pParticle->m_uchEndSize = pParticle->m_uchStartSize + 2;
|
||
|
|
||
|
pParticle->m_vecVelocity = vec3_origin;
|
||
|
pParticle->m_uchStartAlpha = 128;
|
||
|
pParticle->m_uchEndAlpha = 0;
|
||
|
pParticle->m_flRoll = random->RandomFloat( 180, 360 );
|
||
|
pParticle->m_flRollDelta = random->RandomFloat( -1, 1 );
|
||
|
|
||
|
pParticle->m_uchColor[0] = 128;
|
||
|
pParticle->m_uchColor[1] = 128;
|
||
|
pParticle->m_uchColor[2] = 128;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int CGrenadeEMP::DrawModel( int flags )
|
||
|
{
|
||
|
bool bret = BaseClass::DrawModel( flags );
|
||
|
|
||
|
return bret;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|