You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
350 lines
9.2 KiB
350 lines
9.2 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Grigori's personal shotgun (npc_monk) |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "npcevent.h" |
|
#include "basehlcombatweapon_shared.h" |
|
#include "basecombatcharacter.h" |
|
#include "ai_basenpc.h" |
|
#include "player.h" |
|
#include "gamerules.h" // For g_pGameRules |
|
#include "in_buttons.h" |
|
#include "soundent.h" |
|
#include "vstdlib/random.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
extern ConVar sk_auto_reload_time; |
|
|
|
class CWeaponAnnabelle : public CBaseHLCombatWeapon |
|
{ |
|
DECLARE_DATADESC(); |
|
public: |
|
DECLARE_CLASS( CWeaponAnnabelle, CBaseHLCombatWeapon ); |
|
|
|
DECLARE_SERVERCLASS(); |
|
|
|
private: |
|
bool m_bNeedPump; // When emptied completely |
|
bool m_bDelayedFire1; // Fire primary when finished reloading |
|
bool m_bDelayedFire2; // Fire secondary when finished reloading |
|
|
|
public: |
|
void Precache( void ); |
|
|
|
int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } |
|
|
|
virtual const Vector& GetBulletSpread( void ) |
|
{ |
|
static Vector cone = vec3_origin; |
|
return cone; |
|
} |
|
|
|
virtual int GetMinBurst() { return 1; } |
|
virtual int GetMaxBurst() { return 3; } |
|
|
|
void ItemHolsterFrame( void ); |
|
bool StartReload( void ); |
|
bool Reload( void ); |
|
void FillClip( void ); |
|
void FinishReload( void ); |
|
void CheckHolsterReload( void ); |
|
void Pump( void ); |
|
void DryFire( void ); |
|
virtual float GetFireRate( void ) { return 1.5; }; |
|
virtual float GetMinRestTime() { return 1.0; } |
|
virtual float GetMaxRestTime() { return 1.5; } |
|
|
|
void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); |
|
|
|
DECLARE_ACTTABLE(); |
|
|
|
CWeaponAnnabelle(void); |
|
}; |
|
|
|
IMPLEMENT_SERVERCLASS_ST(CWeaponAnnabelle, DT_WeaponAnnabelle) |
|
END_SEND_TABLE() |
|
|
|
LINK_ENTITY_TO_CLASS( weapon_annabelle, CWeaponAnnabelle ); |
|
#ifndef HL2MP |
|
PRECACHE_WEAPON_REGISTER(weapon_annabelle); |
|
#endif |
|
|
|
BEGIN_DATADESC( CWeaponAnnabelle ) |
|
DEFINE_FIELD( m_bNeedPump, FIELD_BOOLEAN ), |
|
DEFINE_FIELD( m_bDelayedFire1, FIELD_BOOLEAN ), |
|
DEFINE_FIELD( m_bDelayedFire2, FIELD_BOOLEAN ), |
|
END_DATADESC() |
|
|
|
acttable_t CWeaponAnnabelle::m_acttable[] = |
|
{ |
|
{ ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SMG1, true }, |
|
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, true }, |
|
{ ACT_RELOAD, ACT_RELOAD_SMG1, true }, |
|
{ ACT_WALK, ACT_WALK_RIFLE, true }, |
|
{ ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true }, |
|
{ ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, false }, |
|
{ ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, false }, |
|
{ ACT_RUN, ACT_RUN_RIFLE, true }, |
|
{ ACT_RUN_AIM, ACT_RUN_AIM_RIFLE, true }, |
|
{ ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, false }, |
|
{ ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, false }, |
|
{ ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_SHOTGUN, true }, |
|
{ ACT_RELOAD_LOW, ACT_RELOAD_SMG1_LOW, false }, |
|
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, false }, |
|
}; |
|
|
|
IMPLEMENT_ACTTABLE(CWeaponAnnabelle); |
|
|
|
void CWeaponAnnabelle::Precache( void ) |
|
{ |
|
CBaseCombatWeapon::Precache(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
void CWeaponAnnabelle::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) |
|
{ |
|
switch( pEvent->event ) |
|
{ |
|
case EVENT_WEAPON_SHOTGUN_FIRE: |
|
{ |
|
Vector vecShootOrigin, vecShootDir; |
|
vecShootOrigin = pOperator->Weapon_ShootPosition(); |
|
CAI_BaseNPC *npc = pOperator->MyNPCPointer(); |
|
ASSERT( npc != NULL ); |
|
WeaponSound( SINGLE_NPC ); |
|
pOperator->DoMuzzleFlash(); |
|
m_iClip1 = m_iClip1 - 1; |
|
|
|
vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); |
|
pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 ); |
|
} |
|
break; |
|
|
|
default: |
|
CBaseCombatWeapon::Operator_HandleAnimEvent( pEvent, pOperator ); |
|
break; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Override so only reload one shell at a time |
|
// Input : |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
bool CWeaponAnnabelle::StartReload( void ) |
|
{ |
|
CBaseCombatCharacter *pOwner = GetOwner(); |
|
|
|
if ( pOwner == NULL ) |
|
return false; |
|
|
|
if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0) |
|
return false; |
|
|
|
if (m_iClip1 >= GetMaxClip1()) |
|
return false; |
|
|
|
// If shotgun totally emptied then a pump animation is needed |
|
if (m_iClip1 <= 0) |
|
{ |
|
m_bNeedPump = true; |
|
} |
|
|
|
int j = MIN(1, pOwner->GetAmmoCount(m_iPrimaryAmmoType)); |
|
|
|
if (j <= 0) |
|
return false; |
|
|
|
SendWeaponAnim( ACT_SHOTGUN_RELOAD_START ); |
|
|
|
// Make shotgun shell visible |
|
SetBodygroup(1,0); |
|
|
|
pOwner->m_flNextAttack = gpGlobals->curtime; |
|
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); |
|
|
|
m_bInReload = true; |
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Override so only reload one shell at a time |
|
// Input : |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
bool CWeaponAnnabelle::Reload( void ) |
|
{ |
|
// Check that StartReload was called first |
|
if (!m_bInReload) |
|
{ |
|
Warning("ERROR: Shotgun Reload called incorrectly!\n"); |
|
} |
|
|
|
CBaseCombatCharacter *pOwner = GetOwner(); |
|
|
|
if ( pOwner == NULL ) |
|
return false; |
|
|
|
if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0) |
|
return false; |
|
|
|
if (m_iClip1 >= GetMaxClip1()) |
|
return false; |
|
|
|
int j = MIN(1, pOwner->GetAmmoCount(m_iPrimaryAmmoType)); |
|
|
|
if (j <= 0) |
|
return false; |
|
|
|
FillClip(); |
|
// Play reload on different channel as otherwise steals channel away from fire sound |
|
WeaponSound(RELOAD); |
|
SendWeaponAnim( ACT_VM_RELOAD ); |
|
|
|
pOwner->m_flNextAttack = gpGlobals->curtime; |
|
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Play finish reload anim and fill clip |
|
// Input : |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
void CWeaponAnnabelle::FinishReload( void ) |
|
{ |
|
// Make shotgun shell invisible |
|
SetBodygroup(1,1); |
|
|
|
CBaseCombatCharacter *pOwner = GetOwner(); |
|
|
|
if ( pOwner == NULL ) |
|
return; |
|
|
|
m_bInReload = false; |
|
|
|
// Finish reload animation |
|
SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH ); |
|
|
|
pOwner->m_flNextAttack = gpGlobals->curtime; |
|
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Play finish reload anim and fill clip |
|
// Input : |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
void CWeaponAnnabelle::FillClip( void ) |
|
{ |
|
CBaseCombatCharacter *pOwner = GetOwner(); |
|
|
|
if ( pOwner == NULL ) |
|
return; |
|
|
|
// Add them to the clip |
|
if ( pOwner->GetAmmoCount( m_iPrimaryAmmoType ) > 0 ) |
|
{ |
|
if ( Clip1() < GetMaxClip1() ) |
|
{ |
|
m_iClip1++; |
|
pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Play weapon pump anim |
|
// Input : |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
void CWeaponAnnabelle::Pump( void ) |
|
{ |
|
CBaseCombatCharacter *pOwner = GetOwner(); |
|
|
|
if ( pOwner == NULL ) |
|
return; |
|
|
|
m_bNeedPump = false; |
|
|
|
WeaponSound( SPECIAL1 ); |
|
|
|
// Finish reload animation |
|
SendWeaponAnim( ACT_SHOTGUN_PUMP ); |
|
|
|
pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration(); |
|
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// |
|
// |
|
//----------------------------------------------------------------------------- |
|
void CWeaponAnnabelle::DryFire( void ) |
|
{ |
|
WeaponSound(EMPTY); |
|
SendWeaponAnim( ACT_VM_DRYFIRE ); |
|
|
|
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CWeaponAnnabelle::ItemHolsterFrame( void ) |
|
{ |
|
// Must be player held |
|
if ( GetOwner() && GetOwner()->IsPlayer() == false ) |
|
return; |
|
|
|
// We can't be active |
|
if ( GetOwner()->GetActiveWeapon() == this ) |
|
return; |
|
|
|
// If it's been longer than three seconds, reload |
|
if ( ( gpGlobals->curtime - m_flHolsterTime ) > sk_auto_reload_time.GetFloat() ) |
|
{ |
|
// Reset the timer |
|
m_flHolsterTime = gpGlobals->curtime; |
|
|
|
if ( GetOwner() == NULL ) |
|
return; |
|
|
|
if ( m_iClip1 == GetMaxClip1() ) |
|
return; |
|
|
|
// Just load the clip with no animations |
|
int ammoFill = MIN( (GetMaxClip1() - m_iClip1), GetOwner()->GetAmmoCount( GetPrimaryAmmoType() ) ); |
|
|
|
GetOwner()->RemoveAmmo( ammoFill, GetPrimaryAmmoType() ); |
|
m_iClip1 += ammoFill; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
CWeaponAnnabelle::CWeaponAnnabelle( void ) |
|
{ |
|
m_bReloadsSingly = true; |
|
|
|
m_bNeedPump = false; |
|
m_bDelayedFire1 = false; |
|
m_bDelayedFire2 = false; |
|
|
|
m_fMinRange1 = 0.0; |
|
m_fMaxRange1 = 500; |
|
m_fMinRange2 = 0.0; |
|
m_fMaxRange2 = 200; |
|
}
|
|
|