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.

591 lines
16 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "cbase.h"
  8. #include "c_tf_player.h"
  9. #include "iclientmode.h"
  10. #include "ienginevgui.h"
  11. #include <vgui/ILocalize.h>
  12. #include <vgui/ISurface.h>
  13. #include <vgui/IVGui.h>
  14. #include <vgui_controls/Label.h>
  15. #include <vgui_controls/EditablePanel.h>
  16. #include "tf_imagepanel.h"
  17. #include "tf_gamerules.h"
  18. #include "c_tf_team.h"
  19. #include "c_team_objectiveresource.h"
  20. #include "tf_hud_match_status.h"
  21. #include "tf_hud_teamgoal_tournament.h"
  22. // memdbgon must be the last include file in a .cpp file!!!
  23. #include "tier0/memdbgon.h"
  24. using namespace vgui;
  25. void AddSubKeyNamed( KeyValues *pKeys, const char *pszName );
  26. DECLARE_HUDELEMENT( CHudTeamGoalTournament );
  27. //-----------------------------------------------------------------------------
  28. // Purpose:
  29. //-----------------------------------------------------------------------------
  30. CHudTeamGoalTournament::CHudTeamGoalTournament( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudTeamGoalTournament" )
  31. {
  32. Panel *pParent = g_pClientMode->GetViewport();
  33. SetParent( pParent );
  34. SetHiddenBits( HIDEHUD_MISCSTATUS );
  35. m_flShowAt = -1.f;
  36. RegisterForRenderGroup( "commentary" );
  37. }
  38. //-----------------------------------------------------------------------------
  39. // Purpose:
  40. //-----------------------------------------------------------------------------
  41. void CHudTeamGoalTournament::LevelInit( void )
  42. {
  43. m_flShowAt = -1.f;
  44. ListenForGameEvent( "tournament_stateupdate" );
  45. ListenForGameEvent( "teamplay_round_start" );
  46. ListenForGameEvent( "competitive_state_changed" );
  47. }
  48. C_TFTeam *GetTeamRoles( int iTeamRole )
  49. {
  50. for ( int i = LAST_SHARED_TEAM+1; i < GetNumberOfTeams(); i++ )
  51. {
  52. C_TFTeam *pTeam = GetGlobalTFTeam( i );
  53. if ( pTeam )
  54. {
  55. if ( pTeam->GetRole() == iTeamRole )
  56. {
  57. return pTeam;
  58. }
  59. }
  60. }
  61. return NULL;
  62. }
  63. //-----------------------------------------------------------------------------
  64. // Purpose:
  65. //-----------------------------------------------------------------------------
  66. int CHudTeamGoalTournament::HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
  67. {
  68. if ( IsVisible() && TFGameRules() && TFGameRules()->IsInTournamentMode() && TFGameRules()->IsInStopWatch() )
  69. {
  70. if ( ( TFGameRules()->State_Get() == GR_STATE_PREROUND ) || TFGameRules()->InSetup() )
  71. {
  72. if ( down && ( keynum == KEY_F1 ) )
  73. {
  74. m_flShowAt = -1.f;
  75. return 0;
  76. }
  77. }
  78. }
  79. return 1;
  80. }
  81. //-----------------------------------------------------------------------------
  82. // Purpose:
  83. //-----------------------------------------------------------------------------
  84. void CHudTeamGoalTournament::FireGameEvent( IGameEvent * event )
  85. {
  86. const char *pEventName = event->GetName();
  87. if ( FStrEq( "tournament_stateupdate", pEventName ) )
  88. {
  89. m_flShowAt = -1.f;
  90. }
  91. else if ( FStrEq( "teamplay_round_start", pEventName ) )
  92. {
  93. if ( TFGameRules() && TFGameRules()->IsInTournamentMode() && TFGameRules()->IsInStopWatch() )
  94. {
  95. C_TFTeam *pAttacker = GetTeamRoles( TEAM_ROLE_ATTACKERS );
  96. C_TFTeam *pDefender = GetTeamRoles( TEAM_ROLE_DEFENDERS );
  97. if( !pAttacker || !pDefender )
  98. return;
  99. if ( ( pAttacker->Get_Score() != 0 ) && ( pDefender->Get_Score() != 0 ) )
  100. return;
  101. m_flShowAt = gpGlobals->curtime + 1.f;
  102. }
  103. }
  104. else if ( FStrEq( "competitive_state_changed", pEventName ) )
  105. {
  106. InvalidateLayout( false, true );
  107. }
  108. }
  109. //-----------------------------------------------------------------------------
  110. // Purpose:
  111. //-----------------------------------------------------------------------------
  112. void CHudTeamGoalTournament::ApplySchemeSettings( IScheme *pScheme )
  113. {
  114. KeyValues *pConditions = NULL;
  115. if ( ShouldUseMatchHUD() )
  116. {
  117. pConditions = new KeyValues( "conditions" );
  118. AddSubKeyNamed( pConditions, "if_comp" );
  119. }
  120. // load control settings...
  121. LoadControlSettings( "resource/UI/HudTeamGoalTournament.res", NULL, NULL, pConditions );
  122. BaseClass::ApplySchemeSettings( pScheme );
  123. if ( pConditions )
  124. {
  125. pConditions->deleteThis();
  126. }
  127. m_cRegularColor = pScheme->GetColor( "TanLight", Color( 0, 0, 0 ) );
  128. m_cHighlightColor = pScheme->GetColor( "GoalOrange", Color( 0, 0, 0 ) );
  129. m_pStopWatchGoal = dynamic_cast<EditablePanel *>( FindChildByName( "HudStopWatchObjective" ) );
  130. if ( m_pStopWatchGoal )
  131. {
  132. m_pStopWatchGoalText = dynamic_cast<CExRichText *>( m_pStopWatchGoal->FindChildByName( "HudStopWatchObjectiveText1" ) );
  133. }
  134. if ( m_pStopWatchGoalText )
  135. {
  136. m_pStopWatchGoalText->SetVisible( true );
  137. m_pStopWatchGoalText->InsertColorChange( m_cRegularColor );
  138. }
  139. if ( m_pStopWatchGoal )
  140. {
  141. m_pStopWatchGoalText2 = dynamic_cast<CExRichText *>( m_pStopWatchGoal->FindChildByName( "HudStopWatchObjectiveText2" ) );
  142. }
  143. if ( m_pStopWatchGoalText2 )
  144. {
  145. m_pStopWatchGoalText2->SetVisible( true );
  146. m_pStopWatchGoalText2->InsertColorChange( m_cRegularColor );
  147. }
  148. if ( m_pStopWatchGoal )
  149. {
  150. m_pStopWatchGoalBGLarge = m_pStopWatchGoal->FindChildByName( "HudStopWatchObjectiveBG" );
  151. m_pStopWatchGoalBGSmall = m_pStopWatchGoal->FindChildByName( "HudStopWatchObjectiveBGSmall" );
  152. m_pStopWatchGoalDivider = m_pStopWatchGoal->FindChildByName( "HudStopWatchObjectiveShadedBar" );
  153. }
  154. m_pStopWatchGoalArrow = FindChildByName( "HudStopWatchObjectiveArrow" );
  155. }
  156. inline wchar_t *CloneWString( const wchar_t *str );
  157. enum
  158. {
  159. STOPWATCH_COLOR_NORMAL = 1,
  160. STOPWATCH_COLOR_SUB = 3,
  161. };
  162. //-----------------------------------------------------------------------------
  163. // Purpose:
  164. //-----------------------------------------------------------------------------
  165. void CHudTeamGoalTournament::SetVisible( bool bState )
  166. {
  167. if ( bState )
  168. {
  169. SetupStopWatchLabel();
  170. }
  171. BaseClass::SetVisible( bState );
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Purpose: Prepares the string with the different colors
  175. // This is kinda nasty since I just copied this code from the chat
  176. // This should be abstracted and made all nice.
  177. //-----------------------------------------------------------------------------
  178. void CHudTeamGoalTournament::PrepareStopWatchString( wchar_t *pszString, CExRichText *pText )
  179. {
  180. if ( m_text )
  181. {
  182. delete[] m_text;
  183. m_text = NULL;
  184. }
  185. m_textRanges.RemoveAll();
  186. m_text = CloneWString( pszString );
  187. wchar_t *txt = m_text;
  188. int lineLen = wcslen( m_text );
  189. TextRange range;
  190. range.start = 0;
  191. range.end = wcslen( m_text );
  192. range.color = Color( 235, 226, 202 );
  193. m_textRanges.AddToTail( range );
  194. while ( txt && *txt )
  195. {
  196. switch ( *txt )
  197. {
  198. case STOPWATCH_COLOR_SUB:
  199. case STOPWATCH_COLOR_NORMAL:
  200. {
  201. // save this start
  202. range.start = (txt-m_text) + 1;
  203. if ( *txt == STOPWATCH_COLOR_NORMAL )
  204. range.color = m_cRegularColor;
  205. else
  206. range.color = m_cHighlightColor;
  207. range.end = lineLen;
  208. int count = m_textRanges.Count();
  209. if ( count )
  210. {
  211. m_textRanges[count-1].end = range.start - 1;
  212. }
  213. m_textRanges.AddToTail( range );
  214. }
  215. ++txt;
  216. break;
  217. default:
  218. ++txt;
  219. }
  220. }
  221. for ( int i=0; i<m_textRanges.Count(); ++i )
  222. {
  223. wchar_t * start = m_text + m_textRanges[i].start;
  224. if ( *start > 0 && *start < COLOR_MAX )
  225. {
  226. m_textRanges[i].start += 1;
  227. }
  228. }
  229. wchar_t wText[4096];
  230. Color color;
  231. for ( int i=0; i<m_textRanges.Count(); ++i )
  232. {
  233. wchar_t * start = m_text + m_textRanges[i].start;
  234. int len = m_textRanges[i].end - m_textRanges[i].start + 1;
  235. if ( len > 1 )
  236. {
  237. wcsncpy( wText, start, len );
  238. wText[len-1] = 0;
  239. color = m_textRanges[i].color;
  240. color[3] = 255;
  241. pText->InsertColorChange( color );
  242. pText->InsertString( wText );
  243. }
  244. }
  245. }
  246. //-----------------------------------------------------------------------------
  247. // Purpose:
  248. //-----------------------------------------------------------------------------
  249. void CHudTeamGoalTournament::SetupStopWatchLabel( void )
  250. {
  251. int iPoints = 0;
  252. if ( !TFGameRules() )
  253. return;
  254. if ( !ObjectiveResource() )
  255. return;
  256. C_TFTeam *pAttacker = GetTeamRoles( TEAM_ROLE_ATTACKERS );
  257. C_TFTeam *pDefender = GetTeamRoles( TEAM_ROLE_DEFENDERS );
  258. if( !pAttacker || !pDefender )
  259. return;
  260. int iActiveTimer = ObjectiveResource()->GetStopWatchTimer();
  261. CTeamRoundTimer *pTimer = dynamic_cast< CTeamRoundTimer* >( ClientEntityList().GetEnt( iActiveTimer ) );
  262. if ( !pTimer )
  263. return;
  264. if ( !pTimer->IsWatchingTimeStamps() )
  265. {
  266. iPoints = pDefender->Get_Score();
  267. if ( m_pStopWatchGoal )
  268. {
  269. m_pStopWatchGoal->SetVisible( true );
  270. }
  271. if ( m_pStopWatchGoalArrow )
  272. {
  273. m_pStopWatchGoalArrow->SetVisible( true );
  274. }
  275. }
  276. else
  277. {
  278. if ( m_pStopWatchGoal )
  279. {
  280. m_pStopWatchGoal->SetVisible( false );
  281. }
  282. if ( m_pStopWatchGoalArrow )
  283. {
  284. m_pStopWatchGoalArrow->SetVisible( false );
  285. }
  286. return;
  287. }
  288. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  289. if ( !pLocalPlayer )
  290. return;
  291. wchar_t wzHelp[256];
  292. C_TFTeam *pBlueTeam = GetGlobalTFTeam( TF_TEAM_BLUE );
  293. const wchar_t *pBlueTeamName = pBlueTeam ? pBlueTeam->Get_Localized_Name() : L"BLU";
  294. C_TFTeam *pRedTeam = GetGlobalTFTeam( TF_TEAM_RED );
  295. const wchar_t *pRedTeamName = pRedTeam ? pRedTeam->Get_Localized_Name() : L"RED";
  296. wchar_t wszAttackersName[MAX_TEAM_NAME_LENGTH];
  297. wchar_t wszDefendersName[MAX_TEAM_NAME_LENGTH];
  298. V_wcscpy_safe( wszAttackersName, ( pAttacker->GetTeamNumber() == TF_TEAM_BLUE ) ? pBlueTeamName : pRedTeamName );
  299. V_wcscpy_safe( wszDefendersName, ( pDefender->GetTeamNumber() == TF_TEAM_BLUE ) ? pBlueTeamName : pRedTeamName );
  300. #ifdef WIN32
  301. #define INT_CHAR_FMT L"%d %s"
  302. #else
  303. #define INT_CHAR_FMT L"%d %S"
  304. #endif
  305. wchar_t wszPoints[256];
  306. _snwprintf( wszPoints, ARRAYSIZE( wszPoints ), INT_CHAR_FMT, iPoints, iPoints == 1 ? g_pVGuiLocalize->Find( "Tournament_StopWatch_Point" ) : g_pVGuiLocalize->Find( "Tournament_StopWatch_Points" ) );
  307. wchar_t wszTime[256];
  308. wchar_t wszLabel[256];
  309. int iMinutes = pTimer->GetTimeRemaining() / 60;
  310. int iSeconds = ((int)pTimer->GetTimeRemaining()) % 60;
  311. if ( iMinutes > 0 )
  312. {
  313. #ifdef WIN32
  314. _snwprintf( wszTime, ARRAYSIZE( wszTime ) , L"%d %s %d %s", iMinutes, iMinutes == 1 ? g_pVGuiLocalize->Find( "Tournament_WinConditionsMinute" ) : g_pVGuiLocalize->Find( "Tournament_WinConditionsMinutes" ), iSeconds, iSeconds == 1 ? g_pVGuiLocalize->Find( "Tournament_WinConditionsSecond" ) : g_pVGuiLocalize->Find( "Tournament_WinConditionsSeconds" ) );
  315. #else
  316. _snwprintf( wszTime, ARRAYSIZE( wszTime ) , L"%d %S %d %S", iMinutes, iMinutes == 1 ? g_pVGuiLocalize->Find( "Tournament_WinConditionsMinute" ) : g_pVGuiLocalize->Find( "Tournament_WinConditionsMinutes" ), iSeconds, iSeconds == 1 ? g_pVGuiLocalize->Find( "Tournament_WinConditionsSecond" ) : g_pVGuiLocalize->Find( "Tournament_WinConditionsSeconds" ) );
  317. #endif
  318. }
  319. else
  320. {
  321. _snwprintf( wszTime, ARRAYSIZE( wszTime ), INT_CHAR_FMT, iSeconds, iSeconds == 1 ? g_pVGuiLocalize->Find( "Tournament_WinConditionsSecond" ) : g_pVGuiLocalize->Find( "Tournament_WinConditionsSeconds" ) );
  322. }
  323. if ( m_pStopWatchGoalText )
  324. {
  325. m_pStopWatchGoalText->SetText("");
  326. }
  327. if ( m_pStopWatchGoalText2 )
  328. {
  329. m_pStopWatchGoalText2->SetText("");
  330. }
  331. if ( m_pStopWatchGoal )
  332. {
  333. m_pStopWatchGoal->SetDialogVariable( "objectivelabel", "" );
  334. }
  335. if ( pLocalPlayer->GetTeam() == pDefender )
  336. {
  337. g_pVGuiLocalize->ConstructString_safe( wszLabel, g_pVGuiLocalize->Find( "Tournament_StopWatch_LabelDefender" ), 1, wszAttackersName );
  338. if ( m_pStopWatchGoal )
  339. {
  340. m_pStopWatchGoal->SetDialogVariable( "objectivelabel", wszLabel );
  341. }
  342. }
  343. //Attackers capped something last round case
  344. if ( iPoints > 0 )
  345. {
  346. bool bCappedAllPoints = ( iPoints == ObjectiveResource()->GetNumControlPoints() );
  347. g_pVGuiLocalize->ConstructString_safe( wzHelp, g_pVGuiLocalize->Find( bCappedAllPoints ? "Tournament_StopWatch_GoalTextPointsAndTimeAndClose" : "Tournament_StopWatch_GoalTextPointsAndTime" ), 5, wszDefendersName, wszPoints, wszTime, wszAttackersName, wszPoints );
  348. if ( m_pStopWatchGoalText )
  349. {
  350. PrepareStopWatchString( wzHelp, m_pStopWatchGoalText );
  351. }
  352. if ( bCappedAllPoints )
  353. {
  354. if ( m_pStopWatchGoalText2 )
  355. {
  356. m_pStopWatchGoalText2->SetVisible( false );
  357. }
  358. if ( m_pStopWatchGoalBGLarge )
  359. {
  360. m_pStopWatchGoalBGLarge->SetVisible( false );
  361. }
  362. if ( m_pStopWatchGoalBGSmall )
  363. {
  364. m_pStopWatchGoalBGSmall->SetVisible( true );
  365. }
  366. if ( m_pStopWatchGoalDivider )
  367. {
  368. m_pStopWatchGoalDivider->SetVisible( false );
  369. }
  370. }
  371. else
  372. {
  373. if ( m_pStopWatchGoalText2 )
  374. {
  375. m_pStopWatchGoalText2->SetVisible( true );
  376. }
  377. if ( m_pStopWatchGoalBGLarge )
  378. {
  379. m_pStopWatchGoalBGLarge->SetVisible( true );
  380. }
  381. if ( m_pStopWatchGoalBGSmall )
  382. {
  383. m_pStopWatchGoalBGSmall->SetVisible( false );
  384. }
  385. if ( m_pStopWatchGoalDivider )
  386. {
  387. m_pStopWatchGoalDivider->SetVisible( true );
  388. }
  389. iPoints += 1;
  390. _snwprintf( wszPoints, ARRAYSIZE( wszPoints ), INT_CHAR_FMT, iPoints, iPoints == 1 ? g_pVGuiLocalize->Find( "Tournament_StopWatch_Point" ) : g_pVGuiLocalize->Find( "Tournament_StopWatch_Points" ) );
  391. g_pVGuiLocalize->ConstructString_safe( wzHelp, g_pVGuiLocalize->Find( "Tournament_StopWatch_GoalTextPointsAndTime2" ), 4, wszAttackersName, wszDefendersName, wszAttackersName, wszPoints );
  392. if ( m_pStopWatchGoalText2 )
  393. {
  394. PrepareStopWatchString( wzHelp, m_pStopWatchGoalText2 );
  395. }
  396. }
  397. if ( pLocalPlayer->GetTeam() == pAttacker )
  398. {
  399. g_pVGuiLocalize->ConstructString_safe( wszLabel, g_pVGuiLocalize->Find( "Tournament_StopWatch_TimeVictory" ), 1, wszDefendersName );
  400. if ( m_pStopWatchGoal )
  401. {
  402. m_pStopWatchGoal->SetDialogVariable( "objectivelabel", wszLabel );
  403. }
  404. }
  405. }
  406. else
  407. {
  408. if ( m_pStopWatchGoalText2 )
  409. {
  410. m_pStopWatchGoalText2->SetVisible( false );
  411. }
  412. if ( m_pStopWatchGoalBGLarge )
  413. {
  414. m_pStopWatchGoalBGLarge->SetVisible( false );
  415. }
  416. if ( m_pStopWatchGoalBGSmall )
  417. {
  418. m_pStopWatchGoalBGSmall->SetVisible( true );
  419. }
  420. if ( m_pStopWatchGoalDivider )
  421. {
  422. m_pStopWatchGoalDivider->SetVisible( false );
  423. }
  424. g_pVGuiLocalize->ConstructString_safe( wzHelp, g_pVGuiLocalize->Find( "Tournament_StopWatch_GoalTextPoints" ), 4, wszDefendersName, wszAttackersName );
  425. if ( m_pStopWatchGoalText )
  426. {
  427. PrepareStopWatchString( wzHelp, m_pStopWatchGoalText );
  428. }
  429. if ( pLocalPlayer->GetTeam() == pAttacker )
  430. {
  431. g_pVGuiLocalize->ConstructString_safe( wszLabel, g_pVGuiLocalize->Find( "Tournament_StopWatch_AttackerScore" ), 1, wszDefendersName );
  432. if ( m_pStopWatchGoal )
  433. {
  434. m_pStopWatchGoal->SetDialogVariable( "objectivelabel", wszLabel );
  435. }
  436. }
  437. }
  438. }
  439. //-----------------------------------------------------------------------------
  440. // Purpose:
  441. //-----------------------------------------------------------------------------
  442. bool CHudTeamGoalTournament::ShouldDraw( void )
  443. {
  444. if ( !TFGameRules() ||
  445. !TFGameRules()->IsInTournamentMode() ||
  446. !TFGameRules()->IsInStopWatch() ||
  447. ( ( TFGameRules()->State_Get() != GR_STATE_PREROUND ) && !TFGameRules()->InSetup() ) )
  448. {
  449. m_flShowAt = -1.f;
  450. return false;
  451. }
  452. if ( ObjectiveResource() )
  453. {
  454. int iActiveTimer = ObjectiveResource()->GetStopWatchTimer();
  455. CTeamRoundTimer *pTimer = dynamic_cast<CTeamRoundTimer*>( ClientEntityList().GetEnt( iActiveTimer ) );
  456. if ( pTimer && pTimer->IsWatchingTimeStamps() )
  457. {
  458. m_flShowAt = -1.f;
  459. return false;
  460. }
  461. }
  462. if ( ( m_flShowAt < 0 ) || ( m_flShowAt > gpGlobals->curtime ) )
  463. {
  464. return false;
  465. }
  466. // only show the panel for 15 seconds after it is first draws
  467. if ( gpGlobals->curtime - m_flShowAt > 15.f )
  468. {
  469. m_flShowAt = -1.f;
  470. return false;
  471. }
  472. C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
  473. if ( pPlayer && pPlayer->IsAlive() && ( pPlayer->GetTeamNumber() >= FIRST_GAME_TEAM ) )
  474. {
  475. if ( CHudElement::ShouldDraw() )
  476. {
  477. CHudElement *pHudSwitch = gHUD.FindElement( "CHudTeamSwitch" );
  478. if ( pHudSwitch && pHudSwitch->ShouldDraw() )
  479. return false;
  480. return true;
  481. }
  482. }
  483. return false;
  484. }