CnC_Remastered_Collection

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

BUILDING.CPP (253013B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/BUILDING.CPP 5     3/13/97 5:18p Joe_b $ */
     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 : BUILDING.CPP                                                 *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : September 10, 1993                                           *
     28  *                                                                                             *
     29  *                  Last Update : October 27, 1996 [JLB]                                       *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   BuildingClass::AI -- Handles non-graphic AI processing for buildings.                     *
     34  *   BuildingClass::Active_Click_With -- Handles cell selection for buildings.                 *
     35  *   BuildingClass::Animation_AI -- Handles normal building animation processing.              *
     36  *   BuildingClass::Assign_Target -- Assigns a target to the building.                         *
     37  *   BuildingClass::Begin_Mode -- Begins an animation mode for the building.                   *
     38  *   BuildingClass::BuildingClass -- Constructor for buildings.                                *
     39  *   BuildingClass::Can_Demolish -- Can the player demolish (sell back) the building?          *
     40  *   BuildingClass::Can_Enter_Cell -- Determines if building can be placed down.               *
     41  *   BuildingClass::Can_Fire -- Determines if this building can fire.                          *
     42  *   BuildingClass::Can_Player_Move -- Can this building be moved?                             *
     43  *   BuildingClass::Captured -- Captures the building.                                         *
     44  *   BuildingClass::Center_Coord -- Fetches the center coordinate for the building.            *
     45  *   BuildingClass::Charging_AI -- Handles the special charging logic for Tesla coils.         *
     46  *   BuildingClass::Check_Point -- Fetches the landing checkpoint for the given flight pattern.*
     47  *   BuildingClass::Click_With -- Handles clicking on the map while the building is selected.  *
     48  *   BuildingClass::Crew_Type -- This determines the crew that this object generates.          *
     49  *   BuildingClass::Death_Announcement -- Announce the death of this building.                 *
     50  *   BuildingClass::Debug_Dump -- Displays building status to the monochrome screen.           *
     51  *   BuildingClass::Detach -- Handles target removal from the game system.                     *
     52  *   BuildingClass::Detach_All -- Possibly abandons production according to factory type.      *
     53  *   BuildingClass::Docking_Coord -- Fetches the coordinate to use for docking.                *
     54  *   BuildingClass::Draw_It -- Displays the building at the location specified.                *
     55  *   BuildingClass::Drop_Debris -- Drops rubble when building is destroyed.                    *
     56  *   BuildingClass::Enter_Idle_Mode -- The building will enter its idle mode.                  *
     57  *   BuildingClass::Exit_Coord -- Determines location where object will leave it.              *
     58  *   BuildingClass::Exit_Object -- Initiates an object to leave the building.                  *
     59  *   BuildingClass::Factory_AI -- Handle factory production and initiation.                    *
     60  *   BuildingClass::Find_Exit_Cell -- Find a clear location to exit an object from this buildin*
     61  *   BuildingClass::Fire_Direction -- Fetches the direction of firing.                         *
     62  *   BuildingClass::Fire_Out -- Handles when attached animation expires.                       *
     63  *   BuildingClass::Flush_For_Placement -- Handles clearing a zone for object placement.       *
     64  *   BuildingClass::Get_Image_Data -- Fetch the image pointer for the building.                *
     65  *   BuildingClass::Grand_Opening -- Handles construction completed special operations.        *
     66  *   BuildingClass::Greatest_Threat -- Searches for target that building can fire upon.        *
     67  *   BuildingClass::How_Many_Survivors -- This determine the maximum number of survivors.      *
     68  *   BuildingClass::Init -- Initialize the building system to an empty null state.             *
     69  *   BuildingClass::Limbo -- Handles power adjustment as building goes into limbo.             *
     70  *   BuildingClass::Mark -- Building interface to map rendering system.                        *
     71  *   BuildingClass::Mission_Attack -- Handles attack mission for building.                     *
     72  *   BuildingClass::Mission_Construction -- Handles mission construction.                      *
     73  *   BuildingClass::Mission_Deconstruction -- Handles building deconstruction.                 *
     74  *   BuildingClass::Mission_Guard -- Handles guard mission for combat buildings.               *
     75  *   BuildingClass::Mission_Harvest -- Handles refinery unloading harvesters.                  *
     76  *   BuildingClass::Mission_Missile -- State machine for nuclear missile launch.               *
     77  *   BuildingClass::Mission_Repair -- Handles the repair (active) state for building.          *
     78  *   BuildingClass::Mission_Unload -- Handles the unload mission for a building.               *
     79  *   BuildingClass::Pip_Count -- Determines "full" pips to display for building.               *
     80  *   BuildingClass::Power_Output -- Fetches the current power output from this building.       *
     81  *   BuildingClass::Read_INI -- Reads buildings from INI file.                                 *
     82  *   BuildingClass::Receive_Message -- Handle an incoming message to the building.             *
     83  *   BuildingClass::Remap_Table -- Fetches the remap table to use for this building.           *
     84  *   BuildingClass::Remove_Gap_Effect -- Stop a gap generator from jamming cells               *
     85  *   BuildingClass::Repair -- Initiates or terminates the repair process.                      *
     86  *   BuildingClass::Repair_AI -- Handle the repair (and sell) logic for the building.          *
     87  *   BuildingClass::Revealed -- Reveals the building to the specified house.                   *
     88  *   BuildingClass::Rotation_AI -- Process any turret rotation required of this building.      *
     89  *   BuildingClass::Sell_Back -- Controls the sell back (demolish) operation.                  *
     90  *   BuildingClass::Shape_Number -- Fetch the shape number for this building.                  *
     91  *   BuildingClass::Sort_Y -- Returns the building coordinate used for sorting.                *
     92  *   BuildingClass::Take_Damage -- Inflicts damage points upon a building.                     *
     93  *   BuildingClass::Target_Coord -- Return the coordinate to use when firing on this building. *
     94  *   BuildingClass::Toggle_Primary -- Toggles the primary factory state.                       *
     95  *   BuildingClass::Turret_Facing -- Fetches the turret facing for this building.              *
     96  *   BuildingClass::Unlimbo -- Removes a building from limbo state.                            *
     97  *   BuildingClass::Update_Buildables -- Informs sidebar of additional construction options.   *
     98  *   BuildingClass::Value -- Determine the value of this building.                             *
     99  *   BuildingClass::What_Action -- Determines action to perform if click on specified object.  *
    100  *   BuildingClass::What_Action -- Determines what action will occur.                          *
    101  *   BuildingClass::Write_INI -- Write out the building data to the INI file specified.        *
    102  *   BuildingClass::delete -- Deallocates building object.                                     *
    103  *   BuildingClass::new -- Allocates a building object from building pool.                     *
    104  *   BuildingClass::~BuildingClass -- Destructor for building type objects.                    *
    105  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    106 
    107 #include	"function.h"
    108 
    109 /*
    110 ** New sidebar for GlyphX multiplayer. ST - 8/2/2019 2:35PM
    111 */
    112 #include "SidebarGlyphx.h"
    113 
    114 enum SAMState {
    115 	SAM_READY,					// Launcher can be facing any direction tracking targets.
    116 	SAM_FIRING					// Stationary while missile is being fired.
    117 };
    118 
    119 
    120 /***************************************************************************
    121 **	Center of building offset table.
    122 */
    123 COORDINATE const BuildingClass::CenterOffset[BSIZE_COUNT] = {
    124 	0x00800080L,
    125 	0x008000FFL,
    126 	0x00FF0080L,
    127 	0x00FF00FFL,
    128 	0x018000FFL,
    129 	0x00FF0180L,
    130 	0x01800180L,
    131 
    132 	0x00FF0200L,
    133 
    134 	0x02800280L,
    135 };
    136 
    137 
    138 /***********************************************************************************************
    139  * BuildingClass::Receive_Message -- Handle an incoming message to the building.               *
    140  *                                                                                             *
    141  *    This routine handles an incoming message to the building. Messages regulate the          *
    142  *    various cooperative ventures between buildings and units. This might include such        *
    143  *    actions as coordinating the construction yard animation with the actual building's       *
    144  *    construction animation.                                                                  *
    145  *                                                                                             *
    146  * INPUT:   from     -- The originator of the message received.                                *
    147  *                                                                                             *
    148  *          message  -- The radio message received.                                            *
    149  *                                                                                             *
    150  *          param    -- Reference to an optional parameter that might be used to return        *
    151  *                      extra information to the message originator.                           *
    152  *                                                                                             *
    153  * OUTPUT:  Returns with the response to the message (typically, this is just RADIO_OK).       *
    154  *                                                                                             *
    155  * WARNINGS:   none                                                                            *
    156  *                                                                                             *
    157  * HISTORY:                                                                                    *
    158  *   06/09/1994 JLB : Created.                                                                 *
    159  *   06/26/1995 JLB : Forces refinery load anim to start immediately.                          *
    160  *   08/13/1995 JLB : Uses ScenarioInit for special loose "CAN_LOAD" check.                    *
    161  *=============================================================================================*/
    162 RadioMessageType BuildingClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)
    163 {
    164 	assert(Buildings.ID(this) == ID);
    165 	assert(IsActive);
    166 
    167 	switch (message) {
    168 
    169 		/*
    170 		**	This message is received as a request to attach/load/dock with this building.
    171 		**	Verify that this is allowed and return the appropriate response.
    172 		*/
    173 		case RADIO_CAN_LOAD:
    174 			TechnoClass::Receive_Message(from, message, param);
    175 			if (!House->Is_Ally(from)) return(RADIO_STATIC);
    176 			if (Mission == MISSION_CONSTRUCTION || Mission == MISSION_DECONSTRUCTION || BState == BSTATE_CONSTRUCTION || (!ScenarioInit && Class->Type != STRUCT_REFINERY && In_Radio_Contact())) return(RADIO_NEGATIVE);
    177 			switch (Class->Type) {
    178 				case STRUCT_AIRSTRIP:
    179 					if (from->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass const *)from)->Class->IsFixedWing) {
    180 						return(RADIO_ROGER);
    181 					}
    182 					break;
    183 
    184 				case STRUCT_HELIPAD:
    185 					if (from->What_Am_I() == RTTI_AIRCRAFT && !((AircraftClass const *)from)->Class->IsFixedWing) {
    186 						return(RADIO_ROGER);
    187 					}
    188 					break;
    189 
    190 				case STRUCT_REPAIR:
    191 					if (from->What_Am_I() == RTTI_UNIT || (from->What_Am_I() == RTTI_AIRCRAFT)) {
    192 						if (Transmit_Message(RADIO_ON_DEPOT, from) != RADIO_ROGER) {
    193 							return(RADIO_ROGER);
    194 						}
    195 					}
    196 					return(RADIO_NEGATIVE);
    197 
    198 				case STRUCT_REFINERY:
    199 					if (from->What_Am_I() == RTTI_UNIT &&
    200 						*((UnitClass *)from) == UNIT_HARVESTER &&
    201 						(ScenarioInit || !Is_Something_Attached())) {
    202 
    203 						return((Contact_With_Whom() != from) ? RADIO_ROGER : RADIO_NEGATIVE);
    204 					}
    205 					break;
    206 
    207 				default:
    208 					break;
    209 			}
    210 			return(RADIO_STATIC);
    211 
    212 		/*
    213 		**	This message is received when the object has attached itself to this
    214 		**	building.
    215 		*/
    216 		case RADIO_IM_IN:
    217 			if (Mission == MISSION_DECONSTRUCTION) {
    218 				return(RADIO_NEGATIVE);
    219 			}
    220 			switch (Class->Type) {
    221 				case STRUCT_REPAIR:
    222 					IsReadyToCommence = true;
    223 					Assign_Mission(MISSION_REPAIR);
    224 					from->Assign_Mission(MISSION_SLEEP);
    225 					return(RADIO_ROGER);
    226 
    227 				case STRUCT_AIRSTRIP:
    228 				case STRUCT_HELIPAD:
    229 					Assign_Mission(MISSION_REPAIR);
    230 					from->Assign_Mission(MISSION_SLEEP);
    231 					return(RADIO_ROGER);
    232 
    233 				case STRUCT_REFINERY:
    234 					Mark(MARK_CHANGE);
    235 					from->Assign_Mission(MISSION_UNLOAD);
    236 					return(RADIO_ROGER);
    237 
    238 				default:
    239 					break;
    240 			}
    241 			break;
    242 
    243 		/*
    244 		**	Docking maneuver maintenance message. See if new order should be given to the
    245 		**	unit trying to dock.
    246 		*/
    247 		case RADIO_DOCKING:
    248 			TechnoClass::Receive_Message(from, message, param);
    249 
    250 			/*
    251 			**	When in radio contact for loading, the refinery starts
    252 			**	flashing the lights.
    253 			*/
    254 			if (*this == STRUCT_REFINERY && BState != BSTATE_FULL) {
    255 				Begin_Mode(BSTATE_FULL);
    256 			}
    257 
    258 			/*
    259 			**	If this building is already in radio contact, then it might
    260 			**	be able to satisfy the request to load by bumping off any
    261 			**	preoccupying task.
    262 			*/
    263 			if (*this == STRUCT_REPAIR) {
    264 				if (Contact_With_Whom() != from) {
    265 					if (Transmit_Message(RADIO_ON_DEPOT) == RADIO_ROGER) {
    266 						if (Transmit_Message(RADIO_NEED_REPAIR) == RADIO_NEGATIVE) {
    267 							Transmit_Message(RADIO_RUN_AWAY);
    268 							Transmit_Message(RADIO_OVER_OUT);
    269 							return(RADIO_ROGER);
    270 						}
    271 					}
    272 				}
    273 			}
    274 
    275 			/*
    276 			**	Establish contact with the object if this building isn't already in contact
    277 			**	with another.
    278 			*/
    279 			if (!In_Radio_Contact()) {
    280 				Transmit_Message(RADIO_HELLO, from);
    281 			}
    282 
    283 			if (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {
    284 				switch (Class->Type) {
    285 					case STRUCT_AIRSTRIP:
    286 						param = As_Target();
    287 						break;
    288 
    289 					case STRUCT_HELIPAD:
    290 						param = As_Target();
    291 						break;
    292 
    293 					case STRUCT_REPAIR:
    294 						Transmit_Message(RADIO_TETHER);
    295 						param = ::As_Target(Coord_Cell(Center_Coord()));
    296 						break;
    297 
    298 					case STRUCT_REFINERY:
    299 						param = ::As_Target(Coord_Cell(Adjacent_Cell(Center_Coord(), DIR_S)));
    300 						break;
    301 				}
    302 
    303 				/*
    304 				**	Tell the harvester to move to the docking pad of the building.
    305 				*/
    306 				if (Transmit_Message(RADIO_MOVE_HERE, param) == RADIO_YEA_NOW_WHAT) {
    307 
    308 					/*
    309 					**	Since the harvester is already there, tell it to begin the backup
    310 					**	procedure now. If it can't, then tell it to get outta here.
    311 					*/
    312 					Transmit_Message(RADIO_TETHER);
    313 					if (*this == STRUCT_REFINERY && Transmit_Message(RADIO_BACKUP_NOW, from) != RADIO_ROGER) {
    314 						from->Scatter(NULL, true, true);
    315 					}
    316 				}
    317 			}
    318 			return(RADIO_ROGER);
    319 
    320 		/*
    321 		**	If a transport or harvester is requesting permission to head toward, dock
    322 		**	and load/unload, check to make sure that this is allowed given the current
    323 		**	state of the building.
    324 		*/
    325 		case RADIO_ARE_REFINERY:
    326 			if (Is_Something_Attached() || In_Radio_Contact() || IsInLimbo || House->Class->House != from->Owner() || (*this != STRUCT_REFINERY/* && *this != STRUCT_REPAIR*/)) {
    327 				return(RADIO_NEGATIVE);
    328 			}
    329 			return(RADIO_ROGER);
    330 
    331 		/*
    332 		**	Someone is telling us that it is starting construction. This should only
    333 		**	occur if this is a construction yard and a building was just placed on
    334 		**	the map.
    335 		*/
    336 		case RADIO_BUILDING:
    337 			Assign_Mission(MISSION_REPAIR);
    338 			TechnoClass::Receive_Message(from, message, param);
    339 			return(RADIO_ROGER);
    340 
    341 		/*
    342 		**	Someone is telling us that they have finished construction. This should
    343 		**	only occur if this is a construction yard and the building that was being
    344 		**	constructed has finished. In this case, stop the construction yard
    345 		**	animation.
    346 		*/
    347 		case RADIO_COMPLETE:
    348 			if (Mission != MISSION_DECONSTRUCTION) {
    349 				Assign_Mission(MISSION_GUARD);
    350 			}
    351 			TechnoClass::Receive_Message(from, message, param);
    352 			return(RADIO_ROGER);
    353 
    354 		/*
    355 		**	This message may occur unexpectedly if the unit in contact with this
    356 		**	building is suddenly destroyed. Handle any cleanup necessary. For example,
    357 		**	a construction yard should stop its construction animation in this case.
    358 		*/
    359 		case RADIO_OVER_OUT:
    360 			Begin_Mode(BSTATE_IDLE);
    361 			if (*this == STRUCT_REPAIR) {
    362 				Assign_Mission(MISSION_GUARD);
    363 			}
    364 			TechnoClass::Receive_Message(from, message, param);
    365 			return(RADIO_ROGER);
    366 
    367 		/*
    368 		**	This message is received when an object has completely left
    369 		** building. Sometimes special cleanup action is required when
    370 		**	this event occurs.
    371 		*/
    372 		case RADIO_UNLOADED:
    373 			if (*this == STRUCT_REPAIR) {
    374 				if (Distance(from) < 0x0180) {
    375 					return(RADIO_ROGER);
    376 				}
    377 			}
    378 			TechnoClass::Receive_Message(from, message, param);
    379 			if (*this == STRUCT_WEAP || *this == STRUCT_AIRSTRIP || *this == STRUCT_REPAIR) return(RADIO_RUN_AWAY);
    380 			return(RADIO_ROGER);
    381 
    382 		default:
    383 			break;
    384 	}
    385 
    386 	/*
    387 	**	Pass along the message to the default message handler in the radio itself.
    388 	*/
    389 	return(TechnoClass::Receive_Message(from, message, param));
    390 }
    391 
    392 
    393 #ifdef CHEAT_KEYS
    394 /***********************************************************************************************
    395  * BuildingClass::Debug_Dump -- Displays building status to the monochrome screen.             *
    396  *                                                                                             *
    397  *    This utility function will output the current status of the building class to the        *
    398  *    monochrome screen. It is through this data that bugs may be fixed or detected.           *
    399  *                                                                                             *
    400  * INPUT:   none                                                                               *
    401  *                                                                                             *
    402  * OUTPUT:  none                                                                               *
    403  *                                                                                             *
    404  * WARNINGS:   none                                                                            *
    405  *                                                                                             *
    406  * HISTORY:                                                                                    *
    407  *   05/31/1994 JLB : Created.                                                                 *
    408  *=============================================================================================*/
    409 void BuildingClass::Debug_Dump(MonoClass * mono) const
    410 {
    411 	assert(Buildings.ID(this) == ID);
    412 	assert(IsActive);
    413 
    414 	mono->Set_Cursor(0, 0);
    415 	mono->Print(Text_String(TXT_DEBUG_BUILDING));
    416 	mono->Fill_Attrib(66, 13, 12, 1, IsRepairing ? MonoClass::INVERSE : MonoClass::NORMAL);
    417 	mono->Fill_Attrib(66, 14, 12, 1, IsToRebuild ? MonoClass::INVERSE : MonoClass::NORMAL);
    418 	mono->Fill_Attrib(66, 15, 12, 1, IsAllowedToSell ? MonoClass::INVERSE : MonoClass::NORMAL);
    419 	mono->Fill_Attrib(66, 16, 12, 1, IsCharging ? MonoClass::INVERSE : MonoClass::NORMAL);
    420 	mono->Fill_Attrib(66, 17, 12, 1, IsCharged ? MonoClass::INVERSE : MonoClass::NORMAL);
    421 	mono->Fill_Attrib(66, 18, 12, 1, IsJamming ? MonoClass::INVERSE : MonoClass::NORMAL);
    422 	mono->Fill_Attrib(66, 19, 12, 1, IsJammed ? MonoClass::INVERSE : MonoClass::NORMAL);
    423 
    424 	mono->Set_Cursor(1, 11);
    425 	if (Factory) {
    426 		mono->Printf("%s %d%%", Factory->Get_Object()->Class_Of().IniName, (100*Factory->Completion())/FactoryClass::STEP_COUNT);
    427 	}
    428 
    429 	TechnoClass::Debug_Dump(mono);
    430 }
    431 #endif
    432 
    433 
    434 /***********************************************************************************************
    435  * BuildingClass::Draw_It -- Displays the building at the location specified.                  *
    436  *                                                                                             *
    437  *    This is the low level graphic routine that displays the building at the location         *
    438  *    specified.                                                                               *
    439  *                                                                                             *
    440  * INPUT:   x,y   -- The coordinate to draw the building at.                                   *
    441  *                                                                                             *
    442  *          window   -- The clipping window to use.                                            *
    443  *                                                                                             *
    444  * OUTPUT:  none                                                                               *
    445  *                                                                                             *
    446  * WARNINGS:   none                                                                            *
    447  *                                                                                             *
    448  * HISTORY:                                                                                    *
    449  *   06/20/1994 JLB : Created.                                                                 *
    450  *   06/27/1994 JLB : Takes a clipping window parameter.                                       *
    451  *   07/06/1995 JLB : Handles damaged silos correctly.                                         *
    452  *=============================================================================================*/
    453 void BuildingClass::Draw_It(int x, int y, WindowNumberType window) const
    454 {
    455 	assert(Buildings.ID(this) == ID);
    456 	assert(IsActive);
    457 
    458 	/*
    459 	**	The shape file to use for rendering depends on whether the building
    460 	**	is undergoing construction or not.
    461 	*/
    462 	void const * shapefile = Get_Image_Data();
    463 	if (shapefile == NULL) return;
    464 
    465 	/*
    466 	**	Actually draw the building shape.
    467 	*/
    468 	IsTheaterShape = Class->IsTheater;	//Let Build_Frame know if this is a theater specific shape
    469 	Techno_Draw_Object(shapefile, Shape_Number(), x, y, window);
    470 	IsTheaterShape = false;
    471 
    472 	/*
    473 	** Patch for adding overlay onto weapon factory.  Only add the overlay if
    474 	** the building has more than 1 hp.  Also, if the building's in radio
    475 	** contact, he must be unloading a constructed vehicle, so draw that
    476 	** vehicle before drawing the overlay.
    477 	*/
    478 	if (BState != BSTATE_CONSTRUCTION) {
    479 
    480 		/*
    481 		**	A Tethered object is always rendered AFTER the building.
    482 		*/
    483 		if (*this == STRUCT_WEAP && IsTethered && In_Radio_Contact() && !Contact_With_Whom()->IsInLimbo && Contact_With_Whom()->What_Am_I() != RTTI_BUILDING) {
    484 			TechnoClass * contact = Contact_With_Whom();
    485 
    486 			assert(contact->IsActive);
    487 			int xxx = x + ((int)Lepton_To_Pixel((int)Coord_X(contact->Render_Coord())) - (int)Lepton_To_Pixel((int)Coord_X(Render_Coord())));
    488 			int yyy = y + ((int)Lepton_To_Pixel((int)Coord_Y(contact->Render_Coord())) - (int)Lepton_To_Pixel((int)Coord_Y(Render_Coord())));
    489 			contact->Draw_It(xxx, yyy, window);
    490 			contact->IsToDisplay = false;
    491 		}
    492 
    493 		/*
    494 		**	Draw the weapon factory custom overlay graphic.
    495 		*/
    496 		if ( (*this == STRUCT_WEAP || *this == STRUCT_FAKEWEAP)) {
    497 			int shapenum = Door_Stage();
    498 			if (Health_Ratio() <= Rule.ConditionYellow) shapenum += 4;
    499 			// Added override shape file name. ST - 8/1/2019 5:24PM
    500 			//Techno_Draw_Object(Class->WarFactoryOverlay, shapenum, x, y, window);
    501 			Techno_Draw_Object_Virtual(Class->WarFactoryOverlay, shapenum, x, y, window, DIR_N, 0x0100, "WEAP2");
    502 		}
    503 
    504 		/*
    505 		**	Draw any repair feedback graphic required.
    506 		*/
    507 		if (IsRepairing && IsWrenchVisible) {
    508 			CC_Draw_Shape(ObjectTypeClass::SelectShapes, SELECT_WRENCH, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL);
    509 		}
    510 	}
    511 
    512 	TechnoClass::Draw_It(x, y, window);
    513 
    514 	/*
    515 	** If this is a factory that we're spying on, show what it's producing
    516 	*/
    517 	if ((Spied_By() & (1<<(PlayerPtr->Class->House)) && Is_Selected_By_Player()) || ((window == WINDOW_VIRTUAL) && (Session.Type != GAME_NORMAL))) {
    518 
    519 		/*
    520 		**	Fetch the factory that is associate with this building. For computer controlled buildings, the
    521 		**	factory pointer is integral to the building itself. For human controlled buildings, the factory
    522 		**	pointer is part of the house structure and must be retrieved from there.
    523 		*/
    524 		FactoryClass * factory = NULL;
    525 		if (House->IsHuman) {
    526 			factory = House->Fetch_Factory(Class->ToBuild);
    527 		} else {
    528 			factory = Factory;
    529 		}
    530 
    531 		/*
    532 		**	If there is a factory associated with this building, then fetch any attached
    533 		**	object under production and display its cameo image over the top of this building.
    534 		*/
    535 		if (factory != NULL) {
    536 			TechnoClass * obj = factory->Get_Object();
    537 			if (obj != NULL) {
    538 #ifdef FIXIT_CSII
    539 				CC_Draw_Shape(obj, obj->Techno_Type_Class()->Get_Cameo_Data(), 0, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_NORMAL, NULL);
    540 #else
    541 				void const * remapper = obj->House->Remap_Table(false, obj->Techno_Type_Class()->Remap);
    542 				CC_Draw_Shape(obj->Techno_Type_Class()->Get_Cameo_Data(), 0, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL | ((remapper != NULL) ? SHAPE_FADING : SHAPE_NORMAL), remapper);
    543 #endif
    544 			}
    545 		}
    546 	}
    547 }
    548 
    549 
    550 /***********************************************************************************************
    551  * BuildingClass::Shape_Number -- Fetch the shape number for this building.                    *
    552  *                                                                                             *
    553  *    This routine will examine the current state of the building and return with the shape    *
    554  *    number to use. The shape number is subordinate to the building graphic image data.       *
    555  *                                                                                             *
    556  * INPUT:   none                                                                               *
    557  *                                                                                             *
    558  * OUTPUT:  Returns with the shape number to use when rendering this building.                 *
    559  *                                                                                             *
    560  * WARNINGS:   none                                                                            *
    561  *                                                                                             *
    562  * HISTORY:                                                                                    *
    563  *   07/29/1996 JLB : Created.                                                                 *
    564  *=============================================================================================*/
    565 int BuildingClass::Shape_Number(void) const
    566 {
    567 	assert(Buildings.ID(this) == ID);
    568 	assert(IsActive);
    569 
    570 	int shapenum = Fetch_Stage();
    571 
    572 	/*
    573 	**	The shape file to use for rendering depends on whether the building
    574 	**	is undergoing construction or not.
    575 	*/
    576 	if (BState == BSTATE_CONSTRUCTION) {
    577 
    578 		/*
    579 		**	If the building is deconstructing, then the display frame progresses
    580 		**	from the end to the beginning. Reverse the shape number accordingly.
    581 		*/
    582 		if (Mission == MISSION_DECONSTRUCTION) {
    583 			shapenum = (Class->Anims[BState].Start+Class->Anims[BState].Count-1)-shapenum;
    584 		}
    585 
    586 	} else {
    587 
    588 		/*
    589 		**	If this is a camouflaged pill box and it is not owned by the player, then
    590 		**	it is displayed with the MEGA-camouflaged imagery.
    591 		*/
    592 		if ((!IsOwnedByPlayer) && (*this == STRUCT_CAMOPILLBOX)) {
    593 			shapenum += 1;
    594 		}
    595 
    596 		/*
    597 		**	The Tesla Coil has a stage value that can be overridden by
    598 		**	its current state.
    599 		*/
    600 		if (*this == STRUCT_TESLA) {
    601 			if (IsCharged) {
    602 				shapenum = 3;
    603 			} else {
    604 				if (IsCharging) {
    605 					shapenum = Fetch_Stage();
    606 				} else {
    607 					shapenum = 0;
    608 				}
    609 			}
    610 		}
    611 
    612 		/*
    613 		**	Buildings that contain a turret handle their shape determination
    614 		**	differently than normal buildings. They need to take into consideration
    615 		**	the direction the turret is facing.
    616 		*/
    617 		if (Class->IsTurretEquipped) {
    618 			shapenum = UnitClass::BodyShape[Dir_To_32(PrimaryFacing.Current())];
    619 
    620 			if (*this == STRUCT_SAM) {
    621 
    622 				/*
    623 				**	SAM sites that are free to rotate fetch their animation frame
    624 				**	from the building's turret facing. All other animation stages
    625 				**	fetch their frame from the embedded animation sequencer.
    626 				*/
    627 //				if (Status == SAM_READY || Status == SAM_FIRING || Status == SAM_LOCKING) {
    628 //					shapenum = Fetch_Stage();
    629 //				}
    630 				if (Health_Ratio() <= Rule.ConditionYellow) {
    631 					shapenum += 35;
    632 				}
    633 			} else {
    634 				if (IsInRecoilState) {
    635 					shapenum += 32;
    636 				}
    637 				if (Health_Ratio() <= Rule.ConditionYellow) {
    638 					shapenum += 64;
    639 				}
    640 			}
    641 		} else {
    642 
    643 			/*
    644 			**	If it is a significantly damaged weapons factory, it is shown in
    645 			**	the worst state possible.
    646 			*/
    647 			if (*this == STRUCT_WEAP || *this == STRUCT_FAKEWEAP) {
    648 				shapenum = 0;
    649 				if (Health_Ratio() <= Rule.ConditionYellow) {
    650 					shapenum = 1;
    651 				}
    652 
    653 			} else {
    654 
    655 				/*
    656 				**	Special render stage for silos. The stage is dependent on the current
    657 				**	Tiberium collected as it relates to Tiberium capacity.
    658 				*/
    659 				if (*this == STRUCT_STORAGE) {
    660 
    661 					int level = 0;
    662 					if (House->Capacity) {
    663 						level = (House->Tiberium * 5) / House->Capacity;
    664 					}
    665 
    666 					shapenum += Bound(level, 0, 4);
    667 					if (Health_Ratio() <= Rule.ConditionYellow) {
    668 						shapenum += 5;
    669 					}
    670 
    671 				} else {
    672 
    673 					/*
    674 					**	If below half strenth, then show the damage frames of the
    675 					**	building.
    676 					*/
    677 					if (Health_Ratio() <= Rule.ConditionYellow) {
    678 						if (*this == STRUCT_CHRONOSPHERE) {
    679 							shapenum += 29;
    680 						} else {
    681 							int last1 = Class->Anims[BSTATE_IDLE].Start + Class->Anims[BSTATE_IDLE].Count;
    682 							int last2 = Class->Anims[BSTATE_ACTIVE].Start + Class->Anims[BSTATE_ACTIVE].Count;
    683 							int largest = max(last1, last2);
    684 							last2 = Class->Anims[BSTATE_AUX1].Start + Class->Anims[BSTATE_AUX1].Count;
    685 							largest = max(largest, last2);
    686 							last2 = Class->Anims[BSTATE_AUX2].Start + Class->Anims[BSTATE_AUX2].Count;
    687 							largest = max(largest, last2);
    688 							shapenum += largest;
    689 						}
    690 					}
    691 				}
    692 			}
    693 		}
    694 	}
    695 	return(shapenum);
    696 }
    697 
    698 
    699 /***********************************************************************************************
    700  * BuildingClass::Mark -- Building interface to map rendering system.                          *
    701  *                                                                                             *
    702  *    This routine is used to mark the map cells so that when it renders                       *
    703  *    the underlying icons will also be updated as necessary.                                  *
    704  *                                                                                             *
    705  * INPUT:   mark  -- Type of image change (MARK_UP, _DOWN, _CHANGE)                            *
    706  *             MARK_UP  -- Building is removed.                                                *
    707  *             MARK_CHANGE -- Building changes shape.                                          *
    708  *             MARK_DOWN -- Building is added.                                                 *
    709  *                                                                                             *
    710  * OUTPUT:  bool; Did the mark operation succeed? Failure could be the result of marking down  *
    711  *                when the building is already marked down, or visa versa.                     *
    712  *                                                                                             *
    713  * WARNINGS:   none                                                                            *
    714  *                                                                                             *
    715  * HISTORY:                                                                                    *
    716  *   03/31/1994 JLB : Created.                                                                 *
    717  *   04/15/1994 JLB : Converted to member function.                                            *
    718  *   04/16/1994 JLB : Added health bar tracking.                                               *
    719  *   12/23/1994 JLB : Calls low level check before proceeding.                                 *
    720  *   01/27/1995 JLB : Special road spacer template added.                                      *
    721  *=============================================================================================*/
    722 bool BuildingClass::Mark(MarkType mark)
    723 {
    724 	assert(Buildings.ID(this) == ID);
    725 	assert(IsActive);
    726 
    727 	if (TechnoClass::Mark(mark)) {
    728 		short const * offset = Overlap_List();
    729 		short const * occupy = Occupy_List();
    730 		CELL cell = Coord_Cell(Coord);
    731 		SmudgeType bib;
    732 
    733 		switch (mark) {
    734 			case MARK_UP:
    735 				Map.Pick_Up(cell, this);
    736 				if (Class->Bib_And_Offset(bib, cell)) {
    737 					SmudgeClass * smudge = new SmudgeClass(bib);
    738 					if (smudge != NULL) {
    739 						smudge->Disown(cell);
    740 						delete smudge;
    741 					}
    742 				}
    743 				break;
    744 
    745 			case MARK_DOWN:
    746 
    747 				/*
    748 				**	Special wall logic is handled here. A building that is really a wall
    749 				**	gets converted into an overlay wall type when it is placed down. The
    750 				**	actual building object itself is destroyed.
    751 				*/
    752 				if (Class->IsWall) {
    753 					switch (Class->Type) {
    754 						case STRUCT_BRICK_WALL:
    755 							new OverlayClass(OVERLAY_BRICK_WALL, cell, House->Class->House);
    756 							break;
    757 
    758 						case STRUCT_BARBWIRE_WALL:
    759 							new OverlayClass(OVERLAY_BARBWIRE_WALL, cell, House->Class->House);
    760 							break;
    761 
    762 						case STRUCT_SANDBAG_WALL:
    763 							new OverlayClass(OVERLAY_SANDBAG_WALL, cell, House->Class->House);
    764 							break;
    765 
    766 						case STRUCT_WOOD_WALL:
    767 							new OverlayClass(OVERLAY_WOOD_WALL, cell, House->Class->House);
    768 							break;
    769 
    770 						case STRUCT_CYCLONE_WALL:
    771 							new OverlayClass(OVERLAY_CYCLONE_WALL, cell, House->Class->House);
    772 							break;
    773 
    774 						case STRUCT_FENCE:
    775 							new OverlayClass(OVERLAY_FENCE, cell, House->Class->House);
    776 							break;
    777 
    778 						default:
    779 							break;
    780 					}
    781 					Transmit_Message(RADIO_OVER_OUT);
    782 					delete this;
    783 
    784 				} else {
    785 					if (Can_Enter_Cell(cell) == MOVE_OK) {
    786 						/*
    787 						**	Determine if a bib is required for this building. If one is, then
    788 						**	create and place it.
    789 						*/
    790 						CELL newcell = cell;
    791 						if (Class->Bib_And_Offset(bib, newcell)) {
    792 							new SmudgeClass(bib, Cell_Coord(newcell), Class->IsBase ? House->Class->House : HOUSE_NONE);
    793 						}
    794 
    795 						Map.Place_Down(cell, this);
    796 					} else {
    797 						return(false);
    798 					}
    799 				}
    800 				break;
    801 
    802 			case MARK_CHANGE_REDRAW:
    803 				Map.Refresh_Cells(cell, Overlap_List(true));
    804 				break;
    805 
    806 			default:
    807 				Map.Refresh_Cells(cell, Overlap_List(false));
    808 				Map.Refresh_Cells(cell, occupy);
    809 				break;
    810 		}
    811 		return(true);
    812 	}
    813 	return(false);
    814 }
    815 
    816 
    817 /***********************************************************************************************
    818  * BuildingClass::AI -- Handles non-graphic AI processing for buildings.                       *
    819  *                                                                                             *
    820  *    This function is to handle the AI logic for the building. The graphic logic (facing,     *
    821  *    firing, and animation) is handled elsewhere.                                             *
    822  *                                                                                             *
    823  * INPUT:   none                                                                               *
    824  *                                                                                             *
    825  * OUTPUT:  none                                                                               *
    826  *                                                                                             *
    827  * WARNINGS:   none                                                                            *
    828  *                                                                                             *
    829  * HISTORY:                                                                                    *
    830  *   05/31/1994 JLB : Created.                                                                 *
    831  *   12/26/1994 JLB : Handles production.                                                      *
    832  *   06/11/1995 JLB : Revamped.                                                                *
    833  *=============================================================================================*/
    834 void BuildingClass::AI(void)
    835 {
    836 	assert(Buildings.ID(this) == ID);
    837 	assert(IsActive);
    838 
    839 	/*
    840 	**	Process building animation state changes. Transition to a following state
    841 	**	if there is one specified and the current animation sequence has expired.
    842 	**	This process must occur before mission AI since the mission AI relies on
    843 	**	the bstate change to occur immediately before the MissionClass::AI.
    844 	*/
    845 	Animation_AI();
    846 
    847 	/*
    848 	**	If now is a good time to act on a new mission, then do so. This process occurs
    849 	**	here because some outside event may have requested a mission change for the building.
    850 	**	Such outside requests (player input) must be initiated BEFORE the normal AI process.
    851 	*/
    852 	if (IsReadyToCommence && BState != BSTATE_CONSTRUCTION) {
    853 
    854 		/*
    855 		**	Clear the commencement flag ONLY if something actually occurred. By acting
    856 		**	this way, a building can set the IsReadyToCommence flag before it goes
    857 		**	to "sleep" knowing that it will wake up as soon as a new mission comes
    858 		**	along.
    859 		*/
    860 		if (Commence()) {
    861 			IsReadyToCommence = false;
    862 		}
    863 	}
    864 
    865 	/*
    866 	**	Proceed with normal logic processing. This is where the mission processing
    867 	**	occurs. This call must be located after the animation sequence makes the
    868 	**	transition to the next frame (see above) in order for the mission logic to
    869 	**	act at the exact moment of graphic transition BEFORE it has a chance to
    870 	**	be displayed.
    871 	*/
    872 	TechnoClass::AI();
    873 
    874 	/*
    875 	**	Bail if the object died in the AI routine.
    876 	*/
    877 	if (!IsActive) {
    878 		return;
    879 	}
    880 
    881 	/*
    882 	**	Building ammo is instantly reloaded.
    883 	*/
    884 	if (!Ammo) {
    885 		Ammo = Class->MaxAmmo;
    886 	}
    887 
    888 	/*
    889 	**	If now is a good time to act on a new mission, then do so. This occurs here because
    890 	**	some AI event may have requested a mission change (usually from another mission
    891 	**	state machine). This must occur here before it has a chance to render.
    892 	*/
    893 	if (IsReadyToCommence) {
    894 
    895 		/*
    896 		**	Clear the commencement flag ONLY if something actually occurred. By acting
    897 		**	this way, a building can set the IsReadyToCommence flag before it goes
    898 		**	to "sleep" knowing that it will wake up as soon as a new mission comes
    899 		**	along.
    900 		*/
    901 		if (Commence()) {
    902 			IsReadyToCommence = false;
    903 		}
    904 	}
    905 
    906 	/*
    907 	**	If a change of animation was requested, then make the change
    908 	**	now. The building animation system acts independently but subordinate
    909 	**	to the mission state machine system. By performing the animation change-up
    910 	**	here, the mission AI system is ensured of immediate visual affect when it
    911 	**	decides to change the animation state of the building.
    912 	*/
    913 	if (QueueBState != BSTATE_NONE) {
    914 		if (BState != QueueBState) {
    915 			BState = QueueBState;
    916 			BuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();
    917 			if (BState == BSTATE_CONSTRUCTION || BState == BSTATE_IDLE) {
    918 				Set_Rate(Options.Normalize_Delay(ctrl->Rate));
    919 			} else {
    920 				Set_Rate(ctrl->Rate);
    921 			}
    922 			Set_Stage(ctrl->Start);
    923 		}
    924 		QueueBState = BSTATE_NONE;
    925 	}
    926 
    927 	/*
    928 	**	If the building's strength has changed, then update the power
    929 	**	accordingly.
    930 	*/
    931 	if (Strength != LastStrength) {
    932 		int oldpower = Power_Output();
    933 		LastStrength = Strength;
    934 		int newpower = Power_Output();
    935 		House->Adjust_Power(newpower - oldpower);
    936 	}
    937 
    938 	/*
    939 	**	Check to see if the destruction countdown timer is active. If so, then decrement it.
    940 	**	When this timer reaches zero, the building is removed from the map. All the explosions
    941 	**	are presumed to be in progress at this time.
    942 	*/
    943 	if (Strength == 0) {
    944 		if (CountDown == 0) {
    945 			Limbo();
    946 			Drop_Debris(WhomToRepay);
    947 			delete this;
    948 		}
    949 		return;
    950 	}
    951 
    952 	/*
    953 	**	Charging logic.
    954 	*/
    955 	Charging_AI();
    956 
    957 	/*
    958 	**	Handle any repair process that may be going on.
    959 	*/
    960 	Repair_AI();
    961 
    962 	/*
    963 	**	For computer controlled buildings, determine what should be produced and start
    964 	**	production accordingly.
    965 	*/
    966 	Factory_AI();
    967 
    968 	/*
    969 	**	Check for demolition timeout. When timeout has expired, the building explodes.
    970 	*/
    971 	if (IsGoingToBlow && CountDown == 0) {
    972 
    973 		/*
    974 		** Maybe trigger an achivement. ST - 11/14/2019 1:53PM
    975 		*/
    976 		TechnoTypeClass const *object_type = Techno_Type_Class();
    977 		if (object_type) {
    978 			TechnoClass *saboteur = As_Techno(WhomToRepay);
    979 			if (saboteur && saboteur->IsActive && saboteur->House && saboteur->House->IsHuman) {
    980 				On_Achievement_Event(saboteur->House, "BUILDING_DESTROYED_C4", object_type->IniName);
    981 			}
    982 		}			
    983 		
    984 		int damage = Strength;
    985 		Take_Damage(damage, 0, WARHEAD_FIRE, As_Techno(WhomToRepay), true);
    986 		if (!IsActive) {
    987 			return;
    988 		}
    989 		Mark(MARK_CHANGE);
    990 	}
    991 
    992 	/*
    993 	**	Turret equiped buildings must handle turret rotation logic here. This entails
    994 	**	rotating the turret to the desired facing as well as figuring out what that
    995 	**	desired facing should be.
    996 	*/
    997 	Rotation_AI();
    998 
    999 	/*
   1000 	** Gap Generators need to scan if they've just become activated, or if
   1001 	** the power has just come on enough so they can scan.  Also, they need
   1002 	** to un-jam if the power has just dropped off.
   1003 	*/
   1004 	if (*this == STRUCT_GAP) {
   1005 		if (Arm == 0) {
   1006 			IsJamming = false;
   1007 			Arm = TICKS_PER_MINUTE * Rule.GapRegenInterval + Random_Pick(1, TICKS_PER_SECOND);
   1008 		}
   1009 
   1010 		if (!IsJamming) {
   1011 			if (House->Power_Fraction() >= 1) {
   1012 				Map.Jam_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, House);
   1013 				IsJamming = true;
   1014 			}
   1015 		} else {
   1016 			if (House->Power_Fraction() < 1) {
   1017 				IsJamming = false;
   1018 				Map.UnJam_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, House);
   1019 			}
   1020 		}
   1021 	}
   1022 
   1023 	/*
   1024 	** Radar facilities and SAMs need to check for the proximity of a mobile
   1025 	** radar jammer.
   1026 	*/
   1027 	if ((*this == STRUCT_RADAR || *this == STRUCT_SAM) && (Frame % TICKS_PER_SECOND) == 0) {
   1028 		IsJammed = false;
   1029 		for (int index = 0; index < Units.Count(); index++) {
   1030 			UnitClass * obj = Units.Ptr(index);
   1031 			if (obj != NULL &&
   1032 					!obj->IsInLimbo &&
   1033 					!obj->House->Is_Ally(House) &&
   1034 					obj->Class->IsJammer &&
   1035 					Distance(obj) <= Rule.RadarJamRadius) {
   1036 
   1037 				IsJammed = true;
   1038 				break;
   1039 			}
   1040 		}
   1041 	}
   1042 
   1043 	/*
   1044 	** Chronosphere active animation control.
   1045 	*/
   1046 	if (*this == STRUCT_CHRONOSPHERE && BState == BSTATE_ACTIVE && QueueBState == BSTATE_NONE && Scen.FadeTimer == 0) {
   1047 		Begin_Mode(BSTATE_IDLE);
   1048 	}
   1049 }
   1050 
   1051 
   1052 /***********************************************************************************************
   1053  * BuildingClass::Unlimbo -- Removes a building from limbo state.                              *
   1054  *                                                                                             *
   1055  *    Use this routine to transform a building that has been held in limbo                     *
   1056  *    state, into one that really exists on the map. Once a building as                        *
   1057  *    been unlimboed, then it becomes a normal object in the game world.                       *
   1058  *                                                                                             *
   1059  * INPUT:   pos   -- The position to place the building on the map.                            *
   1060  *                                                                                             *
   1061  *          dir (optional) -- not used for this class                                          *
   1062  *                                                                                             *
   1063  * OUTPUT:  bool; Was the unlimbo successful?                                                  *
   1064  *                                                                                             *
   1065  * WARNINGS:   The unlimbo operation might not be successful if the                            *
   1066  *             building could not be placed at the location specified.                         *
   1067  *                                                                                             *
   1068  * HISTORY:                                                                                    *
   1069  *   04/16/1994 JLB : Created.                                                                 *
   1070  *   06/07/1994 JLB : Matches virtual function format for base class.                          *
   1071  *   05/09/1995 JLB : Handles wall placement.                                                  *
   1072  *   06/18/1995 JLB : Checks for wall legality before placing down.                            *
   1073  *=============================================================================================*/
   1074 bool BuildingClass::Unlimbo(COORDINATE coord, DirType dir)
   1075 {
   1076 	assert(Buildings.ID(this) == ID);
   1077 	assert(IsActive);
   1078 
   1079 	/*
   1080 	**	If this is a wall type building, then it never gets unlimboed. Instead, it gets
   1081 	**	converted to an overlay type.
   1082 	*/
   1083 	if (Class->IsWall) {
   1084 		if (Can_Enter_Cell(Coord_Cell(coord), FACING_NONE) == MOVE_OK) {
   1085 			OverlayType otype = OVERLAY_NONE;
   1086 			switch (Class->Type) {
   1087 				case STRUCT_SANDBAG_WALL:
   1088 					otype	= OVERLAY_SANDBAG_WALL;
   1089 					break;
   1090 
   1091 				case STRUCT_CYCLONE_WALL:
   1092 					otype = OVERLAY_CYCLONE_WALL;
   1093 					break;
   1094 
   1095 				case STRUCT_BRICK_WALL:
   1096 					otype = OVERLAY_BRICK_WALL;
   1097 					break;
   1098 
   1099 				case STRUCT_BARBWIRE_WALL:
   1100 					otype = OVERLAY_BARBWIRE_WALL;
   1101 					break;
   1102 
   1103 				case STRUCT_WOOD_WALL:
   1104 					otype = OVERLAY_WOOD_WALL;
   1105 					break;
   1106 
   1107 				case STRUCT_FENCE:
   1108 					otype = OVERLAY_FENCE;
   1109 					break;
   1110 
   1111 				default:
   1112 					otype = OVERLAY_NONE;
   1113 					break;
   1114 
   1115 			}
   1116 			if (otype != OVERLAY_NONE) {
   1117 				ObjectClass * o = OverlayTypeClass::As_Reference(otype).Create_One_Of(House);
   1118 				if (o && o->Unlimbo(coord)) {
   1119 					Map[coord].Owner = House->Class->House;
   1120 					Transmit_Message(RADIO_OVER_OUT);
   1121 					Map.Sight_From(Coord_Cell(coord), Class->SightRange, House);
   1122 					delete this;
   1123 					return(true);
   1124 				}
   1125 			}
   1126 		}
   1127 		return(false);
   1128 	}
   1129 
   1130 	/*
   1131 	**	Normal building unlimbo process.
   1132 	*/
   1133 	if (TechnoClass::Unlimbo(coord, dir)) {
   1134 
   1135 		/*
   1136 		**	Ensure that the owning house knows about the
   1137 		**	new object.
   1138 		*/
   1139 		House->BScan |= (1L << Class->Type);
   1140 		House->ActiveBScan |= (1L << Class->Type);
   1141 
   1142 		/*
   1143 		**	Recalculate the center point of the house's base.
   1144 		*/
   1145 		House->Recalc_Center();
   1146 
   1147 		/*
   1148 		**	Update the total factory type, assuming this building has a factory.
   1149 		*/
   1150 		House->Active_Add(this);
   1151 
   1152 		/*
   1153 		**	Possibly the sidebar will be affected by this addition.
   1154 		*/
   1155 		House->IsRecalcNeeded = true;
   1156 		LastStrength = 0;
   1157 
   1158 		// Changes to support client/server multiplayer. ST - 8/2/2019 2:36PM
   1159 		//if ((!IsDiscoveredByPlayer && Map[coord].IsVisible) || Session.Type != GAME_NORMAL) {
   1160 		if ((!Is_Discovered_By_Player(House) && Map[coord].Is_Visible(House)) || Session.Type != GAME_NORMAL) {
   1161 			if (House->IsHuman) {
   1162 				//Revealed(PlayerPtr);
   1163 				Revealed(House);
   1164 			}
   1165 		}
   1166 		if (!House->IsHuman) {
   1167 			Revealed(House);
   1168 		}
   1169 
   1170 		// Changes to support client/server multiplayer. ST - 8/2/2019 2:36PM
   1171 		//if (IsOwnedByPlayer) {
   1172 		if (Is_Owned_By_Player()) {
   1173 			Map.PowerClass::IsToRedraw = true;
   1174 			Map.Flag_To_Redraw(false);
   1175 		}
   1176 
   1177 		if ((Class->Ownable & (HOUSEF_GOOD | HOUSEF_BAD)) != (HOUSEF_GOOD | HOUSEF_BAD)) {
   1178 			if (Class->Ownable & HOUSEF_GOOD) {
   1179 				ActLike = HOUSE_GREECE;
   1180 			} else {
   1181 				ActLike = HOUSE_USSR;
   1182 			}
   1183 		}
   1184 
   1185 		return(true);
   1186 	}
   1187 	return(false);
   1188 }
   1189 
   1190 
   1191 /***********************************************************************************************
   1192  * BuildingClass::Take_Damage -- Inflicts damage points upon a building.                       *
   1193  *                                                                                             *
   1194  *    This routine will inflict damage points upon the specified building.                     *
   1195  *    It will handle the damage animation and building destruction. Use                        *
   1196  *    this routine whenever a building is attacked.                                            *
   1197  *                                                                                             *
   1198  * INPUT:   damage   -- Amount of damage to inflict.                                           *
   1199  *                                                                                             *
   1200  *          distance -- The distance from the damage center point to the object's center point.*
   1201  *                                                                                             *
   1202  *          warhead  -- The kind of damage to inflict.                                         *
   1203  *                                                                                             *
   1204  *          source   -- The source of the damage. This is used to change targeting.            *
   1205  *                                                                                             *
   1206  *          forced   -- Is the damage forced upon the object regardless of whether it          *
   1207  *                      is normally immune?                                                    *
   1208  *                                                                                             *
   1209  * OUTPUT:  true/false; Was the building destroyed?                                            *
   1210  *                                                                                             *
   1211  * WARNINGS:   none                                                                            *
   1212  *                                                                                             *
   1213  * HISTORY:                                                                                    *
   1214  *   07/21/1991     : Created.                                                                 *
   1215  *   04/15/1994 JLB : Converted to member function.                                            *
   1216  *   04/16/1994 JLB : Added warhead modifier to damage.                                        *
   1217  *   06/03/1994 JLB : Added source of damage as target value.                                  *
   1218  *   06/20/1994 JLB : Source is a base class pointer.                                          *
   1219  *   11/22/1994 JLB : Shares base damage handler for techno objects.                           *
   1220  *   07/15/1995 JLB : Power ratio gets adjusted.                                               *
   1221  *=============================================================================================*/
   1222 ResultType BuildingClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, bool forced)
   1223 {
   1224 	assert(Buildings.ID(this) == ID);
   1225 	assert(IsActive);
   1226 
   1227 	ResultType res = RESULT_NONE;
   1228 	int shakes;
   1229 
   1230 	if (this != source /*&& !Class->IsInsignificant*/) {
   1231 
   1232 		if (source) {
   1233 			House->LATime = Frame;
   1234 			House->LAType = source->What_Am_I();
   1235 			House->LAZone = House->Which_Zone(this);
   1236 			House->LAEnemy = source->Owner();
   1237 
   1238 			if (!House->Is_Ally(source)) {
   1239 				House->Enemy = source->Owner();
   1240 			}
   1241 
   1242 			Base_Is_Attacked(source);
   1243 		}
   1244 
   1245 		short const * offset = Occupy_List();
   1246 
   1247 		/*
   1248 		** Memorize who they used to be in radio contact with.
   1249 		*/
   1250 		TechnoClass *tech = Contact_With_Whom();
   1251 		/*
   1252 		**	Perform the low level damage assessment.
   1253 		*/
   1254 		res = TechnoClass::Take_Damage(damage, distance, warhead, source, forced);
   1255 		switch (res) {
   1256 			case RESULT_DESTROYED:
   1257 
   1258 				/*
   1259 				**	Add the building to the base prebuild list if allowed. This will force
   1260 				**	the computer to rebuild this structure if it can.
   1261 				*/
   1262 				if (IsToRebuild && Class->Level != -1 && Base.House == House->Class->House && Base.Get_Node(this) == 0) {
   1263 //				if (IsToRebuild && Class->IsBuildable && Base.House == House->Class->House && Base.Get_Node(this) == 0) {
   1264 					Base.Nodes.Add(BaseNodeClass(Class->Type, Coord_Cell(Coord)));
   1265 				}
   1266 
   1267 				/*
   1268 				**	Destroy all attached objects.
   1269 				*/
   1270 				while (Attached_Object()) {
   1271 					FootClass * obj = Detach_Object();
   1272 
   1273 					Detach_All(true);
   1274 					delete obj;
   1275 				}
   1276 
   1277 				/*
   1278 				** If we were in contact with a landed plane, blow the plane up too.
   1279 				*/
   1280 				if (tech && tech->IsActive && tech->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass *)tech)->Class->IsFixedWing && ((AircraftClass *)tech)->In_Which_Layer() == LAYER_GROUND) {
   1281 					int damage = 500;
   1282 					tech->Take_Damage(damage, 0, WARHEAD_AP, source, forced);
   1283 				}
   1284 
   1285 				Sound_Effect(VOC_KABOOM22, Coord);
   1286 				while (*offset != REFRESH_EOL) {
   1287 					CELL cell = Coord_Cell(Coord) + *offset++;
   1288 
   1289 					/*
   1290 					**	If the building is destroyed, then lots of
   1291 					**	explosions occur.
   1292 					*/
   1293 					new SmudgeClass(Random_Pick(SMUDGE_CRATER1, SMUDGE_CRATER6), Cell_Coord(cell));
   1294 					if (Percent_Chance(50)) {
   1295 						new AnimClass(ANIM_FIRE_SMALL, Coord_Scatter(Cell_Coord(cell), 0x0080), Random_Pick(0, 7), Random_Pick(1, 3));
   1296 						if (Percent_Chance(50)) {
   1297 							new AnimClass(ANIM_FIRE_MED, Coord_Scatter(Cell_Coord(cell), 0x0040), Random_Pick(0, 7), Random_Pick(1, 3));
   1298 						}
   1299 					}
   1300 					new AnimClass(ANIM_FBALL1, Coord_Scatter(Cell_Coord(cell), 0x0040), Random_Pick(0, 3));
   1301 				}
   1302 
   1303 				shakes = Class->Cost_Of() / 400;
   1304 				if (shakes) {
   1305 					Shake_The_Screen(shakes, Owner());
   1306 					if (source && Owner() != source->Owner()) {
   1307 						Shake_The_Screen(shakes, source->Owner());
   1308 					}
   1309 				}
   1310 				Sound_Effect(VOC_CRUMBLE, Coord);
   1311 				if (Mission == MISSION_DECONSTRUCTION) {
   1312 					CountDown = 0;
   1313 					Set_Rate(0);
   1314 				} else {
   1315 					CountDown = 8;
   1316 				}
   1317 
   1318 				/*
   1319 				**	If it is in radio contact and the object seems to be attached, then tell
   1320 				**	it to run away.
   1321 				*/
   1322 				if (In_Radio_Contact() && Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {
   1323 					Transmit_Message(RADIO_RUN_AWAY);
   1324 				}
   1325 
   1326 				/*
   1327 				**	A force destruction will not generate survivors.
   1328 				*/
   1329 				if (forced || *this == STRUCT_KENNEL) {
   1330 					IsSurvivorless = true;
   1331 				}
   1332 
   1333 				/*
   1334 				** Destruction of a radar facility or advanced communications
   1335 				** center will cause the spiedby field to change...
   1336 				*/
   1337 				if (SpiedBy) {
   1338 					SpiedBy = 0;
   1339 					StructType struc = *this;
   1340 					if (struc == STRUCT_RADAR /* || struc == STRUCT_EYE */) {
   1341 						Update_Radar_Spied();
   1342 					}
   1343 				}
   1344 
   1345 				/*
   1346 				** Destruction of a gap generator will cause the cells it affects
   1347 				** to stop being jammed.
   1348 				*/
   1349 				if (*this == STRUCT_GAP) {
   1350 					Remove_Gap_Effect();
   1351 				}
   1352 
   1353 				/*
   1354 				** Destruction of a shipyard or sub pen may cause attached ships
   1355 				** who are repairing themselves to discontinue repairs.
   1356 				*/
   1357 				if (*this == STRUCT_SHIP_YARD || *this == STRUCT_SUB_PEN) {
   1358 					for (int index = 0; index < Vessels.Count(); index++) {
   1359 						VesselClass *obj = Vessels.Ptr(index);
   1360 						if (obj && !obj->IsInLimbo && obj->House == House) {
   1361 							if (obj->IsSelfRepairing) {
   1362 								if (::Distance(Center_Coord(), obj->Center_Coord()) < 0x0200) {
   1363 									obj->IsSelfRepairing = false;
   1364 									obj->IsToSelfRepair = false;
   1365 								}
   1366 							}
   1367 						}
   1368 					}
   1369 				}
   1370 
   1371 				/*
   1372 				** Destruction of a barrel will cause the surrounding squares to
   1373 				** be hit with damage.
   1374 				*/
   1375 				if (*this == STRUCT_BARREL || *this == STRUCT_BARREL3) {
   1376 					COORDINATE center = Center_Coord();
   1377 					CELL cellcenter = Coord_Cell(center);
   1378 
   1379 					BulletClass * bullet;
   1380 
   1381 					bullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_N)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);
   1382 					if (bullet) {
   1383 						bullet->Unlimbo(center, DIR_N);
   1384 					}
   1385 
   1386 					bullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_E)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);
   1387 					if (bullet) {
   1388 						bullet->Unlimbo(center, DIR_E);
   1389 					}
   1390 
   1391 					bullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_S)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);
   1392 					if (bullet) {
   1393 						bullet->Unlimbo(center, DIR_S);
   1394 					}
   1395 
   1396 					bullet = new BulletClass(BULLET_INVISIBLE, ::As_Target(Adjacent_Cell(cellcenter, FACING_W)), 0, 200, WARHEAD_FIRE, MPH_MEDIUM_FAST);
   1397 					if (bullet) {
   1398 						bullet->Unlimbo(center, DIR_W);
   1399 					}
   1400 				}
   1401 
   1402 				if (House) {
   1403 					House->Check_Pertinent_Structures();
   1404 				}
   1405 
   1406 				break;
   1407 
   1408 			case RESULT_HALF:
   1409 				if (*this == STRUCT_PUMP) {
   1410 					AnimClass * anim = new AnimClass(ANIM_OILFIELD_BURN, Coord_Add(Coord, 0x00400130L), 1);
   1411 					if (anim) {
   1412 						anim->Attach_To(this);
   1413 					}
   1414 				}
   1415 				// Fall into next case.
   1416 
   1417 			case RESULT_MAJOR:
   1418 				Sound_Effect(VOC_KABOOM1, Coord);
   1419 				while (*offset != REFRESH_EOL) {
   1420 					CELL cell = Coord_Cell(Coord) + *offset++;
   1421 					AnimClass * anim = NULL;
   1422 
   1423 					/*
   1424 					**	Show pieces of fire to indicate that a significant change in
   1425 					**	damage level has occurred.
   1426 					*/
   1427 					if (warhead == WARHEAD_FIRE) {
   1428 						switch (Random_Pick(0, 5+Class->Width()+Class->Height())) {
   1429 							case 0:
   1430 								break;
   1431 
   1432 							case 1:
   1433 							case 2:
   1434 							case 3:
   1435 							case 4:
   1436 							case 5:
   1437 								anim = new AnimClass(ANIM_ON_FIRE_SMALL, Coord_Scatter(Cell_Coord(cell), 0x0060), 0, Random_Pick(1, 3));
   1438 								break;
   1439 
   1440 							case 6:
   1441 							case 7:
   1442 							case 8:
   1443 								anim = new AnimClass(ANIM_ON_FIRE_MED, Coord_Scatter(Cell_Coord(cell), 0x0060), 0, Random_Pick(1, 3));
   1444 								break;
   1445 
   1446 							case 9:
   1447 								anim = new AnimClass(ANIM_ON_FIRE_BIG, Coord_Scatter(Cell_Coord(cell), 0x0060), 0, 1);
   1448 								break;
   1449 
   1450 							default:
   1451 								break;
   1452 						}
   1453 					} else {
   1454 						if (Percent_Chance(50)) {
   1455 							/*
   1456 							** Building may catch on fire, but only if it wasn't a
   1457 							** renovator that caused the damage.
   1458 							*/
   1459 							if (source == NULL || source->What_Am_I() != RTTI_INFANTRY || *(InfantryClass *)source != INFANTRY_RENOVATOR) {
   1460 								anim = new AnimClass(ANIM_FIRE_SMALL, Coord_Scatter(Cell_Coord(cell), 0x0060), Random_Pick(0, 7), Random_Pick(1, 3));
   1461 							}
   1462 						}
   1463 					}
   1464 					/*
   1465 					**	If the animation was created, then attach it to the building.
   1466 					*/
   1467 					if (anim) {
   1468 						anim->Attach_To(this);
   1469 					}
   1470 				}
   1471 				break;
   1472 
   1473 			case RESULT_NONE:
   1474 				break;
   1475 
   1476 			case RESULT_LIGHT:
   1477 				break;
   1478 		}
   1479 
   1480 		if (source && res != RESULT_NONE) {
   1481 
   1482 			/*
   1483 			**	If any damage occurred, then inform the house of this fact. If it is the player's
   1484 			**	house, it might announce this fact.
   1485 			*/
   1486 			if (!Class->IsInsignificant) {
   1487 				House->Attacked(this);
   1488 			}
   1489 
   1490 			/*
   1491 			** Save the type of the house that's doing the damage, so if the building burns
   1492 			** to death credit can still be given for the kill
   1493 			*/
   1494 			WhoLastHurtMe = source->Owner();
   1495 
   1496 			/*
   1497 			**	When certain buildings are hit, they "snap out of it" and
   1498 			**	return fire if they are able and allowed.
   1499 			*/
   1500 			if (*this != STRUCT_SAM && *this != STRUCT_AAGUN &&
   1501 				!House->Is_Ally(source) &&
   1502 				Class->PrimaryWeapon != NULL &&
   1503 				(!Target_Legal(TarCom) || !In_Range(TarCom))) {
   1504 
   1505 				if (source->What_Am_I() != RTTI_AIRCRAFT && (!House->IsHuman || Rule.IsSmartDefense)) {
   1506 					Assign_Target(source->As_Target());
   1507 				} else {
   1508 
   1509 					/*
   1510 					**	Generate a random rotation effect since there is nothing else that this
   1511 					**	building can do.
   1512 					*/
   1513 					if (!PrimaryFacing.Is_Rotating()) {
   1514 						PrimaryFacing.Set_Desired(Random_Pick(DIR_N, DIR_MAX));
   1515 					}
   1516 				}
   1517 			}
   1518 		}
   1519 	}
   1520 
   1521 	return(res);
   1522 }
   1523 
   1524 
   1525 /***********************************************************************************************
   1526  * BuildingClass::new -- Allocates a building object from building pool.                       *
   1527  *                                                                                             *
   1528  *    This routine will allocate a building slot from the building alloc                       *
   1529  *    system.                                                                                  *
   1530  *                                                                                             *
   1531  * INPUT:   none                                                                               *
   1532  *                                                                                             *
   1533  * OUTPUT:  Returns with a pointer to the allocated building. If NULL is                       *
   1534  *          returned, then this indicates a failure to allocate.                               *
   1535  *                                                                                             *
   1536  * WARNINGS:   none                                                                            *
   1537  *                                                                                             *
   1538  * HISTORY:                                                                                    *
   1539  *   04/11/1994 JLB : Created.                                                                 *
   1540  *   04/21/1994 JLB : Converted to operator new.                                               *
   1541  *   05/17/1994 JLB : Revamped allocation scheme                                               *
   1542  *   07/29/1994 JLB : Simplified.                                                              *
   1543  *=============================================================================================*/
   1544 void * BuildingClass::operator new(size_t )
   1545 {
   1546 	void * ptr = Buildings.Allocate();
   1547 	if (ptr) {
   1548 		((BuildingClass *)ptr)->Set_Active();
   1549 	}
   1550 	return(ptr);
   1551 }
   1552 
   1553 
   1554 /***********************************************************************************************
   1555  * BuildingClass::delete -- Deallocates building object.                                       *
   1556  *                                                                                             *
   1557  *    This is the memory deallocation operation for a building object.                         *
   1558  *    Since buildings are allocated out of a fixed memory block, all that                      *
   1559  *    is needed is to flag the unit as inactive.                                               *
   1560  *                                                                                             *
   1561  * INPUT:   ptr   -- Pointer to building to deallocate.                                        *
   1562  *                                                                                             *
   1563  * OUTPUT:  none                                                                               *
   1564  *                                                                                             *
   1565  * WARNINGS:   none                                                                            *
   1566  *                                                                                             *
   1567  * HISTORY:                                                                                    *
   1568  *   04/21/1994 JLB : Created.                                                                 *
   1569  *=============================================================================================*/
   1570 void BuildingClass::operator delete(void *ptr)
   1571 {
   1572 	if (ptr) {
   1573 		((BuildingClass *)ptr)->IsActive = false;
   1574 	}
   1575 	Buildings.Free((BuildingClass *)ptr);
   1576 }
   1577 
   1578 
   1579 /***********************************************************************************************
   1580  * BuildingClass::BuildingClass -- Constructor for buildings.                                  *
   1581  *                                                                                             *
   1582  *    This routine inserts a building into the object tracking system.                         *
   1583  *    It is placed into a limbo state unless a location is provided for                        *
   1584  *    it to unlimbo at.                                                                        *
   1585  *                                                                                             *
   1586  * INPUT:   type  -- The structure type to make this object.                                   *
   1587  *                                                                                             *
   1588  *          house -- The owner of this building.                                               *
   1589  *                                                                                             *
   1590  *          pos   -- The position to unlimbo the building. If -1 is                            *
   1591  *                   specified, then the building remains in a limbo                           *
   1592  *                   state.                                                                    *
   1593  *                                                                                             *
   1594  * OUTPUT:  none                                                                               *
   1595  *                                                                                             *
   1596  * WARNINGS:   none                                                                            *
   1597  *                                                                                             *
   1598  * HISTORY:                                                                                    *
   1599  *   04/21/1994 JLB : Created.                                                                 *
   1600  *   08/07/1995 JLB : Fixed act like value to match expected value.                            *
   1601  *=============================================================================================*/
   1602 BuildingClass::BuildingClass(StructType type, HousesType house) :
   1603 	TechnoClass(RTTI_BUILDING, Buildings.ID(this), house),
   1604 	Class(BuildingTypes.Ptr((int)type)),
   1605 	Factory(0),
   1606 	ActLike(House->ActLike),
   1607 	IsToRebuild(false),
   1608 	IsToRepair(false),
   1609 	IsAllowedToSell(true),
   1610 	IsReadyToCommence(false),
   1611 	IsRepairing(false),
   1612 	IsWrenchVisible(false),
   1613 	IsGoingToBlow(false),
   1614 	IsSurvivorless(false),
   1615 	IsCharging(false),
   1616 	IsCharged(false),
   1617 	IsCaptured(false),
   1618 	IsJamming(false),
   1619 	IsJammed(false),
   1620 	HasFired(false),
   1621 	HasOpened(false),
   1622 	CountDown(0),
   1623 	BState(BSTATE_NONE),
   1624 	QueueBState(BSTATE_NONE),
   1625 	WhoLastHurtMe(house),
   1626 	WhomToRepay(TARGET_NONE),
   1627 	AnimToTrack(TARGET_NONE),
   1628 	LastStrength(0),
   1629 	PlacementDelay(0)
   1630 {
   1631 	House->Tracking_Add(this);
   1632 	IsSecondShot = !Class->Is_Two_Shooter();
   1633 	Strength = Class->MaxStrength;
   1634 	Ammo = Class->MaxAmmo;
   1635 
   1636 	/*
   1637 	**	If the building could never be built, then it can never be sold either. This
   1638 	**	is due to the lack of buildup animation.
   1639 	*/
   1640 	if (Class->Get_Buildup_Data() != NULL) {
   1641 //	if (!Class->IsBuildable) {
   1642 		IsAllowedToSell = false;
   1643 	}
   1644 
   1645 //	if (Session.Type == GAME_INTERNET) {
   1646 //		House->BuildingTotals->Increment_Unit_Total( (int) type);
   1647 //	}
   1648 
   1649 }
   1650 
   1651 
   1652 /***********************************************************************************************
   1653  * BuildingClass::~BuildingClass -- Destructor for building type objects.                      *
   1654  *                                                                                             *
   1655  *    This destructor for building objects will put the building in limbo if possible.         *
   1656  *                                                                                             *
   1657  * INPUT:   none                                                                               *
   1658  *                                                                                             *
   1659  * OUTPUT:  none                                                                               *
   1660  *                                                                                             *
   1661  * WARNINGS:   none                                                                            *
   1662  *                                                                                             *
   1663  * HISTORY:                                                                                    *
   1664  *   01/18/1995 JLB : Created.                                                                 *
   1665  *=============================================================================================*/
   1666 BuildingClass::~BuildingClass(void)
   1667 {
   1668 	if (GameActive && Class) {
   1669 		if (House) {
   1670 			House->Tracking_Remove(this);
   1671 		}
   1672 		BuildingClass::Limbo();
   1673 	}
   1674 	Class = 0;
   1675 
   1676 	delete (FactoryClass *)Factory;
   1677 	Factory = 0;
   1678 	ID = -1;
   1679 }
   1680 
   1681 
   1682 /***********************************************************************************************
   1683  * BuildingClass::Drop_Debris -- Drops rubble when building is destroyed.                      *
   1684  *                                                                                             *
   1685  *    This routine is called when a building is destroyed. It handles                          *
   1686  *    placing the rubble down.                                                                 *
   1687  *                                                                                             *
   1688  * INPUT:   none                                                                               *
   1689  *                                                                                             *
   1690  * OUTPUT:  none                                                                               *
   1691  *                                                                                             *
   1692  * WARNINGS:   none                                                                            *
   1693  *                                                                                             *
   1694  * HISTORY:                                                                                    *
   1695  *   05/14/1994 JLB : Created.                                                                 *
   1696  *   06/13/1995 JLB : Added smoke and normal infantry survivor possibility.                    *
   1697  *   07/16/1995 JLB : Survival rate depends on if captured or sabotaged.                       *
   1698  *=============================================================================================*/
   1699 void BuildingClass::Drop_Debris(TARGET source)
   1700 {
   1701 	assert(Buildings.ID(this) == ID);
   1702 	assert(IsActive);
   1703 
   1704 	CELL const * offset;
   1705 	CELL cell;
   1706 
   1707 	/*
   1708 	**	Generate random survivors from the destroyed building.
   1709 	*/
   1710 	cell = Coord_Cell(Coord);
   1711 	offset = Occupy_List();
   1712 	int odds = 2;
   1713 	if (Target_Legal(WhomToRepay)) odds -= 1;
   1714 	if (IsCaptured) odds += 6;
   1715 	int count = How_Many_Survivors();
   1716 	while (*offset != REFRESH_EOL) {
   1717 		CELL	newcell;
   1718 
   1719 		newcell = cell + *offset++;
   1720 		CellClass const * cellptr = &Map[newcell];
   1721 
   1722 		/*
   1723 		**	Infantry could run out of a destroyed building.
   1724 		*/
   1725 		if (!House->IsToDie && count > 0) {
   1726 			InfantryClass * i = NULL;
   1727 
   1728 			if (Random_Pick(0, odds) == 1) {
   1729 				i = NULL;
   1730 				InfantryType typ = Crew_Type();
   1731 				if (typ != INFANTRY_NONE) i = new InfantryClass(typ, House->Class->House);
   1732 				if (i != NULL) {
   1733 					if (Class->Get_Buildup_Data() != NULL && i->Class->IsNominal) i->IsTechnician = true;
   1734 					ScenarioInit++;
   1735 					if (i->Unlimbo(Cell_Coord(newcell), DIR_N)) {
   1736 						count--;
   1737 						i->Strength = Random_Pick(5, (int)i->Class->MaxStrength);
   1738 						i->Scatter(0, true);
   1739 						if (source != TARGET_NONE && !House->Is_Ally(As_Object(source))) {
   1740 							i->Assign_Mission(MISSION_ATTACK);
   1741 							i->Assign_Target(source);
   1742 						} else {
   1743 							if (House->IsHuman) {
   1744 								i->Assign_Mission(MISSION_GUARD);
   1745 							} else {
   1746 								i->Assign_Mission(MISSION_HUNT);
   1747 							}
   1748 						}
   1749 					} else {
   1750 						delete i;
   1751 					}
   1752 					ScenarioInit--;
   1753 				}
   1754 			}
   1755 		}
   1756 
   1757 		/*
   1758 		**	Smoke and fire only appear on terrestrail cells. They should not appear on
   1759 		**	rivers, clifs, or water cells.
   1760 		*/
   1761 		if (cellptr->Is_Clear_To_Move(SPEED_TRACK, true, true)) {
   1762 
   1763 			/*
   1764 			**	Possibly add some smoke rising from the ashes of the building.
   1765 			*/
   1766 			switch (Random_Pick(0, 5)) {
   1767 				case 0:
   1768 				case 1:
   1769 				case 2:
   1770 					new AnimClass(ANIM_SMOKE_M, Coord_Scatter(Cell_Coord(newcell), 0x0050, false), Random_Pick(0, 5), Random_Pick(1, 2));
   1771 					break;
   1772 
   1773 				default:
   1774 					break;
   1775 			}
   1776 
   1777 			/*
   1778 			**	The building always scars the ground in some fashion.
   1779 			*/
   1780 			if (Percent_Chance(25)) {
   1781 				new SmudgeClass(Random_Pick(SMUDGE_SCORCH1, SMUDGE_SCORCH6), Cell_Coord(newcell));
   1782 			} else {
   1783 				new SmudgeClass(Random_Pick(SMUDGE_CRATER1, SMUDGE_CRATER6), Coord_Scatter(Cell_Coord(newcell), 0x0080, false));
   1784 			}
   1785 		}
   1786 	}
   1787 }
   1788 
   1789 
   1790 /***********************************************************************************************
   1791  * BuildingClass::Active_Click_With -- Handles clicking on the map while the building is selected.*
   1792  *                                                                                             *
   1793  *    This interface routine handles when the player clicks on the map while this building     *
   1794  *    is currently selected. This is used to assign an override target to a turret or          *
   1795  *    guard tower.                                                                             *
   1796  *                                                                                             *
   1797  * INPUT:   target   -- The target that was clicked upon.                                      *
   1798  *                                                                                             *
   1799  * OUTPUT:  none                                                                               *
   1800  *                                                                                             *
   1801  * WARNINGS:   none                                                                            *
   1802  *                                                                                             *
   1803  * HISTORY:                                                                                    *
   1804  *   05/28/1994 JLB : Created.                                                                 *
   1805  *=============================================================================================*/
   1806 void BuildingClass::Active_Click_With(ActionType action, ObjectClass * object)
   1807 {
   1808 	assert(Buildings.ID(this) == ID);
   1809 	assert(IsActive);
   1810 
   1811 	if (action == ACTION_ATTACK && object != NULL) {
   1812 		Player_Assign_Mission(MISSION_ATTACK, object->As_Target());
   1813 	}
   1814 
   1815 	if (action == ACTION_TOGGLE_PRIMARY && Class->Is_Factory()) {
   1816 		OutList.Add(EventClass(EventClass::PRIMARY, TargetClass(this)));
   1817 	}
   1818 }
   1819 
   1820 
   1821 /***********************************************************************************************
   1822  * BuildingClass::Active_Click_With -- Handles cell selection for buildings.                   *
   1823  *                                                                                             *
   1824  *    This routine really only serves one purpose -- to allow targeting of the ground for      *
   1825  *    buildings that are equipped with weapons.                                                *
   1826  *                                                                                             *
   1827  * INPUT:   action   -- The requested action to perform.                                       *
   1828  *                                                                                             *
   1829  *          cell     -- The cell location to perform the action upon.                          *
   1830  *                                                                                             *
   1831  * OUTPUT:  none                                                                               *
   1832  *                                                                                             *
   1833  * WARNINGS:   none                                                                            *
   1834  *                                                                                             *
   1835  * HISTORY:                                                                                    *
   1836  *   07/04/1995 JLB : Created.                                                                 *
   1837  *   10/04/1995 JLB : Handles construction yard undeploy to move logic.                        *
   1838  *=============================================================================================*/
   1839 void BuildingClass::Active_Click_With(ActionType action, CELL cell)
   1840 {
   1841 	assert(Buildings.ID(this) == ID);
   1842 	assert(IsActive);
   1843 
   1844 	if (action == ACTION_ATTACK) {
   1845 		Player_Assign_Mission(MISSION_ATTACK, ::As_Target(cell));
   1846 	}
   1847 
   1848 	if (action == ACTION_MOVE && *this == STRUCT_CONST) {
   1849 		OutList.Add(EventClass(EventClass::ARCHIVE, TargetClass(this), TargetClass(::As_Target(cell))));
   1850 		OutList.Add(EventClass(EventClass::SELL, TargetClass(this)));
   1851 
   1852 		COORDINATE coord = Map.Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y());
   1853 		OutList.Add(EventClass(ANIM_MOVE_FLASH, PlayerPtr->Class->House, coord, 1 << PlayerPtr->Class->House));
   1854 	}
   1855 }
   1856 
   1857 
   1858 /***********************************************************************************************
   1859  * BuildingClass::Assign_Target -- Assigns a target to the building.                           *
   1860  *                                                                                             *
   1861  *    Assigning of a target to a building makes sense if the building is one that can attack.  *
   1862  *    This routine would be used to assign the attack target to a turret or guard tower.       *
   1863  *                                                                                             *
   1864  * INPUT:   target   -- The target that was clicked on while this building was selected.       *
   1865  *                                                                                             *
   1866  * OUTPUT:  none                                                                               *
   1867  *                                                                                             *
   1868  * WARNINGS:   none                                                                            *
   1869  *                                                                                             *
   1870  * HISTORY:                                                                                    *
   1871  *   05/28/1994 JLB : Created.                                                                 *
   1872  *   11/02/1994 JLB : Checks for range before assigning target.                                *
   1873  *=============================================================================================*/
   1874 void BuildingClass::Assign_Target(TARGET target)
   1875 {
   1876 	assert(Buildings.ID(this) == ID);
   1877 	assert(IsActive);
   1878 
   1879 	if (*this != STRUCT_SAM && *this != STRUCT_AAGUN && !In_Range(target, 0)) {
   1880 		target = TARGET_NONE;
   1881 	}
   1882 
   1883 	TechnoClass::Assign_Target(target);
   1884 }
   1885 
   1886 
   1887 /***********************************************************************************************
   1888  * BuildingClass::Init -- Initialize the building system to an empty null state.               *
   1889  *                                                                                             *
   1890  *    This routine initializes the building system in preparation for a scenario load.         *
   1891  *                                                                                             *
   1892  * INPUT:   none                                                                               *
   1893  *                                                                                             *
   1894  * OUTPUT:  none                                                                               *
   1895  *                                                                                             *
   1896  * WARNINGS:   none                                                                            *
   1897  *                                                                                             *
   1898  * HISTORY:                                                                                    *
   1899  *   09/19/1994 JLB : Created.                                                                 *
   1900  *=============================================================================================*/
   1901 void BuildingClass::Init(void)
   1902 {
   1903 	Buildings.Free_All();
   1904 }
   1905 
   1906 
   1907 /***********************************************************************************************
   1908  * BuildingClass::Exit_Object -- Initiates an object to leave the building.                    *
   1909  *                                                                                             *
   1910  *    This function is used to cause an object to exit the building. It is called when a       *
   1911  *    factory produces a vehicle or other mobile object and that object needs to exit the      *
   1912  *    building to join the ranks of a regular unit. Typically, the object is placed down on    *
   1913  *    the map such that it overlaps the building and then it is given a movement order so that *
   1914  *    it will move to an adjacent free cell.                                                   *
   1915  *                                                                                             *
   1916  * INPUT:   base  -- Pointer to the object that is to exit the building.                       *
   1917  *                                                                                             *
   1918  * OUTPUT:  Returns the success rating for the exit attempt;                                   *
   1919  *             0  = complete failure (refund money please)                                     *
   1920  *             1  = temporarily prevented (try again later please)                             *
   1921  *             2  = successful                                                                 *
   1922  *                                                                                             *
   1923  * WARNINGS:   The building is placed in radio contact with the object. The object is in a     *
   1924  *             tethered condition. This condition will be automatically broken when the        *
   1925  *             object reaches the adjacent square.                                             *
   1926  *                                                                                             *
   1927  * HISTORY:                                                                                    *
   1928  *   11/28/1994 JLB : Created.                                                                 *
   1929  *   04/10/1995 JLB : Handles building production by computer.                                 *
   1930  *   06/17/1995 JLB : Handles refinery exit.                                                   *
   1931  *=============================================================================================*/
   1932 int BuildingClass::Exit_Object(TechnoClass * base)
   1933 {
   1934 	assert(Buildings.ID(this) == ID);
   1935 	assert(IsActive);
   1936 
   1937 	if (!base) return(0);
   1938 
   1939 	TechnoTypeClass const * ttype = (TechnoTypeClass const *)&base->Class_Of();
   1940 
   1941 	/*
   1942 	**	A unit exiting a building is always considered to be "locked". That means, it
   1943 	**	will be considered as to have legally entered the visible map domain.
   1944 	*/
   1945 	base->IsLocked = true;
   1946 
   1947 	/*
   1948 	**	Find a good cell to unload the object to. The object, probably a vehicle
   1949 	**	will drive/walk to the adjacent free cell.
   1950 	*/
   1951 	CELL cell = 0;
   1952 
   1953 	switch (base->What_Am_I()) {
   1954 
   1955 		case RTTI_AIRCRAFT:
   1956 			if (!In_Radio_Contact()) {
   1957 				AircraftClass * air = (AircraftClass *)base;
   1958 
   1959 				air->Height = 0;
   1960 				ScenarioInit++;
   1961 				if (air->Unlimbo(Docking_Coord(), air->Pose_Dir())) {
   1962 					Transmit_Message(RADIO_HELLO, air);
   1963 					Transmit_Message(RADIO_TETHER);
   1964 					ScenarioInit--;
   1965 					return(2);
   1966 				}
   1967 				ScenarioInit--;
   1968 			} else {
   1969 				AircraftClass * air = (AircraftClass *)base;
   1970 
   1971 				if (Cell_X(Coord_Cell(Center_Coord())) - Map.MapCellX < Map.MapCellWidth/2) {
   1972 					cell = XY_Cell(Map.MapCellX-1, Random_Pick(0, Map.MapCellHeight-1)+Map.MapCellY);
   1973 				} else {
   1974 					cell = XY_Cell(Map.MapCellX+Map.MapCellWidth, Random_Pick(0, Map.MapCellHeight-1)+Map.MapCellY);
   1975 				}
   1976 				ScenarioInit++;
   1977 				if (air->Unlimbo(Cell_Coord(cell), DIR_N)) {
   1978 //BG				air->Assign_Destination(::As_Target(Nearby_Location(air)));
   1979 /*BG*/			air->Assign_Destination(::As_Target(air->Nearby_Location(this)));
   1980 					air->Assign_Mission(MISSION_MOVE);
   1981 					ScenarioInit--;
   1982 					return(2);
   1983 				}
   1984 				ScenarioInit--;
   1985 			}
   1986 			break;
   1987 
   1988 		case RTTI_VESSEL:
   1989 			switch (Class->Type) {
   1990 				case STRUCT_SUB_PEN:
   1991 				case STRUCT_SHIP_YARD:
   1992 					ScenarioInit++;
   1993 					cell = Find_Exit_Cell(base);
   1994 					if (cell != 0 && base->Unlimbo(Cell_Coord(cell), Direction(Cell_Coord(cell)))) {
   1995 						base->Assign_Mission(MISSION_GUARD);
   1996 						ScenarioInit--;
   1997 						return(2);
   1998 					}
   1999 					ScenarioInit--;
   2000 					break;
   2001 
   2002 				default:
   2003 					break;
   2004 			}
   2005 			break;
   2006 
   2007 		case RTTI_INFANTRY:
   2008 		case RTTI_UNIT:
   2009 			switch (Class->Type) {
   2010 				case STRUCT_REFINERY:
   2011 					if (base->What_Am_I() == RTTI_UNIT) {
   2012 						cell = Coord_Cell(Center_Coord());
   2013 						UnitClass * unit = (UnitClass *)base;
   2014 
   2015 						cell = Adjacent_Cell(cell, FACING_SW);
   2016 						ScenarioInit++;
   2017 						if (unit->Unlimbo(Cell_Coord(Adjacent_Cell(cell, DIR_S)), DIR_SW_X2)) {
   2018 							unit->PrimaryFacing = DIR_S;
   2019 							unit->Assign_Mission(MISSION_HARVEST);
   2020 						}
   2021 						ScenarioInit--;
   2022 					} else {
   2023 						base->Scatter(0, true);
   2024 					}
   2025 					break;
   2026 
   2027 				case STRUCT_WEAP:
   2028 					if (Mission == MISSION_UNLOAD) {
   2029 						for(int index = 0; index < Buildings.Count(); index++) {
   2030 							BuildingClass *bldg = Buildings.Ptr(index);
   2031 							if (bldg->Owner() == Owner() && *bldg == STRUCT_WEAP && bldg != this && bldg->Mission == MISSION_GUARD && !bldg->Factory) {
   2032 								FactoryClass * temp = Factory;
   2033 								bldg->Factory = Factory;
   2034 								Factory = 0;
   2035 								int retval = (bldg->Exit_Object(base));
   2036 								bldg->Factory = 0;
   2037 								Factory = temp;
   2038 								return(retval);
   2039 							}
   2040 						}
   2041 						return(1);	// fail while we're still unloading previous
   2042 					}
   2043 					ScenarioInit++;
   2044 					if (base->Unlimbo(Exit_Coord(), DIR_S)) {
   2045 						base->Mark(MARK_UP);
   2046 						base->Coord = Exit_Coord();
   2047 						base->Mark(MARK_DOWN);
   2048 						Transmit_Message(RADIO_HELLO, base);
   2049 						Transmit_Message(RADIO_TETHER);
   2050 						Assign_Mission(MISSION_UNLOAD);
   2051 						ScenarioInit--;
   2052 						return(2);
   2053 					}
   2054 					ScenarioInit--;
   2055 					break;
   2056 
   2057 				case STRUCT_BARRACKS:
   2058 				case STRUCT_TENT:
   2059 				case STRUCT_KENNEL:
   2060 
   2061 					cell = Find_Exit_Cell(base);
   2062 					if (cell != 0) {
   2063 						DirType	dir = Direction(cell);
   2064 						COORDINATE		start = Exit_Coord();
   2065 
   2066 						ScenarioInit++;
   2067 						if (base->Unlimbo(start, dir)) {
   2068 
   2069 							base->Assign_Mission(MISSION_MOVE);
   2070 
   2071 							/*
   2072 							**	When disembarking from a transport then guard an area around the
   2073 							**	center of the base.
   2074 							*/
   2075 							base->Assign_Destination(::As_Target(cell));
   2076 							if (House->IQ >= Rule.IQGuardArea) {
   2077 								base->Assign_Mission(MISSION_GUARD_AREA);
   2078 								base->ArchiveTarget = ::As_Target(House->Where_To_Go((FootClass *)base));
   2079 							}
   2080 
   2081 							/*
   2082 							**	Establish radio contact so unload coordination can occur. This
   2083 							**	radio contact should always succeed.
   2084 							*/
   2085 							if (Transmit_Message(RADIO_HELLO, base) == RADIO_ROGER) {
   2086 								Transmit_Message(RADIO_UNLOAD);
   2087 							}
   2088 							ScenarioInit--;
   2089 							return(2);
   2090 						}
   2091 						ScenarioInit--;
   2092 					}
   2093 					break;
   2094 
   2095 				default:
   2096 					cell = Find_Exit_Cell(base);
   2097 					if (cell != 0) {
   2098 						DirType	dir = Direction(cell);
   2099 						COORDINATE		start = Exit_Coord();
   2100 
   2101 						ScenarioInit++;
   2102 						if (base->Unlimbo(start, dir)) {
   2103 
   2104 							base->Assign_Mission(MISSION_MOVE);
   2105 
   2106 							/*
   2107 							**	When disembarking from a transport then guard an area around the
   2108 							**	center of the base.
   2109 							*/
   2110 							base->Assign_Destination(::As_Target(cell));
   2111 							if (House->IQ >= Rule.IQGuardArea) {
   2112 								base->Assign_Mission(MISSION_GUARD_AREA);
   2113 								base->ArchiveTarget = ::As_Target(House->Where_To_Go((FootClass *)base));
   2114 							}
   2115 							ScenarioInit--;
   2116 							return(2);
   2117 						}
   2118 						ScenarioInit--;
   2119 					}
   2120 					break;
   2121 			}
   2122 			break;
   2123 
   2124 		case RTTI_BUILDING:
   2125 
   2126 			if (!House->IsHuman) {
   2127 
   2128 				/*
   2129 				**	Find the next available spot to place this newly created building. If the
   2130 				**	building could be placed at the desired location, fine. If not, then this
   2131 				**	routine will return failure. The calling routine will probably abandon this
   2132 				**	building in preference to building another.
   2133 				*/
   2134 				BaseNodeClass * node = Base.Next_Buildable(((BuildingClass *)base)->Class->Type);
   2135 				COORDINATE coord = 0;
   2136 				if (node) {
   2137 					coord = Cell_Coord(node->Cell);
   2138 				} else {
   2139 
   2140 					/*
   2141 					**	Find a suitable new spot to place.
   2142 					*/
   2143 					coord = House->Find_Build_Location((BuildingClass *)base);
   2144 				}
   2145 
   2146 				if (coord) {
   2147 					if (Flush_For_Placement(base, Coord_Cell(coord))) {
   2148 						return(1);
   2149 					}
   2150 					if (base->Unlimbo(coord)) {
   2151 						if (node && ((BuildingClass *)base)->Class->Type == House->BuildStructure) {
   2152 							House->BuildStructure = STRUCT_NONE;
   2153 						}
   2154 						return(2);
   2155 					}
   2156 				}
   2157 			}
   2158 			break;
   2159 
   2160 		default:
   2161 			break;
   2162 	}
   2163 
   2164 	/*
   2165 	**	Failure to exit the object results in a false return value.
   2166 	*/
   2167 	return(0);
   2168 }
   2169 
   2170 
   2171 /***********************************************************************************************
   2172  * BuildingClass::Update_Buildables -- Informs sidebar of additional construction options.     *
   2173  *                                                                                             *
   2174  *    This routine will tell the sidebar of objects that can be built. The function is called  *
   2175  *    whenever a building matures.                                                             *
   2176  *                                                                                             *
   2177  * INPUT:   none                                                                               *
   2178  *                                                                                             *
   2179  * OUTPUT:  none                                                                               *
   2180  *                                                                                             *
   2181  * WARNINGS:   none                                                                            *
   2182  *                                                                                             *
   2183  * HISTORY:                                                                                    *
   2184  *   11/11/1994 JLB : Created.                                                                 *
   2185  *   12/23/1994 JLB : Only updates for PLAYER buildings.                                       *
   2186  *=============================================================================================*/
   2187 void BuildingClass::Update_Buildables(void)
   2188 {
   2189 	assert(Buildings.ID(this) == ID);
   2190 	assert(IsActive);
   2191 
   2192 	/*
   2193 	** Only do this for real human players. ST - 3/22/2019 1:38PM
   2194 	*/
   2195 	if (PlayerPtr != House) {
   2196 		if (Session.Type != GAME_GLYPHX_MULTIPLAYER || House->IsHuman == false) {
   2197 			return;
   2198 		}
   2199 	}
   2200 
   2201 	bool buildable_via_capture = (IsCaptured && ActLike != House->ActLike) ? true : false;
   2202 
   2203 	if (!IsInLimbo && Is_Discovered_By_Player()) {
   2204 		switch (Class->ToBuild) {
   2205 			int i;
   2206 			int u;
   2207 			int f;
   2208 			int a;
   2209 			int v;
   2210 
   2211 			case RTTI_VESSELTYPE:
   2212 				for (v = VESSEL_FIRST; v < VESSEL_COUNT; v++) {
   2213 					if (PlayerPtr->Can_Build(&VesselTypeClass::As_Reference((VesselType)v), ActLike)) {
   2214 						if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   2215 							Sidebar_Glyphx_Add(RTTI_VESSELTYPE, v, House, buildable_via_capture);
   2216 						} else {
   2217 							Map.Add(RTTI_VESSELTYPE, v, buildable_via_capture);
   2218 						}
   2219 					}
   2220 				}
   2221 				break;
   2222 
   2223 			case RTTI_BUILDINGTYPE:
   2224 				for (i = STRUCT_FIRST; i < STRUCT_COUNT; i++) {
   2225 					if (PlayerPtr->Can_Build(&BuildingTypeClass::As_Reference((StructType)i), ActLike)) {
   2226 						if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   2227 							Sidebar_Glyphx_Add(RTTI_BUILDINGTYPE, i, House, buildable_via_capture);
   2228 						} else {
   2229 							Map.Add(RTTI_BUILDINGTYPE, i, buildable_via_capture);
   2230 						}
   2231 					}
   2232 				}
   2233 				break;
   2234 
   2235 			case RTTI_UNITTYPE:
   2236 				for (u = UNIT_FIRST; u < UNIT_COUNT; u++) {
   2237 					if (PlayerPtr->Can_Build(&UnitTypeClass::As_Reference((UnitType)u), ActLike)) {
   2238 						if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   2239 							Sidebar_Glyphx_Add(RTTI_UNITTYPE, u, House, buildable_via_capture);
   2240 						} else {
   2241 							Map.Add(RTTI_UNITTYPE, u, buildable_via_capture);
   2242 						}
   2243 					}
   2244 				}
   2245 				break;
   2246 
   2247 			case RTTI_INFANTRYTYPE:
   2248 				for (f = INFANTRY_FIRST; f < INFANTRY_COUNT; f++) {
   2249 					if (PlayerPtr->Can_Build(&InfantryTypeClass::As_Reference((InfantryType)f), ActLike)) {
   2250 						if (InfantryTypeClass::As_Reference((InfantryType)f).IsDog) {
   2251 							if (*this == STRUCT_KENNEL) {
   2252 								if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   2253 									Sidebar_Glyphx_Add(RTTI_INFANTRYTYPE, f, House, buildable_via_capture);
   2254 								} else {
   2255 									Map.Add(RTTI_INFANTRYTYPE, f, buildable_via_capture);
   2256 								}
   2257 							}
   2258 						} else {
   2259 							if (*this != STRUCT_KENNEL) {
   2260 								if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   2261 									Sidebar_Glyphx_Add(RTTI_INFANTRYTYPE, f, House, buildable_via_capture);
   2262 								} else {
   2263 									Map.Add(RTTI_INFANTRYTYPE, f, buildable_via_capture);
   2264 								}
   2265 							}
   2266 						}
   2267 					}
   2268 				}
   2269 				break;
   2270 
   2271 			case RTTI_AIRCRAFTTYPE:
   2272 				for (a = AIRCRAFT_FIRST; a < AIRCRAFT_COUNT; a++) {
   2273 					if (PlayerPtr->Can_Build(&AircraftTypeClass::As_Reference((AircraftType)a), ActLike)) {
   2274 						if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   2275 							Sidebar_Glyphx_Add(RTTI_AIRCRAFTTYPE, a, House, buildable_via_capture);
   2276 						} else {
   2277 							Map.Add(RTTI_AIRCRAFTTYPE, a, buildable_via_capture);
   2278 						}
   2279 					}
   2280 				}
   2281 				break;
   2282 
   2283 			default:
   2284 				break;
   2285 		}
   2286 	}
   2287 }
   2288 
   2289 
   2290 
   2291 #if (0) //Old code for reference. ST - 8/2/2019 2:41PM
   2292 /***********************************************************************************************
   2293  * BuildingClass::Update_Buildables -- Informs sidebar of additional construction options.     *
   2294  *                                                                                             *
   2295  *    This routine will tell the sidebar of objects that can be built. The function is called  *
   2296  *    whenever a building matures.                                                             *
   2297  *                                                                                             *
   2298  * INPUT:   none                                                                               *
   2299  *                                                                                             *
   2300  * OUTPUT:  none                                                                               *
   2301  *                                                                                             *
   2302  * WARNINGS:   none                                                                            *
   2303  *                                                                                             *
   2304  * HISTORY:                                                                                    *
   2305  *   11/11/1994 JLB : Created.                                                                 *
   2306  *   12/23/1994 JLB : Only updates for PLAYER buildings.                                       *
   2307  *=============================================================================================*/
   2308 void BuildingClass::Update_Buildables(void)
   2309 {
   2310 	assert(Buildings.ID(this) == ID);
   2311 	assert(IsActive);
   2312 
   2313 	if (House == PlayerPtr && !IsInLimbo && IsDiscoveredByPlayer) {
   2314 		switch (Class->ToBuild) {
   2315 			int i;
   2316 			int u;
   2317 			int f;
   2318 			int a;
   2319 			int v;
   2320 
   2321 			case RTTI_VESSELTYPE:
   2322 				for (v = VESSEL_FIRST; v < VESSEL_COUNT; v++) {
   2323 					if (PlayerPtr->Can_Build(&VesselTypeClass::As_Reference((VesselType)v), ActLike)) {
   2324 						Map.Add(RTTI_VESSELTYPE, v);
   2325 					}
   2326 				}
   2327 				break;
   2328 
   2329 			case RTTI_BUILDINGTYPE:
   2330 				for (i = STRUCT_FIRST; i < STRUCT_COUNT; i++) {
   2331 					if (PlayerPtr->Can_Build(&BuildingTypeClass::As_Reference((StructType)i), ActLike)) {
   2332 						Map.Add(RTTI_BUILDINGTYPE, i);
   2333 					}
   2334 				}
   2335 				break;
   2336 
   2337 			case RTTI_UNITTYPE:
   2338 				for (u = UNIT_FIRST; u < UNIT_COUNT; u++) {
   2339 					if (PlayerPtr->Can_Build(&UnitTypeClass::As_Reference((UnitType)u), ActLike)) {
   2340 						Map.Add(RTTI_UNITTYPE, u);
   2341 					}
   2342 				}
   2343 				break;
   2344 
   2345 			case RTTI_INFANTRYTYPE:
   2346 				for (f = INFANTRY_FIRST; f < INFANTRY_COUNT; f++) {
   2347 					if (PlayerPtr->Can_Build(&InfantryTypeClass::As_Reference((InfantryType)f), ActLike)) {
   2348 						if (InfantryTypeClass::As_Reference((InfantryType)f).IsDog) {
   2349 							if (*this == STRUCT_KENNEL) {
   2350 								Map.Add(RTTI_INFANTRYTYPE, f);
   2351 							}
   2352 						} else {
   2353 							if (*this != STRUCT_KENNEL) {
   2354 								Map.Add(RTTI_INFANTRYTYPE, f);
   2355 							}
   2356 						}
   2357 					}
   2358 				}
   2359 				break;
   2360 
   2361 			case RTTI_AIRCRAFTTYPE:
   2362 				for (a = AIRCRAFT_FIRST; a < AIRCRAFT_COUNT; a++) {
   2363 					if (PlayerPtr->Can_Build(&AircraftTypeClass::As_Reference((AircraftType)a), ActLike)) {
   2364 						Map.Add(RTTI_AIRCRAFTTYPE, a);
   2365 					}
   2366 				}
   2367 				break;
   2368 
   2369 			default:
   2370 				break;
   2371 		}
   2372 	}
   2373 }
   2374 #endif
   2375 
   2376 
   2377 /***********************************************************************************************
   2378  * BuildingClass::Fire_Out -- Handles when attached animation expires.                         *
   2379  *                                                                                             *
   2380  *    This routine is used to perform any fixups necessary when the attached animation has     *
   2381  *    terminated. This occurs when the fire & smoke animation that a SAM site produces stops.  *
   2382  *    At that point, normal reload procedures can commence.                                    *
   2383  *                                                                                             *
   2384  * INPUT:   none                                                                               *
   2385  *                                                                                             *
   2386  * OUTPUT:  none                                                                               *
   2387  *                                                                                             *
   2388  * WARNINGS:   none                                                                            *
   2389  *                                                                                             *
   2390  * HISTORY:                                                                                    *
   2391  *   11/30/1994 JLB : Created.                                                                 *
   2392  *=============================================================================================*/
   2393 void BuildingClass::Fire_Out(void)
   2394 {
   2395 	assert(Buildings.ID(this) == ID);
   2396 	assert(IsActive);
   2397 }
   2398 
   2399 
   2400 /***********************************************************************************************
   2401  * BuildingClass::Limbo -- Handles power adjustment as building goes into limbo.               *
   2402  *                                                                                             *
   2403  *    This routine will handle the power adjustments for the associated house when the         *
   2404  *    building goes into limbo. This means that its power drain or production is subtracted    *
   2405  *    from the house accumulated totals.                                                       *
   2406  *                                                                                             *
   2407  * INPUT:   none                                                                               *
   2408  *                                                                                             *
   2409  * OUTPUT:  bool; Was the building limboed?                                                    *
   2410  *                                                                                             *
   2411  * WARNINGS:   none                                                                            *
   2412  *                                                                                             *
   2413  * HISTORY:                                                                                    *
   2414  *   12/24/1994 JLB : Created.                                                                 *
   2415  *=============================================================================================*/
   2416 bool BuildingClass::Limbo(void)
   2417 {
   2418 	assert(Buildings.ID(this) == ID);
   2419 	assert(IsActive);
   2420 
   2421 	if (!IsInLimbo) {
   2422 
   2423 		/*
   2424 		**	Update the total factory type, assuming this building has a factory.
   2425 		*/
   2426 		House->Active_Remove(this);
   2427 		House->IsRecalcNeeded = true;
   2428 		House->Recalc_Center();
   2429 
   2430 		/*
   2431 		**	Update the power status of the owner's house.
   2432 		*/
   2433 		House->Adjust_Power(-Power_Output());
   2434 		House->Adjust_Drain(-Class->Drain);
   2435 		House->Adjust_Capacity(-Class->Capacity, true);
   2436 		if (House == PlayerPtr) {
   2437 			Map.PowerClass::IsToRedraw = true;
   2438 			Map.Flag_To_Redraw(false);
   2439 		}
   2440 
   2441 		/*
   2442 		**	This could be a building that builds. If so, then the sidebar may need adjustment.
   2443 		** Set IsInLimbo to true to "fool" the sidebar into knowing that this building
   2444 		** isn't available.  Set it back to false so the rest of the Limbo code works.
   2445 		** Otherwise, the sidebar won't properly remove non-available buildables.
   2446 		*/
   2447 //		if (IsOwnedByPlayer && !ScenarioInit) {
   2448 //			IsInLimbo = true;
   2449 //			Map.Recalc();
   2450 //			IsInLimbo = false;
   2451 //		}
   2452 	}
   2453 	return(TechnoClass::Limbo());
   2454 }
   2455 
   2456 
   2457 /***********************************************************************************************
   2458  * BuildingClass::Turret_Facing -- Fetches the turret facing for this building.                *
   2459  *                                                                                             *
   2460  *    This will return the turret facing for this building. Some buildings don't have a        *
   2461  *    visual turret (e.g., pillbox) so they return a turret facing that always faces their     *
   2462  *    current target.                                                                          *
   2463  *                                                                                             *
   2464  * INPUT:   none                                                                               *
   2465  *                                                                                             *
   2466  * OUTPUT:  Returns with the current facing of the turret.                                     *
   2467  *                                                                                             *
   2468  * WARNINGS:   none                                                                            *
   2469  *                                                                                             *
   2470  * HISTORY:                                                                                    *
   2471  *   07/29/1996 JLB : Created.                                                                 *
   2472  *=============================================================================================*/
   2473 DirType BuildingClass::Turret_Facing(void) const
   2474 {
   2475 	if (!Class->IsTurretEquipped && Target_Legal(TarCom)) {
   2476 		return(::Direction(Center_Coord(), As_Coord(TarCom)));
   2477 	}
   2478 	return(PrimaryFacing.Current());
   2479 }
   2480 
   2481 
   2482 /***********************************************************************************************
   2483  * BuildingClass::Greatest_Threat -- Searches for target that building can fire upon.          *
   2484  *                                                                                             *
   2485  *    This routine intercepts the Greatest_Threat function so that it can add the ability      *
   2486  *    to search for ground targets, if this isn't a SAM site.                                  *
   2487  *                                                                                             *
   2488  * INPUT:   threat   -- The base threat control value. Typically, it might be THREAT_RANGE     *
   2489  *                      or THREAT_NORMAL.                                                      *
   2490  *                                                                                             *
   2491  * OUTPUT:  Returns with a suitable target. If none could be found, then TARGET_NONE is        *
   2492  *          returned instead.                                                                  *
   2493  *                                                                                             *
   2494  * WARNINGS:   none                                                                            *
   2495  *                                                                                             *
   2496  * HISTORY:                                                                                    *
   2497  *   01/01/1995 JLB : Created.                                                                 *
   2498  *=============================================================================================*/
   2499 TARGET BuildingClass::Greatest_Threat(ThreatType threat) const
   2500 {
   2501 	assert(Buildings.ID(this) == ID);
   2502 	assert(IsActive);
   2503 
   2504 	if (Class->PrimaryWeapon != NULL) {
   2505 		threat = threat | Class->PrimaryWeapon->Allowed_Threats();
   2506 	}
   2507 	if (Class->SecondaryWeapon != NULL) {
   2508 		threat = threat | Class->SecondaryWeapon->Allowed_Threats();
   2509 	}
   2510 	if (House->IsHuman) {
   2511 		threat = threat & ~THREAT_BUILDINGS;
   2512 	}
   2513 	threat = threat | THREAT_RANGE;
   2514 
   2515 //	if (Class->PrimaryWeapon != NULL) {
   2516 //		if (Class->PrimaryWeapon->Bullet->IsAntiAircraft) {
   2517 //			threat = threat | THREAT_AIR;
   2518 //		}
   2519 //		if (Class->PrimaryWeapon->Bullet->IsAntiGround) {
   2520 //			threat = threat | THREAT_BUILDINGS|THREAT_INFANTRY|THREAT_BOATS|THREAT_VEHICLES;
   2521 //		}
   2522 //		threat = threat | THREAT_RANGE;
   2523 //	}
   2524 	return(TechnoClass::Greatest_Threat(threat));
   2525 }
   2526 
   2527 
   2528 /***********************************************************************************************
   2529  * BuildingClass::Grand_Opening -- Handles construction completed special operations.          *
   2530  *                                                                                             *
   2531  *    This routine is called when construction has finished. Typically, this enables           *
   2532  *    new production options for factories.                                                    *
   2533  *                                                                                             *
   2534  * INPUT:   none                                                                               *
   2535  *                                                                                             *
   2536  * OUTPUT:  none                                                                               *
   2537  *                                                                                             *
   2538  * WARNINGS:   none                                                                            *
   2539  *                                                                                             *
   2540  * HISTORY:                                                                                    *
   2541  *   01/08/1995 JLB : Created.                                                                 *
   2542  *   06/13/1995 JLB : Added helipad.                                                           *
   2543  *=============================================================================================*/
   2544 void BuildingClass::Grand_Opening(bool captured)
   2545 {
   2546 	assert(Buildings.ID(this) == ID);
   2547 	assert(IsActive);
   2548 
   2549 	if (!HasOpened || captured) {
   2550 		HasOpened = true;
   2551 
   2552 		/*
   2553 		**	Adjust the owning house according to the power, drain, and Tiberium capacity that
   2554 		**	this building has.
   2555 		*/
   2556 		House->Adjust_Drain(Class->Drain);
   2557 		House->Adjust_Capacity(Class->Capacity);
   2558 		House->IsRecalcNeeded = true;
   2559 
   2560 		/*	SPECIAL CASE:
   2561 		**	Tiberium Refineries get a free harvester. Add a harvester to the
   2562 		**	reinforcement list at this time.
   2563 		*/
   2564 		if (*this == STRUCT_REFINERY && !ScenarioInit && !captured && !Debug_Map && (!House->IsHuman || PurchasePrice == 0 || PurchasePrice > Class->Raw_Cost())) {
   2565 			CELL cell = Coord_Cell(Adjacent_Cell(Center_Coord(), DIR_S));
   2566 
   2567 			UnitClass * unit = new UnitClass(UNIT_HARVESTER, House->Class->House);
   2568 			if (unit != NULL) {
   2569 
   2570 				/*
   2571 				**	Try to place down the harvesters. If it could not be placed, then try
   2572 				**	to place it in a nearby location.
   2573 				*/
   2574 				if (!unit->Unlimbo(Cell_Coord(cell), DIR_W)) {
   2575 					/*
   2576 					**	Check multiple times for clear locations.
   2577 					*/
   2578 					for (int i = 0; i < 10; i++) {
   2579 						cell = unit->Nearby_Location(this, i);
   2580 						if (unit->Unlimbo(Cell_Coord(cell), DIR_SW)) {
   2581 							break;
   2582 						}
   2583 					}
   2584 
   2585 					/*
   2586 					**	If the harvester could still not be placed, then refund the money
   2587 					**	to the owner and then bail.
   2588 					*/
   2589 					if (unit->IsInLimbo) {
   2590 						House->Refund_Money(unit->Class->Cost_Of());
   2591 						delete unit;
   2592 					}
   2593 				}
   2594 			} else {
   2595 
   2596 				/*
   2597 				**	If the harvester could not be created in the first place, then give
   2598 				**	the full refund price to the owning player.
   2599 				*/
   2600 				House->Refund_Money(UnitTypeClass::As_Reference(UNIT_HARVESTER).Cost_Of());
   2601 			}
   2602 		}
   2603 
   2604 		/*
   2605 		**	Helicopter pads get a free attack helicopter.
   2606 		*/
   2607 		if (!Rule.IsSeparate && *this == STRUCT_HELIPAD && !captured) {
   2608 			ScenarioInit++;
   2609 			AircraftClass * air = 0;
   2610 			if (House->ActLike == HOUSE_USSR || House->ActLike == HOUSE_BAD || House->ActLike == HOUSE_UKRAINE) {
   2611 				air = new AircraftClass(AIRCRAFT_HIND, House->Class->House);
   2612 			} else {
   2613 				air = new AircraftClass(AIRCRAFT_LONGBOW, House->Class->House);
   2614 			}
   2615 			if (air) {
   2616 				air->Height = 0;
   2617 				if (air->Unlimbo(Docking_Coord(), air->Pose_Dir())) {
   2618 					air->Assign_Mission(MISSION_GUARD);
   2619 					air->Transmit_Message(RADIO_HELLO, this);
   2620 					Transmit_Message(RADIO_TETHER);
   2621 				}
   2622 			}
   2623 			ScenarioInit--;
   2624 		}
   2625 	}
   2626 }
   2627 
   2628 
   2629 /***********************************************************************************************
   2630  * BuildingClass::Repair -- Initiates or terminates the repair process.                        *
   2631  *                                                                                             *
   2632  *    This routine will start, stop, or toggle the repair process. When a building repairs, it *
   2633  *    occurs incrementally over time.                                                          *
   2634  *                                                                                             *
   2635  * INPUT:   control  -- Determines how to control the repair process.                          *
   2636  *                      0: Turns repair process off (if it was on).                            *
   2637  *                      1: Turns repair process on (if it was off).                            *
   2638  *                      -1:Toggles repair process to other state.                              *
   2639  *                                                                                             *
   2640  * OUTPUT:  none                                                                               *
   2641  *                                                                                             *
   2642  * WARNINGS:   none                                                                            *
   2643  *                                                                                             *
   2644  * HISTORY:                                                                                    *
   2645  *   01/08/1995 JLB : Created.                                                                 *
   2646  *=============================================================================================*/
   2647 void BuildingClass::Repair(int control)
   2648 {
   2649 	assert(Buildings.ID(this) == ID);
   2650 	assert(IsActive);
   2651 
   2652 	switch (control) {
   2653 		case -1:
   2654 			IsRepairing = (IsRepairing == false);
   2655 			break;
   2656 
   2657 		case 1:
   2658 			if (IsRepairing) return;
   2659 			IsRepairing = true;
   2660 			break;
   2661 
   2662 		case 0:
   2663 			if (!IsRepairing) return;
   2664 			IsRepairing = false;
   2665 			break;
   2666 
   2667 		default:
   2668 			break;
   2669 	}
   2670 
   2671 	/*
   2672 	**	At this point, we know that the repair state has changed. Perform
   2673 	**	appropriate action.
   2674 	*/
   2675 	VocType soundid = VOC_NONE;
   2676 	if (IsRepairing) {
   2677 		if (Strength == Class->MaxStrength) {
   2678 			soundid = VOC_SCOLD;
   2679 		} else {
   2680 			soundid = VOC_CLICK;
   2681 			if (House->IsPlayerControl) {
   2682 				Clicked_As_Target(PlayerPtr->Class->House); // 2019/09/20 JAS - Added record of who clicked on the object
   2683 			}
   2684 			IsWrenchVisible = true;
   2685 		}
   2686 	} else {
   2687 		soundid = VOC_CLICK;
   2688 	}
   2689 	
   2690 	if (House->IsPlayerControl) {
   2691 		Sound_Effect(soundid, Coord);
   2692 	}
   2693 }
   2694 
   2695 
   2696 /***********************************************************************************************
   2697  * BuildingClass::Sell_Back -- Controls the sell back (demolish) operation.                    *
   2698  *                                                                                             *
   2699  *    This routine will initiate or stop the sell back process for a building. It is called    *
   2700  *    when the player clicks on a building when the sell mode is active.                       *
   2701  *                                                                                             *
   2702  * INPUT:   control  -- The action to perform. 0 = turn deconstruction off, 1 = deconstruct,   *
   2703  *                      -1 = toggle deconstruction state.                                      *
   2704  *                                                                                             *
   2705  * OUTPUT:  none                                                                               *
   2706  *                                                                                             *
   2707  * WARNINGS:   none                                                                            *
   2708  *                                                                                             *
   2709  * HISTORY:                                                                                    *
   2710  *   06/25/1995 JLB : Created.                                                                 *
   2711  *=============================================================================================*/
   2712 void BuildingClass::Sell_Back(int control)
   2713 {
   2714 	assert(Buildings.ID(this) == ID);
   2715 	assert(IsActive);
   2716 
   2717 	if (Class->Get_Buildup_Data()) {
   2718 		bool decon = false;
   2719 		switch (control) {
   2720 			case -1:
   2721 				decon = (Mission != MISSION_DECONSTRUCTION);
   2722 				break;
   2723 
   2724 			case 1:
   2725 				if (Mission == MISSION_DECONSTRUCTION) return;
   2726 				if (IsGoingToBlow) return;
   2727 				decon = true;
   2728 				break;
   2729 
   2730 			case 0:
   2731 				if (Mission != MISSION_DECONSTRUCTION) return;
   2732 				decon = false;
   2733 				break;
   2734 
   2735 			default:
   2736 				break;
   2737 		}
   2738 
   2739 		/*
   2740 		**	At this point, we know that the repair state has changed. Perform
   2741 		**	appropriate action.
   2742 		*/
   2743 		if (decon) {
   2744 			Assign_Mission(MISSION_DECONSTRUCTION);
   2745 			Commence();
   2746 			if (House->IsPlayerControl) {
   2747 				Clicked_As_Target(PlayerPtr->Class->House);
   2748 			}
   2749 		}
   2750 		if (House->IsPlayerControl) {
   2751 			Sound_Effect(VOC_CLICK);
   2752 		}
   2753 	}
   2754 }
   2755 
   2756 
   2757 /***********************************************************************************************
   2758  * BuildingClass::What_Action -- Determines action to perform if click on specified object.    *
   2759  *                                                                                             *
   2760  *    This routine will determine what action to perform if the mouse was clicked on the       *
   2761  *    object specified. This determination is used to control the mouse imagery and the        *
   2762  *    function process when the mouse button is pressed.                                       *
   2763  *                                                                                             *
   2764  * INPUT:   object   -- Pointer to the object that, if clicked on, will control what action    *
   2765  *                      is to be performed.                                                    *
   2766  *                                                                                             *
   2767  * OUTPUT:  Returns with the ActionType that will occur if the mouse is clicked over the       *
   2768  *          object specified while the building is currently selected.                         *
   2769  *                                                                                             *
   2770  * WARNINGS:   none                                                                            *
   2771  *                                                                                             *
   2772  * HISTORY:                                                                                    *
   2773  *   01/18/1995 JLB : Created.                                                                 *
   2774  *=============================================================================================*/
   2775 ActionType BuildingClass::What_Action(ObjectClass const * object) const
   2776 {
   2777 	assert(Buildings.ID(this) == ID);
   2778 	assert(IsActive);
   2779 
   2780 	ActionType action = TechnoClass::What_Action(object);
   2781 
   2782 	if (action == ACTION_SELF) {
   2783 		int index;
   2784 		if (Class->Is_Factory() && PlayerPtr == House && *House->Factory_Counter(Class->ToBuild) > 1) {
   2785 			switch (Class->ToBuild) {
   2786 				case RTTI_INFANTRYTYPE:
   2787 				case RTTI_INFANTRY:
   2788 					action = ACTION_NONE;
   2789 					if (*this == STRUCT_KENNEL) {
   2790 						for (index = 0; index < Buildings.Count(); index++) {
   2791 							BuildingClass *bldg = Buildings.Ptr(index);
   2792 							if (bldg != this && bldg->Owner() == Owner() && *bldg == STRUCT_KENNEL) {
   2793 								action = ACTION_TOGGLE_PRIMARY;
   2794 								break;
   2795 							}
   2796 						}
   2797 					} else {
   2798 						for (index = 0; index < Buildings.Count(); index++) {
   2799 							BuildingClass *bldg = Buildings.Ptr(index);
   2800 							if (bldg != this && bldg->Owner() == Owner() && bldg->Class->ToBuild == RTTI_INFANTRYTYPE && *bldg != STRUCT_KENNEL) {
   2801 								action = ACTION_TOGGLE_PRIMARY;
   2802 								break;
   2803 							}
   2804 						}
   2805 					}
   2806 					break;
   2807 
   2808 				case RTTI_AIRCRAFTTYPE:
   2809 				case RTTI_AIRCRAFT:
   2810 					action = ACTION_NONE;
   2811 					if (*this == STRUCT_AIRSTRIP) {
   2812 						for (index = 0; index < Buildings.Count(); index++) {
   2813 							BuildingClass *bldg = Buildings.Ptr(index);
   2814 							if (bldg != this && bldg->Owner() == Owner() && *bldg == STRUCT_AIRSTRIP) {
   2815 								action = ACTION_TOGGLE_PRIMARY;
   2816 								break;
   2817 							}
   2818 						}
   2819 					}
   2820 					else {
   2821 						for (index = 0; index < Buildings.Count(); index++) {
   2822 							BuildingClass *bldg = Buildings.Ptr(index);
   2823 							if (bldg != this && bldg->Owner() == Owner() && bldg->Class->ToBuild == RTTI_AIRCRAFTTYPE && *bldg != STRUCT_AIRSTRIP) {
   2824 								action = ACTION_TOGGLE_PRIMARY;
   2825 								break;
   2826 							}
   2827 						}
   2828 					}
   2829 					break;
   2830 
   2831 				case RTTI_UNITTYPE:
   2832 				case RTTI_UNIT:
   2833 				case RTTI_VESSELTYPE:
   2834 				case RTTI_VESSEL:
   2835 					action = ACTION_TOGGLE_PRIMARY;
   2836 					break;
   2837 
   2838 				case RTTI_NONE:
   2839 					action = ACTION_NONE;
   2840 					break;
   2841 
   2842 				default:
   2843 					break;
   2844 			}
   2845 
   2846 		} else {
   2847 			action = ACTION_NONE;
   2848 		}
   2849 	}
   2850 
   2851 	/*
   2852 	**	Don't allow targeting of SAM sites, even if the CTRL key
   2853 	**	is held down. Also don't allow targeting if the object is too
   2854 	**	far away.
   2855 	*/
   2856 	if (action == ACTION_ATTACK && (*this == STRUCT_SAM || *this == STRUCT_AAGUN || !In_Range(object, 0))) {
   2857 		action = ACTION_NONE;
   2858 	}
   2859 
   2860 	if (action == ACTION_MOVE) {
   2861 		action = ACTION_NONE;
   2862 	}
   2863 
   2864 	return(action);
   2865 }
   2866 
   2867 
   2868 /***********************************************************************************************
   2869  * BuildingClass::What_Action -- Determines what action will occur.                            *
   2870  *                                                                                             *
   2871  *    This routine examines the cell specified and returns with the action that will be        *
   2872  *    performed if that cell were clicked upon while the building is selected.                 *
   2873  *                                                                                             *
   2874  * INPUT:   cell  -- The cell to examine.                                                      *
   2875  *                                                                                             *
   2876  * OUTPUT:  Returns the ActionType that indicates what should occur if the mouse is clicked    *
   2877  *          on this cell.                                                                      *
   2878  *                                                                                             *
   2879  * WARNINGS:   none                                                                            *
   2880  *                                                                                             *
   2881  * HISTORY:                                                                                    *
   2882  *   01/18/1995 JLB : Created.                                                                 *
   2883  *=============================================================================================*/
   2884 ActionType BuildingClass::What_Action(CELL cell) const
   2885 {
   2886 	assert(Buildings.ID(this) == ID);
   2887 	assert(IsActive);
   2888 
   2889 	ActionType action = TechnoClass::What_Action(cell);
   2890 
   2891 	if (action == ACTION_MOVE && (*this != STRUCT_CONST || !Is_MCV_Deploy())) {
   2892 		action = ACTION_NONE;
   2893 	}
   2894 
   2895 	/*
   2896 	**	Don't allow targeting of SAM sites, even if the CTRL key
   2897 	**	is held down.
   2898 	*/
   2899 	if (action == ACTION_ATTACK && Class->PrimaryWeapon != NULL && !Class->PrimaryWeapon->Bullet->IsAntiGround) {
   2900 //	if (action == ACTION_ATTACK && (*this == STRUCT_SAM || *this == STRUCT_AAGUN)) {
   2901 		action = ACTION_NONE;
   2902 	}
   2903 
   2904 	return(action);
   2905 }
   2906 
   2907 
   2908 /***********************************************************************************************
   2909  * BuildingClass::Begin_Mode -- Begins an animation mode for the building.                     *
   2910  *                                                                                             *
   2911  *    This routine will start the building animating. This animation will loop indefinitely    *
   2912  *    until explicitly stopped.                                                                *
   2913  *                                                                                             *
   2914  * INPUT:   bstate   -- The animation state to initiate.                                       *
   2915  *                                                                                             *
   2916  * OUTPUT:  none                                                                               *
   2917  *                                                                                             *
   2918  * WARNINGS:   The building graphic state will reflect the first stage of this animation the   *
   2919  *             very next time it is rendered.                                                  *
   2920  *                                                                                             *
   2921  * HISTORY:                                                                                    *
   2922  *   06/25/1995 JLB : Created.                                                                 *
   2923  *   07/02/1995 JLB : Uses normalize animation rate where applicable.                          *
   2924  *=============================================================================================*/
   2925 void BuildingClass::Begin_Mode(BStateType bstate)
   2926 {
   2927 	assert(Buildings.ID(this) == ID);
   2928 	assert(IsActive);
   2929 
   2930 	QueueBState = bstate;
   2931 	if (BState == BSTATE_NONE || bstate == BSTATE_CONSTRUCTION || ScenarioInit) {
   2932 		BState = bstate;
   2933 		QueueBState = BSTATE_NONE;
   2934 		BuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();
   2935 
   2936 		int rate = ctrl->Rate;
   2937 		if (Class->IsRegulated && bstate != BSTATE_CONSTRUCTION) {
   2938 			rate = Options.Normalize_Delay(rate);
   2939 		}
   2940 		Set_Rate(rate);
   2941 		Set_Stage(ctrl->Start);
   2942 	}
   2943 }
   2944 
   2945 
   2946 /***********************************************************************************************
   2947  * BuildingClass::Center_Coord -- Fetches the center coordinate for the building.              *
   2948  *                                                                                             *
   2949  *    This routine is used to set the center coordinate for this building.                     *
   2950  *                                                                                             *
   2951  * INPUT:   none                                                                               *
   2952  *                                                                                             *
   2953  * OUTPUT:  Returns with the coordinate for the center location for the building.              *
   2954  *                                                                                             *
   2955  * WARNINGS:   none                                                                            *
   2956  *                                                                                             *
   2957  * HISTORY:                                                                                    *
   2958  *   03/10/1995 JLB : Created.                                                                 *
   2959  *=============================================================================================*/
   2960 COORDINATE BuildingClass::Center_Coord(void) const
   2961 {
   2962 	assert(Buildings.ID(this) == ID);
   2963 	assert(IsActive);
   2964 
   2965 	return(Coord_Add(Coord, CenterOffset[Class->Size]));
   2966 }
   2967 
   2968 
   2969 /***********************************************************************************************
   2970  * BuildingClass::Docking_Coord -- Fetches the coordinate to use for docking.                  *
   2971  *                                                                                             *
   2972  *    This routine will return the coordinate to use when an object wishes to dock with this   *
   2973  *    building. Normally the docking coordinate would be the center of the building.           *
   2974  *    Exceptions to this would be the airfield and helipad. Their docking coordinates are      *
   2975  *    offset to match the building artwork.                                                    *
   2976  *                                                                                             *
   2977  * INPUT:   none                                                                               *
   2978  *                                                                                             *
   2979  * OUTPUT:  Returns with the coordinate to head to when trying to dock with this building.     *
   2980  *                                                                                             *
   2981  * WARNINGS:   none                                                                            *
   2982  *                                                                                             *
   2983  * HISTORY:                                                                                    *
   2984  *   09/21/1995 JLB : Created.                                                                 *
   2985  *=============================================================================================*/
   2986 COORDINATE BuildingClass::Docking_Coord(void) const
   2987 {
   2988 	assert(Buildings.ID(this) == ID);
   2989 	assert(IsActive);
   2990 
   2991 	if (*this == STRUCT_HELIPAD) {
   2992 		return(Coord_Add(Coord, XYP_COORD(24, 18)));
   2993 	}
   2994 	if (*this == STRUCT_AIRSTRIP) {
   2995 		return(Coord_Add(Coord, XYP_COORD(ICON_PIXEL_W + ICON_PIXEL_W/2, 28)));
   2996 	}
   2997 	return(TechnoClass::Docking_Coord());
   2998 }
   2999 
   3000 
   3001 /***********************************************************************************************
   3002  * BuildingClass::Can_Fire -- Determines if this building can fire.                            *
   3003  *                                                                                             *
   3004  *    Use this routine to see if the building can fire its weapon.                             *
   3005  *                                                                                             *
   3006  *                                                                                             *
   3007  * INPUT:   target   -- The target that firing upon is desired.                                *
   3008  *                                                                                             *
   3009  *          which    -- Which weapon to use when firing. 0=primary, 1=secondary.               *
   3010  *                                                                                             *
   3011  * OUTPUT:  Returns with the fire possibility code. If firing is allowed, then FIRE_OK is      *
   3012  *          returned. Other cases will result in appropriate fire code value that indicates    *
   3013  *          why firing is not allowed.                                                         *
   3014  *                                                                                             *
   3015  * WARNINGS:   none                                                                            *
   3016  *                                                                                             *
   3017  * HISTORY:                                                                                    *
   3018  *   05/03/1995 JLB : Created.                                                                 *
   3019  *=============================================================================================*/
   3020 FireErrorType BuildingClass::Can_Fire(TARGET target, int which) const
   3021 {
   3022 	assert(Buildings.ID(this) == ID);
   3023 	assert(IsActive);
   3024 
   3025 	FireErrorType canfire = TechnoClass::Can_Fire(target, which);
   3026 
   3027 	if (canfire == FIRE_OK) {
   3028 
   3029 		/*
   3030 		**	Double check to make sure that the facing is roughly toward
   3031 		**	the target. If the difference is too great, then firing is
   3032 		**	temporarily postponed.
   3033 		*/
   3034 		if (Class->IsTurretEquipped) {
   3035 			int diff = PrimaryFacing.Difference(Direction(TarCom));
   3036 			diff = abs(diff);
   3037 			if (ABS(diff) > (*this == STRUCT_SAM ? 64 : 8)) {
   3038 //			if (ABS(diff) > 8) {
   3039 				return(FIRE_FACING);
   3040 			}
   3041 
   3042 			/*
   3043 			**	If the turret is rotating then firing must be delayed.
   3044 			*/
   3045 //			if (PrimaryFacing.Is_Rotating()) {
   3046 //				return(FIRE_ROTATING);
   3047 //			}
   3048 		}
   3049 
   3050 		/*
   3051 		**	Certain buildings cannot fire if there is insufficient power.
   3052 		*/
   3053 		if (Class->IsPowered && House->Power_Fraction() < 1) {
   3054 			return(FIRE_BUSY);
   3055 		}
   3056 
   3057 		/*
   3058 		** If an obelisk can fire, check the state of charge.
   3059 		*/
   3060 		if (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsElectric && !IsCharged) {
   3061 			return(FIRE_BUSY);
   3062 		}
   3063 	}
   3064 	return(canfire);
   3065 }
   3066 
   3067 
   3068 /***********************************************************************************************
   3069  * BuildingClass::Toggle_Primary -- Toggles the primary factory state.                         *
   3070  *                                                                                             *
   3071  *    This routine will change the primary factory state of this building. The primary         *
   3072  *    factory is the one that units will be produced from (by default).                        *
   3073  *                                                                                             *
   3074  * INPUT:   none                                                                               *
   3075  *                                                                                             *
   3076  * OUTPUT:  Is this building NOW the primary factory?                                          *
   3077  *                                                                                             *
   3078  * WARNINGS:   none                                                                            *
   3079  *                                                                                             *
   3080  * HISTORY:                                                                                    *
   3081  *   05/03/1995 JLB : Created.                                                                 *
   3082  *=============================================================================================*/
   3083 bool BuildingClass::Toggle_Primary(void)
   3084 {
   3085 	assert(Buildings.ID(this) == ID);
   3086 	assert(IsActive);
   3087 
   3088 	if (IsLeader) {
   3089 		IsLeader = false;
   3090 	} else {
   3091 		for (int index = 0; index < Buildings.Count(); index++) {
   3092 			BuildingClass * building = Buildings.Ptr(index);
   3093 
   3094 			if (!building->IsInLimbo && building->Owner() == Owner() && building->Class->ToBuild == Class->ToBuild) {
   3095 				if (Class->ToBuild == RTTI_INFANTRYTYPE) {
   3096 					if (*building == STRUCT_KENNEL && *this == STRUCT_KENNEL) {
   3097 						building->IsLeader = false;
   3098 					} else {
   3099 						if (*building != STRUCT_KENNEL && *this != STRUCT_KENNEL) {
   3100 							building->IsLeader = false;
   3101 						}
   3102 					}
   3103 				} else if (Class->ToBuild == RTTI_AIRCRAFTTYPE) {
   3104 					if (*building == STRUCT_AIRSTRIP && *this == STRUCT_AIRSTRIP) {
   3105 						building->IsLeader = false;
   3106 					} else {
   3107 						if (*building != STRUCT_AIRSTRIP && *this != STRUCT_AIRSTRIP) {
   3108 							building->IsLeader = false;
   3109 						}
   3110 					}
   3111 				} else {
   3112 					building->IsLeader = false;
   3113 				}
   3114 			}
   3115 		}
   3116 		IsLeader = true;
   3117 		//
   3118 		// MBL 04.20.2020 - Update so that each player in multiplayer will properly hear this when it applies to them
   3119 		//
   3120 		// if ((HouseClass *)House == PlayerPtr) {
   3121 		// 	Speak(VOX_PRIMARY_SELECTED);
   3122 		// }
   3123 		if ((HouseClass *)House->IsHuman) {
   3124 			Speak(VOX_PRIMARY_SELECTED, House);
   3125 		}
   3126 	}
   3127 	Mark(MARK_CHANGE);
   3128 	return(IsLeader);
   3129 }
   3130 
   3131 
   3132 /***********************************************************************************************
   3133  * BuildingClass::Captured -- Captures the building.                                           *
   3134  *                                                                                             *
   3135  *    This routine will change the owner of the building. It handles updating any related      *
   3136  *    game systems as a result. Factories are the most prone to have great game related        *
   3137  *    consequences when captured. This could also affect the sidebar and building ownership.   *
   3138  *                                                                                             *
   3139  * INPUT:   newowner -- Pointer to the house that is now the new owner.                        *
   3140  *                                                                                             *
   3141  * OUTPUT:  Was the capture attempt successful?                                                *
   3142  *                                                                                             *
   3143  * WARNINGS:   Capturing could fail if the house is already owned by the one specified or      *
   3144  *             the building isn't allowed to be captured.                                      *
   3145  *                                                                                             *
   3146  * HISTORY:                                                                                    *
   3147  *   05/03/1995 JLB : Created.                                                                 *
   3148  *   07/05/1995 JLB : Fixed production problem with capturing enemy buildings.                 *
   3149  *=============================================================================================*/
   3150 bool BuildingClass::Captured(HouseClass * newowner)
   3151 {
   3152 	assert(Buildings.ID(this) == ID);
   3153 	assert(IsActive);
   3154 
   3155 	if (Can_Capture() && newowner != House) {
   3156 #ifdef TOFIX
   3157 		switch (Owner()) {
   3158 			case HOUSE_GOOD:
   3159 				Speak(VOX_GDI_CAPTURED);
   3160 				break;
   3161 
   3162 			case HOUSE_BAD:
   3163 				Speak(VOX_NOD_CAPTURED);
   3164 				break;
   3165 		}
   3166 #endif
   3167 
   3168 		/*
   3169 		** Maybe trigger an achivement. ST - 11/14/2019 1:53PM
   3170 		*/
   3171 		if (newowner->IsHuman) {
   3172 			TechnoTypeClass const *object_type = Techno_Type_Class();
   3173 			if (object_type) {
   3174 				if (newowner->ActLike != House->ActLike) {
   3175 					On_Achievement_Event(newowner, "OPPOSING_BUILDING_CAPTURED", object_type->IniName);
   3176 				} else {
   3177 					On_Achievement_Event(newowner, "BUILDING_CAPTURED", object_type->IniName);
   3178 				}	
   3179 			}
   3180 		}
   3181 
   3182 		/*
   3183 		** Make sure the capturer isn't spying on his own building, and if
   3184 		** it was a radar facility, update the target house's RadarSpied field.
   3185 		*/
   3186 		if (SpiedBy & (1<<(newowner->Class->House)) ) {
   3187 			SpiedBy -= (1<<(newowner->Class->House));
   3188 			if (*this == STRUCT_RADAR) {
   3189 				Update_Radar_Spied();
   3190 			}
   3191 		}
   3192 
   3193 		if (House == PlayerPtr) {
   3194 			Map.PowerClass::IsToRedraw = true;
   3195 			Map.Flag_To_Redraw(false);
   3196 		}
   3197 
   3198 		if (*this == STRUCT_GAP) {
   3199 			Remove_Gap_Effect();
   3200 			IsJamming = false;
   3201 			Arm = 0;
   3202 		}
   3203 
   3204 		/*
   3205 		** Add this building to the list of buildings captured this game. For internet stats purposes.
   3206 		*/
   3207 		if (Session.Type == GAME_INTERNET) {
   3208 			newowner->CapturedBuildings->Increment_Unit_Total (Class->Type);
   3209 		}
   3210 
   3211 		House->Adjust_Power(-Power_Output());
   3212 		LastStrength = 0;
   3213 		House->Adjust_Drain(-Class->Drain);
   3214 		int booty = House->Adjust_Capacity(-Class->Capacity, true);
   3215 
   3216 		/*
   3217 		**	If there is something loaded, then it gets captured as well.
   3218 		*/
   3219 		TechnoClass * tech = Attached_Object();
   3220 		if (tech) tech->Captured(newowner);
   3221 
   3222 		/*
   3223 		**	If something isn't technically attached, but is sitting on this
   3224 		**	building for another reason (e.g., helicopter on helipad), then it
   3225 		**	gets captured as well.
   3226 		*/
   3227 		tech = Contact_With_Whom();
   3228 		if (tech) {
   3229 			if (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER && (::Distance(tech->Center_Coord(), Docking_Coord()) < 0x0040 ||
   3230 				(tech->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass *)tech)->Class->IsFixedWing && ((AircraftClass *)tech)->In_Which_Layer() == LAYER_GROUND)) ) {
   3231 				tech->Captured(newowner);
   3232 			} else {
   3233 				Transmit_Message(RADIO_RUN_AWAY);
   3234 				Transmit_Message(RADIO_OVER_OUT);
   3235 			}
   3236 		}
   3237 
   3238 		/*
   3239 		**	Abort any computer production in progress.
   3240 		*/
   3241 		if (Factory) {
   3242 			delete (FactoryClass *)Factory;
   3243 			Factory = 0;
   3244 		}
   3245 
   3246 		/*
   3247 		**	Decrement the factory counter for the original owner.
   3248 		*/
   3249 		House->Active_Remove(this);
   3250 
   3251 		/*
   3252 		**	Flag that both owners now need to update their buildable lists.
   3253 		*/
   3254 		House->IsRecalcNeeded = true;
   3255 		newowner->IsRecalcNeeded = true;
   3256 		HouseClass * oldowner = House;
   3257 		TARGET tocap = As_Target();
   3258 
   3259 		IsCaptured = true;
   3260 		TechnoClass::Captured(newowner);
   3261 
   3262 		oldowner->ToCapture = tocap;
   3263 		oldowner->Recalc_Center();
   3264 		House->Recalc_Center();
   3265 		if (House->ToCapture == As_Target()) {
   3266 			House->ToCapture = TARGET_NONE;
   3267 		}
   3268 
   3269 		SmudgeType bib;
   3270 		CELL cell = Coord_Cell(Coord);
   3271 		if (Class->Bib_And_Offset(bib, cell)) {
   3272 			SmudgeClass * smudge = new SmudgeClass(bib);
   3273 			if (smudge) {
   3274 				smudge->Disown(cell);
   3275 				delete smudge;
   3276 			}
   3277 #ifdef FIXIT_CAPTURE_BIB
   3278 			if (Session.Type == GAME_NORMAL) {
   3279 				new SmudgeClass(bib, Cell_Coord(cell), Class->IsBase ? House->Class->House : HOUSE_NONE);
   3280 			} else {
   3281 				new SmudgeClass(bib, Cell_Coord(cell), House->Class->House);
   3282 			}
   3283 #else
   3284 			new SmudgeClass(bib, Cell_Coord(cell), House->Class->House);
   3285 #endif
   3286 		}
   3287 
   3288 		House->Stole(Refund_Amount());
   3289 
   3290 		/*
   3291 		**	Increment the factory count for the new owner.
   3292 		*/
   3293 		House->Active_Add(this);
   3294 
   3295 		IsRepairing = false;
   3296 		Grand_Opening(true);
   3297 		House->Harvested(booty);
   3298 
   3299 		Mark(MARK_CHANGE);
   3300 
   3301 		/*
   3302 		**	Perform a look operation when captured if it was the player
   3303 		**	that performed the capture.
   3304 		*/
   3305 		if (Session.Type == GAME_GLYPHX_MULTIPLAYER && House->IsHuman) {
   3306 			Look(false);
   3307 		} else {
   3308 			if (House == PlayerPtr) {
   3309 				Look(false);
   3310 			}
   3311 		}
   3312 		/*
   3313 		** If it was spied upon by the player who just captured it, clear the
   3314 		** spiedby flag for that house.
   3315 		*/
   3316 		if (SpiedBy & (1 << (newowner->Class->House))) {
   3317 			SpiedBy &= ~(1 << (newowner->Class->House));
   3318 		}
   3319 
   3320 		/*
   3321 		** Update the new building's colors on the radar map.
   3322 		*/
   3323 		short const * offset = Occupy_List();
   3324 		while (*offset != REFRESH_EOL) {
   3325 			CELL cell = Coord_Cell(Coord) + *offset++;
   3326 			Map.Radar_Pixel(cell);
   3327 		}
   3328 
   3329 		if (oldowner) {
   3330 			oldowner->Check_Pertinent_Structures();
   3331 		}
   3332 
   3333 		return(true);
   3334 	}
   3335 	return(false);
   3336 }
   3337 
   3338 
   3339 /***********************************************************************************************
   3340  * BuildingClass::Sort_Y -- Returns the building coordinate used for sorting.                  *
   3341  *                                                                                             *
   3342  *    The coordinate value returned from this function should be used for sorting purposes.    *
   3343  *    It has special offset adjustment applied so that vehicles don't overlap (as much).       *
   3344  *                                                                                             *
   3345  * INPUT:   none                                                                               *
   3346  *                                                                                             *
   3347  * OUTPUT:  Returns with a coordinate value suitable to be used for sorting.                   *
   3348  *                                                                                             *
   3349  * WARNINGS:   none                                                                            *
   3350  *                                                                                             *
   3351  * HISTORY:                                                                                    *
   3352  *   05/23/1995 JLB : Created.                                                                 *
   3353  *   06/19/1995 JLB : Handles buildings that come with bibs built-in.                          *
   3354  *=============================================================================================*/
   3355 COORDINATE BuildingClass::Sort_Y(void) const
   3356 {
   3357 	assert(Buildings.ID(this) == ID);
   3358 	assert(IsActive);
   3359 
   3360 	if (*this == STRUCT_REPAIR) {
   3361 		return(Coord);
   3362 	}
   3363 	if (*this == STRUCT_HELIPAD) {
   3364 		return(Center_Coord());
   3365 	}
   3366 	if (*this == STRUCT_AIRSTRIP) {
   3367 		return(Center_Coord());
   3368 	}
   3369 	if (*this == STRUCT_BARRACKS /*|| *this == STRUCT_POWER*/) {
   3370 		return(Center_Coord());
   3371 	}
   3372 	if (*this == STRUCT_REFINERY) {
   3373 		return(Center_Coord());
   3374 	}
   3375 
   3376 	/*
   3377 	**	Mines need to bias their sort location such that they are typically drawn
   3378 	**	before any objects that might overlap them.
   3379 	*/
   3380 	if (*this == STRUCT_AVMINE || *this == STRUCT_APMINE) {
   3381 		return(Coord_Move(Center_Coord(), DIR_N, CELL_LEPTON_H));
   3382 	}
   3383 
   3384 	return(Coord_Add(Center_Coord(), XY_Coord(0, (Class->Height()*256)/3)));
   3385 }
   3386 
   3387 
   3388 /***********************************************************************************************
   3389  * BuildingClass::Can_Enter_Cell -- Determines if building can be placed down.                 *
   3390  *                                                                                             *
   3391  *    This routine will determine if the building can be placed down at the location           *
   3392  *    specified.                                                                               *
   3393  *                                                                                             *
   3394  * INPUT:   cell  -- The cell to examine. This is usually the cell of the upper left corner    *
   3395  *                   of the building if it were to be placed down.                             *
   3396  *                                                                                             *
   3397  * OUTPUT:  Returns with the move legality value for placement at the location specified. This *
   3398  *          will either be MOVE_OK or MOVE_NO.                                                 *
   3399  *                                                                                             *
   3400  * WARNINGS:   none                                                                            *
   3401  *                                                                                             *
   3402  * HISTORY:                                                                                    *
   3403  *   06/25/1995 JLB : Created.                                                                 *
   3404  *=============================================================================================*/
   3405 MoveType BuildingClass::Can_Enter_Cell(CELL cell, FacingType) const
   3406 {
   3407 	assert(Buildings.ID(this) == ID);
   3408 	assert(IsActive);
   3409 
   3410 	if (*this == STRUCT_CONST && IsDown) {
   3411 		return(Map[cell].Is_Clear_To_Build(Class->Speed) ? MOVE_OK : MOVE_NO);
   3412 	}
   3413 
   3414 	if (!Debug_Map && ScenarioInit == 0 && Session.Type == GAME_NORMAL && House->IsPlayerControl && !Map[cell].IsMapped) {
   3415 		return(MOVE_NO);
   3416 	}
   3417 
   3418 	return(Class->Legal_Placement(cell) ? MOVE_OK : MOVE_NO);
   3419 }
   3420 
   3421 
   3422 /***********************************************************************************************
   3423  * BuildingClass::Can_Demolish -- Can the player demolish (sell back) the building?            *
   3424  *                                                                                             *
   3425  *    Determines if the player can sell this building. Selling is possible if the building     *
   3426  *    is not currently in construction or deconstruction animation.                            *
   3427  *                                                                                             *
   3428  * INPUT:   none                                                                               *
   3429  *                                                                                             *
   3430  * OUTPUT:  Can the building be demolished at this time?                                       *
   3431  *                                                                                             *
   3432  * WARNINGS:   none                                                                            *
   3433  *                                                                                             *
   3434  * HISTORY:                                                                                    *
   3435  *   06/25/1995 JLB : Created.                                                                 *
   3436  *   07/01/1995 JLB : If there is no buildup data, then the building can't be sold.            *
   3437  *   07/17/1995 JLB : Cannot sell a refinery that has a harvester attached.                    *
   3438  *=============================================================================================*/
   3439 bool BuildingClass::Can_Demolish(void) const
   3440 {
   3441 	assert(Buildings.ID(this) == ID);
   3442 	assert(IsActive);
   3443 
   3444 	if (Class->IsUnsellable) return(false);
   3445 
   3446 	if (Class->Get_Buildup_Data() && BState != BSTATE_CONSTRUCTION && Mission != MISSION_DECONSTRUCTION && Mission != MISSION_CONSTRUCTION) {
   3447 		if (*this == STRUCT_REFINERY && Is_Something_Attached()) return(false);
   3448 		return(true);
   3449 	}
   3450 	return(false);
   3451 }
   3452 
   3453 
   3454 bool BuildingClass::Can_Demolish_Unit(void) const
   3455 {
   3456 	return((*this == STRUCT_REPAIR || *this == STRUCT_AIRSTRIP) && In_Radio_Contact() && Distance(Contact_With_Whom()) < 0x0080);
   3457 }
   3458 
   3459 
   3460 bool BuildingClass::Can_Capture(void) const
   3461 {
   3462 	bool can_capture = Class->IsCaptureable && Mission != MISSION_DECONSTRUCTION;
   3463 
   3464 	// Only allow capturing of multiplayer-owned structures
   3465 	if (Session.Type != GAME_NORMAL) {
   3466 		if (*this == STRUCT_V01) {		// Check to fix exploit in specific map 'Tournament Ore Rift'
   3467 			can_capture = false;
   3468 		}
   3469 	}
   3470 
   3471 	return(can_capture);
   3472 }
   3473 
   3474 
   3475 /***********************************************************************************************
   3476  * BuildingClass::Mission_Guard -- Handles guard mission for combat buildings.                 *
   3477  *                                                                                             *
   3478  *    Buildings that can attack are given this mission. They will wait until a suitable target *
   3479  *    comes within range and then launch into the attack mission. Buildings that have no       *
   3480  *    weaponry will just sit in this routine forever.                                          *
   3481  *                                                                                             *
   3482  * INPUT:   none                                                                               *
   3483  *                                                                                             *
   3484  * OUTPUT:  Returns with the number of game frames to delay before this routine will be called *
   3485  *          again.                                                                             *
   3486  *                                                                                             *
   3487  * WARNINGS:   none                                                                            *
   3488  *                                                                                             *
   3489  * HISTORY:                                                                                    *
   3490  *   06/25/1995 JLB : Created.                                                                 *
   3491  *=============================================================================================*/
   3492 int BuildingClass::Mission_Guard(void)
   3493 {
   3494 	assert(Buildings.ID(this) == ID);
   3495 	assert(IsActive);
   3496 
   3497 	/*
   3498 	**	If this building has a weapon, then search for a target to attack. When
   3499 	**	a target is found, switch into attack mode to deal with the threat.
   3500 	*/
   3501 	if (Is_Weapon_Equipped()) {
   3502 
   3503 		/*
   3504 		**	Weapon equipped buildings are ALWAYS ready to launch into another mission if
   3505 		**	they are sitting around in guard mode.
   3506 		*/
   3507 		IsReadyToCommence = true;
   3508 
   3509 		/*
   3510 		**	If there is no target available, then search for one.
   3511 		*/
   3512 		if (!Target_Legal(TarCom)) {
   3513 			ThreatType threat = THREAT_NORMAL;
   3514 			Assign_Target(Greatest_Threat(threat));
   3515 		}
   3516 
   3517 		/*
   3518 		**	There is a valid target. Switch into attack mode right away.
   3519 		*/
   3520 		if (Target_Legal(TarCom)) {
   3521 			Assign_Mission(MISSION_ATTACK);
   3522 			Commence();
   3523 			return(1);
   3524 		}
   3525 	} else {
   3526 
   3527 		/*
   3528 		**	This is the very simple state machine that basically does
   3529 		**	nothing. This is the mode that non weapon equipped buildings
   3530 		**	are normally in.
   3531 		*/
   3532 		enum {
   3533 			INITIAL_ENTRY,
   3534 			IDLE
   3535 		};
   3536 		switch (Status) {
   3537 			case INITIAL_ENTRY:
   3538 				Begin_Mode(BSTATE_IDLE);
   3539 				Status = IDLE;
   3540 				break;
   3541 
   3542 			case IDLE:
   3543 				/*
   3544 				**	Special case to break out of guard mode if this is a repair
   3545 				**	facility and there is a customer waiting at the grease pit.
   3546 				*/
   3547 				if (*this == STRUCT_REPAIR &&
   3548 					In_Radio_Contact() &&
   3549 					Contact_With_Whom()->Is_Techno() &&
   3550 					((TechnoClass *)Contact_With_Whom())->Mission == MISSION_ENTER &&
   3551 					Distance(Contact_With_Whom()) < 0x0040 &&
   3552 					Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {
   3553 
   3554 					Assign_Mission(MISSION_REPAIR);
   3555 					return(1);
   3556 				}
   3557 				break;
   3558 
   3559 			default:
   3560 				break;
   3561 		}
   3562 
   3563 		if (*this == STRUCT_REPAIR) {
   3564 			return(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));
   3565 		} else {
   3566 			return(MissionControl[Mission].Normal_Delay() * 3 + Random_Pick(0, 2));
   3567 		}
   3568 	}
   3569 	return(MissionControl[Mission].AA_Delay() + Random_Pick(0, 2));
   3570 }
   3571 
   3572 
   3573 /***********************************************************************************************
   3574  * BuildingClass::Mission_Construction -- Handles mission construction.                        *
   3575  *                                                                                             *
   3576  *    This routine will handle mission construction. When this mission is complete, the        *
   3577  *    building will begin normal operation.                                                    *
   3578  *                                                                                             *
   3579  * INPUT:   none                                                                               *
   3580  *                                                                                             *
   3581  * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *
   3582  *          again.                                                                             *
   3583  *                                                                                             *
   3584  * WARNINGS:   none                                                                            *
   3585  *                                                                                             *
   3586  * HISTORY:                                                                                    *
   3587  *   06/25/1995 JLB : Created.                                                                 *
   3588  *=============================================================================================*/
   3589 int BuildingClass::Mission_Construction(void)
   3590 {
   3591 	assert(Buildings.ID(this) == ID);
   3592 	assert(IsActive);
   3593 
   3594 	enum {
   3595 		INITIAL,
   3596 		DURING
   3597 	};
   3598 	switch (Status) {
   3599 		case INITIAL:
   3600 			Begin_Mode(BSTATE_CONSTRUCTION);
   3601 			Transmit_Message(RADIO_BUILDING);
   3602 			if (House->IsPlayerControl) {
   3603 				Sound_Effect(VOC_CONSTRUCTION, Coord);
   3604 			}
   3605 			Status = DURING;
   3606 			break;
   3607 
   3608 		case DURING:
   3609 			if (IsReadyToCommence) {
   3610 
   3611 				/*
   3612 				**	When construction is complete, then transmit this
   3613 				**	to the construction yard so that it can stop its
   3614 				**	construction animation.
   3615 				*/
   3616 				Transmit_Message(RADIO_COMPLETE);		// "I'm finished."
   3617 				Transmit_Message(RADIO_OVER_OUT);		// "You're free."
   3618 				Begin_Mode(BSTATE_IDLE);
   3619 				Grand_Opening();
   3620 				Assign_Mission(MISSION_GUARD);
   3621 				PrimaryFacing = Class->StartFace;
   3622 			}
   3623 			break;
   3624 
   3625 		default:
   3626 			break;
   3627 	}
   3628 	return(1);
   3629 }
   3630 
   3631 
   3632 /***********************************************************************************************
   3633  * BuildingClass::Mission_Deconstruction -- Handles building deconstruction.                   *
   3634  *                                                                                             *
   3635  *    This state machine is only used when the building is deconstructing as a result of       *
   3636  *    selling.  When this mission is finished, the building will no longer exist.              *
   3637  *                                                                                             *
   3638  * INPUT:   none                                                                               *
   3639  *                                                                                             *
   3640  * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *
   3641  *                                                                                             *
   3642  * WARNINGS:   none                                                                            *
   3643  *                                                                                             *
   3644  * HISTORY:                                                                                    *
   3645  *   06/25/1995 JLB : Created.                                                                 *
   3646  *   08/13/1995 JLB : Enable selling of units on a repair bay.                                 *
   3647  *   08/20/1995 JLB : Scatters infantry from scattered starting points.                        *
   3648  *=============================================================================================*/
   3649 int BuildingClass::Mission_Deconstruction(void)
   3650 {
   3651 	assert(Buildings.ID(this) == ID);
   3652 	assert(IsActive);
   3653 
   3654 	/*
   3655 	**	Always force repair off.
   3656 	*/
   3657 	Repair(0);
   3658 
   3659 	enum {
   3660 		INITIAL,
   3661 		HOLDING,
   3662 		DURING
   3663 	};
   3664 	switch (Status) {
   3665 		case INITIAL:
   3666 
   3667 			/*
   3668 			**	Special check for the repair bay which has the ability to sell
   3669 			**	whatever is on it. If there is something on the repair bay, then
   3670 			**	it will be sold. If there is nothing on the repair bay, then
   3671 			**	the repair bay itself will be sold.
   3672 			*/
   3673 			if (Can_Demolish_Unit() && Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {
   3674 				TechnoClass * tech = Contact_With_Whom();
   3675 				Transmit_Message(RADIO_OVER_OUT);
   3676 				if (IsOwnedByPlayer) Speak(VOX_UNIT_SOLD);
   3677 				tech->Sell_Back(1);
   3678 				Assign_Mission(MISSION_GUARD);
   3679 				return(1);
   3680 			}
   3681 
   3682 			/*
   3683 			** Selling off a shipyard or sub pen may cause attached ships
   3684 			** who are repairing themselves to discontinue repairs.
   3685 			*/
   3686 			if (*this == STRUCT_SHIP_YARD || *this == STRUCT_SUB_PEN) {
   3687 				for (int index = 0; index < Vessels.Count(); index++) {
   3688 					VesselClass * obj = Vessels.Ptr(index);
   3689 					if (obj && !obj->IsInLimbo && obj->House == House) {
   3690 						if (obj->IsSelfRepairing) {
   3691 							if (::Distance(Center_Coord(), obj->Center_Coord()) < 0x0200) {
   3692 								obj->IsSelfRepairing = false;
   3693 								obj->IsToSelfRepair = false;
   3694 							}
   3695 						}
   3696 					}
   3697 				}
   3698 			}
   3699 
   3700 			IsReadyToCommence = false;
   3701 			Transmit_Message(RADIO_RUN_AWAY);
   3702 			Status = HOLDING;
   3703 			break;
   3704 
   3705 		case HOLDING:
   3706 			if (!IsTethered) {
   3707 
   3708 				/*
   3709 				**	The crew will evacuate from the building. The number of crew
   3710 				**	members leaving is equal to the unrecovered cost of the building
   3711 				**	divided by 100 (the typical cost of a minigunner infantryman).
   3712 				*/
   3713 				if (!Target_Legal(ArchiveTarget) || !Is_MCV_Deploy() || *this != STRUCT_CONST) {
   3714 					int count = How_Many_Survivors();
   3715 					bool engine = false;
   3716 
   3717 					while (count) {
   3718 
   3719 						/*
   3720 						**	Ensure that the player only gets ONE engineer and not from a captured
   3721 						**	construction yard.
   3722 						*/
   3723 						InfantryType typ = Crew_Type();
   3724 						while (typ == INFANTRY_RENOVATOR && engine) {
   3725 							typ = Crew_Type();
   3726 						}
   3727 						if (typ == INFANTRY_RENOVATOR) engine = true;
   3728 
   3729 						InfantryClass * infantry = 0;
   3730 						if (typ != INFANTRY_NONE) infantry = new InfantryClass(typ, House->Class->House);
   3731 						if (infantry != NULL) {
   3732 							ScenarioInit++;
   3733 							COORDINATE coord = Coord_Add(Center_Coord(), XYP_COORD(0, -12));
   3734 							coord = Map[coord].Closest_Free_Spot(coord, false);
   3735 
   3736 							if (infantry->Unlimbo(coord, DIR_N)) {
   3737 								infantry->IsZoneCheat = infantry->Can_Enter_Cell(Coord_Cell(infantry->Center_Coord())) != MOVE_OK;
   3738 								if (infantry->Class->IsNominal) infantry->IsTechnician = true;
   3739 								ScenarioInit--;
   3740 								infantry->Scatter(0, true);
   3741 								ScenarioInit++;
   3742 								infantry->Assign_Mission(MISSION_GUARD_AREA);
   3743 							} else {
   3744 								delete infantry;
   3745 							}
   3746 							ScenarioInit--;
   3747 						}
   3748 						count--;
   3749 					}
   3750 				}
   3751 
   3752 				// MBL 07.10.2020 - In 1v1, sometimes both players will hear this SFX, or neither player will hear it
   3753 				// Making it so all players hear it positionally in the map; Per thread discussion in https://jaas.ea.com/browse/TDRA-7245
   3754 				//
   3755 				#if 0
   3756 					if (House->IsPlayerControl) {
   3757 						Sound_Effect(VOC_CASHTURN, Coord);
   3758 					}
   3759 				#else
   3760 					Sound_Effect(VOC_CASHTURN, Coord);
   3761 				#endif
   3762 				
   3763 				/*
   3764 				**	Destroy all attached objects. ST - 4/24/2020 9:38PM
   3765 				*/
   3766 				while (Attached_Object()) {
   3767 					FootClass * obj = Detach_Object();
   3768 
   3769 					Detach_All(true);
   3770 					delete obj;
   3771 				}
   3772 				
   3773 				Transmit_Message(RADIO_OVER_OUT);
   3774 				Status = DURING;
   3775 				Begin_Mode(BSTATE_CONSTRUCTION);
   3776 				IsReadyToCommence = false;
   3777 				IsSurvivorless = true;
   3778 				break;
   3779 			}
   3780 			Transmit_Message(RADIO_RUN_AWAY);
   3781 			break;
   3782 
   3783 		case DURING:
   3784 			if (IsReadyToCommence) {
   3785 				House->IsRecalcNeeded = true;
   3786 
   3787   				// MBL 05.06.2020 - "Structure Sold" is being heard when selecting/moving a redepolyable Con Yard to turn back into an MCV (RA only), so moving below
   3788 				#if 0
   3789 				// MBL 04.06.2020: Fix being heard by wrong player
   3790 				// if (IsOwnedByPlayer) Speak(VOX_STRUCTURE_SOLD);
   3791 				if (IsOwnedByPlayer) {
   3792 					if ((HouseClass *)House == PlayerPtr) {
   3793 						Speak(VOX_STRUCTURE_SOLD);
   3794 					}
   3795 				}
   3796 				#endif
   3797 				bool mcv_redeployed = false;
   3798 
   3799 				/*
   3800 				**	Construction yards that deconstruct, really just revert back
   3801 				**	to an MCV.
   3802 				*/
   3803 				if (Target_Legal(ArchiveTarget) && *this == STRUCT_CONST && House->IsHuman && Strength > 0) {
   3804 					ScenarioInit++;
   3805 					UnitClass * unit = new UnitClass(UNIT_MCV, House->Class->House);
   3806 					ScenarioInit--;
   3807 					if (unit != NULL) {
   3808 
   3809 						/*
   3810 						**	Unlimbo the MCV onto the map. The MCV should start in the same
   3811 						**	health condition that the construction yard was in.
   3812 						*/
   3813 						fixed ratio = Health_Ratio();
   3814 						int money = Refund_Amount();
   3815 						TARGET arch = ArchiveTarget;
   3816 						COORDINATE place = Coord_Snap(Adjacent_Cell(Coord, DIR_SE));
   3817 
   3818 						delete this;
   3819 
   3820 						if (unit->Unlimbo(place, DIR_SW)) {
   3821 							unit->Strength = (int)unit->Class_Of().MaxStrength * ratio;			// Cast to (int). ST - 5/8/2019
   3822 
   3823 							/*
   3824 							**	Lift the move destination from the building and assign
   3825 							**	it to the unit.
   3826 							*/
   3827 							if (Target_Legal(arch)) {
   3828 								unit->Assign_Destination(arch);
   3829 								unit->Assign_Mission(MISSION_MOVE);
   3830 							}
   3831 
   3832 							mcv_redeployed = true;
   3833 
   3834 						} else {
   3835 
   3836 							/*
   3837 							**	If, for some strange reason, the MCV could not be placed on the
   3838 							**	map, then give the player some money to compensate.
   3839 							*/
   3840 							House->Refund_Money(money);
   3841 						}
   3842 					} else {
   3843 						House->Refund_Money(Refund_Amount());
   3844 						delete this;
   3845 					}
   3846 
   3847 				} else {
   3848 
   3849 					/*
   3850 					** Selling off a gap generator will cause the cells it affects
   3851 					** to stop being jammed.
   3852 					*/
   3853 					if (*this == STRUCT_GAP) {
   3854 						Remove_Gap_Effect();
   3855 					}
   3856 
   3857 					/*
   3858 					**	A sold building still counts as a kill, but it just isn't directly
   3859 					**	attributed to the enemy.
   3860 					*/
   3861 					WhoLastHurtMe = HOUSE_NONE;
   3862 					Record_The_Kill(NULL);
   3863 
   3864 					/*
   3865 					**	The player gets part of the money back for the sell.
   3866 					*/
   3867 					House->Refund_Money(Refund_Amount());
   3868 					House->Stole(-Refund_Amount());
   3869 					Limbo();
   3870 
   3871 					if (House) {
   3872 						House->Check_Pertinent_Structures();
   3873 					}
   3874 
   3875 					/*
   3876 					**	Finally, delete the building from the game.
   3877 					*/
   3878 					delete this;
   3879 				}
   3880 
   3881 				// MBL 05.06.2020 - "Structure Sold" was being heard when selecting/moving a redepolyable Con Yard to turn back into an MCV (RA only) above, so moved here
   3882 				#if 1
   3883 				if (!mcv_redeployed) 
   3884 				{
   3885 					if (IsOwnedByPlayer) {
   3886 						if ((HouseClass *)House == PlayerPtr) {
   3887 							Speak(VOX_STRUCTURE_SOLD);
   3888 						}
   3889 					}
   3890 				}
   3891 				#endif
   3892 			}
   3893 			break;
   3894 
   3895 		default:
   3896 			break;
   3897 	}
   3898 	return(1);
   3899 }
   3900 
   3901 
   3902 /***********************************************************************************************
   3903  * BuildingClass::Mission_Attack -- Handles attack mission for building.                       *
   3904  *                                                                                             *
   3905  *    Buildings that can attack are processed by this attack mission state machine.            *
   3906  *                                                                                             *
   3907  * INPUT:   none                                                                               *
   3908  *                                                                                             *
   3909  * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *
   3910  *          again.                                                                             *
   3911  *                                                                                             *
   3912  * WARNINGS:   none                                                                            *
   3913  *                                                                                             *
   3914  * HISTORY:                                                                                    *
   3915  *   06/25/1995 JLB : Created.                                                                 *
   3916  *   02/22/1996 JLB : SAM doesn't lower back into ground.                                      *
   3917  *=============================================================================================*/
   3918 int BuildingClass::Mission_Attack(void)
   3919 {
   3920 	assert(Buildings.ID(this) == ID);
   3921 	assert(IsActive);
   3922 
   3923 	if (*this == STRUCT_SAM) {
   3924 		switch (Status) {
   3925 
   3926 			/*
   3927 			**	This is the target tracking state of the launcher. It will rotate
   3928 			**	to face the current TarCom of the launcher.
   3929 			*/
   3930 			case SAM_READY:
   3931 				if ((Class->IsPowered && House->Power_Fraction() < 1) || IsJammed) {
   3932 					return(1);
   3933 				}
   3934 				if (!Target_Legal(TarCom) || !Is_Target_Aircraft(TarCom) || As_Aircraft(TarCom)->Height == 0) {
   3935 					Assign_Target(TARGET_NONE);
   3936 					Status = SAM_READY;
   3937 					Assign_Mission(MISSION_GUARD);
   3938 					Commence();
   3939 					return(1);
   3940 				} else {
   3941 					if (!PrimaryFacing.Is_Rotating()) {
   3942 						DirType facing = Direction(TarCom);
   3943 						if (PrimaryFacing.Difference(facing)) {
   3944 							PrimaryFacing.Set_Desired(facing);
   3945 						} else {
   3946 							Status = SAM_FIRING;
   3947 						}
   3948 					}
   3949 				}
   3950 				return(1);
   3951 
   3952 			/*
   3953 			**	The launcher is in the process of firing.
   3954 			*/
   3955 			case SAM_FIRING:
   3956 				if (!Target_Legal(TarCom) || !Is_Target_Aircraft(TarCom) || As_Aircraft(TarCom)->Height == 0) {
   3957 					Assign_Target(TARGET_NONE);
   3958 					Status = SAM_READY;
   3959 				} else {
   3960 					FireErrorType error = Can_Fire(TarCom, 0);
   3961 					if (error == FIRE_ILLEGAL || error == FIRE_CANT || error == FIRE_RANGE) {
   3962 						Assign_Target(TARGET_NONE);
   3963 						Status = SAM_READY;
   3964 					} else {
   3965 						if (error == FIRE_FACING) {
   3966 							Status = SAM_READY;
   3967 						} else {
   3968 							if (error == FIRE_OK) {
   3969 								Fire_At(TarCom, 0);
   3970 								Fire_At(TarCom, 1);
   3971 								Status = SAM_READY;
   3972 							}
   3973 						}
   3974 					}
   3975 				}
   3976 				return(1);
   3977 
   3978 			default:
   3979 				break;
   3980 		}
   3981 		return(MissionControl[Mission].AA_Delay() + Random_Pick(0, 2));
   3982 
   3983 	}
   3984 
   3985 	if (!Target_Legal(TarCom)) {
   3986 		Assign_Target(TARGET_NONE);
   3987 		Assign_Mission(MISSION_GUARD);
   3988 		Commence();
   3989 		return(1);
   3990 	}
   3991 
   3992 	int primary = What_Weapon_Should_I_Use(TarCom);
   3993 	IsReadyToCommence = true;
   3994 	switch (Can_Fire(TarCom, primary)) {
   3995 		case FIRE_ILLEGAL:
   3996 		case FIRE_CANT:
   3997 		case FIRE_RANGE:
   3998 		case FIRE_AMMO:
   3999 			Assign_Target(TARGET_NONE);
   4000 			Assign_Mission(MISSION_GUARD);
   4001 			Commence();
   4002 			break;
   4003 
   4004 		case FIRE_FACING:
   4005 			PrimaryFacing.Set_Desired(Direction(TarCom));
   4006 			return(2);
   4007 
   4008 		case FIRE_REARM:
   4009 			PrimaryFacing.Set_Desired(Direction(TarCom));
   4010 			return(Arm);
   4011 
   4012 		case FIRE_BUSY:
   4013 			return(1);
   4014 
   4015 		case FIRE_CLOAKED:
   4016 			Do_Uncloak();
   4017 			break;
   4018 
   4019 		case FIRE_OK:
   4020 			Fire_At(TarCom, primary);
   4021 			return(1);
   4022 
   4023 		default:
   4024 			break;
   4025 	}
   4026 	PrimaryFacing.Set_Desired(Direction(TarCom));
   4027 	return(1);
   4028 //	return(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));
   4029 }
   4030 
   4031 
   4032 /***********************************************************************************************
   4033  * BuildingClass::Mission_Harvest -- Handles refinery unloading harvesters.                    *
   4034  *                                                                                             *
   4035  *    This state machine handles the refinery when it unloads the harvester.                   *
   4036  *                                                                                             *
   4037  * INPUT:   none                                                                               *
   4038  *                                                                                             *
   4039  * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *
   4040  *          again.                                                                             *
   4041  *                                                                                             *
   4042  * WARNINGS:   none                                                                            *
   4043  *                                                                                             *
   4044  * HISTORY:                                                                                    *
   4045  *   06/25/1995 JLB : Created.                                                                 *
   4046  *=============================================================================================*/
   4047 int BuildingClass::Mission_Harvest(void)
   4048 {
   4049 	assert(Buildings.ID(this) == ID);
   4050 	assert(IsActive);
   4051 
   4052 	enum {
   4053 		INITIAL,					// Dock the Tiberium cannister.
   4054 		WAIT_FOR_DOCK,			// Waiting for docking to complete.
   4055 		MIDDLE,					// Offload "bails" of tiberium.
   4056 		WAIT_FOR_UNDOCK		// Waiting for undocking to complete.
   4057 	};
   4058 	switch (Status) {
   4059 		case INITIAL:
   4060 			Status = WAIT_FOR_DOCK;
   4061 			break;
   4062 
   4063 		case WAIT_FOR_DOCK:
   4064 			if (IsReadyToCommence) {
   4065 				IsReadyToCommence = false;
   4066 				Status = MIDDLE;
   4067 			}
   4068 			break;
   4069 
   4070 		case MIDDLE:
   4071 			if (IsReadyToCommence) {
   4072 				IsReadyToCommence = false;
   4073 
   4074 				/*
   4075 				**	Force any bib squatters to scatter.
   4076 				*/
   4077 				Map[Adjacent_Cell(Coord_Cell(Center_Coord()), DIR_S)].Incoming(0, true, true);
   4078 
   4079 				FootClass * techno = Attached_Object();
   4080 				if (techno) {
   4081 					int bail = techno->Offload_Tiberium_Bail();
   4082 
   4083 					if (bail) {
   4084 						House->Harvested(bail);
   4085 						if (techno->Tiberium_Load() > 0) {
   4086 							return(1);
   4087 						}
   4088 					}
   4089 				}
   4090 				Status = WAIT_FOR_UNDOCK;
   4091 			}
   4092 			break;
   4093 
   4094 		case WAIT_FOR_UNDOCK:
   4095 			if (IsReadyToCommence) {
   4096 
   4097 				/*
   4098 				**	Detach harvester and go back into idle state.
   4099 				*/
   4100 				Assign_Mission(MISSION_GUARD);
   4101 			}
   4102 			break;
   4103 
   4104 		default:
   4105 			break;
   4106 	}
   4107 	return(1);
   4108 }
   4109 
   4110 
   4111 /***********************************************************************************************
   4112  * BuildingClass::Mission_Repair -- Handles the repair (active) state for building.            *
   4113  *                                                                                             *
   4114  *    This state machine is used when the building is active in some sort of repair or         *
   4115  *    construction mode. The construction yard will animate. The repair facility will repair   *
   4116  *    anything that it docked on it.                                                           *
   4117  *                                                                                             *
   4118  * INPUT:   none                                                                               *
   4119  *                                                                                             *
   4120  * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *
   4121  *                                                                                             *
   4122  * WARNINGS:   none                                                                            *
   4123  *                                                                                             *
   4124  * HISTORY:                                                                                    *
   4125  *   06/25/1995 JLB : Created.                                                                 *
   4126  *   06/25/1995 JLB : Handles repair facility                                                  *
   4127  *   07/29/1995 JLB : Repair rate is controlled by power rating.                               *
   4128  *=============================================================================================*/
   4129 int BuildingClass::Mission_Repair(void)
   4130 {
   4131 	assert(Buildings.ID(this) == ID);
   4132 	assert(IsActive);
   4133 
   4134 	if (*this == STRUCT_CONST) {
   4135 		enum {
   4136 			INITIAL,
   4137 			DURING
   4138 		};
   4139 		switch (Status) {
   4140 			case INITIAL:
   4141 				Begin_Mode(BSTATE_ACTIVE);
   4142 				Status = DURING;
   4143 				break;
   4144 
   4145 			case DURING:
   4146 				if (!In_Radio_Contact()) {
   4147 					Assign_Mission(MISSION_GUARD);
   4148 				}
   4149 				break;
   4150 
   4151 			default:
   4152 				break;
   4153 		}
   4154 		return(1);
   4155 	}
   4156 
   4157 	if (*this == STRUCT_REPAIR) {
   4158 		enum {
   4159 			INITIAL,
   4160 			IDLE,
   4161 			DURING
   4162 		};
   4163 		switch (Status) {
   4164 			case INITIAL:
   4165 				{
   4166 					if (!In_Radio_Contact()) {
   4167 						Begin_Mode(BSTATE_IDLE);
   4168 						Assign_Mission(MISSION_GUARD);
   4169 						return(1);
   4170 					}
   4171 					IsReadyToCommence = false;
   4172 					int distance = 0x10;
   4173 					TechnoClass *tech = Contact_With_Whom();
   4174 
   4175 					/*
   4176 					** BG: If the unit to repair is an aircraft, and the aircraft is
   4177 					** fixed-wing, and it's landed, be much more liberal with the
   4178 					** distance check.  Fixed-wing aircraft are very inaccurate with
   4179 					** their landings.
   4180 					*/
   4181 					if (tech->What_Am_I() == RTTI_AIRCRAFT) {
   4182 						if ( ((AircraftClass *)tech)->Class->IsFixedWing &&
   4183 							((AircraftClass *)tech)->In_Which_Layer() == LAYER_GROUND) {
   4184 							distance = 0x80;
   4185 						}
   4186 					}
   4187 					if (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER && Distance(Contact_With_Whom()) < distance) {
   4188 						Status = IDLE;
   4189 						return(TICKS_PER_SECOND/4);
   4190 					}
   4191 					break;
   4192 				}
   4193 
   4194 			case IDLE:
   4195 				if (!In_Radio_Contact()) {
   4196 					Assign_Mission(MISSION_GUARD);
   4197 					return(1);
   4198 				}
   4199 
   4200 				if (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {
   4201 					TechnoClass * radio = Contact_With_Whom();
   4202 
   4203 					if ( ((radio->Health_Ratio() < Rule.ConditionGreen) ||
   4204 						   (radio->What_Am_I() == RTTI_UNIT && *(UnitClass *)radio == UNIT_MINELAYER))
   4205 							&& Transmit_Message(RADIO_REPAIR) == RADIO_ROGER) {
   4206 
   4207 						/*
   4208 						**	If the object over the repair bay is marked as useless, then
   4209 						**	sell it back to get some money.
   4210 						*/
   4211 						if (radio->IsUseless) {
   4212 							if (!radio->House->IsHuman) {
   4213 								radio->Sell_Back(1);
   4214 							}
   4215 							Status = INITIAL;
   4216 							IsReadyToCommence = true;
   4217 						} else {
   4218 
   4219 							//
   4220 							// MBL 04.27.2020: Legacy VOX_REPAIRING seems to be never called in TD, but only in RA.
   4221 							// It is currently supported as a client GUI event when standard repairing begins, with "REPAIR1" on both TD and RA
   4222 							//
   4223 							// This repairing is in reference to the repair bay
   4224 							// There is a newer bug (https://jaas.ea.com/browse/TDRA-6224) reporting that it is heard in multiplayer by 
   4225 							// other players, from this call, so modifiying the original call here:
   4226 							//
   4227 							// if (IsOwnedByPlayer) Speak(VOX_REPAIRING);
   4228 							if (IsOwnedByPlayer) Speak(VOX_REPAIRING, House);
   4229 
   4230 							Status = DURING;
   4231 							Begin_Mode(BSTATE_ACTIVE);
   4232 							IsReadyToCommence = false;
   4233 						}
   4234 					} else {
   4235 //						Transmit_Message(RADIO_RUN_AWAY);
   4236 ///*BG*/					if(radio->Health_Ratio() >= Rule.ConditionGreen) {
   4237 //								Transmit_Message(RADIO_RUN_AWAY);
   4238 //							}
   4239 					}
   4240 				}
   4241 				break;
   4242 
   4243 			case DURING:
   4244 				if (!In_Radio_Contact()) {
   4245 					Begin_Mode(BSTATE_IDLE);
   4246 					Status = IDLE;
   4247 					return(1);
   4248 				}
   4249 
   4250 				/*
   4251 				**	Check to see if the repair light blink has completed and the attached
   4252 				**	unit is not doing something else. If these conditions are favorable,
   4253 				**	the repair can proceed another step.
   4254 				*/
   4255 				if (IsReadyToCommence && Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER) {
   4256 					IsReadyToCommence = false;
   4257 
   4258 					/*
   4259 					**	Tell the attached unit to repair one step. It will respond with how
   4260 					**	it fared.
   4261 					*/
   4262 					switch (Transmit_Message(RADIO_REPAIR)) {
   4263 
   4264 						/*
   4265 						**	The repair step proceeded smoothly. Proceed normally with the
   4266 						**	repair process.
   4267 						*/
   4268 						case RADIO_ROGER:
   4269 							break;
   4270 
   4271 						/*
   4272 						**	The repair operation was aborted because of some reason. Presume
   4273 						**	that the reason is because of low cash.
   4274 						*/
   4275 						case RADIO_CANT:
   4276 							if (IsOwnedByPlayer) Speak(VOX_NO_CASH);
   4277 							Begin_Mode(BSTATE_IDLE);
   4278 							Status = IDLE;
   4279 							break;
   4280 
   4281 						/*
   4282 						**	The repair step resulted in a completely repaired unit.
   4283 						*/
   4284 						case RADIO_ALL_DONE:
   4285 
   4286 							// MBL 04.27.2020: Make only audible to the correct player
   4287 							// if (IsOwnedByPlayer) Speak(VOX_UNIT_REPAIRED);
   4288 							if (IsOwnedByPlayer) Speak(VOX_UNIT_REPAIRED, House);
   4289 
   4290 //							Transmit_Message(RADIO_RUN_AWAY);
   4291 							Begin_Mode(BSTATE_IDLE);
   4292 							Status = IDLE;
   4293 							break;
   4294 
   4295 						/*
   4296 						**	The repair step could not be completed because this unit is already
   4297 						**	at full strength.
   4298 						*/
   4299 						case RADIO_NEGATIVE:
   4300 						default:
   4301 //							Transmit_Message(RADIO_RUN_AWAY);
   4302 							Begin_Mode(BSTATE_IDLE);
   4303 							Status = IDLE;
   4304 							break;
   4305 
   4306 					}
   4307 				}
   4308 				return(1);
   4309 
   4310 			default:
   4311 				break;
   4312 		}
   4313 		return(MissionControl[Mission].Normal_Delay());
   4314 	}
   4315 
   4316 	if (*this == STRUCT_HELIPAD || *this == STRUCT_AIRSTRIP) {
   4317 		enum {
   4318 			INITIAL,
   4319 			DURING
   4320 		};
   4321 		switch (Status) {
   4322 			case INITIAL:
   4323 				if (Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_ROGER && Transmit_Message(RADIO_PREPARED) == RADIO_NEGATIVE) {
   4324 					Begin_Mode(BSTATE_ACTIVE);
   4325 					Contact_With_Whom()->Assign_Mission(MISSION_SLEEP);
   4326 					Status = DURING;
   4327 					return(1);
   4328 				}
   4329 				Assign_Mission(MISSION_GUARD);
   4330 				break;
   4331 
   4332 			case DURING:
   4333 				if (IsReadyToCommence) {
   4334 					if (!In_Radio_Contact() || Transmit_Message(RADIO_NEED_TO_MOVE) == RADIO_NEGATIVE) {
   4335 						Assign_Mission(MISSION_GUARD);
   4336 						return(1);
   4337 					}
   4338 
   4339 					if (Transmit_Message(RADIO_PREPARED) == RADIO_ROGER) {
   4340 						Contact_With_Whom()->Assign_Mission(MISSION_GUARD);
   4341 						Assign_Mission(MISSION_GUARD);
   4342 						return(1);
   4343 					}
   4344 
   4345 					if (Transmit_Message(RADIO_RELOAD) != RADIO_ROGER) {
   4346 						Assign_Mission(MISSION_GUARD);
   4347 						Contact_With_Whom()->Assign_Mission(MISSION_GUARD);
   4348 						return(1);
   4349 					} else {
   4350 						fixed pfrac = Saturate(House->Power_Fraction(), 1);
   4351 						if (pfrac < fixed::_1_2) pfrac = fixed::_1_2;
   4352 						int time = Inverse(pfrac) * Rule.ReloadRate * TICKS_PER_MINUTE;
   4353 //						int time = Bound((int)(TICKS_PER_SECOND * Saturate(House->Power_Fraction(), 1)), 0, TICKS_PER_SECOND);
   4354 //						time = (TICKS_PER_SECOND*3) - time;
   4355 						IsReadyToCommence = false;
   4356 						return(time);
   4357 					}
   4358 				}
   4359 				break;
   4360 
   4361 			default:
   4362 				break;
   4363 		}
   4364 		return(3);
   4365 	}
   4366 	return(TICKS_PER_SECOND);
   4367 }
   4368 
   4369 
   4370 /***********************************************************************************************
   4371  * BuildingClass::Mission_Missile -- State machine for nuclear missile launch.                 *
   4372  *                                                                                             *
   4373  *    This handles the Temple of Nod launching its nuclear missile.                            *
   4374  *                                                                                             *
   4375  * INPUT:   none                                                                               *
   4376  *                                                                                             *
   4377  * OUTPUT:  Returns with the number of frames to delay before calling this routine again.      *
   4378  *                                                                                             *
   4379  * WARNINGS:   none                                                                            *
   4380  *                                                                                             *
   4381  * HISTORY:                                                                                    *
   4382  *   07/04/1995 JLB : Commented.                                                               *
   4383  *=============================================================================================*/
   4384 int BuildingClass::Mission_Missile(void)
   4385 {
   4386 	assert(Buildings.ID(this) == ID);
   4387 	assert(IsActive);
   4388 
   4389 	if (*this == STRUCT_ADVANCED_TECH) {
   4390 		enum {
   4391 			DOOR_OPENING,
   4392 			LAUNCH_UP,
   4393 			SATELLITE_DEPLOY,
   4394 			DONE_LAUNCH
   4395 		};
   4396 
   4397 		switch (Status) {
   4398 
   4399 			/*
   4400 			** The initial case is responsible for starting the door
   4401 			** opening on the building, the missile rising, and smoke broiling.
   4402 			*/
   4403 			case DOOR_OPENING:
   4404 				{
   4405 #ifdef FIXIT_VERSION_3
   4406 					COORDINATE door = Coord_Move(Center_Coord(), (DirType)0xC0, 0x30);
   4407 					AnimClass * sput = new AnimClass(ANIM_SPUTDOOR, door);
   4408 					if (sput) {
   4409 						IsReadyToCommence = false;
   4410 						Status = LAUNCH_UP;
   4411 						AnimToTrack = sput->As_Target();
   4412 					}
   4413 #else
   4414 					IsReadyToCommence = false;
   4415 					COORDINATE door = Coord_Move(Center_Coord(), (DirType)0xC0, 0x30);
   4416 					AnimClass * sput = new AnimClass(ANIM_SPUTDOOR, door);
   4417 					Status = LAUNCH_UP;
   4418 					AnimToTrack = sput->As_Target();
   4419 					return(1);
   4420 #endif
   4421 				}
   4422 
   4423 			/*
   4424 			** Once the smoke has been going for a little while this
   4425 			** actually handles launching the missile into the air.
   4426 			*/
   4427 			case LAUNCH_UP:
   4428 				{
   4429 					AnimClass * sput = As_Animation(AnimToTrack);
   4430 					if (sput) {
   4431 						if (sput->Fetch_Stage() >= 19) {
   4432 							CELL center = Coord_Cell(Center_Coord());
   4433 							CELL cell = XY_Cell( Cell_X(center), 1);
   4434 							TARGET targ = ::As_Target(cell);
   4435 
   4436 							BulletClass * bullet = new BulletClass(BULLET_GPS_SATELLITE, targ, this, 200, WARHEAD_FIRE, MPH_ROCKET);
   4437 							if (bullet) {
   4438 								COORDINATE launch = Coord_Move(Center_Coord(), (DirType)0xC0, 0x30);
   4439 								if (!bullet->Unlimbo(launch, DIR_N)) {
   4440 									delete bullet;
   4441 									bullet = NULL;
   4442 								}
   4443 							}
   4444 
   4445 							if (bullet) {
   4446 								Assign_Mission(MISSION_GUARD);
   4447 							}
   4448 						}
   4449 					}
   4450 				}
   4451 				return(1);
   4452 		}
   4453 	}
   4454 
   4455 	if (*this == STRUCT_MSLO) {
   4456 		enum {
   4457 			INITIAL,
   4458 			DOOR_OPENING,
   4459 			LAUNCH_UP,
   4460 			LAUNCH_DOWN,
   4461 			DONE_LAUNCH
   4462 		};
   4463 
   4464 		switch (Status) {
   4465 
   4466 			/*
   4467 			** The initial case is responsible for starting the door
   4468 			** opening on the building.
   4469 			*/
   4470 			case INITIAL:
   4471 				IsReadyToCommence = false;
   4472 				Begin_Mode(BSTATE_ACTIVE);	// open the door
   4473 				Status = DOOR_OPENING;
   4474 				return(1);
   4475 
   4476 			/*
   4477 			** This polls for the case when the door is actually open and
   4478 			** then kicks off the missile smoke.
   4479 			*/
   4480 			case DOOR_OPENING:
   4481 				if (IsReadyToCommence) {
   4482 					Begin_Mode(BSTATE_AUX1);	// hold the door open
   4483 					Status = LAUNCH_UP;
   4484 					return(14);
   4485 				}
   4486 				return(1);
   4487 
   4488 			/*
   4489 			** Once the smoke has been going for a little while this
   4490 			** actually handles launching the missile into the air.
   4491 			*/
   4492 			case LAUNCH_UP:
   4493 				{
   4494 					CELL center = Coord_Cell(Center_Coord());
   4495 					CELL cell = XY_Cell( Cell_X(center), 1);
   4496 					TARGET targ = ::As_Target(cell);
   4497 					BulletClass * bullet = new BulletClass(BULLET_NUKE_UP, targ, this, 200, WARHEAD_HE, MPH_VERY_FAST);
   4498 					if (bullet) {
   4499 						COORDINATE launch = Coord_Move(Center_Coord(), (DirType)28, 0xA0);
   4500 						if (!bullet->Unlimbo(launch, DIR_N)) {
   4501 							delete bullet;
   4502 							bullet = NULL;
   4503 						}
   4504 					}
   4505 
   4506 					if (bullet) {
   4507 						Speak(VOX_ABOMB_LAUNCH);
   4508 						Status = LAUNCH_DOWN;
   4509 						/*
   4510 						** Hack: If it's the artificial nukes, don't let the bullets come down (as
   4511 						** they're the only ones that blow up).  We know it's artificial if you're
   4512 						** at tech level 10 or below, because you can't build the nuclear silo until
   4513 						** tech level 15 or so.
   4514 						*/
   4515 						if (House->Control.TechLevel <= 10) {
   4516 							return(6);
   4517 						}
   4518 						bullet = new BulletClass(BULLET_NUKE_DOWN, ::As_Target(House->NukeDest), this, 200, WARHEAD_NUKE, MPH_VERY_FAST);
   4519 						if (bullet) {
   4520 							int celly = Cell_Y(House->NukeDest);
   4521 							celly -= 64;
   4522 							if (celly < 1) celly = 1;
   4523 							COORDINATE start = Cell_Coord(XY_Cell(Cell_X(House->NukeDest), celly));
   4524 							if (!bullet->Unlimbo(start, DIR_S)) {
   4525 								delete bullet;
   4526 							}
   4527 						}
   4528 						return(8 * TICKS_PER_SECOND);
   4529 					}
   4530 				}
   4531 				return(1);
   4532 
   4533 			/*
   4534 			** Once the missile is in the air, this handles waiting for
   4535 			** the missile to be off the screen and then launching one down
   4536 			** over the target.
   4537 			*/
   4538 			case LAUNCH_DOWN:
   4539 				{
   4540 					Begin_Mode(BSTATE_AUX2);	// start the door closing
   4541 
   4542 #ifdef OBSOLETE
   4543 					/*
   4544 					** Hack: If it's the artificial nukes, don't let the bullets come down (as
   4545 					** they're the only ones that blow up).  We know it's artificial if you're
   4546 					** at tech level 10 or below, because you can't build the nuclear silo until
   4547 					** tech level 15 or so.
   4548 					*/
   4549 					if (House->Control.TechLevel <= 10) {
   4550 						Status = DONE_LAUNCH;
   4551 						return(6);
   4552 					}
   4553 					BulletClass * bullet = new BulletClass(BULLET_NUKE_DOWN, ::As_Target(House->NukeDest), this, 200, WARHEAD_NUKE, MPH_VERY_FAST);
   4554 					if (bullet) {
   4555 						int celly = Cell_Y(House->NukeDest);
   4556 						celly -= 15;
   4557 						if (celly < 1) celly = 1;
   4558 						COORDINATE start = Cell_Coord(XY_Cell(Cell_X(House->NukeDest), celly));
   4559 						if (!bullet->Unlimbo(start, DIR_S)) {
   4560 							delete bullet;
   4561 						}
   4562 					}
   4563 					if (bullet) {
   4564 #endif
   4565 						Status = DONE_LAUNCH;
   4566 						return(6);
   4567 					}
   4568 #ifdef OBSOLETE
   4569 				}
   4570 				return(1);
   4571 #endif
   4572 
   4573 			/*
   4574 			** Once the missile is done launching this handles allowing
   4575 			** the building to sit there with its door closed.
   4576 			*/
   4577 			case DONE_LAUNCH:
   4578 				Begin_Mode(BSTATE_IDLE);	// keep the door closed.
   4579 				Assign_Mission(MISSION_GUARD);
   4580 				return(60);
   4581 		}
   4582 	}
   4583 	return(MissionControl[Mission].Normal_Delay());
   4584 }
   4585 
   4586 
   4587 /***********************************************************************************************
   4588  * BuildingClass::Revealed -- Reveals the building to the specified house.                     *
   4589  *                                                                                             *
   4590  *    This routine will reveal the building to the specified house. It will handle updating    *
   4591  *    the sidebar for player owned buildings. A player owned building that hasn't been         *
   4592  *    revealed, is in a state of pseudo-limbo. It cannot be used for any of its special        *
   4593  *    abilities even though it exists on the map for all other purposes.                       *
   4594  *                                                                                             *
   4595  * INPUT:   house -- The house that this building is being revealed to.                        *
   4596  *                                                                                             *
   4597  * OUTPUT:  Was this building revealed by this procedure?                                      *
   4598  *                                                                                             *
   4599  * WARNINGS:   none                                                                            *
   4600  *                                                                                             *
   4601  * HISTORY:                                                                                    *
   4602  *   06/25/1995 JLB : Created.                                                                 *
   4603  *=============================================================================================*/
   4604 bool BuildingClass::Revealed(HouseClass * house)
   4605 {
   4606 	assert(Buildings.ID(this) == ID);
   4607 	assert(IsActive);
   4608 
   4609 	if (TechnoClass::Revealed(house)) {
   4610 
   4611 		if (!ScenarioInit) {
   4612 			House->JustBuiltStructure = Class->Type;
   4613 			House->IsBuiltSomething = true;
   4614 		}
   4615 		House->IsRecalcNeeded = true;
   4616 
   4617 		/*
   4618 		**	Perform any grand opening here so that in the scenarios where a player
   4619 		**	owned house is not yet revealed, it won't be reflected in the sidebar
   4620 		**	selection icons.
   4621 		*/
   4622 		if (!In_Radio_Contact() && House->IsHuman && Mission != MISSION_CONSTRUCTION) {
   4623 			Grand_Opening();
   4624 		} else {
   4625 			if (!In_Radio_Contact() && !House->IsHuman && house == House && Mission != MISSION_CONSTRUCTION) {
   4626 				Grand_Opening();
   4627 			}
   4628 		}
   4629 
   4630 		return(true);
   4631 	}
   4632 	return(false);
   4633 }
   4634 
   4635 
   4636 /***********************************************************************************************
   4637  * BuildingClass::Enter_Idle_Mode -- The building will enter its idle mode.                    *
   4638  *                                                                                             *
   4639  *    This routine is called when the exact mode of the building isn't known. By examining     *
   4640  *    the building's condition, this routine will assign an appropriate mission.               *
   4641  *                                                                                             *
   4642  * INPUT:   initial  -- This this being called during scenario init?                           *
   4643  *                                                                                             *
   4644  * OUTPUT:  none                                                                               *
   4645  *                                                                                             *
   4646  * WARNINGS:   none                                                                            *
   4647  *                                                                                             *
   4648  * HISTORY:                                                                                    *
   4649  *   06/25/1995 JLB : Created.                                                                 *
   4650  *=============================================================================================*/
   4651 void BuildingClass::Enter_Idle_Mode(bool initial)
   4652 {
   4653 	assert(Buildings.ID(this) == ID);
   4654 	assert(IsActive);
   4655 
   4656 	/*
   4657 	**	Assign an appropriate mission for the building. If the ScenarioInit flag is true, then
   4658 	**	this must be an initial building. Start such buildings in idle state. For other buildings
   4659 	**	it indicates that it is being placed during game play and thus it must start in
   4660 	**	the "construction" mission.
   4661 	*/
   4662 	MissionType mission = MISSION_GUARD;
   4663 
   4664 
   4665 	if (!initial || ScenarioInit || Debug_Map) {
   4666 		Begin_Mode(BSTATE_IDLE);
   4667 		mission = MISSION_GUARD;
   4668 	} else {
   4669 		Begin_Mode(BSTATE_CONSTRUCTION);
   4670 		mission = MISSION_CONSTRUCTION;
   4671 	}
   4672 	Assign_Mission(mission);
   4673 }
   4674 
   4675 
   4676 /***********************************************************************************************
   4677  * BuildingClass::Pip_Count -- Determines "full" pips to display for building.                 *
   4678  *                                                                                             *
   4679  *    This routine will determine the number of pips that should be filled in when rendering   *
   4680  *    the building.                                                                            *
   4681  *                                                                                             *
   4682  * INPUT:   none                                                                               *
   4683  *                                                                                             *
   4684  * OUTPUT:  Returns the number of pips to display as filled in.                                *
   4685  *                                                                                             *
   4686  * WARNINGS:   none                                                                            *
   4687  *                                                                                             *
   4688  * HISTORY:                                                                                    *
   4689  *   06/28/1995 JLB : Created.                                                                 *
   4690  *=============================================================================================*/
   4691 int BuildingClass::Pip_Count(void) const
   4692 {
   4693 	assert(Buildings.ID(this) == ID);
   4694 	assert(IsActive);
   4695 
   4696 	return(Class->Max_Pips() * House->Tiberium_Fraction());
   4697 }
   4698 
   4699 
   4700 /***********************************************************************************************
   4701  * BuildingClass::Death_Announcement -- Announce the death of this building.                   *
   4702  *                                                                                             *
   4703  *    This routine is called when the building is destroyed by "unnatural" means. Typically    *
   4704  *    as a result of combat. If the building is known to the player, then it should be         *
   4705  *    announced.                                                                               *
   4706  *                                                                                             *
   4707  * INPUT:   source   -- The object most directly responsible for the building's death.         *
   4708  *                                                                                             *
   4709  * OUTPUT:  none                                                                               *
   4710  *                                                                                             *
   4711  * WARNINGS:   none                                                                            *
   4712  *                                                                                             *
   4713  * HISTORY:                                                                                    *
   4714  *   07/04/1995 JLB : Created.                                                                 *
   4715  *=============================================================================================*/
   4716 void BuildingClass::Death_Announcement(TechnoClass const * source) const
   4717 {
   4718 	assert(Buildings.ID(this) == ID);
   4719 	assert(IsActive);
   4720 
   4721 	if (source != NULL && House->IsPlayerControl) {
   4722 		Speak(VOX_STRUCTURE_DESTROYED);
   4723 	}
   4724 }
   4725 
   4726 
   4727 /***********************************************************************************************
   4728  * BuildingClass::Fire_Direction -- Fetches the direction of firing.                           *
   4729  *                                                                                             *
   4730  *    This routine will return with the default direction to use when firing from this         *
   4731  *    building. This is the facing of the turret except for the case of non-turret equipped    *
   4732  *    buildings that have a weapon (e.g., guard tower).                                        *
   4733  *                                                                                             *
   4734  * INPUT:   none                                                                               *
   4735  *                                                                                             *
   4736  * OUTPUT:  Returns with the default firing direction for this building.                       *
   4737  *                                                                                             *
   4738  * WARNINGS:   none                                                                            *
   4739  *                                                                                             *
   4740  * HISTORY:                                                                                    *
   4741  *   07/04/1995 JLB : Created.                                                                 *
   4742  *=============================================================================================*/
   4743 DirType BuildingClass::Fire_Direction(void) const
   4744 {
   4745 	assert(Buildings.ID(this) == ID);
   4746 	assert(IsActive);
   4747 
   4748 	if (Class->IsTurretEquipped) {
   4749 		return(PrimaryFacing.Current());
   4750 	}
   4751 	return(Direction(TarCom));
   4752 }
   4753 
   4754 
   4755 /***********************************************************************************************
   4756  * BuildingClass::Remap_Table -- Fetches the remap table to use for this building.             *
   4757  *                                                                                             *
   4758  *    Use this routine to fetch the remap table to use.  This override function is needed      *
   4759  *    because the default remap table for techno objects presumes the object is a unit.        *
   4760  *    Buildings aren't units.                                                                  *
   4761  *                                                                                             *
   4762  * INPUT:   none                                                                               *
   4763  *                                                                                             *
   4764  * OUTPUT:  Returns with the proper remap table to use for this building.                      *
   4765  *                                                                                             *
   4766  * WARNINGS:   none                                                                            *
   4767  *                                                                                             *
   4768  * HISTORY:                                                                                    *
   4769  *   07/08/1995 JLB : Created.                                                                 *
   4770  *=============================================================================================*/
   4771 void const * BuildingClass::Remap_Table(void)
   4772 {
   4773 	assert(Buildings.ID(this) == ID);
   4774 	assert(IsActive);
   4775 
   4776 	return(House->Remap_Table(IsBlushing, Class->Remap));
   4777 }
   4778 
   4779 
   4780 /***********************************************************************************************
   4781  * BuildingClass::Mission_Unload -- Handles the unload mission for a building.                 *
   4782  *                                                                                             *
   4783  *    This is the unload mission for a building. This really only applies to the weapon's      *
   4784  *    factory, since it needs the sophistication of an unload mission due to the door          *
   4785  *    animation.                                                                               *
   4786  *                                                                                             *
   4787  * INPUT:   none                                                                               *
   4788  *                                                                                             *
   4789  * OUTPUT:  Returns with the number of game frames to delay before calling this routine        *
   4790  *          again.                                                                             *
   4791  *                                                                                             *
   4792  * WARNINGS:   none                                                                            *
   4793  *                                                                                             *
   4794  * HISTORY:                                                                                    *
   4795  *   07/29/1995 JLB : Created.                                                                 *
   4796  *=============================================================================================*/
   4797 int BuildingClass::Mission_Unload(void)
   4798 {
   4799 	assert(Buildings.ID(this) == ID);
   4800 	assert(IsActive);
   4801 
   4802 	if (*this == STRUCT_WEAP) {
   4803 		CELL cell = Coord_Cell(Coord) + Class->ExitList[0];
   4804 		COORDINATE coord = Cell_Coord(cell);
   4805 		CellClass * cellptr = &Map[cell];
   4806 		enum {
   4807 			INITIAL,
   4808 			CLEAR_BIB,
   4809 			OPEN,
   4810 			LEAVE,
   4811 			CLOSE
   4812 		};
   4813 		enum {
   4814 			DOOR_STAGES = 5,
   4815 			DOOR_RATE = 8
   4816 		};
   4817 		UnitClass * unit;
   4818 		switch (Status) {
   4819 			/*
   4820 			**	Start the door opening.
   4821 			*/
   4822 			case INITIAL:
   4823 //				if (cellptr->Cell_Techno()) {
   4824 //					cellptr->Incoming(0, true);
   4825 //				}
   4826 				unit = (UnitClass *)Contact_With_Whom();
   4827 				if (unit) {
   4828 					unit->Assign_Mission(MISSION_GUARD);
   4829 					unit->Commence();
   4830 				}
   4831 				Open_Door(DOOR_RATE, DOOR_STAGES);
   4832 				Status = CLEAR_BIB;
   4833 				break;
   4834 
   4835 			/*
   4836 			**	Now that the occupants can peek out the door, they will tell
   4837 			**	everyone that could be blocking the way, that they should
   4838 			**	scatter away.
   4839 			*/
   4840 			case CLEAR_BIB:
   4841 				if (cellptr->Cell_Techno()) {
   4842 					cellptr->Incoming(0, true, true);
   4843 
   4844 					/*
   4845 					**	Scatter everything around the weapon's factory door.
   4846 					*/
   4847 					for (FacingType f = FACING_FIRST; f < FACING_COUNT; f++) {
   4848 						CellClass * cptr = cellptr->Adjacent_Cell(f);
   4849 						if (cptr && cptr->Cell_Building() == NULL) {
   4850 							cptr->Incoming(coord, true, true);
   4851 						}
   4852 					}
   4853 				} else {
   4854 					Status = OPEN;
   4855 				}
   4856 				break;
   4857 
   4858 			/*
   4859 			**	When the door is finally open and the way is clear, tell the
   4860 			**	unit to drive out.
   4861 			*/
   4862 			case OPEN:
   4863 				if (Is_Door_Open()) {
   4864 					unit = (UnitClass *)Contact_With_Whom();
   4865 					if (unit) {
   4866 						unit->Assign_Mission(MISSION_MOVE);
   4867 
   4868 						if (House->IQ >= Rule.IQGuardArea) {
   4869 							unit->Assign_Mission(MISSION_GUARD_AREA);
   4870 							unit->ArchiveTarget = ::As_Target(House->Where_To_Go(unit));
   4871 						}
   4872 						unit->Force_Track(DriveClass::OUT_OF_WEAPON_FACTORY, coord);
   4873 //						unit->Force_Track(DriveClass::OUT_OF_WEAPON_FACTORY, Adjacent_Cell(Adjacent_Cell(Center_Coord(), FACING_S), FACING_S));
   4874 						unit->Set_Speed(128);
   4875 						Status = LEAVE;
   4876 					} else {
   4877 						Close_Door(DOOR_RATE, DOOR_STAGES);
   4878 						Status = CLOSE;
   4879 					}
   4880 				}
   4881 				break;
   4882 
   4883 			/*
   4884 			**	Wait until the unit has completely left the building.
   4885 			*/
   4886 			case LEAVE:
   4887 				if (!IsTethered) {
   4888 					Close_Door(DOOR_RATE, DOOR_STAGES);
   4889 					Status = CLOSE;
   4890 				} else {
   4891 
   4892 //					if (In_Radio_Contact() && !((FootClass *)Contact_With_Whom())->IsDriving) {
   4893 //						Transmit_Message(RADIO_OVER_OUT);
   4894 //					}
   4895 
   4896 				}
   4897 				break;
   4898 
   4899 			/*
   4900 			**	Wait while the door closes.
   4901 			*/
   4902 			case CLOSE:
   4903 				if (Is_Door_Closed()) {
   4904 					Enter_Idle_Mode();
   4905 				}
   4906 				break;
   4907 
   4908 			default:
   4909 				break;
   4910 		}
   4911 		return(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));
   4912 	}
   4913 
   4914 	Assign_Mission(MISSION_GUARD);
   4915 	return(1);
   4916 }
   4917 
   4918 
   4919 /***********************************************************************************************
   4920  * BuildingClass::Power_Output -- Fetches the current power output from this building.         *
   4921  *                                                                                             *
   4922  *    This routine will return the current power output for this building. The power output    *
   4923  *    is adjusted according to the damage level of the building.                               *
   4924  *                                                                                             *
   4925  * INPUT:   none                                                                               *
   4926  *                                                                                             *
   4927  * OUTPUT:  Returns the current power output for this building.                                *
   4928  *                                                                                             *
   4929  * WARNINGS:   none                                                                            *
   4930  *                                                                                             *
   4931  * HISTORY:                                                                                    *
   4932  *   07/29/1995 JLB : Created.                                                                 *
   4933  *=============================================================================================*/
   4934 int BuildingClass::Power_Output(void) const
   4935 {
   4936 	assert(Buildings.ID(this) == ID);
   4937 	assert(IsActive);
   4938 
   4939 	if (Class->Power) {
   4940 		return(Class->Power * fixed(LastStrength, Class->MaxStrength));
   4941 	}
   4942 	return(0);
   4943 }
   4944 
   4945 
   4946 /***********************************************************************************************
   4947  * BuildingClass::Detach -- Handles target removal from the game system.                       *
   4948  *                                                                                             *
   4949  *    This routine is called when the specified target is about to be removed from the game    *
   4950  *    system.                                                                                  *
   4951  *                                                                                             *
   4952  * INPUT:   target   -- The target to be removed from this building's targeting computer.      *
   4953  *                                                                                             *
   4954  *          all      -- Is the target about to be completely eliminated?                       *
   4955  *                                                                                             *
   4956  * OUTPUT:  none                                                                               *
   4957  *                                                                                             *
   4958  * WARNINGS:   none                                                                            *
   4959  *                                                                                             *
   4960  * HISTORY:                                                                                    *
   4961  *   07/29/1995 JLB : Created.                                                                 *
   4962  *=============================================================================================*/
   4963 void BuildingClass::Detach(TARGET target, bool all)
   4964 {
   4965 	assert(Buildings.ID(this) == ID);
   4966 	assert(IsActive);
   4967 
   4968 	TechnoClass::Detach(target, all);
   4969 	if (target == WhomToRepay) {
   4970 		WhomToRepay = TARGET_NONE;
   4971 	}
   4972 	if (target == AnimToTrack) {
   4973 		AnimToTrack = TARGET_NONE;
   4974 	}
   4975 }
   4976 
   4977 
   4978 /***********************************************************************************************
   4979  * BuildingClass::Crew_Type -- This determines the crew that this object generates.            *
   4980  *                                                                                             *
   4981  *    When selling very cheap buildings (such as the silo), a technician will pop out since    *
   4982  *    generating minigunners would be overkill -- the player could use this loophole to        *
   4983  *    gain an advantage.                                                                       *
   4984  *                                                                                             *
   4985  * INPUT:   none                                                                               *
   4986  *                                                                                             *
   4987  * OUTPUT:  Returns the infantry type that this building will generate as a survivor.          *
   4988  *                                                                                             *
   4989  * WARNINGS:   none                                                                            *
   4990  *                                                                                             *
   4991  * HISTORY:                                                                                    *
   4992  *   08/05/1995 JLB : Created.                                                                 *
   4993  *=============================================================================================*/
   4994 InfantryType BuildingClass::Crew_Type(void) const
   4995 {
   4996 	assert(Buildings.ID(this) == ID);
   4997 	assert(IsActive);
   4998 
   4999 	switch (Class->Type) {
   5000 		case STRUCT_STORAGE:
   5001 			if (Percent_Chance(50)) {
   5002 				return(INFANTRY_C1);
   5003 			} else {
   5004 				return(INFANTRY_C7);
   5005 			}
   5006 
   5007 		case STRUCT_CONST:
   5008 			if (!IsCaptured && House->IsHuman && Percent_Chance(25)) {
   5009 				return(INFANTRY_RENOVATOR);
   5010 			}
   5011 			break;
   5012 
   5013 		case STRUCT_KENNEL:
   5014 			if (Percent_Chance(50)) {
   5015 				return(INFANTRY_DOG);
   5016 			} else {
   5017 				return(INFANTRY_NONE);
   5018 			}
   5019 
   5020 		case STRUCT_TENT:
   5021 		case STRUCT_BARRACKS:
   5022 			return(INFANTRY_E1);
   5023 
   5024 		default:
   5025 			break;
   5026 	}
   5027 	return(TechnoClass::Crew_Type());
   5028 }
   5029 
   5030 
   5031 /***********************************************************************************************
   5032  * BuildingClass::Detach_All -- Possibly abandons production according to factory type.        *
   5033  *                                                                                             *
   5034  *    When this routine is called, it indicates that the building is about to be destroyed     *
   5035  *    or captured. In such a case any production it may be doing, must be abandoned.           *
   5036  *                                                                                             *
   5037  * INPUT:   all   -- Is the object about the be completely destroyed?                          *
   5038  *                                                                                             *
   5039  * OUTPUT:  none                                                                               *
   5040  *                                                                                             *
   5041  * WARNINGS:   none                                                                            *
   5042  *                                                                                             *
   5043  * HISTORY:                                                                                    *
   5044  *   08/05/1995 JLB : Created.                                                                 *
   5045  *=============================================================================================*/
   5046 void BuildingClass::Detach_All(bool all)
   5047 {
   5048 	assert(Buildings.ID(this) == ID);
   5049 	assert(IsActive);
   5050 
   5051 	/*
   5052 	**	If it is producing something, then it must be abandoned.
   5053 	*/
   5054 	if (Factory) {
   5055 		Factory->Abandon();
   5056 		delete (FactoryClass *)Factory;
   5057 		Factory = 0;
   5058 	}
   5059 
   5060 	/*
   5061 	** If the owner HouseClass is building something, and this building can
   5062 	** build that thing, we may be the last building for that house that can
   5063 	** build that thing; if so, abandon production of it.
   5064 	*/
   5065 	if (House) {
   5066 		FactoryClass * factory = House->Fetch_Factory(Class->ToBuild);
   5067 
   5068 		/*
   5069 		**	If a factory was found, then temporarily disable this building and then
   5070 		**	determine if any object that is being produced can still be produced. If
   5071 		**	not, then the object being produced must be abandoned.
   5072 		*/
   5073 		if (factory) {
   5074 			TechnoClass * object = factory->Get_Object();
   5075 			IsInLimbo = true;
   5076 			if (object && !object->Techno_Type_Class()->Who_Can_Build_Me(true, false, House->Class->House)) {
   5077 				House->Abandon_Production(Class->ToBuild);
   5078 			}
   5079 			IsInLimbo = false;
   5080 		}
   5081 	}
   5082 
   5083 	TechnoClass::Detach_All(all);
   5084 }
   5085 
   5086 
   5087 /***********************************************************************************************
   5088  * BuildingClass::Flush_For_Placement -- Handles clearing a zone for object placement.         *
   5089  *                                                                                             *
   5090  *    This routine is used to clear the way for placement of the specified object (usually     *
   5091  *    a building). If there are friendly units blocking the placement area, they are told      *
   5092  *    to scatter. Enemy blocking units are attacked.                                           *
   5093  *                                                                                             *
   5094  * INPUT:   techno   -- Pointer to the object that is desired to be placed.                    *
   5095  *                                                                                             *
   5096  *          cell     -- The cell that placement wants to occur at.                             *
   5097  *                                                                                             *
   5098  * OUTPUT:  none                                                                               *
   5099  *                                                                                             *
   5100  * WARNINGS:   none                                                                            *
   5101  *                                                                                             *
   5102  * HISTORY:                                                                                    *
   5103  *   08/06/1995 JLB : Created.                                                                 *
   5104  *   09/27/1995 JLB : Revised to use type class function.                                      *
   5105  *=============================================================================================*/
   5106 bool BuildingClass::Flush_For_Placement(TechnoClass * techno, CELL cell)
   5107 {
   5108 	assert(Buildings.ID(this) == ID);
   5109 	assert(IsActive);
   5110 
   5111 	if (techno) {
   5112 		return (((BuildingTypeClass const &)techno->Class_Of()).Flush_For_Placement(cell, House));
   5113 	}
   5114 	return(false);
   5115 }
   5116 
   5117 
   5118 /***********************************************************************************************
   5119  * BuildingClass::Find_Exit_Cell -- Find a clear location to exit an object from this building *
   5120  *                                                                                             *
   5121  *    This routine is called when the building needs to discharge a unit. It will find a       *
   5122  *    nearby (adjacent) cell that is clear enough for the specified object to enter. Typical   *
   5123  *    use of this routine is when the airfield disgorges its cargo.                            *
   5124  *                                                                                             *
   5125  * INPUT:   techno   -- Pointer to the object that wishes to exit this building.               *
   5126  *                                                                                             *
   5127  * OUTPUT:  Returns with the cell number to use for object placement. If no free location      *
   5128  *          could be found, then zero (0) is returned.                                         *
   5129  *                                                                                             *
   5130  * WARNINGS:   none                                                                            *
   5131  *                                                                                             *
   5132  * HISTORY:                                                                                    *
   5133  *   09/21/1995 JLB : Created.                                                                 *
   5134  *   02/20/1996 JLB : Added default case for exit cell calculation.                            *
   5135  *=============================================================================================*/
   5136 CELL BuildingClass::Find_Exit_Cell(TechnoClass const * techno) const
   5137 {
   5138 	assert(Buildings.ID(this) == ID);
   5139 	assert(IsActive);
   5140 
   5141 	CELL const * ptr;
   5142 	CELL origin = Coord_Cell(Coord);
   5143 
   5144 	ptr = Class->ExitList;
   5145 	if (ptr != NULL) {
   5146 		while (*ptr != REFRESH_EOL) {
   5147 			CELL cell = origin + *ptr++;
   5148 			if (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {
   5149 				return(cell);
   5150 			}
   5151 		}
   5152 	} else {
   5153 		int x1, x2;
   5154 		int y1, y2;
   5155 		CELL cell;
   5156 
   5157 		y1 = -1;
   5158 		y2 = Class->Height();
   5159 		for (x1 = -1; x1 <= Class->Width(); x1++) {
   5160 			cell = origin + x1 + (y1 * MAP_CELL_W);
   5161 			if (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {
   5162 				return(cell);
   5163 			}
   5164 			cell = origin + x1 + (y2 * MAP_CELL_W);
   5165 			if (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {
   5166 				return(cell);
   5167 			}
   5168 		}
   5169 
   5170 		x1 = -1;
   5171 		x2 = Class->Width();
   5172 		for (y1 = -1; y1 <= Class->Height(); y1++) {
   5173 			cell = origin + (y1 * MAP_CELL_W) + x1;
   5174 			if (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {
   5175 				return(cell);
   5176 			}
   5177 			cell = origin + (y1 * MAP_CELL_W) + x2;
   5178 			if (Map.In_Radar(cell) && techno->Can_Enter_Cell(cell) == MOVE_OK) {
   5179 				return(cell);
   5180 			}
   5181 		}
   5182 	}
   5183 	return(0);
   5184 }
   5185 
   5186 
   5187 /***********************************************************************************************
   5188  * BuildingClass::Can_Player_Move -- Can this building be moved?                               *
   5189  *                                                                                             *
   5190  *    This routine answers the question 'can this building be moved?' Typically, only the      *
   5191  *    construction yard can be moved and it does this by undeploying back into a MCV.          *
   5192  *                                                                                             *
   5193  * INPUT:   none                                                                               *
   5194  *                                                                                             *
   5195  * OUTPUT:  Can the building move to a new location under player control?                      *
   5196  *                                                                                             *
   5197  * WARNINGS:   none                                                                            *
   5198  *                                                                                             *
   5199  * HISTORY:                                                                                    *
   5200  *   10/04/1995 JLB : Created.                                                                 *
   5201  *=============================================================================================*/
   5202 bool BuildingClass::Can_Player_Move(void) const
   5203 {
   5204 	assert(Buildings.ID(this) == ID);
   5205 	assert(IsActive);
   5206 
   5207 	return(*this == STRUCT_CONST && (Mission == MISSION_GUARD) && Special.IsMCVDeploy);
   5208 }
   5209 
   5210 
   5211 /***********************************************************************************************
   5212  * BuildingClass::Exit_Coord -- Determines location where object will leave it.                *
   5213  *                                                                                             *
   5214  *    This routine will return the coordinate where an object that wishes to leave the         *
   5215  *    building will exit at.                                                                   *
   5216  *                                                                                             *
   5217  * INPUT:   none                                                                               *
   5218  *                                                                                             *
   5219  * OUTPUT:  Returns with the coordinate that the object should be created at.                  *
   5220  *                                                                                             *
   5221  * WARNINGS:   none                                                                            *
   5222  *                                                                                             *
   5223  * HISTORY:                                                                                    *
   5224  *   02/20/1996 JLB : Created.                                                                 *
   5225  *=============================================================================================*/
   5226 COORDINATE BuildingClass::Exit_Coord(void) const
   5227 {
   5228 	assert(Buildings.ID(this) == ID);
   5229 	assert(IsActive);
   5230 
   5231 	if (Class->ExitCoordinate) {
   5232 		return(Coord_Add(Coord, Class->ExitCoordinate));
   5233 	}
   5234 	return(TechnoClass::Exit_Coord());
   5235 }
   5236 
   5237 
   5238 /***********************************************************************************************
   5239  * BuildingClass::Check_Point -- Fetches the landing checkpoint for the given flight pattern.  *
   5240  *                                                                                             *
   5241  *    Use this routine to coordinate a landing operation. The specified checkpoint is          *
   5242  *    converted into a cell number. The landing aircraft should fly over that cell and then    *
   5243  *    request the next check point.                                                            *
   5244  *                                                                                             *
   5245  * INPUT:   cp    -- The check point to convert to a cell number.                              *
   5246  *                                                                                             *
   5247  * OUTPUT:  Returns with the cell that the aircraft should fly over in order to complete       *
   5248  *          that portion of the landing pattern.                                               *
   5249  *                                                                                             *
   5250  * WARNINGS:   none                                                                            *
   5251  *                                                                                             *
   5252  * HISTORY:                                                                                    *
   5253  *   07/06/1996 JLB : Created.                                                                 *
   5254  *=============================================================================================*/
   5255 CELL BuildingClass::Check_Point(CheckPointType cp) const
   5256 {
   5257 	CELL xoffset = 6;		// Downwind offset.
   5258 	CELL yoffset = 5;		// Crosswind offset.
   5259 	CELL cell = Coord_Cell(Center_Coord());
   5260 
   5261 	switch (cp) {
   5262 		case CHECK_STACK:
   5263 			xoffset = 0;
   5264 			break;
   5265 
   5266 		case CHECK_CROSSWIND:
   5267 			yoffset = 0;
   5268 			break;
   5269 
   5270 		case CHECK_DOWNWIND:
   5271 		default:
   5272 			break;
   5273 	}
   5274 
   5275 	if ((Cell_X(cell) - Map.MapCellX) > Map.MapCellWidth/2)  {
   5276 		xoffset = -xoffset;
   5277 	}
   5278 
   5279 	if ((Cell_Y(cell) - Map.MapCellY) > Map.MapCellHeight/2)  {
   5280 		yoffset = -yoffset;
   5281 	}
   5282 
   5283 	return(XY_Cell(Cell_X(cell)+xoffset, Cell_Y(cell)+yoffset));
   5284 }
   5285 
   5286 
   5287 /***********************************************************************************************
   5288  * BuildingClass::Update_Radar_Spied - set house's RadarSpied field appropriately.				  *
   5289  *                                                                                             *
   5290  *    This routine is called when a radar facility is captured or destroyed.  It fills in the  *
   5291  *    RadarSpied field of the house based on whether there's a spied-upon radar facility or not*
   5292  *                                                                                             *
   5293  * INPUT:   none                                                                               *
   5294  *                                                                                             *
   5295  * OUTPUT:  House->RadarSpied field gets set appropriately.												  *
   5296  *                                                                                             *
   5297  * WARNINGS:   none                                                                            *
   5298  *                                                                                             *
   5299  * HISTORY:                                                                                    *
   5300  *   03/22/1996 BWG : Created.                                                                 *
   5301  *=============================================================================================*/
   5302 void BuildingClass::Update_Radar_Spied(void)
   5303 {
   5304 	House->RadarSpied = 0;
   5305 	for (int index = 0; index < Buildings.Count(); index++) {
   5306 		BuildingClass * obj = Buildings.Ptr(index);
   5307 		if (obj && !obj->IsInLimbo && obj->House == House) {
   5308 			if (*obj == STRUCT_RADAR /* || *obj == STRUCT_EYE */) {
   5309 				House->RadarSpied |= obj->Spied_By();
   5310 			}
   5311 		}
   5312 	}
   5313 	Map.RadarClass::Flag_To_Redraw(true);
   5314 }
   5315 
   5316 
   5317 /***********************************************************************************************
   5318  * BuildingClass::Read_INI -- Reads buildings from INI file.                                   *
   5319  *                                                                                             *
   5320  *    This is the basic scenario initialization of building function. It                       *
   5321  *    is called when reading the scenario startup INI file and it handles                      *
   5322  *    creation of all specified buildings.                                                     *
   5323  *                                                                                             *
   5324  *    INI entry format:                                                                        *
   5325  *      Housename, Typename, Strength, Cell, Facing, Triggername                               *
   5326  *                                                                                             *
   5327  * INPUT:   buffer   -- Pointer to the loaded INI file data.                                   *
   5328  *                                                                                             *
   5329  * OUTPUT:  none                                                                               *
   5330  *                                                                                             *
   5331  * WARNINGS:   none                                                                            *
   5332  *                                                                                             *
   5333  * HISTORY:                                                                                    *
   5334  *   05/24/1994 JLB : Created.                                                                 *
   5335  *=============================================================================================*/
   5336 void BuildingClass::Read_INI(CCINIClass & ini)
   5337 {
   5338 	BuildingClass			* b;			// Working unit pointer.
   5339 	HousesType				bhouse;		// Building house.
   5340 	StructType				classid;		// Building type.
   5341 	CELL						cell;			// Cell of building.
   5342 	char						buf[128];
   5343 	char						* trigname;	// building's trigger's name
   5344 
   5345 
   5346 	int len = ini.Entry_Count(INI_Name());
   5347 	for (int index = 0; index < len; index++) {
   5348 		char const * entry = ini.Get_Entry(INI_Name(), index);
   5349 
   5350 		/*
   5351 		**	Get a building entry.
   5352 		*/
   5353 		ini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));
   5354 
   5355 		/*
   5356 		**	1st token: house name.
   5357 		*/
   5358 		bhouse = HouseTypeClass::From_Name(strtok(buf, ","));
   5359 
   5360 		/*
   5361 		**	2nd token: building name.
   5362 		*/
   5363 		classid = BuildingTypeClass::From_Name(strtok(NULL, ","));
   5364 
   5365 		if (bhouse != HOUSE_NONE && classid != STRUCT_NONE) {
   5366 			int	strength;
   5367 			DirType facing;
   5368 
   5369 			/*
   5370 			**	3rd token: strength.
   5371 			*/
   5372 			strength = atoi(strtok(NULL, ","));
   5373 
   5374 			/*
   5375 			**	4th token: cell #.
   5376 			*/
   5377 			cell = atoi(strtok(NULL, ","));
   5378 
   5379 			/*
   5380 			**	5th token: facing.
   5381 			*/
   5382 			facing = (DirType)atoi(strtok(NULL, ","));
   5383 
   5384 			/*
   5385 			**	6th token: triggername (can be NULL).
   5386 			*/
   5387 			trigname = strtok(NULL, ",");
   5388 
   5389 			bool sellable = false;
   5390 			char * token_pointer = strtok(NULL, ",");
   5391 			if (token_pointer) {
   5392 				sellable = atoi(token_pointer);
   5393 			}
   5394 
   5395 			bool rebuild = false;
   5396 			token_pointer = strtok(NULL, ",");
   5397 			if (token_pointer) {
   5398 				rebuild = atoi(token_pointer);
   5399 			}
   5400 
   5401 			if (HouseClass::As_Pointer(bhouse) != NULL) {
   5402 				b = new BuildingClass(classid, bhouse);
   5403 				if (b) {
   5404 
   5405 					TriggerTypeClass * tp = TriggerTypeClass::From_Name(trigname);
   5406 					if (tp) {
   5407 						TriggerClass * tt = Find_Or_Make(tp);
   5408 						if (tt) {
   5409 							tt->AttachCount++;
   5410 							b->Trigger = tt;
   5411 						}
   5412 					}
   5413 					b->IsAllowedToSell = sellable;
   5414 					b->IsToRebuild = rebuild;
   5415 					b->IsToRepair = rebuild || *b == STRUCT_CONST;
   5416 
   5417 					if (b->Unlimbo(Cell_Coord(cell), facing)) {
   5418 						strength = min(strength, 0x100);
   5419 						strength = (int)b->Class->MaxStrength * fixed(strength, 256);		// Cast to (int). ST - 5/8/2019
   5420 						b->Strength = strength;
   5421 						if (b->Strength > b->Class->MaxStrength-3) b->Strength = b->Class->MaxStrength;
   5422 						b->IsALemon = false;
   5423 					} else {
   5424 
   5425 						/*
   5426 						**	If the building could not be unlimboed on the map, then this indicates
   5427 						**	a serious error. Delete the building.
   5428 						*/
   5429 						delete b;
   5430 					}
   5431 				}
   5432 			}
   5433 		}
   5434 	}
   5435 }
   5436 
   5437 
   5438 /***********************************************************************************************
   5439  * BuildingClass::Write_INI -- Write out the building data to the INI file specified.          *
   5440  *                                                                                             *
   5441  *    This will store the building data (as it relates to scenario initialization) to the      *
   5442  *    INI database specified.                                                                  *
   5443  *                                                                                             *
   5444  * INPUT:   ini   -- Reference to the INI database that the building data will be stored to.   *
   5445  *                                                                                             *
   5446  * OUTPUT:  none                                                                               *
   5447  *                                                                                             *
   5448  * WARNINGS:   none                                                                            *
   5449  *                                                                                             *
   5450  * HISTORY:                                                                                    *
   5451  *   07/06/1996 JLB : Created.                                                                 *
   5452  *=============================================================================================*/
   5453 void BuildingClass::Write_INI(CCINIClass & ini)
   5454 {
   5455 	/*
   5456 	**	First, clear out all existing building data from the ini file.
   5457 	*/
   5458 	ini.Clear(INI_Name());
   5459 
   5460 	/*
   5461 	**	Write the data out.
   5462 	*/
   5463 	for (int index = 0; index < Buildings.Count(); index++) {
   5464 		BuildingClass * building = Buildings.Ptr(index);
   5465 		if (!building->IsInLimbo) {
   5466 			char	uname[10];
   5467 			char	buf[127];
   5468 
   5469 			sprintf(uname, "%d", index);
   5470 			sprintf(buf, "%s,%s,%d,%u,%d,%s,%d,%d",
   5471 				building->House->Class->IniName,
   5472 				building->Class->IniName,
   5473 				building->Health_Ratio()*256,
   5474 				Coord_Cell(building->Coord),
   5475 				building->PrimaryFacing.Current(),
   5476 				building->Trigger.Is_Valid() ? building->Trigger->Class->IniName : "None",
   5477 				building->IsAllowedToSell,
   5478 				building->IsToRebuild
   5479 				);
   5480 			ini.Put_String(INI_Name(), uname, buf);
   5481 		}
   5482 	}
   5483 }
   5484 
   5485 
   5486 /***********************************************************************************************
   5487  * BuildingClass::Target_Coord -- Return the coordinate to use when firing on this building.   *
   5488  *                                                                                             *
   5489  *    This routine will determine the "center" location of this building for purposes of       *
   5490  *    targeting. Usually, this location is somewhere near the foundation of the building.      *
   5491  *                                                                                             *
   5492  * INPUT:   none                                                                               *
   5493  *                                                                                             *
   5494  * OUTPUT:  Returns with the coordinate to use when firing upon this building (or trying to    *
   5495  *          walk onto it).                                                                     *
   5496  *                                                                                             *
   5497  * WARNINGS:   none                                                                            *
   5498  *                                                                                             *
   5499  * HISTORY:                                                                                    *
   5500  *   07/19/1996 JLB : Created.                                                                 *
   5501  *=============================================================================================*/
   5502 COORDINATE BuildingClass::Target_Coord(void) const
   5503 {
   5504 	COORDINATE coord = Center_Coord();
   5505 
   5506 	if (Class->FoundationFace != FACING_NONE) {
   5507 		return(Adjacent_Cell(coord, Class->FoundationFace));
   5508 	}
   5509 	return(coord);
   5510 }
   5511 
   5512 
   5513 /***********************************************************************************************
   5514  * BuildingClass::Factory_AI -- Handle factory production and initiation.                      *
   5515  *                                                                                             *
   5516  *    Some building (notably the computer controlled ones) can have a factory object attached. *
   5517  *    This routine handles processing of that factory and also detecting when production       *
   5518  *    should begin in order to initiate production.                                            *
   5519  *                                                                                             *
   5520  * INPUT:   none                                                                               *
   5521  *                                                                                             *
   5522  * OUTPUT:  none                                                                               *
   5523  *                                                                                             *
   5524  * WARNINGS:   Only call this routine once per building per game logic loop.                   *
   5525  *                                                                                             *
   5526  * HISTORY:                                                                                    *
   5527  *   07/29/1996 JLB : Created.                                                                 *
   5528  *=============================================================================================*/
   5529 void BuildingClass::Factory_AI(void)
   5530 {
   5531 	/*
   5532 	**	Handle any production tied to this building. Only computer controlled buildings have
   5533 	**	production attached to the building itself. The player uses the sidebar interface for
   5534 	**	all production control.
   5535 	*/
   5536 	if (Factory.Is_Valid() && Factory->Has_Completed() && PlacementDelay == 0) {
   5537 		TechnoClass * product = Factory->Get_Object();
   5538 //		FactoryClass * fact = Factory;
   5539 
   5540 		switch (Exit_Object(product)) {
   5541 
   5542 			/*
   5543 			**	If the object could not leave the factory, then either request
   5544 			**	a transport, place the (what must be a) building using another method, or
   5545 			**	abort the production and refund money.
   5546 			*/
   5547 			case 0:
   5548 				Factory->Abandon();
   5549 				delete (FactoryClass *)Factory;
   5550 				Factory = 0;
   5551 				break;
   5552 
   5553 			/*
   5554 			**	Exiting this building is prevented by some temporary blockage. Wait
   5555 			**	a bit before trying again.
   5556 			*/
   5557 			case 1:
   5558 				PlacementDelay = TICKS_PER_SECOND*3;
   5559 				break;
   5560 
   5561 			/*
   5562 			**	The object was successfully sent from this factory. Inform the house
   5563 			**	tracking logic that the requested object has been produced.
   5564 			*/
   5565 			case 2:
   5566 				switch (product->What_Am_I()) {
   5567 					case RTTI_VESSEL:
   5568 						House->JustBuiltVessel = ((VesselClass*)product)->Class->Type;
   5569 						House->IsBuiltSomething = true;
   5570 						break;
   5571 
   5572 					case RTTI_UNIT:
   5573 						House->JustBuiltUnit = ((UnitClass*)product)->Class->Type;
   5574 						House->IsBuiltSomething = true;
   5575 						break;
   5576 
   5577 					case RTTI_INFANTRY:
   5578 						House->JustBuiltInfantry = ((InfantryClass*)product)->Class->Type;
   5579 						House->IsBuiltSomething = true;
   5580 						break;
   5581 
   5582 					case RTTI_BUILDING:
   5583 						House->JustBuiltStructure = ((BuildingClass*)product)->Class->Type;
   5584 						House->IsBuiltSomething = true;
   5585 						break;
   5586 
   5587 					case RTTI_AIRCRAFT:
   5588 						House->JustBuiltAircraft = ((AircraftClass*)product)->Class->Type;
   5589 						House->IsBuiltSomething = true;
   5590 						break;
   5591 
   5592 					default:
   5593 						break;
   5594 				}
   5595 //				fact->Completed();
   5596 				Factory->Completed();
   5597 //				delete fact;
   5598 				delete (FactoryClass *)Factory;
   5599 				Factory = 0;
   5600 				break;
   5601 
   5602 			default:
   5603 				break;
   5604 		}
   5605 	}
   5606 
   5607 	/*
   5608 	**	Pick something to create for this factory.
   5609 	*/
   5610 	if (House->IsStarted && Mission != MISSION_CONSTRUCTION && Mission != MISSION_DECONSTRUCTION) {
   5611 
   5612 		/*
   5613 		**	Buildings that produce other objects have special factory logic handled here.
   5614 		*/
   5615 		if (Class->ToBuild != RTTI_NONE) {
   5616 			if (Factory.Is_Valid()) {
   5617 
   5618 				/*
   5619 				**	If production has halted, then just abort production and make the
   5620 				**	funds available for something else.
   5621 				*/
   5622 				if (PlacementDelay == 0 && !Factory->Is_Building()) {
   5623 					Factory->Abandon();
   5624 					delete (FactoryClass *)Factory;
   5625 					Factory = 0;
   5626 				}
   5627 
   5628 			} else {
   5629 
   5630 				/*
   5631 				**	Only look to start production if there is at least a small amount of
   5632 				**	money available. In cases where there is no practical money left, then
   5633 				**	production can never complete -- don't bother starting it.
   5634 				*/
   5635 				if (House->IsStarted && House->Available_Money() > 10) {
   5636 					TechnoTypeClass const * techno = House->Suggest_New_Object(Class->ToBuild, *this == STRUCT_KENNEL);
   5637 
   5638 					/*
   5639 					**	If a suitable object type was selected for production, then start
   5640 					**	producing it now.
   5641 					*/
   5642 					if (techno != NULL) {
   5643 						Factory = new FactoryClass;
   5644 						if (Factory.Is_Valid()) {
   5645 							if (!Factory->Set(*techno, *House)) {
   5646 								delete (FactoryClass *)Factory;
   5647 								Factory = 0;
   5648 							} else {
   5649 								House->Production_Begun(Factory->Get_Object());
   5650 								Factory->Start();
   5651 							}
   5652 						}
   5653 					}
   5654 				}
   5655 			}
   5656 		}
   5657 	}
   5658 }
   5659 
   5660 
   5661 /***********************************************************************************************
   5662  * BuildingClass::Rotation_AI -- Process any turret rotation required of this building.        *
   5663  *                                                                                             *
   5664  *    Some buildings have a turret and this routine handles processing the turret rotation.    *
   5665  *                                                                                             *
   5666  * INPUT:   none                                                                               *
   5667  *                                                                                             *
   5668  * OUTPUT:  none                                                                               *
   5669  *                                                                                             *
   5670  * WARNINGS:   Only call this routine once per building per game logic loop.                   *
   5671  *                                                                                             *
   5672  * HISTORY:                                                                                    *
   5673  *   07/29/1996 JLB : Created.                                                                 *
   5674  *   10/27/1996 JLB : Rotation does not occur if power and no power avail.                     *
   5675  *=============================================================================================*/
   5676 void BuildingClass::Rotation_AI(void)
   5677 {
   5678 	if (Class->IsTurretEquipped &&
   5679 			Mission != MISSION_CONSTRUCTION &&
   5680 			Mission != MISSION_DECONSTRUCTION &&
   5681 			(!Class->IsPowered || House->Power_Fraction() >= 1)) {
   5682 
   5683 		/*
   5684 		**	Rotate turret to match desired facing.
   5685 		*/
   5686 		if (PrimaryFacing.Is_Rotating()) {
   5687 			if (PrimaryFacing.Rotation_Adjust(Class->ROT)) {
   5688 				Mark(MARK_CHANGE);
   5689 			}
   5690 		}
   5691 	}
   5692 }
   5693 
   5694 
   5695 /***********************************************************************************************
   5696  * BuildingClass::Charging_AI -- Handles the special charging logic for Tesla coils.           *
   5697  *                                                                                             *
   5698  *    This handles the special logic required of the charging tesla coil. It requires special  *
   5699  *    processing since its charge up is dependant upon the target and power surplus of the     *
   5700  *    owning house.                                                                            *
   5701  *                                                                                             *
   5702  * INPUT:   none                                                                               *
   5703  *                                                                                             *
   5704  * OUTPUT:  none                                                                               *
   5705  *                                                                                             *
   5706  * WARNINGS:   none                                                                            *
   5707  *                                                                                             *
   5708  * HISTORY:                                                                                    *
   5709  *   07/29/1996 JLB : Created.                                                                 *
   5710  *=============================================================================================*/
   5711 void BuildingClass::Charging_AI(void)
   5712 {
   5713 	if (Class->PrimaryWeapon != NULL && Class->PrimaryWeapon->IsElectric && BState != BSTATE_CONSTRUCTION) {
   5714 		if (Target_Legal(TarCom) && House->Power_Fraction() >= 1) {
   5715 			if (!IsCharged) {
   5716 				if (IsCharging) {
   5717 //					if (stagechange) {
   5718 						Mark(MARK_CHANGE);
   5719 						if (Fetch_Stage() >= 9) {
   5720 							IsCharged = true;
   5721 							IsCharging = false;
   5722 							Set_Rate(0);
   5723 						}
   5724 //					}
   5725 				} else if (!Arm) {
   5726 					IsCharged = false;
   5727 					IsCharging = true;
   5728 					Set_Stage(0);
   5729 					Set_Rate(3);
   5730 					Sound_Effect(VOC_TESLA_POWER_UP, Coord);
   5731 				}
   5732 			}
   5733 		} else {
   5734 			if (IsCharging || IsCharged) {
   5735 				Mark(MARK_CHANGE);
   5736 				IsCharging = false;
   5737 				IsCharged = false;
   5738 				Set_Stage(0);
   5739 				Set_Rate(0);
   5740 			}
   5741 		}
   5742 	}
   5743 }
   5744 
   5745 
   5746 /***********************************************************************************************
   5747  * BuildingClass::Repair_AI -- Handle the repair (and sell) logic for the building.            *
   5748  *                                                                                             *
   5749  *    This routine handle the repair animation and healing logic. It also detects when the     *
   5750  *    (computer controlled) building should begin repair or sell itself.                       *
   5751  *                                                                                             *
   5752  * INPUT:   none                                                                               *
   5753  *                                                                                             *
   5754  * OUTPUT:  none                                                                               *
   5755  *                                                                                             *
   5756  * WARNINGS:   Only call this routine once per building per game logic loop.                   *
   5757  *                                                                                             *
   5758  * HISTORY:                                                                                    *
   5759  *   07/29/1996 JLB : Created.                                                                 *
   5760  *=============================================================================================*/
   5761 void BuildingClass::Repair_AI(void)
   5762 {
   5763 	if (House->IQ >= Rule.IQRepairSell && Mission != MISSION_CONSTRUCTION && Mission != MISSION_DECONSTRUCTION) {
   5764 		/*
   5765 		**	Possibly start repair process if the building is below half strength.
   5766 		*/
   5767 //		unsigned ratio = MIN(House->Smartness, 0x00F0);
   5768 		if (Can_Repair()) {
   5769 			if (House->Available_Money() >= Rule.RepairThreshhold) {
   5770 				if (!House->DidRepair) {
   5771 					if (!IsRepairing && (IsCaptured || IsToRepair || House->IsHuman || Session.Type != GAME_NORMAL)) {
   5772 						House->DidRepair = true;	// flag that this house did its repair allocation for this frame
   5773 						Repair(1);
   5774 
   5775 						if (!House->IsHuman) {
   5776 							House->RepairTimer = Random_Pick((int)(House->RepairDelay * (TICKS_PER_MINUTE/4)), (int)(House->RepairDelay * TICKS_PER_MINUTE * 2));
   5777 						}
   5778 					}
   5779 				}
   5780 			} else {
   5781 				if ((Session.Type != GAME_NORMAL || IsAllowedToSell) && IsTickedOff && House->Control.TechLevel >= Rule.IQSellBack && Random_Pick(0, 50) < House->Control.TechLevel && !Trigger.Is_Valid() && *this != STRUCT_CONST && Health_Ratio() < Rule.ConditionRed) {
   5782 					Sell_Back(1);
   5783 				}
   5784 			}
   5785 		}
   5786 	}
   5787 
   5788 	/*
   5789 	**	If it is repairing, then apply any repair effects as necessary.
   5790 	*/
   5791 	if (IsRepairing && (Frame % (Rule.RepairRate * TICKS_PER_MINUTE)) == 0) {
   5792 		IsWrenchVisible = (IsWrenchVisible == false);
   5793 		Mark(MARK_CHANGE);
   5794 		int cost = Class->Repair_Cost();
   5795 		int step = Class->Repair_Step();
   5796 
   5797 		/*
   5798 		**	Check for and expend any necessary monies to continue the repair.
   5799 		*/
   5800 		if (House->Available_Money() >= cost) {
   5801 			House->Spend_Money(cost);
   5802 			Strength += step;
   5803 
   5804 			if (Strength >= Class->MaxStrength) {
   5805 				Strength = Class->MaxStrength;
   5806 				IsRepairing = false;
   5807 			}
   5808 		} else {
   5809 			IsRepairing = false;
   5810 		}
   5811 	}
   5812 }
   5813 
   5814 
   5815 /***********************************************************************************************
   5816  * BuildingClass::Animation_AI -- Handles normal building animation processing.                *
   5817  *                                                                                             *
   5818  *    This will process the general building animation mechanism. It detects when the          *
   5819  *    building animation sequence has completed and flags the building to perform mission      *
   5820  *    changes as a result.                                                                     *
   5821  *                                                                                             *
   5822  * INPUT:   none                                                                               *
   5823  *                                                                                             *
   5824  * OUTPUT:  none                                                                               *
   5825  *                                                                                             *
   5826  * WARNINGS:   Call this routine only once per building per game logic loop.                   *
   5827  *                                                                                             *
   5828  * HISTORY:                                                                                    *
   5829  *   07/29/1996 JLB : Created.                                                                 *
   5830  *=============================================================================================*/
   5831 void BuildingClass::Animation_AI(void)
   5832 {
   5833 	bool stagechange = Graphic_Logic();
   5834 	bool toloop = false;
   5835 
   5836 	/*
   5837 	**	Always refresh the SAM site if it has an animation change.
   5838 	*/
   5839 	if (*this == STRUCT_SAM && stagechange) Mark(MARK_CHANGE);
   5840 
   5841 	if ((!Class->IsTurretEquipped && *this != STRUCT_TESLA) || Mission == MISSION_CONSTRUCTION || Mission == MISSION_DECONSTRUCTION) {
   5842 		if (stagechange) {
   5843 
   5844 			/*
   5845 			**	Check for animation end or if special case of MCV deconstructing when it is allowed
   5846 			**	to convert back into an MCV.
   5847 			*/
   5848 			BuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();
   5849 
   5850 			/*
   5851 			**	When the last frame of the current animation sequence is reached, flag that
   5852 			**	a new mission may be started. This must occur before the animation actually
   5853 			**	loops so that if a mission change does occur, it will have a chance to change
   5854 			**	the building graphic before the last frame is replaced by the first frame of
   5855 			**	the loop.
   5856 			*/
   5857 			if (Fetch_Stage() == ctrl->Start+ctrl->Count-1  || (!Target_Legal(ArchiveTarget) /*Is_MCV_Deploy()*/ && *this == STRUCT_CONST && Mission == MISSION_DECONSTRUCTION && Fetch_Stage() == (42-19))) {
   5858 				IsReadyToCommence = true;
   5859 			}
   5860 
   5861 			/*
   5862 			**	If the animation advances beyond the last frame, then start the animation
   5863 			**	sequence over from the beginning.
   5864 			*/
   5865 			if (Fetch_Stage() >= ctrl->Start+ctrl->Count) {
   5866 				toloop = true;
   5867 			}
   5868 			Mark(MARK_CHANGE);
   5869 		} else {
   5870 			if (BState == BSTATE_NONE || Fetch_Rate() == 0) {
   5871 				IsReadyToCommence = true;
   5872 			}
   5873 		}
   5874 	}
   5875 
   5876 	/*
   5877 	**	If there is a door that is animating, then it might cause this building
   5878 	**	to be redrawn. Check for and flag to redraw as necessary.
   5879 	*/
   5880 	if (Time_To_Redraw()) {
   5881 		Clear_Redraw_Flag();
   5882 		Mark(MARK_CHANGE);
   5883 	}
   5884 
   5885 	/*
   5886 	**	The animation sequence has looped. Restart it and flag this loop condition.
   5887 	**	This is used to tell the mission system that the animation has completed. It
   5888 	**	also signals that now is a good time to act on any pending mission.
   5889 	*/
   5890 	if (toloop) {
   5891 		BuildingTypeClass::AnimControlType const * ctrl = Fetch_Anim_Control();
   5892 		if (BState == BSTATE_CONSTRUCTION || BState == BSTATE_IDLE) {
   5893 			Set_Rate(Options.Normalize_Delay(ctrl->Rate));
   5894 		} else {
   5895 			Set_Rate(ctrl->Rate);
   5896 		}
   5897 		Set_Stage(ctrl->Start);
   5898 		Mark(MARK_CHANGE);
   5899 	}
   5900 }
   5901 
   5902 
   5903 /***********************************************************************************************
   5904  * BuildingClass::How_Many_Survivors -- This determine the maximum number of survivors.        *
   5905  *                                                                                             *
   5906  *    This routine is called to determine how many survivors should run from this building     *
   5907  *    when it is either sold or destroyed. Buildings that are captured have fewer survivors.   *
   5908  *    The number of survivors is a portion of the cost of the building divided by the cost     *
   5909  *    of a minigunner.                                                                         *
   5910  *                                                                                             *
   5911  * INPUT:   none                                                                               *
   5912  *                                                                                             *
   5913  * OUTPUT:  Returns with the number of soldiers that should run from this building.            *
   5914  *                                                                                             *
   5915  * WARNINGS:   none                                                                            *
   5916  *                                                                                             *
   5917  * HISTORY:                                                                                    *
   5918  *   08/04/1996 JLB : Created.                                                                 *
   5919  *=============================================================================================*/
   5920 int BuildingClass::How_Many_Survivors(void) const
   5921 {
   5922 	if (IsSurvivorless || !Class->IsCrew) return(0);
   5923 
   5924 	int divisor = InfantryTypeClass::As_Reference(INFANTRY_E1).Raw_Cost();
   5925 	if (divisor == 0) return(0);
   5926 	if (IsCaptured) divisor *= 2;
   5927 	int count = (Class->Raw_Cost() * Rule.SurvivorFraction) / divisor;
   5928 	return(Bound(count, 1, 5));
   5929 }
   5930 
   5931 
   5932 /***********************************************************************************************
   5933  * BuildingClass::Get_Image_Data -- Fetch the image pointer for the building.                  *
   5934  *                                                                                             *
   5935  *    This routine will return with a pointer to the shape data for the building. The shape    *
   5936  *    data is different than normal when the building is undergoing construction and           *
   5937  *    disassembly.                                                                             *
   5938  *                                                                                             *
   5939  * INPUT:   none                                                                               *
   5940  *                                                                                             *
   5941  * OUTPUT:  Returns with a pointer to the shape data for this building.                        *
   5942  *                                                                                             *
   5943  * WARNINGS:   none                                                                            *
   5944  *                                                                                             *
   5945  * HISTORY:                                                                                    *
   5946  *   08/06/1996 JLB : Created.                                                                 *
   5947  *=============================================================================================*/
   5948 void const * BuildingClass::Get_Image_Data(void) const
   5949 {
   5950 	if (BState == BSTATE_CONSTRUCTION) {
   5951 		return(Class->Get_Buildup_Data());
   5952 	}
   5953 	return(TechnoClass::Get_Image_Data());
   5954 }
   5955 
   5956 
   5957 /***********************************************************************************************
   5958  * BuildingClass::Value -- Determine the value of this building.                               *
   5959  *                                                                                             *
   5960  *    The value of the building is normally just its ordinary assigned value. However, in the  *
   5961  *    case of fakes, the value is artificially enhanced to match the structure that is         *
   5962  *    being faked.                                                                             *
   5963  *                                                                                             *
   5964  * INPUT:   none                                                                               *
   5965  *                                                                                             *
   5966  * OUTPUT:  Returns with the point value of the building type.                                 *
   5967  *                                                                                             *
   5968  * WARNINGS:   The point value returned should not be used for scoring, only for target        *
   5969  *             scanning.                                                                       *
   5970  *                                                                                             *
   5971  * HISTORY:                                                                                    *
   5972  *   09/16/1996 JLB : Created.                                                                 *
   5973  *=============================================================================================*/
   5974 int BuildingClass::Value(void) const
   5975 {
   5976 	if (Class->IsFake) {
   5977 		switch (Class->Type) {
   5978 			case STRUCT_FAKEWEAP:
   5979 				return(BuildingTypeClass::As_Reference(STRUCT_WEAP).Reward + BuildingTypeClass::As_Reference(STRUCT_WEAP).Risk);
   5980 
   5981 			case STRUCT_FAKECONST:
   5982 				return(BuildingTypeClass::As_Reference(STRUCT_CONST).Reward + BuildingTypeClass::As_Reference(STRUCT_CONST).Risk);
   5983 
   5984 			case STRUCT_FAKE_YARD:
   5985 				return(BuildingTypeClass::As_Reference(STRUCT_SHIP_YARD).Reward + BuildingTypeClass::As_Reference(STRUCT_SHIP_YARD).Risk);
   5986 
   5987 			case STRUCT_FAKE_PEN:
   5988 				return(BuildingTypeClass::As_Reference(STRUCT_SUB_PEN).Reward + BuildingTypeClass::As_Reference(STRUCT_SUB_PEN).Risk);
   5989 
   5990 			case STRUCT_FAKE_RADAR:
   5991 				return(BuildingTypeClass::As_Reference(STRUCT_RADAR).Reward + BuildingTypeClass::As_Reference(STRUCT_RADAR).Risk);
   5992 
   5993 			default:
   5994 				break;
   5995 		}
   5996 	}
   5997 	return(TechnoClass::Value());
   5998 }
   5999 
   6000 
   6001 /***********************************************************************************************
   6002  * BuildingClass::Remove_Gap_Effect -- Stop a gap generator from jamming cells.					  *
   6003  *                                                                                             *
   6004  * INPUT:   none                                                                               *
   6005  *                                                                                             *
   6006  * OUTPUT:  none																										  *
   6007  *                                                                                             *
   6008  * WARNINGS:   																										  *
   6009  *                                                                                             *
   6010  * HISTORY:                                                                                    *
   6011  *   09/20/1996 BWG : Created.                                                                 *
   6012  *=============================================================================================*/
   6013 void BuildingClass::Remove_Gap_Effect(void)
   6014 {
   6015 	// unjam this one's field...
   6016 	Map.UnJam_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, House);
   6017 	
   6018 	
   6019 	/*
   6020 	** Updated for client/server multiplayer. ST - 8/12/2019 11:14AM
   6021 	*/
   6022 	if (Session.Type != GAME_GLYPHX_MULTIPLAYER) {
   6023 		if (!House->IsPlayerControl && PlayerPtr->IsGPSActive) {
   6024 			Map.Sight_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, PlayerPtr);
   6025 		}
   6026 	
   6027 	} else {
   6028 		
   6029 		for (int i = 0; i < Session.Players.Count(); i++) {
   6030 			HouseClass *player_house = HouseClass::As_Pointer(Session.Players[i]->Player.ID);
   6031 			if (player_house->IsGPSActive && player_house != House) {
   6032 				Map.Sight_From(Coord_Cell(Center_Coord()), Rule.GapShroudRadius, player_house);
   6033 			}
   6034 		}
   6035 	}
   6036 
   6037 
   6038 	// and rejam any overlapping buildings' fields
   6039 	for (int index = 0; index < Buildings.Count(); index++) {
   6040 		BuildingClass *obj = Buildings.Ptr(index);
   6041 		if (obj && !obj->IsInLimbo && obj->House == House && *obj == STRUCT_GAP && obj!=this) {
   6042 			obj->IsJamming = false;
   6043 			obj->Arm = 0;
   6044 //			Map.Jam_From(Coord_Cell(obj->Center_Coord()), Rule.GapShroudRadius, PlayerPtr);
   6045 		}
   6046 	}
   6047 }
   6048 
   6049 
   6050 short const * BuildingClass::Overlap_List(bool redraw) const
   6051 {
   6052 	if ((Spied_By() & (1 << PlayerPtr->Class->House)) != 0 && Is_Selected_By_Player()) {
   6053 		if (*this == STRUCT_BARRACKS || *this == STRUCT_TENT) {
   6054 			static short const _list[] = {
   6055 				-1, 2, (MAP_CELL_W*1)-1, (MAP_CELL_W*1)+2, REFRESH_EOL
   6056 			};
   6057 			return(_list);
   6058 		} else if (*this == STRUCT_REFINERY) {
   6059 			static short const _list[] = {
   6060 				0, 2, (MAP_CELL_W*2)+0, (MAP_CELL_W*2)+1, (MAP_CELL_W*2)+2, REFRESH_EOL
   6061 			};
   6062 			return(_list);
   6063 		}
   6064 	}
   6065 	return(TechnoClass::Overlap_List(redraw));
   6066 }
   6067 
   6068 
   6069 unsigned BuildingClass::Spied_By() const
   6070 {
   6071 	unsigned spiedby = TechnoClass::Spied_By();
   6072 
   6073 	/*
   6074 	** If it's an ore refinery or other such storage-capable building,
   6075 	** loop thru all of their buildings to see if ANY of them are spied
   6076 	** upon, 'cause once you spy any money, you've spied all of it.
   6077 	*/
   6078 	if (Class->Capacity) {
   6079 		for (int index = 0; index < Buildings.Count(); index++) {
   6080 			BuildingClass * building = Buildings.Ptr(index);
   6081 			if (building->House == House && building->Class->Capacity) {
   6082 				spiedby |= building->SpiedBy;
   6083 			}
   6084 		}
   6085 	}
   6086 
   6087 	return spiedby;
   6088 }