CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

SIDEBAR.CPP (114341B)


      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\sidebar.cpv   2.13   02 Aug 1995 17:03:22   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 : SIDEBAR.CPP                                                  *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : October 20, 1994                                             *
     28  *                                                                                             *
     29  *                  Last Update : January 25, 1996   []                    *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   SidebarClass::Abandon_Production -- Stops production of the object specified.             *
     34  *   SidebarClass::Activate -- Controls the sidebar activation.                                *
     35  *   SidebarClass::Activate_Demolish -- Controls the demolish button on the sidebar.           *
     36  *   SidebarClass::Activate_Repair -- Controls the repair button on the sidebar.               *
     37  *   SidebarClass::Activate_Upgrade -- Controls the upgrade button on the sidebar.             *
     38  *   SidebarClass::Add -- Adds a game object to the sidebar list.                              *
     39  *   SidebarClass::AI -- Handles player clicking on sidebar area.                              *
     40  *   SidebarClass::Draw_It -- Renders the sidebar display.                                     *
     41  *   SidebarClass::Factory_Link -- Links a factory to a sidebar strip.                         *
     42  *   SidebarClass::Init_Clear -- Sets sidebar to a known (and deactivated) state               *
     43  *   SidebarClass::Init_IO -- Adds buttons to the button list                                  *
     44  *   SidebarClass::Init_Theater -- Performs theater-specific initialization                    *
     45  *   SidebarClass::One_Time -- Handles the one time game initializations.                      *
     46  *   SidebarClass::One_Time -- Handles the one time game initializations.                      *
     47  *   SidebarClass::Recalc -- Examines the sidebar data and updates it as necessary.            *
     48  *   SidebarClass::Refresh_Cells -- Intercepts the refresh, looking for sidebar controls.      *
     49  *   SidebarClass::SBGadgetClass::Action -- Special function that controls the mouse over the s*
     50  *   SidebarClass::Scroll -- Handles scrolling the sidebar object strip.                       *
     51  *   SidebarClass::Set_Current -- Sets a specified object that controls the sidebar display.   *
     52  *   SidebarClass::SidebarClass -- Default constructor for the sidebar.                        *
     53  *   SidebarClass::StripClass::Abandon_Produ -- Abandons production associated with sidebar.   *
     54  *   SidebarClass::StripClass::Activate -- Adds the strip buttons to the input system.         *
     55  *   SidebarClass::StripClass::Add -- Add an object to the side strip.                         *
     56  *   SidebarClass::StripClass::AI -- Input and AI processing for the side strip.               *
     57  *   SidebarClass::StripClass::Deactivate -- Removes the side strip buttons from the input syst*
     58  *   SidebarClass::StripClass::Draw_It -- Render the sidebar display.                          *
     59  *   SidebarClass::StripClass::Factory_Link -- Links a factory to a sidebar button.            *
     60  *   SidebarClass::StripClass::Flag_To_Redra -- Flags the sidebar strip to be redrawn.         *
     61  *   SidebarClass::StripClass::Get_Special_Cameo -- Fetches the special event cameo shape.     *
     62  *   SidebarClass::StripClass::Init_Clear -- Sets sidebar to a known (and deactivated) state   *
     63  *   SidebarClass::StripClass::Init_IO -- Adds buttons to the button list                      *
     64  *   SidebarClass::StripClass::Init_Theater -- Performs theater-specific initialization        *
     65  *   SidebarClass::StripClass::One_Time -- Performs one time actions necessary for the side str*
     66  *   SidebarClass::StripClass::Recalc -- Revalidates the current sidebar list of objects.      *
     67  *   SidebarClass::StripClass::Scroll -- Causes the side strip to scroll.                      *
     68  *   SidebarClass::StripClass::SelectClass:: -- Action function when buildable cameo is selecte*
     69  *   SidebarClass::StripClass::SelectClass:: -- Assigns special values to a buildable select bu*
     70  *   SidebarClass::StripClass::SelectClass::SelectClass -- Default constructor.                *
     71  *   SidebarClass::StripClass::StripClass -- Default constructor for the side strip class.     *
     72  *   SidebarClass::Which_Column -- Determines which column a given type should appear.         *
     73  *   sortfunc -- Utility routine that handles 'qsort' the strip buttons.                       *
     74  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     75 
     76 #include	"function.h"
     77 
     78 /*
     79 **	Define "_RETRIEVE" if the palette morphing tables are part of the loaded data. If this
     80 **	is undefined, then the files will be created.
     81 */
     82 #define	_RETRIEVE
     83 
     84 
     85 /***************************************************************************
     86 **	This holds the translucent table for use with the construction clock
     87 **	animation.
     88 */
     89 char SidebarClass::StripClass::ClockTranslucentTable[(1+1)*256];
     90 
     91 
     92 /***************************************************************************
     93 **	This points to the main sidebar shapes. These include the upgrade and
     94 **	repair buttons.
     95 */
     96 TheaterType SidebarClass::StripClass::LastTheater = THEATER_NONE;
     97 
     98 typedef enum ButtonNumberType {
     99 	BUTTON_RADAR = 100,
    100 	BUTTON_REPAIR,
    101 	BUTTON_DEMOLISH,
    102 	BUTTON_UPGRADE,
    103 	BUTTON_SELECT,
    104 	BUTTON_ZOOM
    105 } ButtonNumberType;
    106 
    107 /*
    108 ** Sidebar buttons
    109 */
    110 SidebarClass::SBGadgetClass SidebarClass::Background;
    111 ShapeButtonClass SidebarClass::Repair;
    112 ShapeButtonClass SidebarClass::Upgrade;
    113 ShapeButtonClass SidebarClass::Zoom;
    114 ShapeButtonClass SidebarClass::StripClass::UpButton[COLUMNS];
    115 ShapeButtonClass SidebarClass::StripClass::DownButton[COLUMNS];
    116 SidebarClass::StripClass::SelectClass
    117 SidebarClass::StripClass::SelectButton[COLUMNS][MAX_VISIBLE];
    118 
    119 /*
    120 ** Shape data pointers
    121 */
    122 void const * SidebarClass::StripClass::LogoShapes;
    123 void const * SidebarClass::StripClass::ClockShapes;
    124 void const * SidebarClass::StripClass::SpecialShapes[3];
    125 
    126 void const * SidebarClass::SidebarShape1;
    127 void const * SidebarClass::SidebarShape2;
    128 
    129 
    130 /***********************************************************************************************
    131  * SidebarClass::SidebarClass -- Default constructor for the sidebar.                          *
    132  *                                                                                             *
    133  *    Constructor for the sidebar handler. It basically sets up the sidebar to the empty       *
    134  *    condition.                                                                               *
    135  *                                                                                             *
    136  * INPUT:   none                                                                               *
    137  *                                                                                             *
    138  * OUTPUT:  none                                                                               *
    139  *                                                                                             *
    140  * WARNINGS:   none                                                                            *
    141  *                                                                                             *
    142  * HISTORY:                                                                                    *
    143  *   11/17/1994 JLB : Created.                                                                 *
    144  *=============================================================================================*/
    145 SidebarClass::SidebarClass(void)
    146 {
    147 	IsSidebarActive = false;
    148 	IsRepairActive = false;
    149 	IsUpgradeActive = false;
    150 	IsDemolishActive = false;
    151 	IsToRedraw = true;
    152 
    153 }
    154 
    155 
    156 /***********************************************************************************************
    157  * SidebarClass::One_Time -- Handles the one time game initializations.                        *
    158  *                                                                                             *
    159  *    This routine is used to load the graphic data that is needed by the sidebar display. It  *
    160  *    should only be called ONCE.                                                              *
    161  *                                                                                             *
    162  * INPUT:   none                                                                               *
    163  *                                                                                             *
    164  * OUTPUT:  none                                                                               *
    165  *                                                                                             *
    166  * WARNINGS:   Only call this routine once when the game first starts.                         *
    167  *                                                                                             *
    168  * HISTORY:                                                                                    *
    169  *   10/28/94   JLB : Created.                                                                 *
    170  *=============================================================================================*/
    171 void SidebarClass::One_Time(void)
    172 {
    173 	PowerClass::One_Time();
    174 	/*
    175 	** Set up the pixel offsets and widths and heights used to render the
    176 	** sidebar.  They are now variables because we need to change them for
    177 	** variable resolutions.
    178 	*/
    179 	int factor			= (SeenBuff.Get_Width() == 320) ? 1 : 2;
    180 	SideBarWidth		= SIDEBARWIDTH * factor;
    181 	SideX 				= SeenBuff.Get_Width() - SideBarWidth;
    182 	SideY 				= Map.RadY + Map.RadHeight + 1;
    183 	SideWidth 			= SeenBuff.Get_Width() - SideX;
    184 	SideHeight			= SeenBuff.Get_Height() - SideY;
    185 	MaxVisible			= 4;
    186 	ButtonHeight		= 9 * factor;
    187 	TopHeight			= ButtonHeight + (4 * factor);
    188 
    189 	Background.X		= SideX+8 * factor;
    190 	Background.Y		= SideY,
    191 	Background.Width	= SideWidth-1;
    192 	Background.Height = SideHeight-1;
    193 	/*
    194 	**	This sets up the clipping window. This window is used by the shape drawing
    195 	**	code so that as the sidebar buildable buttons scroll, they get properly
    196 	**	clipped at the top and bottom edges.
    197 	*/
    198 	WindowList[WINDOW_SIDEBAR][WINDOWX]			= (SideX+PowWidth) >> 3;
    199 	WindowList[WINDOW_SIDEBAR][WINDOWY]			= SideY + 1 + TopHeight;
    200 	WindowList[WINDOW_SIDEBAR][WINDOWWIDTH]	= SideWidth>>3;
    201 	WindowList[WINDOW_SIDEBAR][WINDOWHEIGHT]	= (MaxVisible * (StripClass::OBJECT_HEIGHT * factor)) - 1;
    202 
    203 	/*
    204 	**	Set up the coordinates for the sidebar strips. These coordinates are for
    205 	**	the upper left corner.
    206 	*/
    207 	int width = (SideWidth - PowWidth) - (((StripClass::STRIP_WIDTH ) * factor) << 1);
    208 	int spacing = width / 3;
    209 
    210 	Column[0].X = SideX + PowWidth + spacing;
    211 	Column[0].Y = SideY + TopHeight + 1;
    212 	Column[1].X = Column[0].X + (StripClass::STRIP_WIDTH * factor) + spacing -1;
    213 	Column[1].Y = SideY + TopHeight + 1;
    214 
    215 	Column[0].One_Time(0);
    216 	Column[1].One_Time(1);
    217 
    218 	SidebarShape1 = Hires_Retrieve("SIDE1.SHP");
    219 	SidebarShape2 = Hires_Retrieve("SIDE2.SHP");
    220 
    221 
    222 }
    223 
    224 
    225 /***********************************************************************************************
    226  * SidebarClass::Init_Clear -- Sets sidebar to a known (and deactivated) state                 *
    227  *                                                                                             *
    228  * INPUT:   none                                                                               *
    229  *                                                                                             *
    230  * OUTPUT:  none                                                                               *
    231  *                                                                                             *
    232  * WARNINGS:   none                                                                            *
    233  *                                                                                             *
    234  * HISTORY:                                                                                    *
    235  *   12/24/1994 JLB : Created.                                                                 *
    236  *=============================================================================================*/
    237 void SidebarClass::Init_Clear(void)
    238 {
    239 	PowerClass::Init_Clear();
    240 
    241 	IsToRedraw = true;
    242 	IsRepairActive = false;
    243 	IsUpgradeActive = false;
    244 	IsDemolishActive = false;
    245 
    246 	Column[0].Init_Clear();
    247 	Column[1].Init_Clear();
    248 
    249 	Activate(false);
    250 }
    251 
    252 
    253 /***********************************************************************************************
    254  * SidebarClass::Init_IO -- Adds buttons to the button list                                    *
    255  *                                                                                             *
    256  * INPUT:   none                                                                               *
    257  *                                                                                             *
    258  * OUTPUT:  none                                                                               *
    259  *                                                                                             *
    260  * WARNINGS:   none                                                                            *
    261  *                                                                                             *
    262  * HISTORY:                                                                                    *
    263  *   12/24/1994 JLB : Created.                                                                 *
    264  *=============================================================================================*/
    265 void SidebarClass::Init_IO(void)
    266 {
    267 	void *oldfont;
    268 	int oldx;
    269 	PowerClass::Init_IO();
    270 
    271 	/*
    272 	** Add the sidebar's buttons only if we're not in editor mode.
    273 	*/
    274 	int buttonspacing = (SideBarWidth - (ButtonOneWidth + ButtonTwoWidth + ButtonThreeWidth)) / 4;
    275 
    276 
    277 	if (!Debug_Map) {
    278 		/*
    279 		** Set the button widths based on the string that goes in them.
    280 		*/
    281 		oldfont = Set_Font(Font6Ptr);
    282 		oldx    = FontXSpacing;
    283 		FontXSpacing = -1;
    284 		Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6POINT | TPF_NOSHADOW);
    285 
    286 		int maxwidth = String_Pixel_Width(Text_String(TXT_REPAIR_BUTTON)) + 8;
    287 		maxwidth = MAX((unsigned)maxwidth, String_Pixel_Width(Text_String(TXT_BUTTON_SELL)) + 8);
    288 		maxwidth = MAX((unsigned)maxwidth, String_Pixel_Width(Text_String(TXT_MAP)) + 8);
    289 		Repair.Width = maxwidth;
    290 		Upgrade.Width = maxwidth;
    291 		Zoom.Width = maxwidth;
    292 //		Repair.Width = String_Pixel_Width(Text_String(TXT_REPAIR_BUTTON)) + 8;
    293 //		Upgrade.Width = String_Pixel_Width(Text_String(TXT_BUTTON_SELL)) + 8;
    294 //		Zoom.Width = String_Pixel_Width(Text_String(TXT_MAP)) + 8;
    295 		/*
    296 		** find the spacing between buttons by getting remaining width
    297 		** and dividing it between the buttons.
    298 		*/
    299 		int buttonspacing = (SideBarWidth - (Repair.Width + Upgrade.Width + Zoom.Width)) / 4;
    300 
    301 		Repair.IsSticky = true;
    302 		Repair.ID = BUTTON_REPAIR;
    303 		Repair.X = 484;
    304 		Repair.Y = 160;
    305 		Repair.IsPressed = false;
    306 		Repair.IsToggleType = true;
    307 		Repair.ReflectButtonState = true;
    308 #if (FRENCH)
    309 		Repair.Set_Shape(Hires_Retrieve("REPAIRF.SHP"));
    310 #else
    311 #if (GERMAN)
    312 		Repair.Set_Shape(Hires_Retrieve("REPAIRG.SHP"));
    313 #else
    314 		Repair.Set_Shape(Hires_Retrieve("REPAIR.SHP"));
    315 #endif
    316 #endif
    317 
    318 		Upgrade.IsSticky = true;
    319 		Upgrade.ID = BUTTON_UPGRADE;
    320 		Upgrade.X = 480+57;
    321 		Upgrade.Y = 160;
    322 		Upgrade.IsPressed = false;
    323 		Upgrade.IsToggleType = true;
    324 		Upgrade.ReflectButtonState = true;
    325 #if (FRENCH)
    326 		Upgrade.Set_Shape(Hires_Retrieve("SELLF.SHP"));
    327 #else
    328 #if (GERMAN)
    329 		Upgrade.Set_Shape(Hires_Retrieve("SELLG.SHP"));
    330 #else
    331 		Upgrade.Set_Shape(Hires_Retrieve("SELL.SHP"));
    332 #endif
    333 #endif
    334 
    335 		Zoom.IsSticky = true;
    336 		Zoom.ID = BUTTON_ZOOM;
    337 		Zoom.X = 480 + 110;
    338 		Zoom.Y = 160;
    339 		Zoom.IsPressed = false;
    340 #if (FRENCH)
    341 		Zoom.Set_Shape(Hires_Retrieve("MAPF.SHP"));
    342 #else
    343 #if (GERMAN)
    344 		Zoom.Set_Shape(Hires_Retrieve("MAPG.SHP"));
    345 #else
    346 		Zoom.Set_Shape(Hires_Retrieve("MAP.SHP"));
    347 #endif
    348 #endif
    349 
    350 		if (IsRadarActive || GameToPlay!=GAME_NORMAL) {
    351 			Zoom.Enable();
    352 		} else {
    353 			Zoom.Disable();
    354 		}
    355 
    356 		Set_Font(oldfont);
    357 		FontXSpacing = oldx;
    358 		FontXSpacing = -1;
    359 
    360 
    361 		Column[0].Init_IO(0);
    362 		Column[1].Init_IO(1);
    363 
    364 		/*
    365 		** If a game was loaded & the sidebar was enabled, pop it up now
    366 		*/
    367 		if (IsSidebarActive) {
    368 			IsSidebarActive = false;
    369 			Activate(1);
    370 //			Background.Zap();
    371 //			Add_A_Button(Background);
    372 		}
    373 	}
    374 }
    375 
    376 
    377 /***********************************************************************************************
    378  * SidebarClass::Init_Theater -- Performs theater-specific initialization                      *
    379  *                                                                                             *
    380  * INPUT:   theater  -- The theater that is being initialized. Sometimes this has an effect on *
    381  *                      the data that is loaded.                                               *
    382  *                                                                                             *
    383  * OUTPUT:  none                                                                               *
    384  *                                                                                             *
    385  * WARNINGS:   none                                                                            *
    386  *                                                                                             *
    387  * HISTORY:                                                                                    *
    388  *   12/24/1994 JLB : Created.                                                                 *
    389  *=============================================================================================*/
    390 void SidebarClass::Init_Theater(TheaterType theater)
    391 {
    392 	PowerClass::Init_Theater(theater);
    393 
    394 	Column[0].Init_Theater(theater);
    395 	Column[1].Init_Theater(theater);
    396 }
    397 
    398 
    399 /***********************************************************************************************
    400  * SidebarClass::Which_Column -- Determines which column a given type should appear.           *
    401  *                                                                                             *
    402  *    Use this function to resolve what column the specified object type should be placed      *
    403  *    into.                                                                                    *
    404  *                                                                                             *
    405  * INPUT:   otype -- Pointer to the object type class of the object in question.               *
    406  *                                                                                             *
    407  * OUTPUT:  Returns with the column number that the object should be placed in.                *
    408  *                                                                                             *
    409  * WARNINGS:   none                                                                            *
    410  *                                                                                             *
    411  * HISTORY:                                                                                    *
    412  *   01/01/1995 JLB : Created.                                                                 *
    413  *=============================================================================================*/
    414 int SidebarClass::Which_Column(RTTIType type)
    415 {
    416 	if (type == RTTI_BUILDINGTYPE || type == RTTI_BUILDING) {
    417 		return(0);
    418 	}
    419 	return(1);
    420 }
    421 
    422 
    423 /***********************************************************************************************
    424  * SidebarClass::Factory_Link -- Links a factory to a sidebar strip.                           *
    425  *                                                                                             *
    426  *    This routine will link the specified factory to the sidebar strip. A factory must be     *
    427  *    linked to the sidebar so that as the factory production progresses, the sidebar will     *
    428  *    show the production progress.                                                            *
    429  *                                                                                             *
    430  * INPUT:   factory  -- The factory number to attach.                                          *
    431  *                                                                                             *
    432  *          type     -- The object type number.                                                *
    433  *                                                                                             *
    434  *          id       -- The object sub-type number.                                            *
    435  *                                                                                             *
    436  * OUTPUT:  Was the factory successfully attached to the sidebar strip?                        *
    437  *                                                                                             *
    438  * WARNINGS:   none                                                                            *
    439  *                                                                                             *
    440  * HISTORY:                                                                                    *
    441  *   05/19/1995 JLB : Created.                                                                 *
    442  *=============================================================================================*/
    443 bool SidebarClass::Factory_Link(int factory, RTTIType type, int id)
    444 {
    445 	return(Column[Which_Column(type)].Factory_Link(factory, type, id));
    446 }
    447 
    448 
    449 /***********************************************************************************************
    450  * SidebarClass::Refresh_Cells -- Intercepts the refresh, looking for sidebar controls.        *
    451  *                                                                                             *
    452  *    This routine intercepts the Refresh_Cells call in order to see if the sidebar needs      *
    453  *    to be refreshed as well. If the special code to refresh the sidebar was found, it        *
    454  *    flags the sidebar to be redrawn and then removes the code from the list.                 *
    455  *                                                                                             *
    456  * INPUT:   cell  -- The cell to base the refresh list on.                                     *
    457  *                                                                                             *
    458  *          list  -- Pointer to the cell offset list that elaborates all the cells that        *
    459  *                   need to be flagged for redraw.                                            *
    460  *                                                                                             *
    461  * OUTPUT:  none                                                                               *
    462  *                                                                                             *
    463  * WARNINGS:   none                                                                            *
    464  *                                                                                             *
    465  * HISTORY:                                                                                    *
    466  *   01/19/1995 JLB : Created.                                                                 *
    467  *=============================================================================================*/
    468 void SidebarClass::Refresh_Cells(CELL cell, short const *list)
    469 {
    470 	if (*list == REFRESH_SIDEBAR) {
    471 		IsToRedraw = true;
    472 		Column[0].IsToRedraw = true;
    473 		Column[1].IsToRedraw = true;
    474 		Flag_To_Redraw(false);
    475 	}
    476 	PowerClass::Refresh_Cells(cell, list);
    477 }
    478 
    479 
    480 /***********************************************************************************************
    481  * SidebarClass::Activate_Repair -- Controls the repair button on the sidebar.                 *
    482  *                                                                                             *
    483  *    Use this routine to turn the repair sidebar button on and off. Typically, the button     *
    484  *    is enabled when the currently selected structure is friendly and damaged.                *
    485  *                                                                                             *
    486  * INPUT:   control  -- The controls how the button is to be activated or deactivated;         *
    487  *                      0  -- Turn button off.                                                 *
    488  *                      1  -- Turn button on.                                                  *
    489  *                      -1 -- Toggle button state.                                             *
    490  *                                                                                             *
    491  * OUTPUT:  bool; Was the button previously activated?                                         *
    492  *                                                                                             *
    493  * WARNINGS:   none                                                                            *
    494  *                                                                                             *
    495  * HISTORY:                                                                                    *
    496  *   12/24/1994 JLB : Created.                                                                 *
    497  *=============================================================================================*/
    498 bool SidebarClass::Activate_Repair(int control)
    499 {
    500 	bool old = IsRepairActive;
    501 
    502 	if (control == -1) {
    503 		control = IsRepairActive ? 0 : 1;
    504 	}
    505 	switch (control) {
    506 		case 1:
    507 			IsRepairActive = true;
    508 			break;
    509 
    510 		default:
    511 		case 0:
    512 			IsRepairActive = false;
    513 			break;
    514 	}
    515 	if (old != IsRepairActive) {
    516 		Flag_To_Redraw(false);
    517 		IsToRedraw = true;
    518 
    519 		if (!IsRepairActive) {
    520 			Help_Text(TXT_NONE);
    521 			Set_Default_Mouse(MOUSE_NORMAL, false);
    522 		}
    523 	}
    524 	return(old);
    525 }
    526 
    527 
    528 /***********************************************************************************************
    529  * SidebarClass::Activate_Upgrade -- Controls the upgrade button on the sidebar.               *
    530  *                                                                                             *
    531  *    Use this routine to turn the upgrade sidebar button on and off. Typically, the button    *
    532  *    is enabled when the currently selected structure can be upgraded and disabled otherwise. *
    533  *                                                                                             *
    534  * INPUT:   control  -- The controls how the button is to be activated or deactivated;         *
    535  *                      0  -- Turn button off.                                                 *
    536  *                      1  -- Turn button on.                                                  *
    537  *                      -1 -- Toggle button state.                                             *
    538  *                                                                                             *
    539  * OUTPUT:  bool; Was the button previously activated?                                         *
    540  *                                                                                             *
    541  * WARNINGS:   none                                                                            *
    542  *                                                                                             *
    543  * HISTORY:                                                                                    *
    544  *   12/24/1994 JLB : Created.                                                                 *
    545  *=============================================================================================*/
    546 bool SidebarClass::Activate_Upgrade(int control)
    547 {
    548 	bool old = IsUpgradeActive;
    549 	if (control == -1) {
    550 		control = IsUpgradeActive ? 0 : 1;
    551 	}
    552 	switch (control) {
    553 		case 1:
    554 			IsUpgradeActive = true;
    555 			break;
    556 
    557 		default:
    558 		case 0:
    559 			IsUpgradeActive = false;
    560 			break;
    561 	}
    562 	if (old != IsUpgradeActive) {
    563 		Flag_To_Redraw(false);
    564 		IsToRedraw = true;
    565 		if (!IsUpgradeActive) {
    566 			Set_Default_Mouse(MOUSE_NORMAL, false);
    567 		}
    568 	}
    569 	return(old);
    570 }
    571 
    572 
    573 /***********************************************************************************************
    574  * SidebarClass::Activate_Demolish -- Controls the demolish button on the sidebar.             *
    575  *                                                                                             *
    576  *    Use this routine to turn the demolish/dismantle sidebar button on and off. Typically,    *
    577  *    the button is enabled when a friendly building is selected and disabled otherwise.       *
    578  *                                                                                             *
    579  * INPUT:   control  -- The controls how the button is to be activated or deactivated;         *
    580  *                      0  -- Turn button off.                                                 *
    581  *                      1  -- Turn button on.                                                  *
    582  *                      -1 -- Toggle button state.                                             *
    583  *                                                                                             *
    584  * OUTPUT:  bool; Was the button previously activated?                                         *
    585  *                                                                                             *
    586  * WARNINGS:   none                                                                            *
    587  *                                                                                             *
    588  * HISTORY:                                                                                    *
    589  *   12/24/1994 JLB : Created.                                                                 *
    590  *=============================================================================================*/
    591 bool SidebarClass::Activate_Demolish(int control)
    592 {
    593 	bool old = IsDemolishActive;
    594 
    595 	if (control == -1) {
    596 		control = IsDemolishActive ? 0 : 1;
    597 	}
    598 	switch (control) {
    599 		case 1:
    600 			IsDemolishActive = true;
    601 			break;
    602 
    603 		default:
    604 		case 0:
    605 			IsDemolishActive = false;
    606 			break;
    607 	}
    608 	if (old != IsDemolishActive) {
    609 		Flag_To_Redraw(false);
    610 		IsToRedraw = true;
    611 		if (!IsDemolishActive) {
    612 			Set_Default_Mouse(MOUSE_NORMAL, false);
    613 		}
    614 	}
    615 	return(old);
    616 }
    617 
    618 
    619 /***********************************************************************************************
    620  * SidebarClass::Add -- Adds a game object to the sidebar list.                                *
    621  *                                                                                             *
    622  *    This routine is used to add a game object to the sidebar. Call this routine when a       *
    623  *    factory type building is created. It handles the case of adding an item that has already *
    624  *    been added -- it just ignores it.                                                        *
    625  *                                                                                             *
    626  * INPUT:   object   -- Pointer to the object that is being added.                             *
    627  *                                                                                             *
    628  * OUTPUT:  bool; Was the object added to the sidebar?                                         *
    629  *                                                                                             *
    630  * WARNINGS:   none                                                                            *
    631  *                                                                                             *
    632  * HISTORY:                                                                                    *
    633  *   11/17/1994 JLB : Created.                                                                 *
    634  *   9/24/2019 3:17PM : Added via capture parameter for new sidebar functionality              *
    635  *=============================================================================================*/
    636 bool SidebarClass::Add(RTTIType type, int id, bool via_capture)
    637 {
    638 	int column;
    639 
    640 	/*
    641 	** Add the sidebar only if we're not in editor mode.
    642 	*/
    643 	if (!Debug_Map) {
    644 		column = Which_Column(type);
    645 
    646 		if (Column[column].Add(type, id, via_capture)) {
    647 			Activate(1);
    648 			IsToRedraw = true;
    649 			Flag_To_Redraw(false);
    650 			return(true);
    651 		}
    652 		return(false);
    653 	}
    654 
    655 	return(false);
    656 }
    657 
    658 
    659 /***********************************************************************************************
    660  * SidebarClass::Scroll -- Handles scrolling the sidebar object strip.                         *
    661  *                                                                                             *
    662  *    This routine is used to scroll the sidebar strip of objects. The strip appears whenever  *
    663  *    a building is selected that can produce units. If the number of units to produce is      *
    664  *    greater than what the sidebar can hold, this routine is used to scroll the other object  *
    665  *    into view so they can be selected.                                                       *
    666  *                                                                                             *
    667  * INPUT:   up -- Should the scroll be upwards? Upward scrolling reveals object that are       *
    668  *                later in the list of objects.                                                *
    669  *                                                                                             *
    670  * OUTPUT:  bool; Did scrolling occur?                                                         *
    671  *                                                                                             *
    672  * WARNINGS:   none                                                                            *
    673  *                                                                                             *
    674  * HISTORY:                                                                                    *
    675  *   10/28/94   JLB : Created.                                                                 *
    676  *=============================================================================================*/
    677 bool SidebarClass::Scroll(bool up, int column)
    678 {
    679 	if (Column[column].Scroll(up)) {
    680 		IsToRedraw = true;
    681 		Flag_To_Redraw(false);
    682 		return(true);
    683 	}
    684 	return(false);
    685 }
    686 
    687 
    688 /***********************************************************************************************
    689  * SidebarClass::Draw_It -- Renders the sidebar display.                                       *
    690  *                                                                                             *
    691  *    This routine performs the actual drawing of the sidebar display.                         *
    692  *                                                                                             *
    693  * INPUT:   none                                                                               *
    694  *                                                                                             *
    695  * OUTPUT:  bool; Was the sidebar imagery changed at all?                                      *
    696  *                                                                                             *
    697  * WARNINGS:   none                                                                            *
    698  *                                                                                             *
    699  * HISTORY:                                                                                    *
    700  *   10/28/94   JLB : Created.                                                                 *
    701  *   12/31/1994 JLB : Split rendering off into the sidebar strip class.                        *
    702  *=============================================================================================*/
    703 void SidebarClass::Draw_It(bool complete)
    704 {
    705 	PowerClass::Draw_It(complete);
    706 
    707 	if (IsSidebarActive && (IsToRedraw || complete) && !Debug_Map) {
    708 		IsToRedraw = false;
    709 
    710 		if (LogicPage->Lock()){
    711 			/*
    712 			**	Draw the outline box around the sidebar buttons.
    713 			*/
    714 			//CC_Draw_Shape(SidebarShape1, (int)complete, SideX, 158, WINDOW_MAIN, SHAPE_WIN_REL);
    715 			//CC_Draw_Shape(SidebarShape2, (int)complete, SideX, 158+118, WINDOW_MAIN, SHAPE_WIN_REL);
    716 			LogicPage->Draw_Line(SideX, 157, SeenBuff.Get_Width()-1, 157, 0);
    717 			CC_Draw_Shape(SidebarShape1, 0, SideX, 158, WINDOW_MAIN, SHAPE_WIN_REL);
    718 			CC_Draw_Shape(SidebarShape2, 0, SideX, 158+118, WINDOW_MAIN, SHAPE_WIN_REL);
    719 
    720 	#if (0)
    721 			if ( complete ) {
    722 				LogicPage->Fill_Rect(SideX+Map.PowWidth, SideY, SideX+SideWidth-1, SideY+SideHeight-1, LTGREY);
    723 			}
    724 			LogicPage->Fill_Rect(SideX, SideY, SideX+SideWidth-1, SideY+TopHeight-1, LTGREY);
    725 			Draw_Box(SideX+Map.PowWidth, SideY+TopHeight, SideWidth-Map.PowWidth, SideHeight-TopHeight, BOXSTYLE_RAISED, false);
    726 	#endif	//(0)
    727 			//Repair.Draw_Me(true);
    728 			//Upgrade.Draw_Me(true);
    729 			//Zoom.Draw_Me(true);
    730 	//	} else {
    731 	//		if (IsToRedraw || complete) {
    732 	//			LogicPage->Fill_Rect(TacPixelX + Lepton_To_Pixel(TacLeptonWidth), SIDE_Y, 319, SIDE_Y+TOP_HEIGHT, BLACK);
    733 	//		}
    734 
    735 			LogicPage->Unlock();
    736 		}
    737 
    738 	}
    739 	/*
    740 	**	Draw the side strip elements by calling their respective draw functions.
    741 	*/
    742 	if (IsSidebarActive){
    743 		Column[0].Draw_It(complete);
    744 		Column[1].Draw_It(complete);
    745 		Repair.Draw_Me(true);
    746 		Upgrade.Draw_Me(true);
    747 		Zoom.Draw_Me(true);
    748 	}
    749 
    750 	IsToRedraw = false;
    751 }
    752 
    753 
    754 /***********************************************************************************************
    755  * SidebarClass::AI -- Handles player clicking on sidebar area.                                *
    756  *                                                                                             *
    757  *    This routine handles the processing necessary when the player clicks on the sidebar.     *
    758  *    Typically, this is selection of the item to build.                                       *
    759  *                                                                                             *
    760  * INPUT:   input -- Reference to the keyboard input value.                                    *
    761  *                                                                                             *
    762  *          x,y   -- Mouse coordinates at time of input.                                       *
    763  *                                                                                             *
    764  * OUTPUT:  bool; Was the click handled?                                                       *
    765  *                                                                                             *
    766  * WARNINGS:   none                                                                            *
    767  *                                                                                             *
    768  * HISTORY:                                                                                    *
    769  *   10/28/94   JLB : Created.                                                                 *
    770  *   11/11/1994 JLB : Processes input directly.                                                *
    771  *   12/26/1994 JLB : Uses factory manager class for construction handling.                    *
    772  *   12/31/1994 JLB : Simplified to use the sidebar strip class handlers.                      *
    773  *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *
    774  *   06/27/1995 JLB : <TAB> key toggles sidebar.                                               *
    775  *=============================================================================================*/
    776 void SidebarClass::AI(KeyNumType & input, int x, int y)
    777 {
    778 	bool redraw = false;
    779 
    780 	//
    781 	// We need to process the sidebar differently in multiplayer. ST - 3/22/2019 1:27PM
    782 	//
    783 	if (GameToPlay == GAME_GLYPHX_MULTIPLAYER) {
    784 		PowerClass::AI(input, x, y);
    785 		return;
    786 	}
    787 
    788 	/*
    789 	**	Toggle the sidebar in and out with the <TAB> key.
    790 	*/
    791 	if (input == KN_TAB) {
    792 		Activate(-1);
    793 	}
    794 
    795 	if (!Debug_Map) {
    796 		Column[0].AI(input, x, y);
    797 		Column[1].AI(input, x, y);
    798 	}
    799 
    800 	if (IsSidebarActive && !Debug_Map) {
    801 
    802 		if (input == KN_DOWN) {
    803 			redraw |= Column[0].Scroll(false);
    804 			redraw |= Column[1].Scroll(false);
    805 			input = KN_NONE;
    806 		}
    807 		if (input == KN_UP) {
    808 			redraw |= Column[0].Scroll(true);
    809 			redraw |= Column[1].Scroll(true);
    810 			input = KN_NONE;
    811 		}
    812 	}
    813 
    814 	if (IsSidebarActive) {
    815 
    816 		/*
    817 		**	If there are any buildings in the payer's inventory, then allow the repair
    818 		**	option.
    819 		*/
    820 		if (PlayerPtr->BScan) {
    821 			Activate_Repair(true);
    822 		} else {
    823 			Activate_Repair(false);
    824 		}
    825 
    826 		if (input == (BUTTON_REPAIR|KN_BUTTON)) {
    827 			Repair_Mode_Control(-1);
    828 		}
    829 
    830 		if (input == (BUTTON_ZOOM|KN_BUTTON)) {
    831 			/*
    832 			** If radar is active, cycle as follows:
    833 			** Zoomed => not zoomed
    834 			** not zoomed => player status (multiplayer only)
    835 			** player status => zoomed
    836 			*/
    837 			if (IsRadarActive) {
    838 				if (Is_Zoomed() || GameToPlay==GAME_NORMAL) {
    839 					Zoom_Mode(Coord_Cell(TacticalCoord));
    840 				} else {
    841 					if (!Is_Player_Names()) {
    842 						Player_Names(1);
    843 					} else {
    844 						Player_Names(0);
    845 						Zoom_Mode(Coord_Cell(TacticalCoord));
    846 					}
    847 				}
    848 			} else {
    849 				if (GameToPlay!=GAME_NORMAL) {
    850 					Player_Names(Is_Player_Names()==0);
    851 				}
    852 			}
    853 		}
    854 
    855 		if (input == (BUTTON_UPGRADE|KN_BUTTON)) {
    856 			Sell_Mode_Control(-1);
    857 		}
    858 
    859 #ifdef NEVER
    860 //		int index = -1;
    861 		if (index != -1) {
    862 			/*
    863 			**	Display help text if the mouse is over a sidebar button.
    864 			*/
    865 			switch (index) {
    866 				default:
    867 				case 2:
    868 					Map.Help_Text(TXT_UPGRADE, -1, -1, PlayerPtr->Class->Color);
    869 					break;
    870 
    871 				case 1:
    872 					Map.Help_Text(PlayerPtr->Class->House == HOUSE_GOOD ? TXT_SELL : TXT_DEMOLISH, x, y, PlayerPtr->Class->Color);
    873 					break;
    874 
    875 				case 0:
    876 					Map.Help_Text(TXT_REPAIR, x, y, PlayerPtr->Class->Color);
    877 					break;
    878 			}
    879 		}
    880 #endif
    881 
    882 		if (redraw) {
    883 			//IsToRedraw = true;
    884 			Column[0].Flag_To_Redraw();
    885 			Column[1].Flag_To_Redraw();
    886 
    887 			Flag_To_Redraw(false);
    888 		}
    889 	}
    890 
    891 	if ((!IsRepairMode) && Repair.IsOn){
    892 		Repair.Turn_Off();
    893 	}
    894 
    895 	if ((!IsSellMode) && Upgrade.IsOn){
    896 		Upgrade.Turn_Off();
    897 	}
    898 
    899 	PowerClass::AI(input, x, y);
    900 }
    901 
    902 
    903 /***********************************************************************************************
    904  * SidebarClass::Recalc -- Examines the sidebar data and updates it as necessary.              *
    905  *                                                                                             *
    906  *    Occasionally a factory gets destroyed. This routine must be called in such a case        *
    907  *    because it might be possible that sidebar object need to be removed. This routine will   *
    908  *    examine all existing objects in the sidebar class and if no possible factory can         *
    909  *    produce it, then it will be removed.                                                     *
    910  *                                                                                             *
    911  * INPUT:   none                                                                               *
    912  *                                                                                             *
    913  * OUTPUT:  none                                                                               *
    914  *                                                                                             *
    915  * WARNINGS:   This routine is exhaustive and thus time consuming. Only call it when really    *
    916  *             necessary. Such as when a factory is destroyed rather than when a non-factory   *
    917  *             is destroyed.                                                                   *
    918  *                                                                                             *
    919  * HISTORY:                                                                                    *
    920  *   11/30/1994 JLB : Created.                                                                 *
    921  *=============================================================================================*/
    922 void SidebarClass::Recalc(void)
    923 {
    924 	bool redraw = false;
    925 
    926 	// Done elsewhere for new multiplayer. ST - 3/22/2019 2:06PM
    927 	if (GameToPlay == GAME_GLYPHX_MULTIPLAYER) {
    928 		return;
    929 	}
    930 
    931 	redraw |= Column[0].Recalc();
    932 	redraw |= Column[1].Recalc();
    933 
    934 	if (redraw) {
    935 		IsToRedraw = true;
    936 		Flag_To_Redraw(false);
    937 	}
    938 }
    939 
    940 
    941 /***********************************************************************************************
    942  * SidebarClass::Activate -- Controls the sidebar activation.                                  *
    943  *                                                                                             *
    944  *    Use this routine to turn the sidebar on or off. This routine handles updating the        *
    945  *    necessary flags.                                                                         *
    946  *                                                                                             *
    947  * INPUT:   control  -- Tells what to do with the sidebar according to the following:          *
    948  *                         0 = Turn sidebar off.                                               *
    949  *                         1 = Turn sidebar on.                                                *
    950  *                         -1= Toggle sidebar on or off.                                       *
    951  *                                                                                             *
    952  * OUTPUT:  bool; Was the sidebar already on?                                                  *
    953  *                                                                                             *
    954  * WARNINGS:   none                                                                            *
    955  *                                                                                             *
    956  * HISTORY:                                                                                    *
    957  *   12/09/1994 JLB : Created.                                                                 *
    958  *=============================================================================================*/
    959 bool SidebarClass::Activate(int control)
    960 {
    961 	//
    962 	// We don't want the original sidebar to be visible. ST - 1/31/2019 11:28AM
    963 	//
    964 	if (control < 100) {
    965 		return IsSidebarActive;
    966 	}
    967 	
    968 	bool old = IsSidebarActive;
    969 
    970 		int sidex 		= SeenBuff.Get_Width() - SideBarWidth;
    971 		int sidey 		= Map.RadY + Map.RadHeight;
    972 		int topheight	= 13;
    973 		int sidewidth  = SeenBuff.Get_Width() - sidex;
    974 		int sideheight = SeenBuff.Get_Height() - sidey;
    975 
    976 	if (PlaybackGame)
    977 		return (old);
    978 
    979 	/*
    980 	**	Determine the new state of the sidebar.
    981 	*/
    982 	switch (control) {
    983 		case -1:
    984 			IsSidebarActive = IsSidebarActive == false;
    985 			break;
    986 
    987 		case 1:
    988 			IsSidebarActive = true;
    989 			break;
    990 
    991 		default:
    992 		case 0:
    993 			IsSidebarActive = false;
    994 			break;
    995 	}
    996 
    997 	/*
    998 	**	Only if there is a change in the state of the sidebar will anything
    999 	**	be done to change it.
   1000 	*/
   1001 	if (IsSidebarActive != old) {
   1002 
   1003 		/*
   1004 		**	If the sidebar is activated but was on the right side of the screen, then
   1005 		**	activate it on the left side of the screen.
   1006 		*/
   1007 		if (IsSidebarActive /*&& X*/) {
   1008 			Set_View_Dimensions(0, Map.Get_Tab_Height(), SeenBuff.Get_Width() - sidewidth);
   1009 			IsToRedraw = true;
   1010 			Help_Text(TXT_NONE);
   1011 			Repair.Zap();
   1012 			Add_A_Button(Repair);
   1013 			Upgrade.Zap();
   1014 			Add_A_Button(Upgrade);
   1015 			Zoom.Zap();
   1016 			Add_A_Button(Zoom);
   1017 			Column[0].Activate();
   1018 			Column[1].Activate();
   1019 			Background.Zap();
   1020 			Add_A_Button(Background);
   1021 			Map.RadarButton.Zap();
   1022 			Add_A_Button(Map.RadarButton);
   1023 			Map.PowerButton.Zap();
   1024 			Add_A_Button(Map.PowerButton);
   1025 		} else  {
   1026 			Help_Text(TXT_NONE);
   1027 			Set_View_Dimensions(0, Map.Get_Tab_Height());
   1028 			Remove_A_Button(Repair);
   1029 			Remove_A_Button(Upgrade);
   1030 			Remove_A_Button(Zoom);
   1031 			Remove_A_Button(Background);
   1032 			Column[0].Deactivate();
   1033 			Column[1].Deactivate();
   1034 			Remove_A_Button(Map.RadarButton);
   1035 			Remove_A_Button(Map.PowerButton);
   1036 		}
   1037 
   1038 		/*
   1039 		**	Since the sidebar status has changed, update the map so that the graphics
   1040 		**	will be rendered correctly.
   1041 		*/
   1042 		Flag_To_Redraw(true);
   1043 	}
   1044 
   1045 	return(old);
   1046 }
   1047 
   1048 
   1049 /***********************************************************************************************
   1050  * SidebarClass::StripClass::StripClass -- Default constructor for the side strip class.       *
   1051  *                                                                                             *
   1052  *    This constructor is used to reset the side strip to default empty state.                 *
   1053  *                                                                                             *
   1054  * INPUT:   none                                                                               *
   1055  *                                                                                             *
   1056  * OUTPUT:  none                                                                               *
   1057  *                                                                                             *
   1058  * WARNINGS:   none                                                                            *
   1059  *                                                                                             *
   1060  * HISTORY:                                                                                    *
   1061  *   12/31/1994 JLB : Created.                                                                 *
   1062  *=============================================================================================*/
   1063 SidebarClass::StripClass::StripClass(void)
   1064 {
   1065 	IsScrollingDown = false;
   1066 	IsScrolling = false;
   1067 	IsBuilding = false;	TopIndex = 0;
   1068 	Slid = 0;
   1069 	BuildableCount = 0;
   1070 	for (int index = 0; index < MAX_BUILDABLES; index++) {
   1071 		Buildables[index].BuildableID = 0;
   1072 		Buildables[index].BuildableType = RTTI_NONE;
   1073 		Buildables[index].Factory = -1;
   1074 		Buildables[index].BuildableViaCapture = false;		// Added for new sidebar functionality. ST - 9/24/2019 3:10PM 
   1075 	}
   1076 }
   1077 
   1078 
   1079 
   1080 /***********************************************************************************************
   1081  * SidebarClass::StripClass::One_Time -- Performs one time actions necessary for the side stri *
   1082  *                                                                                             *
   1083  *    Call this routine ONCE at the beginning of the game. It handles retrieving pointers to   *
   1084  *    the shape files it needs for rendering.                                                  *
   1085  *                                                                                             *
   1086  * INPUT:   none                                                                               *
   1087  *                                                                                             *
   1088  * OUTPUT:  none                                                                               *
   1089  *                                                                                             *
   1090  * WARNINGS:   none                                                                            *
   1091  *                                                                                             *
   1092  * HISTORY:                                                                                    *
   1093  *   12/31/1994 JLB : Created.                                                                 *
   1094  *=============================================================================================*/
   1095 void SidebarClass::StripClass::One_Time(int )
   1096 {
   1097 	static char *_file[3] = {
   1098 		"ION",
   1099 		"ATOM",
   1100 		"BOMB"
   1101 	};
   1102 	int factor = Get_Resolution_Factor();
   1103 
   1104 	ObjectWidth				= OBJECT_WIDTH << factor;
   1105 	ObjectHeight			= OBJECT_HEIGHT << factor;
   1106 	StripWidth 				= STRIP_WIDTH << factor;
   1107 	LeftEdgeOffset			= (StripWidth - ObjectWidth) >> 1;
   1108 	ButtonSpacingOffset	= (StripWidth - ((BUTTON_WIDTH << factor) << 1)) / 3;
   1109 
   1110 	LogoShapes = Hires_Retrieve("STRIP.SHP");
   1111 	ClockShapes = Hires_Retrieve("CLOCK.SHP");
   1112 
   1113 	char	fullname[_MAX_FNAME+_MAX_EXT];
   1114 	char buffer[_MAX_FNAME];
   1115 
   1116 	for (int lp = 0; lp < 3; lp++) {
   1117 		if ( Get_Resolution_Factor() ) {
   1118 			sprintf(buffer, "%sICNH", _file[lp]);
   1119 		} else {
   1120 			sprintf(buffer, "%sICON", _file[lp]);
   1121 		}
   1122 		_makepath(fullname, NULL, NULL, buffer, ".SHP");
   1123 		SpecialShapes[lp] = MixFileClass::Retrieve(fullname);
   1124 	}
   1125 
   1126 
   1127 }
   1128 
   1129 
   1130 /***********************************************************************************************
   1131  * SidebarClass::StripClass::Get_Special_Cameo -- Fetches the special event cameo shape.       *
   1132  *                                                                                             *
   1133  *    This routine will return with a pointer to the cameo data for the special objects that   *
   1134  *    can appear on the sidebar (e.g., nuclear bomb).                                          *
   1135  *                                                                                             *
   1136  * INPUT:   type  -- The special type to fetch the cameo imagery for.                          *
   1137  *                                                                                             *
   1138  * OUTPUT:  Returns with a pointer to the cameo imagery for the specified special object.      *
   1139  *                                                                                             *
   1140  * WARNINGS:   none                                                                            *
   1141  *                                                                                             *
   1142  * HISTORY:                                                                                    *
   1143  *   05/19/1995 JLB : commented                                                                *
   1144  *=============================================================================================*/
   1145 void const * SidebarClass::StripClass::Get_Special_Cameo(int type)
   1146 {
   1147 	return(SpecialShapes[type]);
   1148 }
   1149 
   1150 
   1151 /***********************************************************************************************
   1152  * SidebarClass::StripClass::Init_Clear -- Sets sidebar to a known (and deactivated) state     *
   1153  *                                                                                             *
   1154  * INPUT:   none                                                                               *
   1155  *                                                                                             *
   1156  * OUTPUT:  none                                                                               *
   1157  *                                                                                             *
   1158  * WARNINGS:   none                                                                            *
   1159  *                                                                                             *
   1160  * HISTORY:                                                                                    *
   1161  *   12/24/1994 JLB : Created.                                                                 *
   1162  *=============================================================================================*/
   1163 void SidebarClass::StripClass::Init_Clear(void)
   1164 {
   1165 	IsScrollingDown = false;
   1166 	IsScrolling = false;
   1167 	IsBuilding = false;
   1168 	Flasher = -1;
   1169 	TopIndex = 0;
   1170 	Slid = 0;
   1171 	BuildableCount = 0;
   1172 
   1173 	/*
   1174 	** Since we're resetting the strips, clear out all the buildables & factory pointers.
   1175 	*/
   1176 	for (int index = 0; index < MAX_BUILDABLES; index++) {
   1177 		Buildables[index].BuildableID = 0;
   1178 		Buildables[index].BuildableType = RTTI_NONE;
   1179 		Buildables[index].Factory = -1;
   1180 		Buildables[index].BuildableViaCapture = false;		// Added for new sidebar functionality. ST - 9/24/2019 3:10PM 
   1181 	}
   1182 }
   1183 
   1184 
   1185 /***********************************************************************************************
   1186  * SidebarClass::StripClass::Init_IO -- Initializes the strip's buttons								  *
   1187  *                                                                                             *
   1188  * This routine doesn't actually add any buttons to the list;
   1189  *                                                                                             *
   1190  * INPUT:   none                                                                               *
   1191  *                                                                                             *
   1192  * OUTPUT:  none                                                                               *
   1193  *                                                                                             *
   1194  * WARNINGS:   none                                                                            *
   1195  *                                                                                             *
   1196  * HISTORY:                                                                                    *
   1197  *   12/24/1994 JLB : Created.                                                                 *
   1198  *=============================================================================================*/
   1199 void SidebarClass::StripClass::Init_IO(int id)
   1200 {
   1201 	ID = id;
   1202 
   1203 	UpButton[ID].IsSticky = true;
   1204 	UpButton[ID].ID = BUTTON_UP+id;
   1205 	UpButton[ID].X = X+ButtonSpacingOffset+1;
   1206 	UpButton[ID].Y = Y+MAX_VISIBLE*ObjectHeight-1;
   1207 
   1208 	UpButton[ID].Set_Shape(Hires_Retrieve("STRIPUP.SHP"));
   1209 
   1210 	DownButton[ID].IsSticky = true;
   1211 	DownButton[ID].ID = BUTTON_DOWN+id;
   1212 	DownButton[ID].X = UpButton[ID].X + UpButton[ID].Width + ButtonSpacingOffset-2;
   1213 	DownButton[ID].Y = Y+MAX_VISIBLE*ObjectHeight-1;
   1214 
   1215 	DownButton[ID].Set_Shape(Hires_Retrieve("STRIPDN.SHP"));
   1216 
   1217 	for (int index = 0; index < MAX_VISIBLE; index++) {
   1218 		SelectClass & g = SelectButton[ID][index];
   1219 		g.ID = BUTTON_SELECT;
   1220 		g.X = X;
   1221 		g.Y = Y + (ObjectHeight*index);
   1222 		g.Width = ObjectWidth;
   1223 		g.Height = ObjectHeight;
   1224 		g.Set_Owner(*this, index);
   1225 	}
   1226 
   1227 }
   1228 
   1229 
   1230 /***********************************************************************************************
   1231  * SidebarClass::StripClass::Init_Theater -- Performs theater-specific initialization          *
   1232  *                                                                                             *
   1233  * INPUT:   theater                                                                            *
   1234  *                                                                                             *
   1235  * OUTPUT:  none                                                                               *
   1236  *                                                                                             *
   1237  * WARNINGS:   none                                                                            *
   1238  *                                                                                             *
   1239  * HISTORY:                                                                                    *
   1240  *   12/24/1994 JLB : Created.                                                                 *
   1241  *=============================================================================================*/
   1242 void SidebarClass::StripClass::Init_Theater(TheaterType theater)
   1243 {
   1244 	//if (theater != LastTheater) {
   1245 
   1246 
   1247 		static char *_file[3] = {
   1248 			"ION",
   1249 			"ATOM",
   1250 			"BOMB"
   1251 		};
   1252 		int factor = Get_Resolution_Factor();
   1253 		char	fullname[_MAX_FNAME+_MAX_EXT];
   1254 		char buffer[_MAX_FNAME];
   1255 		void const * cameo_ptr;
   1256 
   1257 		for (int lp = 0; lp < 3; lp++) {
   1258 			if ( Get_Resolution_Factor() ) {
   1259 				sprintf(buffer, "%sICNH", _file[lp]);
   1260 			} else {
   1261 				sprintf(buffer, "%sICON", _file[lp]);
   1262 			}
   1263 			_makepath(fullname, NULL, NULL, buffer, Theaters[theater].Suffix);
   1264 			cameo_ptr = MixFileClass::Retrieve(fullname);
   1265 			if (cameo_ptr){
   1266 				SpecialShapes[lp] = cameo_ptr;
   1267 			}
   1268 		}
   1269 
   1270 
   1271 #ifndef _RETRIEVE
   1272 		static TLucentType const ClockCols[1] = {
   1273 //			{LTGREEN, BLACK, 0, 0},
   1274 			{GREEN, LTGREY, 180, 0}
   1275 		};
   1276 
   1277 		/*
   1278 		**	Make sure that remapping doesn't occur on the colors that cycle.
   1279 		*/
   1280 		Mem_Copy(GamePalette, OriginalPalette, 768);
   1281 		memset(&GamePalette[CYCLE_COLOR_START*3], 0x3f, CYCLE_COLOR_COUNT*3);
   1282 
   1283 		/*
   1284 		**	Create the translucent table used for the sidebar.
   1285 		*/
   1286 		Build_Translucent_Table(GamePalette, &ClockCols[0], 1, (void*)ClockTranslucentTable);
   1287 		CCFileClass(Fading_Table_Name("CLOCK", theater)).Write(ClockTranslucentTable, sizeof(ClockTranslucentTable));
   1288 		Mem_Copy(OriginalPalette, GamePalette, 768);
   1289 #else
   1290 		CCFileClass(Fading_Table_Name("CLOCK", theater)).Read(ClockTranslucentTable, sizeof(ClockTranslucentTable));
   1291 #endif
   1292 	 	LastTheater = theater;
   1293 	//}
   1294 }
   1295 
   1296 
   1297 /***********************************************************************************************
   1298  * SidebarClass::StripClass::Activate -- Adds the strip buttons to the input system.           *
   1299  *                                                                                             *
   1300  *    This routine will add the side strip buttons to the map's input system. This routine     *
   1301  *    should be called once when the sidebar activates.                                        *
   1302  *                                                                                             *
   1303  * INPUT:   none                                                                               *
   1304  *                                                                                             *
   1305  * OUTPUT:  none                                                                               *
   1306  *                                                                                             *
   1307  * WARNINGS:   Never call this routine a second time without first calling Deactivate().       *
   1308  *                                                                                             *
   1309  * HISTORY:                                                                                    *
   1310  *   01/19/1995 JLB : Created.                                                                 *
   1311  *=============================================================================================*/
   1312 void SidebarClass::StripClass::Activate(void)
   1313 {
   1314 	UpButton[ID].Zap();
   1315 	Map.Add_A_Button(UpButton[ID]);
   1316 
   1317 	DownButton[ID].Zap();
   1318 	Map.Add_A_Button(DownButton[ID]);
   1319 
   1320 	for (int index = 0; index < MAX_VISIBLE; index++) {
   1321 		SelectButton[ID][index].Zap();
   1322 		Map.Add_A_Button(SelectButton[ID][index]);
   1323 	}
   1324 }
   1325 
   1326 
   1327 /***********************************************************************************************
   1328  * SidebarClass::StripClass::Deactivate -- Removes the side strip buttons from the input syste *
   1329  *                                                                                             *
   1330  *    Call this routine to remove all the buttons on the side strip from the map's input       *
   1331  *    system.                                                                                  *
   1332  *                                                                                             *
   1333  * INPUT:   none                                                                               *
   1334  *                                                                                             *
   1335  * OUTPUT:  none                                                                               *
   1336  *                                                                                             *
   1337  * WARNINGS:   Never call this routine unless the Activate() function was prevously called.    *
   1338  *                                                                                             *
   1339  * HISTORY:                                                                                    *
   1340  *   01/19/1995 JLB : Created.                                                                 *
   1341  *=============================================================================================*/
   1342 void SidebarClass::StripClass::Deactivate(void)
   1343 {
   1344 	Map.Remove_A_Button(UpButton[ID]);
   1345 	Map.Remove_A_Button(DownButton[ID]);
   1346 	for (int index = 0; index < MAX_VISIBLE; index++) {
   1347 		Map.Remove_A_Button(SelectButton[ID][index]);
   1348 	}
   1349 }
   1350 
   1351 
   1352 #ifdef NEVER
   1353 /***********************************************************************************************
   1354  * sortfunc -- Utility routine that handles 'qsort' the strip buttons.                         *
   1355  *                                                                                             *
   1356  *    This routine is called by qsort() in order to sort the sidebar buttons. This sorting     *
   1357  *    forces the sidebar buttons to always occur in the order that they can be built in,       *
   1358  *    rather than the order that they were added to the sidebar list.                          *
   1359  *                                                                                             *
   1360  * INPUT:   ptr1  -- Pointer to the first sidebar class object.                                *
   1361  *                                                                                             *
   1362  *          ptr2  -- Pointer to the second sidebar class object.                               *
   1363  *                                                                                             *
   1364  * OUTPUT:  Returns <0 if the first object can be produced before the second. It returns       *
   1365  *          >0 if the reverse is true. It returns exactly 0 if the production scneario for     *
   1366  *          both objects is the same.                                                          *
   1367  *                                                                                             *
   1368  * WARNINGS:   none                                                                            *
   1369  *                                                                                             *
   1370  * HISTORY:                                                                                    *
   1371  *   05/18/1995 JLB : Created.                                                                 *
   1372  *=============================================================================================*/
   1373 static int sortfunc(void const * ptr1, void const * ptr2)
   1374 {
   1375 	SidebarClass::StripClass::BuildType * b1 = (SidebarClass::StripClass::BuildType *)ptr1;
   1376 	SidebarClass::StripClass::BuildType * b2 = (SidebarClass::StripClass::BuildType *)ptr2;
   1377 
   1378 	TechnoTypeClass const * p1 = Fetch_Techno_Type(b1->BuildableType, b1->BuildableID);
   1379 	TechnoTypeClass const * p2 = Fetch_Techno_Type(b2->BuildableType, b2->BuildableID);
   1380 
   1381 	int i1 = 0;
   1382 	int i2 = 0;
   1383 
   1384 	if (p1) i1 = p1->What_Am_I()*2;
   1385 	if (p2) i2 = p2->What_Am_I()*2;
   1386 
   1387 	/*
   1388 	**	Walls should be sorted after the regular buildings.
   1389 	*/
   1390 	if (p1 && p1->What_Am_I() == RTTI_BUILDINGTYPE && ((BuildingTypeClass * const)p1)->IsWall) {
   1391 		i1++;
   1392 	}
   1393 	if (p2 && p2->What_Am_I() == RTTI_BUILDINGTYPE && ((BuildingTypeClass * const)p2)->IsWall) {
   1394 		i2++;
   1395 	}
   1396 
   1397 	/*
   1398 	**	If the object types are identical, then sort by scenario available.
   1399 	*/
   1400 	if (i1 == i2) {
   1401 
   1402 		/*
   1403 		**	In the case of walls (can tell if there is an odd value), then sort
   1404 		**	by cost.
   1405 		*/
   1406 		if (i1 & 0x01) {
   1407 			i1 = p1->Cost;
   1408 			i2 = p2->Cost;
   1409 		} else {
   1410 			i1 = p1->Scenario;
   1411 			i2 = p2->Scenario;
   1412 		}
   1413 	}
   1414 
   1415 	return(i1 - i2);
   1416 }
   1417 #endif
   1418 
   1419 
   1420 /***********************************************************************************************
   1421  * SidebarClass::StripClass::Add -- Add an object to the side strip.                           *
   1422  *                                                                                             *
   1423  *    Use this routine to add a buildable object to the side strip.                            *
   1424  *                                                                                             *
   1425  * INPUT:   object   -- Pointer to the object type that can be built and is to be added to     *
   1426  *                      the side strip.                                                        *
   1427  *                                                                                             *
   1428  * OUTPUT:  bool; Was the object successfully added to the side strip? Failure could be the    *
   1429  *                result of running out of room in the side strip array or the object might    *
   1430  *                already be in the list.                                                      *
   1431  *                                                                                             *
   1432  * WARNINGS:   none.                                                                           *
   1433  *                                                                                             *
   1434  * HISTORY:                                                                                    *
   1435  *   12/31/1994 JLB : Created.                                                                 *
   1436  *   9/24/2019 3:17PM : Added via capture parameter for new sidebar functionality              *
   1437  *=============================================================================================*/
   1438 bool SidebarClass::StripClass::Add(RTTIType type, int id, bool via_capture)
   1439 {
   1440 	if (BuildableCount <= MAX_BUILDABLES) {
   1441 		for (int index = 0; index < BuildableCount; index++) {
   1442 			if (Buildables[index].BuildableType == type && Buildables[index].BuildableID == id) {
   1443 				return(false);
   1444 			}
   1445 		}
   1446 		if (!ScenarioInit && type != RTTI_SPECIAL) {
   1447 			Speak(VOX_NEW_CONSTRUCT);
   1448 		}
   1449 		Buildables[BuildableCount].BuildableType = type;
   1450 		Buildables[BuildableCount].BuildableID = id;
   1451 		Buildables[BuildableCount].BuildableViaCapture = via_capture;
   1452 		BuildableCount++;
   1453 		IsToRedraw = true;
   1454 #ifdef OBSOLETE
   1455 		if (GameToPlay == GAME_NORMAL) {
   1456 			qsort(&Buildables[0], BuildableCount, sizeof(Buildables[0]), sortfunc);
   1457 		}
   1458 #endif
   1459 		return(true);
   1460 	}
   1461 	return(false);
   1462 }
   1463 
   1464 
   1465 /***********************************************************************************************
   1466  * SidebarClass::StripClass::Scroll -- Causes the side strip to scroll.                        *
   1467  *                                                                                             *
   1468  *    Use this routine to flag the side strip to scroll. The direction scrolled is controlled  *
   1469  *    by the parameter. Scrolling is merely initiated by this routine. Subsequent calls to     *
   1470  *    the AI function and the Draw_It function are required to properly give the appearence    *
   1471  *    of scrolling.                                                                            *
   1472  *                                                                                             *
   1473  * INPUT:   bool; Should the side strip scroll UP? If it is to scroll down then pass false.    *
   1474  *                                                                                             *
   1475  * OUTPUT:  bool; Was the side strip started to scroll in the desired direction?               *
   1476  *                                                                                             *
   1477  * WARNINGS:   none                                                                            *
   1478  *                                                                                             *
   1479  * HISTORY:                                                                                    *
   1480  *   12/31/1994 JLB : Created.                                                                 *
   1481  *   07/29/1995 JLB : Simplified scrolling logic.                                              *
   1482  *=============================================================================================*/
   1483 bool SidebarClass::StripClass::Scroll(bool up)
   1484 {
   1485 	if (up) {
   1486 		Scroller--;
   1487 	} else {
   1488 		Scroller++;
   1489 	}
   1490 #ifdef NEVER
   1491 	if (BuildableCount <= MAX_VISIBLE) return(false);
   1492 
   1493 	/*
   1494 	**	Top of list is moving toward lower ordered entries in the object list. It looks like
   1495 	**	the "window" to the object list is moving up even though the actual object images are
   1496 	**	scrolling downward.
   1497 	*/
   1498 	if (up) {
   1499 		if (!TopIndex) return(false);
   1500 
   1501 		TopIndex--;
   1502 		Slid = 0;
   1503 	} else {
   1504 		if (TopIndex+MAX_VISIBLE >= BuildableCount) return(false);
   1505 
   1506 		Slid = ObjectHeight;
   1507 	}
   1508 	IsScrollingDown = !up;
   1509 	IsScrolling = true;
   1510 #endif
   1511 	return(true);
   1512 }
   1513 
   1514 
   1515 /***********************************************************************************************
   1516  * SidebarClass::StripClass::Flag_To_Redra -- Flags the sidebar strip to be redrawn.           *
   1517  *                                                                                             *
   1518  *    This utility routine is called when something changes on the sidebar and it must be      *
   1519  *    reflected the next time drawing is performed.                                            *
   1520  *                                                                                             *
   1521  * INPUT:   none                                                                               *
   1522  *                                                                                             *
   1523  * OUTPUT:  none                                                                               *
   1524  *                                                                                             *
   1525  * WARNINGS:   none                                                                            *
   1526  *                                                                                             *
   1527  * HISTORY:                                                                                    *
   1528  *   05/18/1995 JLB : Created.                                                                 *
   1529  *=============================================================================================*/
   1530 void SidebarClass::StripClass::Flag_To_Redraw(void)
   1531 {
   1532 	IsToRedraw = true;
   1533 	//Map.SidebarClass::IsToRedraw = true;
   1534 	Map.Flag_To_Redraw(false);
   1535 }
   1536 
   1537 
   1538 /***********************************************************************************************
   1539  * SidebarClass::StripClass::AI -- Input and AI processing for the side strip.                 *
   1540  *                                                                                             *
   1541  *    The side strip AI processing is performed by this function. This function not only       *
   1542  *    checks for player input, but also handles any graphic logic updating necessary as a      *
   1543  *    result of flashing or construction animation.                                            *
   1544  *                                                                                             *
   1545  * INPUT:   input -- The player input code.                                                    *
   1546  *                                                                                             *
   1547  *          x,y   -- Mouse coordinate to use.                                                  *
   1548  *                                                                                             *
   1549  * OUTPUT:  bool; Did the AI detect that it will need a rendering change? If this routine      *
   1550  *                returns true, then the Draw_It function should be called at the              *
   1551  *                earliest opportunity.                                                        *
   1552  *                                                                                             *
   1553  * WARNINGS:   none                                                                            *
   1554  *                                                                                             *
   1555  * HISTORY:                                                                                    *
   1556  *   12/31/1994 JLB : Created.                                                                 *
   1557  *   12/31/1994 JLB : Uses mouse coordinate parameters.                                        *
   1558  *=============================================================================================*/
   1559 bool SidebarClass::StripClass::AI(KeyNumType & input, int , int )
   1560 {
   1561 	bool redraw = false;
   1562 
   1563 	/*
   1564 	**	If this is scroll button for this side strip, then scroll the strip as
   1565 	**	indicated.
   1566 	*/
   1567 	if (input == (UpButton[ID].ID|KN_BUTTON)) {	// && !IsScrolling
   1568 		UpButton[ID].IsPressed = false;
   1569 		Scroll(true);
   1570 	}
   1571 	if (input == (DownButton[ID].ID|KN_BUTTON)) {	// && !IsScrolling
   1572 		DownButton[ID].IsPressed = false;
   1573 		Scroll(false);
   1574 	}
   1575 
   1576 	/*
   1577 	**	Reflect the scroll desired direction/value into the scroll
   1578 	**	logic handler. This might result in up or down scrolling.
   1579 	*/
   1580 	if (!IsScrolling && Scroller) {
   1581 		if (BuildableCount <= MAX_VISIBLE) {
   1582 			Scroller = 0;
   1583 		} else {
   1584 
   1585 			/*
   1586 			**	Top of list is moving toward lower ordered entries in the object list. It looks like
   1587 			**	the "window" to the object list is moving up even though the actual object images are
   1588 			**	scrolling downward.
   1589 			*/
   1590 			if (Scroller < 0) {
   1591 				if (!TopIndex) {
   1592 					Scroller = 0;
   1593 				} else {
   1594 					Scroller++;
   1595 					IsScrollingDown = false;
   1596 					IsScrolling = true;
   1597 					TopIndex--;
   1598 					Slid = 0;
   1599 				}
   1600 
   1601 			} else {
   1602 				if (TopIndex+MAX_VISIBLE >= BuildableCount) {
   1603 					Scroller = 0;
   1604 				} else {
   1605 					Scroller--;
   1606 					Slid = ObjectHeight;
   1607 					IsScrollingDown = true;
   1608 					IsScrolling = true;
   1609 				}
   1610 			}
   1611 		}
   1612 	}
   1613 
   1614 	/*
   1615 	**	Scroll logic is handled here.
   1616 	*/
   1617 	if (IsScrolling) {
   1618 		if (IsScrollingDown) {
   1619 			Slid -= SCROLL_RATE;
   1620 			if (Slid <= 0) {
   1621 				IsScrolling = false;
   1622 				Slid = 0;
   1623 				TopIndex++;
   1624 			}
   1625 		} else {
   1626 			Slid += SCROLL_RATE;
   1627 			if (Slid >= ObjectHeight) {
   1628 				IsScrolling = false;
   1629 				Slid = 0;
   1630 			}
   1631 		}
   1632 		redraw = true;
   1633 	}
   1634 
   1635 	/*
   1636 	**	Handle any flashing logic. Flashing occurs when the player selects an object
   1637 	**	and provides the visual feedback of a recognized and legal selection.
   1638 	*/
   1639 	if (Flasher != -1) {
   1640 		if (Graphic_Logic()) {
   1641 			redraw = true;
   1642 			if (Fetch_Stage() >= 7) {
   1643 				Set_Rate(0);
   1644 				Set_Stage(0);
   1645 				Flasher = -1;
   1646 			}
   1647 		}
   1648 	}
   1649 
   1650 	/*
   1651 	**	Handle any building clock animation logic.
   1652 	*/
   1653 	if (IsBuilding) {
   1654 		for (int index = 0; index < BuildableCount; index++) {
   1655 			int factoryid = Buildables[index].Factory;
   1656 
   1657 			if (factoryid != -1) {
   1658 				FactoryClass * factory = Factories.Raw_Ptr(factoryid);
   1659 
   1660 				if (factory && (factory->Has_Changed() || factory->Is_Blocked())) {
   1661 					redraw = true;
   1662 					if (factory->Has_Completed()) {
   1663 
   1664 						/*
   1665 						**	Construction has been completed. Announce this fact to the player and
   1666 						**	try to get the object to automatically leave the factory. Buildings are
   1667 						**	the main exception to the ability to leave the factory under their own
   1668 						**	power.
   1669 						*/
   1670 						TechnoClass * pending = factory->Get_Object();
   1671 						if (pending) {
   1672 							switch (pending->What_Am_I()) {
   1673 								case RTTI_UNIT:
   1674 								case RTTI_AIRCRAFT:
   1675 									OutList.Add(EventClass(EventClass::PLACE, pending->What_Am_I(), -1));
   1676 									// Fall into next case.
   1677 
   1678 								case RTTI_BUILDING:
   1679 									if (!factory->Is_Blocked()) {
   1680 										Speak(VOX_CONSTRUCTION);
   1681 									}
   1682 									break;
   1683 
   1684 								case RTTI_INFANTRY:
   1685 									OutList.Add(EventClass(EventClass::PLACE, pending->What_Am_I(), -1));
   1686 									if (!factory->Is_Blocked()) {
   1687 										Speak(VOX_UNIT_READY);
   1688 									}
   1689 									break;
   1690 							}
   1691 						}
   1692 					}
   1693 				}
   1694 			}
   1695 		}
   1696 	}
   1697 
   1698 	/*
   1699 	**	If any of the logic determined that this side strip needs to be redrawn, then
   1700 	**	set the redraw flag for this side strip.
   1701 	*/
   1702 	if (redraw) {
   1703 		Flag_To_Redraw();
   1704 	}
   1705 	return(redraw);
   1706 }
   1707 
   1708 
   1709 /***********************************************************************************************
   1710  * SidebarClass::StripClass::Draw_It -- Render the sidebar display.                            *
   1711  *                                                                                             *
   1712  *    Use this routine to render the sidebar display. It checks to see if it needs to be       *
   1713  *    redrawn and only redraw if necessary. If the "complete" parameter is true, then it       *
   1714  *    will force redraw the entire strip.                                                      *
   1715  *                                                                                             *
   1716  * INPUT:   complete -- Should the redraw be forced? A force redraw will ignore the redraw     *
   1717  *                      flag.                                                                  *
   1718  *                                                                                             *
   1719  * OUTPUT:  none                                                                               *
   1720  *                                                                                             *
   1721  * WARNINGS:   none                                                                            *
   1722  *                                                                                             *
   1723  * HISTORY:                                                                                    *
   1724  *   12/31/1994 JLB : Created.                                                                 *
   1725  *   08/06/1995 JLB : Handles multi factory tracking in same strip.                            *
   1726  *=============================================================================================*/
   1727 void SidebarClass::StripClass::Draw_It(bool complete)
   1728 {
   1729 	if (IsToRedraw || complete) {
   1730 		IsToRedraw = false;
   1731 
   1732 		/*
   1733 		**	Fills the background to the side strip. We shouldnt need to do this if the strip
   1734 		** has a full complement of icons.	ST - 10/7/96 6:03PM
   1735 		*/
   1736 		if (BuildableCount < MAX_VISIBLE){
   1737 			CC_Draw_Shape(LogoShapes, ID,	X+3,	Y-1,	WINDOW_MAIN, SHAPE_WIN_REL|SHAPE_NORMAL,	0);
   1738 		}
   1739 
   1740 		/*
   1741 		**	Redraw the scroll buttons.
   1742 		*/
   1743 		UpButton[ID].Draw_Me(true);
   1744 		DownButton[ID].Draw_Me(true);
   1745 
   1746 		/*
   1747 		**	Loop through all the buildable objects that are visible in the strip and render
   1748 		**	them. Their Y offset may be adjusted if the strip is in the process of scrolling.
   1749 		*/
   1750 		for (int i = 0; i < MAX_VISIBLE + (IsScrolling ? 1 : 0); i++) {
   1751 			bool production;
   1752 			bool completed;
   1753 			int  stage;
   1754 			bool darken = false;
   1755 			void const * shapefile = 0;
   1756 			int shapenum = 0;
   1757 			void const * remapper = 0;
   1758 			FactoryClass * factory = 0;
   1759 			int index = i+TopIndex;
   1760 			int x = X;
   1761 			int y = Y + i*ObjectHeight;
   1762 			y--;
   1763 
   1764 			/*
   1765 			**	If the strip is scrolling, then the offset is adjusted accordingly.
   1766 			*/
   1767 			if (IsScrolling) {
   1768 				y -= ObjectHeight - Slid;
   1769 			}
   1770 
   1771 			/*
   1772 			**	Fetch the shape number for the object type located at this current working
   1773 			**	slot. This shape pointer is used to draw the underlying graphic there.
   1774 			*/
   1775 			if (index < BuildableCount) {
   1776 				ObjectTypeClass const * obj = NULL;
   1777 				int spc  = 0;
   1778 
   1779 				if (Buildables[index].BuildableType != RTTI_SPECIAL) {
   1780 
   1781 					obj = Fetch_Techno_Type(Buildables[index].BuildableType, Buildables[index].BuildableID);
   1782 					if (obj) {
   1783 						bool isbusy = false;
   1784 						switch (Buildables[index].BuildableType) {
   1785 							case RTTI_INFANTRYTYPE:
   1786 								isbusy = (PlayerPtr->InfantryFactory != -1);
   1787 								break;
   1788 
   1789 							case RTTI_BUILDINGTYPE:
   1790 								isbusy = (PlayerPtr->BuildingFactory != -1);
   1791 								if (!BuildingTypeClass::As_Reference((StructType)Buildables[index].BuildableID).IsWall) {
   1792 									remapper = PlayerPtr->Remap_Table(false, false);
   1793 								}
   1794 								break;
   1795 
   1796 							case RTTI_UNITTYPE:
   1797 								isbusy = (PlayerPtr->UnitFactory != -1);
   1798 								switch (Buildables[index].BuildableID) {
   1799 									case UNIT_MCV:
   1800 									case UNIT_HARVESTER:
   1801 										remapper = PlayerPtr->Remap_Table(false, false);
   1802 										break;
   1803 
   1804 									default:
   1805 										remapper = PlayerPtr->Remap_Table(false, true);
   1806 										break;
   1807 								}
   1808 								break;
   1809 
   1810 							case RTTI_AIRCRAFTTYPE:
   1811 								isbusy = (PlayerPtr->AircraftFactory != -1);
   1812 								remapper = PlayerPtr->Remap_Table(false, true);
   1813 								break;
   1814 						}
   1815 						shapefile = obj->Get_Cameo_Data();
   1816 						shapenum  = 0;
   1817 						if (Buildables[index].Factory != -1) {
   1818 							factory 		= Factories.Raw_Ptr(Buildables[index].Factory);
   1819 							production	= true;
   1820 							completed	= factory->Has_Completed();
   1821 							stage			= factory->Completion();
   1822 							darken		= false;
   1823 						} else {
   1824 							production  = false;
   1825 //							darken      = IsBuilding;
   1826 
   1827 							/*
   1828 							**	Darken the imagery if a factory of a matching type is
   1829 							**	already busy.
   1830 							*/
   1831 							darken = isbusy;
   1832 						}
   1833 					}
   1834 
   1835 				} else  {
   1836 
   1837 					spc = Buildables[index].BuildableID;
   1838 					shapefile = Get_Special_Cameo(spc - 1);
   1839 					shapenum = 0;
   1840 
   1841 					switch (spc) {
   1842 						case SPC_ION_CANNON:
   1843 							production = true;
   1844 							completed = PlayerPtr->IonCannon.Is_Ready();
   1845 							stage = PlayerPtr->IonCannon.Anim_Stage();
   1846 							darken = false;
   1847 							break;
   1848 
   1849 						case SPC_AIR_STRIKE:
   1850 							production = true;
   1851 							completed = PlayerPtr->AirStrike.Is_Ready();
   1852 							stage = PlayerPtr->AirStrike.Anim_Stage();
   1853 							darken = false;
   1854 							break;
   1855 
   1856 						case SPC_NUCLEAR_BOMB:
   1857 							production = true;
   1858 							completed = PlayerPtr->NukeStrike.Is_Ready();
   1859 							stage = PlayerPtr->NukeStrike.Anim_Stage();
   1860 							darken = false;
   1861 							break;
   1862 					}
   1863 				}
   1864 
   1865 				if (obj || spc) {
   1866 					/*
   1867 					** If this item is flashing then take care of it.
   1868 					**
   1869 					*/
   1870 					if (Flasher == index && (Fetch_Stage() & 0x01)) {
   1871 						remapper = Map.FadingLight;
   1872 					}
   1873 
   1874 				} else {
   1875 					shapefile	= LogoShapes;
   1876 					shapenum		= SB_BLANK;
   1877 				}
   1878 			} else {
   1879 				shapefile	= LogoShapes;
   1880 				shapenum		= SB_BLANK;
   1881 				production	= false;
   1882 			}
   1883 
   1884 			remapper = 0;
   1885 
   1886 			/*
   1887 			**	Now that the shape of the object at the current working slot has been found,
   1888 			**	draw it and any graphic overlays as necessary.
   1889 			**
   1890 			** Dont draw blank shapes over the new 640x400 sidebar art - ST 5/1/96 6:01PM
   1891 			*/
   1892 			if (shapenum != SB_BLANK || shapefile != LogoShapes){
   1893 				IsTheaterShape = true;	// This shape is theater specific
   1894 				CC_Draw_Shape(shapefile, shapenum,
   1895 					x-(WindowList[WINDOW_SIDEBAR][WINDOWX]*8)+LeftEdgeOffset,
   1896 					y-WindowList[WINDOW_SIDEBAR][WINDOWY],
   1897 					WINDOW_SIDEBAR,
   1898 					SHAPE_NORMAL|SHAPE_WIN_REL| (remapper ? SHAPE_FADING : SHAPE_NORMAL),
   1899 					remapper);
   1900 				IsTheaterShape = false;
   1901 
   1902 
   1903 				/*
   1904 				**	Darken this object because it cannot be produced or is otherwise
   1905 				**	unavailable.
   1906 				*/
   1907 				if (darken) {
   1908 					CC_Draw_Shape(ClockShapes, 0,
   1909 							x-(WindowList[WINDOW_SIDEBAR][WINDOWX]*8)+LeftEdgeOffset,
   1910 							y-WindowList[WINDOW_SIDEBAR][WINDOWY],
   1911 							WINDOW_SIDEBAR,
   1912 							SHAPE_NORMAL|SHAPE_WIN_REL|SHAPE_GHOST,
   1913 							NULL, ClockTranslucentTable);
   1914 				}
   1915 			}
   1916 
   1917 			/*
   1918 			**	Draw the overlapping clock shape if this is object is being constructed.
   1919 			**	If the object is completed, then display "Ready" with no clock shape.
   1920 			*/
   1921 			if (production) {
   1922 				if (completed) {
   1923 
   1924 					/*
   1925 					**	Display text showing that the object is ready to place.
   1926 					*/
   1927 					CC_Draw_Shape(ObjectTypeClass::PipShapes, PIP_READY,
   1928 					(x-(WindowList[WINDOW_SIDEBAR][WINDOWX]*8))+LeftEdgeOffset+(ObjectWidth >> 1),
   1929 					(y-WindowList[WINDOW_SIDEBAR][WINDOWY])+ObjectHeight-Get_Build_Frame_Height(ObjectTypeClass::PipShapes) -8,
   1930 					WINDOW_SIDEBAR, SHAPE_CENTER);
   1931 //					Fancy_Text_Print(TXT_READY, x+TEXT_X_OFFSET, y+TEXT_Y_OFFSET, TEXT_COLOR, TBLACK, TPF_6POINT|TPF_CENTER|TPF_NOSHADOW);
   1932 				} else {
   1933 					CC_Draw_Shape(ClockShapes, stage+1,
   1934 							x-(WindowList[WINDOW_SIDEBAR][WINDOWX]*8)+LeftEdgeOffset,
   1935 							y-WindowList[WINDOW_SIDEBAR][WINDOWY],
   1936 							WINDOW_SIDEBAR,
   1937 							SHAPE_NORMAL|SHAPE_WIN_REL|SHAPE_GHOST,
   1938 							NULL, ClockTranslucentTable);
   1939 					/*
   1940 					**	Display text showing that the construction is temporarily on hold.
   1941 					*/
   1942 					if (factory && !factory->Is_Building()) {
   1943 						CC_Draw_Shape(ObjectTypeClass::PipShapes, PIP_HOLDING,
   1944 						(x-(WindowList[WINDOW_SIDEBAR][WINDOWX]*8))+LeftEdgeOffset+(ObjectWidth >> 1),
   1945 						(y-WindowList[WINDOW_SIDEBAR][WINDOWY])+ObjectHeight-Get_Build_Frame_Height(ObjectTypeClass::PipShapes) - 8,  // Moved up now that icons have names on them
   1946 						WINDOW_SIDEBAR, SHAPE_CENTER);
   1947 //						Fancy_Text_Print(TXT_HOLDING, x+TEXT_X_OFFSET, y+TEXT_Y_OFFSET, TEXT_COLOR, TBLACK, TPF_6POINT|TPF_CENTER|TPF_NOSHADOW);
   1948 					}
   1949 				}
   1950 			}
   1951 		}
   1952 	}
   1953 }
   1954 
   1955 
   1956 /***********************************************************************************************
   1957  * SidebarClass::StripClass::Recalc -- Revalidates the current sidebar list of objects.        *
   1958  *                                                                                             *
   1959  *    This routine will revalidate all the buildable objects in the sidebar. This routine      *
   1960  *    comes in handy when a factory has been destroyed, and the sidebar needs to reflect any   *
   1961  *    change that this requires. It checks every object to see if there is a factory available *
   1962  *    that could produce it. If none can be found, then the object is removed from the         *
   1963  *    sidebar.                                                                                 *
   1964  *                                                                                             *
   1965  * INPUT:   none                                                                               *
   1966  *                                                                                             *
   1967  * OUTPUT:  bool; The sidebar has changed as a result of this call?                            *
   1968  *                                                                                             *
   1969  * WARNINGS:   none                                                                            *
   1970  *                                                                                             *
   1971  * HISTORY:                                                                                    *
   1972  *   01/19/1995 JLB : Created.                                                                 *
   1973  *   06/26/1995 JLB : Doesn't collapse sidebar when buildables removed.                        *
   1974  *=============================================================================================*/
   1975 bool SidebarClass::StripClass::Recalc(void)
   1976 {
   1977 	int ok;
   1978 
   1979 	if (Debug_Map || !BuildableCount) {
   1980 		return(false);
   1981 	}
   1982 
   1983 	/*
   1984 	**	Sweep through all objects listed in the sidebar. If any of those object can
   1985 	**	not be created -- even in theory -- then they must be removed form the sidebar and
   1986 	**	any current production must be abandoned.
   1987 	*/
   1988 	bool redraw = false;
   1989 	for (int index = 0; index < BuildableCount; index++) {
   1990 		TechnoTypeClass const * tech = Fetch_Techno_Type(Buildables[index].BuildableType, Buildables[index].BuildableID);
   1991 		if (tech) {
   1992 			ok = tech->Who_Can_Build_Me(true, false, PlayerPtr->Class->House) != NULL;
   1993 		} else {
   1994 			switch (Buildables[index].BuildableID) {
   1995 				case SPC_ION_CANNON:
   1996 					ok = PlayerPtr->IonCannon.Is_Present();
   1997 					break;
   1998 
   1999 				case SPC_NUCLEAR_BOMB:
   2000 					ok = PlayerPtr->NukeStrike.Is_Present();
   2001 					break;
   2002 
   2003 				case SPC_AIR_STRIKE:
   2004 					ok = PlayerPtr->AirStrike.Is_Present();
   2005 					break;
   2006 
   2007 				default:
   2008 					ok = false;
   2009 					break;
   2010 			}
   2011 
   2012 #ifdef OBSOLETE
   2013 		} else {
   2014 			switch (Buildables[index].BuildableID) {
   2015 				case SPC_ION_CANNON:
   2016 					ok = (PlayerPtr->BScan & STRUCTF_EYE) != 0 || PlayerPtr->IonOneTimeFlag;
   2017 					if (!ok) {
   2018 						PlayerPtr->Remove_Ion_Cannon();
   2019 					}
   2020 					break;
   2021 
   2022 				case SPC_NUCLEAR_BOMB:
   2023 					ok  = (PlayerPtr->BScan & STRUCTF_TEMPLE) != 0 && PlayerPtr->Has_Nuke_Device();
   2024 					ok  = ok || PlayerPtr->NukeOneTimeFlag;
   2025 					if (!ok) {
   2026 						PlayerPtr->Remove_Nuke_Bomb();
   2027 					}
   2028 					break;
   2029 
   2030 				case SPC_AIR_STRIKE:
   2031 //					ok = (PlayerPtr->BScan & STRUCTF_SAM) == 0;
   2032 //					ok = !PlayerPtr->Does_Enemy_Building_Exist(STRUCT_SAM);
   2033 					ok = (PlayerPtr->AirPresent /*&& !PlayerPtr->Does_Enemy_Building_Exist(STRUCT_SAM)*/) || PlayerPtr->AirOneTimeFlag;
   2034 					if (!ok) {
   2035 						PlayerPtr->Remove_Air_Strike();
   2036 					}
   2037 					break;
   2038 
   2039 				default:
   2040 					ok = false;
   2041 					break;
   2042 			}
   2043 #endif
   2044 		}
   2045 
   2046 		if (!ok) {
   2047 
   2048 			/*
   2049 			**	If there was something in production, then abandon it before deleting the
   2050 			**	factory manager.
   2051 			*/
   2052 			//if (Buildables[index].Factory != -1) {
   2053 				//FactoryClass * factory = Factories.Raw_Ptr(Buildables[index].Factory);
   2054 				//factory->Abandon();
   2055 				//delete factory;
   2056 				//Buildables[index].Factory = -1;
   2057 			//}
   2058 //			Buildables[index].Factory = -1;
   2059 
   2060 			/*
   2061 			**	Removes this entry from the list.
   2062 			*/
   2063 			if (BuildableCount > 1 && index < BuildableCount-1) {
   2064 				memcpy(&Buildables[index], &Buildables[index+1], sizeof(Buildables[0])*((BuildableCount-index)-1));
   2065 			}
   2066 			TopIndex = 0;
   2067 			IsToRedraw = true;
   2068 			redraw = true;
   2069 			BuildableCount--;
   2070 			index--;
   2071 		}
   2072 	}
   2073 
   2074 #ifdef NEVER
   2075 	/*
   2076 	**	If there are no more buildable objects to display, make the sidebar go away.
   2077 	*/
   2078 	if (!BuildableCount) {
   2079 		Map.SidebarClass::Activate(0);
   2080 	}
   2081 #endif
   2082 	return(redraw);
   2083 }
   2084 
   2085 
   2086 /***********************************************************************************************
   2087  * SidebarClass::StripClass::SelectClass::SelectClass -- Default constructor.                  *
   2088  *                                                                                             *
   2089  *    This is the default constructor for the button that controls the buildable cameos on     *
   2090  *    the sidebar strip.                                                                       *
   2091  *                                                                                             *
   2092  * INPUT:   none                                                                               *
   2093  *                                                                                             *
   2094  * OUTPUT:  none                                                                               *
   2095  *                                                                                             *
   2096  * WARNINGS:   The coordinates are set to zero by this routine. They must be set to the        *
   2097  *             correct values before this button will function.                                *
   2098  *                                                                                             *
   2099  * HISTORY:                                                                                    *
   2100  *   01/19/1995 JLB : Created.                                                                 *
   2101  *=============================================================================================*/
   2102 SidebarClass::StripClass::SelectClass::SelectClass(void) :
   2103 	ControlClass(0, 0, 0, 0, 0, LEFTPRESS|RIGHTPRESS|LEFTUP)
   2104 {
   2105 	int factor = Get_Resolution_Factor();
   2106 
   2107 	Strip = 0;
   2108 	Index = 0;
   2109 	Width = StripClass::OBJECT_WIDTH << factor;
   2110 	Height = StripClass::OBJECT_HEIGHT << factor;
   2111 }
   2112 
   2113 
   2114 /***********************************************************************************************
   2115  * SidebarClass::StripClass::SelectClass:: -- Assigns special values to a buildable select but *
   2116  *                                                                                             *
   2117  *    Use this routine to set custom buildable vars for this particular select button. It      *
   2118  *    uses this information to properly know what buildable object to start or stop production *
   2119  *    on.                                                                                      *
   2120  *                                                                                             *
   2121  * INPUT:   strip    -- Reference to the strip that owns this buildable button.                *
   2122  *                                                                                             *
   2123  *          index    -- The index (0 .. MAX_VISIBLE-1) of this button. This is used to let     *
   2124  *                      the owning strip know what index this button refers to.                *
   2125  *                                                                                             *
   2126  * OUTPUT:  none                                                                               *
   2127  *                                                                                             *
   2128  * WARNINGS:   none                                                                            *
   2129  *                                                                                             *
   2130  * HISTORY:                                                                                    *
   2131  *   01/19/1995 JLB : Created.                                                                 *
   2132  *=============================================================================================*/
   2133 void SidebarClass::StripClass::SelectClass::Set_Owner(StripClass & strip, int index)
   2134 {
   2135 	int factor = Get_Resolution_Factor();
   2136 	Strip = &strip;
   2137 	Index = index;
   2138 	X = strip.X;
   2139 	Y = strip.Y + (index * (StripClass::OBJECT_HEIGHT << factor));
   2140 }
   2141 
   2142 
   2143 /***********************************************************************************************
   2144  * SidebarClass::StripClass::SelectClass:: -- Action function when buildable cameo is selected *
   2145  *                                                                                             *
   2146  *    This function is called when the buildable icon (cameo) is clicked on. It handles        *
   2147  *    starting and stopping production as indicated.                                           *
   2148  *                                                                                             *
   2149  * INPUT:   flags -- The input event that triggered the call.                                  *
   2150  *                                                                                             *
   2151  *          key   -- The keyboard value at the time of the input.                              *
   2152  *                                                                                             *
   2153  * OUTPUT:  Returns with whether the input list should be scanned further.                     *
   2154  *                                                                                             *
   2155  * WARNINGS:   none                                                                            *
   2156  *                                                                                             *
   2157  * HISTORY:                                                                                    *
   2158  *   01/19/1995 JLB : Created.                                                                 *
   2159  *=============================================================================================*/
   2160 int SidebarClass::StripClass::SelectClass::Action(unsigned flags, KeyNumType & key)
   2161 {
   2162 	int index = Strip->TopIndex + Index;
   2163 	RTTIType otype = Strip->Buildables[index].BuildableType;
   2164 	int oid = Strip->Buildables[index].BuildableID;
   2165 	int fnumber = Strip->Buildables[index].Factory;
   2166 
   2167 	FactoryClass * factory = NULL;
   2168 	ObjectTypeClass const * choice = NULL;
   2169 	int spc = 0;
   2170 
   2171 	/*
   2172 	**	Determine the factory number that would apply to objects of the type
   2173 	**	the mouse is currently addressing. This doesn't mean that the factory number
   2174 	**	fetched is actually producing the indicated object, merely that that particular
   2175 	**	kind of factory is specified by the "genfactory" value. This can be used to see
   2176 	**	if the factory type is currently busy or not.
   2177 	*/
   2178 	int genfactory = -1;
   2179 	switch (otype) {
   2180 		case RTTI_INFANTRYTYPE:
   2181 			genfactory = PlayerPtr->InfantryFactory;
   2182 			break;
   2183 
   2184 		case RTTI_UNITTYPE:
   2185 			genfactory = PlayerPtr->UnitFactory;
   2186 			break;
   2187 
   2188 		case RTTI_AIRCRAFTTYPE:
   2189 			genfactory = PlayerPtr->AircraftFactory;
   2190 			break;
   2191 
   2192 		case RTTI_BUILDINGTYPE:
   2193 			genfactory = PlayerPtr->BuildingFactory;
   2194 			break;
   2195 
   2196 		default:
   2197 			genfactory = -1;
   2198 			break;
   2199 	}
   2200 
   2201 	Map.Override_Mouse_Shape(MOUSE_NORMAL);
   2202 
   2203 	if (index < Strip->BuildableCount) {
   2204 		if (otype != RTTI_SPECIAL) {
   2205 			choice  = Fetch_Techno_Type(otype, oid);
   2206 		} else {
   2207 			spc = oid;
   2208 		}
   2209 
   2210 		if (fnumber != -1) {
   2211 			factory = Factories.Raw_Ptr(fnumber);
   2212 		}
   2213 
   2214   	} else {
   2215   		Map.Help_Text(TXT_NONE);
   2216   	}
   2217 
   2218 	if (spc) {
   2219 		/*
   2220 		**	Display the help text if the mouse is over the button.
   2221 		*/
   2222 		if (flags & LEFTUP) {
   2223 			switch (spc) {
   2224 				case SPC_ION_CANNON:
   2225 					Map.Help_Text(TXT_ION_CANNON, X, Y, CC_GREEN, true);
   2226 					break;
   2227 
   2228 				case SPC_NUCLEAR_BOMB:
   2229 					Map.Help_Text(TXT_NUKE_STRIKE, X, Y, CC_GREEN, true);
   2230 					break;
   2231 
   2232 				case SPC_AIR_STRIKE:
   2233 					Map.Help_Text(TXT_AIR_STRIKE, X, Y, CC_GREEN, true);
   2234 					break;
   2235 			}
   2236 			flags &= ~LEFTUP;
   2237 		}
   2238 
   2239 		/*
   2240 		**	A right mouse button signals "cancel".  If we are in targetting
   2241 		** mode then we don't want to be any more.
   2242 		*/
   2243 		if (flags & RIGHTPRESS) {
   2244 			Map.IsTargettingMode = false;
   2245 		}
   2246 		/*
   2247 		**	A left mouse press signal "activate".  If our weapon type is
   2248 		** available then we should activate it.
   2249 		*/
   2250 		if (flags & LEFTPRESS) {
   2251 			switch (spc) {
   2252 				case SPC_ION_CANNON:
   2253 					if (PlayerPtr->IonCannon.Is_Ready()) {
   2254 						Map.IsTargettingMode = spc;
   2255 						Unselect_All();
   2256 						Speak(VOX_SELECT_TARGET);
   2257 					} else {
   2258 						PlayerPtr->IonCannon.Impatient_Click();
   2259 					}
   2260 					break;
   2261 
   2262 				case SPC_AIR_STRIKE:
   2263 					if (PlayerPtr->AirStrike.Is_Ready()) {
   2264 						Map.IsTargettingMode = spc;
   2265 						Unselect_All();
   2266 						Speak(VOX_SELECT_TARGET);
   2267 					} else {
   2268 						PlayerPtr->AirStrike.Impatient_Click();
   2269 					}
   2270 					break;
   2271 
   2272 				case SPC_NUCLEAR_BOMB:
   2273 					if (PlayerPtr->NukeStrike.Is_Ready()) {
   2274 						Map.IsTargettingMode = spc;
   2275 						Unselect_All();
   2276 						Speak(VOX_SELECT_TARGET);
   2277 					} else {
   2278 						PlayerPtr->NukeStrike.Impatient_Click();
   2279 					}
   2280 					break;
   2281 			}
   2282 		}
   2283 
   2284 	} else {
   2285 
   2286 		if (choice) {
   2287 
   2288 			/*
   2289 			**	Display the help text if the mouse is over the button.
   2290 			*/
   2291 			if (flags & LEFTUP) {
   2292 				Map.Help_Text(choice->Full_Name(), X, Y, CC_GREEN, true, choice->Cost_Of() * PlayerPtr->CostBias);
   2293 				flags &= ~LEFTUP;
   2294 			}
   2295 
   2296 			/*
   2297 			**	A right mouse button signals "cancel".
   2298 			*/
   2299 			if (flags & RIGHTPRESS) {
   2300 
   2301 				/*
   2302 				**	If production is in progress, put it on hold. If production is already
   2303 				**	on hold, then abandon it. Money will be refunded, the factory
   2304 				**	manager deleted, and the object under construction is returned to
   2305 				**	the free pool.
   2306 				*/
   2307 				if (factory) {
   2308 
   2309 					/*
   2310 					**	Cancels placement mode if the sidebar factory is abandoned or
   2311 					**	suspended.
   2312 					*/
   2313 					if (Map.PendingObjectPtr && Map.PendingObjectPtr->Is_Techno()) {
   2314 						Map.PendingObjectPtr = 0;
   2315 						Map.PendingObject = 0;
   2316 						Map.PendingHouse = HOUSE_NONE;
   2317 						Map.Set_Cursor_Shape(0);
   2318 					}
   2319 
   2320 					if (!factory->Is_Building()) {
   2321 						Speak(VOX_CANCELED);
   2322 						OutList.Add(EventClass(EventClass::ABANDON, otype, oid));
   2323 					} else {
   2324 						Speak(VOX_SUSPENDED);
   2325 						OutList.Add(EventClass(EventClass::SUSPEND, otype, oid));
   2326 					}
   2327 				}
   2328 			}
   2329 
   2330 			if (flags & LEFTPRESS) {
   2331 
   2332 				/*
   2333 				**	If there is already a factory attached to this strip but the player didn't click
   2334 				**	on the icon that has the attached factory, then say that the factory is busy and
   2335 				**	ignore the click.
   2336 				*/
   2337 				if (fnumber == -1 && genfactory != -1) {
   2338 					Speak(VOX_NO_FACTORY);
   2339 					ControlClass::Action(flags, key);
   2340 					return(true);
   2341 				}
   2342 
   2343 				if (factory) {
   2344 
   2345 					/*
   2346 					**	If this object is currently being built, then give a scold sound and text and then
   2347 					**	bail.
   2348 					*/
   2349 					if (factory->Is_Building()) {
   2350 						Speak(VOX_NO_FACTORY);
   2351 					} else {
   2352 
   2353 						/*
   2354 						**	If production has completed, then attempt to have the object exit
   2355 						**	the factory or go into placement mode.
   2356 						*/
   2357 						if (factory->Has_Completed()) {
   2358 
   2359 							TechnoClass * pending = factory->Get_Object();
   2360 							if (!pending && factory->Get_Special_Item()) {
   2361 								Map.IsTargettingMode = true;
   2362 							} else {
   2363 								BuildingClass * builder = pending->Who_Can_Build_Me(false, false);
   2364 								if (!builder) {
   2365 									OutList.Add(EventClass(EventClass::ABANDON, otype, oid));
   2366 									Speak(VOX_NO_FACTORY);
   2367 								} else {
   2368 
   2369 									/*
   2370 									**	If the completed object is a building, then change the
   2371 									**	game state into building placement mode. This fact is
   2372 									**	not transmitted to any linked computers until the moment
   2373 									**	the building is actually placed down.
   2374 									*/
   2375 									if (pending->What_Am_I() == RTTI_BUILDING) {
   2376 								 		PlayerPtr->Manual_Place(builder, (BuildingClass *)pending);
   2377 									} else {
   2378 
   2379 										/*
   2380 										**	For objects that can leave the factory under their own
   2381 										**	power, queue this event and process through normal house
   2382 										**	production channels.
   2383 										*/
   2384 										OutList.Add(EventClass(EventClass::PLACE, otype, -1));
   2385 									}
   2386 								}
   2387 							}
   2388 						} else {
   2389 
   2390 							/*
   2391 							**	The factory must have been in a suspended state. Resume construction
   2392 							**	normally.
   2393 							*/
   2394 							Speak(VOX_BUILDING);
   2395 							OutList.Add(EventClass(EventClass::PRODUCE, Strip->Buildables[index].BuildableType, Strip->Buildables[index].BuildableID));
   2396 						}
   2397 					}
   2398 
   2399 				} else {
   2400 
   2401 					/*
   2402 					**	If this side strip is already busy with production, then ignore the
   2403 					**	input and announce this fact.
   2404 					*/
   2405 //					if (Strip->IsBuilding) {
   2406 //						Speak(VOX_NO_FACTORY);
   2407 //					} else {
   2408 						Speak(VOX_BUILDING);
   2409 						OutList.Add(EventClass(EventClass::PRODUCE, Strip->Buildables[index].BuildableType, Strip->Buildables[index].BuildableID));
   2410 //					}
   2411 				}
   2412 			}
   2413 		} else {
   2414 			flags = 0;
   2415 		}
   2416 	}
   2417 
   2418 	ControlClass::Action(flags, key);
   2419 	return(true);
   2420 }
   2421 
   2422 
   2423 /***********************************************************************************************
   2424  * SidebarClass::SBGadgetClass::Action -- Special function that controls the mouse over the si *
   2425  *                                                                                             *
   2426  *    This routine is called whenever the mouse is over the sidebar. It makes sure that the    *
   2427  *    mouse is always the normal shape while over the sidebar.                                 *
   2428  *                                                                                             *
   2429  * INPUT:   flags -- The event flags that resuled in this routine being called.                *
   2430  *                                                                                             *
   2431  *          key   -- Reference the keyboard code that may be present.                          *
   2432  *                                                                                             *
   2433  * OUTPUT:  Returns that no further keyboard processing is necessary.                          *
   2434  *                                                                                             *
   2435  * WARNINGS:   none                                                                            *
   2436  *                                                                                             *
   2437  * HISTORY:                                                                                    *
   2438  *   03/28/1995 JLB : Created.                                                                 *
   2439  *=============================================================================================*/
   2440 int SidebarClass::SBGadgetClass::Action(unsigned , KeyNumType & )
   2441 {
   2442 	Map.Help_Text(TXT_NONE);
   2443 	Map.Override_Mouse_Shape(MOUSE_NORMAL, false);
   2444 	return(true);
   2445 }
   2446 
   2447 
   2448 /***********************************************************************************************
   2449  * SidebarClass::StripClass::Factory_Link -- Links a factory to a sidebar button.              *
   2450  *                                                                                             *
   2451  *    This routine will link the specified factory to this sidebar strip. The exact button to  *
   2452  *    link to is determined from the object type and id specified. A linked button is one that *
   2453  *    will show appropriate construction animation (clock shape) that matches the state of     *
   2454  *    the factory.                                                                             *
   2455  *                                                                                             *
   2456  * INPUT:   factory  -- The factory number to link to the sidebar.                             *
   2457  *                                                                                             *
   2458  *          type     -- The object type that this factory refers to.                           *
   2459  *                                                                                             *
   2460  *          id       -- The object sub-type that this factory refers to.                       *
   2461  *                                                                                             *
   2462  * OUTPUT:  Was the factory successfully attached? Failure would indicate that there is no     *
   2463  *          object of the specified type and sub-type in the sidebar list.                     *
   2464  *                                                                                             *
   2465  * WARNINGS:   none                                                                            *
   2466  *                                                                                             *
   2467  * HISTORY:                                                                                    *
   2468  *   05/18/1995 JLB : Created.                                                                 *
   2469  *=============================================================================================*/
   2470 bool SidebarClass::StripClass::Factory_Link(int factory, RTTIType type, int id)
   2471 {
   2472 	for (int index = 0; index < BuildableCount; index++) {
   2473 		if (Buildables[index].BuildableType == type && Buildables[index].BuildableID == id) {
   2474 			Buildables[index].Factory = factory;
   2475 			IsBuilding = true;
   2476 
   2477 			/*
   2478 			** Flag that all the icons on this strip need to be redrawn
   2479 			*/
   2480 			Flag_To_Redraw();
   2481 			return(true);
   2482 		}
   2483 	}
   2484 	return(false);
   2485 }
   2486 
   2487 
   2488 /***********************************************************************************************
   2489  * SidebarClass::Abandon_Production -- Stops production of the object specified.               *
   2490  *                                                                                             *
   2491  *    This routine is used to abandon production of the object specified. The factory will     *
   2492  *    be completely disabled by this call.                                                     *
   2493  *                                                                                             *
   2494  * INPUT:   type     -- The object type that is to be abandoned. The sub-type is not needed    *
   2495  *                      since it is presumed there can be only one type in production at any   *
   2496  *                      one time.                                                              *
   2497  *                                                                                             *
   2498  *          factory  -- The factory number that is doing the production.                       *
   2499  *                                                                                             *
   2500  * OUTPUT:  Was the factory successfully abandoned?                                            *
   2501  *                                                                                             *
   2502  * WARNINGS:   none                                                                            *
   2503  *                                                                                             *
   2504  * HISTORY:                                                                                    *
   2505  *   05/18/1995 JLB : Created.                                                                 *
   2506  *=============================================================================================*/
   2507 bool SidebarClass::Abandon_Production(RTTIType type, int factory)
   2508 {
   2509 	return(Column[Which_Column(type)].Abandon_Production(factory));
   2510 }
   2511 
   2512 
   2513 /***********************************************************************************************
   2514  * SidebarClass::StripClass::Abandon_Produ -- Abandons production associated with sidebar.     *
   2515  *                                                                                             *
   2516  *    Production of the object associated with this sidebar is abandoned when this routine is  *
   2517  *    called.                                                                                  *
   2518  *                                                                                             *
   2519  * INPUT:   factory  -- The factory index that is to be suspended.                             *
   2520  *                                                                                             *
   2521  * OUTPUT:  Was the production abandonment successful?                                         *
   2522  *                                                                                             *
   2523  * WARNINGS:   none                                                                            *
   2524  *                                                                                             *
   2525  * HISTORY:                                                                                    *
   2526  *   05/18/1995 JLB : Created.                                                                 *
   2527  *   08/06/1995 JLB : More intelligent abandon logic for multiple factories.                   *
   2528  *=============================================================================================*/
   2529 bool SidebarClass::StripClass::Abandon_Production(int factory)
   2530 {
   2531 	bool noprod = true;
   2532 	bool abandon = false;
   2533 	for (int index = 0; index < BuildableCount; index++) {
   2534 		if (Buildables[index].Factory == factory) {
   2535 			Factories.Raw_Ptr(factory)->Abandon();
   2536 			Buildables[index].Factory = -1;
   2537 			abandon = true;
   2538 		} else {
   2539 			if (Buildables[index].Factory != -1) {
   2540 				noprod = false;
   2541 			}
   2542 		}
   2543 	}
   2544 
   2545 	/*
   2546 	**	If there was a change to the strip, then flag the strip to be redrawn.
   2547 	*/
   2548 	if (abandon) {
   2549 		Flag_To_Redraw();
   2550 	}
   2551 
   2552 	/*
   2553 	**	If there is no production whatsoever on this strip, then flag it so.
   2554 	*/
   2555 	if (noprod) {
   2556 		IsBuilding = false;
   2557 	}
   2558 	return(abandon);
   2559 }