mirror of
https://github.com/Gigaslav/HL2Overcharged.git
synced 2026-01-02 17:48:11 +03:00
577 lines
18 KiB
C++
577 lines
18 KiB
C++
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "basehlcombatweapon.h"
|
|
#include "NPCevent.h"
|
|
#include "basecombatcharacter.h"
|
|
#include "AI_BaseNPC.h"
|
|
#include "player.h"
|
|
#include "game.h"
|
|
#include "in_buttons.h"
|
|
#include "grenade_ar2.h"
|
|
#include "weapon_rpg.h"
|
|
#include "triggers.h"
|
|
#include "AI_Memory.h"
|
|
#include "soundent.h"
|
|
#include "rumble_shared.h"
|
|
#include "gamestats.h"
|
|
#include "Filesystem.h"
|
|
#include "weapon_custom.h"
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
extern ConVar sk_plr_dmg_smg1_grenade;
|
|
|
|
//LINK_ENTITY_TO_CLASS( weapon_custom1, CWeaponCustom ); //I give up.
|
|
//PRECACHE_WEAPON_REGISTER(weapon_custom1);
|
|
|
|
//LINK_ENTITY_TO_CLASS( weapon_custom2, CWeaponCustom );
|
|
//PRECACHE_WEAPON_REGISTER(weapon_custom2);
|
|
|
|
//LINK_ENTITY_TO_CLASS( weapon_custom3, CWeaponCustom );
|
|
//PRECACHE_WEAPON_REGISTER(weapon_custom3);
|
|
|
|
//LINK_ENTITY_TO_CLASS( weapon_custom4, CWeaponCustom );
|
|
//PRECACHE_WEAPON_REGISTER(weapon_custom4);
|
|
//LINK_ENTITY_TO_CLASS_CUSTOM("weapon_ak47",CWeaponCustom)
|
|
|
|
IMPLEMENT_SERVERCLASS_ST(CWeaponCustom, DT_WeaponCustom)
|
|
END_SEND_TABLE()
|
|
|
|
BEGIN_DATADESC(CWeaponCustom)
|
|
DEFINE_FIELD(m_hMissile, FIELD_EHANDLE),
|
|
END_DATADESC()
|
|
|
|
//=========================================================
|
|
CWeaponCustom::CWeaponCustom()
|
|
{
|
|
m_fMinRange1 = 0;// No minimum range.
|
|
m_fMaxRange1 = 1400;
|
|
|
|
m_bAltFiresUnderwater = false;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CWeaponCustom::Precache(void)
|
|
{
|
|
|
|
BaseClass::Precache();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Give this weapon longer range when wielded by an ally NPC.
|
|
//-----------------------------------------------------------------------------
|
|
void CWeaponCustom::Equip(CBaseCombatCharacter *pOwner)
|
|
{
|
|
if (pOwner->Classify() == CLASS_PLAYER_ALLY)
|
|
{
|
|
m_fMaxRange1 = 3000;
|
|
}
|
|
else
|
|
{
|
|
m_fMaxRange1 = 1400;
|
|
}
|
|
|
|
BaseClass::Equip(pOwner);
|
|
}
|
|
void CWeaponCustom::ItemPostFrame(void)
|
|
{
|
|
CBasePlayer *pOwner = ToBasePlayer(GetOwner());
|
|
if (!pOwner)
|
|
return;
|
|
|
|
//Track the duration of the fire
|
|
//FIXME: Check for IN_ATTACK2 as well?
|
|
//FIXME: What if we're calling ItemBusyFrame?
|
|
m_fFireDuration = (pOwner->m_nButtons & IN_ATTACK) ? (m_fFireDuration + gpGlobals->frametime) : 0.0f;
|
|
|
|
if (UsesClipsForAmmo1())
|
|
{
|
|
CheckReload();
|
|
}
|
|
if ((pOwner->m_nButtons & IN_ATTACK2) && (m_flNextPrimaryAttack <= gpGlobals->curtime))
|
|
{
|
|
// Clip empty? Or out of ammo on a no-clip weapon?
|
|
if (!IsMeleeWeapon() &&
|
|
((UsesClipsForAmmo1() && m_iClip1 <= 0) || (!UsesClipsForAmmo1() && pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0)))
|
|
{
|
|
HandleFireOnEmpty();
|
|
}
|
|
else if (pOwner->GetWaterLevel() == 3 && m_bFiresUnderwater == false)
|
|
{
|
|
// This weapon doesn't fire underwater
|
|
WeaponSound(EMPTY);
|
|
m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//NOTENOTE: There is a bug with this code with regards to the way machine guns catch the leading edge trigger
|
|
// on the player hitting the attack key. It relies on the gun catching that case in the same frame.
|
|
// However, because the player can also be doing a secondary attack, the edge trigger may be missed.
|
|
// We really need to hold onto the edge trigger and only clear the condition when the gun has fired its
|
|
// first shot. Right now that's too much of an architecture change -- jdw
|
|
|
|
// If the firing button was just pressed, or the alt-fire just released, reset the firing time
|
|
if ((pOwner->m_afButtonPressed & IN_ATTACK) || (pOwner->m_afButtonReleased & IN_ATTACK2))
|
|
{
|
|
m_flNextPrimaryAttack = gpGlobals->curtime;
|
|
}
|
|
|
|
SecondaryAttack();
|
|
}
|
|
}
|
|
if ((pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime))
|
|
{
|
|
// Clip empty? Or out of ammo on a no-clip weapon?
|
|
if (!IsMeleeWeapon() &&
|
|
((UsesClipsForAmmo1() && m_iClip1 <= 0) || (!UsesClipsForAmmo1() && pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0)))
|
|
{
|
|
HandleFireOnEmpty();
|
|
}
|
|
else if (pOwner->GetWaterLevel() == 3 && m_bFiresUnderwater == false)
|
|
{
|
|
// This weapon doesn't fire underwater
|
|
WeaponSound(EMPTY);
|
|
m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//NOTENOTE: There is a bug with this code with regards to the way machine guns catch the leading edge trigger
|
|
// on the player hitting the attack key. It relies on the gun catching that case in the same frame.
|
|
// However, because the player can also be doing a secondary attack, the edge trigger may be missed.
|
|
// We really need to hold onto the edge trigger and only clear the condition when the gun has fired its
|
|
// first shot. Right now that's too much of an architecture change -- jdw
|
|
|
|
// If the firing button was just pressed, or the alt-fire just released, reset the firing time
|
|
if ((pOwner->m_afButtonPressed & IN_ATTACK) || (pOwner->m_afButtonReleased & IN_ATTACK2))
|
|
{
|
|
m_flNextPrimaryAttack = gpGlobals->curtime;
|
|
}
|
|
|
|
PrimaryAttack();
|
|
}
|
|
}
|
|
|
|
// -----------------------
|
|
// Reload pressed / Clip Empty
|
|
// -----------------------
|
|
if (pOwner->m_nButtons & IN_RELOAD && UsesClipsForAmmo1() && !m_bInReload)
|
|
{
|
|
// reload when reload is pressed, or if no buttons are down and weapon is empty.
|
|
Reload();
|
|
m_fFireDuration = 0.0f;
|
|
}
|
|
|
|
// -----------------------
|
|
// No buttons down
|
|
// -----------------------
|
|
if (!((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (pOwner->m_nButtons & IN_RELOAD)))
|
|
{
|
|
// no fire buttons down or reloading
|
|
if (!ReloadOrSwitchWeapons() && (m_bInReload == false))
|
|
{
|
|
WeaponIdle();
|
|
}
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CWeaponCustom::FireNPCPrimaryAttack(CBaseCombatCharacter *pOperator, Vector &vecShootOrigin, Vector &vecShootDir)
|
|
{
|
|
// FIXME: use the returned number of bullets to account for >10hz firerate
|
|
WeaponSoundRealtime(SINGLE_NPC);
|
|
|
|
CSoundEnt::InsertSound(SOUND_COMBAT | SOUND_CONTEXT_GUNFIRE, pOperator->GetAbsOrigin(), SOUNDENT_VOLUME_MACHINEGUN, 0.2, pOperator, SOUNDENT_CHANNEL_WEAPON, pOperator->GetEnemy());
|
|
/*if (IsPrimaryBullet() == true)
|
|
{
|
|
pOperator->FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED,
|
|
MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2, entindex(), 0);
|
|
FireBulletsInfo_t info;
|
|
info.m_iShots = this->GetWpnData().m_sPrimaryShotCount;
|
|
info.m_flDamage = this->GetWpnData().m_sPrimaryDamage;
|
|
info.m_iPlayerDamage = this->GetWpnData().m_sPrimaryDamage;
|
|
info.m_vecSrc = vecShootOrigin;
|
|
info.m_vecDirShooting = vecShootDir;
|
|
info.m_vecSpread = VECTOR_CONE_PRECALCULATED;
|
|
info.m_flDistance = MAX_TRACE_LENGTH;
|
|
info.m_iAmmoType = m_iPrimaryAmmoType;
|
|
info.m_iTracerFreq = 2;
|
|
info.m_iPenetrationCount = this->GetWpnData().m_iPrimaryPenetrateCount;
|
|
FireBullets(info);
|
|
pOperator->DoMuzzleFlash();
|
|
}*/
|
|
m_iClip1 = m_iClip1 - 1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CWeaponCustom::Operator_ForceNPCFire(CBaseCombatCharacter *pOperator, bool bSecondary)
|
|
{
|
|
// Ensure we have enough rounds in the clip
|
|
m_iClip1++;
|
|
|
|
Vector vecShootOrigin, vecShootDir;
|
|
QAngle angShootDir;
|
|
GetAttachment(LookupAttachment("muzzle"), vecShootOrigin, angShootDir);
|
|
AngleVectors(angShootDir, &vecShootDir);
|
|
FireNPCPrimaryAttack(pOperator, vecShootOrigin, vecShootDir);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CWeaponCustom::Operator_HandleAnimEvent(animevent_t *pEvent, CBaseCombatCharacter *pOperator)
|
|
{
|
|
switch (pEvent->event)
|
|
{
|
|
case EVENT_WEAPON_SMG1:
|
|
{
|
|
Vector vecShootOrigin, vecShootDir;
|
|
QAngle angDiscard;
|
|
|
|
// Support old style attachment point firing
|
|
if ((pEvent->options == NULL) || (pEvent->options[0] == '\0') || (!pOperator->GetAttachment(pEvent->options, vecShootOrigin, angDiscard)))
|
|
{
|
|
vecShootOrigin = pOperator->Weapon_ShootPosition();
|
|
}
|
|
|
|
CAI_BaseNPC *npc = pOperator->MyNPCPointer();
|
|
ASSERT(npc != NULL);
|
|
vecShootDir = npc->GetActualShootTrajectory(vecShootOrigin);
|
|
|
|
FireNPCPrimaryAttack(pOperator, vecShootOrigin, vecShootDir);
|
|
}
|
|
break;
|
|
|
|
/*//FIXME: Re-enable
|
|
case EVENT_WEAPON_AR2_GRENADE:
|
|
{
|
|
CAI_BaseNPC *npc = pOperator->MyNPCPointer();
|
|
Vector vecShootOrigin, vecShootDir;
|
|
vecShootOrigin = pOperator->Weapon_ShootPosition();
|
|
vecShootDir = npc->GetShootEnemyDir( vecShootOrigin );
|
|
Vector vecThrow = m_vecTossVelocity;
|
|
CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecShootOrigin, vec3_angle, npc );
|
|
pGrenade->SetAbsVelocity( vecThrow );
|
|
pGrenade->SetLocalAngularVelocity( QAngle( 0, 400, 0 ) );
|
|
pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY );
|
|
pGrenade->m_hOwner = npc;
|
|
pGrenade->m_pMyWeaponAR2 = this;
|
|
pGrenade->SetDamage(sk_npc_dmg_ar2_grenade.GetFloat());
|
|
// FIXME: arrgg ,this is hard coded into the weapon???
|
|
m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown.
|
|
m_iClip2--;
|
|
}
|
|
break;
|
|
*/
|
|
|
|
default:
|
|
BaseClass::Operator_HandleAnimEvent(pEvent, pOperator);
|
|
break;
|
|
}
|
|
}
|
|
void CWeaponCustom::ShootBullets(bool isPrimary, bool usePrimaryAmmo)
|
|
{
|
|
// Only the player fires this way so we can cast
|
|
CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
|
|
if (!pPlayer)
|
|
return;
|
|
if (isPrimary || usePrimaryAmmo)
|
|
{
|
|
// Abort here to handle burst and auto fire modes
|
|
if ((UsesClipsForAmmo1() && m_iClip1 == 0) || (!UsesClipsForAmmo1() && !pPlayer->GetAmmoCount(m_iPrimaryAmmoType)))
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// Abort here to handle burst and auto fire modes
|
|
if ((UsesClipsForAmmo2() && m_iClip2 == 0) || (!UsesClipsForAmmo2() && !pPlayer->GetAmmoCount(m_iSecondaryAmmoType)))
|
|
return;
|
|
}
|
|
m_nShotsFired++;
|
|
|
|
pPlayer->DoMuzzleFlash();
|
|
|
|
// 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.
|
|
int iBulletsToFire = 0;
|
|
|
|
//float fireRate = (isPrimary) ? GetFireRate() : this->GetWpnData().m_sSecondaryFireRate;
|
|
// MUST call sound before removing a round from the clip of a CHLMachineGun
|
|
while (m_flNextPrimaryAttack <= gpGlobals->curtime)
|
|
{
|
|
if (isPrimary)
|
|
WeaponSound(SINGLE, m_flNextPrimaryAttack);
|
|
else
|
|
WeaponSound(WPN_DOUBLE, m_flNextPrimaryAttack);
|
|
//m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate;
|
|
iBulletsToFire++;
|
|
}
|
|
if (isPrimary || usePrimaryAmmo)
|
|
{
|
|
m_iPrimaryAttacks++;
|
|
// 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;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_iSecondaryAttacks++;
|
|
// Make sure we don't fire more than the amount in the clip, if this weapon uses clips
|
|
if (UsesClipsForAmmo2())
|
|
{
|
|
if (iBulletsToFire > m_iClip2)
|
|
iBulletsToFire = m_iClip2;
|
|
m_iClip2 -= iBulletsToFire;
|
|
}
|
|
}
|
|
gamestats->Event_WeaponFired(pPlayer, isPrimary, GetClassname());
|
|
|
|
// Fire the bullets
|
|
FireBulletsInfo_t info;
|
|
/*if (isPrimary)
|
|
{
|
|
info.m_iShots = this->GetWpnData().m_sPrimaryShotCount;
|
|
info.m_flDamage = this->GetWpnData().m_sPrimaryDamage;
|
|
info.m_iPlayerDamage = this->GetWpnData().m_sPrimaryDamage;
|
|
info.m_vecSpread = GetBulletSpreadPrimary();
|
|
info.m_iPenetrationCount = this->GetWpnData().m_iPrimaryPenetrateCount;
|
|
info.m_flPenetrationForce = this->GetWpnData().m_flPrimaryPenetrateDepth;
|
|
}
|
|
else
|
|
{
|
|
info.m_iShots = this->GetWpnData().m_sSecondaryShotCount;
|
|
info.m_flDamage = this->GetWpnData().m_sSecondaryDamage;
|
|
info.m_iPlayerDamage = this->GetWpnData().m_sSecondaryDamage;
|
|
info.m_vecSpread = GetBulletSpreadSecondary();
|
|
info.m_iPenetrationCount = this->GetWpnData().m_iSecondaryPenetrateCount;
|
|
info.m_flPenetrationForce = this->GetWpnData().m_flSecondaryPenetrateDepth;
|
|
}*/
|
|
info.m_vecSrc = pPlayer->Weapon_ShootPosition();
|
|
info.m_vecDirShooting = pPlayer->GetAutoaimVector(AUTOAIM_SCALE_DEFAULT);
|
|
info.m_flDistance = MAX_TRACE_LENGTH;
|
|
info.m_iAmmoType = m_iPrimaryAmmoType;
|
|
info.m_iTracerFreq = 2;
|
|
FireBullets(info);
|
|
|
|
//Factor in the view kick
|
|
AddViewKick();
|
|
|
|
CSoundEnt::InsertSound(SOUND_COMBAT, GetAbsOrigin(), SOUNDENT_VOLUME_MACHINEGUN, 0.2, pPlayer);
|
|
|
|
SendWeaponAnim(GetPrimaryAttackActivity());
|
|
pPlayer->SetAnimation(PLAYER_ATTACK1);
|
|
|
|
// Register a muzzleflash for the AI
|
|
pPlayer->SetMuzzleFlashTime(gpGlobals->curtime + 0.5);
|
|
}
|
|
|
|
#ifdef HL2_DLL
|
|
extern int g_interactionPlayerLaunchedRPG;
|
|
#endif
|
|
|
|
void CWeaponCustom::ShootProjectile(bool isPrimary, bool usePrimaryAmmo)
|
|
{
|
|
|
|
// Can't have an active missile out
|
|
if (m_hMissile != NULL)
|
|
return;
|
|
|
|
// Can't be reloading
|
|
if (GetActivity() == ACT_VM_RELOAD)
|
|
return;
|
|
|
|
Vector vecOrigin;
|
|
Vector vecForward;
|
|
|
|
m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f;
|
|
|
|
CBasePlayer *pOwner = ToBasePlayer(GetOwner());
|
|
|
|
if (pOwner == NULL)
|
|
return;
|
|
|
|
Vector vForward, vRight, vUp;
|
|
|
|
pOwner->EyeVectors(&vForward, &vRight, &vUp);
|
|
|
|
Vector muzzlePoint = pOwner->Weapon_ShootPosition() + vForward * 12.0f + vRight * 6.0f + vUp * -3.0f;
|
|
|
|
QAngle vecAngles;
|
|
VectorAngles(vForward, vecAngles);
|
|
m_hMissile = CMissile::Create(muzzlePoint, vecAngles, GetOwner()->edict());
|
|
|
|
// m_hMissile->m_hOwner = this;
|
|
|
|
// If the shot is clear to the player, give the missile a grace period
|
|
trace_t tr;
|
|
Vector vecEye = pOwner->EyePosition();
|
|
UTIL_TraceLine(vecEye, vecEye + vForward * 128, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr);
|
|
if (tr.fraction == 1.0)
|
|
{
|
|
m_hMissile->SetGracePeriod(0.3);
|
|
}
|
|
|
|
|
|
// Register a muzzleflash for the AI
|
|
pOwner->SetMuzzleFlashTime(gpGlobals->curtime + 0.5);
|
|
|
|
SendWeaponAnim(ACT_VM_PRIMARYATTACK);
|
|
WeaponSound(SINGLE);
|
|
|
|
pOwner->RumbleEffect(RUMBLE_SHOTGUN_SINGLE, 0, RUMBLE_FLAG_RESTART);
|
|
|
|
m_iPrimaryAttacks++;
|
|
gamestats->Event_WeaponFired(pOwner, true, GetClassname());
|
|
|
|
CSoundEnt::InsertSound(SOUND_COMBAT, GetAbsOrigin(), 1000, 0.2, GetOwner(), SOUNDENT_CHANNEL_WEAPON);
|
|
|
|
// Check to see if we should trigger any RPG firing triggers
|
|
//Yes, these now work.
|
|
int iCount = g_hWeaponFireTriggers.Count();
|
|
for (int i = 0; i < iCount; i++)
|
|
{
|
|
if (g_hWeaponFireTriggers[i]->IsTouching(pOwner))
|
|
{
|
|
if (FClassnameIs(g_hWeaponFireTriggers[i], "trigger_rpgfire"))
|
|
{
|
|
g_hWeaponFireTriggers[i]->ActivateMultiTrigger(pOwner);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hl2_episodic.GetBool())
|
|
{
|
|
CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
|
|
int nAIs = g_AI_Manager.NumAIs();
|
|
|
|
string_t iszStriderClassname = AllocPooledString("npc_strider");
|
|
|
|
for (int i = 0; i < nAIs; i++)
|
|
{
|
|
if (ppAIs[i]->m_iClassname == iszStriderClassname)
|
|
{
|
|
ppAIs[i]->DispatchInteraction(g_interactionPlayerLaunchedRPG, NULL, m_hMissile);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Output : Activity
|
|
//-----------------------------------------------------------------------------
|
|
Activity CWeaponCustom::GetPrimaryAttackActivity(void)
|
|
{
|
|
if (m_nShotsFired < 2)
|
|
return ACT_VM_PRIMARYATTACK;
|
|
|
|
if (m_nShotsFired < 3)
|
|
return ACT_VM_RECOIL1;
|
|
|
|
if (m_nShotsFired < 4)
|
|
return ACT_VM_RECOIL2;
|
|
|
|
return ACT_VM_RECOIL3;
|
|
}
|
|
|
|
void CWeaponCustom::PrimaryAttack(void)
|
|
{
|
|
/*if (this->GetWpnData().m_sPrimaryMissleEnabled)
|
|
this->ShootProjectile(true, true);
|
|
else if (IsPrimaryBullet() == true)
|
|
ShootBullets(true, true);*/
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
bool CWeaponCustom::Reload(void)
|
|
{
|
|
bool fRet;
|
|
float fCacheTime = m_flNextSecondaryAttack;
|
|
|
|
fRet = DefaultReload(GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD);
|
|
if (fRet)
|
|
{
|
|
// Undo whatever the reload process has done to our secondary
|
|
// attack timer. We allow you to interrupt reloading to fire
|
|
// a grenade.
|
|
m_flNextSecondaryAttack = GetOwner()->m_flNextAttack = fCacheTime;
|
|
|
|
WeaponSound(RELOAD);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CWeaponCustom::AddViewKick(void)
|
|
{
|
|
#define EASY_DAMPEN 0.5f
|
|
#define MAX_VERTICAL_KICK 1.0f //Degrees
|
|
#define SLIDE_LIMIT 2.0f //Seconds
|
|
|
|
//Get the view kick
|
|
CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
|
|
|
|
if (pPlayer == NULL)
|
|
return;
|
|
|
|
DoMachineGunKick(pPlayer, EASY_DAMPEN, MAX_VERTICAL_KICK, m_fFireDuration, SLIDE_LIMIT);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CWeaponCustom::SecondaryAttack(void)
|
|
{
|
|
/*if (this->GetWpnData().m_sSecondaryMissleEnabled)
|
|
this->ShootProjectile(false, this->GetWpnData().m_sUsePrimaryAmmo);
|
|
else if (IsSecondaryBullet())
|
|
ShootBullets(false, this->GetWpnData().m_sUsePrimaryAmmo);*/
|
|
}
|
|
|
|
#define COMBINE_MIN_GRENADE_CLEAR_DIST 256
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : flDot -
|
|
// flDist -
|
|
// Output : int
|
|
//-----------------------------------------------------------------------------
|
|
int CWeaponCustom::WeaponRangeAttack2Condition(float flDot, float flDist)
|
|
{
|
|
return COND_NONE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
const WeaponProficiencyInfo_t *CWeaponCustom::GetProficiencyValues()
|
|
{
|
|
static WeaponProficiencyInfo_t proficiencyTable[] =
|
|
{
|
|
{ 7.0, 0.75 },
|
|
{ 5.00, 0.75 },
|
|
{ 10.0 / 3.0, 0.75 },
|
|
{ 5.0 / 3.0, 0.75 },
|
|
{ 1.00, 1.0 },
|
|
};
|
|
|
|
COMPILE_TIME_ASSERT(ARRAYSIZE(proficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1);
|
|
|
|
return proficiencyTable;
|
|
} |