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.

286 lines
6.5 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "tf_weapon_bottle.h"
  8. #include "decals.h"
  9. // Client specific.
  10. #ifdef CLIENT_DLL
  11. #include "c_tf_player.h"
  12. // Server specific.
  13. #else
  14. #include "tf_player.h"
  15. #include "tf_fx.h"
  16. #include "tf_gamerules.h"
  17. #endif
  18. //=============================================================================
  19. //
  20. // Weapon Bottle tables.
  21. //
  22. IMPLEMENT_NETWORKCLASS_ALIASED( TFBottle, DT_TFWeaponBottle )
  23. BEGIN_NETWORK_TABLE( CTFBottle, DT_TFWeaponBottle )
  24. #if defined( CLIENT_DLL )
  25. RecvPropBool( RECVINFO( m_bBroken ) )
  26. #else
  27. SendPropBool( SENDINFO( m_bBroken ) )
  28. #endif
  29. END_NETWORK_TABLE()
  30. BEGIN_PREDICTION_DATA( CTFBottle )
  31. END_PREDICTION_DATA()
  32. LINK_ENTITY_TO_CLASS( tf_weapon_bottle, CTFBottle );
  33. PRECACHE_WEAPON_REGISTER( tf_weapon_bottle );
  34. //=============================================================================
  35. //
  36. // Weapon Stickbomb tables.
  37. //
  38. IMPLEMENT_NETWORKCLASS_ALIASED( TFStickBomb, DT_TFWeaponStickBomb )
  39. #ifdef CLIENT_DLL
  40. void RecvProxy_Detonated( const CRecvProxyData *pData, void *pStruct, void *pOut );
  41. #endif
  42. BEGIN_NETWORK_TABLE( CTFStickBomb, DT_TFWeaponStickBomb )
  43. #if defined( CLIENT_DLL )
  44. RecvPropInt( RECVINFO( m_iDetonated ), 0, RecvProxy_Detonated )
  45. #else
  46. SendPropInt( SENDINFO( m_iDetonated ), 1, SPROP_UNSIGNED )
  47. #endif
  48. END_NETWORK_TABLE()
  49. BEGIN_PREDICTION_DATA( CTFStickBomb )
  50. END_PREDICTION_DATA()
  51. LINK_ENTITY_TO_CLASS( tf_weapon_stickbomb, CTFStickBomb );
  52. PRECACHE_WEAPON_REGISTER( tf_weapon_stickbomb );
  53. #ifdef STAGING_ONLY
  54. #define TF_WEAPON_STICKBOMB_NORMAL_MODEL "models/workshop/weapons/c_models/c_caber/c_caber.mdl"
  55. #define TF_WEAPON_STICKBOMB_BROKEN_MODEL "models/workshop/weapons/c_models/c_caber/c_caber_exploded.mdl"
  56. #else
  57. #define TF_WEAPON_STICKBOMB_NORMAL_MODEL "models/weapons/c_models/c_caber/c_caber.mdl"
  58. #define TF_WEAPON_STICKBOMB_BROKEN_MODEL "models/weapons/c_models/c_caber/c_caber_exploded.mdl"
  59. #endif
  60. //=============================================================================
  61. #define TF_BOTTLE_SWITCHGROUP 1
  62. #define TF_BOTTLE_NOTBROKEN 0
  63. #define TF_BOTTLE_BROKEN 1
  64. //=============================================================================
  65. //
  66. // Weapon Bottle functions.
  67. //
  68. //-----------------------------------------------------------------------------
  69. // Purpose:
  70. //-----------------------------------------------------------------------------
  71. CTFBottle::CTFBottle()
  72. {
  73. }
  74. void CTFBottle::WeaponReset( void )
  75. {
  76. BaseClass::WeaponReset();
  77. m_bBroken = false;
  78. }
  79. bool CTFBottle::DefaultDeploy( char *szViewModel, char *szWeaponModel, int iActivity, char *szAnimExt )
  80. {
  81. bool bRet = BaseClass::DefaultDeploy( szViewModel, szWeaponModel, iActivity, szAnimExt );
  82. if ( bRet )
  83. {
  84. SwitchBodyGroups();
  85. }
  86. return bRet;
  87. }
  88. void CTFBottle::SwitchBodyGroups( void )
  89. {
  90. int iState = 0;
  91. if ( m_bBroken == true )
  92. {
  93. iState = 1;
  94. }
  95. SetBodygroup( TF_BOTTLE_SWITCHGROUP, iState );
  96. CTFPlayer *pTFPlayer = ToTFPlayer( GetOwner() );
  97. if ( pTFPlayer && pTFPlayer->GetActiveWeapon() == this )
  98. {
  99. if ( pTFPlayer->GetViewModel() )
  100. {
  101. pTFPlayer->GetViewModel()->SetBodygroup( TF_BOTTLE_SWITCHGROUP, iState );
  102. }
  103. }
  104. }
  105. void CTFBottle::Smack( void )
  106. {
  107. BaseClass::Smack();
  108. if ( ConnectedHit() && IsCurrentAttackACrit() )
  109. {
  110. m_bBroken = true;
  111. SwitchBodyGroups();
  112. }
  113. }
  114. CTFStickBomb::CTFStickBomb()
  115. : CTFBottle()
  116. {
  117. m_iDetonated = 0;
  118. }
  119. void CTFStickBomb::Precache( void )
  120. {
  121. BaseClass::Precache();
  122. PrecacheModel( TF_WEAPON_STICKBOMB_NORMAL_MODEL );
  123. PrecacheModel( TF_WEAPON_STICKBOMB_BROKEN_MODEL );
  124. }
  125. void CTFStickBomb::Smack( void )
  126. {
  127. CTFWeaponBaseMelee::Smack();
  128. // Stick bombs detonate once, on impact.
  129. if ( m_iDetonated == 0 && ConnectedHit() )
  130. {
  131. m_iDetonated = 1;
  132. m_bBroken = true;
  133. SwitchBodyGroups();
  134. #ifdef GAME_DLL
  135. CTFPlayer *pTFPlayer = ToTFPlayer( GetOwner() );
  136. if ( pTFPlayer )
  137. {
  138. Vector vecForward;
  139. AngleVectors( pTFPlayer->EyeAngles(), &vecForward );
  140. Vector vecSwingStart = pTFPlayer->Weapon_ShootPosition();
  141. Vector vecSwingEnd = vecSwingStart + vecForward * GetSwingRange();
  142. Vector explosion = vecSwingStart;
  143. CPVSFilter filter( explosion );
  144. // Halloween Spell
  145. int iHalloweenSpell = 0;
  146. int iCustomParticleIndex = INVALID_STRING_INDEX;
  147. if ( TF_IsHolidayActive( kHoliday_HalloweenOrFullMoon ) )
  148. {
  149. CALL_ATTRIB_HOOK_INT_ON_OTHER( this, iHalloweenSpell, halloween_pumpkin_explosions );
  150. if ( iHalloweenSpell > 0 )
  151. {
  152. iCustomParticleIndex = GetParticleSystemIndex( "halloween_explosion" );
  153. }
  154. }
  155. TE_TFExplosion( filter, 0.0f, explosion, Vector(0,0,1), TF_WEAPON_GRENADELAUNCHER, pTFPlayer->entindex(), -1, SPECIAL1, iCustomParticleIndex );
  156. int dmgType = DMG_BLAST | DMG_USEDISTANCEMOD;
  157. if ( IsCurrentAttackACrit() )
  158. dmgType |= DMG_CRITICAL;
  159. CTakeDamageInfo info( pTFPlayer, pTFPlayer, this, explosion, explosion, 75.0f, dmgType, TF_DMG_CUSTOM_STICKBOMB_EXPLOSION, &explosion );
  160. CTFRadiusDamageInfo radiusinfo( &info, explosion, 100.f );
  161. TFGameRules()->RadiusDamage( radiusinfo );
  162. }
  163. #endif
  164. }
  165. }
  166. void CTFStickBomb::WeaponReset( void )
  167. {
  168. BaseClass::WeaponReset();
  169. m_iDetonated = 0;
  170. SwitchBodyGroups();
  171. }
  172. void CTFStickBomb::WeaponRegenerate( void )
  173. {
  174. BaseClass::WeaponRegenerate();
  175. m_iDetonated = 0;
  176. SetContextThink( &CTFStickBomb::SwitchBodyGroups, gpGlobals->curtime + 0.01f, "SwitchBodyGroups" );
  177. }
  178. void CTFStickBomb::SwitchBodyGroups( void )
  179. {
  180. #ifdef CLIENT_DLL
  181. if ( !GetViewmodelAttachment() )
  182. return;
  183. if ( m_iDetonated == 1 )
  184. {
  185. GetViewmodelAttachment()->SetModel( TF_WEAPON_STICKBOMB_BROKEN_MODEL );
  186. }
  187. else
  188. {
  189. GetViewmodelAttachment()->SetModel( TF_WEAPON_STICKBOMB_NORMAL_MODEL );
  190. }
  191. #endif
  192. }
  193. const char *CTFStickBomb::GetWorldModel( void ) const
  194. {
  195. if ( m_iDetonated == 1 )
  196. {
  197. return TF_WEAPON_STICKBOMB_BROKEN_MODEL;
  198. }
  199. else
  200. {
  201. return BaseClass::GetWorldModel();
  202. }
  203. }
  204. #ifdef CLIENT_DLL
  205. int CTFStickBomb::GetWorldModelIndex( void )
  206. {
  207. if ( !modelinfo )
  208. return BaseClass::GetWorldModelIndex();
  209. if ( m_iDetonated == 1 )
  210. {
  211. m_iWorldModelIndex = modelinfo->GetModelIndex( TF_WEAPON_STICKBOMB_BROKEN_MODEL );
  212. return m_iWorldModelIndex;
  213. }
  214. else
  215. {
  216. m_iWorldModelIndex = modelinfo->GetModelIndex( TF_WEAPON_STICKBOMB_NORMAL_MODEL );
  217. return m_iWorldModelIndex;
  218. }
  219. }
  220. #endif
  221. #ifdef CLIENT_DLL
  222. void RecvProxy_Detonated( const CRecvProxyData *pData, void *pStruct, void *pOut )
  223. {
  224. C_TFStickBomb* pBomb = (C_TFStickBomb*) pStruct;
  225. if ( pData->m_Value.m_Int != pBomb->GetDetonated() )
  226. {
  227. pBomb->SetDetonated( pData->m_Value.m_Int );
  228. pBomb->SwitchBodyGroups();
  229. }
  230. }
  231. #endif