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.

323 lines
9.7 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "hintsystem.h"
  8. #include "hintmessage.h"
  9. #ifdef GAME_DLL
  10. #else
  11. #include <igameevents.h>
  12. #endif
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. #ifdef CLIENT_DLL
  16. ConVar cl_showhelp( "cl_showhelp", "1", FCVAR_ARCHIVE, "Set to 0 to not show on-screen help" );
  17. #endif
  18. //-----------------------------------------------------------------------------
  19. // Purpose:
  20. //-----------------------------------------------------------------------------
  21. CHintSystem::CHintSystem( void )
  22. {
  23. Init( NULL, 0, NULL );
  24. m_pHintMessageQueue = NULL;
  25. m_pHintMessageTimers = NULL;
  26. m_flLastHintPlayedAt = 0;
  27. }
  28. //-----------------------------------------------------------------------------
  29. // Purpose:
  30. //-----------------------------------------------------------------------------
  31. CHintSystem::~CHintSystem( void )
  32. {
  33. if ( m_pHintMessageTimers )
  34. {
  35. delete m_pHintMessageTimers;
  36. m_pHintMessageTimers = NULL;
  37. }
  38. if ( m_pHintMessageQueue )
  39. {
  40. delete m_pHintMessageQueue;
  41. m_pHintMessageQueue = NULL;
  42. }
  43. }
  44. //-----------------------------------------------------------------------------
  45. // Purpose:
  46. //-----------------------------------------------------------------------------
  47. void CHintSystem::Init( CBasePlayer *pPlayer, int iMaxHintTypes, const char **pszHintStrings )
  48. {
  49. m_pPlayer = pPlayer;
  50. m_bShowHints = true;
  51. m_HintHistory.Resize( iMaxHintTypes );
  52. m_HintHistory.ClearAll();
  53. m_pszHintMessages = pszHintStrings;
  54. if ( m_pPlayer )
  55. {
  56. m_pHintMessageQueue = new CHintMessageQueue( m_pPlayer );
  57. m_pHintMessageTimers = new CHintMessageTimers( this, m_pHintMessageQueue );
  58. }
  59. }
  60. //-----------------------------------------------------------------------------
  61. // Purpose:
  62. //-----------------------------------------------------------------------------
  63. void CHintSystem::Update( void )
  64. {
  65. if ( m_pHintMessageQueue )
  66. {
  67. m_pHintMessageQueue->Update();
  68. }
  69. if ( m_pHintMessageTimers )
  70. {
  71. m_pHintMessageTimers->Update();
  72. }
  73. }
  74. //-----------------------------------------------------------------------------
  75. // Purpose: Displays a hint message to the player
  76. // Input : hint - enum'd hint to show
  77. // bForce - always play this hint even if they have seen it before
  78. //-----------------------------------------------------------------------------
  79. bool CHintSystem::HintMessage( int hint, bool bForce /* = false */, bool bOnlyIfClear /* = false */ )
  80. {
  81. Assert( m_pPlayer );
  82. Assert( hint < m_HintHistory.GetNumBits() );
  83. // Not really an optimal solution, but saves us querying the hud element,
  84. // which wouldn't be easy with derived versions in different mods.
  85. if ( bOnlyIfClear && (gpGlobals->curtime - m_flLastHintPlayedAt < 11 ) )
  86. return false;
  87. if ( bForce || !HasPlayedHint(hint) )
  88. {
  89. PlayedAHint();
  90. HintMessage( m_pszHintMessages[hint] );
  91. m_HintHistory.Set(hint);
  92. return true;
  93. }
  94. return false;
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose: Displays a hint message to the player
  98. // Input : *pMessage -
  99. //-----------------------------------------------------------------------------
  100. void CHintSystem::HintMessage( const char *pMessage )
  101. {
  102. Assert( m_pPlayer );
  103. #ifdef GAME_DLL
  104. // On the server, we send it down to the queue who sends it to the client
  105. if ( !m_pPlayer->IsNetClient() || !m_pHintMessageQueue )
  106. return;
  107. if ( !m_bShowHints )
  108. return;
  109. m_pHintMessageQueue->AddMessage( pMessage );
  110. #else
  111. // On the client, we just send it straight to the hint hud element
  112. if ( cl_showhelp.GetBool() )
  113. {
  114. IGameEvent *event = gameeventmanager->CreateEvent( "player_hintmessage" );
  115. if ( event )
  116. {
  117. event->SetString( "hintmessage", pMessage );
  118. gameeventmanager->FireEventClientSide( event );
  119. }
  120. }
  121. #endif
  122. }
  123. //-----------------------------------------------------------------------------
  124. // Purpose: Clear out the existing timers, and register new ones for any
  125. // hints that haven't been displayed yet.
  126. //-----------------------------------------------------------------------------
  127. void CHintSystem::ResetHints( void )
  128. {
  129. if ( !m_pHintMessageTimers )
  130. return;
  131. m_pHintMessageTimers->Reset();
  132. // Readd registered hints
  133. for (int i = 0; i < m_RegisteredResetHints.Count(); i++ )
  134. {
  135. ReAddHintTimerIfNotDisplayed( m_RegisteredResetHints[i].iHintID, m_RegisteredResetHints[i].flTimer );
  136. }
  137. // Reset our queue
  138. if ( m_pHintMessageQueue )
  139. {
  140. m_pHintMessageQueue->Reset();
  141. }
  142. }
  143. //-----------------------------------------------------------------------------
  144. // Purpose: Call this to add a hint message that should be re-added
  145. // everytime we're reset, if it hasn't been displayed yet.
  146. //-----------------------------------------------------------------------------
  147. void CHintSystem::RegisterHintTimer( int iHintID, float flTimerDuration, bool bOnlyIfClear /* = false */, HintTimerCallback pfnCallback )
  148. {
  149. Assert( m_pPlayer );
  150. Assert( iHintID < m_HintHistory.GetNumBits() );
  151. onresethints_t newHint;
  152. newHint.iHintID = iHintID;
  153. newHint.flTimer = flTimerDuration;
  154. newHint.bOnlyIfClear = bOnlyIfClear;
  155. newHint.pfnCallback = pfnCallback;
  156. m_RegisteredResetHints.AddToTail( newHint );
  157. }
  158. //-----------------------------------------------------------------------------
  159. // Purpose: If the hint hasn't been displayed, start a timer for it
  160. //-----------------------------------------------------------------------------
  161. void CHintSystem::ReAddHintTimerIfNotDisplayed( int iHintID, float flTimerDuration )
  162. {
  163. Assert( iHintID < m_HintHistory.GetNumBits() );
  164. if ( m_HintHistory[iHintID] == 0 )
  165. {
  166. m_pHintMessageTimers->AddTimer( iHintID, flTimerDuration );
  167. }
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Purpose:
  171. //-----------------------------------------------------------------------------
  172. void CHintSystem::StartHintTimer( int iHintID )
  173. {
  174. Assert( m_pPlayer );
  175. Assert( iHintID < m_HintHistory.GetNumBits() );
  176. Assert(m_pHintMessageTimers);
  177. m_pHintMessageTimers->StartTimer( iHintID );
  178. }
  179. //-----------------------------------------------------------------------------
  180. // Purpose:
  181. //-----------------------------------------------------------------------------
  182. void CHintSystem::StopHintTimer( int iHintID )
  183. {
  184. Assert( m_pPlayer );
  185. Assert( iHintID < m_HintHistory.GetNumBits() );
  186. Assert(m_pHintMessageTimers);
  187. m_pHintMessageTimers->StopTimer( iHintID );
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Purpose:
  191. //-----------------------------------------------------------------------------
  192. void CHintSystem::ResetHintTimers( void )
  193. {
  194. Assert( m_pPlayer );
  195. Assert(m_pHintMessageTimers);
  196. m_pHintMessageTimers->Reset();
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Purpose:
  200. //-----------------------------------------------------------------------------
  201. void CHintSystem::RemoveHintTimer( int iHintID )
  202. {
  203. Assert( m_pPlayer );
  204. Assert( iHintID < m_HintHistory.GetNumBits() );
  205. Assert(m_pHintMessageTimers);
  206. m_pHintMessageTimers->RemoveTimer( iHintID );
  207. // Mark us as having heard this hint
  208. m_HintHistory.Set(iHintID);
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Purpose: See if there's a callback registered for the specified hint.
  212. // If so, see if it wants to allow the hint to fire.
  213. //-----------------------------------------------------------------------------
  214. bool CHintSystem::TimerShouldFire( int iHintID )
  215. {
  216. for (int i = 0; i < m_RegisteredResetHints.Count(); i++ )
  217. {
  218. if ( m_RegisteredResetHints[i].iHintID != iHintID )
  219. continue;
  220. if ( m_RegisteredResetHints[i].bOnlyIfClear && HintIsCurrentlyVisible() )
  221. return false;
  222. if ( m_RegisteredResetHints[i].pfnCallback )
  223. return m_RegisteredResetHints[i].pfnCallback( m_pPlayer );
  224. }
  225. return true;
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Purpose:
  229. //-----------------------------------------------------------------------------
  230. bool CHintSystem::ShouldShowHints( void )
  231. {
  232. #ifdef GAME_DLL
  233. return m_bShowHints;
  234. #else
  235. return cl_showhelp.GetBool();
  236. #endif
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Purpose:
  240. //-----------------------------------------------------------------------------
  241. void CHintSystem::PlayedAHint( void )
  242. {
  243. m_flLastHintPlayedAt = gpGlobals->curtime;
  244. }
  245. //-----------------------------------------------------------------------------
  246. // Purpose:
  247. //-----------------------------------------------------------------------------
  248. bool CHintSystem::HasPlayedHint( int iHintID )
  249. {
  250. Assert( m_pPlayer );
  251. Assert( iHintID < m_HintHistory.GetNumBits() );
  252. return ( m_HintHistory[iHintID] > 0 );
  253. }
  254. //-----------------------------------------------------------------------------
  255. // Purpose:
  256. //-----------------------------------------------------------------------------
  257. void CHintSystem::SetHintPlayed( int iHintID )
  258. {
  259. Assert( m_pPlayer );
  260. Assert( iHintID < m_HintHistory.GetNumBits() );
  261. m_HintHistory.Set(iHintID);
  262. }
  263. //-----------------------------------------------------------------------------
  264. // Purpose:
  265. //-----------------------------------------------------------------------------
  266. void HintClear( void )
  267. {
  268. #ifdef CLIENT_DLL
  269. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  270. #else
  271. CBasePlayer* pPlayer = UTIL_GetCommandClient();
  272. #endif
  273. if ( pPlayer && pPlayer->Hints() )
  274. {
  275. pPlayer->Hints()->ClearHintHistory();
  276. }
  277. }
  278. #ifdef CLIENT_DLL
  279. ConCommand cl_clearhinthistory( "cl_clearhinthistory", HintClear, "Clear memory of client side hints displayed to the player." );
  280. #else
  281. ConCommand sv_clearhinthistory( "sv_clearhinthistory", HintClear, "Clear memory of server side hints displayed to the player." );
  282. #endif