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.

767 lines
20 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "dod_player.h"
  8. #include "dod_gamerules.h"
  9. #include "dod_shareddefs.h"
  10. #include "dod_bombtarget.h"
  11. #include "basecombatweapon.h"
  12. #include "weapon_dodbasebomb.h"
  13. #include "dod_team.h"
  14. #include "dod_shareddefs.h"
  15. #include "dod_objective_resource.h"
  16. BEGIN_DATADESC(CDODBombTarget)
  17. DEFINE_KEYFIELD( m_iszCapPointName, FIELD_STRING, "target_control_point" ),
  18. DEFINE_KEYFIELD( m_iBombingTeam, FIELD_INTEGER, "bombing_team" ),
  19. DEFINE_KEYFIELD( m_iTimerAddSeconds, FIELD_INTEGER, "add_timer_seconds" ),
  20. DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
  21. DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
  22. DEFINE_OUTPUT( m_OnBecomeActive, "OnBombTargetActivated" ),
  23. DEFINE_OUTPUT( m_OnBecomeInactive, "OnBombTargetDeactivated" ),
  24. DEFINE_OUTPUT( m_OnBombPlanted, "OnBombPlanted" ),
  25. DEFINE_OUTPUT( m_OnBombExploded, "OnBombExploded" ),
  26. DEFINE_OUTPUT( m_OnBombDisarmed, "OnBombDefused" ),
  27. DEFINE_KEYFIELD( m_bStartDisabled, FIELD_INTEGER, "StartDisabled" ),
  28. DEFINE_USEFUNC( State_Use ),
  29. DEFINE_THINKFUNC( State_Think ),
  30. END_DATADESC();
  31. IMPLEMENT_SERVERCLASS_ST(CDODBombTarget, DT_DODBombTarget)
  32. SendPropInt( SENDINFO(m_iState), 3 ),
  33. SendPropInt( SENDINFO(m_iBombingTeam), 3 ),
  34. SendPropModelIndex( SENDINFO(m_iTargetModel) ),
  35. SendPropModelIndex( SENDINFO(m_iUnavailableModel) ),
  36. END_SEND_TABLE()
  37. LINK_ENTITY_TO_CLASS( dod_bomb_target, CDODBombTarget );
  38. //-----------------------------------------------------------------------------
  39. // Purpose:
  40. //-----------------------------------------------------------------------------
  41. void CDODBombTarget::Spawn( void )
  42. {
  43. m_pControlPoint = NULL;
  44. Precache();
  45. SetTouch( NULL );
  46. SetUse( &CDODBombTarget::State_Use );
  47. SetThink( &CDODBombTarget::State_Think );
  48. SetNextThink( gpGlobals->curtime + 0.1 );
  49. m_pCurStateInfo = NULL;
  50. if ( m_bStartDisabled )
  51. State_Transition( BOMB_TARGET_INACTIVE );
  52. else
  53. State_Transition( BOMB_TARGET_ACTIVE );
  54. BaseClass::Spawn();
  55. // incase we have any animating bomb models
  56. SetPlaybackRate( 1.0 );
  57. }
  58. //-----------------------------------------------------------------------------
  59. // Purpose:
  60. //-----------------------------------------------------------------------------
  61. void CDODBombTarget::Precache( void )
  62. {
  63. BaseClass::Precache();
  64. PrecacheModel( DOD_BOMB_TARGET_MODEL_ARMED );
  65. m_iTargetModel = PrecacheModel( DOD_BOMB_TARGET_MODEL_TARGET );
  66. m_iUnavailableModel = PrecacheModel( DOD_BOMB_TARGET_MODEL_UNAVAILABLE );
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose: change use flags based on state
  70. //-----------------------------------------------------------------------------
  71. int CDODBombTarget::ObjectCaps()
  72. {
  73. int caps = BaseClass::ObjectCaps();
  74. if ( State_Get() != BOMB_TARGET_INACTIVE )
  75. {
  76. caps |= (FCAP_CONTINUOUS_USE | FCAP_USE_IN_RADIUS);
  77. }
  78. return caps;
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Purpose: timer length accessor
  82. //-----------------------------------------------------------------------------
  83. float CDODBombTarget::GetBombTimerLength( void )
  84. {
  85. return DOD_BOMB_TIMER_LENGTH;
  86. }
  87. //-----------------------------------------------------------------------------
  88. // Purpose:
  89. //-----------------------------------------------------------------------------
  90. void CDODBombTarget::State_Transition( BombTargetState newState )
  91. {
  92. State_Leave();
  93. State_Enter( newState );
  94. }
  95. //-----------------------------------------------------------------------------
  96. // Purpose:
  97. //-----------------------------------------------------------------------------
  98. void CDODBombTarget::State_Enter( BombTargetState newState )
  99. {
  100. m_pCurStateInfo = State_LookupInfo( newState );
  101. if ( 0 )
  102. {
  103. if ( m_pCurStateInfo )
  104. Msg( "DODRoundState: entering '%s'\n", m_pCurStateInfo->m_pStateName );
  105. else
  106. Msg( "DODRoundState: entering #%d\n", newState );
  107. }
  108. // Initialize the new state.
  109. if ( m_pCurStateInfo && m_pCurStateInfo->pfnEnterState )
  110. (this->*m_pCurStateInfo->pfnEnterState)();
  111. m_iState = (int)newState;
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Purpose:
  115. //-----------------------------------------------------------------------------
  116. void CDODBombTarget::State_Leave()
  117. {
  118. if ( m_pCurStateInfo && m_pCurStateInfo->pfnLeaveState )
  119. {
  120. (this->*m_pCurStateInfo->pfnLeaveState)();
  121. }
  122. }
  123. //-----------------------------------------------------------------------------
  124. // Purpose:
  125. //-----------------------------------------------------------------------------
  126. void CDODBombTarget::State_Think()
  127. {
  128. if ( m_pCurStateInfo && m_pCurStateInfo->pfnThink )
  129. {
  130. (this->*m_pCurStateInfo->pfnThink)();
  131. }
  132. SetNextThink( gpGlobals->curtime + 0.1 );
  133. }
  134. //-----------------------------------------------------------------------------
  135. // Purpose:
  136. //-----------------------------------------------------------------------------
  137. void CDODBombTarget::State_Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  138. {
  139. if ( m_pCurStateInfo && m_pCurStateInfo->pfnUse )
  140. {
  141. (this->*m_pCurStateInfo->pfnUse)( pActivator, pCaller, useType, value );
  142. }
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Purpose:
  146. //-----------------------------------------------------------------------------
  147. CDODBombTargetStateInfo* CDODBombTarget::State_LookupInfo( BombTargetState state )
  148. {
  149. static CDODBombTargetStateInfo bombTargetStateInfos[] =
  150. {
  151. { BOMB_TARGET_INACTIVE, "BOMB_TARGET_INACTIVE", &CDODBombTarget::State_Enter_INACTIVE, NULL, NULL, NULL },
  152. { BOMB_TARGET_ACTIVE, "BOMB_TARGET_ACTIVE", &CDODBombTarget::State_Enter_ACTIVE, NULL, NULL, &CDODBombTarget::State_Use_ACTIVE },
  153. { BOMB_TARGET_ARMED, "BOMB_TARGET_ARMED", &CDODBombTarget::State_Enter_ARMED, &CDODBombTarget::State_Leave_Armed, &CDODBombTarget::State_Think_ARMED, &CDODBombTarget::State_Use_ARMED }
  154. };
  155. for ( int i=0; i < ARRAYSIZE( bombTargetStateInfos ); i++ )
  156. {
  157. if ( bombTargetStateInfos[i].m_iState == state )
  158. return &bombTargetStateInfos[i];
  159. }
  160. return NULL;
  161. }
  162. //-----------------------------------------------------------------------------
  163. // Purpose:
  164. //-----------------------------------------------------------------------------
  165. void CDODBombTarget::State_Enter_INACTIVE( void )
  166. {
  167. // go invisible
  168. AddEffects( EF_NODRAW );
  169. m_OnBecomeInactive.FireOutput( this, this );
  170. }
  171. //-----------------------------------------------------------------------------
  172. // Purpose:
  173. //-----------------------------------------------------------------------------
  174. void CDODBombTarget::State_Enter_ACTIVE( void )
  175. {
  176. RemoveEffects( EF_NODRAW );
  177. // set transparent model
  178. SetModel( DOD_BOMB_TARGET_MODEL_TARGET );
  179. m_OnBecomeActive.FireOutput( this, this );
  180. }
  181. //-----------------------------------------------------------------------------
  182. // Purpose:
  183. //-----------------------------------------------------------------------------
  184. void CDODBombTarget::State_Enter_ARMED( void )
  185. {
  186. RemoveEffects( EF_NODRAW );
  187. // set solid model
  188. SetModel( DOD_BOMB_TARGET_MODEL_ARMED );
  189. // start count down
  190. m_flExplodeTime = gpGlobals->curtime + GetBombTimerLength();
  191. m_OnBombPlanted.FireOutput( this, this );
  192. // tell CP our time until detonation
  193. CControlPoint *pCP = GetControlPoint();
  194. if ( pCP )
  195. {
  196. pCP->BombPlanted( GetBombTimerLength(), m_pPlantingPlayer );
  197. }
  198. EmitSound( "Weapon_C4.Fuse" );
  199. static int iWickSeq = LookupSequence( "w_tnt_wick" );
  200. ResetSequence( iWickSeq );
  201. }
  202. void CDODBombTarget::State_Leave_Armed( void )
  203. {
  204. StopSound( "Weapon_C4.Fuse" );
  205. }
  206. void CDODBombTarget::ResetDefuse( int index )
  207. {
  208. DefusingPlayer *pRec = &m_DefusingPlayers[index];
  209. Assert( pRec );
  210. if ( pRec && pRec->m_pPlayer )
  211. {
  212. pRec->m_pPlayer->SetDefusing( NULL );
  213. //cancel the progress bar
  214. pRec->m_pPlayer->SetProgressBarTime( 0 );
  215. }
  216. m_DefusingPlayers.Remove( index );
  217. // if noone else is defusing, set objective resource to not be defusing
  218. if ( m_DefusingPlayers.Count() <= 0 )
  219. {
  220. CControlPoint *pCP = GetControlPoint();
  221. if ( pCP )
  222. {
  223. g_pObjectiveResource->SetBombBeingDefused( pCP->GetPointIndex(), false );
  224. }
  225. }
  226. }
  227. #include "IEffects.h"
  228. void TE_Sparks( IRecipientFilter& filter, float delay,
  229. const Vector *pos, int nMagnitude, int nTrailLength, const Vector *pDir );
  230. extern short g_sModelIndexFireball;
  231. void CDODBombTarget::Explode( void )
  232. {
  233. // output the explosion
  234. EmitSound( "Weapon_C4.Explode" );
  235. Vector origin = GetAbsOrigin();
  236. CPASFilter filter( origin );
  237. te->Explosion( filter, -1.0, // don't apply cl_interp delay
  238. &origin,
  239. g_sModelIndexFireball,
  240. 20, //scale
  241. 25,
  242. TE_EXPLFLAG_NONE,
  243. 0,
  244. 0 );
  245. float flDamage = 200;
  246. float flDmgRadius = flDamage * 2.5;
  247. // do a separate radius damage that ignores the world for added damage!
  248. CTakeDamageInfo dmgInfo( this, m_pPlantingPlayer, vec3_origin, origin, flDamage, DMG_BLAST | DMG_BOMB );
  249. DODGameRules()->RadiusDamage( dmgInfo, origin, flDmgRadius, CLASS_NONE, NULL, true );
  250. // stun players in a radius
  251. const float flStunDamage = 100;
  252. CTakeDamageInfo stunInfo( this, this, vec3_origin, GetAbsOrigin(), flStunDamage, DMG_STUN );
  253. DODGameRules()->RadiusStun( stunInfo, GetAbsOrigin(), flDmgRadius );
  254. State_Transition( BOMB_TARGET_INACTIVE );
  255. m_OnBombExploded.FireOutput( this, this );
  256. // tell CP bomb is no longer active
  257. CControlPoint *pCP = GetControlPoint();
  258. if ( pCP )
  259. {
  260. CDODPlayer *pPlayer = m_pPlantingPlayer;
  261. if ( !pPlayer || !pPlayer->IsConnected() )
  262. {
  263. // pick a random player from the bombing team
  264. // hax - if we are debug and team is 0, use allies
  265. if ( m_iBombingTeam == TEAM_UNASSIGNED )
  266. m_iBombingTeam = TEAM_ALLIES;
  267. CDODTeam *pTeam = GetGlobalDODTeam( m_iBombingTeam );
  268. pPlayer = NULL;
  269. if ( pTeam->GetNumPlayers() > 0 )
  270. {
  271. pPlayer = ToDODPlayer( pTeam->GetPlayer( 0 ) );
  272. if ( !pPlayer || !pPlayer->IsConnected() )
  273. {
  274. // bad situation, abandon here
  275. pPlayer = NULL;
  276. }
  277. }
  278. }
  279. pCP->BombExploded( pPlayer, m_iBombingTeam );
  280. g_pObjectiveResource->SetBombBeingDefused( pCP->GetPointIndex(), false );
  281. }
  282. // If we add time to the round timer, tell Gamerules
  283. // Don't do this if this bomb ended the game
  284. if ( m_iTimerAddSeconds > 0 )
  285. {
  286. if ( m_pPlantingPlayer && FStrEq( STRING(gpGlobals->mapname), "dod_jagd" ) )
  287. {
  288. // if the timer is 0:00 or less, achievement time
  289. if ( DODGameRules()->GetTimerSeconds() <= 0 )
  290. {
  291. m_pPlantingPlayer->AwardAchievement( ACHIEVEMENT_DOD_JAGD_OVERTIME_CAP );
  292. }
  293. }
  294. if ( DODGameRules()->State_Get() == STATE_RND_RUNNING )
  295. {
  296. DODGameRules()->AddTimerSeconds( m_iTimerAddSeconds );
  297. }
  298. }
  299. }
  300. void CDODBombTarget::BombDefused( CDODPlayer *pDefuser )
  301. {
  302. // tell CP bomb is no longer active
  303. CControlPoint *pCP = GetControlPoint();
  304. if ( pCP )
  305. {
  306. pCP->BombDisarmed( pDefuser );
  307. }
  308. if ( pDefuser )
  309. {
  310. pDefuser->StatEvent_BombDefused();
  311. }
  312. State_Transition( BOMB_TARGET_ACTIVE );
  313. m_OnBombDisarmed.FireOutput( this, this );
  314. }
  315. bool CDODBombTarget::CanPlayerStartDefuse( CDODPlayer *pPlayer )
  316. {
  317. if ( !pPlayer || !pPlayer->IsAlive() || !pPlayer->IsConnected() )
  318. {
  319. // if the defuser is not alive or has disconnected, reset
  320. return false;
  321. }
  322. if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
  323. {
  324. // they are not on the ground, remove them
  325. pPlayer->HintMessage( HINT_BOMB_DEFUSE_ONGROUND );
  326. return false;
  327. }
  328. Vector vecDist = ( pPlayer->GetAbsOrigin() - GetAbsOrigin() );
  329. float flDist = vecDist.Length();
  330. if ( flDist > DOD_BOMB_DEFUSE_MAXDIST ) // PLAYER_USE_RADIUS is not actually used by the playerUse code!!
  331. {
  332. // they are too far away to continue ( or start ) defusing
  333. return false;
  334. }
  335. return true;
  336. }
  337. bool CDODBombTarget::CanPlayerContinueDefusing( CDODPlayer *pPlayer, DefusingPlayer *pDefuseRecord )
  338. {
  339. if ( !pDefuseRecord || pDefuseRecord->m_flDefuseTimeoutTime < gpGlobals->curtime )
  340. {
  341. // they have not updated their +use in a while, assume they stopped
  342. return false;
  343. }
  344. return CanPlayerStartDefuse( pPlayer );
  345. }
  346. //-----------------------------------------------------------------------------
  347. // Purpose:
  348. //-----------------------------------------------------------------------------
  349. void CDODBombTarget::State_Think_ARMED( void )
  350. {
  351. // count down
  352. if ( DODGameRules()->State_Get() != STATE_RND_RUNNING )
  353. {
  354. State_Transition( BOMB_TARGET_ACTIVE );
  355. // reset the timer
  356. CControlPoint *pCP = GetControlPoint();
  357. if ( pCP )
  358. {
  359. pCP->CancelBombPlanted();
  360. }
  361. }
  362. // manually advance frame so that it matches bomb timer length.
  363. float flTimerLength = GetBombTimerLength();
  364. float flTimeLeft = m_flExplodeTime - gpGlobals->curtime;
  365. SetCycle( clamp( 1.0 - ( flTimeLeft / flTimerLength ), 0.0, 1.0 ) );
  366. static int iAttachment = LookupAttachment( "wick" );//ed awesome
  367. Vector pos;
  368. QAngle ang;
  369. GetAttachment( iAttachment, pos, ang );
  370. Vector forward;
  371. AngleVectors( ang, &forward );
  372. CPVSFilter filter( pos );
  373. TE_Sparks( filter, 0.0, &pos, 1, 1, &forward );
  374. // So long as we have valid defusers, we will not explode
  375. if ( m_DefusingPlayers.Count() > 0 )
  376. {
  377. // remove the undesirables
  378. // make sure they are on ground still
  379. // see if they have completed the defuse
  380. for ( int i=m_DefusingPlayers.Count()-1;i>=0;i-- )
  381. {
  382. DefusingPlayer *pDefuseRecord = &m_DefusingPlayers[i];
  383. CDODPlayer *pPlayer = pDefuseRecord->m_pPlayer;
  384. if ( !CanPlayerContinueDefusing( pPlayer, pDefuseRecord ) )
  385. {
  386. ResetDefuse( i );
  387. }
  388. else
  389. {
  390. // they are still a valid defuser
  391. // if their defuse complete time has passed
  392. if ( pDefuseRecord->m_flDefuseCompleteTime < gpGlobals->curtime )
  393. {
  394. // Defuse Complete
  395. BombDefused( pPlayer );
  396. // remove everyone from the list
  397. for ( int j=m_DefusingPlayers.Count()-1;j>=0;j-- )
  398. {
  399. ResetDefuse( j );
  400. }
  401. // break out of this loop
  402. i = -1;
  403. }
  404. }
  405. }
  406. }
  407. else if ( gpGlobals->curtime > m_flExplodeTime )
  408. {
  409. // no defusers, time is up
  410. Explode();
  411. }
  412. }
  413. //-----------------------------------------------------------------------------
  414. // Purpose:
  415. //-----------------------------------------------------------------------------
  416. void CDODBombTarget::State_Use_ACTIVE( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  417. {
  418. CDODPlayer *pPlayer = ToDODPlayer( pActivator );
  419. if ( !CanPlantHere( pPlayer ) )
  420. return;
  421. Vector pos = pPlayer->WorldSpaceCenter();
  422. float flDist = ( pos - GetAbsOrigin() ).Length();
  423. if ( flDist > DOD_BOMB_PLANT_RADIUS )
  424. {
  425. return;
  426. }
  427. if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
  428. {
  429. pPlayer->HintMessage( HINT_BOMB_DEFUSE_ONGROUND, true );
  430. return;
  431. }
  432. CBaseCombatWeapon *pWeapon = NULL;
  433. if ( ( pWeapon = pPlayer->Weapon_OwnsThisType( "weapon_basebomb" ) ) != NULL )
  434. {
  435. CDODBaseBombWeapon *pBomb = dynamic_cast<CDODBaseBombWeapon *>( pWeapon );
  436. if ( pBomb )
  437. {
  438. // switch to their bomb, they will have to hit primary attack
  439. pPlayer->Weapon_Switch( pBomb );
  440. if ( pBomb == pPlayer->GetActiveWeapon() )
  441. {
  442. pBomb->PrimaryAttack();
  443. }
  444. }
  445. }
  446. else
  447. {
  448. // they don't have a bomb - play hint message
  449. pPlayer->HintMessage( HINT_NEED_BOMB );
  450. }
  451. }
  452. //-----------------------------------------------------------------------------
  453. // Purpose:
  454. //-----------------------------------------------------------------------------
  455. void CDODBombTarget::CompletePlanting( CDODPlayer *pPlantingPlayer )
  456. {
  457. if ( pPlantingPlayer && ( pPlantingPlayer->GetTeamNumber() == m_iBombingTeam || m_iBombingTeam == TEAM_UNASSIGNED ) )
  458. {
  459. m_pPlantingPlayer = pPlantingPlayer;
  460. State_Transition( BOMB_TARGET_ARMED );
  461. }
  462. }
  463. DefusingPlayer *CDODBombTarget::FindDefusingPlayer( CDODPlayer *pPlayer )
  464. {
  465. DefusingPlayer *pRec = NULL;
  466. for ( int i=0;i<m_DefusingPlayers.Count();i++ )
  467. {
  468. if ( m_DefusingPlayers[i].m_pPlayer == pPlayer )
  469. {
  470. pRec = &m_DefusingPlayers[i];
  471. break;
  472. }
  473. }
  474. return pRec;
  475. }
  476. //-----------------------------------------------------------------------------
  477. // Purpose:
  478. //-----------------------------------------------------------------------------
  479. void CDODBombTarget::State_Use_ARMED( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  480. {
  481. // check for people disarming
  482. CDODPlayer *pPlayer = ToDODPlayer( pActivator );
  483. if ( !pPlayer || pPlayer->GetTeamNumber() == m_iBombingTeam || pPlayer->GetTeamNumber() == TEAM_SPECTATOR )
  484. return;
  485. // check for distance, offground etc
  486. if ( CanPlayerStartDefuse( pPlayer ) == false )
  487. {
  488. return;
  489. }
  490. DefusingPlayer *pDefusingPlayerRecord = FindDefusingPlayer( pPlayer );
  491. // See if we already added this player to the defusing list
  492. if ( pDefusingPlayerRecord )
  493. {
  494. // They are still defusing for the next 0.2 seconds
  495. pDefusingPlayerRecord->m_flDefuseTimeoutTime = gpGlobals->curtime + 0.2;
  496. }
  497. else
  498. {
  499. // add player to the list
  500. DefusingPlayer defusingPlayer;
  501. defusingPlayer.m_pPlayer = pPlayer;
  502. defusingPlayer.m_flDefuseCompleteTime = gpGlobals->curtime + DOD_BOMB_DEFUSE_TIME;
  503. defusingPlayer.m_flDefuseTimeoutTime = gpGlobals->curtime + 0.2;
  504. m_DefusingPlayers.AddToTail( defusingPlayer );
  505. // tell the player they are defusing
  506. pPlayer->SetDefusing( this );
  507. pPlayer->SetProgressBarTime( DOD_BOMB_DEFUSE_TIME );
  508. CControlPoint *pCP = GetControlPoint();
  509. if ( pCP )
  510. {
  511. g_pObjectiveResource->SetBombBeingDefused( pCP->GetPointIndex(), true );
  512. }
  513. }
  514. }
  515. //-----------------------------------------------------------------------------
  516. // Purpose:
  517. //-----------------------------------------------------------------------------
  518. void CDODBombTarget::InputEnable( inputdata_t &inputdata )
  519. {
  520. if ( m_pCurStateInfo && m_pCurStateInfo->m_iState == BOMB_TARGET_INACTIVE )
  521. {
  522. State_Transition( BOMB_TARGET_ACTIVE );
  523. }
  524. }
  525. //-----------------------------------------------------------------------------
  526. // Purpose:
  527. //-----------------------------------------------------------------------------
  528. void CDODBombTarget::InputDisable( inputdata_t &inputdata )
  529. {
  530. if ( m_pCurStateInfo && m_pCurStateInfo->m_iState != BOMB_TARGET_INACTIVE )
  531. {
  532. if ( m_pCurStateInfo->m_iState == BOMB_TARGET_ARMED )
  533. {
  534. // if planting, tell our cp we're not planting anymore
  535. CControlPoint *pCP = GetControlPoint();
  536. if ( pCP )
  537. {
  538. pCP->CancelBombPlanted();
  539. }
  540. }
  541. State_Transition( BOMB_TARGET_INACTIVE );
  542. }
  543. }
  544. //-----------------------------------------------------------------------------
  545. // Purpose:
  546. //-----------------------------------------------------------------------------
  547. CControlPoint *CDODBombTarget::GetControlPoint( void )
  548. {
  549. if ( !m_pControlPoint )
  550. {
  551. if ( m_iszCapPointName == NULL_STRING )
  552. return NULL;
  553. // try to find it
  554. m_pControlPoint = dynamic_cast<CControlPoint *>( gEntList.FindEntityByName( NULL, STRING(m_iszCapPointName) ) );
  555. if ( !m_pControlPoint )
  556. Warning( "Could not find dod_control_point named \"%s\" for dod_bomb_target \"%s\"\n", STRING(m_iszCapPointName), STRING( GetEntityName() ) );
  557. }
  558. return m_pControlPoint;
  559. }
  560. //-----------------------------------------------------------------------------
  561. // Purpose:
  562. //-----------------------------------------------------------------------------
  563. bool CDODBombTarget::CanPlantHere( CDODPlayer *pPlayer )
  564. {
  565. if ( !m_pCurStateInfo )
  566. return false;
  567. if ( m_pCurStateInfo->m_iState != BOMB_TARGET_ACTIVE )
  568. return false;
  569. if ( pPlayer->GetTeamNumber() != m_iBombingTeam && m_iBombingTeam != TEAM_UNASSIGNED )
  570. return false;
  571. return true;
  572. }
  573. //-----------------------------------------------------------------------------
  574. // Purpose:
  575. //-----------------------------------------------------------------------------
  576. void CDODBombTarget::DefuseBlocked( CDODPlayer *pAttacker )
  577. {
  578. CControlPoint *pPoint = GetControlPoint();
  579. if ( !pPoint )
  580. return;
  581. IGameEvent *event = gameeventmanager->CreateEvent( "dod_capture_blocked" );
  582. if ( event )
  583. {
  584. event->SetInt( "cp", pPoint->GetPointIndex() );
  585. event->SetString( "cpname", pPoint->GetName() );
  586. event->SetInt( "blocker", pAttacker->entindex() );
  587. event->SetInt( "priority", 9 );
  588. event->SetBool( "bomb", true );
  589. gameeventmanager->FireEvent( event );
  590. }
  591. pAttacker->AddScore( PLAYER_POINTS_FOR_BLOCK );
  592. pAttacker->Stats_AreaDefended();
  593. }
  594. void CDODBombTarget::PlantBlocked( CDODPlayer *pAttacker )
  595. {
  596. CControlPoint *pPoint = GetControlPoint();
  597. if ( !pPoint )
  598. return;
  599. IGameEvent *event = gameeventmanager->CreateEvent( "dod_capture_blocked" );
  600. if ( event )
  601. {
  602. event->SetInt( "cp", pPoint->GetPointIndex() );
  603. event->SetString( "cpname", pPoint->GetName() );
  604. event->SetInt( "blocker", pAttacker->entindex() );
  605. event->SetInt( "priority", 9 );
  606. event->SetBool( "bomb", true );
  607. gameeventmanager->FireEvent( event );
  608. }
  609. pAttacker->AddScore( PLAYER_POINTS_FOR_BLOCK );
  610. pAttacker->Stats_AreaDefended();
  611. }