aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/hl2/weapon_flaregun.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/server/hl2/weapon_flaregun.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/server/hl2/weapon_flaregun.cpp')
-rw-r--r--mp/src/game/server/hl2/weapon_flaregun.cpp1510
1 files changed, 755 insertions, 755 deletions
diff --git a/mp/src/game/server/hl2/weapon_flaregun.cpp b/mp/src/game/server/hl2/weapon_flaregun.cpp
index 793a5e23..d3fd6b15 100644
--- a/mp/src/game/server/hl2/weapon_flaregun.cpp
+++ b/mp/src/game/server/hl2/weapon_flaregun.cpp
@@ -1,755 +1,755 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Flare gun (fffsssssssssss!!)
-//
-// $NoKeywords: $
-//=============================================================================//
-
-#include "cbase.h"
-#include "player.h"
-#include "gamerules.h"
-#include "basehlcombatweapon.h"
-#include "decals.h"
-#include "soundenvelope.h"
-#include "IEffects.h"
-#include "engine/IEngineSound.h"
-#include "weapon_flaregun.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-
-/********************************************************************
- NOTE: if you are looking at this file becase you would like flares
- to be considered as fires (and thereby trigger gas traps), be aware
- that the env_flare class is actually found in weapon_flaregun.cpp
- and is really a repurposed piece of ammunition. (env_flare isn't the
- rod-like safety flare prop, but rather the bit of flame on the end.)
-
- You will have some difficulty making it work here, because CFlare
- does not inherit from CFire and will thus not be enumerated by
- CFireSphere::EnumElement(). In order to have flares be detected and
- used by this system, you will need to promote certain member functions
- of CFire into an interface class from which both CFire and CFlare
- inherit. You will also need to modify CFireSphere::EnumElement so that
- it properly disambiguates between fires and flares.
-
- For some partial work towards this end, see changelist 192474.
-
- ********************************************************************/
-
-
-#define FLARE_LAUNCH_SPEED 1500
-
-LINK_ENTITY_TO_CLASS( env_flare, CFlare );
-
-BEGIN_DATADESC( CFlare )
-
- DEFINE_FIELD( m_pOwner, FIELD_CLASSPTR ),
- DEFINE_FIELD( m_nBounces, FIELD_INTEGER ),
- DEFINE_FIELD( m_flTimeBurnOut, FIELD_TIME ),
- DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "scale" ),
- DEFINE_KEYFIELD( m_flDuration, FIELD_FLOAT, "duration" ),
- DEFINE_FIELD( m_flNextDamage, FIELD_TIME ),
- DEFINE_SOUNDPATCH( m_pBurnSound ),
- DEFINE_FIELD( m_bFading, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bLight, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bSmoke, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bPropFlare, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bInActiveList, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_pNextFlare, FIELD_CLASSPTR ),
-
- //Input functions
- DEFINE_INPUTFUNC( FIELD_FLOAT, "Start", InputStart ),
- DEFINE_INPUTFUNC( FIELD_FLOAT, "Die", InputDie ),
- DEFINE_INPUTFUNC( FIELD_FLOAT, "Launch", InputLaunch),
-
- // Function Pointers
- DEFINE_FUNCTION( FlareTouch ),
- DEFINE_FUNCTION( FlareBurnTouch ),
- DEFINE_FUNCTION( FlareThink ),
-
-END_DATADESC()
-
-//Data-tables
-IMPLEMENT_SERVERCLASS_ST( CFlare, DT_Flare )
- SendPropFloat( SENDINFO( m_flTimeBurnOut ), 0, SPROP_NOSCALE ),
- SendPropFloat( SENDINFO( m_flScale ), 0, SPROP_NOSCALE ),
- SendPropInt( SENDINFO( m_bLight ), 1, SPROP_UNSIGNED ),
- SendPropInt( SENDINFO( m_bSmoke ), 1, SPROP_UNSIGNED ),
- SendPropInt( SENDINFO( m_bPropFlare ), 1, SPROP_UNSIGNED ),
-END_SEND_TABLE()
-
-CFlare *CFlare::activeFlares = NULL;
-
-CFlare *CFlare::GetActiveFlares( void )
-{
- return CFlare::activeFlares;
-}
-
-Class_T CFlare::Classify( void )
-{
- return CLASS_FLARE;
-}
-
-CBaseEntity *CreateFlare( Vector vOrigin, QAngle Angles, CBaseEntity *pOwner, float flDuration )
-{
- CFlare *pFlare = CFlare::Create( vOrigin, Angles, pOwner, flDuration );
-
- if ( pFlare )
- {
- pFlare->m_bPropFlare = true;
- }
-
- return pFlare;
-}
-
-void KillFlare( CBaseEntity *pOwnerEntity, CBaseEntity *pEntity, float flKillTime )
-{
- CFlare *pFlare = dynamic_cast< CFlare *>( pEntity );
-
- if ( pFlare )
- {
- float flDieTime = (pFlare->m_flTimeBurnOut - gpGlobals->curtime) - flKillTime;
-
- if ( flDieTime > 1.0f )
- {
- pFlare->Die( flDieTime );
- pOwnerEntity->SetNextThink( gpGlobals->curtime + flDieTime + 3.0f );
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-CFlare::CFlare( void )
-{
- m_flScale = 1.0f;
- m_nBounces = 0;
- m_bFading = false;
- m_bLight = true;
- m_bSmoke = true;
- m_flNextDamage = gpGlobals->curtime;
- m_lifeState = LIFE_ALIVE;
- m_iHealth = 100;
- m_bPropFlare = false;
- m_bInActiveList = false;
- m_pNextFlare = NULL;
-}
-
-CFlare::~CFlare()
-{
- CSoundEnvelopeController::GetController().SoundDestroy( m_pBurnSound );
- m_pBurnSound = NULL;
-
- RemoveFromActiveFlares();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CFlare::Precache( void )
-{
- PrecacheModel("models/weapons/flare.mdl" );
-
- PrecacheScriptSound( "Weapon_FlareGun.Burn" );
-
- // FIXME: needed to precache the fire model. Shouldn't have to do this.
- UTIL_PrecacheOther( "_firesmoke" );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : &restore -
-// Output : int
-//-----------------------------------------------------------------------------
-int CFlare::Restore( IRestore &restore )
-{
- int result = BaseClass::Restore( restore );
-
- if ( m_spawnflags & SF_FLARE_NO_DLIGHT )
- {
- m_bLight = false;
- }
-
- if ( m_spawnflags & SF_FLARE_NO_SMOKE )
- {
- m_bSmoke = false;
- }
-
- return result;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CFlare::Spawn( void )
-{
- Precache();
-
- SetModel( "models/weapons/flare.mdl" );
-
- UTIL_SetSize( this, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ) );
-
- SetSolid( SOLID_BBOX );
- AddSolidFlags( FSOLID_NOT_SOLID );
-
- SetMoveType( MOVETYPE_NONE );
- SetFriction( 0.6f );
- SetGravity( UTIL_ScaleForGravity( 400 ) );
- m_flTimeBurnOut = gpGlobals->curtime + 30;
-
- AddEffects( EF_NOSHADOW|EF_NORECEIVESHADOW );
-
- if ( m_spawnflags & SF_FLARE_NO_DLIGHT )
- {
- m_bLight = false;
- }
-
- if ( m_spawnflags & SF_FLARE_NO_SMOKE )
- {
- m_bSmoke = false;
- }
-
- if ( m_spawnflags & SF_FLARE_INFINITE )
- {
- m_flTimeBurnOut = -1.0f;
- }
-
- if ( m_spawnflags & SF_FLARE_START_OFF )
- {
- AddEffects( EF_NODRAW );
- }
-
- AddFlag( FL_OBJECT );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CFlare::Activate( void )
-{
- BaseClass::Activate();
-
- // Start the burning sound if we're already on
- if ( ( m_spawnflags & SF_FLARE_START_OFF ) == false )
- {
- StartBurnSound();
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CFlare::StartBurnSound( void )
-{
- if ( m_pBurnSound == NULL )
- {
- CPASAttenuationFilter filter( this );
- m_pBurnSound = CSoundEnvelopeController::GetController().SoundCreate(
- filter, entindex(), CHAN_WEAPON, "Weapon_FlareGun.Burn", 3.0f );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : vecOrigin -
-// vecAngles -
-// *pOwner -
-// Output : CFlare
-//-----------------------------------------------------------------------------
-CFlare *CFlare::Create( Vector vecOrigin, QAngle vecAngles, CBaseEntity *pOwner, float lifetime )
-{
- CFlare *pFlare = (CFlare *) CreateEntityByName( "env_flare" );
-
- if ( pFlare == NULL )
- return NULL;
-
- UTIL_SetOrigin( pFlare, vecOrigin );
-
- pFlare->SetLocalAngles( vecAngles );
- pFlare->Spawn();
- pFlare->SetTouch( &CFlare::FlareTouch );
- pFlare->SetThink( &CFlare::FlareThink );
-
- //Start up the flare
- pFlare->Start( lifetime );
-
- //Don't start sparking immediately
- pFlare->SetNextThink( gpGlobals->curtime + 0.5f );
-
- //Burn out time
- pFlare->m_flTimeBurnOut = gpGlobals->curtime + lifetime;
-
- pFlare->RemoveSolidFlags( FSOLID_NOT_SOLID );
- pFlare->AddSolidFlags( FSOLID_NOT_STANDABLE );
-
- pFlare->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
-
- pFlare->SetOwnerEntity( pOwner );
- pFlare->m_pOwner = pOwner;
-
- return pFlare;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-unsigned int CFlare::PhysicsSolidMaskForEntity( void ) const
-{
- return MASK_NPCSOLID;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CFlare::FlareThink( void )
-{
- float deltaTime = ( m_flTimeBurnOut - gpGlobals->curtime );
-
- if ( !m_bInActiveList && ( ( deltaTime > FLARE_BLIND_TIME ) || ( m_flTimeBurnOut == -1.0f ) ) )
- {
- AddToActiveFlares();
- }
-
- if ( m_flTimeBurnOut != -1.0f )
- {
- //Fading away
- if ( ( deltaTime <= FLARE_DECAY_TIME ) && ( m_bFading == false ) )
- {
- m_bFading = true;
- CSoundEnvelopeController::GetController().SoundChangePitch( m_pBurnSound, 60, deltaTime );
- CSoundEnvelopeController::GetController().SoundFadeOut( m_pBurnSound, deltaTime );
- }
-
- // if flare is no longer bright, remove it from active flare list
- if ( m_bInActiveList && ( deltaTime <= FLARE_BLIND_TIME ) )
- {
- RemoveFromActiveFlares();
- }
-
- //Burned out
- if ( m_flTimeBurnOut < gpGlobals->curtime )
- {
- UTIL_Remove( this );
- return;
- }
- }
-
- //Act differently underwater
- if ( GetWaterLevel() > 1 )
- {
- UTIL_Bubbles( GetAbsOrigin() + Vector( -2, -2, -2 ), GetAbsOrigin() + Vector( 2, 2, 2 ), 1 );
- m_bSmoke = false;
- }
- else
- {
- //Shoot sparks
- if ( random->RandomInt( 0, 8 ) == 1 )
- {
- g_pEffects->Sparks( GetAbsOrigin() );
- }
- }
-
- //Next update
- SetNextThink( gpGlobals->curtime + 0.1f );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pOther -
-//-----------------------------------------------------------------------------
-void CFlare::FlareBurnTouch( CBaseEntity *pOther )
-{
- if ( pOther && pOther->m_takedamage && ( m_flNextDamage < gpGlobals->curtime ) )
- {
- pOther->TakeDamage( CTakeDamageInfo( this, m_pOwner, 1, (DMG_BULLET|DMG_BURN) ) );
- m_flNextDamage = gpGlobals->curtime + 1.0f;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pOther -
-//-----------------------------------------------------------------------------
-void CFlare::FlareTouch( CBaseEntity *pOther )
-{
- Assert( pOther );
- if ( !pOther->IsSolid() )
- return;
-
- if ( ( m_nBounces < 10 ) && ( GetWaterLevel() < 1 ) )
- {
- // Throw some real chunks here
- g_pEffects->Sparks( GetAbsOrigin() );
- }
-
- //If the flare hit a person or NPC, do damage here.
- if ( pOther && pOther->m_takedamage )
- {
- /*
- The Flare is the iRifle round right now. No damage, just ignite. (sjb)
-
- //Damage is a function of how fast the flare is flying.
- int iDamage = GetAbsVelocity().Length() / 50.0f;
-
- if ( iDamage < 5 )
- {
- //Clamp minimum damage
- iDamage = 5;
- }
-
- //Use m_pOwner, not GetOwnerEntity()
- pOther->TakeDamage( CTakeDamageInfo( this, m_pOwner, iDamage, (DMG_BULLET|DMG_BURN) ) );
- m_flNextDamage = gpGlobals->curtime + 1.0f;
- */
-
- CBaseAnimating *pAnim;
-
- pAnim = dynamic_cast<CBaseAnimating*>(pOther);
- if( pAnim )
- {
- pAnim->Ignite( 30.0f );
- }
-
- Vector vecNewVelocity = GetAbsVelocity();
- vecNewVelocity *= 0.1f;
- SetAbsVelocity( vecNewVelocity );
-
- SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
- SetGravity(1.0f);
-
-
- Die( 0.5 );
-
- return;
- }
- else
- {
- // hit the world, check the material type here, see if the flare should stick.
- trace_t tr;
- tr = CBaseEntity::GetTouchTrace();
-
- //Only do this on the first bounce
- if ( m_nBounces == 0 )
- {
- const surfacedata_t *pdata = physprops->GetSurfaceData( tr.surface.surfaceProps );
-
- if ( pdata != NULL )
- {
- //Only embed into concrete and wood (jdw: too obscure for players?)
- //if ( ( pdata->gameMaterial == 'C' ) || ( pdata->gameMaterial == 'W' ) )
- {
- Vector impactDir = ( tr.endpos - tr.startpos );
- VectorNormalize( impactDir );
-
- float surfDot = tr.plane.normal.Dot( impactDir );
-
- //Do not stick to ceilings or on shallow impacts
- if ( ( tr.plane.normal.z > -0.5f ) && ( surfDot < -0.9f ) )
- {
- RemoveSolidFlags( FSOLID_NOT_SOLID );
- AddSolidFlags( FSOLID_TRIGGER );
- UTIL_SetOrigin( this, tr.endpos + ( tr.plane.normal * 2.0f ) );
- SetAbsVelocity( vec3_origin );
- SetMoveType( MOVETYPE_NONE );
-
- SetTouch( &CFlare::FlareBurnTouch );
-
- int index = decalsystem->GetDecalIndexForName( "SmallScorch" );
- if ( index >= 0 )
- {
- CBroadcastRecipientFilter filter;
- te->Decal( filter, 0.0, &tr.endpos, &tr.startpos, ENTINDEX( tr.m_pEnt ), tr.hitbox, index );
- }
-
- CPASAttenuationFilter filter2( this, "Flare.Touch" );
- EmitSound( filter2, entindex(), "Flare.Touch" );
-
- return;
- }
- }
- }
- }
-
- //Scorch decal
- if ( GetAbsVelocity().LengthSqr() > (250*250) )
- {
- int index = decalsystem->GetDecalIndexForName( "FadingScorch" );
- if ( index >= 0 )
- {
- CBroadcastRecipientFilter filter;
- te->Decal( filter, 0.0, &tr.endpos, &tr.startpos, ENTINDEX( tr.m_pEnt ), tr.hitbox, index );
- }
- }
-
- // Change our flight characteristics
- SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
- SetGravity( UTIL_ScaleForGravity( 640 ) );
-
- m_nBounces++;
-
- //After the first bounce, smacking into whoever fired the flare is fair game
- SetOwnerEntity( this );
-
- // Slow down
- Vector vecNewVelocity = GetAbsVelocity();
- vecNewVelocity.x *= 0.8f;
- vecNewVelocity.y *= 0.8f;
- SetAbsVelocity( vecNewVelocity );
-
- //Stopped?
- if ( GetAbsVelocity().Length() < 64.0f )
- {
- SetAbsVelocity( vec3_origin );
- SetMoveType( MOVETYPE_NONE );
- RemoveSolidFlags( FSOLID_NOT_SOLID );
- AddSolidFlags( FSOLID_TRIGGER );
- SetTouch( &CFlare::FlareBurnTouch );
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CFlare::Start( float lifeTime )
-{
- StartBurnSound();
-
- if ( m_pBurnSound != NULL )
- {
- CSoundEnvelopeController::GetController().Play( m_pBurnSound, 0.0f, 60 );
- CSoundEnvelopeController::GetController().SoundChangeVolume( m_pBurnSound, 0.8f, 2.0f );
- CSoundEnvelopeController::GetController().SoundChangePitch( m_pBurnSound, 100, 2.0f );
- }
-
- if ( lifeTime > 0 )
- {
- m_flTimeBurnOut = gpGlobals->curtime + lifeTime;
- }
- else
- {
- m_flTimeBurnOut = -1.0f;
- }
-
- RemoveEffects( EF_NODRAW );
-
- SetThink( &CFlare::FlareThink );
- SetNextThink( gpGlobals->curtime + 0.1f );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CFlare::Die( float fadeTime )
-{
- m_flTimeBurnOut = gpGlobals->curtime + fadeTime;
-
- SetThink( &CFlare::FlareThink );
- SetNextThink( gpGlobals->curtime + 0.1f );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CFlare::Launch( const Vector &direction, float speed )
-{
- // Make sure we're visible
- if ( m_spawnflags & SF_FLARE_INFINITE )
- {
- Start( -1 );
- }
- else
- {
- Start( 8.0f );
- }
-
- SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
-
- // Punch our velocity towards our facing
- SetAbsVelocity( direction * speed );
-
- SetGravity( 1.0f );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : &inputdata -
-//-----------------------------------------------------------------------------
-void CFlare::InputStart( inputdata_t &inputdata )
-{
- Start( inputdata.value.Float() );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : &inputdata -
-//-----------------------------------------------------------------------------
-void CFlare::InputDie( inputdata_t &inputdata )
-{
- Die( inputdata.value.Float() );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : &inputdata -
-//-----------------------------------------------------------------------------
-void CFlare::InputLaunch( inputdata_t &inputdata )
-{
- Vector direction;
- AngleVectors( GetAbsAngles(), &direction );
-
- float speed = inputdata.value.Float();
-
- if ( speed == 0 )
- {
- speed = FLARE_LAUNCH_SPEED;
- }
-
- Launch( direction, speed );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Removes flare from active flare list
-//-----------------------------------------------------------------------------
-void CFlare::RemoveFromActiveFlares( void )
-{
- CFlare *pFlare;
- CFlare *pPrevFlare;
-
- if ( !m_bInActiveList )
- return;
-
- pPrevFlare = NULL;
- for( pFlare = CFlare::activeFlares; pFlare != NULL; pFlare = pFlare->m_pNextFlare )
- {
- if ( pFlare == this )
- {
- if ( pPrevFlare )
- {
- pPrevFlare->m_pNextFlare = m_pNextFlare;
- }
- else
- {
- activeFlares = m_pNextFlare;
- }
- break;
- }
- pPrevFlare = pFlare;
- }
-
- m_pNextFlare = NULL;
- m_bInActiveList = false;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Adds flare to active flare list
-//-----------------------------------------------------------------------------
-void CFlare::AddToActiveFlares( void )
-{
- if ( !m_bInActiveList )
- {
- m_pNextFlare = CFlare::activeFlares;
- CFlare::activeFlares = this;
- m_bInActiveList = true;
- }
-}
-
-#if 0
-
-IMPLEMENT_SERVERCLASS_ST(CFlaregun, DT_Flaregun)
-END_SEND_TABLE()
-
-LINK_ENTITY_TO_CLASS( weapon_flaregun, CFlaregun );
-PRECACHE_WEAPON_REGISTER( weapon_flaregun );
-
-//-----------------------------------------------------------------------------
-// Purpose: Precache
-//-----------------------------------------------------------------------------
-void CFlaregun::Precache( void )
-{
- BaseClass::Precache();
-
- PrecacheScriptSound( "Flare.Touch" );
-
- PrecacheScriptSound( "Weapon_FlareGun.Burn" );
-
- UTIL_PrecacheOther( "env_flare" );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Main attack
-//-----------------------------------------------------------------------------
-void CFlaregun::PrimaryAttack( void )
-{
- CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
-
- if ( pOwner == NULL )
- return;
-
- if ( m_iClip1 <= 0 )
- {
- SendWeaponAnim( ACT_VM_DRYFIRE );
- pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration();
- return;
- }
-
- m_iClip1 = m_iClip1 - 1;
-
- SendWeaponAnim( ACT_VM_PRIMARYATTACK );
- pOwner->m_flNextAttack = gpGlobals->curtime + 1;
-
- CFlare *pFlare = CFlare::Create( pOwner->Weapon_ShootPosition(), pOwner->EyeAngles(), pOwner, FLARE_DURATION );
-
- if ( pFlare == NULL )
- return;
-
- Vector forward;
- pOwner->EyeVectors( &forward );
-
- pFlare->SetAbsVelocity( forward * 1500 );
-
- WeaponSound( SINGLE );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CFlaregun::SecondaryAttack( void )
-{
- CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
-
- if ( pOwner == NULL )
- return;
-
- if ( m_iClip1 <= 0 )
- {
- SendWeaponAnim( ACT_VM_DRYFIRE );
- pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration();
- return;
- }
-
- m_iClip1 = m_iClip1 - 1;
-
- SendWeaponAnim( ACT_VM_PRIMARYATTACK );
- pOwner->m_flNextAttack = gpGlobals->curtime + 1;
-
- CFlare *pFlare = CFlare::Create( pOwner->Weapon_ShootPosition(), pOwner->EyeAngles(), pOwner, FLARE_DURATION );
-
- if ( pFlare == NULL )
- return;
-
- Vector forward;
- pOwner->EyeVectors( &forward );
-
- pFlare->SetAbsVelocity( forward * 500 );
- pFlare->SetGravity(1.0f);
- pFlare->SetFriction( 0.85f );
- pFlare->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
-
- WeaponSound( SINGLE );
-}
-
-#endif
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Flare gun (fffsssssssssss!!)
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "player.h"
+#include "gamerules.h"
+#include "basehlcombatweapon.h"
+#include "decals.h"
+#include "soundenvelope.h"
+#include "IEffects.h"
+#include "engine/IEngineSound.h"
+#include "weapon_flaregun.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+/********************************************************************
+ NOTE: if you are looking at this file becase you would like flares
+ to be considered as fires (and thereby trigger gas traps), be aware
+ that the env_flare class is actually found in weapon_flaregun.cpp
+ and is really a repurposed piece of ammunition. (env_flare isn't the
+ rod-like safety flare prop, but rather the bit of flame on the end.)
+
+ You will have some difficulty making it work here, because CFlare
+ does not inherit from CFire and will thus not be enumerated by
+ CFireSphere::EnumElement(). In order to have flares be detected and
+ used by this system, you will need to promote certain member functions
+ of CFire into an interface class from which both CFire and CFlare
+ inherit. You will also need to modify CFireSphere::EnumElement so that
+ it properly disambiguates between fires and flares.
+
+ For some partial work towards this end, see changelist 192474.
+
+ ********************************************************************/
+
+
+#define FLARE_LAUNCH_SPEED 1500
+
+LINK_ENTITY_TO_CLASS( env_flare, CFlare );
+
+BEGIN_DATADESC( CFlare )
+
+ DEFINE_FIELD( m_pOwner, FIELD_CLASSPTR ),
+ DEFINE_FIELD( m_nBounces, FIELD_INTEGER ),
+ DEFINE_FIELD( m_flTimeBurnOut, FIELD_TIME ),
+ DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "scale" ),
+ DEFINE_KEYFIELD( m_flDuration, FIELD_FLOAT, "duration" ),
+ DEFINE_FIELD( m_flNextDamage, FIELD_TIME ),
+ DEFINE_SOUNDPATCH( m_pBurnSound ),
+ DEFINE_FIELD( m_bFading, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bLight, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bSmoke, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bPropFlare, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bInActiveList, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_pNextFlare, FIELD_CLASSPTR ),
+
+ //Input functions
+ DEFINE_INPUTFUNC( FIELD_FLOAT, "Start", InputStart ),
+ DEFINE_INPUTFUNC( FIELD_FLOAT, "Die", InputDie ),
+ DEFINE_INPUTFUNC( FIELD_FLOAT, "Launch", InputLaunch),
+
+ // Function Pointers
+ DEFINE_FUNCTION( FlareTouch ),
+ DEFINE_FUNCTION( FlareBurnTouch ),
+ DEFINE_FUNCTION( FlareThink ),
+
+END_DATADESC()
+
+//Data-tables
+IMPLEMENT_SERVERCLASS_ST( CFlare, DT_Flare )
+ SendPropFloat( SENDINFO( m_flTimeBurnOut ), 0, SPROP_NOSCALE ),
+ SendPropFloat( SENDINFO( m_flScale ), 0, SPROP_NOSCALE ),
+ SendPropInt( SENDINFO( m_bLight ), 1, SPROP_UNSIGNED ),
+ SendPropInt( SENDINFO( m_bSmoke ), 1, SPROP_UNSIGNED ),
+ SendPropInt( SENDINFO( m_bPropFlare ), 1, SPROP_UNSIGNED ),
+END_SEND_TABLE()
+
+CFlare *CFlare::activeFlares = NULL;
+
+CFlare *CFlare::GetActiveFlares( void )
+{
+ return CFlare::activeFlares;
+}
+
+Class_T CFlare::Classify( void )
+{
+ return CLASS_FLARE;
+}
+
+CBaseEntity *CreateFlare( Vector vOrigin, QAngle Angles, CBaseEntity *pOwner, float flDuration )
+{
+ CFlare *pFlare = CFlare::Create( vOrigin, Angles, pOwner, flDuration );
+
+ if ( pFlare )
+ {
+ pFlare->m_bPropFlare = true;
+ }
+
+ return pFlare;
+}
+
+void KillFlare( CBaseEntity *pOwnerEntity, CBaseEntity *pEntity, float flKillTime )
+{
+ CFlare *pFlare = dynamic_cast< CFlare *>( pEntity );
+
+ if ( pFlare )
+ {
+ float flDieTime = (pFlare->m_flTimeBurnOut - gpGlobals->curtime) - flKillTime;
+
+ if ( flDieTime > 1.0f )
+ {
+ pFlare->Die( flDieTime );
+ pOwnerEntity->SetNextThink( gpGlobals->curtime + flDieTime + 3.0f );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CFlare::CFlare( void )
+{
+ m_flScale = 1.0f;
+ m_nBounces = 0;
+ m_bFading = false;
+ m_bLight = true;
+ m_bSmoke = true;
+ m_flNextDamage = gpGlobals->curtime;
+ m_lifeState = LIFE_ALIVE;
+ m_iHealth = 100;
+ m_bPropFlare = false;
+ m_bInActiveList = false;
+ m_pNextFlare = NULL;
+}
+
+CFlare::~CFlare()
+{
+ CSoundEnvelopeController::GetController().SoundDestroy( m_pBurnSound );
+ m_pBurnSound = NULL;
+
+ RemoveFromActiveFlares();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CFlare::Precache( void )
+{
+ PrecacheModel("models/weapons/flare.mdl" );
+
+ PrecacheScriptSound( "Weapon_FlareGun.Burn" );
+
+ // FIXME: needed to precache the fire model. Shouldn't have to do this.
+ UTIL_PrecacheOther( "_firesmoke" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &restore -
+// Output : int
+//-----------------------------------------------------------------------------
+int CFlare::Restore( IRestore &restore )
+{
+ int result = BaseClass::Restore( restore );
+
+ if ( m_spawnflags & SF_FLARE_NO_DLIGHT )
+ {
+ m_bLight = false;
+ }
+
+ if ( m_spawnflags & SF_FLARE_NO_SMOKE )
+ {
+ m_bSmoke = false;
+ }
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CFlare::Spawn( void )
+{
+ Precache();
+
+ SetModel( "models/weapons/flare.mdl" );
+
+ UTIL_SetSize( this, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ) );
+
+ SetSolid( SOLID_BBOX );
+ AddSolidFlags( FSOLID_NOT_SOLID );
+
+ SetMoveType( MOVETYPE_NONE );
+ SetFriction( 0.6f );
+ SetGravity( UTIL_ScaleForGravity( 400 ) );
+ m_flTimeBurnOut = gpGlobals->curtime + 30;
+
+ AddEffects( EF_NOSHADOW|EF_NORECEIVESHADOW );
+
+ if ( m_spawnflags & SF_FLARE_NO_DLIGHT )
+ {
+ m_bLight = false;
+ }
+
+ if ( m_spawnflags & SF_FLARE_NO_SMOKE )
+ {
+ m_bSmoke = false;
+ }
+
+ if ( m_spawnflags & SF_FLARE_INFINITE )
+ {
+ m_flTimeBurnOut = -1.0f;
+ }
+
+ if ( m_spawnflags & SF_FLARE_START_OFF )
+ {
+ AddEffects( EF_NODRAW );
+ }
+
+ AddFlag( FL_OBJECT );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CFlare::Activate( void )
+{
+ BaseClass::Activate();
+
+ // Start the burning sound if we're already on
+ if ( ( m_spawnflags & SF_FLARE_START_OFF ) == false )
+ {
+ StartBurnSound();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CFlare::StartBurnSound( void )
+{
+ if ( m_pBurnSound == NULL )
+ {
+ CPASAttenuationFilter filter( this );
+ m_pBurnSound = CSoundEnvelopeController::GetController().SoundCreate(
+ filter, entindex(), CHAN_WEAPON, "Weapon_FlareGun.Burn", 3.0f );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : vecOrigin -
+// vecAngles -
+// *pOwner -
+// Output : CFlare
+//-----------------------------------------------------------------------------
+CFlare *CFlare::Create( Vector vecOrigin, QAngle vecAngles, CBaseEntity *pOwner, float lifetime )
+{
+ CFlare *pFlare = (CFlare *) CreateEntityByName( "env_flare" );
+
+ if ( pFlare == NULL )
+ return NULL;
+
+ UTIL_SetOrigin( pFlare, vecOrigin );
+
+ pFlare->SetLocalAngles( vecAngles );
+ pFlare->Spawn();
+ pFlare->SetTouch( &CFlare::FlareTouch );
+ pFlare->SetThink( &CFlare::FlareThink );
+
+ //Start up the flare
+ pFlare->Start( lifetime );
+
+ //Don't start sparking immediately
+ pFlare->SetNextThink( gpGlobals->curtime + 0.5f );
+
+ //Burn out time
+ pFlare->m_flTimeBurnOut = gpGlobals->curtime + lifetime;
+
+ pFlare->RemoveSolidFlags( FSOLID_NOT_SOLID );
+ pFlare->AddSolidFlags( FSOLID_NOT_STANDABLE );
+
+ pFlare->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
+
+ pFlare->SetOwnerEntity( pOwner );
+ pFlare->m_pOwner = pOwner;
+
+ return pFlare;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+unsigned int CFlare::PhysicsSolidMaskForEntity( void ) const
+{
+ return MASK_NPCSOLID;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CFlare::FlareThink( void )
+{
+ float deltaTime = ( m_flTimeBurnOut - gpGlobals->curtime );
+
+ if ( !m_bInActiveList && ( ( deltaTime > FLARE_BLIND_TIME ) || ( m_flTimeBurnOut == -1.0f ) ) )
+ {
+ AddToActiveFlares();
+ }
+
+ if ( m_flTimeBurnOut != -1.0f )
+ {
+ //Fading away
+ if ( ( deltaTime <= FLARE_DECAY_TIME ) && ( m_bFading == false ) )
+ {
+ m_bFading = true;
+ CSoundEnvelopeController::GetController().SoundChangePitch( m_pBurnSound, 60, deltaTime );
+ CSoundEnvelopeController::GetController().SoundFadeOut( m_pBurnSound, deltaTime );
+ }
+
+ // if flare is no longer bright, remove it from active flare list
+ if ( m_bInActiveList && ( deltaTime <= FLARE_BLIND_TIME ) )
+ {
+ RemoveFromActiveFlares();
+ }
+
+ //Burned out
+ if ( m_flTimeBurnOut < gpGlobals->curtime )
+ {
+ UTIL_Remove( this );
+ return;
+ }
+ }
+
+ //Act differently underwater
+ if ( GetWaterLevel() > 1 )
+ {
+ UTIL_Bubbles( GetAbsOrigin() + Vector( -2, -2, -2 ), GetAbsOrigin() + Vector( 2, 2, 2 ), 1 );
+ m_bSmoke = false;
+ }
+ else
+ {
+ //Shoot sparks
+ if ( random->RandomInt( 0, 8 ) == 1 )
+ {
+ g_pEffects->Sparks( GetAbsOrigin() );
+ }
+ }
+
+ //Next update
+ SetNextThink( gpGlobals->curtime + 0.1f );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pOther -
+//-----------------------------------------------------------------------------
+void CFlare::FlareBurnTouch( CBaseEntity *pOther )
+{
+ if ( pOther && pOther->m_takedamage && ( m_flNextDamage < gpGlobals->curtime ) )
+ {
+ pOther->TakeDamage( CTakeDamageInfo( this, m_pOwner, 1, (DMG_BULLET|DMG_BURN) ) );
+ m_flNextDamage = gpGlobals->curtime + 1.0f;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pOther -
+//-----------------------------------------------------------------------------
+void CFlare::FlareTouch( CBaseEntity *pOther )
+{
+ Assert( pOther );
+ if ( !pOther->IsSolid() )
+ return;
+
+ if ( ( m_nBounces < 10 ) && ( GetWaterLevel() < 1 ) )
+ {
+ // Throw some real chunks here
+ g_pEffects->Sparks( GetAbsOrigin() );
+ }
+
+ //If the flare hit a person or NPC, do damage here.
+ if ( pOther && pOther->m_takedamage )
+ {
+ /*
+ The Flare is the iRifle round right now. No damage, just ignite. (sjb)
+
+ //Damage is a function of how fast the flare is flying.
+ int iDamage = GetAbsVelocity().Length() / 50.0f;
+
+ if ( iDamage < 5 )
+ {
+ //Clamp minimum damage
+ iDamage = 5;
+ }
+
+ //Use m_pOwner, not GetOwnerEntity()
+ pOther->TakeDamage( CTakeDamageInfo( this, m_pOwner, iDamage, (DMG_BULLET|DMG_BURN) ) );
+ m_flNextDamage = gpGlobals->curtime + 1.0f;
+ */
+
+ CBaseAnimating *pAnim;
+
+ pAnim = dynamic_cast<CBaseAnimating*>(pOther);
+ if( pAnim )
+ {
+ pAnim->Ignite( 30.0f );
+ }
+
+ Vector vecNewVelocity = GetAbsVelocity();
+ vecNewVelocity *= 0.1f;
+ SetAbsVelocity( vecNewVelocity );
+
+ SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
+ SetGravity(1.0f);
+
+
+ Die( 0.5 );
+
+ return;
+ }
+ else
+ {
+ // hit the world, check the material type here, see if the flare should stick.
+ trace_t tr;
+ tr = CBaseEntity::GetTouchTrace();
+
+ //Only do this on the first bounce
+ if ( m_nBounces == 0 )
+ {
+ const surfacedata_t *pdata = physprops->GetSurfaceData( tr.surface.surfaceProps );
+
+ if ( pdata != NULL )
+ {
+ //Only embed into concrete and wood (jdw: too obscure for players?)
+ //if ( ( pdata->gameMaterial == 'C' ) || ( pdata->gameMaterial == 'W' ) )
+ {
+ Vector impactDir = ( tr.endpos - tr.startpos );
+ VectorNormalize( impactDir );
+
+ float surfDot = tr.plane.normal.Dot( impactDir );
+
+ //Do not stick to ceilings or on shallow impacts
+ if ( ( tr.plane.normal.z > -0.5f ) && ( surfDot < -0.9f ) )
+ {
+ RemoveSolidFlags( FSOLID_NOT_SOLID );
+ AddSolidFlags( FSOLID_TRIGGER );
+ UTIL_SetOrigin( this, tr.endpos + ( tr.plane.normal * 2.0f ) );
+ SetAbsVelocity( vec3_origin );
+ SetMoveType( MOVETYPE_NONE );
+
+ SetTouch( &CFlare::FlareBurnTouch );
+
+ int index = decalsystem->GetDecalIndexForName( "SmallScorch" );
+ if ( index >= 0 )
+ {
+ CBroadcastRecipientFilter filter;
+ te->Decal( filter, 0.0, &tr.endpos, &tr.startpos, ENTINDEX( tr.m_pEnt ), tr.hitbox, index );
+ }
+
+ CPASAttenuationFilter filter2( this, "Flare.Touch" );
+ EmitSound( filter2, entindex(), "Flare.Touch" );
+
+ return;
+ }
+ }
+ }
+ }
+
+ //Scorch decal
+ if ( GetAbsVelocity().LengthSqr() > (250*250) )
+ {
+ int index = decalsystem->GetDecalIndexForName( "FadingScorch" );
+ if ( index >= 0 )
+ {
+ CBroadcastRecipientFilter filter;
+ te->Decal( filter, 0.0, &tr.endpos, &tr.startpos, ENTINDEX( tr.m_pEnt ), tr.hitbox, index );
+ }
+ }
+
+ // Change our flight characteristics
+ SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
+ SetGravity( UTIL_ScaleForGravity( 640 ) );
+
+ m_nBounces++;
+
+ //After the first bounce, smacking into whoever fired the flare is fair game
+ SetOwnerEntity( this );
+
+ // Slow down
+ Vector vecNewVelocity = GetAbsVelocity();
+ vecNewVelocity.x *= 0.8f;
+ vecNewVelocity.y *= 0.8f;
+ SetAbsVelocity( vecNewVelocity );
+
+ //Stopped?
+ if ( GetAbsVelocity().Length() < 64.0f )
+ {
+ SetAbsVelocity( vec3_origin );
+ SetMoveType( MOVETYPE_NONE );
+ RemoveSolidFlags( FSOLID_NOT_SOLID );
+ AddSolidFlags( FSOLID_TRIGGER );
+ SetTouch( &CFlare::FlareBurnTouch );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CFlare::Start( float lifeTime )
+{
+ StartBurnSound();
+
+ if ( m_pBurnSound != NULL )
+ {
+ CSoundEnvelopeController::GetController().Play( m_pBurnSound, 0.0f, 60 );
+ CSoundEnvelopeController::GetController().SoundChangeVolume( m_pBurnSound, 0.8f, 2.0f );
+ CSoundEnvelopeController::GetController().SoundChangePitch( m_pBurnSound, 100, 2.0f );
+ }
+
+ if ( lifeTime > 0 )
+ {
+ m_flTimeBurnOut = gpGlobals->curtime + lifeTime;
+ }
+ else
+ {
+ m_flTimeBurnOut = -1.0f;
+ }
+
+ RemoveEffects( EF_NODRAW );
+
+ SetThink( &CFlare::FlareThink );
+ SetNextThink( gpGlobals->curtime + 0.1f );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CFlare::Die( float fadeTime )
+{
+ m_flTimeBurnOut = gpGlobals->curtime + fadeTime;
+
+ SetThink( &CFlare::FlareThink );
+ SetNextThink( gpGlobals->curtime + 0.1f );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CFlare::Launch( const Vector &direction, float speed )
+{
+ // Make sure we're visible
+ if ( m_spawnflags & SF_FLARE_INFINITE )
+ {
+ Start( -1 );
+ }
+ else
+ {
+ Start( 8.0f );
+ }
+
+ SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
+
+ // Punch our velocity towards our facing
+ SetAbsVelocity( direction * speed );
+
+ SetGravity( 1.0f );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &inputdata -
+//-----------------------------------------------------------------------------
+void CFlare::InputStart( inputdata_t &inputdata )
+{
+ Start( inputdata.value.Float() );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &inputdata -
+//-----------------------------------------------------------------------------
+void CFlare::InputDie( inputdata_t &inputdata )
+{
+ Die( inputdata.value.Float() );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &inputdata -
+//-----------------------------------------------------------------------------
+void CFlare::InputLaunch( inputdata_t &inputdata )
+{
+ Vector direction;
+ AngleVectors( GetAbsAngles(), &direction );
+
+ float speed = inputdata.value.Float();
+
+ if ( speed == 0 )
+ {
+ speed = FLARE_LAUNCH_SPEED;
+ }
+
+ Launch( direction, speed );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Removes flare from active flare list
+//-----------------------------------------------------------------------------
+void CFlare::RemoveFromActiveFlares( void )
+{
+ CFlare *pFlare;
+ CFlare *pPrevFlare;
+
+ if ( !m_bInActiveList )
+ return;
+
+ pPrevFlare = NULL;
+ for( pFlare = CFlare::activeFlares; pFlare != NULL; pFlare = pFlare->m_pNextFlare )
+ {
+ if ( pFlare == this )
+ {
+ if ( pPrevFlare )
+ {
+ pPrevFlare->m_pNextFlare = m_pNextFlare;
+ }
+ else
+ {
+ activeFlares = m_pNextFlare;
+ }
+ break;
+ }
+ pPrevFlare = pFlare;
+ }
+
+ m_pNextFlare = NULL;
+ m_bInActiveList = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Adds flare to active flare list
+//-----------------------------------------------------------------------------
+void CFlare::AddToActiveFlares( void )
+{
+ if ( !m_bInActiveList )
+ {
+ m_pNextFlare = CFlare::activeFlares;
+ CFlare::activeFlares = this;
+ m_bInActiveList = true;
+ }
+}
+
+#if 0
+
+IMPLEMENT_SERVERCLASS_ST(CFlaregun, DT_Flaregun)
+END_SEND_TABLE()
+
+LINK_ENTITY_TO_CLASS( weapon_flaregun, CFlaregun );
+PRECACHE_WEAPON_REGISTER( weapon_flaregun );
+
+//-----------------------------------------------------------------------------
+// Purpose: Precache
+//-----------------------------------------------------------------------------
+void CFlaregun::Precache( void )
+{
+ BaseClass::Precache();
+
+ PrecacheScriptSound( "Flare.Touch" );
+
+ PrecacheScriptSound( "Weapon_FlareGun.Burn" );
+
+ UTIL_PrecacheOther( "env_flare" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Main attack
+//-----------------------------------------------------------------------------
+void CFlaregun::PrimaryAttack( void )
+{
+ CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
+
+ if ( pOwner == NULL )
+ return;
+
+ if ( m_iClip1 <= 0 )
+ {
+ SendWeaponAnim( ACT_VM_DRYFIRE );
+ pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration();
+ return;
+ }
+
+ m_iClip1 = m_iClip1 - 1;
+
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+ pOwner->m_flNextAttack = gpGlobals->curtime + 1;
+
+ CFlare *pFlare = CFlare::Create( pOwner->Weapon_ShootPosition(), pOwner->EyeAngles(), pOwner, FLARE_DURATION );
+
+ if ( pFlare == NULL )
+ return;
+
+ Vector forward;
+ pOwner->EyeVectors( &forward );
+
+ pFlare->SetAbsVelocity( forward * 1500 );
+
+ WeaponSound( SINGLE );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CFlaregun::SecondaryAttack( void )
+{
+ CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
+
+ if ( pOwner == NULL )
+ return;
+
+ if ( m_iClip1 <= 0 )
+ {
+ SendWeaponAnim( ACT_VM_DRYFIRE );
+ pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration();
+ return;
+ }
+
+ m_iClip1 = m_iClip1 - 1;
+
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+ pOwner->m_flNextAttack = gpGlobals->curtime + 1;
+
+ CFlare *pFlare = CFlare::Create( pOwner->Weapon_ShootPosition(), pOwner->EyeAngles(), pOwner, FLARE_DURATION );
+
+ if ( pFlare == NULL )
+ return;
+
+ Vector forward;
+ pOwner->EyeVectors( &forward );
+
+ pFlare->SetAbsVelocity( forward * 500 );
+ pFlare->SetGravity(1.0f);
+ pFlare->SetFriction( 0.85f );
+ pFlare->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
+
+ WeaponSound( SINGLE );
+}
+
+#endif