source-engine/game/server/hl2/grenade_molotov.cpp

245 lines
6.1 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Flaming bottle thrown from the hand
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "player.h"
#include "ammodef.h"
#include "gamerules.h"
#include "grenade_molotov.h"
#include "weapon_brickbat.h"
#include "soundent.h"
#include "decals.h"
#include "fire.h"
#include "shake.h"
#include "ndebugoverlay.h"
#include "vstdlib/random.h"
#include "engine/IEngineSound.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern short g_sModelIndexFireball;
extern ConVar sk_plr_dmg_molotov;
extern ConVar sk_npc_dmg_molotov;
ConVar sk_molotov_radius ( "sk_molotov_radius","0");
#define MOLOTOV_EXPLOSION_VOLUME 1024
BEGIN_DATADESC( CGrenade_Molotov )
DEFINE_FIELD( m_pFireTrail, FIELD_CLASSPTR ),
// Function Pointers
DEFINE_FUNCTION( MolotovTouch ),
DEFINE_FUNCTION( MolotovThink ),
END_DATADESC()
LINK_ENTITY_TO_CLASS( grenade_molotov, CGrenade_Molotov );
void CGrenade_Molotov::Spawn( void )
{
SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
SetSolid( SOLID_BBOX );
SetCollisionGroup( COLLISION_GROUP_PROJECTILE );
SetModel( "models/weapons/w_molotov.mdl");
UTIL_SetSize(this, Vector( -6, -6, -2), Vector(6, 6, 2));
SetTouch( MolotovTouch );
SetThink( MolotovThink );
SetNextThink( gpGlobals->curtime + 0.1f );
m_flDamage = sk_plr_dmg_molotov.GetFloat();
m_DmgRadius = sk_molotov_radius.GetFloat();
m_takedamage = DAMAGE_YES;
m_iHealth = 1;
SetGravity( 1.0 );
SetFriction( 0.8 ); // Give a little bounce so can flatten
SetSequence( 1 );
m_pFireTrail = SmokeTrail::CreateSmokeTrail();
if( m_pFireTrail )
{
m_pFireTrail->m_SpawnRate = 48;
m_pFireTrail->m_ParticleLifetime = 1.0f;
m_pFireTrail->m_StartColor.Init( 0.2f, 0.2f, 0.2f );
m_pFireTrail->m_EndColor.Init( 0.0, 0.0, 0.0 );
m_pFireTrail->m_StartSize = 8;
m_pFireTrail->m_EndSize = 32;
m_pFireTrail->m_SpawnRadius = 4;
m_pFireTrail->m_MinSpeed = 8;
m_pFireTrail->m_MaxSpeed = 16;
m_pFireTrail->m_Opacity = 0.25f;
m_pFireTrail->SetLifetime( 20.0f );
m_pFireTrail->FollowEntity( this, "0" );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CGrenade_Molotov::MolotovTouch( CBaseEntity *pOther )
{
Detonate();
}
//-----------------------------------------------------------------------------
// Purpose:
//
//
//-----------------------------------------------------------------------------
void CGrenade_Molotov::Detonate( void )
{
SetModelName( NULL_STRING ); //invisible
AddSolidFlags( FSOLID_NOT_SOLID ); // intangible
m_takedamage = DAMAGE_NO;
trace_t trace;
UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + Vector ( 0, 0, -128 ), MASK_SOLID_BRUSHONLY,
this, COLLISION_GROUP_NONE, &trace);
// Pull out of the wall a bit
if ( trace.fraction != 1.0 )
{
SetLocalOrigin( trace.endpos + (trace.plane.normal * (m_flDamage - 24) * 0.6) );
}
int contents = UTIL_PointContents ( GetAbsOrigin() );
if ( (contents & MASK_WATER) )
{
UTIL_Remove( this );
return;
}
EmitSound( "Grenade_Molotov.Detonate");
// Start some fires
int i;
QAngle vecTraceAngles;
Vector vecTraceDir;
trace_t firetrace;
for( i = 0 ; i < 16 ; i++ )
{
// build a little ray
vecTraceAngles[PITCH] = random->RandomFloat(45, 135);
vecTraceAngles[YAW] = random->RandomFloat(0, 360);
vecTraceAngles[ROLL] = 0.0f;
AngleVectors( vecTraceAngles, &vecTraceDir );
Vector vecStart, vecEnd;
vecStart = GetAbsOrigin() + ( trace.plane.normal * 128 );
vecEnd = vecStart + vecTraceDir * 512;
UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &firetrace );
Vector ofsDir = ( firetrace.endpos - GetAbsOrigin() );
float offset = VectorNormalize( ofsDir );
if ( offset > 128 )
offset = 128;
//Get our scale based on distance
float scale = 0.1f + ( 0.75f * ( 1.0f - ( offset / 128.0f ) ) );
float growth = 0.1f + ( 0.75f * ( offset / 128.0f ) );
if( firetrace.fraction != 1.0 )
{
FireSystem_StartFire( firetrace.endpos, scale, growth, 30.0f, (SF_FIRE_START_ON|SF_FIRE_SMOKELESS|SF_FIRE_NO_GLOW), (CBaseEntity*) this, FIRE_NATURAL );
}
}
// End Start some fires
CPASFilter filter2( trace.endpos );
te->Explosion( filter2, 0.0,
&trace.endpos,
g_sModelIndexFireball,
2.0,
15,
TE_EXPLFLAG_NOPARTICLES,
m_DmgRadius,
m_flDamage );
CBaseEntity *pOwner;
pOwner = GetOwnerEntity();
SetOwnerEntity( NULL ); // can't traceline attack owner if this is set
UTIL_DecalTrace( &trace, "Scorch" );
UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START );
CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 );
RadiusDamage( CTakeDamageInfo( this, pOwner, m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL );
AddEffects( EF_NODRAW );
SetAbsVelocity( vec3_origin );
SetNextThink( gpGlobals->curtime + 0.2 );
if ( m_pFireTrail )
{
UTIL_Remove( m_pFireTrail );
}
UTIL_Remove(this);
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void CGrenade_Molotov::MolotovThink( void )
{
// See if I can lose my owner (has dropper moved out of way?)
// Want do this so owner can throw the brickbat
if (GetOwnerEntity())
{
trace_t tr;
Vector vUpABit = GetAbsOrigin();
vUpABit.z += 5.0;
CBaseEntity* saveOwner = GetOwnerEntity();
SetOwnerEntity( NULL );
UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr );
if ( tr.startsolid || tr.fraction != 1.0 )
{
SetOwnerEntity( saveOwner );
}
}
SetNextThink( gpGlobals->curtime + 0.1f );
}
void CGrenade_Molotov::Precache( void )
{
BaseClass::Precache();
PrecacheModel("models/weapons/w_bb_bottle.mdl");
UTIL_PrecacheOther("_firesmoke");
PrecacheScriptSound( "Grenade_Molotov.Detonate" );
}