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