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

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;
}