sniper.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** Confidential - Westwood Studios ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Commando *
  23. * *
  24. * $Archive:: /Commando/Code/Combat/sniper.cpp $*
  25. * *
  26. * $Author:: Byon_g $*
  27. * *
  28. * $Modtime:: 7/05/01 11:37a $*
  29. * *
  30. * $Revision:: 60 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "sniper.h"
  36. #include "render2d.h"
  37. #include "texture.h"
  38. #include "assets.h"
  39. #include "combat.h"
  40. #include "ccamera.h"
  41. #include "debug.h"
  42. #include "globalsettings.h"
  43. #include "timemgr.h"
  44. #include "input.h"
  45. /*
  46. **
  47. */
  48. Vector2 SNIPER_UV_SCALE( 1.0f/128.0f, 1.0f/128.0f );
  49. Vector2 BLACK_UV_UL( 1, 1 );
  50. Vector2 BLACK_UV_LR( 5, 7 );
  51. Vector2 SNIPER_VIEW_UV_UL( 1, 2 );
  52. Vector2 SNIPER_VIEW_UV_LR( 115, 115 );
  53. Vector2 SNIPER_VIEW_UL( 193, 153 );
  54. Vector2 SNIPER_VIEW_LR( 839, 853 );
  55. Vector2 BOX_SIZE( 235, 127 );
  56. Vector2 TOP_LINE_1( 149, 209 );
  57. Vector2 TOP_LINE_2( 151, 426 );
  58. Vector2 TOP_LINE_3( 151, 403 );
  59. Vector2 BOTTOM_LINE_1( 543, 768 );
  60. Vector2 BOTTOM_LINE_2( 34, 597 );
  61. Vector2 BOTTOM_LINE_3( 519, 10 );
  62. Vector2 CENTER_LINE_1( 144, 42 );
  63. Vector2 CENTER_LINE_2( 166, 117 );
  64. Vector2 LEFT_LINE_UL( 203, 723 );
  65. Vector2 LEFT_LINE_LR( 222, 10 );
  66. Vector2 LEFT_LINE_2( 247, 435 );
  67. Vector2 ZOOM_UV_UL( 117, 41 );
  68. Vector2 ZOOM_UV_LR( 128, 62 );
  69. Vector2 ZOOM_OFFSET_TOP( 177, 620 );
  70. Vector2 ZOOM_OFFSET_BOTTOM( 177, 316 );
  71. /*
  72. **
  73. */
  74. #define SNIPER_LEFT_BLACK_COVER RectClass( 0, 0, settings->SniperView.Left, 1 )
  75. #define SNIPER_RIGHT_BLACK_COVER RectClass( settings->SniperView.Right, 0, 1, 1 )
  76. #define SNIPER_TOP_BLACK_COVER RectClass( settings->SniperView.Left, 0, settings->SniperView.Right, settings->SniperView.Top )
  77. #define SNIPER_BOTTOM_BLACK_COVER RectClass( settings->SniperView.Left, settings->SniperView.Bottom, settings->SniperView.Right, 1 )
  78. /*
  79. **
  80. */
  81. Render2DClass * _Sniper2DBaseRenderer;
  82. Render2DClass * _Sniper2DRenderer;
  83. #define HUD_SNIPER_TEXTURE "hud_sniper.tga"
  84. static void Info_Editor_Init( void );
  85. static void Info_Editor_Update( void );
  86. static void Info_Editor_Shutdown( void );
  87. /*
  88. **
  89. */
  90. void SniperHUDClass::Init( void )
  91. {
  92. _Sniper2DBaseRenderer = new Render2DClass();
  93. _Sniper2DBaseRenderer->Set_Texture( HUD_SNIPER_TEXTURE );
  94. _Sniper2DBaseRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  95. Build_Base();
  96. _Sniper2DRenderer = new Render2DClass();
  97. _Sniper2DRenderer->Set_Texture( HUD_SNIPER_TEXTURE );
  98. _Sniper2DRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  99. // Info_Editor_Init();
  100. }
  101. /*
  102. **
  103. */
  104. void SniperHUDClass::Shutdown( void )
  105. {
  106. if ( _Sniper2DBaseRenderer ) {
  107. delete _Sniper2DBaseRenderer;
  108. _Sniper2DBaseRenderer = NULL;
  109. }
  110. if ( _Sniper2DRenderer ) {
  111. delete _Sniper2DRenderer;
  112. _Sniper2DRenderer = NULL;
  113. }
  114. // Info_Editor_Shutdown();
  115. }
  116. void SniperHUDClass::Build_Base( void )
  117. {
  118. if ( _Sniper2DBaseRenderer == NULL ) {
  119. return;
  120. }
  121. _Sniper2DBaseRenderer->Reset();
  122. RectClass uv;
  123. RectClass draw;
  124. uv.Set( SNIPER_VIEW_UV_UL, SNIPER_VIEW_UV_LR );
  125. uv.Scale( SNIPER_UV_SCALE );
  126. Vector2 screen_size = Render2DClass::Get_Screen_Resolution().Lower_Right();
  127. Vector2 screen_center = screen_size * 0.5f;
  128. Vector2 screen_scale = screen_size * 0.001f;
  129. // Set tint color
  130. int tint = 0xFF0000FF; // Blue
  131. tint = 0xFF00FF00; // Green
  132. // Draw the center view
  133. draw.Set( SNIPER_VIEW_UL, SNIPER_VIEW_LR );
  134. draw.Scale( screen_scale );
  135. _Sniper2DBaseRenderer->Add_Quad( draw, uv, tint );
  136. // Draw the black sides
  137. RectClass blackuv( BLACK_UV_UL, BLACK_UV_LR );
  138. blackuv.Scale( SNIPER_UV_SCALE );
  139. RectClass edge;
  140. edge.Set( 0, 0, draw.Left, screen_size.Y ); // Left
  141. _Sniper2DBaseRenderer->Add_Quad( edge, blackuv );
  142. edge.Set( draw.Right, 0, screen_size.X, screen_size.Y ); // Right
  143. _Sniper2DBaseRenderer->Add_Quad( edge, blackuv );
  144. edge.Set( draw.Left, 0, draw.Right, draw.Top ); // Top
  145. _Sniper2DBaseRenderer->Add_Quad( edge, blackuv );
  146. edge.Set( draw.Left, draw.Bottom, draw.Right, screen_size.Y ); // Bottom
  147. _Sniper2DBaseRenderer->Add_Quad( edge, blackuv );
  148. // Draw the center box
  149. Vector2 box_corner = BOX_SIZE;
  150. box_corner.Scale( screen_scale );
  151. RectClass box( -box_corner, box_corner );
  152. box += screen_center; // Center it
  153. _Sniper2DBaseRenderer->Add_Outline( box, 1, blackuv );
  154. // Draw the top line
  155. Vector2 top_line_1 = TOP_LINE_1;
  156. top_line_1.Scale( screen_scale );
  157. _Sniper2DBaseRenderer->Add_Line( Vector2(screen_center.X,0), Vector2(screen_center.X,top_line_1.Y), 1, blackuv );
  158. // Draw the top line 2
  159. Vector2 top_line_2 = TOP_LINE_2;
  160. top_line_2.Scale( screen_scale );
  161. _Sniper2DBaseRenderer->Add_Line( Vector2(screen_center.X,box.Top), Vector2(screen_center.X,top_line_2.Y), 1, blackuv );
  162. // Draw the top line 3
  163. Vector2 top_line_3 = TOP_LINE_3;
  164. top_line_3.Scale( screen_scale );
  165. _Sniper2DBaseRenderer->Add_Line( Vector2(screen_center.X,box.Top), Vector2(screen_center.X,top_line_3.Y), 3, blackuv );
  166. // Draw the bottom line
  167. Vector2 bottom_line_1 = BOTTOM_LINE_1;
  168. bottom_line_1.Scale( screen_scale.Y, screen_scale.Y );
  169. _Sniper2DBaseRenderer->Add_Line( Vector2(screen_center.X,bottom_line_1.X), Vector2(screen_center.X,bottom_line_1.Y), 1, blackuv );
  170. // Draw the bottom line 2
  171. Vector2 bottom_line_2 = BOTTOM_LINE_2;
  172. bottom_line_2.Scale( screen_scale );
  173. _Sniper2DBaseRenderer->Add_Line( Vector2(screen_center.X - bottom_line_2.X,bottom_line_2.Y), Vector2(screen_center.X + bottom_line_2.X,bottom_line_2.Y), 1, blackuv );
  174. // Draw the bottom line 3
  175. float y;
  176. float left = screen_center.X + 3;
  177. float right = BOTTOM_LINE_3.X * screen_scale.X;
  178. float step = BOTTOM_LINE_3.Y * screen_scale.Y;
  179. for ( y = bottom_line_2.Y; y < bottom_line_1.Y; y += step ) {
  180. _Sniper2DBaseRenderer->Add_Line( Vector2(left,y), Vector2(right,y), 1, blackuv );
  181. }
  182. // Draw the left lines
  183. left = LEFT_LINE_UL.X * screen_scale.X;
  184. right = LEFT_LINE_LR.X * screen_scale.X;
  185. for ( y = screen_center.Y; y < LEFT_LINE_UL.Y * screen_scale.Y; y += LEFT_LINE_LR.Y * screen_scale.Y ) {
  186. float flip = screen_size.Y - y;
  187. _Sniper2DBaseRenderer->Add_Line( Vector2( left, y ), Vector2( right,y ), 1, blackuv );
  188. _Sniper2DBaseRenderer->Add_Line( Vector2( left, flip ), Vector2( right, flip ), 1, blackuv );
  189. }
  190. // Draw the right line
  191. _Sniper2DBaseRenderer->Add_Line( Vector2(box.Right,screen_center.Y), Vector2(screen_size.X,screen_center.Y), 1, blackuv );
  192. // Draw the center line
  193. Vector2 center_line( -screen_scale.X, screen_scale.X );
  194. center_line *= CENTER_LINE_1.X;
  195. center_line += Vector2( screen_center.X, screen_center.X);
  196. _Sniper2DBaseRenderer->Add_Line( Vector2(center_line.X,screen_center.Y), Vector2(center_line.Y,screen_center.Y), 1, blackuv );
  197. // Draw the center line 2
  198. center_line = Vector2( screen_scale.X, screen_scale.X );
  199. center_line.Scale( CENTER_LINE_2 );
  200. center_line += Vector2( screen_center.X, screen_center.X);
  201. _Sniper2DBaseRenderer->Add_Line( Vector2(center_line.X,screen_center.Y), Vector2(center_line.Y,screen_center.Y), 3, blackuv );
  202. center_line -= Vector2( screen_center.X, screen_center.X);
  203. center_line *= -1;
  204. center_line += Vector2( screen_center.X, screen_center.X);
  205. _Sniper2DBaseRenderer->Add_Line( Vector2(center_line.X,screen_center.Y), Vector2(center_line.Y,screen_center.Y), 3, blackuv );
  206. // Draw the left line
  207. _Sniper2DBaseRenderer->Add_Line( Vector2(0, screen_center.Y), Vector2(LEFT_LINE_2.X*screen_scale.X,screen_center.Y), 1, blackuv );
  208. }
  209. /*
  210. **
  211. */
  212. void SniperHUDClass::Update( void )
  213. {
  214. // Info_Editor_Update();
  215. if ( _Sniper2DRenderer == NULL ) {
  216. return;
  217. }
  218. _Sniper2DRenderer->Reset();
  219. Vector2 screen_size = Render2DClass::Get_Screen_Resolution().Lower_Right();
  220. Vector2 screen_scale = screen_size * 0.001f;
  221. // Set tint color
  222. int tint = 0xFF0000FF; // Blue
  223. tint = 0xFF00FF00; // Green
  224. // Draw Zoom Indicator
  225. RectClass uv;
  226. uv.Set( ZOOM_UV_UL, ZOOM_UV_LR );
  227. RectClass draw = uv;
  228. uv.Scale( SNIPER_UV_SCALE );
  229. float zoom_ratio = COMBAT_CAMERA->Get_Sniper_Zoom();
  230. Vector2 pos = ((ZOOM_OFFSET_BOTTOM - ZOOM_OFFSET_TOP) * zoom_ratio) + ZOOM_OFFSET_TOP;
  231. pos.Scale( screen_scale );
  232. draw += pos - draw.Center();
  233. _Sniper2DRenderer->Add_Quad( draw, uv, tint );
  234. #if 0
  235. // Add Scanline
  236. static float _scan_line_offset = 0;
  237. RectClass scan_line = settings->SniperView;
  238. scan_line.Bottom = scan_line.Top + 0.005f;
  239. _scan_line_offset += TimeManager::Get_Frame_Seconds() * 0.1f;
  240. if ( _scan_line_offset > settings->SniperView.Height() + 0.05f ) {
  241. _scan_line_offset = -0.05f;
  242. }
  243. scan_line += Vector2( 0, _scan_line_offset );
  244. _Sniper2DRenderer->Add_Quad( scan_line, Scale_UV( settings->SniperScanLineUV, sniper_texture_size ) );
  245. // Add Distance Graph
  246. float dist = COMBAT_CAMERA->Get_Sniper_Distance();
  247. float dist_ratio = WWMath::Clamp( dist / settings->SniperDistanceGraphMax, 0, 1 );
  248. dist_ratio = WWMath::Sqrt( dist_ratio );
  249. RectClass dist_screen = settings->SniperDistanceGraph;
  250. RectClass dist_uv = Scale_UV( settings->SniperDistanceGraphUV, sniper_texture_size );
  251. dist_screen.Top = dist_screen.Bottom - dist_screen.Height() * dist_ratio;
  252. dist_uv.Top = dist_uv.Bottom - dist_uv.Height() * dist_ratio;
  253. _Sniper2DRenderer->Add_Quad( dist_screen, dist_uv );
  254. #endif
  255. }
  256. /*
  257. **
  258. */
  259. void SniperHUDClass::Render( void )
  260. {
  261. if ( _Sniper2DBaseRenderer ) {
  262. _Sniper2DBaseRenderer->Render();
  263. }
  264. if ( _Sniper2DRenderer ) {
  265. _Sniper2DRenderer->Render();
  266. }
  267. }
  268. #if 0
  269. /*
  270. ** Info Display
  271. */
  272. struct InfoEditorField {
  273. const char * Name;
  274. Vector2 * Value;
  275. bool operator == (InfoEditorField const & rec) const { return false; }
  276. bool operator != (InfoEditorField const & rec) const { return true; }
  277. };
  278. static DynamicVectorClass<InfoEditorField> InfoEditorFieldList;
  279. #define INFO_EDITOR_ADD(x) field.Name = #x; field.Value = &x; InfoEditorFieldList.Add( field );
  280. static void Info_Editor_Init( void )
  281. {
  282. InfoEditorField field;
  283. INFO_EDITOR_ADD( BLACK_UV_UL );
  284. INFO_EDITOR_ADD( BLACK_UV_LR );
  285. INFO_EDITOR_ADD( SNIPER_VIEW_UV_UL );
  286. INFO_EDITOR_ADD( SNIPER_VIEW_UV_LR );
  287. INFO_EDITOR_ADD( SNIPER_VIEW_UL );
  288. INFO_EDITOR_ADD( SNIPER_VIEW_LR );
  289. INFO_EDITOR_ADD( BOX_SIZE );
  290. INFO_EDITOR_ADD( TOP_LINE_1 );
  291. INFO_EDITOR_ADD( TOP_LINE_2 );
  292. INFO_EDITOR_ADD( TOP_LINE_3 );
  293. INFO_EDITOR_ADD( BOTTOM_LINE_1 );
  294. INFO_EDITOR_ADD( BOTTOM_LINE_2 );
  295. INFO_EDITOR_ADD( BOTTOM_LINE_3 );
  296. INFO_EDITOR_ADD( CENTER_LINE_1 );
  297. INFO_EDITOR_ADD( CENTER_LINE_2 );
  298. INFO_EDITOR_ADD( LEFT_LINE_UL );
  299. INFO_EDITOR_ADD( LEFT_LINE_LR );
  300. INFO_EDITOR_ADD( LEFT_LINE_2 );
  301. INFO_EDITOR_ADD( ZOOM_UV_UL );
  302. INFO_EDITOR_ADD( ZOOM_UV_LR );
  303. INFO_EDITOR_ADD( ZOOM_OFFSET_TOP );
  304. INFO_EDITOR_ADD( ZOOM_OFFSET_BOTTOM );
  305. }
  306. static void Info_Editor_Update( void )
  307. {
  308. bool changed = false;
  309. static int index = 0;
  310. static float _move = 0;
  311. float move = Input::Get_Amount( INPUT_FUNCTION_MOVE_LEFT ) - Input::Get_Amount( INPUT_FUNCTION_MOVE_RIGHT );
  312. if ( _move != move ) {
  313. _move = move;
  314. index += (int)-move;
  315. index = (int)WWMath::Wrap( index, (float)0, (float)(InfoEditorFieldList.Count()) );
  316. if ( move != 0 ) {
  317. changed = true;
  318. }
  319. }
  320. float _forward = 0;
  321. float forward = Input::Get_Amount( INPUT_FUNCTION_MOVE_FORWARD ) - Input::Get_Amount( INPUT_FUNCTION_MOVE_BACKWARD );
  322. forward *= 10;
  323. forward = WWMath::Clamp( forward, -1, 1 );
  324. if ( _forward != forward ) {
  325. _forward = forward;
  326. InfoEditorFieldList[index].Value->V += forward;
  327. if ( forward != 0 ) {
  328. changed = true;
  329. }
  330. }
  331. float _left = 0;
  332. float left = Input::Get_Amount( INPUT_FUNCTION_TURN_LEFT ) - Input::Get_Amount( INPUT_FUNCTION_TURN_RIGHT );
  333. left *= 10;
  334. left = WWMath::Clamp( left, -1, 1 );
  335. if ( _left != left ) {
  336. _left = left;
  337. InfoEditorFieldList[index].Value->U += left;
  338. if ( left != 0 ) {
  339. changed = true;
  340. }
  341. }
  342. if ( changed ) {
  343. Debug_Say(( "Vector2 %s( %d, %d );\n", InfoEditorFieldList[index].Name, (int)InfoEditorFieldList[index].Value->U, (int)InfoEditorFieldList[index].Value->V ));
  344. }
  345. }
  346. static void Info_Editor_Shutdown( void )
  347. {
  348. while ( InfoEditorFieldList.Count() > 0 ) {
  349. Debug_Say(( "Vector2 %s( %d, %d );\n", InfoEditorFieldList[0].Name, (int)InfoEditorFieldList[0].Value->U, (int)InfoEditorFieldList[0].Value->V ));
  350. InfoEditorFieldList.Delete(0);
  351. }
  352. }
  353. #endif