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.

299 lines
7.6 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "tf_hud_escort.h"
  8. #include <vgui/IVGui.h>
  9. #include "tf_hud_freezepanel.h"
  10. #include "teamplayroundbased_gamerules.h"
  11. #include "iclientmode.h"
  12. #include "tf_gamerules.h"
  13. #include "tf_hud_training.h"
  14. #include <vgui/ILocalize.h>
  15. using namespace vgui;
  16. //-----------------------------------------------------------------------------
  17. // Purpose: Localize text for training messages. Used in annotations and in the training hud. Assumes the output string size is greater than or equal to MAX_TRAINING_MSG_LENGTH
  18. //-----------------------------------------------------------------------------
  19. bool CTFHudTraining::FormatTrainingText(const char* inputString, wchar_t* outputString)
  20. {
  21. static wchar_t szBuf[MAX_TRAINING_MSG_LENGTH];
  22. static wchar_t *pszBuf;
  23. if ( !inputString || !inputString[0] )
  24. {
  25. return false;
  26. }
  27. // init buffers & pointers
  28. outputString[0] = 0;
  29. szBuf[0] = 0;
  30. pszBuf = szBuf;
  31. // try to localize
  32. pszBuf = g_pVGuiLocalize->Find( inputString );
  33. if ( !pszBuf )
  34. {
  35. // use plain ASCII string
  36. g_pVGuiLocalize->ConvertANSIToUnicode( inputString, szBuf, sizeof(szBuf) );
  37. pszBuf = szBuf;
  38. }
  39. // Replace bindings with the keys
  40. // parse out the text into a label set
  41. wchar_t *ws = pszBuf;
  42. while ( *ws )
  43. {
  44. wchar_t token[MAX_TRAINING_MSG_LENGTH];
  45. bool isVar = false;
  46. // check for variables
  47. if ( *ws == '%' )
  48. {
  49. isVar = true;
  50. ++ws;
  51. }
  52. // parse out the string
  53. wchar_t *end = wcschr( ws, '%' );
  54. if ( end )
  55. {
  56. wcsncpy( token, ws, end - ws );
  57. token[end - ws] = 0;
  58. }
  59. else
  60. {
  61. V_wcscpy_safe( token, ws );
  62. }
  63. ws += wcslen( token );
  64. if ( isVar )
  65. {
  66. // move over the end of the variable
  67. ++ws;
  68. }
  69. // modify the label if necessary
  70. if ( isVar )
  71. {
  72. // lookup key names
  73. char binding[64];
  74. g_pVGuiLocalize->ConvertUnicodeToANSI( token, binding, sizeof(binding) );
  75. //!! change some key names into better names
  76. char friendlyName[64];
  77. const char *key = engine->Key_LookupBinding( *binding == '+' ? binding + 1 : binding );
  78. if ( !key )
  79. {
  80. key = "< not bound >";
  81. }
  82. Q_snprintf( friendlyName, sizeof(friendlyName), "#%s", key );
  83. Q_strupr( friendlyName );
  84. // set the variable text - key may need to be localized (button images for example)
  85. wchar_t *locName = g_pVGuiLocalize->Find( friendlyName );
  86. if ( !locName || wcslen(locName) <= 0)
  87. {
  88. wchar_t wszFriendly[64];
  89. g_pVGuiLocalize->ConvertANSIToUnicode( friendlyName+1, wszFriendly, sizeof( wszFriendly ) );
  90. V_wcsncat( outputString, wszFriendly, MAX_TRAINING_MSG_LENGTH );
  91. }
  92. else
  93. {
  94. V_wcsncat( outputString, locName, MAX_TRAINING_MSG_LENGTH );
  95. }
  96. }
  97. else
  98. {
  99. V_wcsncat( outputString, token, MAX_TRAINING_MSG_LENGTH );
  100. }
  101. }
  102. return true;
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Purpose:
  106. //-----------------------------------------------------------------------------
  107. CTFHudTraining::CTFHudTraining( Panel *parent, const char *name ) : EditablePanel( parent, name )
  108. {
  109. m_pMsgLabel = NULL;
  110. m_pPressSpacebarToContinueLabel = NULL;
  111. ivgui()->AddTickSignal( GetVPanel(), 10 );
  112. ListenForGameEvent( "teamplay_round_start" );
  113. }
  114. //-----------------------------------------------------------------------------
  115. // Purpose:
  116. //-----------------------------------------------------------------------------
  117. CTFHudTraining::~CTFHudTraining()
  118. {
  119. ivgui()->RemoveTickSignal( GetVPanel() );
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Purpose: Hide when we take a freeze cam shot
  123. //-----------------------------------------------------------------------------
  124. bool CTFHudTraining::IsVisible( void )
  125. {
  126. if( IsTakingAFreezecamScreenshot() )
  127. return false;
  128. if ( IsInFreezeCam() )
  129. return false;
  130. return BaseClass::IsVisible();
  131. }
  132. void CTFHudTraining::Reset( void )
  133. {
  134. const char *emptyText = "";
  135. SetDialogVariable( "goal", emptyText );
  136. if (m_pMsgLabel) m_pMsgLabel->SetText(emptyText);
  137. if (m_pPressSpacebarToContinueLabel) m_pPressSpacebarToContinueLabel->SetVisible( false );
  138. }
  139. //-----------------------------------------------------------------------------
  140. // Purpose:
  141. //-----------------------------------------------------------------------------
  142. void CTFHudTraining::ApplySchemeSettings( IScheme *pScheme )
  143. {
  144. BaseClass::ApplySchemeSettings( pScheme );
  145. // load control settings...
  146. LoadControlSettings( "resource/UI/HudTraining.res" );
  147. m_pMsgLabel = dynamic_cast<CExRichText *>( FindChildByName("MsgLabel") );
  148. m_pPressSpacebarToContinueLabel = dynamic_cast<CExLabel *>( FindChildByName("PressSpacebarToContinue") );
  149. }
  150. void CTFHudTraining::SetTrainingObjective(char *szRawString)
  151. {
  152. wchar_t wszText[MAX_TRAINING_MSG_LENGTH];
  153. if (!FormatTrainingText(szRawString, wszText))
  154. {
  155. SetDialogVariable( "goal", "" );
  156. return;
  157. }
  158. SetDialogVariable( "goal", wszText );
  159. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  160. if ( pLocalPlayer )
  161. {
  162. pLocalPlayer->EmitSound( "Hud.TrainingMsgUpdate" );
  163. }
  164. }
  165. void CTFHudTraining::SetTrainingText(char *szRawString)
  166. {
  167. static wchar_t wszText[MAX_TRAINING_MSG_LENGTH];
  168. InvalidateLayout( false, true );
  169. if ( !m_pMsgLabel )
  170. return;
  171. if (!FormatTrainingText(szRawString, wszText))
  172. {
  173. m_pMsgLabel->SetText( "" );
  174. return;
  175. }
  176. // clear the text first
  177. m_pMsgLabel->SetText("");
  178. enum
  179. {
  180. COLOR_NORMAL = 1,
  181. COLOR_HINT = 2,
  182. };
  183. static wchar_t wszInsertedText[MAX_TRAINING_MSG_LENGTH];
  184. Color color = m_pMsgLabel->GetFgColor();
  185. Color newColor = color;
  186. int startIdx = 0;
  187. int endIdx = 0;
  188. bool bContinue = true;
  189. while ( bContinue )
  190. {
  191. bool bSetText = false;
  192. switch ( wszText[endIdx] )
  193. {
  194. case 0:
  195. bContinue = false;
  196. bSetText = true;
  197. break;
  198. case COLOR_NORMAL:
  199. newColor = m_pMsgLabel->GetFgColor();
  200. bSetText = true;
  201. break;
  202. case COLOR_HINT:
  203. newColor = m_pMsgLabel->GetSchemeColor( "HudTrainingHint", Color(255, 255, 255, 255), scheme()->GetIScheme( m_pMsgLabel->GetScheme() ) );
  204. bSetText = true;
  205. break;
  206. }
  207. if ( bSetText )
  208. {
  209. if ( startIdx != endIdx )
  210. {
  211. int len = endIdx - startIdx + 1;
  212. wcsncpy( wszInsertedText, wszText + startIdx, len );
  213. wszInsertedText[len-1] = 0;
  214. m_pMsgLabel->InsertColorChange( color );
  215. m_pMsgLabel->InsertString( wszInsertedText );
  216. // skip past the color change character
  217. startIdx = endIdx + 1;
  218. }
  219. color = newColor;
  220. }
  221. ++endIdx;
  222. }
  223. //m_pMessageFlashEndTime = gpGlobals->curtime + MESSAGE_FLASH_TIME;
  224. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "TrainingHudBounce");
  225. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  226. if ( pLocalPlayer )
  227. {
  228. pLocalPlayer->EmitSound( "Hud.TrainingMsgUpdate" );
  229. }
  230. }
  231. //-----------------------------------------------------------------------------
  232. // Purpose: Receive messages about changes in state
  233. //-----------------------------------------------------------------------------
  234. void CTFHudTraining::FireGameEvent( IGameEvent *event )
  235. {
  236. const char *eventName = event->GetName();
  237. if ( FStrEq( "teamplay_round_start", eventName ) )
  238. {
  239. InvalidateLayout( false, true );
  240. }
  241. }
  242. void CTFHudTraining::OnTick( )
  243. {
  244. bool bShouldBeVisible = TFGameRules() && TFGameRules()->IsWaitingForTrainingContinue();
  245. if ( m_pPressSpacebarToContinueLabel && bShouldBeVisible != m_pPressSpacebarToContinueLabel->IsVisible() )
  246. {
  247. m_pPressSpacebarToContinueLabel->SetVisible( bShouldBeVisible );
  248. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( bShouldBeVisible ? "TrainingPressSpacebarBlink" : "TrainingPressSpacebarBlinkStop" );
  249. }
  250. }