//========= Copyright © 1996-2015 L1ght 15 ====================================// // // Purpose: Auto Shotgun Alternative // // //=============================================================================// #include "cbase.h" #include "NPCEvent.h" #include "basecombatcharacter.h" #include "AI_BaseNPC.h" #include "player.h" #include "gamerules.h" #include "in_buttons.h" #include "soundent.h" #include "vstdlib/random.h" #include "gamestats.h" #include "weapon_autoshotgun.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" extern ConVar sk_auto_reload_time; extern ConVar sk_plr_num_shotgun_pellets; BEGIN_DATADESC( CWeaponAutoShotgun ) DEFINE_FIELD( m_bNeedPump, FIELD_BOOLEAN ), DEFINE_FIELD( m_bDelayedFire, FIELD_BOOLEAN ), DEFINE_FIELD( m_nShotsFired, FIELD_INTEGER ), END_DATADESC() IMPLEMENT_SERVERCLASS_ST( CWeaponAutoShotgun, DT_WeaponAutoShotgun ) END_SEND_TABLE() LINK_ENTITY_TO_CLASS( weapon_autoshotgun, CWeaponAutoShotgun ); PRECACHE_WEAPON_REGISTER( weapon_autoshotgun ); acttable_t CWeaponAutoShotgun::m_acttable[] = { { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_SHOTGUN, false }, // Light Kill : MP animstate for singleplayer { ACT_HL2MP_RUN, ACT_HL2MP_RUN_SHOTGUN, false }, { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SHOTGUN, false }, { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_SHOTGUN, false }, { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN, false }, { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SHOTGUN, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SHOTGUN, false }, //{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, false }, // END { 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( CWeaponAutoShotgun ); CWeaponAutoShotgun::CWeaponAutoShotgun( void ) { m_bReloadsSingly = true; m_bNeedPump = false; m_bDelayedFire = false; m_fMinRange1 = 0.0; m_fMaxRange1 = 500; m_fMinRange2 = 0.0; m_fMaxRange2 = 200; m_nShotsFired = 0; } void CWeaponAutoShotgun::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 ); } info.m_vecSpread = pOperator->GetAttackSpread(this); if (((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 0)) || ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 2))) { pOperator->FireBullets(8, vecShootOrigin, vecShootDir, info.m_vecSpread, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 1); } else if ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 1)) { pOperator->FireBulletsShotgun(8, vecShootOrigin, vecShootDir, info.m_vecSpread, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 1); } } void CWeaponAutoShotgun::Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ) { m_iClip1++; FireNPCPrimaryAttack( pOperator, true ); } void CWeaponAutoShotgun::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; } }