Guest User

weapon_ar2.cpp

a guest
Sep 26th, 2026
36
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.33 KB | None | 0 0
  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6.  
  7. #include "cbase.h"
  8. #include "basehlcombatweapon.h"
  9. #include "npcevent.h"
  10. #include "basecombatcharacter.h"
  11. #include "ai_basenpc.h"
  12. #include "player.h"
  13. #include "game.h"
  14. #include "in_buttons.h"
  15. #include "grenade_ar2.h"
  16. #include "ai_memory.h"
  17. #include "soundent.h"
  18. #include "rumble_shared.h"
  19. #include "gamestats.h"
  20.  
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include "tier0/memdbgon.h"
  23.  
  24.  
  25. class CWeaponAR2 : public CHLMachineGun
  26. {
  27. DECLARE_DATADESC();
  28. public:
  29. DECLARE_CLASS(CWeaponAR2, CHLMachineGun);
  30.  
  31. CWeaponAR2();
  32.  
  33. DECLARE_SERVERCLASS();
  34.  
  35. void Precache(void);
  36. void AddViewKick(void);
  37.  
  38. int GetMinBurst() { return 2; }
  39. int GetMaxBurst() { return 5; }
  40.  
  41. virtual void Equip(CBaseCombatCharacter* pOwner);
  42. bool Reload(void);
  43.  
  44. float GetFireRate(void) { return 0.1f; } // 13.3hz
  45. int CapabilitiesGet(void) { return bits_CAP_WEAPON_RANGE_ATTACK1; }
  46. Activity GetPrimaryAttackActivity(void);
  47.  
  48. virtual const Vector& GetBulletSpread(void)
  49. {
  50. static const Vector cone = VECTOR_CONE_5DEGREES;
  51. return cone;
  52. }
  53.  
  54. const WeaponProficiencyInfo_t* GetProficiencyValues();
  55.  
  56. void FireNPCPrimaryAttack(CBaseCombatCharacter* pOperator, Vector& vecShootOrigin, Vector& vecShootDir);
  57. void Operator_ForceNPCFire(CBaseCombatCharacter* pOperator, bool bSecondary);
  58. void Operator_HandleAnimEvent(animevent_t* pEvent, CBaseCombatCharacter* pOperator);
  59.  
  60. DECLARE_ACTTABLE();
  61.  
  62.  
  63.  
  64.  
  65. protected:
  66.  
  67.  
  68. bool m_bInZoom;
  69.  
  70. /**
  71. * Check for weapon being holstered so we can disable scope zoom
  72. */
  73. bool CWeaponAR2::Holster(CBaseCombatWeapon* pSwitchingTo /* = NULL */)
  74. {
  75. if (m_bInZoom)
  76. {
  77. ToggleZoom();
  78. }
  79.  
  80. return BaseClass::Holster(pSwitchingTo);
  81. }
  82.  
  83. /**
  84. * Check the status of the zoom key every frame to see if player is still zoomed in
  85. */
  86. void CWeaponAR2::ItemPostFrame()
  87. {
  88. // Allow zoom toggling
  89. CheckZoomToggle();
  90.  
  91. BaseClass::ItemPostFrame();
  92. }
  93.  
  94. /**
  95. * Check the status of the zoom key every frame to see if player is still zoomed in
  96. */
  97. void CWeaponAR2::ItemBusyFrame(void)
  98. {
  99. // Allow zoom toggling even when we're reloading
  100. CheckZoomToggle();
  101.  
  102. BaseClass::ItemBusyFrame();
  103. }
  104.  
  105. /**
  106. * Check if the zoom key was pressed in the last input tick
  107. */
  108. void CWeaponAR2::CheckZoomToggle(void)
  109. {
  110. CBasePlayer* pPlayer = ToBasePlayer(GetOwner());
  111.  
  112. if (pPlayer && (pPlayer->m_afButtonPressed & IN_ATTACK2)) //We need to include "in_buttons.h" for IN_ATTACK2
  113. {
  114. ToggleZoom();
  115. }
  116. }
  117.  
  118. /**
  119. * If we're zooming, stop. If we're not, start.
  120. */
  121. void CWeaponAR2::ToggleZoom(void)
  122. {
  123. CBasePlayer* pPlayer = ToBasePlayer(GetOwner());
  124.  
  125. if (pPlayer == NULL)
  126. return;
  127. #ifndef CLIENT_DLL
  128. if (m_bInZoom)
  129. {
  130. // Narrowing the Field Of View here is what gives us the zoomed effect
  131. if (pPlayer->SetFOV(this, 0, 0.2f))
  132. {
  133. m_bInZoom = false;
  134.  
  135. // Send a message to hide the scope
  136. CSingleUserRecipientFilter filter(pPlayer);
  137. UserMessageBegin(filter, "ShowScope");
  138. WRITE_BYTE(0);
  139. MessageEnd();
  140. }
  141. }
  142. else
  143. {
  144. if (pPlayer->SetFOV(this, 20, 0.1f))
  145. {
  146. m_bInZoom = true;
  147.  
  148. // Send a message to Show the scope
  149. CSingleUserRecipientFilter filter(pPlayer);
  150. UserMessageBegin(filter, "ShowScope");
  151. WRITE_BYTE(1);
  152. MessageEnd();
  153. }
  154. }
  155. #endif
  156. }
  157.  
  158. protected:
  159.  
  160. Vector m_vecTossVelocity;
  161. float m_flNextGrenadeCheck;
  162. };
  163.  
  164. IMPLEMENT_SERVERCLASS_ST(CWeaponAR2, DT_WeaponAR2)
  165. END_SEND_TABLE()
  166.  
  167. LINK_ENTITY_TO_CLASS(weapon_ar2, CWeaponAR2);
  168. PRECACHE_WEAPON_REGISTER(weapon_ar2);
  169.  
  170. BEGIN_DATADESC(CWeaponAR2)
  171.  
  172. DEFINE_FIELD(m_vecTossVelocity, FIELD_VECTOR),
  173. DEFINE_FIELD(m_flNextGrenadeCheck, FIELD_TIME),
  174.  
  175. END_DATADESC()
  176.  
  177. acttable_t CWeaponAR2::m_acttable[] =
  178. {
  179. { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SMG1, true },
  180. { ACT_RELOAD, ACT_RELOAD_SMG1, true },
  181. { ACT_IDLE, ACT_IDLE_SMG1, true },
  182. { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SMG1, true },
  183.  
  184. { ACT_WALK, ACT_WALK_RIFLE, true },
  185. { ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true },
  186.  
  187. // Readiness activities (not aiming)
  188. { ACT_IDLE_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims
  189. { ACT_IDLE_STIMULATED, ACT_IDLE_SMG1_STIMULATED, false },
  190. { ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims
  191.  
  192. { ACT_WALK_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims
  193. { ACT_WALK_STIMULATED, ACT_WALK_RIFLE_STIMULATED, false },
  194. { ACT_WALK_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims
  195.  
  196. { ACT_RUN_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims
  197. { ACT_RUN_STIMULATED, ACT_RUN_RIFLE_STIMULATED, false },
  198. { ACT_RUN_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims
  199.  
  200. // Readiness activities (aiming)
  201. { ACT_IDLE_AIM_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims
  202. { ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_RIFLE_STIMULATED, false },
  203. { ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims
  204.  
  205. { ACT_WALK_AIM_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims
  206. { ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_RIFLE_STIMULATED, false },
  207. { ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims
  208.  
  209. { ACT_RUN_AIM_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims
  210. { ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_RIFLE_STIMULATED, false },
  211. { ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims
  212. //End readiness activities
  213.  
  214. { ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true },
  215. { ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true },
  216. { ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true },
  217. { ACT_RUN, ACT_RUN_RIFLE, true },
  218. { ACT_RUN_AIM, ACT_RUN_AIM_RIFLE, true },
  219. { ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true },
  220. { ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true },
  221. { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_SMG1, true },
  222. { ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_SMG1_LOW, true },
  223. { ACT_COVER_LOW, ACT_COVER_SMG1_LOW, false },
  224. { ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_SMG1_LOW, false },
  225. { ACT_RELOAD_LOW, ACT_RELOAD_SMG1_LOW, false },
  226. { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, true },
  227. };
  228.  
  229. IMPLEMENT_ACTTABLE(CWeaponAR2);
  230.  
  231. //=========================================================
  232. CWeaponAR2::CWeaponAR2()
  233. {
  234. m_fMinRange1 = 0;// No minimum range.
  235. m_fMaxRange1 = 1400;
  236.  
  237. m_bAltFiresUnderwater = false;
  238. }
  239.  
  240. //-----------------------------------------------------------------------------
  241. // Purpose:
  242. //-----------------------------------------------------------------------------
  243. void CWeaponAR2::Precache(void)
  244. {
  245. UTIL_PrecacheOther("grenade_ar2");
  246.  
  247. BaseClass::Precache();
  248. }
  249.  
  250. //-----------------------------------------------------------------------------
  251. // Purpose: Give this weapon longer range when wielded by an ally NPC.
  252. //-----------------------------------------------------------------------------
  253. void CWeaponAR2::Equip(CBaseCombatCharacter* pOwner)
  254. {
  255. if (pOwner->Classify() == CLASS_PLAYER_ALLY)
  256. {
  257. m_fMaxRange1 = 3000;
  258. }
  259. else
  260. {
  261. m_fMaxRange1 = 1400;
  262. }
  263.  
  264. BaseClass::Equip(pOwner);
  265. }
  266.  
  267. //-----------------------------------------------------------------------------
  268. // Purpose:
  269. //-----------------------------------------------------------------------------
  270. void CWeaponAR2::FireNPCPrimaryAttack(CBaseCombatCharacter* pOperator, Vector& vecShootOrigin, Vector& vecShootDir)
  271. {
  272. // FIXME: use the returned number of bullets to account for >10hz firerate
  273. WeaponSoundRealtime(SINGLE_NPC);
  274.  
  275. CSoundEnt::InsertSound(SOUND_COMBAT | SOUND_CONTEXT_GUNFIRE, pOperator->GetAbsOrigin(), SOUNDENT_VOLUME_MACHINEGUN, 0.2, pOperator, SOUNDENT_CHANNEL_WEAPON, pOperator->GetEnemy());
  276. pOperator->FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED,
  277. MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2, entindex(), 0);
  278.  
  279. pOperator->DoMuzzleFlash();
  280. m_iClip1 = m_iClip1 - 1;
  281. }
  282.  
  283. //-----------------------------------------------------------------------------
  284. // Purpose:
  285. //-----------------------------------------------------------------------------
  286. void CWeaponAR2::Operator_ForceNPCFire(CBaseCombatCharacter* pOperator, bool bSecondary)
  287. {
  288. // Ensure we have enough rounds in the clip
  289. m_iClip1++;
  290.  
  291. Vector vecShootOrigin, vecShootDir;
  292. QAngle angShootDir;
  293. GetAttachment(LookupAttachment("muzzle"), vecShootOrigin, angShootDir);
  294. AngleVectors(angShootDir, &vecShootDir);
  295. FireNPCPrimaryAttack(pOperator, vecShootOrigin, vecShootDir);
  296. }
  297.  
  298. //-----------------------------------------------------------------------------
  299. // Purpose:
  300. //-----------------------------------------------------------------------------
  301. void CWeaponAR2::Operator_HandleAnimEvent(animevent_t* pEvent, CBaseCombatCharacter* pOperator)
  302. {
  303. switch (pEvent->event)
  304. {
  305. case EVENT_WEAPON_SMG1:
  306. {
  307. Vector vecShootOrigin, vecShootDir;
  308. QAngle angDiscard;
  309.  
  310. // Support old style attachment point firing
  311. if ((pEvent->options == NULL) || (pEvent->options[0] == '\0') || (!pOperator->GetAttachment(pEvent->options, vecShootOrigin, angDiscard)))
  312. {
  313. vecShootOrigin = pOperator->Weapon_ShootPosition();
  314. }
  315.  
  316. CAI_BaseNPC* npc = pOperator->MyNPCPointer();
  317. ASSERT(npc != NULL);
  318. vecShootDir = npc->GetActualShootTrajectory(vecShootOrigin);
  319.  
  320. FireNPCPrimaryAttack(pOperator, vecShootOrigin, vecShootDir);
  321. }
  322. break;
  323.  
  324. /*//FIXME: Re-enable
  325. case EVENT_WEAPON_AR2_GRENADE:
  326. {
  327. CAI_BaseNPC *npc = pOperator->MyNPCPointer();
  328.  
  329. Vector vecShootOrigin, vecShootDir;
  330. vecShootOrigin = pOperator->Weapon_ShootPosition();
  331. vecShootDir = npc->GetShootEnemyDir( vecShootOrigin );
  332.  
  333. Vector vecThrow = m_vecTossVelocity;
  334.  
  335. CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecShootOrigin, vec3_angle, npc );
  336. pGrenade->SetAbsVelocity( vecThrow );
  337. pGrenade->SetLocalAngularVelocity( QAngle( 0, 400, 0 ) );
  338. pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY );
  339. pGrenade->m_hOwner = npc;
  340. pGrenade->m_pMyWeaponAR2 = this;
  341. pGrenade->SetDamage(sk_npc_dmg_ar2_grenade.GetFloat());
  342.  
  343. // FIXME: arrgg ,this is hard coded into the weapon???
  344. m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown.
  345.  
  346. m_iClip2--;
  347. }
  348. break;
  349. */
  350.  
  351. default:
  352. BaseClass::Operator_HandleAnimEvent(pEvent, pOperator);
  353. break;
  354. }
  355. }
  356.  
  357. //-----------------------------------------------------------------------------
  358. // Purpose:
  359. // Output : Activity
  360. //-----------------------------------------------------------------------------
  361. Activity CWeaponAR2::GetPrimaryAttackActivity(void)
  362. {
  363. if (m_nShotsFired < 2)
  364. return ACT_VM_PRIMARYATTACK;
  365.  
  366.  
  367.  
  368. return ACT_VM_PRIMARYATTACK;
  369. }
  370.  
  371. //-----------------------------------------------------------------------------
  372. //-----------------------------------------------------------------------------
  373. bool CWeaponAR2::Reload(void)
  374. {
  375. bool fRet;
  376. float fCacheTime = m_flNextSecondaryAttack;
  377.  
  378. fRet = DefaultReload(GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD);
  379. if (fRet)
  380. {
  381. // Undo whatever the reload process has done to our secondary
  382. // attack timer. We allow you to interrupt reloading to fire
  383. // a grenade.
  384. m_flNextSecondaryAttack = GetOwner()->m_flNextAttack = fCacheTime;
  385.  
  386. WeaponSound(RELOAD);
  387. }
  388.  
  389. return fRet;
  390. }
  391.  
  392. //-----------------------------------------------------------------------------
  393. // Purpose:
  394. //-----------------------------------------------------------------------------
  395. void CWeaponAR2::AddViewKick(void)
  396. {
  397. #define EASY_DAMPEN 0.5f
  398. #define MAX_VERTICAL_KICK 1.0f //Degrees
  399. #define SLIDE_LIMIT 2.0f //Seconds
  400.  
  401. //Get the view kick
  402. CBasePlayer* pPlayer = ToBasePlayer(GetOwner());
  403.  
  404. if (pPlayer == NULL)
  405. return;
  406.  
  407. DoMachineGunKick(pPlayer, EASY_DAMPEN, MAX_VERTICAL_KICK, m_fFireDuration, SLIDE_LIMIT);
  408. }
  409.  
  410.  
  411.  
  412. //-----------------------------------------------------------------------------
  413. const WeaponProficiencyInfo_t* CWeaponAR2::GetProficiencyValues()
  414. {
  415. static WeaponProficiencyInfo_t proficiencyTable[] =
  416. {
  417. { 7.0, 0.75 },
  418. { 5.00, 0.75 },
  419. { 10.0 / 3.0, 0.75 },
  420. { 5.0 / 3.0, 0.75 },
  421. { 1.00, 1.0 },
  422. };
  423.  
  424. COMPILE_TIME_ASSERT(ARRAYSIZE(proficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1);
  425.  
  426. return proficiencyTable;
  427. }
  428.  
Advertisement
Add Comment
Please, Sign In to add comment