This is a multi-part message in MIME format.
--
I'm trying to add a weapon with an alt_fire like that of the flare gun or 
irifle. When I only had the main fire, everything worked. I added in the flare, 
copying from weapon_flaregun, but sound and collisions didn't work right.

When I tried to fix it, hl2 makes it to the loading screen (before title, after 
intro videos), then crashes with "InitFastCopy - missing client class 44". I 
suspect it has something to do with client/server problems, but beyond that I'm 
clueless.

Can someone tell me what I'm doing wrong? Complete code below:

weapon_smg2.h (server)

======================================================================

#include "basehlcombatweapon.h"
#include "soundenvelope.h"
#include "cbase.h"
#include "player.h"
#include "gamerules.h"
#include "decals.h"
#include "IEffects.h"
#include "engine/IEngineSound.h"

#ifndef WEAPON_SMG2_H
#define WEAPON_SMG2_H
#ifdef _WIN32
#pragma once
#endif

#define SF_FLARE_NO_DLIGHT      0x00000001
#define SF_FLARE_NO_SMOKE       0x00000002
#define SF_FLARE_INFINITE       0x00000004
#define SF_FLARE_START_OFF      0x00000008

#define FLARE_DURATION          30.0f
#define FLARE_DECAY_TIME        10.0f
#define FLARE_BLIND_TIME        6.0f

//---------------------
// Flare
//---------------------

class CFlareGrenade : public CBaseCombatCharacter
{
public:
        DECLARE_CLASS( CFlareGrenade, CBaseCombatCharacter );

        CFlareGrenade();
        ~CFlareGrenade();

        static CFlareGrenade *  GetActiveFlares( void );
        CFlareGrenade *         GetNextFlare( void ) const { return 
m_pNextFlare; }

        static CFlareGrenade *Create( Vector vecOrigin, QAngle vecAngles, 
CBaseEntity *pOwner, float lifetime );

        virtual unsigned int PhysicsSolidMaskForEntity( void ) const;

        void    Spawn( void );
        void    Precache( void );
        int             Restore( IRestore &restore );
        void    Activate( void );

        void    StartBurnSound( void );

        void    Start( float lifeTime );
        void    Die( float fadeTime );
        void    Launch( const Vector &direction, float speed );

        Class_T Classify( void );

        void    FlareTouch( CBaseEntity *pOther );
        void    FlareBurnTouch( CBaseEntity *pOther );
        void    FlareThink( void );

        void    InputStart( inputdata_t &inputdata );
        void    InputDie( inputdata_t &inputdata );
        void    InputLaunch( inputdata_t &inputdata );

        DECLARE_SERVERCLASS();
        DECLARE_DATADESC();

        static CFlareGrenade *activeFlares;

        CBaseEntity *m_pOwner;
        int                     m_nBounces;                     // how many 
times has this flare bounced?
        CNetworkVar( float, m_flTimeBurnOut );  // when will the flare burn out?
        CNetworkVar( float, m_flScale );
        float           m_flDuration;
        float           m_flNextDamage;

        CSoundPatch     *m_pBurnSound;
        bool            m_bFading;
        CNetworkVar( bool, m_bLight );
        CNetworkVar( bool, m_bSmoke );
        CNetworkVar( bool, m_bPropFlare );

        bool            m_bInActiveList;
        CFlareGrenade * m_pNextFlare;

        void            RemoveFromActiveFlares( void );
        void            AddToActiveFlares( void );
};


#define FLARE_LAUNCH_SPEED      1500

BEGIN_DATADESC( CFlareGrenade )

        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( CFlareGrenade, DT_FlareGrenade )
        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()

LINK_ENTITY_TO_CLASS( flare_grenade, CFlareGrenade );

CFlareGrenade *CFlareGrenade::activeFlares = NULL;

CFlareGrenade *CFlareGrenade::GetActiveFlares( void )
{
        return CFlareGrenade::activeFlares;
}

Class_T CFlareGrenade::Classify( void )
{
        return CLASS_FLARE;
}

CBaseEntity *CreateFlareGrenade( Vector vOrigin, QAngle Angles, CBaseEntity 
*pOwner, float flDuration )
{
        CFlareGrenade *pFlare = CFlareGrenade::Create( vOrigin, Angles, pOwner, 
flDuration );

        if ( pFlare )
        {
                pFlare->m_bPropFlare = true;
        }

        return pFlare;
}

void KillFlareGrenade( CBaseEntity *pOwnerEntity, CBaseEntity *pEntity, float 
flKillTime )
{
        CFlareGrenade *pFlare = dynamic_cast< CFlareGrenade *>( 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:
//-----------------------------------------------------------------------------
CFlareGrenade::CFlareGrenade( 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;
}

CFlareGrenade::~CFlareGrenade()
{
        CSoundEnvelopeController::GetController().SoundDestroy( m_pBurnSound );
        m_pBurnSound = NULL;

        RemoveFromActiveFlares();
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFlareGrenade::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 CFlareGrenade::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 CFlareGrenade::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 CFlareGrenade::Activate( void )
{
        BaseClass::Activate();

        // Start the burning sound if we're already on
        if ( ( m_spawnflags & SF_FLARE_START_OFF ) == false )
        {
                StartBurnSound();
        }
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFlareGrenade::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 : CFlareGrenade
//-----------------------------------------------------------------------------
CFlareGrenade *CFlareGrenade::Create( Vector vecOrigin, QAngle vecAngles, 
CBaseEntity *pOwner, float lifetime )
{
        CFlareGrenade *pFlare = (CFlareGrenade *) CreateEntityByName( 
"env_flare" );

        if ( pFlare == NULL )
                return NULL;

        UTIL_SetOrigin( pFlare, vecOrigin );

        pFlare->SetLocalAngles( vecAngles );
        pFlare->Spawn();
        pFlare->SetTouch( &CFlareGrenade::FlareTouch );
        pFlare->SetThink( &CFlareGrenade::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 CFlareGrenade::PhysicsSolidMaskForEntity( void ) const
{
        return MASK_NPCSOLID;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFlareGrenade::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 CFlareGrenade::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 CFlareGrenade::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 )
                {
                        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( 
&CFlareGrenade::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( &CFlareGrenade::FlareBurnTouch );
                }
        }
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFlareGrenade::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( &CFlareGrenade::FlareThink );
        SetNextThink( gpGlobals->curtime + 0.1f );
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFlareGrenade::Die( float fadeTime )
{
        m_flTimeBurnOut = gpGlobals->curtime + fadeTime;

        SetThink( &CFlareGrenade::FlareThink );
        SetNextThink( gpGlobals->curtime + 0.1f );
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFlareGrenade::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 CFlareGrenade::InputStart( inputdata_t &inputdata )
{
        Start( inputdata.value.Float() );
}

//-----------------------------------------------------------------------------
// Purpose:
// Input  : &inputdata -
//-----------------------------------------------------------------------------
void CFlareGrenade::InputDie( inputdata_t &inputdata )
{
        Die( inputdata.value.Float() );
}

//-----------------------------------------------------------------------------
// Purpose:
// Input  : &inputdata -
//-----------------------------------------------------------------------------
void CFlareGrenade::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 CFlareGrenade::RemoveFromActiveFlares( void )
{
        CFlareGrenade *pFlare;
        CFlareGrenade *pPrevFlare;

        if ( !m_bInActiveList )
                return;

        pPrevFlare = NULL;
        for( pFlare = CFlareGrenade::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 CFlareGrenade::AddToActiveFlares( void )
{
        if ( !m_bInActiveList )
        {
                m_pNextFlare = CFlareGrenade::activeFlares;
                CFlareGrenade::activeFlares = this;
                m_bInActiveList = true;
        }
}

#endif // WEAPON_SMG2_H





















weapon_smg2.cpp (server)

======================================================================

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. 
============//
//
// Purpose:
//
//=============================================================================//

#include "cbase.h"
#include "basehlcombatweapon.h"
#include "NPCevent.h"
#include "basecombatcharacter.h"
#include "AI_BaseNPC.h"
#include "player.h"
#include "game.h"
#include "in_buttons.h"
#include "grenade_ar2.h"
#include "AI_Memory.h"
#include "soundent.h"
#include "rumble_shared.h"

#include "weapon_smg2.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

extern ConVar    sk_plr_dmg_smg2_grenade;


#include "basehlcombatweapon.h"
#include "soundenvelope.h"

//-----------------------------------------------------------------------------
// Actual Gun!
//-----------------------------------------------------------------------------

class CWeaponSMG2 : public CHLSelectFireMachineGun
{
        DECLARE_DATADESC();
public:
        DECLARE_CLASS( CWeaponSMG2, CHLSelectFireMachineGun );

        CWeaponSMG2();

        DECLARE_SERVERCLASS();

        void    Precache( void );
        void    AddViewKick( void );
        void    SecondaryAttack( void );

        int             GetMinBurst() { return 5; }
        int             GetMaxBurst() { return 12; }

        virtual void Equip( CBaseCombatCharacter *pOwner );
        bool    Reload( void );

        float   GetFireRate( void ) { return 0.075f; }  // fast
        int             CapabilitiesGet( void ) { return 
bits_CAP_WEAPON_RANGE_ATTACK1; }
        int             WeaponRangeAttack2Condition( float flDot, float flDist 
);
        Activity        GetPrimaryAttackActivity( void );

        virtual const Vector& GetBulletSpread( void )
        {
                static const Vector cone = VECTOR_CONE_5DEGREES;
                return cone;
        }

        const WeaponProficiencyInfo_t *GetProficiencyValues();

        void FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, Vector 
&vecShootOrigin, Vector &vecShootDir );
        void Operator_ForceNPCFire( CBaseCombatCharacter  *pOperator, bool 
bSecondary );
        void Operator_HandleAnimEvent( animevent_t *pEvent, 
CBaseCombatCharacter *pOperator );

        DECLARE_ACTTABLE();

protected:

        Vector  m_vecTossVelocity;
        float   m_flNextGrenadeCheck;
};

IMPLEMENT_SERVERCLASS_ST(CWeaponSMG2, DT_WeaponSMG2)
END_SEND_TABLE()

LINK_ENTITY_TO_CLASS( weapon_smg2, CWeaponSMG2 );
PRECACHE_WEAPON_REGISTER(weapon_smg2);

BEGIN_DATADESC( CWeaponSMG2 )

        DEFINE_FIELD( m_vecTossVelocity, FIELD_VECTOR ),
        DEFINE_FIELD( m_flNextGrenadeCheck, FIELD_TIME ),

END_DATADESC()

acttable_t      CWeaponSMG2::m_acttable[] =
{
        { ACT_RANGE_ATTACK1,                    ACT_RANGE_ATTACK_SMG2,          
        true },
        { ACT_RELOAD,                                   ACT_RELOAD_SMG2,        
                        true },
        { ACT_IDLE,                                             ACT_IDLE_SMG2,  
                                true },
        { ACT_IDLE_ANGRY,                               ACT_IDLE_ANGRY_SMG2,    
                true },

        { ACT_WALK,                                             ACT_WALK_RIFLE, 
                                true },
        { ACT_WALK_AIM,                                 ACT_WALK_AIM_RIFLE,     
                        true  },

// Readiness activities (not aiming)
        { ACT_IDLE_RELAXED,                             ACT_IDLE_SMG2_RELAXED,  
                false },//never aims
        { ACT_IDLE_STIMULATED,                  ACT_IDLE_SMG2_STIMULATED,       
        false },
        { ACT_IDLE_AGITATED,                    ACT_IDLE_ANGRY_SMG2,            
        false },//always aims

        { ACT_WALK_RELAXED,                             ACT_WALK_RIFLE_RELAXED, 
                false },//never aims
        { ACT_WALK_STIMULATED,                  ACT_WALK_RIFLE_STIMULATED,      
        false },
        { ACT_WALK_AGITATED,                    ACT_WALK_AIM_RIFLE,             
                false },//always aims

        { ACT_RUN_RELAXED,                              ACT_RUN_RIFLE_RELAXED,  
                false },//never aims
        { ACT_RUN_STIMULATED,                   ACT_RUN_RIFLE_STIMULATED,       
        false },
        { ACT_RUN_AGITATED,                             ACT_RUN_AIM_RIFLE,      
                        false },//always aims

// Readiness activities (aiming)
        { ACT_IDLE_AIM_RELAXED,                 ACT_IDLE_SMG2_RELAXED,          
        false },//never aims
        { ACT_IDLE_AIM_STIMULATED,              ACT_IDLE_AIM_RIFLE_STIMULATED,  
false },
        { ACT_IDLE_AIM_AGITATED,                ACT_IDLE_ANGRY_SMG2,            
        false },//always aims

        { ACT_WALK_AIM_RELAXED,                 ACT_WALK_RIFLE_RELAXED,         
        false },//never aims
        { ACT_WALK_AIM_STIMULATED,              ACT_WALK_AIM_RIFLE_STIMULATED,  
false },
        { ACT_WALK_AIM_AGITATED,                ACT_WALK_AIM_RIFLE,             
                false },//always aims

        { ACT_RUN_AIM_RELAXED,                  ACT_RUN_RIFLE_RELAXED,          
        false },//never aims
        { ACT_RUN_AIM_STIMULATED,               ACT_RUN_AIM_RIFLE_STIMULATED,   
false },
        { ACT_RUN_AIM_AGITATED,                 ACT_RUN_AIM_RIFLE,              
                false },//always aims
//End readiness activities

        { ACT_WALK_AIM,                                 ACT_WALK_AIM_RIFLE,     
                        true },
        { ACT_WALK_CROUCH,                              ACT_WALK_CROUCH_RIFLE,  
                true },
        { ACT_WALK_CROUCH_AIM,                  ACT_WALK_CROUCH_AIM_RIFLE,      
        true },
        { ACT_RUN,                                              ACT_RUN_RIFLE,  
                                true },
        { ACT_RUN_AIM,                                  ACT_RUN_AIM_RIFLE,      
                        true },
        { ACT_RUN_CROUCH,                               ACT_RUN_CROUCH_RIFLE,   
                true },
        { ACT_RUN_CROUCH_AIM,                   ACT_RUN_CROUCH_AIM_RIFLE,       
        true },
        { ACT_GESTURE_RANGE_ATTACK1,    ACT_GESTURE_RANGE_ATTACK_SMG2,  true },
        { ACT_RANGE_ATTACK1_LOW,                ACT_RANGE_ATTACK_SMG2_LOW,      
        true },
        { ACT_COVER_LOW,                                ACT_COVER_SMG2_LOW,     
                        false },
        { ACT_RANGE_AIM_LOW,                    ACT_RANGE_AIM_SMG2_LOW,         
        false },
        { ACT_RELOAD_LOW,                               ACT_RELOAD_SMG2_LOW,    
                false },
        { ACT_GESTURE_RELOAD,                   ACT_GESTURE_RELOAD_SMG2,        
        true },
};

IMPLEMENT_ACTTABLE(CWeaponSMG2);

//=========================================================
CWeaponSMG2::CWeaponSMG2( )
{
        m_fMinRange1            = 0;// No minimum range.
        m_fMaxRange1            = 1400;

        m_bAltFiresUnderwater = true;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponSMG2::Precache( void )
{
        UTIL_PrecacheOther("grenade_ar2"); // Not needed now

        PrecacheScriptSound( "Flare.Touch" );
        PrecacheScriptSound( "Weapon_FlareGun.Burn" );
        UTIL_PrecacheOther( "env_flare" );

        BaseClass::Precache();
}

//-----------------------------------------------------------------------------
// Purpose: Give this weapon longer range when wielded by an ally NPC.
//-----------------------------------------------------------------------------
void CWeaponSMG2::Equip( CBaseCombatCharacter *pOwner )
{
        if( pOwner->Classify() == CLASS_PLAYER_ALLY )
        {
                m_fMaxRange1 = 3000;
        }
        else
        {
                m_fMaxRange1 = 1400;
        }

        BaseClass::Equip( pOwner );
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponSMG2::FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, Vector 
&vecShootOrigin, Vector &vecShootDir )
{
        // FIXME: use the returned number of bullets to account for >10hz 
firerate
        WeaponSoundRealtime( SINGLE_NPC );

        CSoundEnt::InsertSound( SOUND_COMBAT|SOUND_CONTEXT_GUNFIRE, 
pOperator->GetAbsOrigin(), SOUNDENT_VOLUME_MACHINEGUN, 0.2, pOperator, 
SOUNDENT_CHANNEL_WEAPON, pOperator->GetEnemy() );
        pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, 
VECTOR_CONE_PRECALCULATED,
                MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 1, entindex(), 0 );

        pOperator->DoMuzzleFlash();
        m_iClip1 = m_iClip1 - 1;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponSMG2::Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool 
bSecondary )
{
        // Ensure we have enough rounds in the clip
        m_iClip1++;

        Vector vecShootOrigin, vecShootDir;
        QAngle  angShootDir;
        GetAttachment( LookupAttachment( "muzzle" ), vecShootOrigin, 
angShootDir );
        AngleVectors( angShootDir, &vecShootDir );
        FireNPCPrimaryAttack( pOperator, vecShootOrigin, vecShootDir );
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponSMG2::Operator_HandleAnimEvent( animevent_t *pEvent, 
CBaseCombatCharacter *pOperator )
{
        switch( pEvent->event )
        {
        case EVENT_WEAPON_SMG2:
                {
                        Vector vecShootOrigin, vecShootDir;
                        QAngle angDiscard;

                        // Support old style attachment point firing
                        if ((pEvent->options == NULL) || (pEvent->options[0] == 
'\0') || (!pOperator->GetAttachment(pEvent->options, vecShootOrigin, 
angDiscard)))
                        {
                                vecShootOrigin = 
pOperator->Weapon_ShootPosition();
                        }

                        CAI_BaseNPC *npc = pOperator->MyNPCPointer();
                        ASSERT( npc != NULL );
                        vecShootDir = npc->GetActualShootTrajectory( 
vecShootOrigin );

                        FireNPCPrimaryAttack( pOperator, vecShootOrigin, 
vecShootDir );
                }
                break;

                /*//FIXME: Re-enable
                case EVENT_WEAPON_AR2_GRENADE:
                {
                CAI_BaseNPC *npc = pOperator->MyNPCPointer();

                Vector vecShootOrigin, vecShootDir;
                vecShootOrigin = pOperator->Weapon_ShootPosition();
                vecShootDir = npc->GetShootEnemyDir( vecShootOrigin );

                Vector vecThrow = m_vecTossVelocity;

                CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", 
vecShootOrigin, vec3_angle, npc );
                pGrenade->SetAbsVelocity( vecThrow );
                pGrenade->SetLocalAngularVelocity( QAngle( 0, 400, 0 ) );
                pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY );
                pGrenade->m_hOwner                      = npc;
                pGrenade->m_pMyWeaponAR2        = this;
                pGrenade->SetDamage(sk_npc_dmg_ar2_grenade.GetFloat());

                // FIXME: arrgg ,this is hard coded into the weapon???
                m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six 
seconds before even looking again to see if a grenade can be thrown.

                m_iClip2--;
                }
                break;
                */

        default:
                BaseClass::Operator_HandleAnimEvent( pEvent, pOperator );
                break;
        }
}

//-----------------------------------------------------------------------------
// Purpose:
// Output : Activity
//-----------------------------------------------------------------------------
Activity CWeaponSMG2::GetPrimaryAttackActivity( void )
{
        if ( m_nShotsFired < 2 )
                return ACT_VM_PRIMARYATTACK;

        if ( m_nShotsFired < 3 )
                return ACT_VM_RECOIL1;

        if ( m_nShotsFired < 4 )
                return ACT_VM_RECOIL2;

        return ACT_VM_RECOIL3;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool CWeaponSMG2::Reload( void )
{
        bool fRet;
        float fCacheTime = m_flNextSecondaryAttack;

        fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD );
        if ( fRet )
        {
                // Undo whatever the reload process has done to our secondary
                // attack timer. We allow you to interrupt reloading to fire
                // a grenade.
                m_flNextSecondaryAttack = GetOwner()->m_flNextAttack = 
fCacheTime;

                WeaponSound( RELOAD );
        }

        return fRet;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponSMG2::AddViewKick( void )
{
        #define EASY_DAMPEN                     0.5f
        #define MAX_VERTICAL_KICK       1.0f    //Degrees
        #define SLIDE_LIMIT                     2.0f    //Seconds

        //Get the view kick
        CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );

        if ( pPlayer == NULL )
                return;

        DoMachineGunKick( pPlayer, EASY_DAMPEN, MAX_VERTICAL_KICK, 
m_fFireDuration, SLIDE_LIMIT );
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponSMG2::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;

        CFlareGrenade *pFlare = CFlareGrenade::Create( 
pOwner->Weapon_ShootPosition(), pOwner->EyeAngles(), pOwner, FLARE_DURATION );

        if ( pFlare == NULL )
                return;

        Vector forward;
        pOwner->EyeVectors( &forward );

        pFlare->SetAbsVelocity( forward * 1500 );

        WeaponSound( SINGLE );

        // Register a muzzleflash for the AI.
        pOwner->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );
}

#define COMBINE_MIN_GRENADE_CLEAR_DIST 256

//-----------------------------------------------------------------------------
// Purpose:
// Input  : flDot -
//                      flDist -
// Output : int
//-----------------------------------------------------------------------------
int CWeaponSMG2::WeaponRangeAttack2Condition( float flDot, float flDist )
{
        CAI_BaseNPC *npcOwner = GetOwner()->MyNPCPointer();

        return COND_NONE;

/*
        // --------------------------------------------------------
        // Assume things haven't changed too much since last time
        // --------------------------------------------------------
        if (gpGlobals->curtime < m_flNextGrenadeCheck )
                return m_lastGrenadeCondition;
*/

        // -----------------------
        // If moving, don't check.
        // -----------------------
        if ( npcOwner->IsMoving())
                return COND_NONE;

        CBaseEntity *pEnemy = npcOwner->GetEnemy();

        if (!pEnemy)
                return COND_NONE;

        Vector vecEnemyLKP = npcOwner->GetEnemyLKP();
        if ( !( pEnemy->GetFlags() & FL_ONGROUND ) && pEnemy->GetWaterLevel() 
== 0 && vecEnemyLKP.z > (GetAbsOrigin().z + WorldAlignMaxs().z) )
        {
                //!!!BUGBUG - we should make this check movetype and make sure 
it isn't FLY? Players who jump a lot are unlikely to
                // be grenaded.
                // don't throw grenades at anything that isn't on the ground!
                return COND_NONE;
        }

        // --------------------------------------
        //  Get target vector
        // --------------------------------------
        Vector vecTarget;
        if (random->RandomInt(0,1))
        {
                // magically know where they are
                vecTarget = pEnemy->WorldSpaceCenter();
        }
        else
        {
                // toss it to where you last saw them
                vecTarget = vecEnemyLKP;
        }
        // vecTarget = m_vecEnemyLKP + (pEnemy->BodyTarget( GetLocalOrigin() ) 
- pEnemy->GetLocalOrigin());
        // estimate position
        // vecTarget = vecTarget + pEnemy->m_vecVelocity * 2;


        if ( ( vecTarget - npcOwner->GetLocalOrigin() ).Length2D() <= 
COMBINE_MIN_GRENADE_CLEAR_DIST )
        {
                // crap, I don't want to blow myself up
                m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full 
second.
                return (COND_NONE);
        }

        // ---------------------------------------------------------------------
        // Are any friendlies near the intended grenade impact area?
        // ---------------------------------------------------------------------
        CBaseEntity *pTarget = NULL;

        while ( ( pTarget = gEntList.FindEntityInSphere( pTarget, vecTarget, 
COMBINE_MIN_GRENADE_CLEAR_DIST ) ) != NULL )
        {
                //Check to see if the default relationship is hatred, and if so 
intensify that
                if ( npcOwner->IRelationType( pTarget ) == D_LI )
                {
                        // crap, I might blow my own guy up. Don't throw a 
grenade and don't check again for a while.
                        m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one 
full second.
                        return (COND_WEAPON_BLOCKED_BY_FRIEND);
                }
        }

        // ---------------------------------------------------------------------
        // Check that throw is legal and clear
        // ---------------------------------------------------------------------
        // FIXME: speed is based on difficulty...

        Vector vecToss = VecCheckThrow( this, npcOwner->GetLocalOrigin() + 
Vector(0,0,60), vecTarget, 600.0, 0.5 );
        if ( vecToss != vec3_origin )
        {
                m_vecTossVelocity = vecToss;

                // don't check again for a while.
                // JAY: HL1 keeps checking - test?
                //m_flNextGrenadeCheck = gpGlobals->curtime;
                m_flNextGrenadeCheck = gpGlobals->curtime + 0.3; // 1/3 second.
                return COND_CAN_RANGE_ATTACK2;
        }
        else
        {
                // don't check again for a while.
                m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full 
second.
                return COND_WEAPON_SIGHT_OCCLUDED;
        }
}

//-----------------------------------------------------------------------------
const WeaponProficiencyInfo_t *CWeaponSMG2::GetProficiencyValues()
{
        static WeaponProficiencyInfo_t proficiencyTable[] =
        {
                { 7.0,          0.75    },
                { 5.00,         0.75    },
                { 10.0/3.0, 0.75        },
                { 5.0/3.0,      0.75    },
                { 1.00,         1.0             },
        };

        COMPILE_TIME_ASSERT( ARRAYSIZE(proficiencyTable) == 
WEAPON_PROFICIENCY_PERFECT + 1);

        return proficiencyTable;
}



















c_flaregrenade.cpp

======================================================================

#include "cbase.h"
#include "c_basecombatcharacter.h"
#include "ClientEffectPrecacheSystem.h"
#include "particles_simple.h"
#include "iefx.h"
#include "dlight.h"
#include "view.h"
#include "fx.h"
#include "clientsideeffects.h"
#include "c_pixel_visibility.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

class C_FlareGrenade : public CBaseCombatCharacter
{
public:
        DECLARE_CLASS( C_FlareGrenade, CBaseCombatCharacter );
        DECLARE_CLIENTCLASS();

        C_FlareGrenade();
        ~C_FlareGrenade();

        static C_FlareGrenade * GetActiveFlares( void );
        C_FlareGrenade *                GetNextFlare( void ) const { return 
m_pNextFlare; }

        static C_FlareGrenade *Create( Vector vecOrigin, QAngle vecAngles, 
CBaseEntity *pOwner, float lifetime );

        virtual unsigned int PhysicsSolidMaskForEntity( void ) const;

        void    Spawn( void );
        void    Precache( void );
        int             Restore( IRestore &restore );
        void    Activate( void );

        void    StartBurnSound( void );

        void    Start( float lifeTime );
        void    Die( float fadeTime );
        void    Launch( const Vector &direction, float speed );

        //Class_T Classify( void );

        void    FlareTouch( CBaseEntity *pOther );
        void    FlareBurnTouch( CBaseEntity *pOther );
        void    FlareThink( void );

        void    InputStart( inputdata_t &inputdata );
        void    InputDie( inputdata_t &inputdata );
        void    InputLaunch( inputdata_t &inputdata );

        //DECLARE_DATADESC();

        static C_FlareGrenade *activeFlares;

        CBaseEntity *m_pOwner;
        int                     m_nBounces;                     // how many 
times has this flare bounced?
        CNetworkVar( float, m_flTimeBurnOut );  // when will the flare burn out?
        CNetworkVar( float, m_flScale );
        float           m_flDuration;
        float           m_flNextDamage;

        CSoundPatch     *m_pBurnSound;
        bool            m_bFading;
        CNetworkVar( bool, m_bLight );
        CNetworkVar( bool, m_bSmoke );
        CNetworkVar( bool, m_bPropFlare );

        bool            m_bInActiveList;
        C_FlareGrenade *        m_pNextFlare;

        void            RemoveFromActiveFlares( void );
        void            AddToActiveFlares( void );
};

LINK_ENTITY_TO_CLASS( flare_grenade, C_FlareGrenade )

IMPLEMENT_CLIENTCLASS_DT( C_FlareGrenade, DT_FlareGrenade, CFlareGrenade )
        RecvPropInt( RECVINFO( m_nBounces ) ),
        RecvPropFloat( RECVINFO( m_flScale ) ),
        RecvPropFloat( RECVINFO( m_flDuration ) ),
        RecvPropFloat( RECVINFO( m_flTimeBurnOut ) ),
        RecvPropFloat( RECVINFO( m_flNextDamage ) ),
        RecvPropInt( RECVINFO( m_bFading ) ), // closest to bool I could find
        RecvPropInt( RECVINFO( m_bLight ) ),
        RecvPropInt( RECVINFO( m_bSmoke ) ),
        RecvPropInt( RECVINFO( m_bPropFlare ) ),
        RecvPropInt( RECVINFO( m_bInActiveList ) ),
        //DEFINE_FIELD( m_pOwner,                       FIELD_CLASSPTR ),
        //DEFINE_FIELD( m_pNextFlare,           FIELD_CLASSPTR ),

END_RECV_TABLE()

C_FlareGrenade::C_FlareGrenade( 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;
}


C_FlareGrenade::~C_FlareGrenade()
{
        m_pBurnSound = NULL;

        RemoveFromActiveFlares();
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_FlareGrenade::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 C_FlareGrenade::Restore( IRestore &restore )
{
        int result = BaseClass::Restore( restore );

        return result;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_FlareGrenade::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 C_FlareGrenade::Activate( void )
{
        BaseClass::Activate();

}

unsigned int C_FlareGrenade::PhysicsSolidMaskForEntity( void ) const
{
        return MASK_NPCSOLID;
}

//-----------------------------------------------------------------------------
// Purpose: Removes flare from active flare list
//-----------------------------------------------------------------------------
void C_FlareGrenade::RemoveFromActiveFlares( void )
{
        //C_FlareGrenade *pFlare;
        //C_FlareGrenade *pPrevFlare;

        //if ( !m_bInActiveList )
        //      return;

        //pPrevFlare = NULL;
        //for( pFlare = C_FlareGrenade::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;
}
--
[ winmail.dat of type application/ms-tnef deleted ]
--

_______________________________________________
To unsubscribe, edit your list preferences, or view the list archives, please 
visit:
http://list.valvesoftware.com/mailman/listinfo/hlcoders

Reply via email to