Counter Strike : Global Offensive Source Code
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.

357 lines
9.0 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "c_plantedc4.h"
  10. #include "engine/IEngineSound.h"
  11. #include "cs_gamerules.h"
  12. #include "SoundEmitterSystem/isoundemittersystembase.h"
  13. #include <bitbuf.h>
  14. #include "precache_register.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. #define PLANTEDC4_MSG_JUSTBLEW 1
  18. #define TIME_TO_DETONATE_WARNING 10
  19. extern ConVar spec_show_xray;
  20. IMPLEMENT_CLIENTCLASS_DT(C_PlantedC4, DT_PlantedC4, CPlantedC4)
  21. RecvPropBool( RECVINFO(m_bBombTicking) ),
  22. RecvPropFloat( RECVINFO(m_flC4Blow) ),
  23. RecvPropFloat( RECVINFO(m_flTimerLength) ),
  24. RecvPropFloat( RECVINFO(m_flDefuseLength) ),
  25. RecvPropFloat( RECVINFO(m_flDefuseCountDown) ),
  26. RecvPropBool( RECVINFO(m_bBombDefused) ),
  27. RecvPropEHandle( RECVINFO(m_hBombDefuser) ),
  28. END_RECV_TABLE()
  29. // PRECACHE_REGISTER_BEGIN( GLOBAL, C_PlantedC4 )
  30. // PRECACHE( PARTICLE_SYSTEM, "bomb_explosion_huge" )
  31. // PRECACHE_REGISTER_END()
  32. CUtlVector< C_PlantedC4* > g_PlantedC4s;
  33. C_PlantedC4::C_PlantedC4() :
  34. m_GlowObject( this, Vector( 1.0f, 1.0f, 1.0f ), 0.0f, false, false )
  35. {
  36. g_PlantedC4s.AddToTail( this );
  37. m_flNextRadarFlashTime = gpGlobals->curtime;
  38. m_bRadarFlash = true;
  39. // Don't beep right away, leave time for the planting sound
  40. m_flNextGlow = gpGlobals->curtime + 1.0;
  41. m_flNextBeep = gpGlobals->curtime + 1.0;
  42. m_hLocalDefusingPlayerHandle = NULL;
  43. }
  44. C_PlantedC4::~C_PlantedC4()
  45. {
  46. g_PlantedC4s.FindAndRemove( this );
  47. }
  48. void C_PlantedC4::SetDormant( bool bDormant )
  49. {
  50. BaseClass::SetDormant( bDormant );
  51. // Remove us from the list of planted C4s.
  52. if ( bDormant )
  53. {
  54. g_PlantedC4s.FindAndRemove( this );
  55. m_bTenSecWarning = false;
  56. }
  57. else
  58. {
  59. if ( g_PlantedC4s.Find( this ) == -1 )
  60. g_PlantedC4s.AddToTail( this );
  61. }
  62. }
  63. void C_PlantedC4::UpdateOnRemove( void )
  64. {
  65. DestroyDefuserRopes();
  66. BaseClass::UpdateOnRemove();
  67. }
  68. void C_PlantedC4::Spawn( void )
  69. {
  70. BaseClass::Spawn();
  71. AddFlag( FL_OBJECT );
  72. SetNextClientThink( CLIENT_THINK_ALWAYS );
  73. m_bTenSecWarning = false;
  74. m_bExplodeWarning = false;
  75. m_bTriggerWarning = false;
  76. DestroyDefuserRopes();
  77. }
  78. void C_PlantedC4::DestroyDefuserRopes( void )
  79. {
  80. FOR_EACH_VEC_BACK( m_hDefuserRopes, i )
  81. {
  82. if ( m_hDefuserRopes[i] )
  83. UTIL_Remove( m_hDefuserRopes[i] );
  84. }
  85. m_hDefuserRopes.RemoveAll();
  86. if ( m_hDefuserMultimeter )
  87. UTIL_Remove( m_hDefuserMultimeter );
  88. }
  89. bool C_PlantedC4::CreateDefuserRopes( void )
  90. {
  91. DestroyDefuserRopes();
  92. // make sure we are being defused
  93. C_CSPlayer *pDefusingPlayer = m_hBombDefuser->Get();
  94. if ( !pDefusingPlayer )
  95. {
  96. DevWarning( "Cannot find defusing player to create bomb defuse wire.\n" );
  97. return false;
  98. }
  99. if ( pDefusingPlayer->IsDormant() )
  100. return false;
  101. if ( !m_hDefuserMultimeter )
  102. {
  103. C_BaseAnimating *pMultimeter = new C_BaseAnimating;
  104. if ( pMultimeter->InitializeAsClientEntity( "models/weapons/w_eq_multimeter.mdl", false ) )
  105. {
  106. pMultimeter->AddSolidFlags( FSOLID_NOT_SOLID );
  107. pMultimeter->AddEffects( EF_BONEMERGE );
  108. pMultimeter->SetParent( pDefusingPlayer );
  109. m_hDefuserMultimeter = pMultimeter;
  110. }
  111. else
  112. {
  113. m_hDefuserMultimeter = NULL;
  114. }
  115. }
  116. if ( !m_hDefuserMultimeter )
  117. {
  118. DevWarning( "Could not create defuser tool model.\n" );
  119. return false;
  120. }
  121. // validate attachments
  122. int nDefuseToolAttachmentA = m_hDefuserMultimeter->LookupAttachment("weapon_defusewire_a");
  123. int nDefuseToolAttachmentB = m_hDefuserMultimeter->LookupAttachment("weapon_defusewire_b");
  124. int nBombClipAttachmentA = LookupAttachment("weapon_defusewire_a");
  125. int nBombClipAttachmentB = LookupAttachment("weapon_defusewire_b");
  126. if ( nDefuseToolAttachmentA < 0 ||
  127. nDefuseToolAttachmentB < 0 ||
  128. nBombClipAttachmentA < 0 ||
  129. nBombClipAttachmentB < 0 )
  130. {
  131. DevWarning( "Could not locate attachment for bomb defuse wire.\n" );
  132. return false;
  133. }
  134. // create the wires
  135. C_RopeKeyframe* pRopeA = C_RopeKeyframe::Create( this, m_hDefuserMultimeter, nBombClipAttachmentA, nDefuseToolAttachmentA, 0.9, "cable/phonecable", 8, ROPE_SIMULATE, ROPE_TYPE_DEFUSECABLES );
  136. if ( pRopeA )
  137. {
  138. pRopeA->AddRopeFlags( ROPE_USE_WIND );
  139. pRopeA->SetSlack( 142 );
  140. pRopeA->AddToLeafSystem();
  141. m_hDefuserRopes[ m_hDefuserRopes.AddToTail() ] = pRopeA;
  142. //pRopeA->AddEffects( EF_NORECEIVESHADOW );
  143. }
  144. else
  145. {
  146. DevWarning( "Failed to create bomb defuse wire.\n" );
  147. return false;
  148. }
  149. C_RopeKeyframe* pRopeB = C_RopeKeyframe::Create( this, m_hDefuserMultimeter, nBombClipAttachmentB, nDefuseToolAttachmentB, 0.9, "cable/phonecable_red", 8, ROPE_SIMULATE, ROPE_TYPE_DEFUSECABLES );
  150. if ( pRopeB )
  151. {
  152. pRopeB->AddRopeFlags( ROPE_USE_WIND );
  153. pRopeB->SetSlack( 142 );
  154. pRopeB->AddToLeafSystem();
  155. m_hDefuserRopes[ m_hDefuserRopes.AddToTail() ] = pRopeB;
  156. //pRopeA->AddEffects( EF_NORECEIVESHADOW );
  157. }
  158. else
  159. {
  160. DevWarning( "Failed to create bomb defuse wire.\n" );
  161. return false;
  162. }
  163. m_hLocalDefusingPlayerHandle = m_hBombDefuser->Get(); // remember this player handle in case it changes
  164. return true;
  165. }
  166. void C_PlantedC4::ClientThink( void )
  167. {
  168. BaseClass::ClientThink();
  169. C_CSPlayer *pDefusingPlayer = m_hBombDefuser->Get();
  170. if ( m_hBombDefuser->Get() != m_hLocalDefusingPlayerHandle )
  171. DestroyDefuserRopes(); // we're still being defused, but the defusing player changed
  172. C_CSPlayer *pLocalPlayer = GetLocalOrInEyeCSPlayer();
  173. if ( pDefusingPlayer && ( pDefusingPlayer != pLocalPlayer || pLocalPlayer->ShouldDraw() ) )
  174. {
  175. if ( m_hDefuserRopes.Count() == 0 )
  176. {
  177. CreateDefuserRopes();
  178. }
  179. }
  180. else
  181. {
  182. DestroyDefuserRopes();
  183. }
  184. // If it's dormant, don't beep or anything..
  185. if ( IsDormant() )
  186. return;
  187. Vector glowColor;
  188. bool bRenderGlow = (CanSeeSpectatorOnlyTools() && spec_show_xray.GetInt());
  189. if ( !m_bBombTicking )
  190. {
  191. // disable C4 thinking if not armed
  192. // undone. we need the bome to resume thinking once it's been actiavted (for training) - mtw
  193. //SetNextClientThink( CLIENT_THINK_NEVER );
  194. if ( m_bBombDefused )
  195. {
  196. glowColor.x = (64.0f/255.0f);
  197. glowColor.y = (255.0f/255.0f);
  198. glowColor.z = (64.0f/255.0f);
  199. m_GlowObject.SetRenderFlags( bRenderGlow, false );
  200. m_GlowObject.SetColor( glowColor );
  201. m_GlowObject.SetAlpha( bRenderGlow ? 0.95f : 0.0f );
  202. }
  203. return;
  204. }
  205. if( ( m_flC4Blow - gpGlobals->curtime ) < 1.0f &&
  206. !m_bTriggerWarning )
  207. {
  208. EmitSound( "C4.ExplodeTriggerTrip" );
  209. int ledAttachmentIndex = LookupAttachment("led");
  210. DispatchParticleEffect( "c4_timer_light_trigger", PATTACH_POINT_FOLLOW, this, ledAttachmentIndex, false, -1 );
  211. m_bTriggerWarning = true;
  212. }
  213. if( ( m_flC4Blow - gpGlobals->curtime ) < 0.0f &&
  214. !m_bExplodeWarning )
  215. {
  216. EmitSound( "C4.ExplodeWarning" );
  217. m_bExplodeWarning = true;
  218. }
  219. if( gpGlobals->curtime > m_flNextBeep )
  220. {
  221. // as it gets closer to going off, increase the radius
  222. CLocalPlayerFilter filter;
  223. float attenuation;
  224. float freq;
  225. //the percent complete of the bomb timer
  226. float fComplete = ( ( m_flC4Blow - gpGlobals->curtime ) / m_flTimerLength );
  227. fComplete = clamp( fComplete, 0.0f, 1.0f );
  228. attenuation = MIN( 0.3 + 0.6 * fComplete, 1.0 );
  229. CSoundParameters params;
  230. if ( ( m_flC4Blow - gpGlobals->curtime ) > 1.0f && GetParametersForSound( "C4.PlantSound", params, NULL ) )
  231. {
  232. EmitSound_t ep( params );
  233. ep.m_SoundLevel = ATTN_TO_SNDLVL( attenuation );
  234. ep.m_pOrigin = &GetAbsOrigin();
  235. EmitSound( filter, SOUND_FROM_WORLD, ep );
  236. }
  237. freq = MAX( 0.1 + 0.9 * fComplete, 0.15 );
  238. m_flNextBeep = gpGlobals->curtime + freq;
  239. }
  240. if( ( m_flC4Blow - gpGlobals->curtime ) <= TIME_TO_DETONATE_WARNING &&
  241. !m_bTenSecWarning )
  242. {
  243. m_bTenSecWarning = true;
  244. if ( !CSGameRules()->IsPlayingTraining() )
  245. {
  246. CLocalPlayerFilter filter;
  247. PlayMusicSelection( filter, CSMUSIC_BOMBTEN );
  248. }
  249. }
  250. glowColor.x = (170.0f/255.0f);
  251. glowColor.y = (0.0f/255.0f);
  252. glowColor.z = (0.0f/255.0f);
  253. if ( (gpGlobals->curtime + 0.25f) > m_flNextGlow )
  254. glowColor.x = (255.0f/255.0f);
  255. if ( gpGlobals->curtime > m_flNextGlow )
  256. {
  257. if ( gpGlobals->curtime > m_flNextGlow && ( m_flC4Blow - gpGlobals->curtime ) > 1.0f )
  258. {
  259. int ledAttachmentIndex = LookupAttachment("led");
  260. DispatchParticleEffect( "c4_timer_light", PATTACH_POINT_FOLLOW, this, ledAttachmentIndex, false, -1 );
  261. }
  262. float freq = 0.1 + 0.9 * ( ( m_flC4Blow - gpGlobals->curtime ) / m_flTimerLength );
  263. if( freq < 0.15 ) freq = 0.15;
  264. m_flNextGlow = gpGlobals->curtime + freq;
  265. }
  266. // Start glowing
  267. m_GlowObject.SetRenderFlags( bRenderGlow, false );
  268. m_GlowObject.SetColor( glowColor );
  269. m_GlowObject.SetAlpha( bRenderGlow ? 0.95f : 0.0f );
  270. }
  271. // Using a new particle system, networked down from the server (KWD)
  272. void C_PlantedC4::Explode( void )
  273. {
  274. // don't hide it in training, we have a particle effect that covers it up and then eventally it all gets removed
  275. if ( !CSGameRules()->IsPlayingTraining() )
  276. AddEffects( EF_NODRAW );
  277. SetDormant( true );
  278. }
  279. float C_PlantedC4::GetDetonationProgress( void )
  280. {
  281. float fComplete = 0.0f;
  282. if ( m_flTimerLength > 0.0f )
  283. {
  284. fComplete = ( ( m_flC4Blow - gpGlobals->curtime ) / m_flTimerLength );
  285. }
  286. return fComplete;
  287. }