CnC_Remastered_Collection

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

BUILDING.CPP (224993B)


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