Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

984 lines
24 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: The various ammo types for HL2
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "player.h"
  8. #include "gamerules.h"
  9. #include "items.h"
  10. #include "ammodef.h"
  11. #include "eventlist.h"
  12. #include "npcevent.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. //---------------------------------------------------------
  16. // Applies ammo quantity scale.
  17. //---------------------------------------------------------
  18. int ITEM_GiveAmmo( CBasePlayer *pPlayer, float flCount, const char *pszAmmoName, bool bSuppressSound = false )
  19. {
  20. int iAmmoType = GetAmmoDef()->Index(pszAmmoName);
  21. if (iAmmoType == -1)
  22. {
  23. Msg("ERROR: Attempting to give unknown ammo type (%s)\n",pszAmmoName);
  24. return 0;
  25. }
  26. flCount *= g_pGameRules->GetAmmoQuantityScale(iAmmoType);
  27. // Don't give out less than 1 of anything.
  28. flCount = MAX( 1.0f, flCount );
  29. return pPlayer->GiveAmmo( flCount, iAmmoType, bSuppressSound );
  30. }
  31. // ========================================================================
  32. // >> BoxSRounds
  33. // ========================================================================
  34. class CItem_BoxSRounds : public CItem
  35. {
  36. public:
  37. DECLARE_CLASS( CItem_BoxSRounds, CItem );
  38. void Spawn( void )
  39. {
  40. Precache( );
  41. SetModel( "models/items/boxsrounds.mdl" );
  42. BaseClass::Spawn( );
  43. }
  44. void Precache( void )
  45. {
  46. PrecacheModel ("models/items/boxsrounds.mdl");
  47. }
  48. bool MyTouch( CBasePlayer *pPlayer )
  49. {
  50. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_PISTOL, "Pistol"))
  51. {
  52. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  53. {
  54. UTIL_Remove(this);
  55. }
  56. return true;
  57. }
  58. return false;
  59. }
  60. };
  61. LINK_ENTITY_TO_CLASS(item_box_srounds, CItem_BoxSRounds);
  62. LINK_ENTITY_TO_CLASS(item_ammo_pistol, CItem_BoxSRounds);
  63. // ========================================================================
  64. // >> LargeBoxSRounds
  65. // ========================================================================
  66. class CItem_LargeBoxSRounds : public CItem
  67. {
  68. public:
  69. DECLARE_CLASS( CItem_LargeBoxSRounds, CItem );
  70. void Spawn( void )
  71. {
  72. Precache( );
  73. SetModel( "models/items/boxsrounds.mdl" );
  74. BaseClass::Spawn( );
  75. }
  76. void Precache( void )
  77. {
  78. PrecacheModel ("models/items/boxsrounds.mdl");
  79. }
  80. bool MyTouch( CBasePlayer *pPlayer )
  81. {
  82. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_PISTOL_LARGE, "Pistol"))
  83. {
  84. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  85. {
  86. UTIL_Remove(this);
  87. }
  88. return true;
  89. }
  90. return false;
  91. }
  92. };
  93. LINK_ENTITY_TO_CLASS(item_large_box_srounds, CItem_LargeBoxSRounds);
  94. LINK_ENTITY_TO_CLASS(item_ammo_pistol_large, CItem_LargeBoxSRounds);
  95. // ========================================================================
  96. // >> BoxMRounds
  97. // ========================================================================
  98. class CItem_BoxMRounds : public CItem
  99. {
  100. public:
  101. DECLARE_CLASS( CItem_BoxMRounds, CItem );
  102. void Spawn( void )
  103. {
  104. Precache( );
  105. SetModel( "models/items/boxmrounds.mdl");
  106. BaseClass::Spawn( );
  107. }
  108. void Precache( void )
  109. {
  110. PrecacheModel ("models/items/boxmrounds.mdl");
  111. }
  112. bool MyTouch( CBasePlayer *pPlayer )
  113. {
  114. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_SMG1, "SMG1"))
  115. {
  116. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  117. {
  118. UTIL_Remove(this);
  119. }
  120. return true;
  121. }
  122. return false;
  123. }
  124. };
  125. LINK_ENTITY_TO_CLASS(item_box_mrounds, CItem_BoxMRounds);
  126. LINK_ENTITY_TO_CLASS(item_ammo_smg1, CItem_BoxMRounds);
  127. // ========================================================================
  128. // >> LargeBoxMRounds
  129. // ========================================================================
  130. class CItem_LargeBoxMRounds : public CItem
  131. {
  132. public:
  133. DECLARE_CLASS( CItem_LargeBoxMRounds, CItem );
  134. void Spawn( void )
  135. {
  136. Precache( );
  137. SetModel( "models/items/boxmrounds.mdl");
  138. BaseClass::Spawn( );
  139. }
  140. void Precache( void )
  141. {
  142. PrecacheModel ("models/items/boxmrounds.mdl");
  143. }
  144. bool MyTouch( CBasePlayer *pPlayer )
  145. {
  146. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_SMG1_LARGE, "SMG1"))
  147. {
  148. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  149. {
  150. UTIL_Remove(this);
  151. }
  152. return true;
  153. }
  154. return false;
  155. }
  156. };
  157. LINK_ENTITY_TO_CLASS(item_large_box_mrounds, CItem_LargeBoxMRounds);
  158. LINK_ENTITY_TO_CLASS(item_ammo_smg1_large, CItem_LargeBoxMRounds);
  159. // ========================================================================
  160. // >> BoxLRounds
  161. // ========================================================================
  162. class CItem_BoxLRounds : public CItem
  163. {
  164. public:
  165. DECLARE_CLASS( CItem_BoxLRounds, CItem );
  166. void Spawn( void )
  167. {
  168. Precache( );
  169. SetModel( "models/items/combine_rifle_cartridge01.mdl");
  170. BaseClass::Spawn( );
  171. }
  172. void Precache( void )
  173. {
  174. PrecacheModel ("models/items/combine_rifle_cartridge01.mdl");
  175. }
  176. bool MyTouch( CBasePlayer *pPlayer )
  177. {
  178. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_AR2, "AR2"))
  179. {
  180. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  181. {
  182. UTIL_Remove(this);
  183. }
  184. return true;
  185. }
  186. return false;
  187. }
  188. };
  189. LINK_ENTITY_TO_CLASS(item_box_lrounds, CItem_BoxLRounds);
  190. LINK_ENTITY_TO_CLASS(item_ammo_ar2, CItem_BoxLRounds);
  191. // ========================================================================
  192. // >> LargeBoxLRounds
  193. // ========================================================================
  194. class CItem_LargeBoxLRounds : public CItem
  195. {
  196. public:
  197. DECLARE_CLASS( CItem_LargeBoxLRounds, CItem );
  198. void Spawn( void )
  199. {
  200. Precache( );
  201. SetModel( "models/items/combine_rifle_cartridge01.mdl");
  202. BaseClass::Spawn( );
  203. }
  204. void Precache( void )
  205. {
  206. PrecacheModel ("models/items/combine_rifle_cartridge01.mdl");
  207. }
  208. bool MyTouch( CBasePlayer *pPlayer )
  209. {
  210. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_AR2_LARGE, "AR2"))
  211. {
  212. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  213. {
  214. UTIL_Remove(this);
  215. }
  216. return true;
  217. }
  218. return false;
  219. }
  220. };
  221. LINK_ENTITY_TO_CLASS(item_large_box_lrounds, CItem_LargeBoxLRounds);
  222. LINK_ENTITY_TO_CLASS(item_ammo_ar2_large, CItem_LargeBoxLRounds);
  223. // ========================================================================
  224. // >> CItem_Box357Rounds
  225. // ========================================================================
  226. class CItem_Box357Rounds : public CItem
  227. {
  228. public:
  229. DECLARE_CLASS( CItem_Box357Rounds, CItem );
  230. void Precache( void )
  231. {
  232. PrecacheModel ("models/items/357ammo.mdl");
  233. }
  234. void Spawn( void )
  235. {
  236. Precache( );
  237. SetModel( "models/items/357ammo.mdl");
  238. BaseClass::Spawn( );
  239. }
  240. bool MyTouch( CBasePlayer *pPlayer )
  241. {
  242. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_357, "357"))
  243. {
  244. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  245. {
  246. UTIL_Remove(this);
  247. }
  248. return true;
  249. }
  250. return false;
  251. }
  252. };
  253. LINK_ENTITY_TO_CLASS(item_ammo_357, CItem_Box357Rounds);
  254. // ========================================================================
  255. // >> CItem_LargeBox357Rounds
  256. // ========================================================================
  257. class CItem_LargeBox357Rounds : public CItem
  258. {
  259. public:
  260. DECLARE_CLASS( CItem_LargeBox357Rounds, CItem );
  261. void Precache( void )
  262. {
  263. PrecacheModel ("models/items/357ammobox.mdl");
  264. }
  265. void Spawn( void )
  266. {
  267. Precache( );
  268. SetModel( "models/items/357ammobox.mdl");
  269. BaseClass::Spawn( );
  270. }
  271. bool MyTouch( CBasePlayer *pPlayer )
  272. {
  273. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_357_LARGE, "357"))
  274. {
  275. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  276. {
  277. UTIL_Remove(this);
  278. }
  279. return true;
  280. }
  281. return false;
  282. }
  283. };
  284. LINK_ENTITY_TO_CLASS(item_ammo_357_large, CItem_LargeBox357Rounds);
  285. // ========================================================================
  286. // >> CItem_BoxXBowRounds
  287. // ========================================================================
  288. class CItem_BoxXBowRounds : public CItem
  289. {
  290. public:
  291. DECLARE_CLASS( CItem_BoxXBowRounds, CItem );
  292. void Precache( void )
  293. {
  294. PrecacheModel ("models/items/crossbowrounds.mdl");
  295. }
  296. void Spawn( void )
  297. {
  298. Precache( );
  299. SetModel( "models/items/crossbowrounds.mdl");
  300. BaseClass::Spawn( );
  301. }
  302. bool MyTouch( CBasePlayer *pPlayer )
  303. {
  304. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_CROSSBOW, "XBowBolt" ))
  305. {
  306. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  307. {
  308. UTIL_Remove(this);
  309. }
  310. return true;
  311. }
  312. return false;
  313. }
  314. };
  315. LINK_ENTITY_TO_CLASS(item_ammo_crossbow, CItem_BoxXBowRounds);
  316. // ========================================================================
  317. // >> FlareRound
  318. // ========================================================================
  319. class CItem_FlareRound : public CItem
  320. {
  321. public:
  322. DECLARE_CLASS( CItem_FlareRound, CItem );
  323. void Spawn( void )
  324. {
  325. Precache( );
  326. SetModel( "models/items/flare.mdl");
  327. BaseClass::Spawn( );
  328. }
  329. void Precache( void )
  330. {
  331. PrecacheModel ("models/items/flare.mdl");
  332. }
  333. bool MyTouch( CBasePlayer *pPlayer )
  334. {
  335. if (ITEM_GiveAmmo( pPlayer, 1, "FlareRound"))
  336. {
  337. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  338. {
  339. UTIL_Remove(this);
  340. }
  341. return true;
  342. }
  343. return false;
  344. }
  345. };
  346. LINK_ENTITY_TO_CLASS(item_flare_round, CItem_FlareRound);
  347. // ========================================================================
  348. // >> BoxFlareRounds
  349. // ========================================================================
  350. #define SIZE_BOX_FLARE_ROUNDS 5
  351. class CItem_BoxFlareRounds : public CItem
  352. {
  353. public:
  354. DECLARE_CLASS( CItem_BoxFlareRounds, CItem );
  355. void Spawn( void )
  356. {
  357. Precache( );
  358. SetModel( "models/items/boxflares.mdl");
  359. BaseClass::Spawn( );
  360. }
  361. void Precache( void )
  362. {
  363. PrecacheModel ("models/items/boxflares.mdl");
  364. }
  365. bool MyTouch( CBasePlayer *pPlayer )
  366. {
  367. if (ITEM_GiveAmmo( pPlayer, SIZE_BOX_FLARE_ROUNDS, "FlareRound"))
  368. {
  369. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  370. {
  371. UTIL_Remove(this);
  372. }
  373. return true;
  374. }
  375. return false;
  376. }
  377. };
  378. LINK_ENTITY_TO_CLASS(item_box_flare_rounds, CItem_BoxFlareRounds);
  379. // ========================================================================
  380. // RPG Round
  381. // ========================================================================
  382. class CItem_RPG_Round : public CItem
  383. {
  384. public:
  385. DECLARE_CLASS( CItem_RPG_Round, CItem );
  386. void Spawn( void )
  387. {
  388. Precache( );
  389. SetModel( "models/weapons/w_missile_closed.mdl");
  390. BaseClass::Spawn( );
  391. }
  392. void Precache( void )
  393. {
  394. PrecacheModel ("models/weapons/w_missile_closed.mdl");
  395. }
  396. bool MyTouch( CBasePlayer *pPlayer )
  397. {
  398. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_RPG_ROUND, "RPG_Round"))
  399. {
  400. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  401. {
  402. UTIL_Remove(this);
  403. }
  404. return true;
  405. }
  406. return false;
  407. }
  408. };
  409. LINK_ENTITY_TO_CLASS( item_ml_grenade, CItem_RPG_Round );
  410. LINK_ENTITY_TO_CLASS( item_rpg_round, CItem_RPG_Round );
  411. // ========================================================================
  412. // >> AR2_Grenade
  413. // ========================================================================
  414. class CItem_AR2_Grenade : public CItem
  415. {
  416. public:
  417. DECLARE_CLASS( CItem_AR2_Grenade, CItem );
  418. void Spawn( void )
  419. {
  420. Precache( );
  421. SetModel( "models/items/ar2_grenade.mdl");
  422. BaseClass::Spawn( );
  423. }
  424. void Precache( void )
  425. {
  426. PrecacheModel ("models/items/ar2_grenade.mdl");
  427. }
  428. bool MyTouch( CBasePlayer *pPlayer )
  429. {
  430. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_SMG1_GRENADE, "SMG1_Grenade"))
  431. {
  432. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  433. {
  434. UTIL_Remove(this);
  435. }
  436. return true;
  437. }
  438. return false;
  439. }
  440. };
  441. LINK_ENTITY_TO_CLASS(item_ar2_grenade, CItem_AR2_Grenade);
  442. LINK_ENTITY_TO_CLASS(item_ammo_smg1_grenade, CItem_AR2_Grenade);
  443. // ========================================================================
  444. // >> BoxSniperRounds
  445. // ========================================================================
  446. #define SIZE_BOX_SNIPER_ROUNDS 10
  447. class CItem_BoxSniperRounds : public CItem
  448. {
  449. public:
  450. DECLARE_CLASS( CItem_BoxSniperRounds, CItem );
  451. void Spawn( void )
  452. {
  453. Precache( );
  454. SetModel( "models/items/boxsniperrounds.mdl");
  455. BaseClass::Spawn( );
  456. }
  457. void Precache( void )
  458. {
  459. PrecacheModel ("models/items/boxsniperrounds.mdl");
  460. }
  461. bool MyTouch( CBasePlayer *pPlayer )
  462. {
  463. if (ITEM_GiveAmmo( pPlayer, SIZE_BOX_SNIPER_ROUNDS, "SniperRound"))
  464. {
  465. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  466. {
  467. UTIL_Remove(this);
  468. }
  469. return true;
  470. }
  471. return false;
  472. }
  473. };
  474. LINK_ENTITY_TO_CLASS(item_box_sniper_rounds, CItem_BoxSniperRounds);
  475. // ========================================================================
  476. // >> BoxBuckshot
  477. // ========================================================================
  478. class CItem_BoxBuckshot : public CItem
  479. {
  480. public:
  481. DECLARE_CLASS( CItem_BoxBuckshot, CItem );
  482. void Spawn( void )
  483. {
  484. Precache( );
  485. SetModel( "models/items/boxbuckshot.mdl");
  486. BaseClass::Spawn( );
  487. }
  488. void Precache( void )
  489. {
  490. PrecacheModel ("models/items/boxbuckshot.mdl");
  491. }
  492. bool MyTouch( CBasePlayer *pPlayer )
  493. {
  494. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_BUCKSHOT, "Buckshot"))
  495. {
  496. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  497. {
  498. UTIL_Remove(this);
  499. }
  500. return true;
  501. }
  502. return false;
  503. }
  504. };
  505. LINK_ENTITY_TO_CLASS(item_box_buckshot, CItem_BoxBuckshot);
  506. // ========================================================================
  507. // >> CItem_AR2AltFireRound
  508. // ========================================================================
  509. class CItem_AR2AltFireRound : public CItem
  510. {
  511. public:
  512. DECLARE_CLASS( CItem_AR2AltFireRound, CItem );
  513. void Precache( void )
  514. {
  515. PrecacheParticleSystem( "combineball" );
  516. PrecacheModel ("models/items/combine_rifle_ammo01.mdl");
  517. }
  518. void Spawn( void )
  519. {
  520. Precache( );
  521. SetModel( "models/items/combine_rifle_ammo01.mdl");
  522. BaseClass::Spawn( );
  523. }
  524. bool MyTouch( CBasePlayer *pPlayer )
  525. {
  526. if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_AR2_ALTFIRE, "AR2AltFire" ) )
  527. {
  528. if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
  529. {
  530. UTIL_Remove(this);
  531. }
  532. return true;
  533. }
  534. return false;
  535. }
  536. };
  537. LINK_ENTITY_TO_CLASS( item_ammo_ar2_altfire, CItem_AR2AltFireRound );
  538. // ==================================================================
  539. // Ammo crate which will supply infinite ammo of the specified type
  540. // ==================================================================
  541. // Ammo types
  542. enum
  543. {
  544. AMMOCRATE_SMALL_ROUNDS,
  545. AMMOCRATE_MEDIUM_ROUNDS,
  546. AMMOCRATE_LARGE_ROUNDS,
  547. AMMOCRATE_RPG_ROUNDS,
  548. AMMOCRATE_BUCKSHOT,
  549. AMMOCRATE_GRENADES,
  550. AMMOCRATE_357,
  551. AMMOCRATE_CROSSBOW,
  552. AMMOCRATE_AR2_ALTFIRE,
  553. AMMOCRATE_SMG_ALTFIRE,
  554. NUM_AMMO_CRATE_TYPES,
  555. };
  556. // Ammo crate
  557. class CItem_AmmoCrate : public CBaseAnimating
  558. {
  559. public:
  560. DECLARE_CLASS( CItem_AmmoCrate, CBaseAnimating );
  561. void Spawn( void );
  562. void Precache( void );
  563. bool CreateVPhysics( void );
  564. virtual void HandleAnimEvent( animevent_t *pEvent );
  565. void SetupCrate( void );
  566. void OnRestore( void );
  567. //FIXME: May not want to have this used in a radius
  568. int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | (FCAP_IMPULSE_USE|FCAP_USE_IN_RADIUS)); };
  569. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  570. void InputKill( inputdata_t &data );
  571. void CrateThink( void );
  572. virtual int OnTakeDamage( const CTakeDamageInfo &info );
  573. protected:
  574. int m_nAmmoType;
  575. int m_nAmmoIndex;
  576. static const char *m_lpzModelNames[NUM_AMMO_CRATE_TYPES];
  577. static const char *m_lpzAmmoNames[NUM_AMMO_CRATE_TYPES];
  578. static int m_nAmmoAmounts[NUM_AMMO_CRATE_TYPES];
  579. static const char *m_pGiveWeapon[NUM_AMMO_CRATE_TYPES];
  580. float m_flCloseTime;
  581. COutputEvent m_OnUsed;
  582. CHandle< CBasePlayer > m_hActivator;
  583. DECLARE_DATADESC();
  584. };
  585. LINK_ENTITY_TO_CLASS( item_ammo_crate, CItem_AmmoCrate );
  586. BEGIN_DATADESC( CItem_AmmoCrate )
  587. DEFINE_KEYFIELD( m_nAmmoType, FIELD_INTEGER, "AmmoType" ),
  588. DEFINE_FIELD( m_flCloseTime, FIELD_FLOAT ),
  589. DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ),
  590. // These can be recreated
  591. //DEFINE_FIELD( m_nAmmoIndex, FIELD_INTEGER ),
  592. //DEFINE_FIELD( m_lpzModelNames, FIELD_ ),
  593. //DEFINE_FIELD( m_lpzAmmoNames, FIELD_ ),
  594. //DEFINE_FIELD( m_nAmmoAmounts, FIELD_INTEGER ),
  595. DEFINE_OUTPUT( m_OnUsed, "OnUsed" ),
  596. DEFINE_INPUTFUNC( FIELD_VOID, "Kill", InputKill ),
  597. DEFINE_THINKFUNC( CrateThink ),
  598. END_DATADESC()
  599. //-----------------------------------------------------------------------------
  600. // Animation events.
  601. //-----------------------------------------------------------------------------
  602. // Models names
  603. const char *CItem_AmmoCrate::m_lpzModelNames[NUM_AMMO_CRATE_TYPES] =
  604. {
  605. "models/items/ammocrate_pistol.mdl", // Small rounds
  606. "models/items/ammocrate_smg1.mdl", // Medium rounds
  607. "models/items/ammocrate_ar2.mdl", // Large rounds
  608. "models/items/ammocrate_rockets.mdl", // RPG rounds
  609. "models/items/ammocrate_buckshot.mdl", // Buckshot
  610. "models/items/ammocrate_grenade.mdl", // Grenades
  611. "models/items/ammocrate_smg1.mdl", // 357
  612. "models/items/ammocrate_smg1.mdl", // Crossbow
  613. //FIXME: This model is incorrect!
  614. "models/items/ammocrate_ar2.mdl", // Combine Ball
  615. "models/items/ammocrate_smg2.mdl", // smg grenade
  616. };
  617. // Ammo type names
  618. const char *CItem_AmmoCrate::m_lpzAmmoNames[NUM_AMMO_CRATE_TYPES] =
  619. {
  620. "Pistol",
  621. "SMG1",
  622. "AR2",
  623. "RPG_Round",
  624. "Buckshot",
  625. "Grenade",
  626. "357",
  627. "XBowBolt",
  628. "AR2AltFire",
  629. "SMG1_Grenade",
  630. };
  631. // Ammo amount given per +use
  632. int CItem_AmmoCrate::m_nAmmoAmounts[NUM_AMMO_CRATE_TYPES] =
  633. {
  634. 300, // Pistol
  635. 300, // SMG1
  636. 300, // AR2
  637. 3, // RPG rounds
  638. 120, // Buckshot
  639. 5, // Grenades
  640. 50, // 357
  641. 50, // Crossbow
  642. 3, // AR2 alt-fire
  643. 5,
  644. };
  645. const char *CItem_AmmoCrate::m_pGiveWeapon[NUM_AMMO_CRATE_TYPES] =
  646. {
  647. NULL, // Pistol
  648. NULL, // SMG1
  649. NULL, // AR2
  650. NULL, // RPG rounds
  651. NULL, // Buckshot
  652. "weapon_frag", // Grenades
  653. NULL, // 357
  654. NULL, // Crossbow
  655. NULL, // AR2 alt-fire
  656. NULL, // SMG alt-fire
  657. };
  658. #define AMMO_CRATE_CLOSE_DELAY 1.5f
  659. //-----------------------------------------------------------------------------
  660. // Purpose:
  661. //-----------------------------------------------------------------------------
  662. void CItem_AmmoCrate::Spawn( void )
  663. {
  664. Precache();
  665. BaseClass::Spawn();
  666. SetModel( STRING( GetModelName() ) );
  667. SetMoveType( MOVETYPE_NONE );
  668. SetSolid( SOLID_VPHYSICS );
  669. CreateVPhysics();
  670. ResetSequence( LookupSequence( "Idle" ) );
  671. SetBodygroup( 1, true );
  672. m_flCloseTime = gpGlobals->curtime;
  673. m_flAnimTime = gpGlobals->curtime;
  674. m_flPlaybackRate = 0.0;
  675. SetCycle( 0 );
  676. m_takedamage = DAMAGE_EVENTS_ONLY;
  677. }
  678. //------------------------------------------------------------------------------
  679. // Purpose:
  680. //------------------------------------------------------------------------------
  681. bool CItem_AmmoCrate::CreateVPhysics( void )
  682. {
  683. return ( VPhysicsInitStatic() != NULL );
  684. }
  685. //-----------------------------------------------------------------------------
  686. // Purpose:
  687. //-----------------------------------------------------------------------------
  688. void CItem_AmmoCrate::Precache( void )
  689. {
  690. SetupCrate();
  691. PrecacheModel( STRING( GetModelName() ) );
  692. PrecacheScriptSound( "AmmoCrate.Open" );
  693. PrecacheScriptSound( "AmmoCrate.Close" );
  694. }
  695. //-----------------------------------------------------------------------------
  696. // Purpose:
  697. //-----------------------------------------------------------------------------
  698. void CItem_AmmoCrate::SetupCrate( void )
  699. {
  700. SetModelName( AllocPooledString( m_lpzModelNames[m_nAmmoType] ) );
  701. m_nAmmoIndex = GetAmmoDef()->Index( m_lpzAmmoNames[m_nAmmoType] );
  702. }
  703. //-----------------------------------------------------------------------------
  704. // Purpose:
  705. //-----------------------------------------------------------------------------
  706. void CItem_AmmoCrate::OnRestore( void )
  707. {
  708. BaseClass::OnRestore();
  709. // Restore our internal state
  710. SetupCrate();
  711. }
  712. //-----------------------------------------------------------------------------
  713. // Purpose:
  714. // Input : *pActivator -
  715. // *pCaller -
  716. // useType -
  717. // value -
  718. //-----------------------------------------------------------------------------
  719. void CItem_AmmoCrate::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  720. {
  721. CBasePlayer *pPlayer = ToBasePlayer( pActivator );
  722. if ( pPlayer == NULL )
  723. return;
  724. m_OnUsed.FireOutput( pActivator, this );
  725. int iSequence = LookupSequence( "Open" );
  726. // See if we're not opening already
  727. if ( GetSequence() != iSequence )
  728. {
  729. Vector mins, maxs;
  730. trace_t tr;
  731. CollisionProp()->WorldSpaceAABB( &mins, &maxs );
  732. Vector vOrigin = GetAbsOrigin();
  733. vOrigin.z += ( maxs.z - mins.z );
  734. mins = (mins - GetAbsOrigin()) * 0.2f;
  735. maxs = (maxs - GetAbsOrigin()) * 0.2f;
  736. mins.z = ( GetAbsOrigin().z - vOrigin.z );
  737. UTIL_TraceHull( vOrigin, vOrigin, mins, maxs, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
  738. if ( tr.startsolid || tr.allsolid )
  739. return;
  740. m_hActivator = pPlayer;
  741. // Animate!
  742. ResetSequence( iSequence );
  743. // Make sound
  744. CPASAttenuationFilter sndFilter( this, "AmmoCrate.Open" );
  745. EmitSound( sndFilter, entindex(), "AmmoCrate.Open" );
  746. // Start thinking to make it return
  747. SetThink( &CItem_AmmoCrate::CrateThink );
  748. SetNextThink( gpGlobals->curtime + 0.1f );
  749. }
  750. // Don't close again for two seconds
  751. m_flCloseTime = gpGlobals->curtime + AMMO_CRATE_CLOSE_DELAY;
  752. }
  753. //-----------------------------------------------------------------------------
  754. // Purpose: allows the crate to open up when hit by a crowbar
  755. //-----------------------------------------------------------------------------
  756. int CItem_AmmoCrate::OnTakeDamage( const CTakeDamageInfo &info )
  757. {
  758. // if it's the player hitting us with a crowbar, open up
  759. CBasePlayer *player = ToBasePlayer(info.GetAttacker());
  760. if (player)
  761. {
  762. CBaseCombatWeapon *weapon = player->GetActiveWeapon();
  763. if (weapon && !stricmp(weapon->GetName(), "weapon_crowbar"))
  764. {
  765. // play the normal use sound
  766. player->EmitSound( "HL2Player.Use" );
  767. // open the crate
  768. Use(info.GetAttacker(), info.GetAttacker(), USE_TOGGLE, 0.0f);
  769. }
  770. }
  771. // don't actually take any damage
  772. return 0;
  773. }
  774. //-----------------------------------------------------------------------------
  775. // Purpose: Catches the monster-specific messages that occur when tagged
  776. // animation frames are played.
  777. // Input : *pEvent -
  778. //-----------------------------------------------------------------------------
  779. void CItem_AmmoCrate::HandleAnimEvent( animevent_t *pEvent )
  780. {
  781. if ( pEvent->event == AE_AMMOCRATE_PICKUP_AMMO )
  782. {
  783. if ( m_hActivator )
  784. {
  785. if ( m_pGiveWeapon[m_nAmmoType] && !m_hActivator->Weapon_OwnsThisType( m_pGiveWeapon[m_nAmmoType] ) )
  786. {
  787. CBaseEntity *pEntity = CreateEntityByName( m_pGiveWeapon[m_nAmmoType] );
  788. CBaseCombatWeapon *pWeapon = dynamic_cast<CBaseCombatWeapon*>(pEntity);
  789. if ( pWeapon )
  790. {
  791. pWeapon->SetAbsOrigin( m_hActivator->GetAbsOrigin() );
  792. pWeapon->m_iPrimaryAmmoType = 0;
  793. pWeapon->m_iSecondaryAmmoType = 0;
  794. pWeapon->Spawn();
  795. if ( !m_hActivator->BumpWeapon( pWeapon ) )
  796. {
  797. UTIL_Remove( pEntity );
  798. }
  799. else
  800. {
  801. SetBodygroup( 1, false );
  802. }
  803. }
  804. }
  805. if ( m_hActivator->GiveAmmo( m_nAmmoAmounts[m_nAmmoType], m_nAmmoIndex ) != 0 )
  806. {
  807. SetBodygroup( 1, false );
  808. }
  809. m_hActivator = NULL;
  810. }
  811. return;
  812. }
  813. BaseClass::HandleAnimEvent( pEvent );
  814. }
  815. //-----------------------------------------------------------------------------
  816. // Purpose:
  817. //-----------------------------------------------------------------------------
  818. void CItem_AmmoCrate::CrateThink( void )
  819. {
  820. StudioFrameAdvance();
  821. DispatchAnimEvents( this );
  822. SetNextThink( gpGlobals->curtime + 0.1f );
  823. // Start closing if we're not already
  824. if ( GetSequence() != LookupSequence( "Close" ) )
  825. {
  826. // Not ready to close?
  827. if ( m_flCloseTime <= gpGlobals->curtime )
  828. {
  829. m_hActivator = NULL;
  830. ResetSequence( LookupSequence( "Close" ) );
  831. }
  832. }
  833. else
  834. {
  835. // See if we're fully closed
  836. if ( IsSequenceFinished() )
  837. {
  838. // Stop thinking
  839. SetThink( NULL );
  840. CPASAttenuationFilter sndFilter( this, "AmmoCrate.Close" );
  841. EmitSound( sndFilter, entindex(), "AmmoCrate.Close" );
  842. // FIXME: We're resetting the sequence here
  843. // but setting Think to NULL will cause this to never have
  844. // StudioFrameAdvance called. What are the consequences of that?
  845. ResetSequence( LookupSequence( "Idle" ) );
  846. SetBodygroup( 1, true );
  847. }
  848. }
  849. }
  850. //-----------------------------------------------------------------------------
  851. // Purpose:
  852. // Input : &data -
  853. //-----------------------------------------------------------------------------
  854. void CItem_AmmoCrate::InputKill( inputdata_t &data )
  855. {
  856. UTIL_Remove( this );
  857. }