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.

737 lines
18 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "dod_shareddefs.h"
  8. #include "dod_control_point.h"
  9. #include "dod_player.h"
  10. #include "dod_gamerules.h"
  11. #include "dod_team.h"
  12. #include "dod_objective_resource.h"
  13. #include "dod_control_point_master.h"
  14. LINK_ENTITY_TO_CLASS( dod_control_point, CControlPoint );
  15. #define OBJ_ICON_NEUTRAL_FLAG 0
  16. #define OBJ_ICON_ALLIES_FLAG 1
  17. #define OBJ_ICON_AXIS_FLAG 2
  18. BEGIN_DATADESC(CControlPoint)
  19. DEFINE_KEYFIELD( m_iszPrintName, FIELD_STRING, "point_printname" ),
  20. DEFINE_KEYFIELD( m_iszAlliesCapSound, FIELD_STRING, "point_allies_capsound" ),
  21. DEFINE_KEYFIELD( m_iszAxisCapSound, FIELD_STRING, "point_axis_capsound" ),
  22. DEFINE_KEYFIELD( m_iszResetSound, FIELD_STRING, "point_resetsound" ),
  23. DEFINE_KEYFIELD( m_iszAlliesModel, FIELD_STRING, "point_allies_model" ),
  24. DEFINE_KEYFIELD( m_iszAxisModel, FIELD_STRING, "point_axis_model" ),
  25. DEFINE_KEYFIELD( m_iszResetModel, FIELD_STRING, "point_reset_model" ),
  26. DEFINE_KEYFIELD( m_iCPGroup, FIELD_INTEGER, "point_group" ),
  27. DEFINE_KEYFIELD( m_iTimedPointsAllies, FIELD_INTEGER, "point_timedpoints_allies" ),
  28. DEFINE_KEYFIELD( m_iTimedPointsAxis, FIELD_INTEGER, "point_timedpoints_axis" ),
  29. DEFINE_KEYFIELD( m_iBombsRequired, FIELD_INTEGER, "point_num_bombs" ),
  30. DEFINE_INPUTFUNC( FIELD_INTEGER, "SetOwner", InputSetOwner ),
  31. DEFINE_INPUTFUNC( FIELD_VOID, "ShowModel", InputShowModel ),
  32. DEFINE_INPUTFUNC( FIELD_VOID, "HideModel", InputHideModel ),
  33. DEFINE_OUTPUT( m_AlliesCapOutput, "OnAlliesCap" ), // these are fired whenever the point changes modes
  34. DEFINE_OUTPUT( m_AxisCapOutput, "OnAxisCap" ),
  35. DEFINE_OUTPUT( m_PointResetOutput, "OnCapReset" ),
  36. DEFINE_OUTPUT( m_OwnerChangedToAllies, "AlliesCapturePoint" ), // these are fired when a team does the work to change the owner
  37. DEFINE_OUTPUT( m_OwnerChangedToAxis, "AxisCapturePoint" ),
  38. END_DATADESC();
  39. CControlPoint::CControlPoint( )
  40. {
  41. m_iPointIndex = -1;
  42. m_bPointVisible = false;
  43. m_iAlliesIcon = 0;
  44. m_iAxisIcon = 0;
  45. m_iNeutralIcon = 0;
  46. m_iNeutralIcon = 0;
  47. //default group is 0 for backwards compatibility
  48. m_iAlliesModelBodygroup = 0;
  49. m_iAxisModelBodygroup = 0;
  50. m_iResetModelBodygroup = 0;
  51. m_bBombPlanted = false;
  52. }
  53. void CControlPoint::Spawn( void )
  54. {
  55. Precache();
  56. SetTouch( NULL );
  57. InternalSetOwner( m_iDefaultOwner, false ); //init the owner of this point
  58. SetActive( !m_bStartDisabled );
  59. BaseClass::Spawn();
  60. UseClientSideAnimation();
  61. SetPlaybackRate( 1.0 );
  62. SetCycle( random->RandomFloat( 0, 1.0 ) );
  63. m_iAlliesRequired = 0;
  64. m_iAxisRequired = 0;
  65. if ( FBitSet( m_spawnflags, CAP_POINT_HIDE_MODEL ) )
  66. {
  67. AddEffects( EF_NODRAW );
  68. }
  69. m_iBombsRemaining = m_iBombsRequired;
  70. }
  71. void CControlPoint::SetNumCappersRequired( int alliesRequired, int axisRequired )
  72. {
  73. m_iAlliesRequired = alliesRequired;
  74. m_iAxisRequired = axisRequired;
  75. }
  76. //================================
  77. // InputReset
  78. // Used by ControlMaster to this point to its default owner
  79. //================================
  80. void CControlPoint::InputReset( inputdata_t &input )
  81. {
  82. InternalSetOwner( m_iDefaultOwner, false );
  83. g_pObjectiveResource->SetOwningTeam( GetPointIndex(), m_iTeam );
  84. }
  85. //================================
  86. // InputReset
  87. // Used by Area caps to set the owner
  88. //================================
  89. void CControlPoint::InputSetOwner( inputdata_t &input )
  90. {
  91. int team = input.value.Int();
  92. Assert( team == TEAM_UNASSIGNED || team == TEAM_ALLIES || team == TEAM_AXIS );
  93. Assert( input.pCaller );
  94. Assert( input.pCaller->IsPlayer() );
  95. CDODPlayer *pPlayer = ToDODPlayer( input.pCaller );
  96. int iCappingPlayer = pPlayer->entindex();
  97. // Only allow cp caps when round is running ( but not when in warmup )
  98. if( DODGameRules()->State_Get() == STATE_RND_RUNNING &&
  99. !DODGameRules()->IsInWarmup() )
  100. {
  101. InternalSetOwner( team, true, 1, &iCappingPlayer );
  102. g_pObjectiveResource->SetOwningTeam( GetPointIndex(), m_iTeam );
  103. }
  104. }
  105. void CControlPoint::SetOwner( int owner, bool bMakeSound, int iNumCappers, int *pCappingPlayers )
  106. {
  107. // Only allow cp caps when round is running ( but not when in warmup )
  108. if( DODGameRules()->State_Get() == STATE_RND_RUNNING &&
  109. !DODGameRules()->IsInWarmup() )
  110. {
  111. InternalSetOwner( owner, bMakeSound, iNumCappers, pCappingPlayers );
  112. g_pObjectiveResource->SetOwningTeam( GetPointIndex(), m_iTeam );
  113. }
  114. }
  115. void CControlPoint::InputShowModel( inputdata_t &input )
  116. {
  117. RemoveEffects( EF_NODRAW );
  118. }
  119. void CControlPoint::InputHideModel( inputdata_t &input )
  120. {
  121. AddEffects( EF_NODRAW );
  122. }
  123. int CControlPoint::GetCurrentHudIconIndex( void )
  124. {
  125. return GetHudIconIndexForTeam( GetOwner() );
  126. }
  127. int CControlPoint::GetHudIconIndexForTeam( int team )
  128. {
  129. int icon = m_iNeutralIcon;
  130. switch( team )
  131. {
  132. case TEAM_ALLIES:
  133. icon = m_iAlliesIcon;
  134. break;
  135. case TEAM_AXIS:
  136. icon = m_iAxisIcon;
  137. break;
  138. case TEAM_UNASSIGNED:
  139. icon = m_iNeutralIcon;
  140. break;
  141. default:
  142. Assert( !"Bad team in GetHudIconIndexForTeam()" );
  143. break;
  144. }
  145. return icon;
  146. }
  147. int CControlPoint::GetTimerCapHudIcon( void )
  148. {
  149. return m_iTimerCapIcon;
  150. }
  151. int CControlPoint::GetBombedHudIcon( void )
  152. {
  153. return m_iBombedIcon;
  154. }
  155. // SetOwner
  156. // ========
  157. // Sets the new owner of the point
  158. // plays the appropriate sound
  159. // and shows the right model
  160. void CControlPoint::InternalSetOwner( int owner, bool bMakeSound, int iNumCappers, int *pCappingPlayers )
  161. {
  162. m_iTeam = owner;
  163. switch ( m_iTeam )
  164. {
  165. case TEAM_UNASSIGNED:
  166. {
  167. if( bMakeSound )
  168. {
  169. CBroadcastRecipientFilter filter;
  170. EmitSound( filter, entindex(), STRING(m_iszResetSound) );
  171. }
  172. SetModel( STRING(m_iszResetModel) );
  173. SetBodygroup( 0, m_iResetModelBodygroup );
  174. m_PointResetOutput.FireOutput( this, this );
  175. }
  176. break;
  177. case TEAM_ALLIES:
  178. {
  179. if( bMakeSound )
  180. {
  181. CBroadcastRecipientFilter filter;
  182. EmitSound( filter, entindex(), STRING(m_iszAlliesCapSound) );
  183. }
  184. SetModel( STRING(m_iszAlliesModel) );
  185. SetBodygroup( 0, m_iAlliesModelBodygroup );
  186. m_AlliesCapOutput.FireOutput( this, this );
  187. }
  188. break;
  189. case TEAM_AXIS:
  190. {
  191. if( bMakeSound )
  192. {
  193. CBroadcastRecipientFilter filter;
  194. EmitSound( filter, entindex(), STRING(m_iszAxisCapSound) );
  195. }
  196. SetModel( STRING(m_iszAxisModel) );
  197. SetBodygroup( 0, m_iAxisModelBodygroup );
  198. m_AxisCapOutput.FireOutput( this, this );
  199. }
  200. break;
  201. default:
  202. Assert(0);
  203. break;
  204. }
  205. if( bMakeSound ) //make sure this is a real cap and not a reset
  206. {
  207. for( int i=0;i<iNumCappers;i++ )
  208. {
  209. int playerIndex = pCappingPlayers[i];
  210. Assert( playerIndex > 0 && playerIndex <= gpGlobals->maxClients );
  211. CDODPlayer *pPlayer = ToDODPlayer( UTIL_PlayerByIndex( playerIndex ) );
  212. Assert( pPlayer );
  213. if ( pPlayer )
  214. {
  215. pPlayer->AddScore( PLAYER_POINTS_FOR_CAP );
  216. pPlayer->Stats_AreaCaptured();
  217. DODGameRules()->Stats_PlayerCap( pPlayer->GetTeamNumber(), pPlayer->m_Shared.DesiredPlayerClass() );
  218. // count bomb plants as point capture
  219. //if ( !m_bSetOwnerIsBombPlant )
  220. {
  221. pPlayer->StatEvent_PointCaptured();
  222. }
  223. }
  224. }
  225. if ( m_iTeam == TEAM_ALLIES )
  226. {
  227. m_OwnerChangedToAllies.FireOutput( this, this );
  228. }
  229. else if ( m_iTeam == TEAM_AXIS )
  230. {
  231. m_OwnerChangedToAxis.FireOutput( this, this );
  232. }
  233. }
  234. if( bMakeSound && m_iTeam != TEAM_UNASSIGNED && iNumCappers > 0 ) //dont print message if its a reset
  235. SendCapString( m_iTeam, iNumCappers, pCappingPlayers );
  236. // have control point master check the win conditions now!
  237. CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, "dod_control_point_master" );
  238. while( pEnt )
  239. {
  240. CControlPointMaster *pMaster = dynamic_cast<CControlPointMaster *>( pEnt );
  241. if ( pMaster->IsActive() )
  242. {
  243. pMaster->CheckWinConditions();
  244. }
  245. pEnt = gEntList.FindEntityByClassname( pEnt, "dod_control_point_master" );
  246. }
  247. // Capping the last flag achievement
  248. if ( ( DODGameRules()->State_Get() == STATE_ALLIES_WIN && m_iTeam == TEAM_ALLIES ) ||
  249. ( DODGameRules()->State_Get() == STATE_AXIS_WIN && m_iTeam == TEAM_AXIS ) )
  250. {
  251. // limit to flag cap maps
  252. if ( m_iBombsRequired == 0 )
  253. {
  254. for ( int i=0;i<iNumCappers;i++ )
  255. {
  256. CDODPlayer *pDODPlayer = ToDODPlayer( UTIL_PlayerByIndex( pCappingPlayers[i] ) );
  257. if ( pDODPlayer )
  258. {
  259. pDODPlayer->AwardAchievement( ACHIEVEMENT_DOD_CAP_LAST_FLAG );
  260. }
  261. }
  262. }
  263. }
  264. }
  265. void CControlPoint::SendCapString( int team, int iNumCappers, int *pCappingPlayers )
  266. {
  267. if( strlen( STRING(m_iszPrintName) ) <= 0 )
  268. return;
  269. IGameEvent * event = gameeventmanager->CreateEvent( "dod_point_captured" );
  270. if ( event )
  271. {
  272. event->SetInt( "cp", m_iPointIndex );
  273. event->SetString( "cpname", STRING(m_iszPrintName) );
  274. char cappers[9]; // pCappingPlayers is max length 8
  275. int i;
  276. for( i=0;i<iNumCappers;i++ )
  277. {
  278. cappers[i] = (char)pCappingPlayers[i];
  279. }
  280. cappers[i] = '\0';
  281. // pCappingPlayers is a null terminated list of player indeces
  282. event->SetString( "cappers", cappers );
  283. event->SetInt( "priority", 9 );
  284. event->SetBool( "bomb", m_bSetOwnerIsBombPlant );
  285. gameeventmanager->FireEvent( event );
  286. }
  287. }
  288. void CControlPoint::CaptureBlocked( CDODPlayer *pPlayer )
  289. {
  290. if( strlen( STRING(m_iszPrintName) ) <= 0 )
  291. return;
  292. IGameEvent *event = gameeventmanager->CreateEvent( "dod_capture_blocked" );
  293. if ( event )
  294. {
  295. event->SetInt( "cp", m_iPointIndex );
  296. event->SetString( "cpname", STRING(m_iszPrintName) );
  297. event->SetInt( "blocker", pPlayer->entindex() );
  298. event->SetInt( "priority", 9 );
  299. event->SetBool( "bomb", GetBombsRemaining() > 0 );
  300. gameeventmanager->FireEvent( event );
  301. }
  302. pPlayer->AddScore( PLAYER_POINTS_FOR_BLOCK );
  303. if ( GetBombsRemaining() <= 0 ) // no bomb blocks ( kills planter or defuser )
  304. {
  305. pPlayer->StatEvent_CaptureBlocked();
  306. }
  307. pPlayer->Stats_AreaDefended();
  308. DODGameRules()->Stats_PlayerDefended( pPlayer->GetTeamNumber(), pPlayer->m_Shared.DesiredPlayerClass() );
  309. }
  310. // GetOwner
  311. // ========
  312. // returns the current owner
  313. // 2 for allies
  314. // 3 for axis
  315. // 0 if noone owns it
  316. int CControlPoint::GetOwner( void ) const
  317. {
  318. return m_iTeam;
  319. }
  320. int CControlPoint::GetDefaultOwner( void ) const
  321. {
  322. return m_iDefaultOwner;
  323. }
  324. int CControlPoint::GetCPGroup( void )
  325. {
  326. return m_iCPGroup;
  327. }
  328. // PointValue
  329. // ==========
  330. // returns the time-based point value of this control point
  331. int CControlPoint::PointValue( void )
  332. {
  333. // teams earn 0 points for a flag they start with
  334. // after that its 1 additional point for each flag closer to the spawn.
  335. int value = 0;
  336. if ( FBitSet( m_spawnflags, CAP_POINT_TICK_FOR_BOMBS_REMAINING ) )
  337. {
  338. value = m_iBombsRemaining;
  339. }
  340. else if ( GetOwner() == m_iDefaultOwner )
  341. {
  342. value = 0;
  343. }
  344. else
  345. {
  346. if ( GetOwner() == TEAM_ALLIES )
  347. {
  348. value = m_iTimedPointsAllies;
  349. }
  350. else if ( GetOwner() == TEAM_AXIS )
  351. {
  352. value = m_iTimedPointsAxis;
  353. }
  354. }
  355. return value;
  356. }
  357. //precache the necessary models and sounds
  358. void CControlPoint::Precache( void )
  359. {
  360. if ( m_iszAlliesCapSound != NULL_STRING )
  361. {
  362. PrecacheScriptSound( STRING(m_iszAlliesCapSound) );
  363. }
  364. if ( m_iszAxisCapSound != NULL_STRING )
  365. {
  366. PrecacheScriptSound( STRING(m_iszAxisCapSound) );
  367. }
  368. if ( m_iszResetSound != NULL_STRING )
  369. {
  370. PrecacheScriptSound( STRING(m_iszResetSound) );
  371. }
  372. PrecacheModel( STRING( m_iszAlliesModel ) );
  373. PrecacheModel( STRING( m_iszAxisModel ) );
  374. PrecacheModel( STRING( m_iszResetModel ) );
  375. PrecacheMaterial( STRING( m_iszAlliesIcon ) );
  376. m_iAlliesIcon = GetMaterialIndex( STRING( m_iszAlliesIcon ) );
  377. Assert( m_iAlliesIcon != 0 );
  378. PrecacheMaterial( STRING( m_iszAxisIcon ) );
  379. m_iAxisIcon = GetMaterialIndex( STRING( m_iszAxisIcon ) );
  380. Assert( m_iAxisIcon != 0 );
  381. PrecacheMaterial( STRING( m_iszNeutralIcon ) );
  382. m_iNeutralIcon = GetMaterialIndex( STRING( m_iszNeutralIcon ) );
  383. Assert( m_iNeutralIcon != 0 );
  384. if ( strlen( STRING( m_iszTimerCapIcon ) ) > 0 )
  385. {
  386. PrecacheMaterial( STRING( m_iszTimerCapIcon ) );
  387. m_iTimerCapIcon = GetMaterialIndex( STRING( m_iszTimerCapIcon ) );
  388. }
  389. if ( strlen( STRING( m_iszBombedIcon ) ) > 0 )
  390. {
  391. PrecacheMaterial( STRING( m_iszBombedIcon ) );
  392. m_iBombedIcon = GetMaterialIndex( STRING( m_iszBombedIcon ) );
  393. }
  394. if( !m_iNeutralIcon || !m_iAxisIcon || !m_iAlliesIcon )
  395. {
  396. Warning( "Invalid hud icon material in control point ( point index %d )\n", GetPointIndex() );
  397. }
  398. }
  399. // Keyvalue
  400. // ========
  401. // this function interfaces with the keyvalues set by the mapper
  402. //
  403. // Values:
  404. // point_name - the name of the point displayed in the capture string ( and ControlStatus command )
  405. // point_reset_time - time after which the point spontaneously resets - currently not used
  406. // point_default_owner - the owner of this point at the start and after resets
  407. // point_allies_capsound |
  408. // point_axis_capsound | the sounds that are made when the points are capped by each team
  409. // point_resetsound |
  410. //
  411. // point_allies_model |
  412. // point_axis_model | the models that the ent is set to after each team caps it
  413. // point_reset_model |
  414. //point_team_points - number of team points to give to the capper's team for capping
  415. bool CControlPoint::KeyValue( const char *szKeyName, const char *szValue )
  416. {
  417. if (FStrEq(szKeyName, "point_default_owner"))
  418. {
  419. m_iDefaultOwner = atoi(szValue);
  420. Assert( m_iDefaultOwner == TEAM_ALLIES ||
  421. m_iDefaultOwner == TEAM_AXIS ||
  422. m_iDefaultOwner == TEAM_UNASSIGNED );
  423. if( m_iDefaultOwner != TEAM_ALLIES &&
  424. m_iDefaultOwner != TEAM_AXIS &&
  425. m_iDefaultOwner != TEAM_UNASSIGNED )
  426. {
  427. Warning( "dod_control_point with bad point_default_owner - probably '1'\n" );
  428. m_iDefaultOwner = TEAM_UNASSIGNED;
  429. }
  430. }
  431. else if (FStrEq(szKeyName, "point_allies_model_bodygroup"))
  432. {
  433. m_iAlliesModelBodygroup = atoi(szValue);
  434. }
  435. else if (FStrEq(szKeyName, "point_axis_model_bodygroup"))
  436. {
  437. m_iAxisModelBodygroup = atoi(szValue);
  438. }
  439. else if (FStrEq(szKeyName, "point_reset_model_bodygroup"))
  440. {
  441. m_iResetModelBodygroup = atoi(szValue);
  442. }
  443. else if (FStrEq(szKeyName, "point_index"))
  444. {
  445. m_iPointIndex = atoi(szValue);
  446. }
  447. else if (FStrEq(szKeyName, "point_hud_icon_allies"))
  448. {
  449. m_iszAlliesIcon = AllocPooledString(szValue);
  450. }
  451. else if (FStrEq(szKeyName, "point_hud_icon_axis"))
  452. {
  453. m_iszAxisIcon = AllocPooledString(szValue);
  454. }
  455. else if (FStrEq(szKeyName, "point_hud_icon_neutral"))
  456. {
  457. m_iszNeutralIcon = AllocPooledString(szValue);
  458. }
  459. else if (FStrEq(szKeyName, "point_hud_icon_timercap"))
  460. {
  461. m_iszTimerCapIcon = AllocPooledString(szValue);
  462. }
  463. else if (FStrEq(szKeyName, "point_hud_icon_bombed"))
  464. {
  465. m_iszBombedIcon = AllocPooledString(szValue);
  466. }
  467. else
  468. return CBaseEntity::KeyValue( szKeyName, szValue );
  469. return true;
  470. }
  471. void CControlPoint::SetActive( bool active )
  472. {
  473. m_bActive = active;
  474. if( active )
  475. {
  476. RemoveEffects( EF_NODRAW );
  477. }
  478. else
  479. {
  480. AddEffects( EF_NODRAW );
  481. }
  482. }
  483. void CControlPoint::BombPlanted( float flTimerLength, CDODPlayer *pPlantingPlayer )
  484. {
  485. if ( m_bBombPlanted == true )
  486. {
  487. Warning( "ERROR - dod_control_point only supports one bomb being planted at once\n" );
  488. return;
  489. }
  490. //send it to everyone
  491. IGameEvent *event = gameeventmanager->CreateEvent( "dod_bomb_planted" );
  492. if ( event )
  493. {
  494. int iOppositeTeam = ( pPlantingPlayer->GetTeamNumber() == TEAM_ALLIES ) ? TEAM_AXIS : TEAM_ALLIES;
  495. event->SetInt( "team", iOppositeTeam );
  496. event->SetInt( "cp", m_iPointIndex );
  497. event->SetString( "cpname", STRING(m_iszPrintName) );
  498. event->SetInt( "userid", pPlantingPlayer->GetUserID() );
  499. gameeventmanager->FireEvent( event );
  500. }
  501. m_bBombPlanted = true;
  502. m_flBombExplodeTime = gpGlobals->curtime + flTimerLength;
  503. // give the planter a point
  504. pPlantingPlayer->AddScore( PLAYER_POINTS_FOR_BOMB_PLANT );
  505. pPlantingPlayer->StatEvent_BombPlanted();
  506. // set hud display
  507. // this triggers the countdown ( using a shared, constant bomb timer )
  508. g_pObjectiveResource->SetBombPlanted( GetPointIndex(), true );
  509. }
  510. void CControlPoint::BombExploded( CDODPlayer *pPlantingPlayer /* = NULL */, int iPlantingTeam /* = TEAM_UNASSIGNED */ )
  511. {
  512. m_bBombPlanted = false;
  513. m_iBombsRemaining -= 1;
  514. g_pObjectiveResource->SetBombsRemaining( GetPointIndex(), m_iBombsRemaining );
  515. if ( pPlantingPlayer )
  516. {
  517. IGameEvent *event = gameeventmanager->CreateEvent( "dod_bomb_exploded" );
  518. if ( event )
  519. {
  520. event->SetInt( "cp", m_iPointIndex );
  521. event->SetString( "cpname", STRING(m_iszPrintName) );
  522. event->SetInt( "userid", pPlantingPlayer->GetUserID() );
  523. gameeventmanager->FireEvent( event );
  524. }
  525. pPlantingPlayer->Stats_BombDetonated();
  526. int iCappingPlayer = pPlantingPlayer->entindex();
  527. DODGameRules()->CapEvent( CAP_EVENT_BOMB, iPlantingTeam );
  528. if ( m_iBombsRemaining <= 0 )
  529. {
  530. m_bSetOwnerIsBombPlant = true;
  531. InternalSetOwner( iPlantingTeam, true, 1, &iCappingPlayer );
  532. g_pObjectiveResource->SetOwningTeam( GetPointIndex(), GetOwner() );
  533. m_bSetOwnerIsBombPlant = false;
  534. // top up points so it equals PLAYER_POINTS_FOR_BOMB_EXPLODED
  535. pPlantingPlayer->AddScore( PLAYER_POINTS_FOR_BOMB_EXPLODED - PLAYER_POINTS_FOR_CAP );
  536. }
  537. else
  538. {
  539. // give that bomber a point!
  540. pPlantingPlayer->AddScore( PLAYER_POINTS_FOR_BOMB_EXPLODED );
  541. pPlantingPlayer->Stats_AreaCaptured();
  542. pPlantingPlayer->StatEvent_PointCaptured();
  543. // send something to death notices to show that something was accomplished
  544. IGameEvent * event = gameeventmanager->CreateEvent( "dod_point_captured" );
  545. if ( event )
  546. {
  547. event->SetInt( "cp", m_iPointIndex );
  548. event->SetString( "cpname", STRING(m_iszPrintName) );
  549. char cappers[3];
  550. cappers[0] = iCappingPlayer;
  551. cappers[1] = '\0';
  552. // pCappingPlayers is a null terminated list of player indeces
  553. event->SetString( "cappers", cappers );
  554. event->SetInt( "priority", 9 );
  555. event->SetBool( "bomb", true );
  556. gameeventmanager->FireEvent( event );
  557. }
  558. }
  559. }
  560. else
  561. {
  562. if ( m_iBombsRemaining <= 0 )
  563. {
  564. // get the opposite team
  565. int team = ( GetOwner() == TEAM_ALLIES ) ? TEAM_AXIS : TEAM_ALLIES;
  566. InternalSetOwner( team, true );
  567. g_pObjectiveResource->SetOwningTeam( GetPointIndex(), GetOwner() );
  568. }
  569. }
  570. g_pObjectiveResource->SetBombPlanted( GetPointIndex(), false );
  571. }
  572. void CControlPoint::BombDisarmed( CDODPlayer *pDisarmingPlayer )
  573. {
  574. CancelBombPlanted();
  575. CaptureBlocked( pDisarmingPlayer );
  576. IGameEvent *event = gameeventmanager->CreateEvent( "dod_bomb_defused" );
  577. if ( event )
  578. {
  579. event->SetInt( "cp", m_iPointIndex );
  580. event->SetString( "cpname", STRING(m_iszPrintName) );
  581. event->SetInt( "userid", pDisarmingPlayer->GetUserID() );
  582. event->SetInt( "team", pDisarmingPlayer->GetTeamNumber() );
  583. gameeventmanager->FireEvent( event );
  584. }
  585. }
  586. void CControlPoint::CancelBombPlanted( void )
  587. {
  588. m_bBombPlanted = false;
  589. // reset hud display
  590. g_pObjectiveResource->SetBombPlanted( GetPointIndex(), false );
  591. }