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