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.

1155 lines
28 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Contains entities for implementing/changing game rules dynamically within each BSP.
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "datamap.h"
  8. #include "gamerules.h"
  9. #include "maprules.h"
  10. #include "player.h"
  11. #include "entitylist.h"
  12. #include "ai_hull.h"
  13. #include "entityoutput.h"
  14. #if defined( CSTRIKE15 )
  15. #include "weapon_csbase.h"
  16. #include "cs_weapon_parse.h"
  17. #include "cs_shareddefs.h"
  18. #include "cs_gamerules.h"
  19. #include "cs_player.h"
  20. #endif
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include "tier0/memdbgon.h"
  23. BEGIN_DATADESC( CRuleEntity )
  24. DEFINE_KEYFIELD( m_iszMaster, FIELD_STRING, "master" ),
  25. END_DATADESC()
  26. void CRuleEntity::Spawn( void )
  27. {
  28. SetSolid( SOLID_NONE );
  29. SetMoveType( MOVETYPE_NONE );
  30. AddEffects( EF_NODRAW );
  31. }
  32. bool CRuleEntity::CanFireForActivator( CBaseEntity *pActivator )
  33. {
  34. if ( m_iszMaster != NULL_STRING )
  35. {
  36. if ( UTIL_IsMasterTriggered( m_iszMaster, pActivator ) )
  37. return true;
  38. else
  39. return false;
  40. }
  41. return true;
  42. }
  43. //---------------------------------------------------------
  44. // Save/Restore
  45. //---------------------------------------------------------
  46. BEGIN_DATADESC( CRulePointEntity )
  47. DEFINE_FIELD( m_Score, FIELD_INTEGER ),
  48. END_DATADESC()
  49. void CRulePointEntity::Spawn( void )
  50. {
  51. BaseClass::Spawn();
  52. SetModelName( NULL_STRING );
  53. m_Score = 0;
  54. }
  55. //
  56. // CRuleBrushEntity -- base class for all rule "brush" entities (not brushes)
  57. // Default behavior is to set up like a trigger, invisible, but keep the model for volume testing
  58. //
  59. class CRuleBrushEntity : public CRuleEntity
  60. {
  61. public:
  62. DECLARE_CLASS( CRuleBrushEntity, CRuleEntity );
  63. void Spawn( void );
  64. private:
  65. };
  66. void CRuleBrushEntity::Spawn( void )
  67. {
  68. SetModel( STRING( GetModelName() ) );
  69. BaseClass::Spawn();
  70. }
  71. // CGameScore / game_score -- award points to player / team
  72. // Points +/- total
  73. // Flag: Allow negative scores SF_SCORE_NEGATIVE
  74. // Flag: Award points to team in teamplay SF_SCORE_TEAM
  75. #define SF_SCORE_NEGATIVE 0x0001
  76. #define SF_SCORE_TEAM 0x0002
  77. class CGameScore : public CRulePointEntity
  78. {
  79. public:
  80. DECLARE_CLASS( CGameScore, CRulePointEntity );
  81. DECLARE_DATADESC();
  82. void Spawn( void );
  83. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  84. bool KeyValue( const char *szKeyName, const char *szValue );
  85. inline int Points( void ) { return m_Score; }
  86. inline bool AllowNegativeScore( void ) { return m_spawnflags & SF_SCORE_NEGATIVE; }
  87. inline int AwardToTeam( void ) { return (m_spawnflags & SF_SCORE_TEAM); }
  88. inline void SetPoints( int points ) { m_Score = points; }
  89. void InputApplyScore( inputdata_t &inputdata );
  90. #if defined( CSTRIKE15 )
  91. void InputAddScoreTerrorist( inputdata_t &inputdata );
  92. void InputAddScoreCT( inputdata_t &inputdata );
  93. #endif
  94. private:
  95. };
  96. LINK_ENTITY_TO_CLASS( game_score, CGameScore );
  97. BEGIN_DATADESC( CGameScore )
  98. // Inputs
  99. DEFINE_INPUTFUNC( FIELD_VOID, "ApplyScore", InputApplyScore ),
  100. DEFINE_INPUTFUNC( FIELD_VOID, "AddScoreTerrorist", InputAddScoreTerrorist ),
  101. DEFINE_INPUTFUNC( FIELD_VOID, "AddScoreCT", InputAddScoreCT ),
  102. END_DATADESC()
  103. void CGameScore::Spawn( void )
  104. {
  105. int iScore = Points();
  106. BaseClass::Spawn();
  107. SetPoints( iScore );
  108. }
  109. bool CGameScore::KeyValue( const char *szKeyName, const char *szValue )
  110. {
  111. if (FStrEq(szKeyName, "points"))
  112. {
  113. SetPoints( atoi(szValue) );
  114. }
  115. else
  116. return BaseClass::KeyValue( szKeyName, szValue );
  117. return true;
  118. }
  119. void CGameScore::InputApplyScore( inputdata_t &inputdata )
  120. {
  121. CBaseEntity *pActivator = inputdata.pActivator;
  122. if ( pActivator == NULL )
  123. return;
  124. if ( CanFireForActivator( pActivator ) == false )
  125. return;
  126. // Only players can use this
  127. if ( pActivator->IsPlayer() )
  128. {
  129. if ( AwardToTeam() )
  130. {
  131. pActivator->AddPointsToTeam( Points(), AllowNegativeScore() );
  132. }
  133. else
  134. {
  135. pActivator->AddPoints( Points(), AllowNegativeScore() );
  136. }
  137. }
  138. }
  139. #if defined( CSTRIKE15 )
  140. void CGameScore::InputAddScoreTerrorist( inputdata_t &inputdata )
  141. {
  142. CCSMatch* match = CSGameRules()->GetMatch();
  143. if ( match )
  144. {
  145. match->AddTerroristScore( Points() );
  146. }
  147. }
  148. void CGameScore::InputAddScoreCT( inputdata_t &inputdata )
  149. {
  150. CCSMatch* match = CSGameRules()->GetMatch();
  151. if ( match )
  152. {
  153. match->AddCTScore( Points() );
  154. }
  155. }
  156. #endif
  157. void CGameScore::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  158. {
  159. if ( !CanFireForActivator( pActivator ) )
  160. return;
  161. // Only players can use this
  162. if ( pActivator->IsPlayer() )
  163. {
  164. if ( AwardToTeam() )
  165. {
  166. pActivator->AddPointsToTeam( Points(), AllowNegativeScore() );
  167. }
  168. else
  169. {
  170. pActivator->AddPoints( Points(), AllowNegativeScore() );
  171. }
  172. }
  173. }
  174. BEGIN_ENT_SCRIPTDESC( CGameCoopMissionManager, CBaseEntity, "game_coopmission_manager" )
  175. DEFINE_SCRIPTFUNC_NAMED( GetWaveNumber, "GetWaveNumber", "Get the number of waves the players have completed" )
  176. END_SCRIPTDESC()
  177. LINK_ENTITY_TO_CLASS( game_coopmission_manager, CGameCoopMissionManager );
  178. BEGIN_DATADESC( CGameCoopMissionManager )
  179. // inputs
  180. //DEFINE_INPUTFUNC( FIELD_FLOAT, "EndRound_Draw", InputEndRound_Draw ),
  181. DEFINE_OUTPUT( m_OnWaveCompleted, "OnWaveCompleted" ),
  182. DEFINE_OUTPUT( m_OnRoundReset, "OnRoundReset" ),
  183. DEFINE_OUTPUT( m_OnSpawnsReset, "OnSpawnsReset" ),
  184. DEFINE_OUTPUT( m_OnRoundLostKilled, "OnRoundLostKilled" ),
  185. DEFINE_OUTPUT( m_OnRoundLostTime, "OnRoundLostTime" ),
  186. DEFINE_OUTPUT( m_OnMissionCompleted, "OnMissionCompleted" ),
  187. END_DATADESC()
  188. void CGameCoopMissionManager::Spawn( void )
  189. {
  190. BaseClass::Spawn();
  191. }
  192. bool CGameCoopMissionManager::KeyValue( const char *szKeyName, const char *szValue )
  193. {
  194. return BaseClass::KeyValue( szKeyName, szValue );
  195. }
  196. int CGameCoopMissionManager::GetWaveNumber( void )
  197. {
  198. if ( !CSGameRules() )
  199. return 0;
  200. return CSGameRules()->GetCoopWaveNumber();
  201. }
  202. void CGameCoopMissionManager::SetWaveCompleted( void )
  203. {
  204. // send output
  205. m_OnWaveCompleted.FireOutput( NULL, NULL );
  206. }
  207. void CGameCoopMissionManager::SetRoundReset( void )
  208. {
  209. // send output
  210. m_OnRoundReset.FireOutput( NULL, NULL );
  211. }
  212. void CGameCoopMissionManager::SetSpawnsReset( void )
  213. {
  214. // send output
  215. m_OnSpawnsReset.FireOutput( NULL, NULL );
  216. }
  217. void CGameCoopMissionManager::SetRoundLostKilled( void )
  218. {
  219. // send output
  220. m_OnRoundLostKilled.FireOutput( NULL, NULL );
  221. }
  222. void CGameCoopMissionManager::SetRoundLostTime( void )
  223. {
  224. // send output
  225. m_OnRoundLostTime.FireOutput( NULL, NULL );
  226. }
  227. void CGameCoopMissionManager::SetMissionCompleted( void )
  228. {
  229. // send output
  230. m_OnMissionCompleted.FireOutput( NULL, NULL );
  231. }
  232. // void CGameCoopMissionManager::InputApplyScore( inputdata_t &inputdata )
  233. // {
  234. // CBaseEntity *pActivator = inputdata.pActivator;
  235. //
  236. // if ( pActivator == NULL )
  237. // return;
  238. //
  239. // if ( CanFireForActivator( pActivator ) == false )
  240. // return;
  241. //
  242. // // Only players can use this
  243. // if ( pActivator->IsPlayer() )
  244. // {
  245. // if ( AwardToTeam() )
  246. // {
  247. // pActivator->AddPointsToTeam( Points(), AllowNegativeScore() );
  248. // }
  249. // else
  250. // {
  251. // pActivator->AddPoints( Points(), AllowNegativeScore() );
  252. // }
  253. // }
  254. // }
  255. #if defined( CSTRIKE15 )
  256. // CGameMoney / game_money -- award money to player / team
  257. class CGameMoney : public CRulePointEntity
  258. {
  259. public:
  260. DECLARE_CLASS( CGameMoney, CRulePointEntity );
  261. DECLARE_DATADESC();
  262. void Spawn( void );
  263. inline int Money( void ) { return m_nMoney; }
  264. void InputSetMoneyAmount( inputdata_t &inputdata );
  265. void InputSetTeamMoneyTerrorist( inputdata_t &inputdata );
  266. void InputSetTeamMoneyCT( inputdata_t &inputdata );
  267. void InputAddTeamMoneyTerrorist( inputdata_t &inputdata );
  268. void InputAddTeamMoneyCT( inputdata_t &inputdata );
  269. void InputAddMoneyPlayer( inputdata_t &inputdata );
  270. private:
  271. int m_nMoney;
  272. string_t m_strAwardText;
  273. };
  274. LINK_ENTITY_TO_CLASS( game_money, CGameMoney );
  275. BEGIN_DATADESC( CGameMoney )
  276. DEFINE_KEYFIELD( m_nMoney, FIELD_INTEGER, "Money" ),
  277. DEFINE_KEYFIELD( m_strAwardText, FIELD_STRING, "AwardText" ),
  278. // Inputs
  279. DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMoneyAmount", InputSetMoneyAmount ),
  280. DEFINE_INPUTFUNC( FIELD_VOID, "AddTeamMoneyTerrorist", InputAddTeamMoneyTerrorist ),
  281. DEFINE_INPUTFUNC( FIELD_VOID, "AddTeamMoneyCT", InputAddTeamMoneyCT ),
  282. DEFINE_INPUTFUNC( FIELD_VOID, "AddMoneyPlayer", InputAddMoneyPlayer ),
  283. END_DATADESC()
  284. void CGameMoney::Spawn( void )
  285. {
  286. BaseClass::Spawn();
  287. }
  288. void CGameMoney::InputSetMoneyAmount( inputdata_t &inputdata )
  289. {
  290. int nMoney = inputdata.value.Int();
  291. m_nMoney = nMoney;
  292. }
  293. void CGameMoney::InputAddMoneyPlayer( inputdata_t &inputdata )
  294. {
  295. CBaseEntity *pActivator = inputdata.pActivator;
  296. if ( pActivator == NULL )
  297. return;
  298. // if ( CanFireForActivator( pActivator ) == false )
  299. // return;
  300. // Only players can use this
  301. if ( pActivator->IsPlayer() )
  302. {
  303. int nMoney = clamp( m_nMoney, 0, CSGameRules()->GetMaxMoney() );
  304. CCSPlayer *pPlayer = dynamic_cast<CCSPlayer*>( inputdata.pActivator );
  305. pPlayer->AddAccount( nMoney, true, false );
  306. }
  307. }
  308. void CGameMoney::InputAddTeamMoneyTerrorist( inputdata_t &inputdata )
  309. {
  310. int nMoney = clamp( m_nMoney, 0, CSGameRules()->GetMaxMoney() );
  311. CSGameRules()->AddTeamAccount( TEAM_TERRORIST, TeamCashAward::CUSTOM_AWARD, nMoney, STRING(m_strAwardText) );
  312. }
  313. void CGameMoney::InputAddTeamMoneyCT( inputdata_t &inputdata )
  314. {
  315. int nMoney = clamp( m_nMoney, 0, CSGameRules()->GetMaxMoney() );
  316. CSGameRules()->AddTeamAccount( TEAM_CT, TeamCashAward::CUSTOM_AWARD, nMoney, STRING(m_strAwardText) );
  317. }
  318. #endif
  319. // CGameEnd / game_end -- Ends the game in MP
  320. class CGameEnd : public CRulePointEntity
  321. {
  322. DECLARE_CLASS( CGameEnd, CRulePointEntity );
  323. public:
  324. DECLARE_DATADESC();
  325. void InputGameEnd( inputdata_t &inputdata );
  326. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  327. private:
  328. };
  329. BEGIN_DATADESC( CGameEnd )
  330. // inputs
  331. DEFINE_INPUTFUNC( FIELD_VOID, "EndGame", InputGameEnd ),
  332. END_DATADESC()
  333. LINK_ENTITY_TO_CLASS( game_end, CGameEnd );
  334. void CGameEnd::InputGameEnd( inputdata_t &inputdata )
  335. {
  336. g_pGameRules->EndMultiplayerGame();
  337. }
  338. void CGameEnd::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  339. {
  340. if ( !CanFireForActivator( pActivator ) )
  341. return;
  342. g_pGameRules->EndMultiplayerGame();
  343. }
  344. #if defined( CSTRIKE15 )
  345. // CGameEnd / game_round_end -- Ends the round in MP
  346. class CGameRoundEnd : public CRulePointEntity , public CGameEventListener
  347. {
  348. DECLARE_CLASS( CGameRoundEnd, CRulePointEntity );
  349. public:
  350. DECLARE_DATADESC();
  351. CGameRoundEnd();
  352. virtual void FireGameEvent( IGameEvent *event );
  353. void InputEndRound_Draw( inputdata_t &inputdata );
  354. void InputEndRound_TerroristsWin( inputdata_t &inputdata );
  355. void InputEndRound_CounterTerroristsWin( inputdata_t &inputdata );
  356. private:
  357. COutputEvent m_OnRoundEnded;
  358. //m_OnForcedInteractionFinished.FireOutput( this, this );
  359. };
  360. BEGIN_DATADESC( CGameRoundEnd )
  361. // inputs
  362. DEFINE_INPUTFUNC( FIELD_FLOAT, "EndRound_Draw", InputEndRound_Draw ),
  363. DEFINE_INPUTFUNC( FIELD_FLOAT, "EndRound_TerroristsWin", InputEndRound_TerroristsWin ),
  364. DEFINE_INPUTFUNC( FIELD_FLOAT, "EndRound_CounterTerroristsWin", InputEndRound_CounterTerroristsWin ),
  365. DEFINE_OUTPUT( m_OnRoundEnded, "OnRoundEnded" ),
  366. END_DATADESC()
  367. LINK_ENTITY_TO_CLASS( game_round_end, CGameRoundEnd );
  368. CGameRoundEnd::CGameRoundEnd()
  369. {
  370. ListenForGameEvent( "round_end" );
  371. }
  372. void CGameRoundEnd::FireGameEvent( IGameEvent *event )
  373. {
  374. const char *name = event->GetName();
  375. if ( Q_strcmp( name, "round_end" ) == 0 )
  376. {
  377. m_OnRoundEnded.FireOutput( NULL, NULL );
  378. }
  379. }
  380. void CGameRoundEnd::InputEndRound_Draw( inputdata_t &inputdata )
  381. {
  382. float flDelay = inputdata.value.Float();
  383. CSGameRules()->IncrementAndTerminateRound( flDelay, Round_Draw );
  384. }
  385. void CGameRoundEnd::InputEndRound_TerroristsWin( inputdata_t &inputdata )
  386. {
  387. float flDelay = inputdata.value.Float();
  388. CSGameRules()->IncrementAndTerminateRound( flDelay, Terrorists_Win );
  389. }
  390. void CGameRoundEnd::InputEndRound_CounterTerroristsWin( inputdata_t &inputdata )
  391. {
  392. float flDelay = inputdata.value.Float();
  393. CSGameRules()->IncrementAndTerminateRound( flDelay, CTs_Win );
  394. }
  395. #endif
  396. //
  397. // CGameText / game_text -- NON-Localized HUD Message (use env_message to display a titles.txt message)
  398. // Flag: All players SF_ENVTEXT_ALLPLAYERS
  399. //
  400. #define SF_ENVTEXT_ALLPLAYERS 0x0001
  401. class CGameText : public CRulePointEntity
  402. {
  403. public:
  404. DECLARE_CLASS( CGameText, CRulePointEntity );
  405. bool KeyValue( const char *szKeyName, const char *szValue );
  406. DECLARE_DATADESC();
  407. inline bool MessageToAll( void ) { return (m_spawnflags & SF_ENVTEXT_ALLPLAYERS); }
  408. inline void MessageSet( const char *pMessage ) { m_iszMessage = AllocPooledString(pMessage); }
  409. inline const char *MessageGet( void ) { return STRING( m_iszMessage ); }
  410. void InputDisplay( inputdata_t &inputdata );
  411. void Display( CBaseEntity *pActivator );
  412. void InputSetText ( inputdata_t &inputdata );
  413. void SetText( const char* pszStr );
  414. void InputSetPosX( inputdata_t &inputdata );
  415. void SetPosX( float flPosX );
  416. void InputSetPosY( inputdata_t &inputdata );
  417. void SetPosY( float flPosY );
  418. void InputSetTextColor( inputdata_t &inputdata );
  419. void SetTextColor( color32 color );
  420. void InputSetTextColor2( inputdata_t &inputdata );
  421. void SetTextColor2( color32 color );
  422. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  423. {
  424. Display( pActivator );
  425. }
  426. private:
  427. string_t m_iszMessage;
  428. hudtextparms_t m_textParms;
  429. };
  430. LINK_ENTITY_TO_CLASS( game_text, CGameText );
  431. // Save parms as a block. Will break save/restore if the structure changes, but this entity didn't ship with Half-Life, so
  432. // it can't impact saved Half-Life games.
  433. BEGIN_DATADESC( CGameText )
  434. DEFINE_KEYFIELD( m_iszMessage, FIELD_STRING, "message" ),
  435. DEFINE_KEYFIELD( m_textParms.channel, FIELD_INTEGER, "channel" ),
  436. DEFINE_KEYFIELD( m_textParms.x, FIELD_FLOAT, "x" ),
  437. DEFINE_KEYFIELD( m_textParms.y, FIELD_FLOAT, "y" ),
  438. DEFINE_KEYFIELD( m_textParms.effect, FIELD_INTEGER, "effect" ),
  439. DEFINE_KEYFIELD( m_textParms.fadeinTime, FIELD_FLOAT, "fadein" ),
  440. DEFINE_KEYFIELD( m_textParms.fadeoutTime, FIELD_FLOAT, "fadeout" ),
  441. DEFINE_KEYFIELD( m_textParms.holdTime, FIELD_FLOAT, "holdtime" ),
  442. DEFINE_KEYFIELD( m_textParms.fxTime, FIELD_FLOAT, "fxtime" ),
  443. DEFINE_ARRAY( m_textParms, FIELD_CHARACTER, sizeof(hudtextparms_t) ),
  444. // Inputs
  445. DEFINE_INPUTFUNC( FIELD_VOID, "Display", InputDisplay ),
  446. DEFINE_INPUTFUNC( FIELD_STRING, "SetText", InputSetText ),
  447. DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPosX", InputSetPosX ),
  448. DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPosY", InputSetPosY ),
  449. DEFINE_INPUTFUNC( FIELD_COLOR32, "SetTextColor", InputSetTextColor ),
  450. DEFINE_INPUTFUNC( FIELD_COLOR32, "SetTextColor2", InputSetTextColor2 ),
  451. END_DATADESC()
  452. bool CGameText::KeyValue( const char *szKeyName, const char *szValue )
  453. {
  454. if (FStrEq(szKeyName, "color"))
  455. {
  456. int color[4];
  457. V_StringToIntArray( color, 4, szValue );
  458. m_textParms.r1 = color[0];
  459. m_textParms.g1 = color[1];
  460. m_textParms.b1 = color[2];
  461. m_textParms.a1 = color[3];
  462. }
  463. else if (FStrEq(szKeyName, "color2"))
  464. {
  465. int color[4];
  466. V_StringToIntArray( color, 4, szValue );
  467. m_textParms.r2 = color[0];
  468. m_textParms.g2 = color[1];
  469. m_textParms.b2 = color[2];
  470. m_textParms.a2 = color[3];
  471. }
  472. else
  473. return BaseClass::KeyValue( szKeyName, szValue );
  474. return true;
  475. }
  476. void CGameText::InputDisplay( inputdata_t &inputdata )
  477. {
  478. Display( inputdata.pActivator );
  479. }
  480. void CGameText::Display( CBaseEntity *pActivator )
  481. {
  482. if ( !CanFireForActivator( pActivator ) )
  483. return;
  484. if ( MessageToAll() )
  485. {
  486. UTIL_HudMessageAll( m_textParms, MessageGet() );
  487. }
  488. else
  489. {
  490. // If we're in singleplayer, show the message to the player.
  491. if ( gpGlobals->maxClients == 1 )
  492. {
  493. CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
  494. UTIL_HudMessage( pPlayer, m_textParms, MessageGet() );
  495. }
  496. // Otherwise show the message to the player that triggered us.
  497. else if ( pActivator && pActivator->IsNetClient() )
  498. {
  499. UTIL_HudMessage( ToBasePlayer( pActivator ), m_textParms, MessageGet() );
  500. }
  501. }
  502. }
  503. void CGameText::InputSetText( inputdata_t &inputdata )
  504. {
  505. SetText( inputdata.value.String() );
  506. }
  507. void CGameText::SetText( const char* pszStr )
  508. {
  509. m_iszMessage = AllocPooledString( pszStr );
  510. }
  511. void CGameText::InputSetPosX( inputdata_t &inputdata )
  512. {
  513. SetPosX( inputdata.value.Float() );
  514. }
  515. void CGameText::SetPosX( float flPosX )
  516. {
  517. m_textParms.x = flPosX;
  518. }
  519. void CGameText::InputSetPosY( inputdata_t &inputdata )
  520. {
  521. SetPosY( inputdata.value.Float() );
  522. }
  523. void CGameText::SetPosY( float flPosY )
  524. {
  525. m_textParms.y = flPosY;
  526. }
  527. void CGameText::InputSetTextColor( inputdata_t &inputdata )
  528. {
  529. SetTextColor( inputdata.value.Color32() );
  530. }
  531. void CGameText::SetTextColor( color32 color )
  532. {
  533. m_textParms.r1 = color.r;
  534. m_textParms.g1 = color.g;
  535. m_textParms.b1 = color.b;
  536. m_textParms.a1 = color.a;
  537. }
  538. void CGameText::InputSetTextColor2( inputdata_t &inputdata )
  539. {
  540. SetTextColor2( inputdata.value.Color32() );
  541. }
  542. void CGameText::SetTextColor2( color32 color )
  543. {
  544. m_textParms.r2 = color.r;
  545. m_textParms.g2 = color.g;
  546. m_textParms.b2 = color.b;
  547. m_textParms.a2 = color.a;
  548. }
  549. /* TODO: Replace with an entity I/O version
  550. //
  551. // CGameTeamSet / game_team_set -- Changes the team of the entity it targets to the activator's team
  552. // Flag: Fire once
  553. // Flag: Clear team -- Sets the team to "NONE" instead of activator
  554. #define SF_TEAMSET_FIREONCE 0x0001
  555. #define SF_TEAMSET_CLEARTEAM 0x0002
  556. class CGameTeamSet : public CRulePointEntity
  557. {
  558. public:
  559. DECLARE_CLASS( CGameTeamSet, CRulePointEntity );
  560. inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_TEAMSET_FIREONCE) ? true : false; }
  561. inline bool ShouldClearTeam( void ) { return (m_spawnflags & SF_TEAMSET_CLEARTEAM) ? true : false; }
  562. void InputTrigger( inputdata_t &inputdata );
  563. private:
  564. COutputEvent m_OnTrigger;
  565. };
  566. LINK_ENTITY_TO_CLASS( game_team_set, CGameTeamSet );
  567. void CGameTeamSet::InputTrigger( inputdata_t &inputdata )
  568. {
  569. if ( !CanFireForActivator( inputdata.pActivator ) )
  570. return;
  571. if ( ShouldClearTeam() )
  572. {
  573. // clear the team of our target
  574. }
  575. else
  576. {
  577. // set the team of our target to our activator's team
  578. }
  579. m_OnTrigger.FireOutput(pActivator, this);
  580. if ( RemoveOnFire() )
  581. {
  582. UTIL_Remove( this );
  583. }
  584. }
  585. */
  586. //
  587. // CGamePlayerZone / game_player_zone -- players in the zone fire my target when I'm fired
  588. //
  589. // Needs master?
  590. class CGamePlayerZone : public CRuleBrushEntity
  591. {
  592. public:
  593. DECLARE_CLASS( CGamePlayerZone, CRuleBrushEntity );
  594. void InputCountPlayersInZone( inputdata_t &inputdata );
  595. DECLARE_DATADESC();
  596. private:
  597. COutputEvent m_OnPlayerInZone;
  598. COutputEvent m_OnPlayerOutZone;
  599. COutputInt m_PlayersInCount;
  600. COutputInt m_PlayersOutCount;
  601. };
  602. LINK_ENTITY_TO_CLASS( game_zone_player, CGamePlayerZone );
  603. BEGIN_DATADESC( CGamePlayerZone )
  604. // Inputs
  605. DEFINE_INPUTFUNC(FIELD_VOID, "CountPlayersInZone", InputCountPlayersInZone),
  606. // Outputs
  607. DEFINE_OUTPUT(m_OnPlayerInZone, "OnPlayerInZone"),
  608. DEFINE_OUTPUT(m_OnPlayerOutZone, "OnPlayerOutZone"),
  609. DEFINE_OUTPUT(m_PlayersInCount, "PlayersInCount"),
  610. DEFINE_OUTPUT(m_PlayersOutCount, "PlayersOutCount"),
  611. END_DATADESC()
  612. //-----------------------------------------------------------------------------
  613. // Purpose: Counts all the players in the zone. Fires one output per player
  614. // in the zone, one output per player out of the zone, and outputs
  615. // with the total counts of players in and out of the zone.
  616. //-----------------------------------------------------------------------------
  617. void CGamePlayerZone::InputCountPlayersInZone( inputdata_t &inputdata )
  618. {
  619. int playersInCount = 0;
  620. int playersOutCount = 0;
  621. if ( !CanFireForActivator( inputdata.pActivator ) )
  622. return;
  623. CBaseEntity *pPlayer = NULL;
  624. for ( int i = 1; i <= gpGlobals->maxClients; i++ )
  625. {
  626. pPlayer = UTIL_PlayerByIndex( i );
  627. if ( pPlayer )
  628. {
  629. trace_t trace;
  630. Hull_t hullType;
  631. hullType = HULL_HUMAN;
  632. if ( pPlayer->GetFlags() & FL_DUCKING )
  633. {
  634. hullType = HULL_SMALL_CENTERED;
  635. }
  636. UTIL_TraceModel( pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin(), NAI_Hull::Mins(hullType),
  637. NAI_Hull::Maxs(hullType), this, COLLISION_GROUP_NONE, &trace );
  638. if ( trace.startsolid )
  639. {
  640. playersInCount++;
  641. m_OnPlayerInZone.FireOutput(pPlayer, this);
  642. }
  643. else
  644. {
  645. playersOutCount++;
  646. m_OnPlayerOutZone.FireOutput(pPlayer, this);
  647. }
  648. }
  649. }
  650. m_PlayersInCount.Set(playersInCount, inputdata.pActivator, this);
  651. m_PlayersOutCount.Set(playersOutCount, inputdata.pActivator, this);
  652. }
  653. /*
  654. // Disable. Eventually will be replace by new activator filter entities. (LHL)
  655. //
  656. // CGamePlayerHurt / game_player_hurt -- Damages the player who fires it
  657. // Flag: Fire once
  658. #define SF_PKILL_FIREONCE 0x0001
  659. class CGamePlayerHurt : public CRulePointEntity
  660. {
  661. public:
  662. DECLARE_CLASS( CGamePlayerHurt, CRulePointEntity );
  663. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  664. inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_PKILL_FIREONCE) ? true : false; }
  665. DECLARE_DATADESC();
  666. private:
  667. float m_flDamage; // Damage to inflict, negative values give health.
  668. COutputEvent m_OnUse;
  669. };
  670. LINK_ENTITY_TO_CLASS( game_player_hurt, CGamePlayerHurt );
  671. BEGIN_DATADESC( CGamePlayerHurt )
  672. DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "dmg" ),
  673. END_DATADESC()
  674. void CGamePlayerHurt::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  675. {
  676. if ( !CanFireForActivator( pActivator ) )
  677. return;
  678. if ( pActivator->IsPlayer() )
  679. {
  680. if ( m_flDamage < 0 )
  681. {
  682. pActivator->TakeHealth( -m_flDamage, DMG_GENERIC );
  683. }
  684. else
  685. {
  686. pActivator->TakeDamage( this, this, m_flDamage, DMG_GENERIC );
  687. }
  688. }
  689. SUB_UseTargets( pActivator, useType, value );
  690. m_OnUse.FireOutput(pActivator, this); // dvsents2: handle useType and value here - they are passed through
  691. if ( RemoveOnFire() )
  692. {
  693. UTIL_Remove( this );
  694. }
  695. }
  696. */
  697. //
  698. // CGamePlayerEquip / game_playerequip -- Sets the default player equipment
  699. // Flag: USE Only
  700. LINK_ENTITY_TO_CLASS( game_player_equip, CGamePlayerEquip );
  701. //---------------------------------------------------------
  702. // Save/Restore
  703. //---------------------------------------------------------
  704. BEGIN_DATADESC( CGamePlayerEquip )
  705. DEFINE_AUTO_ARRAY( m_weaponNames, FIELD_STRING ),
  706. DEFINE_AUTO_ARRAY( m_weaponCount, FIELD_INTEGER ),
  707. // Inputs
  708. DEFINE_INPUTFUNC(FIELD_VOID, "TriggerForAllPlayers", InputTriggerForAllPlayers),
  709. DEFINE_INPUTFUNC(FIELD_STRING, "TriggerForActivatedPlayer", InputTriggerForActivatedPlayer),
  710. END_DATADESC()
  711. void CGamePlayerEquip::InputTriggerForAllPlayers( inputdata_t &inputdata )
  712. {
  713. TriggerForAllPlayers();
  714. }
  715. void CGamePlayerEquip::InputTriggerForActivatedPlayer( inputdata_t &inputdata )
  716. {
  717. CBasePlayer *pPlayer = dynamic_cast<CBasePlayer*>( inputdata.pActivator );
  718. if ( pPlayer )
  719. TriggerForActivatedPlayer( pPlayer, inputdata.value.String() );
  720. }
  721. bool CGamePlayerEquip::KeyValue( const char *szKeyName, const char *szValue )
  722. {
  723. if ( !BaseClass::KeyValue( szKeyName, szValue ) )
  724. {
  725. for ( int i = 0; i < MAX_EQUIP; i++ )
  726. {
  727. if ( !m_weaponNames[i] )
  728. {
  729. char tmp[128];
  730. UTIL_StripToken( szKeyName, tmp );
  731. m_weaponNames[i] = AllocPooledString(tmp);
  732. m_weaponCount[i] = atoi(szValue);
  733. m_weaponCount[i] = MAX(0,m_weaponCount[i]);
  734. return true;
  735. }
  736. }
  737. }
  738. return false;
  739. }
  740. void CGamePlayerEquip::TriggerForAllPlayers( void )
  741. {
  742. for( int i = 1; i <= gpGlobals->maxClients; ++i )
  743. {
  744. CBasePlayer *pToPlayer = UTIL_PlayerByIndex( i );
  745. if ( pToPlayer )
  746. {
  747. if ( CanFireForActivator( pToPlayer ) )
  748. {
  749. EquipPlayer( pToPlayer );
  750. }
  751. }
  752. }
  753. }
  754. void CGamePlayerEquip::TriggerForActivatedPlayer( CBasePlayer *pPlayer, const char *szWeapon )
  755. {
  756. if ( pPlayer )
  757. {
  758. if ( CanFireForActivator( pPlayer ) )
  759. {
  760. EquipPlayer( pPlayer, szWeapon );
  761. }
  762. }
  763. }
  764. void CGamePlayerEquip::Touch( CBaseEntity *pOther )
  765. {
  766. if ( !CanFireForActivator( pOther ) )
  767. return;
  768. if ( UseOnly() )
  769. return;
  770. EquipPlayer( pOther );
  771. }
  772. void CGamePlayerEquip::EquipPlayer( CBaseEntity *pEntity, const char *szWeapon )
  773. {
  774. if ( !pEntity )
  775. return;
  776. CBasePlayer *pPlayer = NULL;
  777. if ( pEntity->IsPlayer() )
  778. {
  779. pPlayer = (CBasePlayer *)pEntity;
  780. }
  781. if ( !pPlayer )
  782. return;
  783. if ( StripFirst() )
  784. {
  785. // remove all our weapons and armor
  786. pPlayer->RemoveAllItems( true );
  787. }
  788. const char *weaponName = szWeapon;
  789. int nMaxLoop = MAX_EQUIP;
  790. if ( szWeapon != NULL )
  791. nMaxLoop = 1;
  792. for ( int i = 0; i < MAX_EQUIP; i++ )
  793. {
  794. if ( szWeapon == NULL && !m_weaponNames[i] )
  795. break;
  796. if ( szWeapon == NULL )
  797. weaponName = STRING( m_weaponNames[i] );
  798. CSWeaponID weaponID = WeaponIdFromString( weaponName );
  799. CCSPlayer *pCSPlayer = static_cast<CCSPlayer*>( pPlayer );
  800. // if it's a grenade and we don't have it, give it
  801. // if we do have it, don't do anything because you can only carry one of each grenade
  802. // TODO: if we change how many grenades you can carry, this code needs to cover that, this is poor code otherwise
  803. if ( pCSPlayer && IsGrenadeWeapon( weaponID ) )
  804. {
  805. if ( !pCSPlayer->Weapon_OwnsThisType( weaponName ) )
  806. {
  807. AcquireResult::Type acquireResult = pCSPlayer->CanAcquire( weaponID, AcquireMethod::PickUp, NULL );
  808. if ( acquireResult == AcquireResult::Allowed )
  809. pCSPlayer->GiveNamedItem( weaponName );
  810. }
  811. }
  812. else
  813. {
  814. if ( OnlyStripSameWeaponType() )
  815. {
  816. if ( weaponID == WEAPON_NONE )
  817. {
  818. for ( int i = GGLIST_PISTOLS_START; i < ( GGLIST_SNIPERS_LAST ); i++ )
  819. {
  820. const char *item_name = weaponName;
  821. if ( IsWeaponClassname( item_name ) )
  822. {
  823. item_name += WEAPON_CLASSNAME_PREFIX_LENGTH;
  824. }
  825. if ( V_strcmp( ggWeaponAliasNameList[i].aliasName, item_name ) == 0 )
  826. {
  827. weaponID = ggWeaponAliasNameList[i].id;
  828. break;
  829. }
  830. }
  831. }
  832. if ( IsPrimaryWeapon( weaponID ) )
  833. {
  834. CBaseCombatWeapon *pPrimary = pPlayer->Weapon_GetSlot( WEAPON_SLOT_RIFLE );
  835. if ( pPrimary )
  836. pPlayer->RemoveWeaponOnPlayer( pPrimary );
  837. }
  838. else if ( IsSecondaryWeapon( weaponID ) )
  839. {
  840. CBaseCombatWeapon *pSecondary = pPlayer->Weapon_GetSlot( WEAPON_SLOT_PISTOL );
  841. if ( pSecondary )
  842. pPlayer->RemoveWeaponOnPlayer( pSecondary );
  843. }
  844. }
  845. pPlayer->GiveNamedItem( weaponName );
  846. if ( const CCSWeaponInfo* pWeaponInfo = GetWeaponInfo( weaponID ) )
  847. {
  848. int nType = pWeaponInfo->GetPrimaryAmmoType();
  849. pPlayer->GiveAmmo( m_weaponCount[ i ], nType );
  850. }
  851. }
  852. }
  853. }
  854. void CGamePlayerEquip::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  855. {
  856. EquipPlayer( pActivator ); // note: pActivator may sometimes be NULL
  857. }
  858. //
  859. // CGamePlayerTeam / game_player_team -- Changes the team of the player who fired it
  860. // Flag: Fire once
  861. // Flag: Kill Player
  862. // Flag: Gib Player
  863. #define SF_PTEAM_FIREONCE 0x0001
  864. #define SF_PTEAM_KILL 0x0002
  865. #define SF_PTEAM_GIB 0x0004
  866. class CGamePlayerTeam : public CRulePointEntity
  867. {
  868. public:
  869. DECLARE_CLASS( CGamePlayerTeam, CRulePointEntity );
  870. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  871. private:
  872. inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_PTEAM_FIREONCE) ? true : false; }
  873. inline bool ShouldKillPlayer( void ) { return (m_spawnflags & SF_PTEAM_KILL) ? true : false; }
  874. inline bool ShouldGibPlayer( void ) { return (m_spawnflags & SF_PTEAM_GIB) ? true : false; }
  875. const char *TargetTeamName( const char *pszTargetName, CBaseEntity *pActivator );
  876. };
  877. LINK_ENTITY_TO_CLASS( game_player_team, CGamePlayerTeam );
  878. const char *CGamePlayerTeam::TargetTeamName( const char *pszTargetName, CBaseEntity *pActivator )
  879. {
  880. CBaseEntity *pTeamEntity = NULL;
  881. while ((pTeamEntity = gEntList.FindEntityByName( pTeamEntity, pszTargetName, NULL, pActivator )) != NULL)
  882. {
  883. if ( FClassnameIs( pTeamEntity, "game_team_master" ) )
  884. return pTeamEntity->TeamID();
  885. }
  886. return NULL;
  887. }
  888. void CGamePlayerTeam::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  889. {
  890. if ( !CanFireForActivator( pActivator ) )
  891. return;
  892. if ( pActivator->IsPlayer() )
  893. {
  894. const char *pszTargetTeam = TargetTeamName( STRING(m_target), pActivator );
  895. if ( pszTargetTeam )
  896. {
  897. CBasePlayer *pPlayer = (CBasePlayer *)pActivator;
  898. g_pGameRules->ChangePlayerTeam( pPlayer, pszTargetTeam, ShouldKillPlayer(), ShouldGibPlayer() );
  899. }
  900. }
  901. if ( RemoveOnFire() )
  902. {
  903. UTIL_Remove( this );
  904. }
  905. }