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.

434 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //=============================================================================//
  9. #include "cbase.h"
  10. #include "util.h"
  11. #include "basehlcombatweapon.h"
  12. #include "player.h"
  13. #include "gamerules.h"
  14. #include "grenade_tripwire.h"
  15. #include "grenade_satchel.h"
  16. #include "entitylist.h"
  17. #include "weapon_tripwire.h"
  18. #include "npcevent.h"
  19. #include "in_buttons.h"
  20. #include "engine/IEngineSound.h"
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include "tier0/memdbgon.h"
  23. BEGIN_DATADESC( CWeapon_Tripwire )
  24. DEFINE_FIELD( m_bNeedReload, FIELD_BOOLEAN ),
  25. DEFINE_FIELD( m_bClearReload, FIELD_BOOLEAN ),
  26. DEFINE_FIELD( m_bAttachTripwire, FIELD_BOOLEAN ),
  27. // Function Pointers
  28. DEFINE_FUNCTION( TripwireTouch ),
  29. END_DATADESC()
  30. IMPLEMENT_SERVERCLASS_ST(CWeapon_Tripwire, DT_Weapon_Tripwire)
  31. END_SEND_TABLE()
  32. LINK_ENTITY_TO_CLASS( weapon_tripwire, CWeapon_Tripwire );
  33. // BUGBUG: Enable this when the script & resources are checked in.
  34. //PRECACHE_WEAPON_REGISTER(weapon_tripwire);
  35. acttable_t CWeapon_Tripwire::m_acttable[] =
  36. {
  37. { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_TRIPWIRE, true },
  38. };
  39. IMPLEMENT_ACTTABLE(CWeapon_Tripwire);
  40. void CWeapon_Tripwire::Spawn( )
  41. {
  42. UTIL_Remove(this);
  43. return;
  44. BaseClass::Spawn();
  45. Precache( );
  46. UTIL_SetSize(this, Vector(-4,-4,-2),Vector(4,4,2));
  47. FallInit();// get ready to fall down
  48. SetThink( NULL );
  49. // Give one piece of default ammo when first picked up
  50. m_iClip2 = 1;
  51. }
  52. void CWeapon_Tripwire::Precache( void )
  53. {
  54. BaseClass::Precache();
  55. PrecacheScriptSound( "Weapon_Tripwire.Attach" );
  56. UTIL_PrecacheOther( "npc_tripwire" );
  57. }
  58. //------------------------------------------------------------------------------
  59. // Purpose : Override to use tripwire's pickup touch function
  60. // Input :
  61. // Output :
  62. //------------------------------------------------------------------------------
  63. void CWeapon_Tripwire::SetPickupTouch( void )
  64. {
  65. SetTouch(TripwireTouch);
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Purpose: Override so give correct ammo
  69. // Input : pOther - the entity that touched me
  70. // Output :
  71. //-----------------------------------------------------------------------------
  72. void CWeapon_Tripwire::TripwireTouch( CBaseEntity *pOther )
  73. {
  74. // ---------------------------------------------------
  75. // First give weapon to touching entity if allowed
  76. // ---------------------------------------------------
  77. BaseClass::DefaultTouch(pOther);
  78. // ----------------------------------------------------
  79. // Give ammo if touching client
  80. // ----------------------------------------------------
  81. if (pOther->GetFlags() & FL_CLIENT)
  82. {
  83. // ------------------------------------------------
  84. // If already owned weapon of this type remove me
  85. // ------------------------------------------------
  86. CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pOther );
  87. CWeapon_Tripwire* oldWeapon = (CWeapon_Tripwire*)pBCC->Weapon_OwnsThisType( GetClassname() );
  88. if (oldWeapon != this)
  89. {
  90. UTIL_Remove( this );
  91. }
  92. else
  93. {
  94. pBCC->GiveAmmo( 1, m_iSecondaryAmmoType );
  95. SetThink(NULL);
  96. }
  97. }
  98. }
  99. //------------------------------------------------------------------------------
  100. // Purpose :
  101. // Input :
  102. // Output :
  103. //------------------------------------------------------------------------------
  104. bool CWeapon_Tripwire::Holster( CBaseCombatWeapon *pSwitchingTo )
  105. {
  106. SetThink(NULL);
  107. return BaseClass::Holster(pSwitchingTo);
  108. }
  109. //-----------------------------------------------------------------------------
  110. // Purpose: Tripwire has no reload, but must call weapon idle to update state
  111. // Input :
  112. // Output :
  113. //-----------------------------------------------------------------------------
  114. bool CWeapon_Tripwire::Reload( void )
  115. {
  116. WeaponIdle( );
  117. return true;
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Purpose:
  121. // Input :
  122. // Output :
  123. //-----------------------------------------------------------------------------
  124. void CWeapon_Tripwire::PrimaryAttack( void )
  125. {
  126. CBaseCombatCharacter *pOwner = GetOwner();
  127. if (!pOwner)
  128. {
  129. return;
  130. }
  131. if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0)
  132. {
  133. return;
  134. }
  135. if (CanAttachTripwire())
  136. {
  137. StartTripwireAttach();
  138. }
  139. }
  140. //-----------------------------------------------------------------------------
  141. // Purpose: Secondary attack does nothing
  142. // Input :
  143. // Output :
  144. //-----------------------------------------------------------------------------
  145. void CWeapon_Tripwire::SecondaryAttack( void )
  146. {
  147. }
  148. //-----------------------------------------------------------------------------
  149. // Purpose:
  150. // Input :
  151. // Output :
  152. //-----------------------------------------------------------------------------
  153. void CWeapon_Tripwire::TripwireAttach( void )
  154. {
  155. CBaseCombatCharacter *pOwner = GetOwner();
  156. if (!pOwner)
  157. {
  158. return;
  159. }
  160. m_bAttachTripwire = false;
  161. Vector vecSrc = pOwner->Weapon_ShootPosition();
  162. Vector vecAiming = pOwner->BodyDirection2D( );
  163. trace_t tr;
  164. UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
  165. if (tr.fraction < 1.0)
  166. {
  167. CBaseEntity *pEntity = tr.m_pEnt;
  168. if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR))
  169. {
  170. QAngle angles;
  171. VectorAngles(tr.plane.normal, angles);
  172. angles.x += 90;
  173. CBaseEntity *pEnt = CBaseEntity::Create( "npc_tripwire", tr.endpos + tr.plane.normal * 3, angles, NULL );
  174. CTripwireGrenade *pMine = (CTripwireGrenade *)pEnt;
  175. pMine->SetThrower( GetOwner() );
  176. pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
  177. EmitSound( "Weapon_Tripwire.Attach" );
  178. }
  179. }
  180. }
  181. //-----------------------------------------------------------------------------
  182. // Purpose:
  183. // Input :
  184. // Output :
  185. //-----------------------------------------------------------------------------
  186. void CWeapon_Tripwire::StartTripwireAttach( void )
  187. {
  188. // Only the player fires this way so we can cast
  189. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  190. if (!pPlayer)
  191. {
  192. return;
  193. }
  194. Vector vecSrc = pPlayer->Weapon_ShootPosition();
  195. Vector vecAiming = pPlayer->BodyDirection3D( );
  196. trace_t tr;
  197. UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr );
  198. if (tr.fraction < 1.0)
  199. {
  200. // ALERT( at_console, "hit %f\n", tr.flFraction );
  201. CBaseEntity *pEntity = tr.m_pEnt;
  202. if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR))
  203. {
  204. // player "shoot" animation
  205. pPlayer->SetAnimation( PLAYER_ATTACK1 );
  206. // -----------------------------------------
  207. // Play attach animation
  208. // -----------------------------------------
  209. SendWeaponAnim(ACT_SLAM_TRIPMINE_ATTACH);
  210. m_bNeedReload = true;
  211. m_bAttachTripwire = true;
  212. }
  213. else
  214. {
  215. // ALERT( at_console, "no deploy\n" );
  216. }
  217. }
  218. m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
  219. m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
  220. // SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
  221. }
  222. //-----------------------------------------------------------------------------
  223. // Purpose:
  224. // Input :
  225. // Output :
  226. //-----------------------------------------------------------------------------
  227. bool CWeapon_Tripwire::CanAttachTripwire( void )
  228. {
  229. CBaseCombatCharacter *pOwner = GetOwner();
  230. if (!pOwner)
  231. {
  232. return false;
  233. }
  234. Vector vecSrc = pOwner->Weapon_ShootPosition();
  235. Vector vecAiming = pOwner->BodyDirection2D( );
  236. trace_t tr;
  237. Vector vecEnd = vecSrc + (vecAiming * 42);
  238. UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
  239. if (tr.fraction < 1.0)
  240. {
  241. // Don't attach to a living creature
  242. if (tr.m_pEnt)
  243. {
  244. CBaseEntity *pEntity = tr.m_pEnt;
  245. CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity );
  246. if (pBCC)
  247. {
  248. return false;
  249. }
  250. }
  251. return true;
  252. }
  253. else
  254. {
  255. return false;
  256. }
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Purpose:
  260. // Input :
  261. // Output :
  262. //-----------------------------------------------------------------------------
  263. void CWeapon_Tripwire::ItemPostFrame( void )
  264. {
  265. CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
  266. if (!pOwner)
  267. {
  268. return;
  269. }
  270. if ((pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime))
  271. {
  272. SecondaryAttack();
  273. }
  274. else if (!m_bNeedReload && (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime))
  275. {
  276. PrimaryAttack();
  277. }
  278. // -----------------------
  279. // No buttons down
  280. // -----------------------
  281. else
  282. {
  283. WeaponIdle( );
  284. return;
  285. }
  286. }
  287. //-----------------------------------------------------------------------------
  288. // Purpose:
  289. // Input :
  290. // Output :
  291. //-----------------------------------------------------------------------------
  292. void CWeapon_Tripwire::WeaponIdle( void )
  293. {
  294. // Ready to switch animations?
  295. if ( HasWeaponIdleTimeElapsed() )
  296. {
  297. if (m_bClearReload)
  298. {
  299. m_bNeedReload = false;
  300. m_bClearReload = false;
  301. }
  302. CBaseCombatCharacter *pOwner = GetOwner();
  303. if (!pOwner)
  304. {
  305. return;
  306. }
  307. int iAnim = 0;
  308. if (m_bAttachTripwire)
  309. {
  310. TripwireAttach();
  311. iAnim = ACT_SLAM_TRIPMINE_ATTACH2;
  312. }
  313. else if (m_bNeedReload)
  314. {
  315. // If owner had ammo draw the correct tripwire type
  316. if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0)
  317. {
  318. iAnim = ACT_SLAM_TRIPMINE_DRAW;
  319. m_bClearReload = true;
  320. }
  321. else
  322. {
  323. pOwner->Weapon_Drop( this );
  324. UTIL_Remove(this);
  325. }
  326. }
  327. else if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0)
  328. {
  329. pOwner->Weapon_Drop( this );
  330. UTIL_Remove(this);
  331. }
  332. // If I don't need to reload just do the appropriate idle
  333. else
  334. {
  335. iAnim = ACT_SLAM_TRIPMINE_IDLE;
  336. }
  337. SendWeaponAnim( iAnim );
  338. }
  339. }
  340. bool CWeapon_Tripwire::Deploy( void )
  341. {
  342. CBaseCombatCharacter *pOwner = GetOwner();
  343. if (!pOwner)
  344. {
  345. return false;
  346. }
  347. SetModel( GetViewModel() );
  348. // ------------------------------
  349. // Pick the right draw animation
  350. // ------------------------------
  351. int iActivity;
  352. // If detonator is already armed
  353. m_bNeedReload = false;
  354. iActivity = ACT_SLAM_STICKWALL_ND_DRAW;
  355. return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), iActivity, (char*)GetAnimPrefix() );
  356. }
  357. //-----------------------------------------------------------------------------
  358. // Purpose: Constructor
  359. // Input :
  360. // Output :
  361. //-----------------------------------------------------------------------------
  362. CWeapon_Tripwire::CWeapon_Tripwire(void)
  363. {
  364. m_bNeedReload = true;
  365. m_bClearReload = false;
  366. m_bAttachTripwire = false;
  367. }