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.
253 lines
6.2 KiB
253 lines
6.2 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "grenade_ar2.h" |
|
#include "weapon_ar2.h" |
|
#include "soundent.h" |
|
#include "decals.h" |
|
#include "shake.h" |
|
#include "smoke_trail.h" |
|
#include "ar2_explosion.h" |
|
#include "vstdlib/random.h" |
|
#include "engine/IEngineSound.h" |
|
#include "world.h" |
|
|
|
#ifdef PORTAL |
|
#include "portal_util_shared.h" |
|
#endif |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
#define AR2_GRENADE_MAX_DANGER_RADIUS 300 |
|
|
|
extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the smoke cloud |
|
|
|
// Moved to HL2_SharedGameRules because these are referenced by shared AmmoDef functions |
|
extern ConVar sk_plr_dmg_smg1_grenade; |
|
extern ConVar sk_npc_dmg_smg1_grenade; |
|
extern ConVar sk_max_smg1_grenade; |
|
|
|
ConVar sk_smg1_grenade_radius ( "sk_smg1_grenade_radius","0"); |
|
|
|
ConVar g_CV_SmokeTrail("smoke_trail", "1", 0); // temporary dust explosion switch |
|
|
|
BEGIN_DATADESC( CGrenadeAR2 ) |
|
|
|
DEFINE_FIELD( m_hSmokeTrail, FIELD_EHANDLE ), |
|
DEFINE_FIELD( m_fSpawnTime, FIELD_TIME ), |
|
DEFINE_FIELD( m_fDangerRadius, FIELD_FLOAT ), |
|
|
|
// Function pointers |
|
DEFINE_ENTITYFUNC( GrenadeAR2Touch ), |
|
DEFINE_THINKFUNC( GrenadeAR2Think ), |
|
|
|
END_DATADESC() |
|
|
|
LINK_ENTITY_TO_CLASS( grenade_ar2, CGrenadeAR2 ); |
|
|
|
void CGrenadeAR2::Spawn( void ) |
|
{ |
|
Precache( ); |
|
SetSolid( SOLID_BBOX ); |
|
SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); |
|
|
|
// Hits everything but debris |
|
SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); |
|
|
|
SetModel( "models/Weapons/ar2_grenade.mdl"); |
|
UTIL_SetSize(this, Vector(-3, -3, -3), Vector(3, 3, 3)); |
|
// UTIL_SetSize(this, Vector(0, 0, 0), Vector(0, 0, 0)); |
|
|
|
SetUse( &CGrenadeAR2::DetonateUse ); |
|
SetTouch( &CGrenadeAR2::GrenadeAR2Touch ); |
|
SetThink( &CGrenadeAR2::GrenadeAR2Think ); |
|
SetNextThink( gpGlobals->curtime + 0.1f ); |
|
|
|
if( GetOwnerEntity() && GetOwnerEntity()->IsPlayer() ) |
|
{ |
|
m_flDamage = sk_plr_dmg_smg1_grenade.GetFloat(); |
|
} |
|
else |
|
{ |
|
m_flDamage = sk_npc_dmg_smg1_grenade.GetFloat(); |
|
} |
|
|
|
m_DmgRadius = sk_smg1_grenade_radius.GetFloat(); |
|
m_takedamage = DAMAGE_YES; |
|
m_bIsLive = true; |
|
m_iHealth = 1; |
|
|
|
SetGravity( UTIL_ScaleForGravity( 400 ) ); // use a lower gravity for grenades to make them easier to see |
|
SetFriction( 0.8 ); |
|
SetSequence( 0 ); |
|
|
|
m_fDangerRadius = 100; |
|
|
|
m_fSpawnTime = gpGlobals->curtime; |
|
|
|
// ------------- |
|
// Smoke trail. |
|
// ------------- |
|
if( g_CV_SmokeTrail.GetInt() && !IsXbox() ) |
|
{ |
|
m_hSmokeTrail = SmokeTrail::CreateSmokeTrail(); |
|
|
|
if( m_hSmokeTrail ) |
|
{ |
|
m_hSmokeTrail->m_SpawnRate = 48; |
|
m_hSmokeTrail->m_ParticleLifetime = 1; |
|
m_hSmokeTrail->m_StartColor.Init(0.1f, 0.1f, 0.1f); |
|
m_hSmokeTrail->m_EndColor.Init(0,0,0); |
|
m_hSmokeTrail->m_StartSize = 12; |
|
m_hSmokeTrail->m_EndSize = m_hSmokeTrail->m_StartSize * 4; |
|
m_hSmokeTrail->m_SpawnRadius = 4; |
|
m_hSmokeTrail->m_MinSpeed = 4; |
|
m_hSmokeTrail->m_MaxSpeed = 24; |
|
m_hSmokeTrail->m_Opacity = 0.2f; |
|
|
|
m_hSmokeTrail->SetLifetime(10.0f); |
|
m_hSmokeTrail->FollowEntity(this); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: The grenade has a slight delay before it goes live. That way the |
|
// person firing it can bounce it off a nearby wall. However if it |
|
// hits another character it blows up immediately |
|
// Input : |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
void CGrenadeAR2::GrenadeAR2Think( void ) |
|
{ |
|
SetNextThink( gpGlobals->curtime + 0.05f ); |
|
|
|
if (!m_bIsLive) |
|
{ |
|
// Go live after a short delay |
|
if (m_fSpawnTime + MAX_AR2_NO_COLLIDE_TIME < gpGlobals->curtime) |
|
{ |
|
m_bIsLive = true; |
|
} |
|
} |
|
|
|
// If I just went solid and my velocity is zero, it means I'm resting on |
|
// the floor already when I went solid so blow up |
|
if (m_bIsLive) |
|
{ |
|
if (GetAbsVelocity().Length() == 0.0 || |
|
GetGroundEntity() != NULL ) |
|
{ |
|
Detonate(); |
|
} |
|
} |
|
|
|
// The old way of making danger sounds would scare the crap out of EVERYONE between you and where the grenade |
|
// was going to hit. The radius of the danger sound now 'blossoms' over the grenade's lifetime, making it seem |
|
// dangerous to a larger area downrange than it does from where it was fired. |
|
if( m_fDangerRadius <= AR2_GRENADE_MAX_DANGER_RADIUS ) |
|
{ |
|
m_fDangerRadius += ( AR2_GRENADE_MAX_DANGER_RADIUS * 0.05 ); |
|
} |
|
|
|
CSoundEnt::InsertSound( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, m_fDangerRadius, 0.2, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); |
|
} |
|
|
|
void CGrenadeAR2::Event_Killed( const CTakeDamageInfo &info ) |
|
{ |
|
Detonate( ); |
|
} |
|
|
|
void CGrenadeAR2::GrenadeAR2Touch( CBaseEntity *pOther ) |
|
{ |
|
Assert( pOther ); |
|
if ( !pOther->IsSolid() ) |
|
return; |
|
|
|
// If I'm live go ahead and blow up |
|
if (m_bIsLive) |
|
{ |
|
Detonate(); |
|
} |
|
else |
|
{ |
|
// If I'm not live, only blow up if I'm hitting an chacter that |
|
// is not the owner of the weapon |
|
CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pOther ); |
|
if (pBCC && GetThrower() != pBCC) |
|
{ |
|
m_bIsLive = true; |
|
Detonate(); |
|
} |
|
} |
|
} |
|
|
|
void CGrenadeAR2::Detonate(void) |
|
{ |
|
if (!m_bIsLive) |
|
{ |
|
return; |
|
} |
|
m_bIsLive = false; |
|
m_takedamage = DAMAGE_NO; |
|
|
|
if(m_hSmokeTrail) |
|
{ |
|
UTIL_Remove(m_hSmokeTrail); |
|
m_hSmokeTrail = NULL; |
|
} |
|
|
|
CPASFilter filter( GetAbsOrigin() ); |
|
|
|
te->Explosion( filter, 0.0, |
|
&GetAbsOrigin(), |
|
g_sModelIndexFireball, |
|
2.0, |
|
15, |
|
TE_EXPLFLAG_NONE, |
|
m_DmgRadius, |
|
m_flDamage ); |
|
|
|
Vector vecForward = GetAbsVelocity(); |
|
VectorNormalize(vecForward); |
|
trace_t tr; |
|
UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + 60*vecForward, MASK_SHOT, |
|
this, COLLISION_GROUP_NONE, &tr); |
|
|
|
|
|
if ((tr.m_pEnt != GetWorldEntity()) || (tr.hitbox != 0)) |
|
{ |
|
// non-world needs smaller decals |
|
if( tr.m_pEnt && !tr.m_pEnt->IsNPC() ) |
|
{ |
|
UTIL_DecalTrace( &tr, "SmallScorch" ); |
|
} |
|
} |
|
else |
|
{ |
|
UTIL_DecalTrace( &tr, "Scorch" ); |
|
} |
|
|
|
UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START ); |
|
|
|
RadiusDamage ( CTakeDamageInfo( this, GetThrower(), m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL ); |
|
|
|
UTIL_Remove( this ); |
|
} |
|
|
|
void CGrenadeAR2::Precache( void ) |
|
{ |
|
PrecacheModel("models/Weapons/ar2_grenade.mdl"); |
|
} |
|
|
|
|
|
CGrenadeAR2::CGrenadeAR2(void) |
|
{ |
|
m_hSmokeTrail = NULL; |
|
}
|
|
|