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.

374 lines
8.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "weapon_dodbasebomb.h"
  10. #ifdef CLIENT_DLL
  11. #include "c_dod_player.h"
  12. #else
  13. #include "dod_player.h"
  14. #include "dod_bombtarget.h"
  15. #include "collisionutils.h"
  16. #include "in_buttons.h"
  17. #endif
  18. IMPLEMENT_NETWORKCLASS_ALIASED( DODBaseBombWeapon, DT_BaseBombWeapon )
  19. BEGIN_NETWORK_TABLE( CDODBaseBombWeapon, DT_BaseBombWeapon )
  20. #ifdef CLIENT_DLL
  21. //RecvPropBool( RECVINFO(m_bDeployed) )
  22. #else
  23. //SendPropBool( SENDINFO(m_bDeployed) )
  24. #endif
  25. END_NETWORK_TABLE()
  26. BEGIN_PREDICTION_DATA( CDODBaseBombWeapon )
  27. END_PREDICTION_DATA()
  28. #ifndef CLIENT_DLL
  29. BEGIN_DATADESC( CDODBaseBombWeapon )
  30. END_DATADESC()
  31. #endif
  32. LINK_ENTITY_TO_CLASS( weapon_basebomb, CDODBaseBombWeapon );
  33. PRECACHE_WEAPON_REGISTER( weapon_basebomb );
  34. acttable_t CDODBaseBombWeapon::m_acttable[] =
  35. {
  36. { ACT_PRONE_IDLE, ACT_DOD_PRONEWALK_IDLE_PISTOL, false }, //?
  37. { ACT_PRONE_FORWARD, ACT_DOD_PRONEWALK_IDLE_PISTOL, false }, //?
  38. { ACT_DOD_STAND_IDLE, ACT_DOD_STAND_IDLE_TNT, false },
  39. { ACT_DOD_CROUCH_IDLE, ACT_DOD_CROUCH_IDLE_TNT, false }, //?
  40. { ACT_DOD_CROUCHWALK_IDLE, ACT_DOD_CROUCHWALK_IDLE_TNT, false },
  41. { ACT_DOD_WALK_IDLE, ACT_DOD_WALK_IDLE_TNT, false },
  42. { ACT_DOD_RUN_IDLE, ACT_DOD_RUN_IDLE_TNT, false },
  43. { ACT_SPRINT, ACT_DOD_SPRINT_IDLE_TNT, false },
  44. // Hand Signals
  45. { ACT_DOD_HS_IDLE, ACT_DOD_HS_IDLE_PISTOL, false },
  46. { ACT_DOD_HS_CROUCH, ACT_DOD_HS_CROUCH_PISTOL, false },
  47. };
  48. IMPLEMENT_ACTTABLE( CDODBaseBombWeapon );
  49. CDODBaseBombWeapon::CDODBaseBombWeapon()
  50. {
  51. }
  52. void CDODBaseBombWeapon::Spawn( )
  53. {
  54. WEAPON_FILE_INFO_HANDLE hWpnInfo = LookupWeaponInfoSlot( GetClassname() );
  55. Assert( hWpnInfo != GetInvalidWeaponInfoHandle() );
  56. CDODWeaponInfo *pWeaponInfo = dynamic_cast< CDODWeaponInfo* >( GetFileWeaponInfoFromHandle( hWpnInfo ) );
  57. Assert( pWeaponInfo && "Failed to get CDODWeaponInfo in weapon spawn" );
  58. m_pWeaponInfo = pWeaponInfo;
  59. SetPlanting( false );
  60. BaseClass::Spawn();
  61. }
  62. void CDODBaseBombWeapon::Precache()
  63. {
  64. BaseClass::Precache();
  65. }
  66. bool CDODBaseBombWeapon::Deploy( )
  67. {
  68. #ifdef CLIENT_DLL
  69. CDODPlayer *pPlayer = GetDODPlayerOwner();
  70. if ( pPlayer )
  71. {
  72. pPlayer->HintMessage( HINT_BOMB_FIRST_SELECT );
  73. }
  74. #endif
  75. return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), GetDrawActivity(), (char*)GetAnimPrefix() );
  76. }
  77. void CDODBaseBombWeapon::PrimaryAttack()
  78. {
  79. #ifndef CLIENT_DLL
  80. if ( IsPlanting() )
  81. {
  82. CDODBombTarget *pTarget = (CDODBombTarget *)m_hBombTarget.Get();
  83. CBasePlayer *pPlayer = GetPlayerOwner();
  84. if ( !pTarget || !pPlayer )
  85. {
  86. CancelPlanting();
  87. return;
  88. }
  89. if ( pTarget->CanPlantHere( GetDODPlayerOwner() ) == false )
  90. {
  91. // if the target is not active anymore, cancel ( someone planted there already? )
  92. CancelPlanting();
  93. }
  94. else if ( ( pTarget->GetAbsOrigin() - pPlayer->WorldSpaceCenter() ).Length() > DOD_BOMB_PLANT_RADIUS )
  95. {
  96. // if we're too far away, cancel
  97. CancelPlanting();
  98. }
  99. else if ( IsLookingAtBombTarget( pPlayer, pTarget ) == false || ( pPlayer->GetFlags() & FL_ONGROUND ) == 0 )
  100. {
  101. // not looking at the target anymore
  102. CancelPlanting();
  103. }
  104. else if ( gpGlobals->curtime > m_flPlantCompleteTime )
  105. {
  106. // we finished the plant
  107. CompletePlant();
  108. }
  109. else
  110. {
  111. m_flNextPlantCheck = gpGlobals->curtime + 0.2;
  112. }
  113. return;
  114. }
  115. // find nearby, visible bomb targets
  116. CBaseEntity *pEnt = NULL;
  117. CDODBombTarget *pBestTarget = NULL;
  118. float flBestDist = FLT_MAX;
  119. CDODPlayer *pPlayer = GetDODPlayerOwner();
  120. if ( !pPlayer )
  121. return;
  122. while( ( pEnt = gEntList.FindEntityByClassname( pEnt, "dod_bomb_target" ) ) != NULL )
  123. {
  124. CDODBombTarget *pTarget = static_cast<CDODBombTarget *>( pEnt );
  125. if ( !pTarget->CanPlantHere( pPlayer ) )
  126. continue;
  127. Vector pos = pPlayer->WorldSpaceCenter();
  128. float flDist = ( pos - pTarget->GetAbsOrigin() ).Length();
  129. // if we are looking directly at a bomb target and it is within our radius, that automatically wins
  130. if ( flDist < flBestDist &&
  131. flDist < DOD_BOMB_PLANT_RADIUS &&
  132. IsLookingAtBombTarget( pPlayer, pTarget ) &&
  133. ( pPlayer->GetFlags() & FL_ONGROUND ) )
  134. {
  135. flBestDist = flDist;
  136. pBestTarget = pTarget;
  137. }
  138. }
  139. if ( pBestTarget )
  140. {
  141. StartPlanting( pBestTarget );
  142. }
  143. m_flNextPlantCheck = gpGlobals->curtime + 0.2;
  144. // true if the player is not holding primary attack
  145. m_bUsePlant = !( pPlayer->m_nButtons & (IN_ATTACK|IN_ATTACK2) );
  146. #endif
  147. }
  148. void CDODBaseBombWeapon::SecondaryAttack()
  149. {
  150. PrimaryAttack();
  151. }
  152. #ifndef CLIENT_DLL
  153. void CDODBaseBombWeapon::StartPlanting( CDODBombTarget *pTarget )
  154. {
  155. // we have already checked that we can plant here
  156. // store a pointer to the target we're bombing
  157. m_hBombTarget = pTarget;
  158. // must do this after setting the bomb target as we tell the planter
  159. // what target they are at
  160. SetPlanting( true );
  161. // set the timer for when we'll be done
  162. m_flPlantCompleteTime = gpGlobals->curtime + DOD_BOMB_PLANT_TIME;
  163. // play the planting animation
  164. SendWeaponAnim( ACT_VM_PRIMARYATTACK );
  165. CDODPlayer *pPlayer = GetDODPlayerOwner();
  166. if ( pPlayer )
  167. {
  168. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_PLANT_TNT );
  169. pPlayer->SetMaxSpeed( 1 );
  170. pPlayer->SetProgressBarTime( DOD_BOMB_PLANT_TIME );
  171. }
  172. }
  173. bool CDODBaseBombWeapon::CancelPlanting( void )
  174. {
  175. bool bHolster = false;
  176. SetPlanting( false );
  177. // play a stop animation
  178. SendWeaponAnim( ACT_VM_IDLE );
  179. CDODPlayer *pPlayer = GetDODPlayerOwner();
  180. if ( pPlayer )
  181. {
  182. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_CANCEL_GESTURES );
  183. // restore player speed
  184. pPlayer->SetMaxSpeed( 600 );
  185. pPlayer->ResetProgressBar();
  186. if ( m_bUsePlant )
  187. {
  188. pPlayer->SelectLastItem();
  189. bHolster = true;
  190. }
  191. }
  192. return bHolster;
  193. }
  194. void CDODBaseBombWeapon::CompletePlant( void )
  195. {
  196. CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
  197. if ( pPlayer )
  198. {
  199. SetPlanting( false );
  200. // restore player speed
  201. GetDODPlayerOwner()->SetMaxSpeed( 600 );
  202. // Tell the target that we finished planting the bomb
  203. ((CDODBombTarget *)m_hBombTarget.Get())->CompletePlanting( pPlayer );
  204. // destroy the bomb weapon
  205. pPlayer->Weapon_Drop( this, NULL, NULL );
  206. UTIL_Remove(this);
  207. pPlayer->ResetProgressBar();
  208. pPlayer->SelectLastItem();
  209. }
  210. }
  211. bool CDODBaseBombWeapon::IsLookingAtBombTarget( CBasePlayer *pPlayer, CDODBombTarget *pTarget )
  212. {
  213. Vector forward;
  214. AngleVectors( pPlayer->EyeAngles(), &forward );
  215. Vector toBomb = pTarget->GetAbsOrigin() - pPlayer->EyePosition();
  216. toBomb.NormalizeInPlace();
  217. return ( DotProduct( forward, toBomb ) >= 0.8 );
  218. }
  219. #endif
  220. void CDODBaseBombWeapon::ItemPostFrame()
  221. {
  222. #ifndef CLIENT_DLL
  223. CBasePlayer *pPlayer = GetPlayerOwner();
  224. if ( !pPlayer )
  225. return;
  226. if ( pPlayer->m_nButtons & (IN_ATTACK|IN_ATTACK2) )
  227. {
  228. PrimaryAttack();
  229. }
  230. // Only use the time check if we are planting with the +use key
  231. // adds a slight lag to breaking the player lock otherwise
  232. else if ( !m_bUsePlant || m_flNextPlantCheck < gpGlobals->curtime )
  233. {
  234. if ( IsPlanting() )
  235. {
  236. // reset all planting
  237. bool bHolster = CancelPlanting();
  238. // sometimes after canceling we put the weapon away and switch
  239. // to our last weapon. In that case, we don't want to send any more
  240. // anim calls b/c it confuses the client.
  241. if ( bHolster )
  242. {
  243. // we've put this weapon away, stop everything
  244. return;
  245. }
  246. // anim now
  247. m_flTimeWeaponIdle = 0;
  248. }
  249. // idle
  250. if (m_flTimeWeaponIdle > gpGlobals->curtime)
  251. return;
  252. SendWeaponAnim( GetIdleActivity() );
  253. m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration();
  254. // if we're not planting, why do we have the bomb out?
  255. // switch to our next best weapon
  256. pPlayer->SelectLastItem();
  257. }
  258. #endif // CLIENT_DLL
  259. }
  260. bool CDODBaseBombWeapon::Holster( CBaseCombatWeapon *pSwitchingTo )
  261. {
  262. #ifndef CLIENT_DLL
  263. if ( IsPlanting() )
  264. CancelPlanting();
  265. #endif
  266. return BaseClass::Holster( pSwitchingTo );
  267. }
  268. void CDODBaseBombWeapon::SetPlanting( bool bPlanting )
  269. {
  270. m_bPlanting = bPlanting;
  271. #ifndef CLIENT_DLL
  272. CDODPlayer *pPlayer = GetDODPlayerOwner();
  273. if ( pPlayer )
  274. {
  275. pPlayer->SetPlanting( m_bPlanting ? (CDODBombTarget *)m_hBombTarget.Get() : NULL );
  276. }
  277. #endif
  278. }
  279. bool CDODBaseBombWeapon::IsPlanting( void )
  280. {
  281. return m_bPlanting;
  282. }