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.

346 lines
10 KiB

  1. //========= Copyright � 1996-2001, Valve LLC, All rights reserved. ============
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "cbase.h"
  8. #include "mp_shareddefs.h"
  9. #include "basemultiplayerplayer.h"
  10. #include "cdll_int.h"
  11. #include "gameinterface.h"
  12. #include "usermessages.h"
  13. ConVar sv_allchat("sv_allchat", "1", FCVAR_NOTIFY, "Players can receive all other players' text chat, team restrictions apply");
  14. // NOTE: This has to be the last file included!
  15. #include "tier0/memdbgon.h"
  16. CBaseMultiplayerPlayer::CBaseMultiplayerPlayer()
  17. {
  18. m_iCurrentConcept = MP_CONCEPT_NONE;
  19. m_flLastForcedChangeTeamTime = -1;
  20. m_iBalanceScore = 0;
  21. m_flConnectionTime = gpGlobals->curtime;
  22. m_pExpresser = NULL;
  23. // per life achievement counters
  24. m_pAchievementKV = new KeyValues( "achievement_counts" );
  25. m_flAreaCaptureScoreAccumulator = 0.0f;
  26. }
  27. CBaseMultiplayerPlayer::~CBaseMultiplayerPlayer()
  28. {
  29. m_pAchievementKV->deleteThis();
  30. delete m_pExpresser;
  31. }
  32. BEGIN_ENT_SCRIPTDESC( CBaseMultiplayerPlayer, CBasePlayer, "Player" )
  33. END_SCRIPTDESC();
  34. //-----------------------------------------------------------------------------
  35. // Purpose:
  36. //-----------------------------------------------------------------------------
  37. CAI_Expresser *CBaseMultiplayerPlayer::CreateExpresser( void )
  38. {
  39. m_pExpresser = new CMultiplayer_Expresser(this);
  40. if ( !m_pExpresser)
  41. return NULL;
  42. m_pExpresser->Connect(this);
  43. return m_pExpresser;
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Purpose:
  47. //-----------------------------------------------------------------------------
  48. void CBaseMultiplayerPlayer::PostConstructor( const char *szClassname )
  49. {
  50. BaseClass::PostConstructor( szClassname );
  51. CreateExpresser();
  52. }
  53. //-----------------------------------------------------------------------------
  54. // Purpose:
  55. //-----------------------------------------------------------------------------
  56. void CBaseMultiplayerPlayer::ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet )
  57. {
  58. BaseClass::ModifyOrAppendCriteria( criteriaSet );
  59. ModifyOrAppendPlayerCriteria( criteriaSet );
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Purpose:
  63. //-----------------------------------------------------------------------------
  64. bool CBaseMultiplayerPlayer::SpeakIfAllowed( AIConcept_t concept, SpeechPriorityType priority, const char *modifiers, char *pszOutResponseChosen, size_t bufsize, IRecipientFilter *filter )
  65. {
  66. if ( !IsAlive() )
  67. return false;
  68. //if ( IsAllowedToSpeak( concept, bRespondingToPlayer ) )
  69. return Speak( concept, modifiers, pszOutResponseChosen, bufsize, filter );
  70. }
  71. //-----------------------------------------------------------------------------
  72. // Purpose: Fill out given response with the appropriate one for this concept
  73. //-----------------------------------------------------------------------------
  74. void CBaseMultiplayerPlayer::SpeakConcept( AI_Response &outResponse, int iConcept )
  75. {
  76. m_iCurrentConcept = iConcept;
  77. AIConcept_t concept( g_pszMPConcepts[iConcept] );
  78. FindResponse( outResponse, concept );
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Purpose:
  82. //-----------------------------------------------------------------------------
  83. bool CBaseMultiplayerPlayer::SpeakConceptIfAllowed( int iConcept, const char *modifiers, char *pszOutResponseChosen, size_t bufsize, IRecipientFilter *filter )
  84. {
  85. // Save the current concept.
  86. m_iCurrentConcept = iConcept;
  87. return SpeakIfAllowed( g_pszMPConcepts[iConcept], SPEECH_PRIORITY_NORMAL, modifiers, pszOutResponseChosen, bufsize, filter );
  88. }
  89. //-----------------------------------------------------------------------------
  90. // Purpose:
  91. //-----------------------------------------------------------------------------
  92. bool CBaseMultiplayerPlayer::CanHearAndReadChatFrom( CBasePlayer *pPlayer )
  93. {
  94. // can always hear the console unless we're ignoring every chat
  95. if ( !pPlayer )
  96. return m_iIgnoreGlobalChat != CHAT_IGNORE_EVERYTHING;
  97. // check if we're ignoring all chat
  98. if ( m_iIgnoreGlobalChat == CHAT_IGNORE_BROADCAST_AND_TEAM )
  99. return false;
  100. // check if we're ignoring all but teammates
  101. if ( m_iIgnoreGlobalChat == CHAT_IGNORE_BROADCAST && g_pGameRules->PlayerRelationship( this, pPlayer ) != GR_TEAMMATE )
  102. return false;
  103. // can't hear dead players if we're alive
  104. if ( pPlayer->m_lifeState != LIFE_ALIVE && m_lifeState == LIFE_ALIVE )
  105. return false;
  106. return true;
  107. }
  108. bool CBaseMultiplayerPlayer::ClientCommand( const CCommand &args )
  109. {
  110. const char *pcmd = args[0];
  111. if ( FStrEq( pcmd, "ignoremsg" ) )
  112. {
  113. m_iIgnoreGlobalChat = (m_iIgnoreGlobalChat + 1) % 4;
  114. switch( m_iIgnoreGlobalChat )
  115. {
  116. case CHAT_IGNORE_NONE:
  117. ClientPrint( this, HUD_PRINTTALK, "#Accept_All_Messages" );
  118. break;
  119. case CHAT_IGNORE_BROADCAST:
  120. ClientPrint( this, HUD_PRINTTALK, "#Ignore_Broadcast_Messages" );
  121. break;
  122. case CHAT_IGNORE_BROADCAST_AND_TEAM:
  123. ClientPrint( this, HUD_PRINTTALK, "#Ignore_Broadcast_Team_Messages" );
  124. break;
  125. case CHAT_IGNORE_EVERYTHING:
  126. ClientPrint( this, HUD_PRINTTALK, "#Ignore_All_Messages" );
  127. break;
  128. default:
  129. break;
  130. }
  131. return true;
  132. }
  133. return BaseClass::ClientCommand( args );
  134. }
  135. bool CBaseMultiplayerPlayer::ShouldShowVoiceSubtitleToEnemy( void )
  136. {
  137. return false;
  138. }
  139. //-----------------------------------------------------------------------------
  140. // calculate a score for this player. higher is more likely to be switched
  141. //-----------------------------------------------------------------------------
  142. int CBaseMultiplayerPlayer::CalculateTeamBalanceScore( void )
  143. {
  144. // base score is 0 - ( seconds on server )
  145. float flTimeConnected = gpGlobals->curtime - m_flConnectionTime;
  146. int iScore = 0 - (int)flTimeConnected;
  147. // if we were switched recently, score us way down
  148. float flLastSwitchedTime = GetLastForcedChangeTeamTime();
  149. if ( flLastSwitchedTime > 0 && ( gpGlobals->curtime - flLastSwitchedTime ) < 300 )
  150. {
  151. iScore -= 10000;
  152. }
  153. return iScore;
  154. }
  155. void CBaseMultiplayerPlayer::Spawn( void )
  156. {
  157. ResetPerLifeCounters();
  158. BaseClass::Spawn();
  159. }
  160. void CBaseMultiplayerPlayer::AwardAchievement( int iAchievement, int iCount )
  161. {
  162. Assert( iAchievement >= 0 && iAchievement < 0xFFFF ); // must fit in short
  163. CSingleUserRecipientFilter filter( this );
  164. int userID = GetPlayerInfo()->GetUserID();
  165. CCSUsrMsg_AchievementEvent msg;
  166. msg.set_achievement( iAchievement );
  167. msg.set_count( iCount );
  168. msg.set_user_id( userID );
  169. SendUserMessage( filter, CS_UM_AchievementEvent, msg );
  170. }
  171. #ifdef _DEBUG
  172. #include "utlbuffer.h"
  173. void DumpAchievementCounters( const CCommand &args )
  174. {
  175. int iPlayerIndex = 1;
  176. if ( args.ArgC() >= 2 )
  177. {
  178. iPlayerIndex = atoi( args[1] );
  179. }
  180. CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( iPlayerIndex ) );
  181. if ( pPlayer && pPlayer->GetPerLifeCounterKeys() )
  182. {
  183. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  184. pPlayer->GetPerLifeCounterKeys()->RecursiveSaveToFile( buf, 0 );
  185. char szBuf[1024];
  186. // probably not the best way to print out a CUtlBuffer
  187. int pos = 0;
  188. while ( buf.PeekStringLength() )
  189. {
  190. szBuf[pos] = buf.GetChar();
  191. pos++;
  192. }
  193. szBuf[pos] = '\0';
  194. Msg( "%s\n", szBuf );
  195. }
  196. }
  197. ConCommand dump_achievement_counters( "dump_achievement_counters", DumpAchievementCounters, "Spew the per-life achievement counters for multiplayer players", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY );
  198. #endif // _DEBUG
  199. int CBaseMultiplayerPlayer::GetPerLifeCounterKV( const char *name )
  200. {
  201. return m_pAchievementKV->GetInt( name, 0 );
  202. }
  203. void CBaseMultiplayerPlayer::SetPerLifeCounterKV( const char *name, int value )
  204. {
  205. m_pAchievementKV->SetInt( name, value );
  206. }
  207. void CBaseMultiplayerPlayer::ResetPerLifeCounters( void )
  208. {
  209. m_pAchievementKV->Clear();
  210. }
  211. #ifndef CSTRIKE_DLL
  212. ConVar tf_escort_score_rate( "tf_escort_score_rate", "1", FCVAR_CHEAT, "Score for escorting the train, in points per second" );
  213. #endif
  214. #define ESCORT_SCORE_CONTEXT "AreaScoreContext"
  215. #define ESCORT_SCORE_INTERVAL 0.1
  216. //-----------------------------------------------------------------------------
  217. // Purpose: think to accumulate and award points for escorting the train
  218. //-----------------------------------------------------------------------------
  219. void CBaseMultiplayerPlayer::EscortScoringThink( void )
  220. {
  221. m_flAreaCaptureScoreAccumulator += ESCORT_SCORE_INTERVAL;
  222. if ( m_flCapPointScoreRate > 0 )
  223. {
  224. float flTimeForOnePoint = 1.0f / m_flCapPointScoreRate;
  225. int iPoints = 0;
  226. while ( m_flAreaCaptureScoreAccumulator >= flTimeForOnePoint )
  227. {
  228. m_flAreaCaptureScoreAccumulator -= flTimeForOnePoint;
  229. iPoints++;
  230. }
  231. if ( iPoints > 0 )
  232. {
  233. IGameEvent *event = gameeventmanager->CreateEvent( "player_escort_score" );
  234. if ( event )
  235. {
  236. event->SetInt( "player", entindex() );
  237. event->SetInt( "points", iPoints );
  238. gameeventmanager->FireEvent( event, true /* only to server */ );
  239. }
  240. }
  241. }
  242. SetContextThink( &CBaseMultiplayerPlayer::EscortScoringThink, gpGlobals->curtime + ESCORT_SCORE_INTERVAL, ESCORT_SCORE_CONTEXT );
  243. }
  244. //-----------------------------------------------------------------------------
  245. // Purpose: We're escorting the train, start giving points
  246. //-----------------------------------------------------------------------------
  247. void CBaseMultiplayerPlayer::StartScoringEscortPoints( float flRate )
  248. {
  249. Assert( flRate > 0.0f );
  250. m_flCapPointScoreRate = flRate;
  251. SetContextThink( &CBaseMultiplayerPlayer::EscortScoringThink, gpGlobals->curtime + ESCORT_SCORE_INTERVAL, ESCORT_SCORE_CONTEXT );
  252. }
  253. //-----------------------------------------------------------------------------
  254. // Purpose: Stopped escorting the train
  255. //-----------------------------------------------------------------------------
  256. void CBaseMultiplayerPlayer::StopScoringEscortPoints( void )
  257. {
  258. SetContextThink( NULL, 0, ESCORT_SCORE_CONTEXT );
  259. }
  260. #if !defined(NO_STEAM)
  261. //-----------------------------------------------------------------------------
  262. // Purpose:
  263. //-----------------------------------------------------------------------------
  264. bool CBaseMultiplayerPlayer::GetSteamID( CSteamID *pID ) const
  265. {
  266. const CSteamID *pClientID = engine->GetClientSteamID( edict() );
  267. if ( pClientID )
  268. {
  269. *pID = *pClientID;
  270. return true;
  271. }
  272. return false;
  273. }
  274. //-----------------------------------------------------------------------------
  275. // Purpose:
  276. //-----------------------------------------------------------------------------
  277. uint64 CBaseMultiplayerPlayer::GetSteamIDAsUInt64( void ) const
  278. {
  279. CSteamID steamIDForPlayer;
  280. if ( GetSteamID( &steamIDForPlayer ) )
  281. return steamIDForPlayer.ConvertToUint64();
  282. return 0;
  283. }
  284. #endif // NO_STEAM