Files
HL2Overcharged/game/server/overcharged/weapon_dualpistol.cpp
2025-05-21 21:20:08 +03:00

653 lines
20 KiB
C++

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Dual pistols FTW
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "NPCEvent.h"
#include "basehlcombatweapon.h"
#include "basecombatcharacter.h"
#include "AI_BaseNPC.h"
#include "player.h"
#include "gamerules.h"
#include "in_buttons.h"
#include "soundent.h"
#include "game.h"
#include "vstdlib/random.h"
#include "gamestats.h"
#include "particle_parse.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define Dualpistol_FASTEST_REFIRE_TIME 0.1f
#define Dualpistol_FASTEST_DRY_REFIRE_TIME 0.2f
#define Dualpistol_ACCURACY_SHOT_PENALTY_TIME 0.5f // Applied amount of time each shot adds to the time we must recover from
#define Dualpistol_ACCURACY_MAXIMUM_PENALTY_TIME 3.0f // Maximum penalty to deal out
// Light Kill : Define old and new attachments
#define DP_old_attachment1 "1"
#define DP_old_attachment2 "2"
#define DP_new_attachment1 "muzzle"
#define DP_new_attachment2 "muzzle2"
//ConVar aa_wpn_dualpistol_use_new_accuracy( "aa_wpn_dualpistol_use_new_accuracy", "1" );
ConVar aa_wpn_dualpistol_use_new_attachments( "aa_wpn_dualpistol_use_new_attachments", "0", FCVAR_REPLICATED|FCVAR_ARCHIVE, "Old attachements = (1,2) css model, New one -(muzzle,muzzle2)." );
//-----------------------------------------------------------------------------
// CWeaponDualpistol
//-----------------------------------------------------------------------------
class CWeaponDualpistol : public CBaseHLCombatWeapon
{
DECLARE_DATADESC();
public:
DECLARE_CLASS( CWeaponDualpistol, CBaseHLCombatWeapon );
CWeaponDualpistol(void);
DECLARE_SERVERCLASS();
void Precache( void );
void ItemPostFrame( void );
void ItemPreFrame( void );
void ItemBusyFrame( void );
void PrimaryAttack( void );
void Basefire( void );
void AddViewKick( void );
void DryFire( void );
void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator );
//int ChangeAttachment( void );
//int GetTracerAttachment( void );
void UpdatePenaltyTime( void );
bool Deploy( void );
int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; }
//Activity GetPrimaryAttackActivity( void );
//Activity GetSecondaryAttackActivity( void );
virtual bool Reload( void );
virtual int GetMinBurst()
{
return 1;
}
virtual int GetMaxBurst()
{
return 3;
}
/*virtual float GetFireRate( void )
{
return 0.5f;
}*/
//bool ShouldUseAttachment2ForMuzzleFlashes( void ) { return bFlip; } // alternate between using attachment 1 and attachment 2 for muzzleflashes
DECLARE_ACTTABLE();
private:
float m_flSoonestPrimaryAttack;
float m_flLastAttackTime;
float m_flAccuracyPenalty;
int m_nNumShotsFired;
bool bFlip;
};
IMPLEMENT_SERVERCLASS_ST(CWeaponDualpistol, DT_WeaponDualpistol)
END_SEND_TABLE()
LINK_ENTITY_TO_CLASS( weapon_dualpistol, CWeaponDualpistol );
PRECACHE_WEAPON_REGISTER( weapon_dualpistol );
BEGIN_DATADESC( CWeaponDualpistol )
DEFINE_FIELD( m_flSoonestPrimaryAttack, FIELD_TIME ),
DEFINE_FIELD( m_flLastAttackTime, FIELD_TIME ),
DEFINE_FIELD( m_flAccuracyPenalty, FIELD_FLOAT ), //NOTENOTE: This is NOT tracking game time
DEFINE_FIELD( m_nNumShotsFired, FIELD_INTEGER ),
END_DATADESC()
acttable_t CWeaponDualpistol::m_acttable[] =
{
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PISTOL, false }, // L1ght 15 : MP animstate
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_PISTOL, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PISTOL, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PISTOL, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, false }, //fix
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PISTOL, false },
//{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, false }, // END
{ ACT_IDLE, ACT_IDLE_PISTOL, true },
{ ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_PISTOL, true },
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, true },
{ ACT_RELOAD, ACT_RELOAD_PISTOL, true },
{ ACT_WALK_AIM, ACT_WALK_AIM_PISTOL, true },
{ ACT_RUN_AIM, ACT_RUN_AIM_PISTOL, true },
{ ACT_COVER_LOW, ACT_COVER_PISTOL_LOW, true },
{ ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_PISTOL_LOW, true },
{ ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_PISTOL,true },
{ ACT_RELOAD_LOW, ACT_RELOAD_PISTOL_LOW, true },
{ ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_PISTOL_LOW, true },
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_PISTOL, true },
// Readiness activities (not aiming)
{ ACT_IDLE_RELAXED, ACT_IDLE/*_PISTOL*/, false },//never aims
{ ACT_IDLE_STIMULATED, ACT_IDLE_STIMULATED, false },
{ ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_PISTOL, false },//always aims
{ ACT_IDLE_STEALTH, ACT_IDLE_STEALTH_PISTOL, false },
{ ACT_WALK_RELAXED, ACT_WALK, false },//never aims
{ ACT_WALK_STIMULATED, ACT_WALK_STIMULATED, false },
{ ACT_WALK_AGITATED, ACT_WALK_AIM_PISTOL, false },//always aims
{ ACT_WALK_STEALTH, ACT_WALK_STEALTH_PISTOL, false },
{ ACT_RUN_RELAXED, ACT_RUN, false },//never aims
{ ACT_RUN_STIMULATED, ACT_RUN_STIMULATED, false },
{ ACT_RUN_AGITATED, ACT_RUN_AIM_PISTOL, false },//always aims
{ ACT_RUN_STEALTH, ACT_RUN_STEALTH_PISTOL, false },
// Readiness activities (aiming)
{ ACT_IDLE_AIM_RELAXED, ACT_IDLE_PISTOL, false },//never aims
{ ACT_IDLE_AIM_STIMULATED, ACT_IDLE_ANGRY_PISTOL, false },
{ ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_PISTOL, false },//always aims
{ ACT_IDLE_AIM_STEALTH, ACT_IDLE_STEALTH_PISTOL, false },
{ ACT_WALK_AIM_RELAXED, ACT_WALK, false },//never aims
{ ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_PISTOL, false },
{ ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_PISTOL, false },//always aims
{ ACT_WALK_AIM_STEALTH, ACT_WALK_AIM_STEALTH_PISTOL, false },//always aims
{ ACT_RUN_AIM_RELAXED, ACT_RUN, false },//never aims
{ ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_PISTOL, false },
{ ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_PISTOL, false },//always aims
{ ACT_RUN_AIM_STEALTH, ACT_RUN_AIM_STEALTH_PISTOL, false },//always aims
//End readiness activities
// Crouch activities
{ ACT_CROUCHIDLE_STIMULATED, ACT_CROUCHIDLE_STIMULATED, false },
{ ACT_CROUCHIDLE_AIM_STIMULATED,ACT_RANGE_AIM_PISTOL_LOW, false },//always aims
{ ACT_CROUCHIDLE_AGITATED, ACT_RANGE_AIM_PISTOL_LOW, false },//always aims
// Readiness translations
{ ACT_READINESS_RELAXED_TO_STIMULATED, ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED, false },
{ ACT_READINESS_RELAXED_TO_STIMULATED_WALK, ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK, false },
{ ACT_READINESS_AGITATED_TO_STIMULATED, ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED, false },
{ ACT_READINESS_STIMULATED_TO_RELAXED, ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED, false },
};
IMPLEMENT_ACTTABLE( CWeaponDualpistol );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CWeaponDualpistol::CWeaponDualpistol( void )
{
m_flSoonestPrimaryAttack = gpGlobals->curtime;
m_flAccuracyPenalty = 0.0f;
m_fMinRange1 = 24;
m_fMaxRange1 = 1500;
m_fMinRange2 = 24;
m_fMaxRange2 = 200;
m_bFiresUnderwater = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponDualpistol::Precache( void )
{
PrecacheParticleSystem( "weapon_muzzle_smoke" );
BaseClass::Precache();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CWeaponDualpistol::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator )
{
switch( pEvent->event )
{
case EVENT_WEAPON_PISTOL_FIRE:
{
Vector vecShootOrigin, vecShootDir;
vecShootOrigin = pOperator->Weapon_ShootPosition();
CAI_BaseNPC *npc = pOperator->MyNPCPointer();
ASSERT( npc != NULL );
vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin );
CSoundEnt::InsertSound( SOUND_COMBAT|SOUND_CONTEXT_GUNFIRE, pOperator->GetAbsOrigin(), SOUNDENT_VOLUME_PISTOL, 0.2, pOperator, SOUNDENT_CHANNEL_WEAPON, pOperator->GetEnemy() );
WeaponSound( SINGLE_NPC );
pOperator->FireBullets(1, vecShootOrigin, vecShootDir, pOperator->GetAttackSpread(this), MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2);
pOperator->DoMuzzleFlash();
m_iClip1 = m_iClip1 - 1;
}
break;
default:
BaseClass::Operator_HandleAnimEvent( pEvent, pOperator );
break;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponDualpistol::DryFire( void )
{
WeaponSound( EMPTY );
SendWeaponAnim( ACT_VM_DRYFIRE );
m_flSoonestPrimaryAttack = gpGlobals->curtime + Dualpistol_FASTEST_DRY_REFIRE_TIME;
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponDualpistol::PrimaryAttack( void )
{
if ( ( gpGlobals->curtime - m_flLastAttackTime ) > 0.5f )
{
m_nNumShotsFired = 0;
}
else
{
m_nNumShotsFired++;
}
m_flLastAttackTime = gpGlobals->curtime;
m_flSoonestPrimaryAttack = gpGlobals->curtime + Dualpistol_FASTEST_REFIRE_TIME;
CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), SOUNDENT_VOLUME_PISTOL, 0.2, GetOwner() );
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if( pOwner )
{
// Each time the player fires the pistol, reset the view punch. This prevents
// the aim from 'drifting off' when the player fires very quickly. This may
// not be the ideal way to achieve this, but it's cheap and it works, which is
// great for a feature we're evaluating. (sjb)
pOwner->ViewPunchReset();
}
/*if(m_nNumShotsFired >= 7|9|11)
{
if (cvar->FindVar("Dualpistol_use_new_attachments")->GetInt() == 1)
{
DispatchParticleEffect( "weapon_muzzle_smoke", PATTACH_POINT_FOLLOW, pOwner->GetViewModel(), "muzzle2", true);
}
else
{
DispatchParticleEffect( "weapon_muzzle_smoke", PATTACH_POINT_FOLLOW, pOwner->GetViewModel(), "2", true);
}
}
if(m_nNumShotsFired >= 8,10,12)
{
if (cvar->FindVar("Dualpistol_use_new_attachments")->GetInt() == 1)
{
DispatchParticleEffect( "weapon_muzzle_smoke", PATTACH_POINT_FOLLOW, pOwner->GetViewModel(), "muzzle", true);
}
else
{
DispatchParticleEffect( "weapon_muzzle_smoke", PATTACH_POINT_FOLLOW, pOwner->GetViewModel(), "1", true);
}
}*/
Basefire();
// Add an accuracy penalty which can move past our maximum penalty time if we're really spastic
m_flAccuracyPenalty += Dualpistol_ACCURACY_SHOT_PENALTY_TIME;
m_iPrimaryAttacks++;
gamestats->Event_WeaponFired( pOwner, true, GetClassname() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponDualpistol::UpdatePenaltyTime( void )
{
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( pOwner == NULL )
return;
// Check our penalty time decay
if ( ( ( pOwner->m_nButtons & IN_ATTACK ) == false ) && ( m_flSoonestPrimaryAttack < gpGlobals->curtime ) )
{
m_flAccuracyPenalty -= gpGlobals->frametime;
m_flAccuracyPenalty = clamp( m_flAccuracyPenalty, 0.0f, Dualpistol_ACCURACY_MAXIMUM_PENALTY_TIME );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponDualpistol::ItemPreFrame( void )
{
UpdatePenaltyTime();
BaseClass::ItemPreFrame();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponDualpistol::ItemBusyFrame( void )
{
SecondaryAttack();
UpdatePenaltyTime();
BaseClass::ItemBusyFrame();
}
//-----------------------------------------------------------------------------
// Purpose: Allows firing as fast as button is pressed
//-----------------------------------------------------------------------------
void CWeaponDualpistol::ItemPostFrame( void )
{
BaseClass::ItemPostFrame();
if ( m_bInReload )
return;
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( pOwner == NULL )
return;
//Allow a refire as fast as the player can click
if ( ( ( pOwner->m_nButtons & IN_ATTACK ) == false ) && ( m_flSoonestPrimaryAttack < gpGlobals->curtime ) )
{
m_flNextPrimaryAttack = gpGlobals->curtime - 0.1f;
}
else if ( ( pOwner->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack < gpGlobals->curtime ) && ( m_iClip1 <= 0 ) )
{
DryFire();
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
/*Activity CWeaponDualpistol::GetPrimaryAttackActivity( void )
{
if ( m_nNumShotsFired < 1 )
return ACT_VM_PRIMARYATTACK;
if ( m_nNumShotsFired < 2 )
return ACT_VM_RECOIL1;
if ( m_nNumShotsFired < 3 )
return ACT_VM_RECOIL2;
//return ACT_VM_RECOIL3;
return ACT_VM_PRIMARYATTACK;
}*/
/*Activity CWeaponDualpistol::GetSecondaryAttackActivity( void )
{
return ACT_VM_SECONDARYATTACK;;
}*/
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool CWeaponDualpistol::Reload( void )
{
bool fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD );
if ( fRet )
{
WeaponSound( RELOAD );
m_flAccuracyPenalty = 0.0f;
}
return fRet;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponDualpistol::AddViewKick( void )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( pPlayer == NULL )
return;
QAngle viewPunch;
viewPunch.x = random->RandomFloat( 0.25f, 0.5f );
viewPunch.y = random->RandomFloat( -.6f, .6f );
viewPunch.z = 0.0f;
//Add it to the view punch
pPlayer->ViewPunch( viewPunch );
}
//-----------------------------------------------------------------------------
// Purpose: Dual Pistols Firing
//-----------------------------------------------------------------------------
/*void CWeaponDualpistol::LeftGunAttack()
{
// If my clip is empty (and I use clips) start reload
if ( UsesClipsForAmmo1() && !m_iClip1 )
{
Reload();
return;
}
// Only the player fires this way so we can cast
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if (!pPlayer)
{
return;
}
// MUST call sound before removing a round from the clip of a CMachineGun
WeaponSound(SINGLE);
pPlayer->DoMuzzleFlash();
SendWeaponAnim( GetSecondaryAttackActivity() );
// player "shoot" animation
pPlayer->SetAnimation( PLAYER_ATTACK1 );
FireBulletsInfo_t info;
info.m_vecSrc = pPlayer->Weapon_ShootPosition( );
info.m_vecDirShooting = pPlayer->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT );
// To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems,
// especially if the weapon we're firing has a really fast rate of fire.
info.m_iShots = 0;
float fireRate = GetFireRate();
while ( m_flNextPrimaryAttack <= gpGlobals->curtime )
{
m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate;
info.m_iShots++;
if ( !fireRate )
break;
}
// Make sure we don't fire more than the amount in the clip
if ( UsesClipsForAmmo1() )
{
info.m_iShots = min( info.m_iShots, m_iClip1 );
m_iClip1 -= info.m_iShots;
}
else
{
info.m_iShots = min( info.m_iShots, pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) );
pPlayer->RemoveAmmo( info.m_iShots, m_iPrimaryAmmoType );
}
info.m_flDistance = MAX_TRACE_LENGTH;
info.m_iAmmoType = m_iPrimaryAmmoType;
info.m_iTracerFreq = 2;
#if !defined( CLIENT_DLL )
// Fire the bullets
info.m_vecSpread = pPlayer->GetAttackSpread( this );
#else
//!!!HACKHACK - what does the client want this function for?
info.m_vecSpread = GetActiveWeapon()->GetBulletSpread();
#endif // CLIENT_DLL
pPlayer->FireBullets( info );
if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0)
{
// HEV suit - indicate out of ammo condition
pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
}
//Add our view kick in
AddViewKick();
}*/
/*int CWeaponDualpistol::GetTracerAttachment( void )
{
int iAttachment = TRACER_DONT_USE_ATTACHMENT;
if ( bFlip )
iAttachment = 2;
else
iAttachment = 1;
return iAttachment;
}*/
void CWeaponDualpistol::Basefire( void )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if (!pPlayer)
return;
// Abort here to handle burst and auto fire modes
if ( (UsesClipsForAmmo1() && m_iClip1 == 0) || ( !UsesClipsForAmmo1() && !pPlayer->GetAmmoCount(m_iPrimaryAmmoType) ) )
return;
// MUST call sound before removing a round from the clip of a CMachineGun
WeaponSound(SINGLE);
pPlayer->DoMuzzleFlash();
int iBulletsToFire = 0;
float fireRate = GetFireRate();
while ( m_flNextPrimaryAttack <= gpGlobals->curtime )
{
// MUST call sound before removing a round from the clip of a CHLMachineGun
WeaponSound(SINGLE, m_flNextPrimaryAttack);
m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate;
iBulletsToFire++;
}
// Make sure we don't fire more than the amount in the clip, if this weapon uses clips
if ( UsesClipsForAmmo1() )
{
if ( iBulletsToFire > m_iClip1 )
iBulletsToFire = m_iClip1;
m_iClip1 -= iBulletsToFire;
}
// Fire the bullets
FireBulletsInfo_t info;
info.m_iShots = iBulletsToFire;
info.m_vecSrc = pPlayer->Weapon_ShootPosition( );
info.m_vecDirShooting = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
info.m_vecSpread = pPlayer->GetAttackSpread( this );
info.m_flDistance = MAX_TRACE_LENGTH;
info.m_iAmmoType = m_iPrimaryAmmoType;
info.m_iTracerFreq = 2;
FireBullets( info );
//Factor in the view kick
AddViewKick();
if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0)
{
// HEV suit - indicate out of ammo condition
pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
}
pPlayer->SetAnimation( PLAYER_ATTACK1 );
//GetTracerAttachment();
//int DP_DoSmokeEffect = random->RandomInt( 1, 70 );
//int DP_DoSmokeEffect2 = random->RandomInt( 1, 70 );
if ( bFlip )
{
SendWeaponAnim( GetSecondaryAttackActivity() );
bFlip = false;
if (cvar->FindVar("aa_wpn_dualpistol_use_new_attachments")->GetInt() == 1)
{
DispatchParticleEffect( "weapon_muzzle_smoke", PATTACH_POINT_FOLLOW, pPlayer->GetViewModel(), DP_new_attachment1, true);
}
else
{
DispatchParticleEffect( "weapon_muzzle_smoke", PATTACH_POINT_FOLLOW, pPlayer->GetViewModel(), DP_old_attachment1, true);
}
}
else
{
SendWeaponAnim( GetPrimaryAttackActivity() );
bFlip = true;
if (cvar->FindVar("aa_wpn_dualpistol_use_new_attachments")->GetInt() == 1)
{
DispatchParticleEffect( "weapon_muzzle_smoke", PATTACH_POINT_FOLLOW, pPlayer->GetViewModel(), DP_new_attachment2, true);
}
else
{
DispatchParticleEffect( "weapon_muzzle_smoke", PATTACH_POINT_FOLLOW, pPlayer->GetViewModel(), DP_old_attachment2, true);
}
}
//PrepareHitmarker();
}
bool CWeaponDualpistol::Deploy( void )
{
if (BaseClass::Deploy())
{
SendWeaponAnim( ACT_VM_DRAW );
bFlip = false;
m_flNextPrimaryAttack = gpGlobals->curtime + GetViewModelSequenceDuration();
return true;
}
return false;
}