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.
755 lines
20 KiB
755 lines
20 KiB
//========= 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
|
|
|