POWER.CPP 23 KB

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