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.

430 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "basehlcombatweapon_shared.h"
  8. #include "hl2_player_shared.h"
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. LINK_ENTITY_TO_CLASS( basehlcombatweapon, CBaseHLCombatWeapon );
  12. IMPLEMENT_NETWORKCLASS_ALIASED( BaseHLCombatWeapon , DT_BaseHLCombatWeapon )
  13. BEGIN_NETWORK_TABLE( CBaseHLCombatWeapon , DT_BaseHLCombatWeapon )
  14. #if !defined( CLIENT_DLL )
  15. // SendPropInt( SENDINFO( m_bReflectViewModelAnimations ), 1, SPROP_UNSIGNED ),
  16. #else
  17. // RecvPropInt( RECVINFO( m_bReflectViewModelAnimations ) ),
  18. #endif
  19. END_NETWORK_TABLE()
  20. #if !defined( CLIENT_DLL )
  21. #include "globalstate.h"
  22. //---------------------------------------------------------
  23. // Save/Restore
  24. //---------------------------------------------------------
  25. BEGIN_DATADESC( CBaseHLCombatWeapon )
  26. DEFINE_FIELD( m_bLowered, FIELD_BOOLEAN ),
  27. DEFINE_FIELD( m_flRaiseTime, FIELD_TIME ),
  28. DEFINE_FIELD( m_flHolsterTime, FIELD_TIME ),
  29. DEFINE_FIELD( m_iPrimaryAttacks, FIELD_INTEGER ),
  30. DEFINE_FIELD( m_iSecondaryAttacks, FIELD_INTEGER ),
  31. END_DATADESC()
  32. #endif
  33. BEGIN_PREDICTION_DATA( CBaseHLCombatWeapon )
  34. END_PREDICTION_DATA()
  35. ConVar sk_auto_reload_time( "sk_auto_reload_time", "3", FCVAR_REPLICATED );
  36. //-----------------------------------------------------------------------------
  37. // Purpose:
  38. //-----------------------------------------------------------------------------
  39. void CBaseHLCombatWeapon::ItemHolsterFrame( void )
  40. {
  41. BaseClass::ItemHolsterFrame();
  42. // Must be player held
  43. if ( GetOwner() && GetOwner()->IsPlayer() == false )
  44. return;
  45. // We can't be active
  46. if ( GetOwner()->GetActiveWeapon() == this )
  47. return;
  48. // If it's been longer than three seconds, reload
  49. if ( ( gpGlobals->curtime - m_flHolsterTime ) > sk_auto_reload_time.GetFloat() )
  50. {
  51. // Just load the clip with no animations
  52. FinishReload();
  53. m_flHolsterTime = gpGlobals->curtime;
  54. }
  55. }
  56. //-----------------------------------------------------------------------------
  57. //-----------------------------------------------------------------------------
  58. bool CBaseHLCombatWeapon::CanLower()
  59. {
  60. if ( SelectWeightedSequence( ACT_VM_IDLE_LOWERED ) == ACTIVITY_NOT_AVAILABLE )
  61. return false;
  62. return true;
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Purpose: Drops the weapon into a lowered pose
  66. // Output : Returns true on success, false on failure.
  67. //-----------------------------------------------------------------------------
  68. bool CBaseHLCombatWeapon::Lower( void )
  69. {
  70. //Don't bother if we don't have the animation
  71. if ( SelectWeightedSequence( ACT_VM_IDLE_LOWERED ) == ACTIVITY_NOT_AVAILABLE )
  72. return false;
  73. m_bLowered = true;
  74. return true;
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Purpose: Brings the weapon up to the ready position
  78. // Output : Returns true on success, false on failure.
  79. //-----------------------------------------------------------------------------
  80. bool CBaseHLCombatWeapon::Ready( void )
  81. {
  82. //Don't bother if we don't have the animation
  83. if ( SelectWeightedSequence( ACT_VM_LOWERED_TO_IDLE ) == ACTIVITY_NOT_AVAILABLE )
  84. return false;
  85. m_bLowered = false;
  86. m_flRaiseTime = gpGlobals->curtime + 0.5f;
  87. return true;
  88. }
  89. //-----------------------------------------------------------------------------
  90. // Purpose:
  91. // Output : Returns true on success, false on failure.
  92. //-----------------------------------------------------------------------------
  93. bool CBaseHLCombatWeapon::Deploy( void )
  94. {
  95. // If we should be lowered, deploy in the lowered position
  96. // We have to ask the player if the last time it checked, the weapon was lowered
  97. if ( GetOwner() && GetOwner()->IsPlayer() )
  98. {
  99. CHL2_Player *pPlayer = assert_cast<CHL2_Player*>( GetOwner() );
  100. if ( pPlayer->IsWeaponLowered() )
  101. {
  102. if ( SelectWeightedSequence( ACT_VM_IDLE_LOWERED ) != ACTIVITY_NOT_AVAILABLE )
  103. {
  104. if ( DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_VM_IDLE_LOWERED, (char*)GetAnimPrefix() ) )
  105. {
  106. m_bLowered = true;
  107. // Stomp the next attack time to fix the fact that the lower idles are long
  108. pPlayer->SetNextAttack( gpGlobals->curtime + 1.0 );
  109. m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
  110. m_flNextSecondaryAttack = gpGlobals->curtime + 1.0;
  111. return true;
  112. }
  113. }
  114. }
  115. }
  116. m_bLowered = false;
  117. return BaseClass::Deploy();
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Purpose:
  121. // Output : Returns true on success, false on failure.
  122. //-----------------------------------------------------------------------------
  123. bool CBaseHLCombatWeapon::Holster( CBaseCombatWeapon *pSwitchingTo )
  124. {
  125. if ( BaseClass::Holster( pSwitchingTo ) )
  126. {
  127. m_flHolsterTime = gpGlobals->curtime;
  128. return true;
  129. }
  130. return false;
  131. }
  132. //-----------------------------------------------------------------------------
  133. // Purpose:
  134. // Output : Returns true on success, false on failure.
  135. //-----------------------------------------------------------------------------
  136. bool CBaseHLCombatWeapon::WeaponShouldBeLowered( void )
  137. {
  138. // Can't be in the middle of another animation
  139. if ( GetIdealActivity() != ACT_VM_IDLE_LOWERED && GetIdealActivity() != ACT_VM_IDLE &&
  140. GetIdealActivity() != ACT_VM_IDLE_TO_LOWERED && GetIdealActivity() != ACT_VM_LOWERED_TO_IDLE )
  141. return false;
  142. if ( m_bLowered )
  143. return true;
  144. #if !defined( CLIENT_DLL )
  145. if ( GlobalEntity_GetState( "friendly_encounter" ) == GLOBAL_ON )
  146. return true;
  147. #endif
  148. return false;
  149. }
  150. //-----------------------------------------------------------------------------
  151. // Purpose: Allows the weapon to choose proper weapon idle animation
  152. //-----------------------------------------------------------------------------
  153. void CBaseHLCombatWeapon::WeaponIdle( void )
  154. {
  155. //See if we should idle high or low
  156. if ( WeaponShouldBeLowered() )
  157. {
  158. #if !defined( CLIENT_DLL )
  159. CHL2_Player *pPlayer = dynamic_cast<CHL2_Player*>(GetOwner());
  160. if( pPlayer )
  161. {
  162. pPlayer->Weapon_Lower();
  163. }
  164. #endif
  165. // Move to lowered position if we're not there yet
  166. if ( GetActivity() != ACT_VM_IDLE_LOWERED && GetActivity() != ACT_VM_IDLE_TO_LOWERED
  167. && GetActivity() != ACT_TRANSITION )
  168. {
  169. SendWeaponAnim( ACT_VM_IDLE_LOWERED );
  170. }
  171. else if ( HasWeaponIdleTimeElapsed() )
  172. {
  173. // Keep idling low
  174. SendWeaponAnim( ACT_VM_IDLE_LOWERED );
  175. }
  176. }
  177. else
  178. {
  179. // See if we need to raise immediately
  180. if ( m_flRaiseTime < gpGlobals->curtime && GetActivity() == ACT_VM_IDLE_LOWERED )
  181. {
  182. SendWeaponAnim( ACT_VM_IDLE );
  183. }
  184. else if ( HasWeaponIdleTimeElapsed() )
  185. {
  186. SendWeaponAnim( ACT_VM_IDLE );
  187. }
  188. }
  189. }
  190. float g_lateralBob;
  191. float g_verticalBob;
  192. #if defined( CLIENT_DLL ) && ( !defined( HL2MP ) && !defined( PORTAL ) )
  193. #define HL2_BOB_CYCLE_MIN 1.0f
  194. #define HL2_BOB_CYCLE_MAX 0.45f
  195. #define HL2_BOB 0.002f
  196. #define HL2_BOB_UP 0.5f
  197. static ConVar cl_bobcycle( "cl_bobcycle","0.8" );
  198. static ConVar cl_bob( "cl_bob","0.002" );
  199. static ConVar cl_bobup( "cl_bobup","0.5" );
  200. // Register these cvars if needed for easy tweaking
  201. static ConVar v_iyaw_cycle( "v_iyaw_cycle", "2"/*, FCVAR_UNREGISTERED*/ );
  202. static ConVar v_iroll_cycle( "v_iroll_cycle", "0.5"/*, FCVAR_UNREGISTERED*/ );
  203. static ConVar v_ipitch_cycle( "v_ipitch_cycle", "1"/*, FCVAR_UNREGISTERED*/ );
  204. static ConVar v_iyaw_level( "v_iyaw_level", "0.3"/*, FCVAR_UNREGISTERED*/ );
  205. static ConVar v_iroll_level( "v_iroll_level", "0.1"/*, FCVAR_UNREGISTERED*/ );
  206. static ConVar v_ipitch_level( "v_ipitch_level", "0.3"/*, FCVAR_UNREGISTERED*/ );
  207. //-----------------------------------------------------------------------------
  208. // Purpose:
  209. // Output : float
  210. //-----------------------------------------------------------------------------
  211. float CBaseHLCombatWeapon::CalcViewmodelBob( void )
  212. {
  213. static float bobtime;
  214. static float lastbobtime;
  215. float cycle;
  216. CBasePlayer *player = ToBasePlayer( GetOwner() );
  217. //Assert( player );
  218. //NOTENOTE: For now, let this cycle continue when in the air, because it snaps badly without it
  219. if ( ( !gpGlobals->frametime ) || ( player == NULL ) )
  220. {
  221. //NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!)
  222. return 0.0f;// just use old value
  223. }
  224. //Find the speed of the player
  225. float speed = player->GetLocalVelocity().Length2D();
  226. //FIXME: This maximum speed value must come from the server.
  227. // MaxSpeed() is not sufficient for dealing with sprinting - jdw
  228. speed = clamp( speed, -320, 320 );
  229. float bob_offset = RemapVal( speed, 0, 320, 0.0f, 1.0f );
  230. bobtime += ( gpGlobals->curtime - lastbobtime ) * bob_offset;
  231. lastbobtime = gpGlobals->curtime;
  232. //Calculate the vertical bob
  233. cycle = bobtime - (int)(bobtime/HL2_BOB_CYCLE_MAX)*HL2_BOB_CYCLE_MAX;
  234. cycle /= HL2_BOB_CYCLE_MAX;
  235. if ( cycle < HL2_BOB_UP )
  236. {
  237. cycle = M_PI * cycle / HL2_BOB_UP;
  238. }
  239. else
  240. {
  241. cycle = M_PI + M_PI*(cycle-HL2_BOB_UP)/(1.0 - HL2_BOB_UP);
  242. }
  243. g_verticalBob = speed*0.005f;
  244. g_verticalBob = g_verticalBob*0.3 + g_verticalBob*0.7*sin(cycle);
  245. g_verticalBob = clamp( g_verticalBob, -7.0f, 4.0f );
  246. //Calculate the lateral bob
  247. cycle = bobtime - (int)(bobtime/HL2_BOB_CYCLE_MAX*2)*HL2_BOB_CYCLE_MAX*2;
  248. cycle /= HL2_BOB_CYCLE_MAX*2;
  249. if ( cycle < HL2_BOB_UP )
  250. {
  251. cycle = M_PI * cycle / HL2_BOB_UP;
  252. }
  253. else
  254. {
  255. cycle = M_PI + M_PI*(cycle-HL2_BOB_UP)/(1.0 - HL2_BOB_UP);
  256. }
  257. g_lateralBob = speed*0.005f;
  258. g_lateralBob = g_lateralBob*0.3 + g_lateralBob*0.7*sin(cycle);
  259. g_lateralBob = clamp( g_lateralBob, -7.0f, 4.0f );
  260. //NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!)
  261. return 0.0f;
  262. }
  263. //-----------------------------------------------------------------------------
  264. // Purpose:
  265. // Input : &origin -
  266. // &angles -
  267. // viewmodelindex -
  268. //-----------------------------------------------------------------------------
  269. void CBaseHLCombatWeapon::AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles )
  270. {
  271. Vector forward, right;
  272. AngleVectors( angles, &forward, &right, NULL );
  273. CalcViewmodelBob();
  274. // Apply bob, but scaled down to 40%
  275. VectorMA( origin, g_verticalBob * 0.1f, forward, origin );
  276. // Z bob a bit more
  277. origin[2] += g_verticalBob * 0.1f;
  278. // bob the angles
  279. angles[ ROLL ] += g_verticalBob * 0.5f;
  280. angles[ PITCH ] -= g_verticalBob * 0.4f;
  281. angles[ YAW ] -= g_lateralBob * 0.3f;
  282. VectorMA( origin, g_lateralBob * 0.8f, right, origin );
  283. }
  284. //-----------------------------------------------------------------------------
  285. Vector CBaseHLCombatWeapon::GetBulletSpread( WeaponProficiency_t proficiency )
  286. {
  287. return BaseClass::GetBulletSpread( proficiency );
  288. }
  289. //-----------------------------------------------------------------------------
  290. float CBaseHLCombatWeapon::GetSpreadBias( WeaponProficiency_t proficiency )
  291. {
  292. return BaseClass::GetSpreadBias( proficiency );
  293. }
  294. //-----------------------------------------------------------------------------
  295. const WeaponProficiencyInfo_t *CBaseHLCombatWeapon::GetProficiencyValues()
  296. {
  297. return NULL;
  298. }
  299. #else
  300. // Server stubs
  301. float CBaseHLCombatWeapon::CalcViewmodelBob( void )
  302. {
  303. return 0.0f;
  304. }
  305. //-----------------------------------------------------------------------------
  306. // Purpose:
  307. // Input : &origin -
  308. // &angles -
  309. // viewmodelindex -
  310. //-----------------------------------------------------------------------------
  311. void CBaseHLCombatWeapon::AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles )
  312. {
  313. }
  314. //-----------------------------------------------------------------------------
  315. Vector CBaseHLCombatWeapon::GetBulletSpread( WeaponProficiency_t proficiency )
  316. {
  317. Vector baseSpread = BaseClass::GetBulletSpread( proficiency );
  318. const WeaponProficiencyInfo_t *pProficiencyValues = GetProficiencyValues();
  319. float flModifier = (pProficiencyValues)[ proficiency ].spreadscale;
  320. return ( baseSpread * flModifier );
  321. }
  322. //-----------------------------------------------------------------------------
  323. float CBaseHLCombatWeapon::GetSpreadBias( WeaponProficiency_t proficiency )
  324. {
  325. const WeaponProficiencyInfo_t *pProficiencyValues = GetProficiencyValues();
  326. return (pProficiencyValues)[ proficiency ].bias;
  327. }
  328. //-----------------------------------------------------------------------------
  329. const WeaponProficiencyInfo_t *CBaseHLCombatWeapon::GetProficiencyValues()
  330. {
  331. return GetDefaultProficiencyValues();
  332. }
  333. //-----------------------------------------------------------------------------
  334. const WeaponProficiencyInfo_t *CBaseHLCombatWeapon::GetDefaultProficiencyValues()
  335. {
  336. // Weapon proficiency table. Keep this in sync with WeaponProficiency_t enum in the header!!
  337. static WeaponProficiencyInfo_t g_BaseWeaponProficiencyTable[] =
  338. {
  339. { 2.50, 1.0 },
  340. { 2.00, 1.0 },
  341. { 1.50, 1.0 },
  342. { 1.25, 1.0 },
  343. { 1.00, 1.0 },
  344. };
  345. COMPILE_TIME_ASSERT( ARRAYSIZE(g_BaseWeaponProficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1);
  346. return g_BaseWeaponProficiencyTable;
  347. }
  348. #endif