POWER.CPP 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  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: F:\projects\c&c\vcs\code\power.cpv 2.18 16 Oct 1995 16:52:10 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 : August 7, 1995 [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. * Power_Height -- Given a value figure where it falls on bar *
  39. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  40. #include "function.h"
  41. /*
  42. ** Points to the shape to use for the "desired" power level indicator.
  43. */
  44. void const * PowerClass::PowerShape;
  45. void const * PowerClass::PowerBarShape;
  46. PowerClass::PowerButtonClass PowerClass::PowerButton;
  47. /***********************************************************************************************
  48. * PowerClass::PowerClass -- Default constructor for the power bar class. *
  49. * *
  50. * This is the default constructor for the power bar class. It doesn't really do anything. *
  51. * *
  52. * INPUT: none *
  53. * *
  54. * OUTPUT: none *
  55. * *
  56. * WARNINGS: none *
  57. * *
  58. * HISTORY: *
  59. * 12/20/1994 JLB : Created. *
  60. *=============================================================================================*/
  61. PowerClass::PowerClass(void)
  62. {
  63. IsToRedraw = false;
  64. RecordedDrain = -1;
  65. RecordedPower = -1;
  66. DesiredDrainHeight = 0;
  67. DesiredPowerHeight = 0;
  68. DrainHeight = 0;
  69. PowerHeight = 0;
  70. PowerBounce = 0;
  71. DrainBounce = 0;
  72. DrainDir = 0;
  73. PowerDir = 0;
  74. }
  75. /***********************************************************************************************
  76. * PowerClass::Init_Clear -- Clears all the power bar variables. *
  77. * *
  78. * This routine is called in preparation for the start of a scenario. The power bar is *
  79. * initialized into the null state by this routine. As soon as the scenario starts, the *
  80. * power bar will rise to reflect the actual power output and drain. *
  81. * *
  82. * INPUT: none *
  83. * *
  84. * OUTPUT: none *
  85. * *
  86. * WARNINGS: none *
  87. * *
  88. * HISTORY: *
  89. * 08/07/1995 JLB : Created. *
  90. *=============================================================================================*/
  91. void PowerClass::Init_Clear(void)
  92. {
  93. RadarClass::Init_Clear();
  94. RecordedDrain = -1;
  95. RecordedPower = -1;
  96. DesiredDrainHeight = 0;
  97. DesiredPowerHeight = 0;
  98. DrainHeight = 0;
  99. PowerHeight = 0;
  100. PowerBounce = 0;
  101. DrainBounce = 0;
  102. DrainDir = 0;
  103. PowerDir = 0;
  104. }
  105. /***********************************************************************************************
  106. * PowerClass::One_Time -- One time processing for the power bar. *
  107. * *
  108. * This routine is for code that truly only needs to be done once per game run. *
  109. * *
  110. * INPUT: none *
  111. * *
  112. * OUTPUT: none *
  113. * *
  114. * WARNINGS: none *
  115. * *
  116. * HISTORY: *
  117. * 12/26/1994 JLB : Created. *
  118. *=============================================================================================*/
  119. void PowerClass::One_Time(void)
  120. {
  121. RadarClass::One_Time();
  122. int factor = Get_Resolution_Factor();
  123. PowX = SeenBuff.Get_Width() - Map.RadWidth;
  124. PowY = Map.RadY+Map.RadHeight + (13 << factor);
  125. PowWidth = 8 << factor;
  126. PowHeight = SeenBuff.Get_Height() - PowY;
  127. PowLineSpace = 5 << factor;
  128. PowLineWidth = PowWidth - 4;
  129. PowerButton.X = PowX;
  130. PowerButton.Y = PowY;
  131. PowerButton.Width = PowWidth-1;
  132. PowerButton.Height = PowHeight;
  133. PowerShape = MixFileClass::Retrieve((factor)? "HPOWER.SHP" :"POWER.SHP");
  134. PowerBarShape = Hires_Retrieve("PWRBAR.SHP");
  135. }
  136. /***********************************************************************************************
  137. * PowerClass::Draw_It -- Renders the power bar graphic. *
  138. * *
  139. * This routine will draw the power bar graphic to the LogicPage. *
  140. * *
  141. * INPUT: complete -- Should the power bar be redrawn even if it isn't specifically flagged *
  142. * to do so? *
  143. * *
  144. * OUTPUT: none *
  145. * *
  146. * WARNINGS: none *
  147. * *
  148. * HISTORY: *
  149. * 12/20/1994 JLB : Created. *
  150. * 12/27/1994 JLB : Changes power bar color depending on amount of power. *
  151. *=============================================================================================*/
  152. void PowerClass::Draw_It(bool complete)
  153. {
  154. static int _modtable[]={
  155. 0, -1, 0, 1, 0, -1, -2, -1, 0, 1, 2, 1 ,0
  156. };
  157. int power_color;
  158. if (complete || IsToRedraw) {
  159. // PowX = TacPixelX + TacWidth*ICON_PIXEL_W; // X position of upper left corner of power bar.
  160. if (LogicPage->Lock()){
  161. if (Map.IsSidebarActive) {
  162. IsToRedraw = false;
  163. /*
  164. ** 1st get the height of the filled section of the power bar
  165. */
  166. int bottom = PowY + PowHeight - 1;
  167. int power_height = (PowerHeight == DesiredPowerHeight) ? PowerHeight + (_modtable[PowerBounce] * PowerDir) : PowerHeight;
  168. int drain_height = (DrainHeight == DesiredDrainHeight) ? DrainHeight + (_modtable[DrainBounce] * DrainDir) : DrainHeight;
  169. power_height = Bound(power_height, 0, PowHeight - 2);
  170. drain_height = Bound(drain_height, 0, PowHeight - 2);
  171. /*
  172. ** Create a clip region to draw the unfilled section of the bar
  173. */
  174. WindowList[WINDOW_CUSTOM][WINDOWX] = 0;
  175. WindowList[WINDOW_CUSTOM][WINDOWY] = 0;
  176. WindowList[WINDOW_CUSTOM][WINDOWWIDTH] = SeenBuff.Get_Width();
  177. WindowList[WINDOW_CUSTOM][WINDOWHEIGHT] = bottom-power_height;
  178. /*
  179. ** Draw the unfilled section
  180. */
  181. CC_Draw_Shape(PowerBarShape, 0, PowX, PowY, WINDOW_CUSTOM, SHAPE_WIN_REL);
  182. CC_Draw_Shape(PowerBarShape, 1 ,PowX, PowY+100, WINDOW_CUSTOM, SHAPE_WIN_REL);
  183. /*
  184. ** Set up the clip region for the filled section
  185. */
  186. WindowList[WINDOW_CUSTOM][WINDOWY] = bottom-power_height;
  187. WindowList[WINDOW_CUSTOM][WINDOWHEIGHT] = SeenBuff.Get_Height() - WindowList[WINDOW_CUSTOM][WINDOWY];
  188. /*
  189. ** What color is the filled section?
  190. */
  191. if (power_height) {
  192. power_color = 0; //green
  193. if (PlayerPtr->Drain > PlayerPtr->Power) {
  194. power_color = 2;
  195. }
  196. if (PlayerPtr->Drain > (PlayerPtr->Power * 2)) {
  197. power_color = 4;
  198. }
  199. /*
  200. ** Draw the filled section
  201. */
  202. CC_Draw_Shape(PowerBarShape, 2+power_color,
  203. PowX,
  204. PowY - WindowList[WINDOW_CUSTOM][WINDOWY],
  205. WINDOW_CUSTOM,
  206. SHAPE_WIN_REL);
  207. CC_Draw_Shape(PowerBarShape, 3+power_color,
  208. PowX,
  209. PowY - WindowList[WINDOW_CUSTOM][WINDOWY] + 100,
  210. WINDOW_CUSTOM,
  211. SHAPE_WIN_REL);
  212. }
  213. /*
  214. ** Draw the power drain threshold marker.
  215. */
  216. CC_Draw_Shape(PowerShape, 0, PowX, bottom - drain_height + 1, WINDOW_MAIN, SHAPE_NORMAL);
  217. }
  218. LogicPage->Unlock();
  219. }
  220. }
  221. RadarClass::Draw_It(complete);
  222. }
  223. /***********************************************************************************************
  224. * PowerClass::AI -- Process the power bar logic. *
  225. * *
  226. * Use this routine to process the power bar logic. This consists of animation effects. *
  227. * *
  228. * INPUT: input -- The player input value to be consumed or ignored as appropriate. *
  229. * *
  230. * x,y -- Mouse coordinate parameters to use. *
  231. * *
  232. * OUTPUT: none *
  233. * *
  234. * WARNINGS: none *
  235. * *
  236. * HISTORY: *
  237. * 12/20/1994 JLB : Created. *
  238. * 12/31/1994 JLB : Uses mouse coordinate parameters. *
  239. *=============================================================================================*/
  240. void PowerClass::AI(KeyNumType &input, int x, int y)
  241. {
  242. // if (!IsActive) {
  243. // IsActive = true;
  244. // IsToRedraw = true;
  245. // Flag_To_Redraw(false);
  246. // }
  247. if (Map.IsSidebarActive /*IsActive*/) {
  248. int olddrain = DrainHeight;
  249. int oldpower = PowerHeight;
  250. /*
  251. ** If the recorded power value has changed we need to adjust for
  252. ** it.
  253. */
  254. if (PlayerPtr->Power != RecordedPower) {
  255. DesiredPowerHeight = Power_Height(PlayerPtr->Power);
  256. RecordedPower = PlayerPtr->Power;
  257. PowerBounce = 12;
  258. if (PowerHeight > DesiredPowerHeight) {
  259. PowerDir = -1;
  260. } else if (PowerHeight < DesiredPowerHeight) {
  261. PowerDir = 1;
  262. } else {
  263. PowerBounce = 0;
  264. }
  265. }
  266. /*
  267. ** If the recorded drain value has changed we need to adjust for
  268. ** it.
  269. */
  270. if (PlayerPtr->Drain != RecordedDrain) {
  271. DesiredDrainHeight = Power_Height(PlayerPtr->Drain);
  272. RecordedDrain = PlayerPtr->Drain;
  273. DrainBounce = 12;
  274. if (DrainHeight > DesiredDrainHeight) {
  275. DrainDir = -1;
  276. } else if (DrainHeight < DesiredDrainHeight) {
  277. DrainDir = 1;
  278. } else {
  279. DrainBounce = 0;
  280. }
  281. }
  282. if (DrainBounce && DrainHeight == DesiredDrainHeight) {
  283. IsToRedraw = true;
  284. Flag_To_Redraw(false);
  285. DrainBounce--;
  286. } else {
  287. /*
  288. ** If we need to move the drain height then do so.
  289. */
  290. if (DrainHeight != DesiredDrainHeight) {
  291. DrainHeight += DrainDir;
  292. }
  293. }
  294. if (PowerBounce && PowerHeight == DesiredPowerHeight) {
  295. IsToRedraw = true;
  296. Flag_To_Redraw(false);
  297. PowerBounce--;
  298. } else {
  299. /*
  300. ** If we need to move the power height then do so.
  301. */
  302. if (PowerHeight != DesiredPowerHeight) {
  303. PowerHeight += PowerDir;
  304. }
  305. }
  306. if (olddrain != DrainHeight || oldpower != PowerHeight) {
  307. IsToRedraw = true;
  308. Flag_To_Redraw(false);
  309. }
  310. }
  311. RadarClass::AI(input, x, y);
  312. }
  313. /***********************************************************************************************
  314. * PowerClass::Refresh_Cells -- Intercepts the redraw logic to see if sidebar to redraw too. *
  315. * *
  316. * This routine will examine a refresh list request and determine if the sidebar would be *
  317. * affect. If so, it will flag the sidebar to be redrawn. *
  318. * *
  319. * INPUT: cell -- The cell that the offset list is base on. *
  320. * *
  321. * list -- The list of cell offset used to flag for redraw. If the special sidebar *
  322. * affecting cell magic offset number is detected, the sidebar is flagged *
  323. * for redraw and the magic offset is removed. *
  324. * *
  325. * OUTPUT: none *
  326. * *
  327. * WARNINGS: none *
  328. * *
  329. * HISTORY: *
  330. * 06/01/1995 JLB : Created. *
  331. *=============================================================================================*/
  332. void PowerClass::Refresh_Cells(CELL cell, short const *list)
  333. {
  334. if (*list == REFRESH_SIDEBAR) {
  335. IsToRedraw = true;
  336. Flag_To_Redraw(false);
  337. }
  338. RadarClass::Refresh_Cells(cell, list);
  339. }
  340. /***************************************************************************
  341. * PowHeight -- Given a value figure where it falls on bar *
  342. * *
  343. * INPUT: int value - the value we are testing *
  344. * *
  345. * OUTPUT: int the height of the point that this value is on graph *
  346. * *
  347. * WARNINGS: none *
  348. * *
  349. * HISTORY: *
  350. * 06/14/1995 PWG : Created. *
  351. *=========================================================================*/
  352. int PowerClass::Power_Height(int value)
  353. {
  354. int num = value/ POWER_STEP_LEVEL; // figure out the initial num of DRAIN_VALUE's
  355. int retval = 0; // currently there is no power
  356. /*
  357. ** Loop through the diffrent hundreds figuring out the fractional piece
  358. ** of each.
  359. */
  360. for (int lp = 0; lp < num; lp ++) {
  361. retval = retval + (((PowHeight - 2) - retval) / POWER_STEP_FACTOR);
  362. value -= POWER_STEP_LEVEL;
  363. }
  364. /*
  365. ** Adjust the retval to factor in the remainder
  366. */
  367. if (value) {
  368. retval = retval + (((((PowHeight - 2) - retval) / POWER_STEP_FACTOR) * value) / POWER_STEP_LEVEL);
  369. }
  370. retval = Bound(retval, 0, PowHeight -2);
  371. return(retval);
  372. }
  373. /***********************************************************************************************
  374. * PowerClass::PowerButtonClass::Action -- Handles the mouse over the power bar area. *
  375. * *
  376. * This routine handles input on the power bar area. Since no input is used for the power *
  377. * bar, this routine just pops up appropriate help text for the power bar. *
  378. * *
  379. * INPUT: flags -- The event flags that triggered this action call. *
  380. * *
  381. * key -- The key code (if any) associated with the trigger event. *
  382. * *
  383. * OUTPUT: Should further button processing be stopped? *
  384. * *
  385. * WARNINGS: none *
  386. * *
  387. * HISTORY: *
  388. * 08/07/1995 JLB : Created. *
  389. *=============================================================================================*/
  390. int PowerClass::PowerButtonClass::Action(unsigned flags, KeyNumType & key)
  391. {
  392. if (!Map.IsSidebarActive) {
  393. return(false);
  394. }
  395. /*
  396. ** Force any help label to disappear when the mouse is held over the
  397. ** radar map.
  398. */
  399. Map.Override_Mouse_Shape(MOUSE_NORMAL);
  400. if (PlayerPtr->Power_Fraction() < 0x0100 && PlayerPtr->Power > 0) {
  401. Map.Help_Text(TXT_POWER_OUTPUT_LOW, -1, -1, CC_GREEN);
  402. } else {
  403. Map.Help_Text(TXT_POWER_OUTPUT, -1, -1, CC_GREEN);
  404. }
  405. GadgetClass::Action(flags, key);
  406. return(true);
  407. }