// // Copyright 2020 Electronic Arts Inc. // // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free // software: you can redistribute it and/or modify it under the terms of // the GNU General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed // in the hope that it will be useful, but with permitted additional restrictions // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT // distributed with this program. You should have received a copy of the // GNU General Public License along with permitted additional restrictions // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection /* $Header: /CounterStrike/POWER.CPP 1 3/03/97 10:25a Joe_bostic $ */ /*********************************************************************************************** *** 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 *** *********************************************************************************************** * * * Project Name : Command & Conquer * * * * File Name : POWER.CPP * * * * Programmer : Joe L. Bostic * * * * Start Date : 12/15/94 * * * * Last Update : October 14, 1996 [JLB] * * * *---------------------------------------------------------------------------------------------* * Functions: * * PowerClass::AI -- Process the power bar logic. * * PowerClass::Draw_It -- Renders the power bar graphic. * * PowerClass::Init_Clear -- Clears all the power bar variables. * * PowerClass::One_Time -- One time processing for the power bar. * * PowerClass::PowerButtonClass::Action -- Handles the mouse over the power bar area. * * PowerClass::PowerClass -- Default constructor for the power bar class. * * PowerClass::Refresh_Cells -- Intercepts the redraw logic to see if sidebar to redraw too. * * PowerClass::Power_Height -- Given a value figure where it falls on bar * * PowerClass::Flash_Power -- Flag the power bar to flash. * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "function.h" /* ** Points to the shape to use for the "desired" power level indicator. */ void const * PowerClass::PowerShape; void const * PowerClass::PowerBarShape; PowerClass::PowerButtonClass PowerClass::PowerButton; /*********************************************************************************************** * PowerClass::PowerClass -- Default constructor for the power bar class. * * * * This is the default constructor for the power bar class. It doesn't really do anything. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 12/20/1994 JLB : Created. * *=============================================================================================*/ PowerClass::PowerClass(void) : IsToRedraw(false), IsActive(false), FlashTimer(0), RecordedDrain(-1), RecordedPower(-1), DesiredDrainHeight(0), DesiredPowerHeight(0), DrainHeight(0), PowerHeight(0), DrainBounce(0), PowerBounce(0), PowerDir(0), DrainDir(0) { } /*********************************************************************************************** * PowerClass::Init_Clear -- Clears all the power bar variables. * * * * This routine is called in preparation for the start of a scenario. The power bar is * * initialized into the null state by this routine. As soon as the scenario starts, the * * power bar will rise to reflect the actual power output and drain. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 08/07/1995 JLB : Created. * *=============================================================================================*/ void PowerClass::Init_Clear(void) { RadarClass::Init_Clear(); RecordedDrain = -1; RecordedPower = -1; DesiredDrainHeight = 0; DesiredPowerHeight = 0; DrainHeight = 0; PowerHeight = 0; PowerBounce = 0; DrainBounce = 0; DrainDir = 0; PowerDir = 0; FlashTimer = 0; } /*********************************************************************************************** * PowerClass::One_Time -- One time processing for the power bar. * * * * This routine is for code that truly only needs to be done once per game run. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 12/26/1994 JLB : Created. * *=============================================================================================*/ void PowerClass::One_Time(void) { RadarClass::One_Time(); PowerButton.X = POWER_X * RESFACTOR; PowerButton.Y = POWER_Y * RESFACTOR; PowerButton.Width = (POWER_WIDTH * RESFACTOR)-1; PowerButton.Height = POWER_HEIGHT * RESFACTOR; PowerShape = MFCD::Retrieve("POWER.SHP"); PowerBarShape = MFCD::Retrieve("POWERBAR.SHP"); } /*********************************************************************************************** * PowerClass::Draw_It -- Renders the power bar graphic. * * * * This routine will draw the power bar graphic to the LogicPage. * * * * INPUT: complete -- Should the power bar be redrawn even if it isn't specifically flagged * * to do so? * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 12/20/1994 JLB : Created. * * 12/27/1994 JLB : Changes power bar color depending on amount of power. * *=============================================================================================*/ void PowerClass::Draw_It(bool complete) { static int _modtable[]={ 0, -1, 0, 1, 0, -1, -2, -1, 0, 1, 2, 1 ,0 }; if (complete || IsToRedraw) { BStart(BENCH_POWER); if (LogicPage->Lock()) { if (Map.IsSidebarActive) { IsToRedraw = false; ShapeFlags_Type flags = SHAPE_NORMAL; void const * remap = NULL; if (FlashTimer > 1 && ((FlashTimer % 3) & 0x01) != 0) { flags = flags | SHAPE_FADING; remap = Map.FadingRed; } // LogicPage->Fill_Rect(POWER_X, POWER_Y, POWER_X+POWER_WIDTH-1, POWER_Y+POWER_HEIGHT-1, LTGREY); CC_Draw_Shape(PowerBarShape, 0, 240 * RESFACTOR, 88 * RESFACTOR, WINDOW_MAIN, flags | SHAPE_NORMAL | SHAPE_WIN_REL, remap); #ifdef WIN32 /* ** Hires power strip is too big to fit into a shape so it is in two parts */ CC_Draw_Shape(PowerBarShape, 1, 240 * RESFACTOR, (88 * RESFACTOR) + (56*RESFACTOR), WINDOW_MAIN, flags | SHAPE_NORMAL | SHAPE_WIN_REL, remap); #endif /* ** Determine how much the power production exceeds or falls short ** of power demands. */ int bottom = (POWER_Y + POWER_HEIGHT - 1) * RESFACTOR; int power_height = (PowerHeight == DesiredPowerHeight) ? PowerHeight + (_modtable[PowerBounce] * PowerDir) : PowerHeight; int drain_height = (DrainHeight == DesiredDrainHeight) ? DrainHeight + (_modtable[DrainBounce] * DrainDir) : DrainHeight; power_height = Bound(power_height, 0, POWER_HEIGHT - 2); drain_height = Bound(drain_height, 0, POWER_HEIGHT - 2); /* ** Draw the power output graphic on top of the power bar framework. */ if (power_height) { int color1 = 3; int color2 = 4; if (PlayerPtr->Drain > PlayerPtr->Power) { color1 = 214; color2 = 211; } if (PlayerPtr->Drain > (PlayerPtr->Power * 2)) { color1 = 235; color2 = 230; } /* ** New power bar is in slightly different place ** ** Old power bar was 107 pixels high. New bar is 153 pixels high. ** ** ST - 5/2/96 11:23AM */ #ifdef WIN32 power_height = (power_height*(76*RESFACTOR+1)) / (53*RESFACTOR+1); drain_height = (drain_height*(76*RESFACTOR+1)) / (53*RESFACTOR+1); #endif bottom = (175*RESFACTOR)+1; LogicPage->Fill_Rect(245*RESFACTOR, bottom-power_height, 245*RESFACTOR+1, bottom, color2); LogicPage->Fill_Rect(246*RESFACTOR, bottom-power_height, 246*RESFACTOR+1, bottom, color1); } /* ** Draw the power drain threshold marker. */ CC_Draw_Shape(PowerShape, 0, (POWER_X * RESFACTOR)+RESFACTOR, bottom - (drain_height + (2 * RESFACTOR)), WINDOW_MAIN, flags | SHAPE_NORMAL, remap); } LogicPage->Unlock(); } BEnd(BENCH_POWER); } RadarClass::Draw_It(complete); } /*********************************************************************************************** * PowerClass::AI -- Process the power bar logic. * * * * Use this routine to process the power bar logic. This consists of animation effects. * * * * INPUT: input -- The player input value to be consumed or ignored as appropriate. * * * * x,y -- Mouse coordinate parameters to use. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 12/20/1994 JLB : Created. * * 12/31/1994 JLB : Uses mouse coordinate parameters. * *=============================================================================================*/ void PowerClass::AI(KeyNumType &input, int x, int y) { if (Map.IsSidebarActive /*IsActive*/) { int olddrain = DrainHeight; int oldpower = PowerHeight; /* ** If the recorded power value has changed we need to adjust for ** it. */ if (PlayerPtr->Power != RecordedPower) { DesiredPowerHeight = Power_Height(PlayerPtr->Power); RecordedPower = PlayerPtr->Power; PowerBounce = 12; if (PowerHeight > DesiredPowerHeight) { PowerDir = -1; } else if (PowerHeight < DesiredPowerHeight) { PowerDir = 1; } else { PowerBounce = 0; } } /* ** If the recorded drain value has changed we need to adjust for ** it. */ if (PlayerPtr->Drain != RecordedDrain) { DesiredDrainHeight = Power_Height(PlayerPtr->Drain); RecordedDrain = PlayerPtr->Drain; DrainBounce = 12; if (DrainHeight > DesiredDrainHeight) { DrainDir = -1; } else if (DrainHeight < DesiredDrainHeight) { DrainDir = 1; } else { DrainBounce = 0; } } if (DrainBounce && DrainHeight == DesiredDrainHeight) { IsToRedraw = true; Flag_To_Redraw(false); DrainBounce--; } else { /* ** If we need to move the drain height then do so. */ if (DrainHeight != DesiredDrainHeight) { DrainHeight += DrainDir; } } if (PowerBounce && PowerHeight == DesiredPowerHeight) { IsToRedraw = true; Flag_To_Redraw(false); PowerBounce--; } else { /* ** If we need to move the power height then do so. */ if (PowerHeight != DesiredPowerHeight) { PowerHeight += PowerDir; } } if (olddrain != DrainHeight || oldpower != PowerHeight) { IsToRedraw = true; Flag_To_Redraw(false); } /* ** Flag to redraw if the power bar flash effect has expired. */ // if (FlashTimer == 1) { if (FlashTimer > 0) { IsToRedraw = true; Flag_To_Redraw(false); } } RadarClass::AI(input, x, y); } /*********************************************************************************************** * PowerClass::Refresh_Cells -- Intercepts the redraw logic to see if sidebar to redraw too. * * * * This routine will examine a refresh list request and determine if the sidebar would be * * affect. If so, it will flag the sidebar to be redrawn. * * * * INPUT: cell -- The cell that the offset list is base on. * * * * list -- The list of cell offset used to flag for redraw. If the special sidebar * * affecting cell magic offset number is detected, the sidebar is flagged * * for redraw and the magic offset is removed. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 06/01/1995 JLB : Created. * *=============================================================================================*/ void PowerClass::Refresh_Cells(CELL cell, short const * list) { if (*list == REFRESH_SIDEBAR) { IsToRedraw = true; Flag_To_Redraw(false); } RadarClass::Refresh_Cells(cell, list); } /*************************************************************************** * PowerClass::Power_Height -- Given a value figure where it falls on bar * * * * INPUT: int value - the value we are testing * * * * OUTPUT: int the height of the point that this value is on graph * * * * WARNINGS: none * * * * HISTORY: * * 06/14/1995 PWG : Created. * *=========================================================================*/ int PowerClass::Power_Height(int value) { int num = value/ POWER_STEP_LEVEL; // figure out the initial num of DRAIN_VALUE's int retval = 0; // currently there is no power /* ** Loop through the different hundreds figuring out the fractional piece ** of each. */ for (int lp = 0; lp < num; lp ++) { retval = retval + (((POWER_HEIGHT - 2) - retval) / POWER_STEP_FACTOR); value -= POWER_STEP_LEVEL; } /* ** Adjust the retval to factor in the remainder */ if (value) { retval = retval + (((((POWER_HEIGHT - 2) - retval) / POWER_STEP_FACTOR) * value) / POWER_STEP_LEVEL); } retval = Bound(retval, 0, POWER_HEIGHT-2); return(retval); } /*********************************************************************************************** * PowerClass::PowerButtonClass::Action -- Handles the mouse over the power bar area. * * * * This routine handles input on the power bar area. Since no input is used for the power * * bar, this routine just pops up appropriate help text for the power bar. * * * * INPUT: flags -- The event flags that triggered this action call. * * * * key -- The key code (if any) associated with the trigger event. * * * * OUTPUT: Should further button processing be stopped? * * * * WARNINGS: none * * * * HISTORY: * * 08/07/1995 JLB : Created. * *=============================================================================================*/ int PowerClass::PowerButtonClass::Action(unsigned flags, KeyNumType & key) { if (!Map.IsSidebarActive) { return(false); } /* ** Force any help label to disappear when the mouse is held over the ** radar map. */ Map.Override_Mouse_Shape(MOUSE_NORMAL); if (PlayerPtr->Power_Fraction() < 1 && PlayerPtr->Power > 0) { Map.Help_Text(TXT_POWER_OUTPUT_LOW, -1, -1, GadgetClass::Get_Color_Scheme()->Color); } else { Map.Help_Text(TXT_POWER_OUTPUT, -1, -1, GadgetClass::Get_Color_Scheme()->Color); } GadgetClass::Action(flags, key); return(true); } /*********************************************************************************************** * PowerClass::Flash_Power -- Flag the power bar to flash. * * * * This will cause the power bar to display with a flash so as to draw attention to * * itself. Typical use of this effect is when power is low. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 10/14/1996 JLB : Created. * *=============================================================================================*/ void PowerClass::Flash_Power(void) { FlashTimer = TICKS_PER_SECOND; IsToRedraw = true; Flag_To_Redraw(false); }