mirror of
https://github.com/Gigaslav/HL2Overcharged.git
synced 2026-01-05 06:10:21 +03:00
409 lines
10 KiB
C++
409 lines
10 KiB
C++
//========= Copyright Š 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose: Grigori's personal shotgun (npc_monk)
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "npcevent.h"
|
|
#include "weapon_annabelle.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"
|
|
#include "gamestats.h"
|
|
#include "IEffects.h"
|
|
#include "te_effect_dispatch.h"
|
|
#include "particle_parse.h"
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
extern ConVar sk_auto_reload_time;
|
|
|
|
|
|
IMPLEMENT_SERVERCLASS_ST(CWeaponAnnabelle, DT_WeaponAnnabelle)
|
|
END_SEND_TABLE()
|
|
|
|
LINK_ENTITY_TO_CLASS(weapon_annabelle, CWeaponAnnabelle);
|
|
PRECACHE_WEAPON_REGISTER(weapon_annabelle);
|
|
|
|
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 },
|
|
|
|
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PHYSGUN, false },
|
|
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_PHYSGUN, false },
|
|
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PHYSGUN, false },
|
|
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PHYSGUN, false },
|
|
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PHYSGUN, false },
|
|
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PHYSGUN, false },
|
|
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PHYSGUN, false },
|
|
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, false },
|
|
};
|
|
|
|
IMPLEMENT_ACTTABLE(CWeaponAnnabelle);
|
|
|
|
|
|
|
|
void CWeaponAnnabelle::Precache(void)
|
|
{
|
|
CBaseCombatWeapon::Precache();
|
|
PrecacheScriptSound("Weapon_Annabelle.Draw");
|
|
}
|
|
|
|
|
|
/*void CWeaponAnnabelle::ItemPostFrame(void)
|
|
{
|
|
BaseClass::ItemPostFrame();
|
|
|
|
CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
|
|
|
|
if (pPlayer == NULL)
|
|
return;
|
|
}*/
|
|
void CWeaponAnnabelle::PrimaryAttack(void)
|
|
{
|
|
// Only the player fires this way so we can cast
|
|
CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
|
|
|
|
if (!pPlayer)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (IsNearWall() || GetOwnerIsRunning())
|
|
{
|
|
return;
|
|
}
|
|
|
|
/*CBasePlayer *pOwner = ToBasePlayer(GetOwner());
|
|
if (pOwner)
|
|
{
|
|
//if ((m_nShotsFired == 2) || (m_nShotsFired == 4) || (m_nShotsFired == 6) || (m_nShotsFired == 8))
|
|
{
|
|
DispatchParticleEffect("weapon_muzzle_smoke2", PATTACH_POINT_FOLLOW, pOwner->GetViewModel(), "muzzle", false);
|
|
}
|
|
}*/
|
|
|
|
BaseClass::PrimaryAttack();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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, pOperator->GetAttackSpread(this), 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)
|
|
{
|
|
|
|
CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
|
|
if (!pPlayer)
|
|
return false;
|
|
|
|
m_bInReload = true;
|
|
|
|
CBaseCombatCharacter *pOwner = GetOwner();
|
|
|
|
if (pOwner == NULL)
|
|
return false;
|
|
|
|
if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (m_iClip1 >= GetMaxClip1())
|
|
{
|
|
return false;
|
|
}*/
|
|
|
|
/*if (m_iClip1 == 0)
|
|
{
|
|
if ((gpGlobals->curtime) > sk_auto_reload_time.GetFloat())
|
|
{
|
|
CEffectData data;
|
|
// Emit six spent shells
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
data.m_vOrigin = pOwner->WorldSpaceCenter() + RandomVector(-4, 4);
|
|
data.m_vAngles = QAngle(90, random->RandomInt(0, 360), 0);
|
|
data.m_nEntIndex = entindex();
|
|
|
|
DispatchEffect("ShellEject", data);
|
|
}
|
|
}
|
|
SendWeaponAnim(ACT_VM_RELOAD_EMPTY);
|
|
}
|
|
if (m_iClip1 > 0)*/
|
|
//{
|
|
/*if ((gpGlobals->curtime) > sk_auto_reload_time.GetFloat())
|
|
{
|
|
CEffectData data;
|
|
// Emit six spent shells
|
|
for (int i = 0; i < 1; i++)
|
|
{
|
|
data.m_vOrigin = pOwner->WorldSpaceCenter() + RandomVector(-4, 4);
|
|
data.m_vAngles = QAngle(90, random->RandomInt(0, 360), 0);
|
|
data.m_nEntIndex = entindex();
|
|
|
|
DispatchEffect("ShellEject", data);
|
|
}
|
|
}*/
|
|
/*SendWeaponAnim(ACT_VM_RELOAD);
|
|
}
|
|
|
|
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() <= 0)// GetMaxClip1() )
|
|
{
|
|
m_iClip1 = m_iClip1 + 1;
|
|
pOwner->RemoveAmmo(2, m_iPrimaryAmmoType);
|
|
}
|
|
if ( (Clip1() < 2) && (Clip1() > 0) )*/
|
|
/*{
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool CWeaponAnnabelle::Holster(CBaseCombatWeapon *pSwitchingTo)
|
|
{
|
|
return BaseClass::Holster(pSwitchingTo);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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;
|
|
}
|