Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //========= Copyright Valve Corporation, All rights reserved. ============//
- //
- // Purpose: Carabine - The Paradox carabine weapon
- //
- // $NoKeywords: $
- //=============================================================================//
- #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"
- #include "gamestats.h"
- // memdbgon must be the last include file in a .cpp file!!!
- #include "tier0/memdbgon.h"
- extern ConVar sk_auto_reload_time;
- class CWeaponCarabine : public CBaseHLCombatWeapon
- {
- DECLARE_DATADESC();
- public:
- DECLARE_CLASS(CWeaponCarabine, 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
- bool bFlip;
- public:
- void Precache(void);
- int CapabilitiesGet(void) { return bits_CAP_WEAPON_RANGE_ATTACK1; }
- virtual const Vector& GetBulletSpread(void)
- {
- static Vector vitalAllyCone = VECTOR_CONE_3DEGREES;
- static Vector cone = VECTOR_CONE_10DEGREES;
- if (GetOwner() && (GetOwner()->Classify() == CLASS_PLAYER_ALLY_VITAL))
- {
- // Give Alyx's carabine blasts more a more directed punch. She needs
- // to be at least as deadly as she would be with her pistol to stay interesting (sjb)
- return vitalAllyCone;
- }
- return cone;
- }
- virtual int GetMinBurst() { return 1; }
- virtual int GetMaxBurst() { return 3; }
- virtual float GetMinRestTime();
- virtual float GetMaxRestTime();
- virtual float GetFireRate(void);
- bool StartReload(void);
- bool Reload(void);
- void FillClip(void);
- void FinishReload(void);
- void CheckHolsterReload(void);
- void Pump(void);
- void WeaponIdle( void );
- void ItemHolsterFrame(void);
- void ItemPostFrame(void);
- void PrimaryAttack(void);
- void LeftGunAttack(void);
- void SecondaryAttack(void);
- void DryFire(void);
- void FireNPCPrimaryAttack(CBaseCombatCharacter *pOperator, bool bUseWeaponAngles);
- void Operator_ForceNPCFire(CBaseCombatCharacter *pOperator, bool bSecondary);
- void Operator_HandleAnimEvent(animevent_t *pEvent, CBaseCombatCharacter *pOperator);
- DECLARE_ACTTABLE();
- CWeaponCarabine(void);
- };
- IMPLEMENT_SERVERCLASS_ST(CWeaponCarabine, DT_WeaponCarabine)
- END_SEND_TABLE()
- LINK_ENTITY_TO_CLASS(weapon_carabine, CWeaponCarabine);
- PRECACHE_WEAPON_REGISTER(weapon_carabine);
- BEGIN_DATADESC(CWeaponCarabine)
- DEFINE_FIELD(m_bNeedPump, FIELD_BOOLEAN),
- DEFINE_FIELD(m_bDelayedFire1, FIELD_BOOLEAN),
- DEFINE_FIELD(m_bDelayedFire2, FIELD_BOOLEAN),
- END_DATADESC()
- acttable_t CWeaponCarabine::m_acttable[] =
- {
- { ACT_IDLE, ACT_IDLE_SMG1, true }, // FIXME: hook to shotgun unique
- { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, true },
- { ACT_RELOAD, ACT_RELOAD_SHOTGUN, false },
- { ACT_WALK, ACT_WALK_RIFLE, true },
- { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SHOTGUN, true },
- // Readiness activities (not aiming)
- { ACT_IDLE_RELAXED, ACT_IDLE_SHOTGUN_RELAXED, false },//never aims
- { ACT_IDLE_STIMULATED, ACT_IDLE_SHOTGUN_STIMULATED, false },
- { ACT_IDLE_AGITATED, ACT_IDLE_SHOTGUN_AGITATED, false },//always aims
- { ACT_WALK_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims
- { ACT_WALK_STIMULATED, ACT_WALK_RIFLE_STIMULATED, false },
- { ACT_WALK_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims
- { ACT_RUN_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims
- { ACT_RUN_STIMULATED, ACT_RUN_RIFLE_STIMULATED, false },
- { ACT_RUN_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims
- // Readiness activities (aiming)
- { ACT_IDLE_AIM_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims
- { ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_RIFLE_STIMULATED, false },
- { ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims
- { ACT_WALK_AIM_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims
- { ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_RIFLE_STIMULATED, false },
- { ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims
- { ACT_RUN_AIM_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims
- { ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_RIFLE_STIMULATED, false },
- { ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims
- //End readiness activities
- { ACT_WALK_AIM, ACT_WALK_AIM_SHOTGUN, true },
- { ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true },
- { ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true },
- { ACT_RUN, ACT_RUN_RIFLE, true },
- { ACT_RUN_AIM, ACT_RUN_AIM_SHOTGUN, true },
- { ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true },
- { ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true },
- { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_SHOTGUN, true },
- { ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_SHOTGUN_LOW, true },
- { ACT_RELOAD_LOW, ACT_RELOAD_SHOTGUN_LOW, false },
- { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SHOTGUN, false },
- };
- IMPLEMENT_ACTTABLE(CWeaponCarabine);
- void CWeaponCarabine::Precache(void)
- {
- CBaseCombatWeapon::Precache();
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Input : *pOperator -
- //-----------------------------------------------------------------------------
- void CWeaponCarabine::FireNPCPrimaryAttack(CBaseCombatCharacter *pOperator, bool bUseWeaponAngles)
- {
- Vector vecShootOrigin, vecShootDir;
- CAI_BaseNPC *npc = pOperator->MyNPCPointer();
- ASSERT(npc != NULL);
- WeaponSound(SINGLE_NPC);
- pOperator->DoMuzzleFlash();
- m_iClip1 = m_iClip1 - 1;
- if (bUseWeaponAngles)
- {
- QAngle angShootDir;
- GetAttachment(LookupAttachment("muzzle"), vecShootOrigin, angShootDir);
- AngleVectors(angShootDir, &vecShootDir);
- }
- else
- {
- vecShootOrigin = pOperator->Weapon_ShootPosition();
- vecShootDir = npc->GetActualShootTrajectory(vecShootOrigin);
- }
- pOperator->FireBullets(8, vecShootOrigin, vecShootDir, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0);
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- void CWeaponCarabine::Operator_ForceNPCFire(CBaseCombatCharacter *pOperator, bool bSecondary)
- {
- // Ensure we have enough rounds in the clip
- m_iClip1++;
- FireNPCPrimaryAttack(pOperator, true);
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Input :
- // Output :
- //-----------------------------------------------------------------------------
- void CWeaponCarabine::Operator_HandleAnimEvent(animevent_t *pEvent, CBaseCombatCharacter *pOperator)
- {
- switch (pEvent->event)
- {
- case EVENT_WEAPON_SHOTGUN_FIRE:
- {
- FireNPCPrimaryAttack(pOperator, false);
- }
- break;
- default:
- CBaseCombatWeapon::Operator_HandleAnimEvent(pEvent, pOperator);
- break;
- }
- }
- //-----------------------------------------------------------------------------
- // Purpose: When we shipped HL2, the carabine weapon did not override the
- // BaseCombatWeapon default rest time of 0.3 to 0.6 seconds. When
- // NPC's fight from a stationary position, their animation events
- // govern when they fire so the rate of fire is specified by the
- // animation. When NPC's move-and-shoot, the rate of fire is
- // specifically controlled by the shot regulator, so it's imporant
- // that GetMinRestTime and GetMaxRestTime are implemented and provide
- // reasonable defaults for the weapon. To address difficulty concerns,
- // we are going to fix the combine's rate of carabine fire in episodic.
- // This change will not affect Alyx using a carabine in EP1. (sjb)
- //-----------------------------------------------------------------------------
- float CWeaponCarabine::GetMinRestTime()
- {
- if (hl2_episodic.GetBool() && GetOwner() && GetOwner()->Classify() == CLASS_COMBINE)
- {
- return 1.2f;
- }
- return BaseClass::GetMinRestTime();
- }
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- float CWeaponCarabine::GetMaxRestTime()
- {
- if (hl2_episodic.GetBool() && GetOwner() && GetOwner()->Classify() == CLASS_COMBINE)
- {
- return 1.5f;
- }
- return BaseClass::GetMaxRestTime();
- }
- //-----------------------------------------------------------------------------
- // Purpose: Time between successive shots in a burst. Also returned for EP2
- // with an eye to not messing up Alyx in EP1.
- //-----------------------------------------------------------------------------
- float CWeaponCarabine::GetFireRate()
- {
- if (hl2_episodic.GetBool() && GetOwner() && GetOwner()->Classify() == CLASS_COMBINE)
- {
- return 0.8f;
- }
- return 0.7;
- }
- //-----------------------------------------------------------------------------
- // Purpose: Override so only reload one shell at a time
- // Input :
- // Output :
- //-----------------------------------------------------------------------------
- bool CWeaponCarabine::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 carabine totally emptied then a pump animation is needed
- //NOTENOTE: This is kinda lame because the player doesn't get strong feedback on when the reload has finished,
- // without the pump. Technically, it's incorrect, but it's good for feedback...
- 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 carabine shell visible
- SetBodygroup(1, 0);
- pOwner->m_flNextAttack = gpGlobals->curtime;
- m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
- m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
- m_bInReload = true;
- return true;
- }
- //-----------------------------------------------------------------------------
- // Purpose: Override so only reload one shell at a time
- // Input :
- // Output :
- //-----------------------------------------------------------------------------
- bool CWeaponCarabine::Reload(void)
- {
- // Check that StartReload was called first
- if (!m_bInReload)
- {
- Warning("ERROR: Carabine 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();
- m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
- return true;
- }
- //-----------------------------------------------------------------------------
- // Purpose: Play finish reload anim and fill clip
- // Input :
- // Output :
- //-----------------------------------------------------------------------------
- void CWeaponCarabine::FinishReload(void)
- {
- // Make carabine 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 CWeaponCarabine::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 CWeaponCarabine::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 CWeaponCarabine::DryFire(void)
- {
- WeaponSound(EMPTY);
- SendWeaponAnim(ACT_VM_DRYFIRE);
- m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //
- //
- //-----------------------------------------------------------------------------
- void CWeaponCarabine::PrimaryAttack(void)
- {
- // 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(ACT_VM_PRIMARYATTACK);
- // player "shoot" animation
- pPlayer->SetAnimation(PLAYER_ATTACK1);
- // Don't fire again until fire animation has completed
- m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
- m_iClip1 -= 1;
- Vector vecSrc = pPlayer->Weapon_ShootPosition();
- Vector vecAiming = pPlayer->GetAutoaimVector(AUTOAIM_SCALE_DEFAULT);
- pPlayer->SetMuzzleFlashTime(gpGlobals->curtime + 1.0);
- // Fire the bullets, and force the first shot to be perfectly accuracy
- pPlayer->FireBullets(6, vecSrc, vecAiming, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0, -1, -1, 0, NULL, true, true);
- pPlayer->ViewPunch(QAngle(random->RandomFloat(-2, -1), random->RandomFloat(-2, 2), 0));
- CSoundEnt::InsertSound(SOUND_COMBAT, GetAbsOrigin(), SOUNDENT_VOLUME_SHOTGUN, 0.2, GetOwner());
- if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0)
- {
- // HEV suit - indicate out of ammo condition
- pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
- }
- //if (m_iClip1)
- //{
- // // pump so long as some rounds are left.
- // m_bNeedPump = true;
- //}
- //Flipping Code -Jman
- if ( !bFlip)
- {
- BaseClass::PrimaryAttack();
- m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
- bFlip= true;
- }
- else
- {
- LeftGunAttack();
- m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
- bFlip = false;
- }
- m_iPrimaryAttacks++;
- gamestats->Event_WeaponFired(pPlayer, true, GetClassname());
- }
- //-----------------------------------------------------------------------------
- // Purpose: Carabine Fire second barrel
- //-----------------------------------------------------------------------------
- void CWeaponCarabine::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();
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //
- //
- //-----------------------------------------------------------------------------
- void CWeaponCarabine::SecondaryAttack(void)
- {
- // Only the player fires this way so we can cast
- CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
- if (!pPlayer)
- {
- return;
- }
- pPlayer->m_nButtons &= ~IN_ATTACK2;
- // MUST call sound before removing a round from the clip of a CMachineGun
- WeaponSound(WPN_DOUBLE);
- pPlayer->DoMuzzleFlash();
- SendWeaponAnim(ACT_VM_SECONDARYATTACK);
- // player "shoot" animation
- pPlayer->SetAnimation(PLAYER_ATTACK1);
- // Don't fire again until fire animation has completed
- m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
- m_iClip1 -= 2; // Carabine uses same clip for primary and secondary attacks
- Vector vecSrc = pPlayer->Weapon_ShootPosition();
- Vector vecAiming = pPlayer->GetAutoaimVector(AUTOAIM_SCALE_DEFAULT);
- // Fire the bullets
- pPlayer->FireBullets(12, vecSrc, vecAiming, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0, -1, -1, 0, NULL, false, false);
- pPlayer->ViewPunch(QAngle(random->RandomFloat(-5, 5), 0, 0));
- pPlayer->SetMuzzleFlashTime(gpGlobals->curtime + 1.0);
- CSoundEnt::InsertSound(SOUND_COMBAT, GetAbsOrigin(), SOUNDENT_VOLUME_SHOTGUN, 0.2);
- if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0)
- {
- // HEV suit - indicate out of ammo condition
- pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
- }
- if (m_iClip1)
- {
- // pump so long as some rounds are left.
- m_bNeedPump = true;
- }
- m_iSecondaryAttacks++;
- gamestats->Event_WeaponFired(pPlayer, false, GetClassname());
- }
- //-----------------------------------------------------------------------------
- // Purpose: Override so carabine can do multiple reloads in a row
- //-----------------------------------------------------------------------------
- void CWeaponCarabine::ItemPostFrame(void)
- {
- CBasePlayer *pOwner = ToBasePlayer(GetOwner());
- if (!pOwner)
- {
- return;
- }
- if (m_bInReload)
- {
- // If I'm primary firing and have one round stop reloading and fire
- if ((pOwner->m_nButtons & IN_ATTACK) && (m_iClip1 >= 1))
- {
- m_bInReload = false;
- m_bNeedPump = false;
- m_bDelayedFire1 = true;
- }
- // If I'm secondary firing and have one round stop reloading and fire
- else if ((pOwner->m_nButtons & IN_ATTACK2) && (m_iClip1 >= 2))
- {
- m_bInReload = false;
- m_bNeedPump = false;
- m_bDelayedFire2 = true;
- }
- else if (m_flNextPrimaryAttack <= gpGlobals->curtime)
- {
- // If out of ammo end reload
- if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0)
- {
- FinishReload();
- return;
- }
- // If clip not full reload again
- if (m_iClip1 < GetMaxClip1())
- {
- Reload();
- return;
- }
- // Clip full, stop reloading
- else
- {
- FinishReload();
- return;
- }
- }
- }
- else
- {
- // Make carabine shell invisible
- SetBodygroup(1, 1);
- }
- if ((m_bNeedPump) && (m_flNextPrimaryAttack <= gpGlobals->curtime))
- {
- Pump();
- return;
- }
- // Carabine uses same timing and ammo for secondary attack
- if ((m_bDelayedFire2 || pOwner->m_nButtons & IN_ATTACK2) && (m_flNextPrimaryAttack <= gpGlobals->curtime))
- {
- m_bDelayedFire2 = false;
- if ((m_iClip1 <= 1 && UsesClipsForAmmo1()))
- {
- // If only one shell is left, do a single shot instead
- if (m_iClip1 == 1)
- {
- PrimaryAttack();
- }
- else if (!pOwner->GetAmmoCount(m_iPrimaryAmmoType))
- {
- DryFire();
- }
- else
- {
- StartReload();
- }
- }
- // Fire underwater?
- else if (GetOwner()->GetWaterLevel() == 3 && m_bFiresUnderwater == false)
- {
- WeaponSound(EMPTY);
- m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
- return;
- }
- else
- {
- // If the firing button was just pressed, reset the firing time
- if (pOwner->m_afButtonPressed & IN_ATTACK)
- {
- m_flNextPrimaryAttack = gpGlobals->curtime;
- }
- SecondaryAttack();
- }
- }
- else if ((m_bDelayedFire1 || pOwner->m_nButtons & IN_ATTACK) && m_flNextPrimaryAttack <= gpGlobals->curtime)
- {
- m_bDelayedFire1 = false;
- if ((m_iClip1 <= 0 && UsesClipsForAmmo1()) || (!UsesClipsForAmmo1() && !pOwner->GetAmmoCount(m_iPrimaryAmmoType)))
- {
- if (!pOwner->GetAmmoCount(m_iPrimaryAmmoType))
- {
- DryFire();
- }
- else
- {
- StartReload();
- }
- }
- // Fire underwater?
- else if (pOwner->GetWaterLevel() == 3 && m_bFiresUnderwater == false)
- {
- WeaponSound(EMPTY);
- m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
- return;
- }
- else
- {
- // If the firing button was just pressed, reset the firing time
- CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
- if (pPlayer && pPlayer->m_afButtonPressed & IN_ATTACK)
- {
- m_flNextPrimaryAttack = gpGlobals->curtime;
- }
- PrimaryAttack();
- }
- }
- if (pOwner->m_nButtons & IN_RELOAD && UsesClipsForAmmo1() && !m_bInReload)
- {
- // reload when reload is pressed, or if no buttons are down and weapon is empty.
- StartReload();
- }
- else
- {
- // no fire buttons down
- m_bFireOnEmpty = false;
- if (!HasAnyAmmo() && m_flNextPrimaryAttack < gpGlobals->curtime)
- {
- // weapon isn't useable, switch.
- if (!(GetWeaponFlags() & ITEM_FLAG_NOAUTOSWITCHEMPTY) && pOwner->SwitchToNextBestWeapon(this))
- {
- m_flNextPrimaryAttack = gpGlobals->curtime + 0.3;
- return;
- }
- }
- else
- {
- // weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
- if (m_iClip1 <= 0 && !(GetWeaponFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < gpGlobals->curtime)
- {
- if (StartReload())
- {
- // if we've successfully started to reload, we're done
- return;
- }
- }
- }
- WeaponIdle();
- return;
- }
- }
- //-----------------------------------------------------------------------------
- // Purpose: Constructor
- //-----------------------------------------------------------------------------
- CWeaponCarabine::CWeaponCarabine(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;
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- void CWeaponCarabine::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:
- //==================================================
- void CWeaponCarabine::WeaponIdle( void )
- {
- //Only the player fires this way so we can cast
- CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
- if ( pPlayer == NULL )
- return;
- //If we're on a target, play the new anim
- if ( pPlayer->IsOnTarget() )
- {
- SendWeaponAnim( ACT_VM_IDLE );
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment