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.

303 lines
8.5 KiB

  1. //====== Copyright � 1996-2004, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "hintmessage.h"
  8. #include "hintsystem.h"
  9. #include "usermessages.h"
  10. #ifdef GAME_DLL
  11. #include "util.h"
  12. #endif
  13. // NOTE: This has to be the last file included!
  14. #include "tier0/memdbgon.h"
  15. //--------------------------------------------------------------------------------------------------------
  16. /**
  17. * Simple utility function to allocate memory and duplicate a string
  18. */
  19. inline char *CloneString( const char *str )
  20. {
  21. char *cloneStr = new char [ strlen(str)+1 ];
  22. strcpy( cloneStr, str );
  23. return cloneStr;
  24. }
  25. extern int gmsgHudText;
  26. enum { HMQ_SIZE = 8 }; // Maximum number of messages queue can hold
  27. // If the limit is reached, no more can be
  28. // added.
  29. //--------------------------------------------------------------------------------------------------------------
  30. CHintMessage::CHintMessage( const char * hintString, CUtlVector< const char * > * args, float duration )
  31. {
  32. m_hintString = hintString;
  33. m_duration = duration;
  34. if ( args )
  35. {
  36. for ( int i=0; i<args->Count(); ++i )
  37. {
  38. m_args.AddToTail( CloneString( (*args)[i] ) );
  39. }
  40. }
  41. }
  42. //--------------------------------------------------------------------------------------------------------------
  43. CHintMessage::~CHintMessage()
  44. {
  45. for ( int i=0; i<m_args.Count(); ++i )
  46. {
  47. delete[] m_args[i];
  48. }
  49. m_args.RemoveAll();
  50. }
  51. //--------------------------------------------------------------------------------------------------------------
  52. bool CHintMessage::IsEquivalent( const char *hintString, CUtlVector< const char * > * args ) const
  53. {
  54. if ( FStrEq( hintString, m_hintString ) )
  55. {
  56. if ( !args && !m_args.Count() )
  57. {
  58. return true;
  59. }
  60. if ( !args )
  61. return false;
  62. if ( args->Count() != m_args.Count() )
  63. return false;
  64. for ( int i=0; i<args->Count(); ++i )
  65. {
  66. if ( !FStrEq( (*args)[i], m_args[i] ) )
  67. {
  68. return false;
  69. }
  70. }
  71. }
  72. return false;
  73. }
  74. //--------------------------------------------------------------------------------------------------------------
  75. void CHintMessage::Send( CBasePlayer * client )
  76. {
  77. if ( !client )
  78. return;
  79. #ifdef GAME_DLL
  80. // Custom hint text sending to allow for arguments. This is OK because the client has a custom
  81. // message parser for hint text that can read the arguments.
  82. CSingleUserRecipientFilter user( (CBasePlayer *)client );
  83. user.MakeReliable();
  84. // client can handle 1 string only
  85. CCSUsrMsg_HintText msg;
  86. msg.set_text( m_hintString );
  87. SendUserMessage( user, CS_UM_HintText, msg );
  88. #endif
  89. }
  90. //--------------------------------------------------------------------------------------------------------------
  91. CHintMessageQueue::CHintMessageQueue( CBasePlayer *pPlayer )
  92. {
  93. m_pPlayer = pPlayer;
  94. }
  95. //--------------------------------------------------------------------------------------------------------------
  96. void CHintMessageQueue::Reset()
  97. {
  98. m_tmMessageEnd = 0;
  99. for ( int i=0; i<m_messages.Count(); ++i )
  100. {
  101. delete m_messages[i];
  102. }
  103. m_messages.RemoveAll();
  104. }
  105. //--------------------------------------------------------------------------------------------------------------
  106. void CHintMessageQueue::Update()
  107. {
  108. if ( !m_pPlayer )
  109. return;
  110. // test this - send the message as soon as it is ready,
  111. // just stomp the old message
  112. //if ( gpGlobals->curtime > m_tmMessageEnd )
  113. {
  114. if ( m_messages.Count() )
  115. {
  116. CHintMessage *msg = m_messages[0];
  117. m_tmMessageEnd = gpGlobals->curtime + msg->GetDuration();
  118. msg->Send( m_pPlayer );
  119. delete msg;
  120. m_messages.Remove( 0 );
  121. }
  122. }
  123. }
  124. //--------------------------------------------------------------------------------------------------------------
  125. bool CHintMessageQueue::AddMessage( const char* message, float duration, CUtlVector< const char * > * args )
  126. {
  127. if ( !m_pPlayer )
  128. return false;
  129. for ( int i=0; i<m_messages.Count(); ++i )
  130. {
  131. // weed out duplicates
  132. if ( m_messages[i]->IsEquivalent( message, args ) )
  133. {
  134. return true;
  135. }
  136. }
  137. // 'message' is not copied, so the pointer must remain valid forever
  138. CHintMessage *msg = new CHintMessage( message, args, duration );
  139. m_messages.AddToTail( msg );
  140. return true;
  141. }
  142. //--------------------------------------------------------------------------------------------------------------
  143. //-----------------------------------------------------------------------------
  144. // Purpose:
  145. // Input : *pPlayer -
  146. //-----------------------------------------------------------------------------
  147. CHintMessageTimers::CHintMessageTimers( CHintSystem *pSystem, CHintMessageQueue *pQueue )
  148. {
  149. m_pHintSystem = pSystem;
  150. m_pQueue = pQueue;
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Purpose: Clear out all registered timers
  154. //-----------------------------------------------------------------------------
  155. void CHintMessageTimers::Reset()
  156. {
  157. for ( int i=0; i<m_Timers.Count(); ++i )
  158. {
  159. delete m_Timers[i];
  160. }
  161. m_Timers.RemoveAll();
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Purpose: Check & fire any timers that should fire based on their duration.
  165. //-----------------------------------------------------------------------------
  166. void CHintMessageTimers::Update()
  167. {
  168. if ( !m_pHintSystem )
  169. return;
  170. for ( int i = 0; i < m_Timers.Count(); i++ )
  171. {
  172. if ( m_Timers[i]->timer.Expired() )
  173. {
  174. if ( m_pHintSystem->TimerShouldFire( m_Timers[i]->iHintID ) )
  175. {
  176. //Warning("TIMER FIRED: %s\n", m_pszHintMessages[m_Timers[i]->iHintID] );
  177. m_pHintSystem->HintMessage( m_Timers[i]->iHintID );
  178. // Remove and return. No reason to bring up multiple hints.
  179. RemoveTimer( m_Timers[i]->iHintID );
  180. return;
  181. }
  182. else
  183. {
  184. // Push the timer out again
  185. m_Timers[i]->timer.Start();
  186. }
  187. }
  188. }
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Purpose: Register a new timer that the system should should keep track of.
  192. // Input : iHintID - The ID of the hint message
  193. // timer_duration - the total time the timer should run for until it fires the hint message
  194. // message_duration - the duration passed into the hint message system when the hint fires
  195. // args - the arguments passed into the hint message system when the hint fires
  196. //-----------------------------------------------------------------------------
  197. void CHintMessageTimers::AddTimer( int iHintID, float timer_duration, float message_duration, CUtlVector< const char * > * args )
  198. {
  199. if ( GetTimerIndex(iHintID) != m_Timers.InvalidIndex() )
  200. return;
  201. // 'message' is not copied, so the pointer must remain valid forever
  202. hintmessagetime_t *newTimer = new hintmessagetime_t( timer_duration );
  203. newTimer->iHintID = iHintID;
  204. newTimer->flMessageDuration = message_duration;
  205. if ( args )
  206. {
  207. for ( int i=0; i<args->Count(); ++i )
  208. {
  209. newTimer->args.AddToTail( CloneString( (*args)[i] ) );
  210. }
  211. }
  212. m_Timers.AddToTail( newTimer );
  213. //Warning("TIMER ADDED: %s\n", m_pszHintMessages[iHintID] );
  214. }
  215. //-----------------------------------------------------------------------------
  216. // Purpose:
  217. //-----------------------------------------------------------------------------
  218. void CHintMessageTimers::RemoveTimer( int iHintID )
  219. {
  220. int iIndex = GetTimerIndex(iHintID);
  221. if ( iIndex != m_Timers.InvalidIndex() )
  222. {
  223. //Warning("TIMER REMOVED: %s\n", m_pszHintMessages[iHintID] );
  224. m_Timers.Remove( iIndex );
  225. }
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Purpose:
  229. //-----------------------------------------------------------------------------
  230. void CHintMessageTimers::StartTimer( int iHintID )
  231. {
  232. int iIndex = GetTimerIndex(iHintID);
  233. if ( iIndex != m_Timers.InvalidIndex() )
  234. {
  235. //Warning("TIMER STARTED: %s\n", m_pszHintMessages[iHintID] );
  236. m_Timers[iIndex]->timer.Start();
  237. }
  238. }
  239. //-----------------------------------------------------------------------------
  240. // Purpose:
  241. //-----------------------------------------------------------------------------
  242. void CHintMessageTimers::StopTimer( int iHintID )
  243. {
  244. int iIndex = GetTimerIndex(iHintID);
  245. if ( iIndex != m_Timers.InvalidIndex() )
  246. {
  247. //Warning("TIMER STOPPED: %s\n", m_pszHintMessages[iHintID] );
  248. m_Timers[iIndex]->timer.Stop();
  249. }
  250. }
  251. //-----------------------------------------------------------------------------
  252. // Purpose: Return the index of the hint message in the timer list, if any
  253. //-----------------------------------------------------------------------------
  254. int CHintMessageTimers::GetTimerIndex( int iHintID )
  255. {
  256. for ( int i = 0; i < m_Timers.Count(); i++ )
  257. {
  258. if ( m_Timers[i]->iHintID == iHintID )
  259. return i;
  260. }
  261. return m_Timers.InvalidIndex();
  262. }