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.

348 lines
8.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //
  4. //=============================================================================
  5. #include "cbase.h"
  6. #include "tf_weapon_revolver.h"
  7. #include "tf_fx_shared.h"
  8. #include "datamap.h"
  9. #include "tf_weaponbase_gun.h"
  10. // Client specific.
  11. #ifdef CLIENT_DLL
  12. #include "c_tf_player.h"
  13. // Server specific.
  14. #else
  15. #include "tf_player.h"
  16. #endif
  17. //=============================================================================
  18. //
  19. // Weapon Revolver tables.
  20. //
  21. IMPLEMENT_NETWORKCLASS_ALIASED( TFRevolver, DT_WeaponRevolver )
  22. BEGIN_NETWORK_TABLE( CTFRevolver, DT_WeaponRevolver )
  23. END_NETWORK_TABLE()
  24. #ifdef CLIENT_DLL
  25. BEGIN_PREDICTION_DATA( CTFRevolver )
  26. DEFINE_PRED_FIELD( m_flLastAccuracyCheck, FIELD_FLOAT, 0 ),
  27. END_PREDICTION_DATA()
  28. #endif
  29. LINK_ENTITY_TO_CLASS( tf_weapon_revolver, CTFRevolver );
  30. PRECACHE_WEAPON_REGISTER( tf_weapon_revolver );
  31. // Server specific.
  32. #ifndef CLIENT_DLL
  33. BEGIN_DATADESC( CTFRevolver )
  34. END_DATADESC()
  35. #endif
  36. #ifdef STAGING_ONLY
  37. CREATE_SIMPLE_WEAPON_TABLE( TFRevolver_Secondary, tf_weapon_revolver_secondary )
  38. #endif
  39. //=============================================================================
  40. //
  41. // Weapon Revolver functions.
  42. //
  43. CTFRevolver::CTFRevolver()
  44. {
  45. m_flLastAccuracyCheck = 0.f;
  46. m_flAccuracyCheckTime = 0.f;
  47. }
  48. //-----------------------------------------------------------------------------
  49. // Purpose:
  50. //-----------------------------------------------------------------------------
  51. bool CTFRevolver::DefaultReload( int iClipSize1, int iClipSize2, int iActivity )
  52. {
  53. // The the owning local player.
  54. CTFPlayer *pPlayer = GetTFPlayerOwner();
  55. if ( !pPlayer )
  56. return false;
  57. if ( pPlayer->IsPlayerClass( TF_CLASS_SPY ) )
  58. {
  59. if ( pPlayer->m_Shared.InCond( TF_COND_STEALTHED ) )
  60. {
  61. return false;
  62. }
  63. }
  64. if ( pPlayer->m_Shared.IsFeignDeathReady() )
  65. return false; // Can't reload if our feign death arm is up.
  66. return BaseClass::DefaultReload( iClipSize1, iClipSize2, iActivity );
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose:
  70. //-----------------------------------------------------------------------------
  71. int CTFRevolver::GetDamageType( void ) const
  72. {
  73. if ( CanHeadshot() && (gpGlobals->curtime - m_flLastAccuracyCheck > 1.f) )
  74. {
  75. int iDamageType = BaseClass::GetDamageType() | DMG_USE_HITLOCATIONS;
  76. return iDamageType;
  77. }
  78. return BaseClass::GetDamageType();
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Purpose:
  82. //-----------------------------------------------------------------------------
  83. bool CTFRevolver::CanFireCriticalShot( bool bIsHeadshot )
  84. {
  85. if ( !BaseClass::CanFireCriticalShot( bIsHeadshot ) )
  86. return false;
  87. CTFPlayer *pPlayer = GetTFPlayerOwner();
  88. if ( pPlayer && pPlayer->m_Shared.IsCritBoosted() )
  89. return true;
  90. // can only fire a crit shot if this is a headshot, unless we're critboosted
  91. if ( !bIsHeadshot )
  92. {
  93. // Base revolver still randomly crits. Ambassador doesn't.
  94. return !CanHeadshot();
  95. }
  96. return true;
  97. }
  98. //-----------------------------------------------------------------------------
  99. // Purpose:
  100. //-----------------------------------------------------------------------------
  101. void CTFRevolver::PrimaryAttack( void )
  102. {
  103. // Check for ammunition.
  104. if ( m_iClip1 <= 0 && m_iClip1 != -1 )
  105. return;
  106. // Are we capable of firing again?
  107. if ( m_flNextPrimaryAttack > gpGlobals->curtime )
  108. return;
  109. // Get the player owning the weapon.
  110. CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() );
  111. if ( !pPlayer )
  112. return;
  113. if ( !CanAttack() )
  114. return;
  115. BaseClass::PrimaryAttack();
  116. if ( HasLastShotCritical() )
  117. {
  118. pPlayer->m_Shared.AddCond( TF_COND_CRITBOOSTED );
  119. }
  120. else
  121. {
  122. int iAttr = 0;
  123. CALL_ATTRIB_HOOK_INT( iAttr, last_shot_crits );
  124. if ( iAttr )
  125. {
  126. pPlayer->m_Shared.RemoveCond( TF_COND_CRITBOOSTED );
  127. }
  128. }
  129. m_flLastAccuracyCheck = gpGlobals->curtime;
  130. if ( SapperKillsCollectCrits() )
  131. {
  132. // Do this after the attack, so that we know if we are doing custom damage
  133. CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() );
  134. if ( pOwner )
  135. {
  136. int iRevengeCrits = pOwner->m_Shared.GetRevengeCrits();
  137. if ( iRevengeCrits > 0 )
  138. {
  139. pOwner->m_Shared.SetRevengeCrits( iRevengeCrits-1 );
  140. }
  141. }
  142. }
  143. #ifdef GAME_DLL
  144. // Lower bonus for each attack
  145. int iExtraDamageOnHitPenalty = 0;
  146. CALL_ATTRIB_HOOK_INT( iExtraDamageOnHitPenalty, extra_damage_on_hit_penalty );
  147. if ( iExtraDamageOnHitPenalty )
  148. {
  149. int iDecaps = pPlayer->m_Shared.GetDecapitations();
  150. pPlayer->m_Shared.SetDecapitations( Max( 0, iDecaps - iExtraDamageOnHitPenalty ) );
  151. }
  152. #endif
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Purpose:
  156. //-----------------------------------------------------------------------------
  157. float CTFRevolver::GetWeaponSpread( void )
  158. {
  159. float fSpread = BaseClass::GetWeaponSpread();
  160. if ( CanHeadshot() )
  161. {
  162. // We are highly accurate for our first shot.
  163. float flTimeSinceCheck = gpGlobals->curtime - m_flLastAccuracyCheck;
  164. fSpread = RemapValClamped( flTimeSinceCheck, 1.0f, 0.5f, 0.0f, fSpread+0.0f );
  165. }
  166. return fSpread;
  167. }
  168. #ifdef CLIENT_DLL
  169. //-----------------------------------------------------------------------------
  170. // Purpose:
  171. //-----------------------------------------------------------------------------
  172. void CTFRevolver::GetWeaponCrosshairScale( float &flScale )
  173. {
  174. C_TFPlayer* pTFPlayer = ToTFPlayer( GetOwner() );
  175. if ( !pTFPlayer )
  176. return;
  177. if ( CanHeadshot() )
  178. {
  179. float curtime = pTFPlayer->GetFinalPredictedTime() + ( gpGlobals->interpolation_amount * TICK_INTERVAL );
  180. float flTimeSinceCheck = curtime - m_flLastAccuracyCheck;
  181. flScale = RemapValClamped( flTimeSinceCheck, 1.0f, 0.5f, 0.75f, 2.5f );
  182. }
  183. else
  184. {
  185. BaseClass::GetWeaponCrosshairScale( flScale );
  186. }
  187. }
  188. #endif
  189. //-----------------------------------------------------------------------------
  190. // Purpose:
  191. //-----------------------------------------------------------------------------
  192. int CTFRevolver::GetCount( void )
  193. {
  194. CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() );
  195. if ( !pOwner )
  196. return 0;
  197. if ( SapperKillsCollectCrits() )
  198. {
  199. return pOwner->m_Shared.GetRevengeCrits();
  200. }
  201. int iExtraDamageOnHit = 0;
  202. CALL_ATTRIB_HOOK_INT( iExtraDamageOnHit, extra_damage_on_hit );
  203. if ( iExtraDamageOnHit )
  204. {
  205. return Min( 200, pOwner->m_Shared.GetDecapitations() );
  206. }
  207. return 0;
  208. }
  209. //-----------------------------------------------------------------------------
  210. const char* CTFRevolver::GetEffectLabelText( void )
  211. {
  212. int iExtraDamageOnHit = 0;
  213. CALL_ATTRIB_HOOK_INT( iExtraDamageOnHit, extra_damage_on_hit );
  214. if ( iExtraDamageOnHit )
  215. {
  216. return "#TF_BONUS";
  217. }
  218. return "#TF_CRITS";
  219. }
  220. //-----------------------------------------------------------------------------
  221. // Purpose:
  222. //-----------------------------------------------------------------------------
  223. bool CTFRevolver::Holster( CBaseCombatWeapon *pSwitchingTo )
  224. {
  225. #ifdef GAME_DLL
  226. CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() );
  227. if ( pOwner )
  228. {
  229. if ( SapperKillsCollectCrits() )
  230. {
  231. if ( pOwner->m_Shared.GetRevengeCrits() )
  232. {
  233. pOwner->m_Shared.RemoveCond( TF_COND_CRITBOOSTED );
  234. }
  235. }
  236. if ( HasLastShotCritical() )
  237. {
  238. pOwner->m_Shared.RemoveCond( TF_COND_CRITBOOSTED );
  239. }
  240. }
  241. #endif
  242. return BaseClass::Holster( pSwitchingTo );
  243. }
  244. //-----------------------------------------------------------------------------
  245. // Purpose:
  246. //-----------------------------------------------------------------------------
  247. bool CTFRevolver::Deploy( void )
  248. {
  249. #ifdef GAME_DLL
  250. CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() );
  251. if ( pOwner )
  252. {
  253. if ( SapperKillsCollectCrits() )
  254. {
  255. if ( pOwner->m_Shared.GetRevengeCrits() )
  256. {
  257. pOwner->m_Shared.AddCond( TF_COND_CRITBOOSTED );
  258. }
  259. }
  260. if ( HasLastShotCritical() )
  261. {
  262. pOwner->m_Shared.AddCond( TF_COND_CRITBOOSTED );
  263. }
  264. }
  265. #endif
  266. return BaseClass::Deploy();
  267. }
  268. #ifdef GAME_DLL
  269. //-----------------------------------------------------------------------------
  270. // Purpose: Reset revenge crits when the revolver is changed
  271. //-----------------------------------------------------------------------------
  272. void CTFRevolver::Detach( void )
  273. {
  274. if ( SapperKillsCollectCrits() )
  275. {
  276. CTFPlayer *pPlayer = GetTFPlayerOwner();
  277. if ( pPlayer )
  278. {
  279. pPlayer->m_Shared.SetRevengeCrits( 0 );
  280. pPlayer->m_Shared.RemoveCond( TF_COND_CRITBOOSTED );
  281. }
  282. }
  283. BaseClass::Detach();
  284. }
  285. //-----------------------------------------------------------------------------
  286. float CTFRevolver::GetProjectileDamage( void )
  287. {
  288. float flDamageMod = 1.0f;
  289. int iExtraDamageOnHit = 0;
  290. CALL_ATTRIB_HOOK_INT( iExtraDamageOnHit, extra_damage_on_hit );
  291. if ( iExtraDamageOnHit )
  292. {
  293. CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
  294. if ( pOwner )
  295. {
  296. flDamageMod = 1.0f + ( Min( 200, pOwner->m_Shared.GetDecapitations() ) * 0.01f );
  297. }
  298. }
  299. return BaseClass::GetProjectileDamage() * flDamageMod;
  300. }
  301. #endif