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.

617 lines
17 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "tf_weapon_sword.h"
  8. // Client specific.
  9. #ifdef CLIENT_DLL
  10. #include "c_tf_player.h"
  11. #include "econ_entity.h"
  12. // Server specific.
  13. #else
  14. #include "tf_player.h"
  15. #endif
  16. //=============================================================================
  17. //
  18. // Weapon Sword tables.
  19. //
  20. // CTFSword
  21. IMPLEMENT_NETWORKCLASS_ALIASED( TFSword, DT_TFWeaponSword )
  22. BEGIN_NETWORK_TABLE( CTFSword, DT_TFWeaponSword )
  23. END_NETWORK_TABLE()
  24. BEGIN_PREDICTION_DATA( CTFSword )
  25. END_PREDICTION_DATA()
  26. LINK_ENTITY_TO_CLASS( tf_weapon_sword, CTFSword );
  27. PRECACHE_WEAPON_REGISTER( tf_weapon_sword );
  28. // CTFKatana
  29. IMPLEMENT_NETWORKCLASS_ALIASED( TFKatana, DT_TFWeaponKatana )
  30. BEGIN_NETWORK_TABLE( CTFKatana, DT_TFWeaponKatana )
  31. #ifdef CLIENT_DLL
  32. RecvPropBool( RECVINFO( m_bIsBloody ) ),
  33. #else
  34. SendPropBool( SENDINFO( m_bIsBloody ) ),
  35. #endif
  36. END_NETWORK_TABLE()
  37. BEGIN_PREDICTION_DATA( CTFKatana )
  38. END_PREDICTION_DATA()
  39. LINK_ENTITY_TO_CLASS( tf_weapon_katana, CTFKatana );
  40. PRECACHE_WEAPON_REGISTER( tf_weapon_katana );
  41. //=============================================================================
  42. //
  43. // Decapitation melee weapon base implementation.
  44. //
  45. //-----------------------------------------------------------------------------
  46. // Purpose:
  47. //-----------------------------------------------------------------------------
  48. CTFDecapitationMeleeWeaponBase::CTFDecapitationMeleeWeaponBase()
  49. : m_bHolstering( false )
  50. {
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Purpose:
  54. //-----------------------------------------------------------------------------
  55. void CTFDecapitationMeleeWeaponBase::Precache()
  56. {
  57. BaseClass::Precache();
  58. }
  59. //-----------------------------------------------------------------------------
  60. // Purpose:
  61. //-----------------------------------------------------------------------------
  62. float CTFDecapitationMeleeWeaponBase::GetMeleeDamage( CBaseEntity *pTarget, int* piDamageType, int* piCustomDamage )
  63. {
  64. float flBaseDamage = BaseClass::GetMeleeDamage( pTarget, piDamageType, piCustomDamage );
  65. *piCustomDamage = TF_DMG_CUSTOM_DECAPITATION;
  66. return flBaseDamage;
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose:
  70. //-----------------------------------------------------------------------------
  71. Activity CTFDecapitationMeleeWeaponBase::TranslateViewmodelHandActivityInternal( Activity actBase )
  72. {
  73. CTFPlayer *pPlayer = GetTFPlayerOwner();
  74. if ( !pPlayer )
  75. return BaseClass::TranslateViewmodelHandActivityInternal( actBase );
  76. CEconItemView *pEconItemView = GetAttributeContainer()->GetItem();
  77. if ( pEconItemView )
  78. {
  79. if ( pEconItemView->GetAnimationSlot() == TF_WPN_TYPE_MELEE_ALLCLASS )
  80. return BaseClass::TranslateViewmodelHandActivityInternal( actBase );
  81. }
  82. // Alright, so we have some decapitation weapons (katana) that can be used
  83. // by both the soldier and the demoman, but the classes play totally different
  84. // animations using the same weapon.
  85. //
  86. // This logic is also responsible for playing the correct animations on the
  87. // demo when he's using non-shared weapons like the Eyelanders.
  88. if ( pPlayer->GetPlayerClass()->GetClassIndex() == TF_CLASS_DEMOMAN )
  89. {
  90. switch ( actBase )
  91. {
  92. case ACT_VM_DRAW:
  93. actBase = ACT_VM_DRAW_SPECIAL;
  94. break;
  95. case ACT_VM_HOLSTER:
  96. actBase = ACT_VM_HOLSTER_SPECIAL;
  97. break;
  98. case ACT_VM_IDLE:
  99. actBase = ACT_VM_IDLE_SPECIAL;
  100. break;
  101. case ACT_VM_PULLBACK:
  102. actBase = ACT_VM_PULLBACK_SPECIAL;
  103. break;
  104. case ACT_VM_PRIMARYATTACK:
  105. actBase = ACT_VM_PRIMARYATTACK_SPECIAL;
  106. break;
  107. case ACT_VM_SECONDARYATTACK:
  108. actBase = ACT_VM_PRIMARYATTACK_SPECIAL;
  109. break;
  110. case ACT_VM_HITCENTER:
  111. actBase = ACT_VM_HITCENTER_SPECIAL;
  112. break;
  113. case ACT_VM_SWINGHARD:
  114. actBase = ACT_VM_SWINGHARD_SPECIAL;
  115. break;
  116. case ACT_VM_IDLE_TO_LOWERED:
  117. actBase = ACT_VM_IDLE_TO_LOWERED_SPECIAL;
  118. break;
  119. case ACT_VM_IDLE_LOWERED:
  120. actBase = ACT_VM_IDLE_LOWERED_SPECIAL;
  121. break;
  122. case ACT_VM_LOWERED_TO_IDLE:
  123. actBase = ACT_VM_LOWERED_TO_IDLE_SPECIAL;
  124. break;
  125. default:
  126. break;
  127. }
  128. }
  129. return BaseClass::TranslateViewmodelHandActivityInternal( actBase );
  130. }
  131. /*
  132. //-----------------------------------------------------------------------------
  133. // Purpose:
  134. //-----------------------------------------------------------------------------
  135. bool CTFDecapitationMeleeWeaponBase::SendWeaponAnim( int iActivity )
  136. {
  137. }*/
  138. //-----------------------------------------------------------------------------
  139. // Purpose:
  140. //-----------------------------------------------------------------------------
  141. bool CTFDecapitationMeleeWeaponBase::CanDecapitate( void )
  142. {
  143. CEconItemView *pScriptItem = GetAttributeContainer()->GetItem();
  144. if ( !pScriptItem )
  145. return false;
  146. CEconItemDefinition *pStaticData = pScriptItem->GetStaticData();
  147. if ( !pStaticData )
  148. return false;
  149. int iDecapitateType = 0;
  150. CALL_ATTRIB_HOOK_INT( iDecapitateType, decapitate_type );
  151. return iDecapitateType != 0;
  152. }
  153. //-----------------------------------------------------------------------------
  154. // Purpose:
  155. //-----------------------------------------------------------------------------
  156. void CTFDecapitationMeleeWeaponBase::SetupGameEventListeners( void )
  157. {
  158. ListenForGameEvent( "player_death" );
  159. }
  160. #ifdef CLIENT_DLL
  161. //-----------------------------------------------------------------------------
  162. // Purpose:
  163. //-----------------------------------------------------------------------------
  164. void CTFDecapitationMeleeWeaponBase::UpdateAttachmentModels( void )
  165. {
  166. BaseClass::UpdateAttachmentModels();
  167. CTFPlayer *pTFPlayer = GetTFPlayerOwner();
  168. if ( !pTFPlayer )
  169. return;
  170. if ( !pTFPlayer->IsLocalPlayer() )
  171. return;
  172. if ( !pTFPlayer->GetViewModel() )
  173. return;
  174. if ( !pTFPlayer->m_Shared.IsShieldEquipped() )
  175. return;
  176. CTFWearableDemoShield* pMyShield = dynamic_cast<CTFWearableDemoShield*>( m_hShield.Get() );
  177. if ( pMyShield )
  178. {
  179. pMyShield->UpdateAttachmentModels();
  180. }
  181. else
  182. {
  183. // Find a shield wearable...
  184. for ( int i=0; i<pTFPlayer->GetNumWearables(); ++i )
  185. {
  186. CEconWearable* pItem = pTFPlayer->GetWearable(i);
  187. if ( !pItem )
  188. continue;
  189. pMyShield = dynamic_cast<CTFWearableDemoShield*>( pItem );
  190. if ( !pMyShield )
  191. continue;
  192. m_hShield.Set( pMyShield );
  193. }
  194. if ( pMyShield )
  195. {
  196. pMyShield->UpdateAttachmentModels();
  197. }
  198. }
  199. }
  200. //-----------------------------------------------------------------------------
  201. // Purpose:
  202. //-----------------------------------------------------------------------------
  203. int CTFDecapitationMeleeWeaponBase::DrawOverriddenViewmodel( C_BaseViewModel *pViewmodel, int flags )
  204. {
  205. int iRes = BaseClass::DrawOverriddenViewmodel( pViewmodel, flags );
  206. CTFWearableDemoShield* pMyShield = dynamic_cast<CTFWearableDemoShield*>( m_hShield.Get() );
  207. if ( pMyShield )
  208. {
  209. pMyShield->DrawOverriddenViewmodel( pViewmodel, flags );
  210. }
  211. return iRes;
  212. }
  213. #endif // CLIENT_DLL
  214. //=============================================================================
  215. //
  216. // Weapon Sword functions.
  217. //
  218. //-----------------------------------------------------------------------------
  219. // Purpose:
  220. //-----------------------------------------------------------------------------
  221. void CTFSword::WeaponReset( void )
  222. {
  223. BaseClass::WeaponReset();
  224. #ifdef CLIENT_DLL
  225. m_flNextIdleWavRoll = 0;
  226. m_iPrevWavDecap = 0;
  227. #endif
  228. }
  229. //-----------------------------------------------------------------------------
  230. // Purpose:
  231. //-----------------------------------------------------------------------------
  232. int CTFSword::GetSwingRange( void )
  233. {
  234. CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
  235. if ( pOwner && pOwner->m_Shared.InCond( TF_COND_SHIELD_CHARGE ) )
  236. {
  237. return 128;
  238. }
  239. else
  240. {
  241. //int iRange = 0;
  242. //CALL_ATTRIB_HOOK_INT( iRange, is_a_sword )
  243. //return 72;
  244. return 72;
  245. }
  246. }
  247. //-----------------------------------------------------------------------------
  248. // Purpose: A speed mod that is applied even if the weapon isn't in hand.
  249. //-----------------------------------------------------------------------------
  250. float CTFSword::GetSwordSpeedMod( void )
  251. {
  252. if ( m_bHolstering )
  253. return 1.f;
  254. CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
  255. if ( !pOwner )
  256. return 0;
  257. if ( !CanDecapitate() )
  258. return 1.f;
  259. int iDecaps = MIN( MAX_DECAPITATIONS, pOwner->m_Shared.GetDecapitations() );
  260. return 1.f + (iDecaps * 0.08f);
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Purpose:
  264. //-----------------------------------------------------------------------------
  265. int CTFSword::GetSwordHealthMod( void )
  266. {
  267. CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
  268. if ( !pOwner )
  269. return 0;
  270. if ( !CanDecapitate() )
  271. return 0.f;
  272. int iDecaps = MIN( MAX_DECAPITATIONS, pOwner->m_Shared.GetDecapitations() );
  273. return (iDecaps * 15);
  274. }
  275. //-----------------------------------------------------------------------------
  276. // Purpose:
  277. //-----------------------------------------------------------------------------
  278. void CTFSword::OnDecapitation( CTFPlayer *pDeadPlayer )
  279. {
  280. BaseClass::OnDecapitation( pDeadPlayer );
  281. #ifdef GAME_DLL
  282. CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
  283. Assert( pOwner );
  284. // The pyro's scythe is actually a "sword" as far as the gameplay code is concerned,
  285. // but we don't want the demo's head-collecting silliness to apply.
  286. if ( pOwner->GetPlayerClass()->GetClassIndex() == TF_CLASS_DEMOMAN )
  287. {
  288. // We have chopped someone's bloody 'ead off!
  289. int iDecap = pOwner->m_Shared.GetDecapitations();
  290. // transfer decapitations
  291. if ( pDeadPlayer )
  292. {
  293. iDecap += pDeadPlayer->m_Shared.GetDecapitations();
  294. }
  295. pOwner->m_Shared.SetDecapitations( ++iDecap );
  296. pOwner->TeamFortress_SetSpeed();
  297. if ( pOwner->m_Shared.GetBestOverhealDecayMult() == -1.f )
  298. {
  299. pOwner->m_Shared.SetBestOverhealDecayMult( 0.25f );
  300. }
  301. if ( pOwner->GetHealth() < pOwner->m_Shared.GetMaxBuffedHealth() )
  302. {
  303. pOwner->TakeHealth( 15, DMG_IGNORE_MAXHEALTH );
  304. }
  305. if ( !pOwner->m_Shared.InCond( TF_COND_DEMO_BUFF ) )
  306. {
  307. pOwner->m_Shared.AddCond( TF_COND_DEMO_BUFF );
  308. }
  309. }
  310. #endif // GAME_DLL
  311. }
  312. #ifdef GAME_DLL
  313. //-----------------------------------------------------------------------------
  314. // Purpose:
  315. //-----------------------------------------------------------------------------
  316. bool CTFDecapitationMeleeWeaponBase::Holster( CBaseCombatWeapon *pSwitchingTo )
  317. {
  318. m_bHolstering = true;
  319. bool res = BaseClass::Holster( pSwitchingTo );
  320. m_bHolstering = false;
  321. if ( res )
  322. {
  323. StopListeningForAllEvents();
  324. }
  325. return res;
  326. }
  327. //-----------------------------------------------------------------------------
  328. // Purpose:
  329. //-----------------------------------------------------------------------------
  330. void CTFDecapitationMeleeWeaponBase::FireGameEvent( IGameEvent *event )
  331. {
  332. const char *pszEventName = event->GetName();
  333. if ( Q_strcmp( pszEventName, "player_death" ) != 0 )
  334. return;
  335. CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
  336. if ( !pOwner )
  337. return;
  338. int iAttackerID = event->GetInt( "attacker" );
  339. if ( iAttackerID != pOwner->GetUserID() )
  340. return;
  341. int iWeaponID = event->GetInt( "weaponid" );
  342. int iCustomKill = event->GetInt( "customkill" );
  343. if ( iWeaponID != TF_WEAPON_SWORD && iCustomKill != TF_DMG_CUSTOM_TAUNTATK_BARBARIAN_SWING )
  344. return;
  345. // Off with their heads!
  346. if ( !CanDecapitate() )
  347. return;
  348. OnDecapitation( ToTFPlayer( UTIL_PlayerByUserId( event->GetInt( "userid" ) ) ) );
  349. }
  350. #endif
  351. //-----------------------------------------------------------------------------
  352. // Purpose:
  353. //-----------------------------------------------------------------------------
  354. bool CTFSword::Deploy( void )
  355. {
  356. bool res = BaseClass::Deploy();
  357. if ( !CanDecapitate() )
  358. {
  359. CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
  360. if ( !pOwner )
  361. return res;
  362. pOwner->m_Shared.SetDecapitations( 0 );
  363. return res;
  364. }
  365. #ifdef GAME_DLL
  366. if ( res )
  367. {
  368. SetupGameEventListeners();
  369. }
  370. #else
  371. // When we go active, there's a chance we immediately thirst for heads.
  372. if ( RandomInt( 1,4 ) == 1 )
  373. {
  374. m_flNextIdleWavRoll = gpGlobals->curtime + 3.0;
  375. }
  376. else
  377. {
  378. m_flNextIdleWavRoll = gpGlobals->curtime + RandomFloat( 5.0, 30.0 );
  379. }
  380. #endif
  381. return res;
  382. }
  383. //-----------------------------------------------------------------------------
  384. // Purpose:
  385. //-----------------------------------------------------------------------------
  386. int CTFSword::GetCount( void )
  387. {
  388. CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
  389. if ( !pOwner )
  390. return 0;
  391. if ( !CanDecapitate() )
  392. return 0;
  393. return pOwner->m_Shared.GetDecapitations();
  394. }
  395. #ifdef CLIENT_DLL
  396. //-----------------------------------------------------------------------------
  397. // Purpose:
  398. //-----------------------------------------------------------------------------
  399. void CTFSword::WeaponIdle( void )
  400. {
  401. BaseClass::WeaponIdle();
  402. CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
  403. if ( !pOwner )
  404. return;
  405. if ( !CanDecapitate() )
  406. return;
  407. // If we've decapped someone recently, we roll shortly afterwards
  408. int iDecaps = pOwner->m_Shared.GetDecapitations();
  409. if ( m_iPrevWavDecap < iDecaps )
  410. {
  411. m_flNextIdleWavRoll = MIN( m_flNextIdleWavRoll, gpGlobals->curtime + RandomFloat(3,5) );
  412. }
  413. m_iPrevWavDecap = iDecaps;
  414. // Randomly play sounds to the local player. The more decaps we have, the more chance it's a good wav.
  415. if ( m_flNextIdleWavRoll < gpGlobals->curtime )
  416. {
  417. float flChance = RemapValClamped( iDecaps, 0, 10, 0.25, 0.9 );
  418. if ( RandomFloat() <= flChance )
  419. {
  420. // Chance to get the more powerful wav:
  421. float flChanceForGoodWav = RemapValClamped( iDecaps, 0, 10, 0.1, 0.75 );
  422. if ( RandomFloat() <= flChanceForGoodWav )
  423. {
  424. WeaponSound( SPECIAL2 );
  425. }
  426. else
  427. {
  428. WeaponSound( SPECIAL1 );
  429. }
  430. }
  431. m_flNextIdleWavRoll = gpGlobals->curtime + RandomFloat( 30.0, 60.0 );
  432. }
  433. }
  434. #endif
  435. //-----------------------------------------------------------------------------
  436. //-----------------------------------------------------------------------------
  437. //-----------------------------------------------------------------------------
  438. // Purpose:
  439. //-----------------------------------------------------------------------------
  440. CTFKatana::CTFKatana()
  441. {
  442. m_bIsBloody = false;
  443. }
  444. //-----------------------------------------------------------------------------
  445. // Purpose:
  446. //-----------------------------------------------------------------------------
  447. bool CTFKatana::Deploy( void )
  448. {
  449. bool res = BaseClass::Deploy();
  450. m_bIsBloody = false;
  451. if ( CanDecapitate() && res )
  452. {
  453. #ifdef GAME_DLL
  454. SetupGameEventListeners();
  455. #endif
  456. }
  457. return res;
  458. }
  459. //-----------------------------------------------------------------------------
  460. // Purpose:
  461. //-----------------------------------------------------------------------------
  462. float CTFKatana::GetMeleeDamage( CBaseEntity *pTarget, int* piDamageType, int* piCustomDamage )
  463. {
  464. // Start with our base damage. We use this to generate our custom damage flags,
  465. // if any. We may trash the damage amount.
  466. float fDamage = BaseClass::GetMeleeDamage( pTarget, piDamageType, piCustomDamage );
  467. // The katana is a weapon of honor!!!! (Hitting someone wielding a katana with
  468. // your katana results in a massive damage boost, a one-hit kill.)
  469. if ( IsHonorBound() )
  470. {
  471. CTFPlayer *pTFPlayerTarget = ToTFPlayer( pTarget );
  472. if ( pTFPlayerTarget )
  473. {
  474. // If our victim is wielding the weapon we're looking for, bump the damage way up.
  475. if ( pTFPlayerTarget->GetActiveTFWeapon() && pTFPlayerTarget->GetActiveTFWeapon()->IsHonorBound() )
  476. {
  477. fDamage = MAX( fDamage, pTFPlayerTarget->GetHealth() * 3 );
  478. *piDamageType |= DMG_DONT_COUNT_DAMAGE_TOWARDS_CRIT_RATE;
  479. }
  480. }
  481. }
  482. return fDamage;
  483. }
  484. //-----------------------------------------------------------------------------
  485. // Purpose:
  486. //-----------------------------------------------------------------------------
  487. int CTFKatana::GetActivityWeaponRole() const
  488. {
  489. CTFPlayer *pPlayer = GetTFPlayerOwner();
  490. if ( pPlayer && pPlayer->GetPlayerClass()->GetClassIndex() == TF_CLASS_DEMOMAN )
  491. {
  492. // demo should use act table item1
  493. return TF_WPN_TYPE_ITEM1;
  494. }
  495. return BaseClass::GetActivityWeaponRole();
  496. }
  497. //-----------------------------------------------------------------------------
  498. // Purpose:
  499. //-----------------------------------------------------------------------------
  500. void CTFKatana::OnDecapitation( CTFPlayer *pDeadPlayer )
  501. {
  502. BaseClass::OnDecapitation( pDeadPlayer );
  503. #ifndef CLIENT_DLL
  504. m_bIsBloody = true;
  505. #endif
  506. }
  507. //-----------------------------------------------------------------------------
  508. // Purpose:
  509. //-----------------------------------------------------------------------------
  510. int CTFKatana::GetSkinOverride() const
  511. {
  512. if ( m_bIsBloody && !UTIL_IsLowViolence() )
  513. {
  514. CTFPlayer *pPlayer = GetTFPlayerOwner();
  515. if ( pPlayer )
  516. {
  517. return ( ( pPlayer->GetTeamNumber() == TF_TEAM_RED ) ? 2 : 3 );
  518. }
  519. }
  520. return BaseClass::GetSkinOverride();
  521. }