mirror of
https://github.com/Gigaslav/HL2Overcharged.git
synced 2026-09-04 11:44:45 +03:00
653 lines
20 KiB
C++
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;
|
|
}
|