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.

976 lines
25 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include <vgui/ISurface.h>
  9. #include <vgui/ILocalize.h>
  10. #include "dod_shareddefs.h"
  11. #include "dodoverview.h"
  12. #include "c_playerresource.h"
  13. #include "c_dod_objective_resource.h"
  14. #include "usermessages.h"
  15. #include "coordsize.h"
  16. #include "clientmode.h"
  17. #include <vgui_controls/AnimationController.h>
  18. #include "voice_status.h"
  19. #include "spectatorgui.h"
  20. #include "dod_hud_freezepanel.h"
  21. using namespace vgui;
  22. void __MsgFunc_UpdateRadar(bf_read &msg)
  23. {
  24. if ( !g_pMapOverview )
  25. return;
  26. int iPlayerEntity = msg.ReadByte();
  27. while ( iPlayerEntity > 0 )
  28. {
  29. int x = msg.ReadSBitLong( COORD_INTEGER_BITS-1 ) * 4;
  30. int y = msg.ReadSBitLong( COORD_INTEGER_BITS-1 ) * 4;
  31. int a = msg.ReadSBitLong( 9 );
  32. Vector origin( x, y, 0 );
  33. QAngle angles( 0, a, 0 );
  34. g_pMapOverview->SetPlayerPositions( iPlayerEntity-1, origin, angles );
  35. iPlayerEntity = msg.ReadByte(); // read index for next player
  36. }
  37. }
  38. extern ConVar _overview_mode;
  39. ConVar _cl_minimapzoom( "_cl_minimapzoom", "1", FCVAR_ARCHIVE );
  40. ConVar _overview_mode( "_overview_mode", "1", FCVAR_ARCHIVE, "Overview mode - 0=off, 1=inset, 2=full\n", true, 0, true, 2 );
  41. CDODMapOverview *GetDODOverview( void )
  42. {
  43. return dynamic_cast<CDODMapOverview *>(g_pMapOverview);
  44. }
  45. // overview_togglezoom rotates through 3 levels of zoom for the small map
  46. //-----------------------------------------------------------------------
  47. void ToggleZoom( void )
  48. {
  49. if ( !GetDODOverview() )
  50. return;
  51. GetDODOverview()->ToggleZoom();
  52. }
  53. static ConCommand overview_togglezoom( "overview_togglezoom", ToggleZoom );
  54. // overview_largemap toggles showing the large map
  55. //------------------------------------------------
  56. void ShowLargeMap( void )
  57. {
  58. if ( !GetDODOverview() )
  59. return;
  60. GetDODOverview()->ShowLargeMap();
  61. }
  62. static ConCommand overview_showlargemap( "+overview_largemap", ShowLargeMap );
  63. void HideLargeMap( void )
  64. {
  65. if ( !GetDODOverview() )
  66. return;
  67. GetDODOverview()->HideLargeMap();
  68. }
  69. static ConCommand overview_hidelargemap( "-overview_largemap", HideLargeMap );
  70. //--------------------------------
  71. // map border ?
  72. // icon minimum zoom
  73. // flag swipes
  74. // grenades
  75. // chatting icon
  76. // voice com icon
  77. //---------------------------------
  78. DECLARE_HUDELEMENT( CDODMapOverview );
  79. ConVar dod_overview_voice_icon_size( "dod_overview_voice_icon_size", "64", FCVAR_ARCHIVE );
  80. CDODMapOverview::CDODMapOverview( const char *pElementName ) : BaseClass( pElementName )
  81. {
  82. InitTeamColorsAndIcons();
  83. m_flIconSize = 96.0f;
  84. m_iLastMode = MAP_MODE_OFF;
  85. usermessages->HookMessage( "UpdateRadar", __MsgFunc_UpdateRadar );
  86. }
  87. void CDODMapOverview::Update()
  88. {
  89. UpdateCapturePoints();
  90. BaseClass::Update();
  91. }
  92. void CDODMapOverview::VidInit( void )
  93. {
  94. m_pC4Icon = gHUD.GetIcon( "icon_c4" );
  95. m_pExplodedIcon = gHUD.GetIcon( "icon_c4_exploded" );
  96. m_pC4PlantedBG = gHUD.GetIcon( "icon_c4_planted_bg" );
  97. m_pIconDefended = gHUD.GetIcon( "icon_defended" );
  98. BaseClass::VidInit();
  99. }
  100. void CDODMapOverview::UpdateCapturePoints()
  101. {
  102. if ( !g_pObjectiveResource )
  103. return;
  104. Color colorGreen(0,255,0,255);
  105. if ( !g_pObjectiveResource )
  106. return;
  107. for( int i=0;i<g_pObjectiveResource->GetNumControlPoints();i++ )
  108. {
  109. // check if CP is visible at all
  110. if( !g_pObjectiveResource->IsCPVisible(i) )
  111. {
  112. if ( m_CapturePoints[i] != 0 )
  113. {
  114. // remove capture point from map
  115. RemoveObject( m_CapturePoints[i] );
  116. m_CapturePoints[i] = 0;
  117. }
  118. continue;
  119. }
  120. // ok, show CP
  121. int iOwningTeam = g_pObjectiveResource->GetOwningTeam(i);
  122. int iCappingTeam = g_pObjectiveResource->GetCappingTeam(i);
  123. int iOwningIcon = g_pObjectiveResource->GetIconForTeam( i, iOwningTeam );
  124. if ( iOwningIcon <= 0 )
  125. continue; // baah
  126. const char *textureName = GetMaterialNameFromIndex( iOwningIcon );
  127. int objID = m_CapturePoints[i];
  128. if ( objID == 0 )
  129. {
  130. // add object if not already there
  131. objID = m_CapturePoints[i] = AddObject( textureName, 0, -1 );
  132. // objective positions never change (so far)
  133. SetObjectPosition( objID, g_pObjectiveResource->GetCPPosition(i), vec3_angle );
  134. AddObjectFlags( objID, MAP_OBJECT_ALIGN_TO_MAP );
  135. }
  136. SetObjectIcon( objID, textureName, 128.0 );
  137. int iBombs = g_pObjectiveResource->GetBombsRemaining( i );
  138. if ( iBombs > 0 )
  139. {
  140. char text[8];
  141. Q_snprintf( text, sizeof(text), "%d", iBombs );
  142. SetObjectText( objID, text, colorGreen );
  143. }
  144. //Draw the number of cappers below the icon
  145. else if ( iCappingTeam != TEAM_UNASSIGNED )
  146. {
  147. int numPlayers = g_pObjectiveResource->GetNumPlayersInArea( i, iCappingTeam );
  148. int requiredPlayers = g_pObjectiveResource->GetRequiredCappers( i, iCappingTeam );
  149. if( requiredPlayers > 1 )
  150. {
  151. char text[8];
  152. Q_snprintf( text, sizeof(text), "%d/%d", numPlayers, requiredPlayers );
  153. SetObjectText( objID, text, colorGreen );
  154. }
  155. else
  156. {
  157. SetObjectText( objID, NULL, colorGreen );
  158. }
  159. }
  160. else
  161. {
  162. SetObjectText( objID, NULL, colorGreen );
  163. }
  164. float flBombTime = g_pObjectiveResource->GetBombTimeForPoint( i );
  165. //Draw cap percentage
  166. if( iCappingTeam != TEAM_UNASSIGNED )
  167. {
  168. SetObjectStatus( objID, g_pObjectiveResource->GetCPCapPercentage(i), colorGreen );
  169. }
  170. else if ( flBombTime > 0 )
  171. {
  172. float flPercentRemaining = ( flBombTime / DOD_BOMB_TIMER_LENGTH );
  173. SetObjectStatus( objID, flPercentRemaining, colorGreen );
  174. }
  175. else
  176. {
  177. SetObjectStatus( objID, -1, colorGreen ); // turn it off
  178. }
  179. }
  180. }
  181. void CDODMapOverview::InitTeamColorsAndIcons()
  182. {
  183. BaseClass::InitTeamColorsAndIcons();
  184. m_TeamColors[TEAM_ALLIES] = COLOR_DOD_GREEN;
  185. m_TeamIcons[TEAM_ALLIES] = AddIconTexture( "sprites/minimap_icons/aplayer" );
  186. m_CameraIcons[TEAM_ALLIES] = AddIconTexture( "sprites/minimap_icons/allies_camera" );
  187. m_TeamColors[TEAM_AXIS] = COLOR_DOD_RED;
  188. m_TeamIcons[TEAM_AXIS] = AddIconTexture( "sprites/minimap_icons/gplayer" );
  189. m_CameraIcons[TEAM_AXIS] = AddIconTexture( "sprites/minimap_icons/axis_camera" );
  190. Q_memset( m_flPlayerChatTime, 0, sizeof(m_flPlayerChatTime ) );
  191. m_iVoiceIcon = AddIconTexture( "voice/icntlk_pl" );
  192. m_iChatIcon = AddIconTexture( "sprites/minimap_icons/voiceIcon" );
  193. Q_memset( m_CapturePoints, 0, sizeof(m_CapturePoints) );
  194. }
  195. void CDODMapOverview::DrawCamera()
  196. {
  197. C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer();
  198. if ( !localPlayer )
  199. return;
  200. int iTexture = m_CameraIcons[localPlayer->GetTeamNumber()];
  201. if ( localPlayer->IsObserver() || iTexture <= 0 )
  202. {
  203. BaseClass::DrawCamera();
  204. }
  205. else
  206. {
  207. MapObject_t obj;
  208. memset( &obj, 0, sizeof(MapObject_t) );
  209. obj.icon = iTexture;
  210. obj.position = localPlayer->GetAbsOrigin();
  211. obj.size = m_flIconSize * 1.5;
  212. obj.angle = localPlayer->EyeAngles();
  213. obj.status = -1;
  214. DrawIcon( &obj );
  215. DrawVoiceIconForPlayer( localPlayer->entindex() - 1 );
  216. }
  217. }
  218. void CDODMapOverview::FireGameEvent( IGameEvent *event )
  219. {
  220. const char * type = event->GetName();
  221. if ( Q_strcmp(type, "player_death") == 0 )
  222. {
  223. MapPlayer_t *player = GetPlayerByUserID( event->GetInt("userid") );
  224. if ( player && CanPlayerBeSeen( player ) )
  225. {
  226. // create skull icon for 3 seconds
  227. int handle = AddObject( "sprites/minimap_icons/death", 0, 3 );
  228. SetObjectText( handle, player->name, player->color );
  229. SetObjectPosition( handle, player->position, player->angle );
  230. }
  231. }
  232. else if ( Q_strcmp(type, "game_newmap") == 0 )
  233. {
  234. SetMode( _overview_mode.GetInt() );
  235. }
  236. BaseClass::FireGameEvent( event );
  237. }
  238. // rules that define if you can see a player on the overview or not
  239. bool CDODMapOverview::CanPlayerBeSeen(MapPlayer_t *player)
  240. {
  241. C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer();
  242. if ( !localPlayer || !player )
  243. return false;
  244. // don't draw ourselves
  245. if ( localPlayer->entindex() == (player->index+1) )
  246. return false;
  247. // if local player is on spectator team, he can see everyone
  248. if ( localPlayer->GetTeamNumber() <= TEAM_SPECTATOR )
  249. return true;
  250. // we never track unassigned or real spectators
  251. if ( player->team <= TEAM_SPECTATOR )
  252. return false;
  253. // ingame and as dead player we can only see our own teammates
  254. return (localPlayer->GetTeamNumber() == player->team );
  255. }
  256. void CDODMapOverview::ShowLargeMap( void )
  257. {
  258. // remember old mode
  259. m_iLastMode = GetMode();
  260. // if we hit the toggle while full, set to disappear when we release
  261. if ( m_iLastMode == MAP_MODE_FULL )
  262. m_iLastMode = MAP_MODE_OFF;
  263. SetMode( MAP_MODE_FULL );
  264. }
  265. void CDODMapOverview::HideLargeMap( void )
  266. {
  267. SetMode( m_iLastMode );
  268. }
  269. void CDODMapOverview::ToggleZoom( void )
  270. {
  271. if ( GetMode() != MAP_MODE_INSET )
  272. return;
  273. int iZoomLevel = ( _cl_minimapzoom.GetInt() + 1 ) % DOD_MAP_ZOOM_LEVELS;
  274. _cl_minimapzoom.SetValue( iZoomLevel );
  275. switch( _cl_minimapzoom.GetInt() )
  276. {
  277. case 0:
  278. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "MapZoomLevel1" );
  279. break;
  280. case 1:
  281. default:
  282. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "MapZoomLevel2" );
  283. break;
  284. }
  285. }
  286. void CDODMapOverview::SetMode(int mode)
  287. {
  288. m_flChangeSpeed = 0; // change size instantly
  289. if ( mode == MAP_MODE_OFF )
  290. {
  291. ShowPanel( false );
  292. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "MapOff" );
  293. }
  294. else if ( mode == MAP_MODE_INSET )
  295. {
  296. switch( _cl_minimapzoom.GetInt() )
  297. {
  298. case 0:
  299. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "MapZoomLevel1" );
  300. break;
  301. case 1:
  302. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "MapZoomLevel2" );
  303. break;
  304. case 2:
  305. default:
  306. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "MapZoomLevel3" );
  307. break;
  308. }
  309. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  310. if ( pPlayer )
  311. SetFollowEntity( pPlayer->entindex() );
  312. ShowPanel( true );
  313. if ( m_nMode == MAP_MODE_FULL )
  314. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "MapScaleToSmall" );
  315. else
  316. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "SnapToSmall" );
  317. }
  318. else if ( mode == MAP_MODE_FULL )
  319. {
  320. SetFollowEntity( 0 );
  321. ShowPanel( true );
  322. if ( m_nMode == MAP_MODE_INSET )
  323. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "ZoomToLarge" );
  324. else
  325. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "SnapToLarge" );
  326. }
  327. // finally set mode
  328. m_nMode = mode;
  329. // save in a cvar for archive
  330. _overview_mode.SetValue( m_nMode );
  331. UpdateSizeAndPosition();
  332. }
  333. void CDODMapOverview::UpdateSizeAndPosition()
  334. {
  335. // move back up if the spectator menu is not visible
  336. if ( !g_pSpectatorGUI || ( !g_pSpectatorGUI->IsVisible() && GetMode() == MAP_MODE_INSET ) )
  337. {
  338. int x,y,w,h;
  339. GetBounds( x,y,w,h );
  340. y = YRES(5); // hax, align to top of the screen
  341. SetBounds( x,y,w,h );
  342. }
  343. BaseClass::UpdateSizeAndPosition();
  344. }
  345. void CDODMapOverview::AddGrenade( C_DODBaseGrenade *pGrenade )
  346. {
  347. C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer();
  348. if ( !localPlayer )
  349. return;
  350. int localTeam = localPlayer->GetTeamNumber();
  351. // Spectators can see all grenades
  352. // players can only see them if they are on the same team
  353. if ( localTeam == TEAM_SPECTATOR || ( localTeam == pGrenade->GetTeamNumber() ) )
  354. {
  355. AddObject( pGrenade->GetOverviewSpriteName(), pGrenade->entindex(), -1 );
  356. }
  357. }
  358. void CDODMapOverview::RemoveGrenade( C_DODBaseGrenade *pGrenade )
  359. {
  360. RemoveObjectByIndex( pGrenade->entindex() );
  361. }
  362. ConVar cl_voicetest( "cl_voicetest", "0", FCVAR_CHEAT );
  363. ConVar cl_overview_chat_time( "cl_overview_chat_time", "2.0", FCVAR_ARCHIVE );
  364. void CDODMapOverview::PlayerChat( int index )
  365. {
  366. m_flPlayerChatTime[index-1] = gpGlobals->curtime + cl_overview_chat_time.GetFloat();
  367. }
  368. void CDODMapOverview::DrawMapPlayers()
  369. {
  370. BaseClass::DrawMapPlayers();
  371. C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer();
  372. Assert( localPlayer );
  373. int iLocalPlayer = localPlayer->entindex() - 1;
  374. for (int i=0; i<MAX_PLAYERS; i++)
  375. {
  376. if ( i == iLocalPlayer )
  377. continue;
  378. MapPlayer_t *player = &m_Players[i];
  379. if ( !CanPlayerBeSeen( player ) )
  380. continue;
  381. if ( player->health <= 0 ) // don't draw dead players / spectators
  382. continue;
  383. DrawVoiceIconForPlayer( i );
  384. }
  385. }
  386. void CDODMapOverview::DrawVoiceIconForPlayer( int playerIndex )
  387. {
  388. Assert( playerIndex >= 0 && playerIndex < MAX_PLAYERS );
  389. MapPlayer_t *player = &m_Players[playerIndex];
  390. // if they just sent a chat msg, or are using voice, or did a hand signal or voice command
  391. // draw a chat icon
  392. if ( cl_voicetest.GetInt() || GetClientVoiceMgr()->IsPlayerSpeaking( player->index+1 ) )
  393. {
  394. MapObject_t obj;
  395. memset( &obj, 0, sizeof(MapObject_t) );
  396. obj.icon = m_iVoiceIcon;
  397. obj.position = player->position;
  398. obj.size = dod_overview_voice_icon_size.GetFloat();
  399. obj.status = -1;
  400. DrawIcon( &obj );
  401. }
  402. else if ( m_flPlayerChatTime[player->index] > gpGlobals->curtime )
  403. {
  404. MapObject_t obj;
  405. memset( &obj, 0, sizeof(MapObject_t) );
  406. obj.icon = m_iChatIcon;
  407. obj.position = player->position;
  408. obj.size = dod_overview_voice_icon_size.GetFloat();
  409. obj.status = -1;
  410. DrawIcon( &obj );
  411. }
  412. }
  413. bool CDODMapOverview::DrawIcon( MapObject_t *obj )
  414. {
  415. for ( int i=0;i<MAX_CONTROL_POINTS;i++ )
  416. {
  417. if ( obj->objectID == m_CapturePoints[i] && obj->objectID != 0 )
  418. {
  419. return DrawCapturePoint( i, obj );
  420. }
  421. }
  422. return BaseClass::DrawIcon( obj );
  423. }
  424. void CDODMapOverview::DrawQuad( Vector pos, int scale, float angle, int textureID, int alpha )
  425. {
  426. Vector offset;
  427. offset.z = 0;
  428. offset.x = -scale; offset.y = scale;
  429. VectorYawRotate( offset, angle, offset );
  430. Vector2D pos1 = WorldToMap( pos + offset );
  431. offset.x = scale; offset.y = scale;
  432. VectorYawRotate( offset, angle, offset );
  433. Vector2D pos2 = WorldToMap( pos + offset );
  434. offset.x = scale; offset.y = -scale;
  435. VectorYawRotate( offset, angle, offset );
  436. Vector2D pos3 = WorldToMap( pos + offset );
  437. offset.x = -scale; offset.y = -scale;
  438. VectorYawRotate( offset, angle, offset );
  439. Vector2D pos4 = WorldToMap( pos + offset );
  440. Vertex_t points[4] =
  441. {
  442. Vertex_t( MapToPanel ( pos1 ), Vector2D(0,0) ),
  443. Vertex_t( MapToPanel ( pos2 ), Vector2D(1,0) ),
  444. Vertex_t( MapToPanel ( pos3 ), Vector2D(1,1) ),
  445. Vertex_t( MapToPanel ( pos4 ), Vector2D(0,1) )
  446. };
  447. surface()->DrawSetColor( 255, 255, 255, alpha );
  448. surface()->DrawSetTexture( textureID );
  449. surface()->DrawTexturedPolygon( 4, points );
  450. }
  451. bool CDODMapOverview::DrawCapturePoint( int iCP, MapObject_t *obj )
  452. {
  453. int textureID = obj->icon;
  454. Vector pos = obj->position;
  455. float scale = obj->size;
  456. float angle = 0;
  457. Vector2D pospanel = WorldToMap( pos );
  458. pospanel = MapToPanel( pospanel );
  459. if ( !IsInPanel( pospanel ) )
  460. return false; // player is not within overview panel
  461. int iBombsRequired = g_pObjectiveResource->GetBombsRequired( iCP );
  462. if ( iBombsRequired )
  463. {
  464. if ( g_pObjectiveResource->IsBombSetAtPoint( iCP ) )
  465. {
  466. // draw swipe over blank icon
  467. // 'white' icon
  468. int iBlankIcon = g_pObjectiveResource->GetCPTimerCapIcon( iCP );
  469. const char *textureName = GetMaterialNameFromIndex( iBlankIcon );
  470. DrawQuad( pos, scale, 0, AddIconTexture( textureName ), 255 );
  471. // the circular swipe
  472. float flBombTime = g_pObjectiveResource->GetBombTimeForPoint( iCP );
  473. float flPercentRemaining = ( flBombTime / DOD_BOMB_TIMER_LENGTH );
  474. DrawBombTimerSwipeIcon( pos, scale, textureID, flPercentRemaining );
  475. }
  476. else
  477. {
  478. DrawQuad( pos, scale, 0, textureID, 255 );
  479. }
  480. }
  481. else
  482. {
  483. // draw capture swipe
  484. DrawQuad( pos, scale, 0, textureID, 255 );
  485. int iCappingTeam = g_pObjectiveResource->GetCappingTeam( iCP );
  486. if ( iCappingTeam != TEAM_UNASSIGNED )
  487. {
  488. int iCapperIcon = g_pObjectiveResource->GetCPCappingIcon( iCP );
  489. const char *textureName = GetMaterialNameFromIndex( iCapperIcon );
  490. float flCapPercent = g_pObjectiveResource->GetCPCapPercentage(iCP);
  491. bool bSwipeLeft = ( iCappingTeam == TEAM_AXIS ) ? true : false;
  492. DrawHorizontalSwipe( pos, scale, AddIconTexture( textureName ), flCapPercent, bSwipeLeft );
  493. }
  494. // fixup for noone is capping, but someone is in the area
  495. int iNumAllies = g_pObjectiveResource->GetNumPlayersInArea( iCP, TEAM_ALLIES );
  496. int iNumAxis = g_pObjectiveResource->GetNumPlayersInArea( iCP, TEAM_AXIS );
  497. int iOwningTeam = g_pObjectiveResource->GetOwningTeam( iCP );
  498. if ( iCappingTeam == TEAM_UNASSIGNED )
  499. {
  500. if ( iNumAllies > 0 && iNumAxis == 0 && iOwningTeam != TEAM_ALLIES )
  501. {
  502. iCappingTeam = TEAM_ALLIES;
  503. }
  504. else if ( iNumAxis > 0 && iNumAllies == 0 && iOwningTeam != TEAM_AXIS )
  505. {
  506. iCappingTeam = TEAM_AXIS;
  507. }
  508. }
  509. if ( iCappingTeam != TEAM_UNASSIGNED )
  510. {
  511. // Draw the number of cappers below the icon
  512. int numPlayers = g_pObjectiveResource->GetNumPlayersInArea( iCP, iCappingTeam );
  513. int requiredPlayers = g_pObjectiveResource->GetRequiredCappers( iCP, iCappingTeam );
  514. if ( requiredPlayers > 1 )
  515. {
  516. numPlayers = MIN( numPlayers, requiredPlayers );
  517. wchar_t wText[6];
  518. _snwprintf( wText, sizeof(wText)/sizeof(wchar_t), L"%d/%d", numPlayers, requiredPlayers );
  519. int wide, tall;
  520. surface()->GetTextSize( m_hIconFont, wText, wide, tall );
  521. int x = pospanel.x-(wide/2);
  522. int y = pospanel.y;
  523. // match the offset that MapOverview uses
  524. y += GetPixelOffset( scale ) + 4;
  525. // draw black shadow text
  526. surface()->DrawSetTextColor( 0, 0, 0, 255 );
  527. surface()->DrawSetTextPos( x+1, y );
  528. surface()->DrawPrintText( wText, wcslen(wText) );
  529. // draw name in color
  530. surface()->DrawSetTextColor( g_PR->GetTeamColor( iCappingTeam ) );
  531. surface()->DrawSetTextPos( x, y );
  532. surface()->DrawPrintText( wText, wcslen(wText) );
  533. }
  534. }
  535. }
  536. // draw bombs underneath if necessary
  537. if ( iBombsRequired > 0 )
  538. {
  539. int iBombsRemaining = g_pObjectiveResource->GetBombsRemaining( iCP );
  540. bool bBombPlanted = g_pObjectiveResource->IsBombSetAtPoint( iCP );
  541. // draw bomb state underneath
  542. float flBombIconScale = scale * 0.5;
  543. switch( iBombsRequired )
  544. {
  545. case 1:
  546. {
  547. Vector bombPos = pos;
  548. bombPos.y -= scale * 1.5;
  549. switch( iBombsRemaining )
  550. {
  551. case 0:
  552. DrawQuad( bombPos, flBombIconScale, angle, m_pExplodedIcon->textureId, 255 );
  553. break;
  554. case 1:
  555. if ( bBombPlanted )
  556. {
  557. // draw the background behind 1
  558. int alpha = (float)( abs( sin(2*gpGlobals->curtime) ) * 205.0 + 50.0 );
  559. DrawQuad( bombPos, flBombIconScale*2, angle, m_pC4PlantedBG->textureId, alpha );
  560. }
  561. DrawQuad( bombPos, flBombIconScale, angle, m_pC4Icon->textureId, 255 );
  562. break;
  563. }
  564. }
  565. break;
  566. case 2:
  567. {
  568. Vector bombPos1, bombPos2;
  569. bombPos1 = bombPos2 = pos;
  570. bombPos1.y = bombPos2.y = pos.y - scale * 1.5;
  571. bombPos1.x = pos.x - scale * 0.5;
  572. bombPos2.x = pos.x + scale * 0.5;
  573. switch( iBombsRemaining )
  574. {
  575. case 0:
  576. DrawQuad( bombPos1, flBombIconScale, angle, m_pExplodedIcon->textureId, 255 );
  577. DrawQuad( bombPos2, flBombIconScale, angle, m_pExplodedIcon->textureId, 255 );
  578. break;
  579. case 1:
  580. if ( bBombPlanted )
  581. {
  582. // draw the background behind 1
  583. int alpha = (float)( abs( sin(2*gpGlobals->curtime) ) * 205.0 + 50.0 );
  584. DrawQuad( bombPos1, flBombIconScale*2, angle, m_pC4PlantedBG->textureId, alpha );
  585. }
  586. DrawQuad( bombPos1, flBombIconScale, angle, m_pC4Icon->textureId, 255 );
  587. DrawQuad( bombPos2, flBombIconScale, angle, m_pExplodedIcon->textureId, 255 );
  588. break;
  589. case 2:
  590. if ( bBombPlanted )
  591. {
  592. // draw the background behind 2
  593. int alpha = (float)( abs( sin(2*gpGlobals->curtime) ) * 205.0 + 50.0 );
  594. DrawQuad( bombPos2, flBombIconScale*2, angle, m_pC4PlantedBG->textureId, alpha );
  595. }
  596. DrawQuad( bombPos1, flBombIconScale, angle, m_pC4Icon->textureId, 255 );
  597. DrawQuad( bombPos2, flBombIconScale, angle, m_pC4Icon->textureId, 255 );
  598. break;
  599. }
  600. }
  601. break;
  602. }
  603. // draw shield over top
  604. if ( g_pObjectiveResource->IsBombBeingDefused( iCP ) )
  605. {
  606. DrawQuad( pos, scale * 0.75, angle, m_pIconDefended->textureId, 255 );
  607. }
  608. }
  609. return true;
  610. }
  611. void CDODMapOverview::DrawBombTimerSwipeIcon( Vector pos, int scale, int textureID, float flPercentRemaining )
  612. {
  613. const float flCompleteCircle = ( 2.0f * M_PI );
  614. const float fl90degrees = flCompleteCircle * 0.25f;
  615. const float fl45degrees = fl90degrees * 0.5f;
  616. float flEndAngle = flCompleteCircle * flPercentRemaining; // clockwise
  617. typedef struct
  618. {
  619. Vector2D vecTrailing;
  620. Vector2D vecLeading;
  621. } icon_quadrant_t;
  622. /*
  623. Quadrants are numbered 0 - 7 counter-clockwise
  624. _________________
  625. | 0 | 7 |
  626. | | |
  627. | 1 | 6 |
  628. -----------------
  629. | 2 | 5 |
  630. | | |
  631. | 3 | 4 |
  632. -----------------
  633. */
  634. // Encode the leading and trailing edge of each quadrant
  635. // in the range 0.0 -> 1.0
  636. icon_quadrant_t quadrants[8];
  637. quadrants[0].vecTrailing.Init( 0.5, 0.0 );
  638. quadrants[0].vecLeading.Init( 0.0, 0.0 );
  639. quadrants[1].vecTrailing.Init( 0.0, 0.0 );
  640. quadrants[1].vecLeading.Init( 0.0, 0.5 );
  641. quadrants[2].vecTrailing.Init( 0.0, 0.5 );
  642. quadrants[2].vecLeading.Init( 0.0, 1.0 );
  643. quadrants[3].vecTrailing.Init( 0.0, 1.0 );
  644. quadrants[3].vecLeading.Init( 0.5, 1.0 );
  645. quadrants[4].vecTrailing.Init( 0.5, 1.0 );
  646. quadrants[4].vecLeading.Init( 1.0, 1.0 );
  647. quadrants[5].vecTrailing.Init( 1.0, 1.0 );
  648. quadrants[5].vecLeading.Init( 1.0, 0.5 );
  649. quadrants[6].vecTrailing.Init( 1.0, 0.5 );
  650. quadrants[6].vecLeading.Init( 1.0, 0.0 );
  651. quadrants[7].vecTrailing.Init( 1.0, 0.0 );
  652. quadrants[7].vecLeading.Init( 0.5, 0.0 );
  653. surface()->DrawSetColor( 255, 255, 255, 255 );
  654. surface()->DrawSetTexture( textureID );
  655. Vector2D uvMid( 0.5, 0.5 );
  656. Vector2D newPos( pos.x - scale, pos.y + scale );
  657. int j;
  658. for ( j=0;j<=7;j++ )
  659. {
  660. float flMinAngle = j * fl45degrees;
  661. float flAngle = clamp( flEndAngle - flMinAngle, 0, fl45degrees );
  662. if ( flAngle <= 0 )
  663. {
  664. // past our quadrant, draw nothing
  665. continue;
  666. }
  667. else
  668. {
  669. // draw our segment
  670. vgui::Vertex_t vert[3];
  671. // vert 0 is mid ( 0.5, 0.5 )
  672. Vector2D pos0 = WorldToMap( pos );
  673. vert[0].Init( MapToPanel( pos0 ), uvMid );
  674. int xdir = 0, ydir = 0;
  675. switch( j )
  676. {
  677. case 0:
  678. case 7:
  679. //right
  680. xdir = 1;
  681. ydir = 0;
  682. break;
  683. case 1:
  684. case 2:
  685. //up
  686. xdir = 0;
  687. ydir = -1;
  688. break;
  689. case 3:
  690. case 4:
  691. //left
  692. xdir = -1;
  693. ydir = 0;
  694. break;
  695. case 5:
  696. case 6:
  697. //down
  698. xdir = 0;
  699. ydir = 1;
  700. break;
  701. }
  702. Vector vec1;
  703. Vector2D uv1;
  704. // vert 1 is the variable vert based on leading edge
  705. vec1.x = newPos.x + quadrants[j].vecTrailing.x * scale*2 - xdir * tan(flAngle) * scale;
  706. vec1.y = newPos.y - quadrants[j].vecTrailing.y * scale*2 + ydir * tan(flAngle) * scale;
  707. uv1.x = quadrants[j].vecTrailing.x - xdir * abs( quadrants[j].vecLeading.x - quadrants[j].vecTrailing.x ) * tan(flAngle);
  708. uv1.y = quadrants[j].vecTrailing.y - ydir * abs( quadrants[j].vecLeading.y - quadrants[j].vecTrailing.y ) * tan(flAngle);
  709. Vector2D pos1 = WorldToMap( vec1 );
  710. vert[1].Init( MapToPanel( pos1 ), uv1 );
  711. // vert 2 is our trailing edge
  712. Vector vec2;
  713. vec2.x = newPos.x + quadrants[j].vecTrailing.x * scale*2;
  714. vec2.y = newPos.y - quadrants[j].vecTrailing.y * scale*2;
  715. Vector2D pos2 = WorldToMap( vec2 );
  716. vert[2].Init( MapToPanel( pos2 ), quadrants[j].vecTrailing );
  717. surface()->DrawTexturedPolygon( 3, vert );
  718. }
  719. }
  720. }
  721. void CDODMapOverview::DrawHorizontalSwipe( Vector pos, int scale, int textureID, float flCapPercentage, bool bSwipeLeft )
  722. {
  723. float flIconSize = scale * 2;
  724. float width = ( flIconSize * flCapPercentage );
  725. float uv1 = 0.0f;
  726. float uv2 = 1.0f;
  727. Vector2D uv11( uv1, uv2 );
  728. Vector2D uv21( flCapPercentage, uv2 );
  729. Vector2D uv22( flCapPercentage, uv1 );
  730. Vector2D uv12( uv1, uv1 );
  731. // reversing the direction of the swipe effect
  732. if ( bSwipeLeft )
  733. {
  734. uv11.x = uv2 - flCapPercentage;
  735. uv21.x = uv2;
  736. uv22.x = uv2;
  737. uv12.x = uv2 - flCapPercentage;
  738. }
  739. float flXPos = pos.x - scale;
  740. float flYPos = pos.y - scale;
  741. Vector upperLeft( flXPos, flYPos, 0 );
  742. Vector upperRight( flXPos + width, flYPos, 0 );
  743. Vector lowerRight( flXPos + width, flYPos + flIconSize, 0 );
  744. Vector lowerLeft ( flXPos, flYPos + flIconSize, 0 );
  745. /// reversing the direction of the swipe effect
  746. if ( bSwipeLeft )
  747. {
  748. upperLeft.x = flXPos + flIconSize - width;
  749. upperRight.x = flXPos + flIconSize;
  750. lowerRight.x = flXPos + flIconSize;
  751. lowerLeft.x = flXPos + flIconSize - width;
  752. }
  753. vgui::Vertex_t vert[4];
  754. Vector2D pos0 = WorldToMap( upperLeft );
  755. vert[0].Init( MapToPanel( pos0 ), uv11 );
  756. Vector2D pos3 = WorldToMap( lowerLeft );
  757. vert[1].Init( MapToPanel( pos3 ), uv12 );
  758. Vector2D pos2 = WorldToMap( lowerRight );
  759. vert[2].Init( MapToPanel( pos2 ), uv22 );
  760. Vector2D pos1 = WorldToMap( upperRight );
  761. vert[3].Init( MapToPanel( pos1 ), uv21 );
  762. surface()->DrawSetColor( 255, 255, 255, 255 );
  763. surface()->DrawSetTexture( textureID );
  764. surface()->DrawTexturedPolygon( 4, vert );
  765. }
  766. bool CDODMapOverview::IsVisible( void )
  767. {
  768. if ( IsTakingAFreezecamScreenshot() )
  769. return false;
  770. return BaseClass::IsVisible();
  771. }