POWER.CPP 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: /CounterStrike/POWER.CPP 1 3/03/97 10:25a Joe_bostic $ */
  15. /***********************************************************************************************
  16. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  17. ***********************************************************************************************
  18. * *
  19. * Project Name : Command & Conquer *
  20. * *
  21. * File Name : POWER.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : 12/15/94 *
  26. * *
  27. * Last Update : October 14, 1996 [JLB] *
  28. * *
  29. *---------------------------------------------------------------------------------------------*
  30. * Functions: *
  31. * PowerClass::AI -- Process the power bar logic. *
  32. * PowerClass::Draw_It -- Renders the power bar graphic. *
  33. * PowerClass::Init_Clear -- Clears all the power bar variables. *
  34. * PowerClass::One_Time -- One time processing for the power bar. *
  35. * PowerClass::PowerButtonClass::Action -- Handles the mouse over the power bar area. *
  36. * PowerClass::PowerClass -- Default constructor for the power bar class. *
  37. * PowerClass::Refresh_Cells -- Intercepts the redraw logic to see if sidebar to redraw too. *
  38. * PowerClass::Power_Height -- Given a value figure where it falls on bar *
  39. * PowerClass::Flash_Power -- Flag the power bar to flash. *
  40. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  41. #include "function.h"
  42. /*
  43. ** Points to the shape to use for the "desired" power level indicator.
  44. */
  45. void const * PowerClass::PowerShape;
  46. void const * PowerClass::PowerBarShape;
  47. PowerClass::PowerButtonClass PowerClass::PowerButton;
  48. /***********************************************************************************************
  49. * PowerClass::PowerClass -- Default constructor for the power bar class. *
  50. * *
  51. * This is the default constructor for the power bar class. It doesn't really do anything. *
  52. * *
  53. * INPUT: none *
  54. * *
  55. * OUTPUT: none *
  56. * *
  57. * WARNINGS: none *
  58. * *
  59. * HISTORY: *
  60. * 12/20/1994 JLB : Created. *
  61. *=============================================================================================*/
  62. PowerClass::PowerClass(void) :
  63. IsToRedraw(false),
  64. IsActive(false),
  65. FlashTimer(0),
  66. RecordedDrain(-1),
  67. RecordedPower(-1),
  68. DesiredDrainHeight(0),
  69. DesiredPowerHeight(0),
  70. DrainHeight(0),
  71. PowerHeight(0),
  72. DrainBounce(0),
  73. PowerBounce(0),
  74. PowerDir(0),
  75. DrainDir(0)
  76. {
  77. }
  78. /***********************************************************************************************
  79. * PowerClass::Init_Clear -- Clears all the power bar variables. *
  80. * *
  81. * This routine is called in preparation for the start of a scenario. The power bar is *
  82. * initialized into the null state by this routine. As soon as the scenario starts, the *
  83. * power bar will rise to reflect the actual power output and drain. *
  84. * *
  85. * INPUT: none *
  86. * *
  87. * OUTPUT: none *
  88. * *
  89. * WARNINGS: none *
  90. * *
  91. * HISTORY: *
  92. * 08/07/1995 JLB : Created. *
  93. *=============================================================================================*/
  94. void PowerClass::Init_Clear(void)
  95. {
  96. RadarClass::Init_Clear();
  97. RecordedDrain = -1;
  98. RecordedPower = -1;
  99. DesiredDrainHeight = 0;
  100. DesiredPowerHeight = 0;
  101. DrainHeight = 0;
  102. PowerHeight = 0;
  103. PowerBounce = 0;
  104. DrainBounce = 0;
  105. DrainDir = 0;
  106. PowerDir = 0;
  107. FlashTimer = 0;
  108. }
  109. /***********************************************************************************************
  110. * PowerClass::One_Time -- One time processing for the power bar. *
  111. * *
  112. * This routine is for code that truly only needs to be done once per game run. *
  113. * *
  114. * INPUT: none *
  115. * *
  116. * OUTPUT: none *
  117. * *
  118. * WARNINGS: none *
  119. * *
  120. * HISTORY: *
  121. * 12/26/1994 JLB : Created. *
  122. *=============================================================================================*/
  123. void PowerClass::One_Time(void)
  124. {
  125. RadarClass::One_Time();
  126. PowerButton.X = POWER_X * RESFACTOR;
  127. PowerButton.Y = POWER_Y * RESFACTOR;
  128. PowerButton.Width = (POWER_WIDTH * RESFACTOR)-1;
  129. PowerButton.Height = POWER_HEIGHT * RESFACTOR;
  130. PowerShape = MFCD::Retrieve("POWER.SHP");
  131. PowerBarShape = MFCD::Retrieve("POWERBAR.SHP");
  132. }
  133. /***********************************************************************************************
  134. * PowerClass::Draw_It -- Renders the power bar graphic. *
  135. * *
  136. * This routine will draw the power bar graphic to the LogicPage. *
  137. * *
  138. * INPUT: complete -- Should the power bar be redrawn even if it isn't specifically flagged *
  139. * to do so? *
  140. * *
  141. * OUTPUT: none *
  142. * *
  143. * WARNINGS: none *
  144. * *
  145. * HISTORY: *
  146. * 12/20/1994 JLB : Created. *
  147. * 12/27/1994 JLB : Changes power bar color depending on amount of power. *
  148. *=============================================================================================*/
  149. void PowerClass::Draw_It(bool complete)
  150. {
  151. static int _modtable[]={
  152. 0, -1, 0, 1, 0, -1, -2, -1, 0, 1, 2, 1 ,0
  153. };
  154. if (complete || IsToRedraw) {
  155. BStart(BENCH_POWER);
  156. if (LogicPage->Lock()) {
  157. if (Map.IsSidebarActive) {
  158. IsToRedraw = false;
  159. ShapeFlags_Type flags = SHAPE_NORMAL;
  160. void const * remap = NULL;
  161. if (FlashTimer > 1 && ((FlashTimer % 3) & 0x01) != 0) {
  162. flags = flags | SHAPE_FADING;
  163. remap = Map.FadingRed;
  164. }
  165. // LogicPage->Fill_Rect(POWER_X, POWER_Y, POWER_X+POWER_WIDTH-1, POWER_Y+POWER_HEIGHT-1, LTGREY);
  166. CC_Draw_Shape(PowerBarShape, 0, 240 * RESFACTOR, 88 * RESFACTOR, WINDOW_MAIN, flags | SHAPE_NORMAL | SHAPE_WIN_REL, remap);
  167. #ifdef WIN32
  168. /*
  169. ** Hires power strip is too big to fit into a shape so it is in two parts
  170. */
  171. CC_Draw_Shape(PowerBarShape, 1, 240 * RESFACTOR, (88 * RESFACTOR) + (56*RESFACTOR), WINDOW_MAIN, flags | SHAPE_NORMAL | SHAPE_WIN_REL, remap);
  172. #endif
  173. /*
  174. ** Determine how much the power production exceeds or falls short
  175. ** of power demands.
  176. */
  177. int bottom = (POWER_Y + POWER_HEIGHT - 1) * RESFACTOR;
  178. int power_height = (PowerHeight == DesiredPowerHeight) ? PowerHeight + (_modtable[PowerBounce] * PowerDir) : PowerHeight;
  179. int drain_height = (DrainHeight == DesiredDrainHeight) ? DrainHeight + (_modtable[DrainBounce] * DrainDir) : DrainHeight;
  180. power_height = Bound(power_height, 0, POWER_HEIGHT - 2);
  181. drain_height = Bound(drain_height, 0, POWER_HEIGHT - 2);
  182. /*
  183. ** Draw the power output graphic on top of the power bar framework.
  184. */
  185. if (power_height) {
  186. int color1 = 3;
  187. int color2 = 4;
  188. if (PlayerPtr->Drain > PlayerPtr->Power) {
  189. color1 = 214;
  190. color2 = 211;
  191. }
  192. if (PlayerPtr->Drain > (PlayerPtr->Power * 2)) {
  193. color1 = 235;
  194. color2 = 230;
  195. }
  196. /*
  197. ** New power bar is in slightly different place
  198. **
  199. ** Old power bar was 107 pixels high. New bar is 153 pixels high.
  200. **
  201. ** ST - 5/2/96 11:23AM
  202. */
  203. #ifdef WIN32
  204. power_height = (power_height*(76*RESFACTOR+1)) / (53*RESFACTOR+1);
  205. drain_height = (drain_height*(76*RESFACTOR+1)) / (53*RESFACTOR+1);
  206. #endif
  207. bottom = (175*RESFACTOR)+1;
  208. LogicPage->Fill_Rect(245*RESFACTOR, bottom-power_height, 245*RESFACTOR+1, bottom, color2);
  209. LogicPage->Fill_Rect(246*RESFACTOR, bottom-power_height, 246*RESFACTOR+1, bottom, color1);
  210. }
  211. /*
  212. ** Draw the power drain threshold marker.
  213. */
  214. CC_Draw_Shape(PowerShape, 0, (POWER_X * RESFACTOR)+RESFACTOR, bottom - (drain_height + (2 * RESFACTOR)), WINDOW_MAIN, flags | SHAPE_NORMAL, remap);
  215. }
  216. LogicPage->Unlock();
  217. }
  218. BEnd(BENCH_POWER);
  219. }
  220. RadarClass::Draw_It(complete);
  221. }
  222. /***********************************************************************************************
  223. * PowerClass::AI -- Process the power bar logic. *
  224. * *
  225. * Use this routine to process the power bar logic. This consists of animation effects. *
  226. * *
  227. * INPUT: input -- The player input value to be consumed or ignored as appropriate. *
  228. * *
  229. * x,y -- Mouse coordinate parameters to use. *
  230. * *
  231. * OUTPUT: none *
  232. * *
  233. * WARNINGS: none *
  234. * *
  235. * HISTORY: *
  236. * 12/20/1994 JLB : Created. *
  237. * 12/31/1994 JLB : Uses mouse coordinate parameters. *
  238. *=============================================================================================*/
  239. void PowerClass::AI(KeyNumType &input, int x, int y)
  240. {
  241. if (Map.IsSidebarActive /*IsActive*/) {
  242. int olddrain = DrainHeight;
  243. int oldpower = PowerHeight;
  244. /*
  245. ** If the recorded power value has changed we need to adjust for
  246. ** it.
  247. */
  248. if (PlayerPtr->Power != RecordedPower) {
  249. DesiredPowerHeight = Power_Height(PlayerPtr->Power);
  250. RecordedPower = PlayerPtr->Power;
  251. PowerBounce = 12;
  252. if (PowerHeight > DesiredPowerHeight) {
  253. PowerDir = -1;
  254. } else if (PowerHeight < DesiredPowerHeight) {
  255. PowerDir = 1;
  256. } else {
  257. PowerBounce = 0;
  258. }
  259. }
  260. /*
  261. ** If the recorded drain value has changed we need to adjust for
  262. ** it.
  263. */
  264. if (PlayerPtr->Drain != RecordedDrain) {
  265. DesiredDrainHeight = Power_Height(PlayerPtr->Drain);
  266. RecordedDrain = PlayerPtr->Drain;
  267. DrainBounce = 12;
  268. if (DrainHeight > DesiredDrainHeight) {
  269. DrainDir = -1;
  270. } else if (DrainHeight < DesiredDrainHeight) {
  271. DrainDir = 1;
  272. } else {
  273. DrainBounce = 0;
  274. }
  275. }
  276. if (DrainBounce && DrainHeight == DesiredDrainHeight) {
  277. IsToRedraw = true;
  278. Flag_To_Redraw(false);
  279. DrainBounce--;
  280. } else {
  281. /*
  282. ** If we need to move the drain height then do so.
  283. */
  284. if (DrainHeight != DesiredDrainHeight) {
  285. DrainHeight += DrainDir;
  286. }
  287. }
  288. if (PowerBounce && PowerHeight == DesiredPowerHeight) {
  289. IsToRedraw = true;
  290. Flag_To_Redraw(false);
  291. PowerBounce--;
  292. } else {
  293. /*
  294. ** If we need to move the power height then do so.
  295. */
  296. if (PowerHeight != DesiredPowerHeight) {
  297. PowerHeight += PowerDir;
  298. }
  299. }
  300. if (olddrain != DrainHeight || oldpower != PowerHeight) {
  301. IsToRedraw = true;
  302. Flag_To_Redraw(false);
  303. }
  304. /*
  305. ** Flag to redraw if the power bar flash effect has expired.
  306. */
  307. // if (FlashTimer == 1) {
  308. if (FlashTimer > 0) {
  309. IsToRedraw = true;
  310. Flag_To_Redraw(false);
  311. }
  312. }
  313. RadarClass::AI(input, x, y);
  314. }
  315. /***********************************************************************************************
  316. * PowerClass::Refresh_Cells -- Intercepts the redraw logic to see if sidebar to redraw too. *
  317. * *
  318. * This routine will examine a refresh list request and determine if the sidebar would be *
  319. * affect. If so, it will flag the sidebar to be redrawn. *
  320. * *
  321. * INPUT: cell -- The cell that the offset list is base on. *
  322. * *
  323. * list -- The list of cell offset used to flag for redraw. If the special sidebar *
  324. * affecting cell magic offset number is detected, the sidebar is flagged *
  325. * for redraw and the magic offset is removed. *
  326. * *
  327. * OUTPUT: none *
  328. * *
  329. * WARNINGS: none *
  330. * *
  331. * HISTORY: *
  332. * 06/01/1995 JLB : Created. *
  333. *=============================================================================================*/
  334. void PowerClass::Refresh_Cells(CELL cell, short const * list)
  335. {
  336. if (*list == REFRESH_SIDEBAR) {
  337. IsToRedraw = true;
  338. Flag_To_Redraw(false);
  339. }
  340. RadarClass::Refresh_Cells(cell, list);
  341. }
  342. /***************************************************************************
  343. * PowerClass::Power_Height -- Given a value figure where it falls on bar *
  344. * *
  345. * INPUT: int value - the value we are testing *
  346. * *
  347. * OUTPUT: int the height of the point that this value is on graph *
  348. * *
  349. * WARNINGS: none *
  350. * *
  351. * HISTORY: *
  352. * 06/14/1995 PWG : Created. *
  353. *=========================================================================*/
  354. int PowerClass::Power_Height(int value)
  355. {
  356. int num = value/ POWER_STEP_LEVEL; // figure out the initial num of DRAIN_VALUE's
  357. int retval = 0; // currently there is no power
  358. /*
  359. ** Loop through the different hundreds figuring out the fractional piece
  360. ** of each.
  361. */
  362. for (int lp = 0; lp < num; lp ++) {
  363. retval = retval + (((POWER_HEIGHT - 2) - retval) / POWER_STEP_FACTOR);
  364. value -= POWER_STEP_LEVEL;
  365. }
  366. /*
  367. ** Adjust the retval to factor in the remainder
  368. */
  369. if (value) {
  370. retval = retval + (((((POWER_HEIGHT - 2) - retval) / POWER_STEP_FACTOR) * value) / POWER_STEP_LEVEL);
  371. }
  372. retval = Bound(retval, 0, POWER_HEIGHT-2);
  373. return(retval);
  374. }
  375. /***********************************************************************************************
  376. * PowerClass::PowerButtonClass::Action -- Handles the mouse over the power bar area. *
  377. * *
  378. * This routine handles input on the power bar area. Since no input is used for the power *
  379. * bar, this routine just pops up appropriate help text for the power bar. *
  380. * *
  381. * INPUT: flags -- The event flags that triggered this action call. *
  382. * *
  383. * key -- The key code (if any) associated with the trigger event. *
  384. * *
  385. * OUTPUT: Should further button processing be stopped? *
  386. * *
  387. * WARNINGS: none *
  388. * *
  389. * HISTORY: *
  390. * 08/07/1995 JLB : Created. *
  391. *=============================================================================================*/
  392. int PowerClass::PowerButtonClass::Action(unsigned flags, KeyNumType & key)
  393. {
  394. if (!Map.IsSidebarActive) {
  395. return(false);
  396. }
  397. /*
  398. ** Force any help label to disappear when the mouse is held over the
  399. ** radar map.
  400. */
  401. Map.Override_Mouse_Shape(MOUSE_NORMAL);
  402. if (PlayerPtr->Power_Fraction() < 1 && PlayerPtr->Power > 0) {
  403. Map.Help_Text(TXT_POWER_OUTPUT_LOW, -1, -1, GadgetClass::Get_Color_Scheme()->Color);
  404. } else {
  405. Map.Help_Text(TXT_POWER_OUTPUT, -1, -1, GadgetClass::Get_Color_Scheme()->Color);
  406. }
  407. GadgetClass::Action(flags, key);
  408. return(true);
  409. }
  410. /***********************************************************************************************
  411. * PowerClass::Flash_Power -- Flag the power bar to flash. *
  412. * *
  413. * This will cause the power bar to display with a flash so as to draw attention to *
  414. * itself. Typical use of this effect is when power is low. *
  415. * *
  416. * INPUT: none *
  417. * *
  418. * OUTPUT: none *
  419. * *
  420. * WARNINGS: none *
  421. * *
  422. * HISTORY: *
  423. * 10/14/1996 JLB : Created. *
  424. *=============================================================================================*/
  425. void PowerClass::Flash_Power(void)
  426. {
  427. FlashTimer = TICKS_PER_SECOND;
  428. IsToRedraw = true;
  429. Flag_To_Redraw(false);
  430. }