CnC_Remastered_Collection

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

CELL.CPP (122294B)


      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\cell.cpv   2.18   16 Oct 1995 16:49:20   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 : CELL.CPP                                                     *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : April 29, 1994                                               *
     28  *                                                                                             *
     29  *                  Last Update : August 17, 1995 [JLB]                                        *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   CellClass::Adjacent_Cell -- Determines the adjacent cell according to facing.             *
     34  *   CellClass::Adjust_Threat -- Allows adjustment of threat at cell level                     *
     35  *   CellClass::CellClass -- Constructor for cell objects.                                     *
     36  *   CellClass::Cell_Building -- Return with building at specified cell.                       *
     37  *   CellClass::Cell_Color   -- Determine what radar color to use for this cell.               *
     38  *   CellClass::Cell_Coord -- Returns the coordinate of this cell.                             *
     39  *   CellClass::Cell_Find_Object -- Returns ptr to RTTI type occupying cell                    *
     40  *   CellClass::Cell_Infantry -- Returns with pointer of first infantry unit.                  *
     41  *   CellClass::Cell_Object -- Returns with clickable object in cell.                          *
     42  *   CellClass::Cell_Techno -- Return with the unit/building at specified cell.                *
     43  *   CellClass::Cell_Terrain -- Determines terrain object in cell.                             *
     44  *   CellClass::Cell_Unit -- Returns with pointer to unit occupying cell.                      *
     45  *   CellClass::Clear_Icon -- Calculates what the clear icon number should be.                 *
     46  *   CellClass::Closest_Free_Spot -- returns free spot closest to given coord                  *
     47  *   CellClass::Concrete_Calc -- Calculates the concrete icon to use for the cell.             *
     48  *   CellClass::Draw_It -- Draws the cell imagery at the location specified.                   *
     49  *   CellClass::Flag_Place -- Places a house flag down on the cell.                            *
     50  *   CellClass::Flag_Remove -- Removes the house flag from the cell.                           *
     51  *   CellClass::Cell_Occupier -- Fetches the occupier for the cell.                            *
     52  *   CellClass::Get_Trigger -- retrieves reference to the cell's trigger                       *
     53  *   CellClass::Goodie_Check -- Performs crate discovery logic.                                *
     54  *   CellClass::Incoming -- Causes objects in cell to "run for cover".                         *
     55  *   CellClass::Is_Generally_Clear -- Determines if cell can be built upon.                    *
     56  *   CellClass::Occupy_Down -- Flag occupation of specified cell.                              *
     57  *   CellClass::Occupy_Unit -- Marks cell as unit occupied.                                    *
     58  *   CellClass::Occupy_Up -- Removes occupation flag from the specified cell.                  *
     59  *   CellClass::Overlap_Down -- This routine is used to mark a cell as being spilled over (overla*
     60  *   CellClass::Overlap_Unit -- Marks cell as being overlapped by unit.                        *
     61  *   CellClass::Overlap_Up -- Removes overlap flag for the cell.                               *
     62  *   CellClass::Read -- Reads a particular cell value from a save game file.                   *
     63  *   CellClass::Recalc_Attributes -- Recalculates the ground type attributes for the cell.     *
     64  *   CellClass::Redraw_Objects -- Redraws all objects overlapping this cell.                   *
     65  *   CellClass::Reduce_Tiberium -- Reduces the tiberium in the cell by the amount specified.   *
     66  *   CellClass::Reduce_Wall -- Damages a wall, if damage is high enough.                       *
     67  *   CellClass::Reserve_Cell -- Marks a cell as being occupied by the specified unit ID.       *
     68  *   CellClass::Shimmer -- Causes all objects in the cell to shimmer.                          *
     69  *   CellClass::Spot_Index -- returns cell sub-coord index for given COORD                     *
     70  *   CellClass::Tiberium_Adjust -- Adjust the look of the Tiberium for smooth.                 *
     71  *   CellClass::Validate -- validates cell's number                                            *
     72  *   CellClass::Wall_Update -- Updates the imagery for wall objects in cell.                   *
     73  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     74 
     75 #include	"function.h"
     76 
     77 /*
     78 ** New sidebar for GlyphX multiplayer. ST - 3/26/2019 12:24PM
     79 */
     80 #include "SidebarGlyphx.h"
     81 
     82 #define	FIXUP		0
     83 
     84 
     85 /***********************************************************************************************
     86  * CellClass::Validate -- validates cell's number                                              *
     87  *                                                                                             *
     88  * INPUT:                                                                                      *
     89  *		none.																												  *
     90  *                                                                                             *
     91  * OUTPUT:                                                                                     *
     92  *		1 = ok, 0 = error																								  *
     93  *                                                                                             *
     94  * WARNINGS:                                                                                   *
     95  *		none.																												  *
     96  *                                                                                             *
     97  * HISTORY:                                                                                    *
     98  *   08/09/1995 BRR : Created.                                                                 *
     99  *=============================================================================================*/
    100 #ifdef CHEAT_KEYS
    101 int CellClass::Validate(void) const
    102 {
    103 	int num;
    104 
    105 	num = Cell_Number();
    106 	if (num < 0 || num > 4095) {
    107 		Validate_Error("CELL");
    108 		return (0);
    109 	}
    110 	else
    111 		return (1);
    112 }
    113 #else
    114 #define	Validate()
    115 #endif
    116 
    117 
    118 /***********************************************************************************************
    119  * CellClass::CellClass -- Constructor for cell objects.                                       *
    120  *                                                                                             *
    121  *    A cell object is constructed into an empty state. It contains no specific objects,       *
    122  *    templates, or overlays.                                                                  *
    123  *                                                                                             *
    124  * INPUT:   none                                                                               *
    125  *                                                                                             *
    126  * OUTPUT:  none                                                                               *
    127  *                                                                                             *
    128  * WARNINGS:   none                                                                            *
    129  *                                                                                             *
    130  * HISTORY:                                                                                    *
    131  *   08/09/1994 JLB : Created.                                                                 *
    132  *=============================================================================================*/
    133 CellClass::CellClass(void)
    134 {
    135 	memset(this, 0, sizeof(CellClass));
    136 	Overlay = OVERLAY_NONE;
    137 	Smudge = SMUDGE_NONE;
    138 	TType = TEMPLATE_NONE;
    139 	Owner = HOUSE_NONE;
    140 	InfType = HOUSE_NONE;
    141 	OverrideLand = LAND_COUNT;
    142 }
    143 
    144 
    145 /***********************************************************************************************
    146  * CellClass::Cell_Color   -- Determine what radar color to use for this cell.                 *
    147  *                                                                                             *
    148  *    Use this routine to determine what radar color to render a radar                         *
    149  *    pixel with. This routine is called many many times to render the                         *
    150  *    radar map, so it must be fast.                                                           *
    151  *                                                                                             *
    152  * INPUT:   none                                                                               *
    153  *                                                                                             *
    154  * OUTPUT:  Returns with the color to display the radar pixel with.                            *
    155  *                                                                                             *
    156  * WARNINGS:   none                                                                            *
    157  *                                                                                             *
    158  * HISTORY:                                                                                    *
    159  *   03/01/1994 JLB : Created.                                                                 *
    160  *   04/30/1994 JLB : Converted to member function.                                            *
    161  *   05/31/1994 JLB : Takes into account any stealth characteristics of object.                *
    162  *=============================================================================================*/
    163 int CellClass::Cell_Color(bool override) const
    164 {
    165 	Validate();
    166 	BuildingClass * object = Cell_Building();
    167 	if (object) {
    168 		return(object->House->Class->Color);
    169 	}
    170 
    171 	if (override) {
    172 		return(TBLACK);
    173 	}
    174 	return(::Ground[Land_Type()].Color);
    175 }
    176 
    177 
    178 /***********************************************************************************************
    179  * CellClass::Cell_Techno -- Return with the unit/building at specified cell.                  *
    180  *                                                                                             *
    181  *    Returns an object located in the cell. If there is a                                     *
    182  *    building present, it returns a pointer to that, otherwise it returns                     *
    183  *    a pointer to one of the units there. If nothing is present in the                        *
    184  *    specified cell, then it returns NULL.                                                    *
    185  *                                                                                             *
    186  * INPUT:   x,y   -- Coordinate offset (from upper left corner) to use as an aid in selecting  *
    187  *                   the desired object within the cell.                                       *
    188  *                                                                                             *
    189  * OUTPUT:  Returns a pointer to a building or unit located in cell. If                        *
    190  *          nothing present, just returns NULL.                                                *
    191  *                                                                                             *
    192  * WARNINGS:   none                                                                            *
    193  *                                                                                             *
    194  * HISTORY:                                                                                    *
    195  *   08/05/1992 JLB : Created.                                                                 *
    196  *   04/30/1994 JLB : Converted to member function.                                            *
    197  *=============================================================================================*/
    198 TechnoClass * CellClass::Cell_Techno(int x, int y) const
    199 {
    200 	Validate();
    201 	ObjectClass * object;
    202 	COORDINATE		click;			// Coordinate of click relative to cell corner.
    203 	TechnoClass * close = NULL;
    204 	long		distance = 0;	// Recorded closest distance.
    205 
    206 	/*
    207 	**	Create a coordinate value that represent the pixel location within the cell. This is
    208 	**	actually the lower significant bits (leptons) of a regular coordinate value.
    209 	*/
    210 	click = XY_Coord(Pixel_To_Lepton(x), Pixel_To_Lepton(y));
    211 
    212 	if (Cell_Occupier()) {
    213 		object = Cell_Occupier();
    214 		while (object && object->IsActive) {
    215 			if (object->Is_Techno()) {
    216 				COORDINATE		coord;		// Coordinate relative to cell corner.
    217 				long		dist;
    218 
    219 				coord = object->Center_Coord() & 0x00FF00FFL;
    220 				dist = Distance(coord, click);
    221 				if (!close || dist < distance) {
    222 					close = (TechnoClass *)object;
    223 					distance = dist;
    224 				}
    225 			}
    226 			object = object->Next;
    227 		}
    228 	}
    229 	return(close);
    230 }
    231 
    232 
    233 /***************************************************************************
    234  * CellClass::Cell_Find_Object -- Returns ptr to RTTI type occupying cell  *
    235  *                                                                         *
    236  * INPUT:		RTTIType the RTTI type we are searching for                 *
    237  *                                                                         *
    238  * OUTPUT:		none                                                        *
    239  *                                                                         *
    240  * WARNINGS:   none                                                        *
    241  *                                                                         *
    242  * HISTORY:                                                                *
    243  *   03/17/1995 PWG : Created.                                             *
    244  *   06/12/1995 JLB : Returns object class pointer.                        *
    245  *=========================================================================*/
    246 ObjectClass * CellClass::Cell_Find_Object(RTTIType rtti) const
    247 {
    248 	Validate();
    249 	ObjectClass * object = Cell_Occupier();
    250 
    251 	while (object && object->IsActive) {
    252 		if (object->What_Am_I() == rtti) {
    253 			return(object);
    254 		}
    255 		object = object->Next;
    256 	}
    257 	return(NULL);
    258 }
    259 
    260 
    261 /***********************************************************************************************
    262  * CellClass::Cell_Building -- Return with building at specified cell.                         *
    263  *                                                                                             *
    264  *    Given a cell, determine if there is a building associated                                *
    265  *    and return with a pointer to this building.                                              *
    266  *                                                                                             *
    267  * INPUT:   none                                                                               *
    268  *                                                                                             *
    269  * OUTPUT:  Returns with a pointer to the building associated with the                         *
    270  *          cell. If there is no building associated, then NULL is                             *
    271  *          returned.                                                                          *
    272  *                                                                                             *
    273  * WARNINGS:   none                                                                            *
    274  *                                                                                             *
    275  * HISTORY:                                                                                    *
    276  *   08/05/1992 JLB : Created.                                                                 *
    277  *   04/30/1994 JLB : Converted to member function.                                            *
    278  *=============================================================================================*/
    279 BuildingClass * CellClass::Cell_Building(void) const
    280 {
    281 	Validate();
    282 	return((BuildingClass *)Cell_Find_Object(RTTI_BUILDING));
    283 }
    284 
    285 
    286 /***********************************************************************************************
    287  * CellClass::Cell_Terrain -- Determines terrain object in cell.                               *
    288  *                                                                                             *
    289  *    This routine is used to determine the terrain object (if any) that                       *
    290  *    overlaps this cell.                                                                      *
    291  *                                                                                             *
    292  * INPUT:   none                                                                               *
    293  *                                                                                             *
    294  * OUTPUT:  Returns with a pointer to the terrain object that overlaps                         *
    295  *          this cell. If there is no terrain object present, then NULL                        *
    296  *          is returned.                                                                       *
    297  *                                                                                             *
    298  * WARNINGS:   none                                                                            *
    299  *                                                                                             *
    300  * HISTORY:                                                                                    *
    301  *   05/18/1994 JLB : Created.                                                                 *
    302  *=============================================================================================*/
    303 TerrainClass * CellClass::Cell_Terrain(void) const
    304 {
    305 	Validate();
    306 	return((TerrainClass *)Cell_Find_Object(RTTI_TERRAIN));
    307 }
    308 
    309 
    310 /***********************************************************************************************
    311  * CellClass::Cell_Object -- Returns with clickable object in cell.                            *
    312  *                                                                                             *
    313  *    This routine is used to determine which object is to be selected                         *
    314  *    by a player click upon the cell. Not all objects that overlap the                        *
    315  *    cell are selectable by the player. This routine sorts out which                          *
    316  *    is which and returns with the appropriate object pointer.                                *
    317  *                                                                                             *
    318  * INPUT:   x,y   -- Coordinate (from upper left corner of cell) to use as a guide when        *
    319  *                   selecting the object within the cell. This plays a role in those cases    *
    320  *                   where several objects (such as infantry) exist within the same cell.      *
    321  *                                                                                             *
    322  * OUTPUT:  Returns with pointer to the object clickable within the                            *
    323  *          cell. NULL is returned if there is no clickable object                             *
    324  *          present.                                                                           *
    325  *                                                                                             *
    326  * WARNINGS:   none                                                                            *
    327  *                                                                                             *
    328  * HISTORY:                                                                                    *
    329  *   05/13/1994 JLB : Created.                                                                 *
    330  *=============================================================================================*/
    331 ObjectClass * CellClass::Cell_Object(int x, int y) const
    332 {
    333 	Validate();
    334 	ObjectClass * ptr;
    335 
    336 	/*
    337 	**	Hack so that aircraft landed on helipads can still be selected if directly
    338 	**	clicked on.
    339 	*/
    340 	ptr = (ObjectClass *)Cell_Find_Object(RTTI_AIRCRAFT);
    341 	if (ptr) {
    342 		return(ptr);
    343 	}
    344 
    345 	ptr = Cell_Techno(x, y);
    346 	if (ptr) {
    347 		return(ptr);
    348 	}
    349 	ptr = Cell_Terrain();
    350 	if (ptr) return(ptr);
    351 	return(ptr);
    352 }
    353 
    354 
    355 /***********************************************************************************************
    356  * CellClass::Redraw_Objects -- Redraws all objects overlapping this cell.                     *
    357  *                                                                                             *
    358  *    This is a low level routine that marks all objects that overlap this                     *
    359  *    cell to be redrawn. It is necessary to call this routine whenever                        *
    360  *    the underlying icon has to be redrawn.                                                   *
    361  *                                                                                             *
    362  * INPUT:   forced   -- Should this redraw be forced even if flags                             *
    363  *                      indicate that it would be redundant?                                   *
    364  *                                                                                             *
    365  * OUTPUT:  none                                                                               *
    366  *                                                                                             *
    367  * WARNINGS:   none                                                                            *
    368  *                                                                                             *
    369  * HISTORY:                                                                                    *
    370  *   05/18/1994 JLB : Created.                                                                 *
    371  *   06/20/1994 JLB : Simplified to use object pointers.                                       *
    372  *   12/24/1994 JLB : Only checks if cell is in view and not flagged already.                  *
    373  *=============================================================================================*/
    374 void CellClass::Redraw_Objects(bool forced)
    375 {
    376 	Validate();
    377 	CELL	cell = Cell_Number();
    378 
    379 	if (Map.In_View(cell) && (forced || !Map.Is_Cell_Flagged(cell))) {
    380 
    381 		/*
    382 		**	Flag the icon to be redrawn.
    383 		*/
    384 		Map.Flag_Cell(cell);
    385 
    386 		/*
    387 		**	Flag the main object in the cell to be redrawn.
    388 		*/
    389 		if (Cell_Occupier()) {
    390 			ObjectClass * optr = Cell_Occupier();
    391 			while (optr) {
    392 				if (optr->IsActive) {
    393 					optr->Mark(MARK_CHANGE);
    394 				}
    395 				optr = optr->Next;
    396 			}
    397 		}
    398 
    399 		/*
    400 		**	Flag any overlapping object in this cell to be redrawn.
    401 		*/
    402 		for (int index = 0; index < sizeof(Overlapper)/sizeof(Overlapper[0]); index++) {
    403 			if (Overlapper[index]) {
    404 				if (!Overlapper[index]->IsActive) {
    405 					Overlapper[index] = 0;
    406 				} else {
    407 					Overlapper[index]->Mark(MARK_CHANGE);
    408 				}
    409 			}
    410 		}
    411 	}
    412 }
    413 
    414 
    415 /***********************************************************************************************
    416  * CellClass::Is_Generally_Clear -- Determines if cell can be built upon.                      *
    417  *                                                                                             *
    418  *    This determines if the cell can become a proper foundation for                           *
    419  *    building placement.                                                                      *
    420  *                                                                                             *
    421  * INPUT:   none                                                                               *
    422  *                                                                                             *
    423  * OUTPUT:  bool; Can the cell be built upon?                                                  *
    424  *                                                                                             *
    425  * WARNINGS:   none                                                                            *
    426  *                                                                                             *
    427  * HISTORY:                                                                                    *
    428  *   05/18/1994 JLB : Created.                                                                 *
    429  *=============================================================================================*/
    430 bool CellClass::Is_Generally_Clear(bool ignore_cloaked) const
    431 {
    432 	Validate();
    433 	if (ScenarioInit) return(true);
    434 	if (Flag.Composite || IsFlagged || Cell_Occupier()) {
    435 		if (!ignore_cloaked || (Cell_Occupier() && Cell_Occupier()->Is_Techno() && ((TechnoClass *)Cell_Occupier())->Cloak != CLOAKED)) {
    436 			return(false);
    437 		}
    438 	}
    439 	if (Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference(Smudge).IsBib && Owner != HOUSE_NONE) {
    440 		return(false);
    441 	}
    442 	if (Overlay != OVERLAY_NONE && (Overlay == OVERLAY_FLAG_SPOT || OverlayTypeClass::As_Reference(Overlay).IsWall)) {
    443 		return(false);
    444 	}
    445 
    446 #ifdef ADVANCED
    447 	/*
    448 	**	Building certain kinds of terrain is prohibited -- bridges in particular.
    449 	*/
    450 	switch (TType) {
    451 		case TEMPLATE_BRIDGE1:
    452 		case TEMPLATE_BRIDGE1D:
    453 		case TEMPLATE_BRIDGE2:
    454 		case TEMPLATE_BRIDGE2D:
    455 		case TEMPLATE_BRIDGE3:
    456 		case TEMPLATE_BRIDGE3D:
    457 		case TEMPLATE_BRIDGE4:
    458 		case TEMPLATE_BRIDGE4D:
    459 		case TEMPLATE_FORD1:
    460 		case TEMPLATE_FORD2:
    461 			return(false);
    462 
    463 		default:
    464 			break;
    465 	}
    466 #endif
    467 
    468 	return(::Ground[Land_Type()].Build);
    469 }
    470 
    471 
    472 /***********************************************************************************************
    473  * CellClass::Recalc_Attributes -- Recalculates the ground type attributes for the cell.       *
    474  *                                                                                             *
    475  *    This routine recalculates the ground type in the cell. The speeds the find path          *
    476  *    algorithm and other determinations of the cell type.                                     *
    477  *                                                                                             *
    478  * INPUT:   none                                                                               *
    479  *                                                                                             *
    480  * OUTPUT:  none                                                                               *
    481  *                                                                                             *
    482  * WARNINGS:   none                                                                            *
    483  *                                                                                             *
    484  * HISTORY:                                                                                    *
    485  *   05/29/1994 JLB : Created.                                                                 *
    486  *   06/20/1994 JLB : Knows about template pointer in cell object.                             *
    487  *=============================================================================================*/
    488 void CellClass::Recalc_Attributes(void)
    489 {
    490 	Validate();
    491 	/*
    492 	**	Check for wall effects.
    493 	*/
    494 	if (Overlay != OVERLAY_NONE) {
    495 		Land = OverlayTypeClass::As_Reference(Overlay).Land;
    496 		if (Land != LAND_CLEAR) return;
    497 	}
    498 
    499 	/*
    500 	**	If there is a template associated with this cell, then scan
    501 	**	through the template exception list checking to see if this cell
    502 	**	is one of the exception types. If it is, then return that ground type,
    503 	**	otherwise return the template's default type.
    504 	*/
    505 	if (TType != TEMPLATE_NONE) {
    506 		TemplateTypeClass const *ttype = &TemplateTypeClass::As_Reference(TType);
    507 
    508 		/*
    509 		**	If there is an exception type list for the icons of this template, then
    510 		**	find out if the current icon is one of them. If so, apply the exception
    511 		**	ground type to the cell.
    512 		*/
    513 		char const *ptr = ttype->AltIcons;
    514 		if (ptr) {
    515 			int icon = TIcon;
    516 
    517 			while (*ptr != -1) {
    518 				if (icon == *ptr++) {
    519 					Land = ttype->AltLand;
    520 					return;
    521 				}
    522 			}
    523 		}
    524 
    525 		/*
    526 		**	No exception found, so just return the default ground type for this template.
    527 		*/
    528 		Land = ttype->Land;
    529 		return;
    530 	}
    531 
    532 	/*
    533 	**	No template is the same as clear terrain.
    534 	*/
    535 	Land = TemplateTypeClass::As_Reference(TEMPLATE_CLEAR1).Land;
    536 }
    537 
    538 
    539 /***********************************************************************************************
    540  * CellClass::Occupy_Down -- Flag occupation of specified cell.                                *
    541  *                                                                                             *
    542  *    This routine is used to mark the cell as being occupied by the specified object.         *
    543  *                                                                                             *
    544  * INPUT:   object   -- The object that is to occupy the cell                                  *
    545  *                                                                                             *
    546  * OUTPUT:  none                                                                               *
    547  *                                                                                             *
    548  * WARNINGS:   none                                                                            *
    549  *                                                                                             *
    550  * HISTORY:                                                                                    *
    551  *   07/18/1994 JLB : Created.                                                                 *
    552  *   11/29/1994 JLB : Simplified.                                                              *
    553  *=============================================================================================*/
    554 void CellClass::Occupy_Down(ObjectClass * object)
    555 {
    556 	Validate();
    557 	ObjectClass * optr;
    558 
    559 	/*
    560 	**	If the specified object is already part of the occupation list, then don't add
    561 	**	it again -- bail instead.
    562 	*/
    563 	if (Cell_Occupier()) {
    564 		optr = Cell_Occupier();
    565 		while (optr) {
    566 			if (optr == object) {
    567 				return;
    568 			}
    569 			if (!optr->Next) break;
    570 			optr = optr->Next;
    571 		}
    572 	}
    573 	optr = Cell_Occupier();
    574 	object->Next = optr;
    575 
    576 	OccupierPtr = object;
    577 	Map.Radar_Pixel(Cell_Number());
    578 
    579 	/*
    580 	**	If being placed down on a visible square, then flag this
    581 	**	techno object as being revealed to the player.
    582 	*/
    583 	// Changes for GlyphX multiplayer. ST - 4/17/2019 3:02PM
    584 	//if (IsVisible || GameToPlay != GAME_NORMAL) {
    585 	//	object->Revealed(PlayerPtr);
    586 	//}
    587 	if (GameToPlay != GAME_GLYPHX_MULTIPLAYER) {
    588 		if (IsVisible || GameToPlay != GAME_NORMAL) {
    589 			object->Revealed(PlayerPtr);
    590 		}
    591 	} else {
    592 		
    593 		for (int i = 0; i < MPlayerCount; i++) {
    594 			HousesType house_type = MPlayerHouses[i];
    595 			if (Is_Visible(house_type)) {
    596 				HouseClass *house = HouseClass::As_Pointer(house_type);
    597 				object->Revealed(house);
    598 			}
    599 		}
    600 	}	
    601 
    602 	/*
    603 	**	Special occupy bit set.
    604 	*/
    605 	switch (object->What_Am_I()) {
    606 		case RTTI_BUILDING:
    607 			Flag.Occupy.Building = true;
    608 			break;
    609 
    610 		case RTTI_AIRCRAFT:
    611 		case RTTI_UNIT:
    612 			Flag.Occupy.Vehicle = true;
    613 			break;
    614 
    615 		case RTTI_TERRAIN:
    616 			Flag.Occupy.Monolith = true;
    617 			break;
    618 
    619 		default:
    620 			break;
    621 	}
    622 }
    623 
    624 
    625 /***********************************************************************************************
    626  * CellClass::Occupy_Up -- Removes occupation flag from the specified cell.                    *
    627  *                                                                                             *
    628  *    This routine will lift the object from the cell and free the cell to be occupied by      *
    629  *    another object. Only if the cell was previously marked with the object specified, will   *
    630  *    the object be lifted off. This routine is the counterpart to Occupy_Down().              *
    631  *                                                                                             *
    632  * INPUT:   object   -- The object that is being lifted off.                                   *
    633  *                                                                                             *
    634  * OUTPUT:  none                                                                               *
    635  *                                                                                             *
    636  * WARNINGS:   none                                                                            *
    637  *                                                                                             *
    638  * HISTORY:                                                                                    *
    639  *   07/18/1994 JLB : Created.                                                                 *
    640  *   11/29/1994 JLB : Fixed to handle next pointer in previous object.                         *
    641  *=============================================================================================*/
    642 void CellClass::Occupy_Up(ObjectClass * object)
    643 {
    644 	Validate();
    645 	ObjectClass * optr = NULL;			// Working pointer to the objects in the chain.
    646 
    647 	if (Cell_Occupier()) {
    648 		optr = Cell_Occupier();
    649 	}
    650 	if (optr == object) {
    651 		OccupierPtr = object->Next;
    652 		object->Next = 0;
    653 	} else {
    654 		while (optr) {
    655 			if (optr->Next == object) {
    656 				optr->Next = object->Next;
    657 				object->Next = 0;
    658 				break;
    659 			}
    660 			if (!optr->Next) break;
    661 			optr = optr->Next;
    662 		}
    663 	}
    664 	Map.Radar_Pixel(Cell_Number());
    665 
    666 	/*
    667 	**	Special occupy bit clear.
    668 	*/
    669 	switch (object->What_Am_I()) {
    670 		case RTTI_BUILDING:
    671 			Flag.Occupy.Building = false;
    672 			break;
    673 
    674 		case RTTI_AIRCRAFT:
    675 		case RTTI_UNIT:
    676 			Flag.Occupy.Vehicle = false;
    677 #ifdef NEVER
    678 			int x,y;
    679 			if (Map.Coord_To_Pixel(Cell_Coord(), x, y)) {
    680 		 		SeenBuff.Put_Pixel(x, y, BLUE);
    681 			}
    682 #endif
    683 			break;
    684 
    685 		case RTTI_TERRAIN:
    686 			Flag.Occupy.Monolith = false;
    687 			break;
    688 
    689 		default:
    690 			break;
    691 	}
    692 }
    693 
    694 
    695 /***********************************************************************************************
    696  * CellClass::Overlap_Down -- This routine is used to mark a cell as being spilled over (overla*
    697  *                                                                                             *
    698  *    Most game objects can often have their graphic imagery spill into more than one cell     *
    699  *    even though they are considered to "occupy" only one cell. All cells overlapped are      *
    700  *    flagged by this routine. Using this information it is possible to keep the tactical map  *
    701  *    display correct.                                                                         *
    702  *                                                                                             *
    703  * INPUT:   object   -- The object to mark as overlapping this cell.                           *
    704  *                                                                                             *
    705  * OUTPUT:  none                                                                               *
    706  *                                                                                             *
    707  * WARNINGS:   none                                                                            *
    708  *                                                                                             *
    709  * HISTORY:                                                                                    *
    710  *   07/18/1994 JLB : Created.                                                                 *
    711  *   07/04/1995 JLB : Ensures that buildings are always marked down.                           *
    712  *=============================================================================================*/
    713 void CellClass::Overlap_Down(ObjectClass * object)
    714 {
    715 	Validate();
    716 	ObjectClass **ptr = 0;
    717 
    718 	if (!object) return;
    719 	int index;
    720 	for (index = 0; index < sizeof(Overlapper)/sizeof(Overlapper[0]); index++) {
    721 		if (Overlapper[index] == object) return;
    722 		if (!Overlapper[index]) ptr = &Overlapper[index];
    723 	}
    724 
    725 	/*
    726 	**	Buildings must ALWAYS succeed in marking the cell as overlapped. Bump somebody
    727 	**	else out in this case.
    728 	*/
    729 	if (!ptr && object->What_Am_I() == RTTI_BUILDING) {
    730 		for (index = 0; index < sizeof(Overlapper)/sizeof(Overlapper[0]); index++) {
    731 			switch (Overlapper[index]->What_Am_I()) {
    732 				case RTTI_BUILDING:
    733 				case RTTI_TERRAIN:
    734 					break;
    735 
    736 				default:
    737 					Overlapper[index] = object;
    738 					index = sizeof(Overlapper)/sizeof(Overlapper[0]);
    739 					break;
    740 			}
    741 		}
    742 	}
    743 	if (ptr) *ptr = object;
    744 
    745 	/*
    746 	**	If being placed down on a visible square, then flag this
    747 	**	techno object as being revealed to the player.
    748 	*/
    749 	// Changes for GlyphX multiplayer. ST - 4/18/2019 9:50AM
    750 	//if (IsVisible) {
    751 	//	object->Revealed(PlayerPtr);
    752 	//}
    753 	if (GameToPlay != GAME_GLYPHX_MULTIPLAYER) {
    754 		if (IsVisible) {
    755 			object->Revealed(PlayerPtr);
    756 		}
    757 	} else {
    758 		
    759 		if (object->Is_Techno()) {
    760 			TechnoClass *tech = static_cast<TechnoClass*>(object);
    761 			object->Revealed(tech->House);
    762 		} else {
    763 		
    764 			for (int i = 0; i < MPlayerCount; i++) {
    765 				HousesType house_type = MPlayerHouses[i];
    766 				HouseClass *house = HouseClass::As_Pointer(house_type);
    767 				object->Revealed(house);
    768 			}
    769 		}	
    770 	}	
    771 }
    772 
    773 
    774 /***********************************************************************************************
    775  * CellClass::Overlap_Up -- Removes overlap flag for the cell.                                 *
    776  *                                                                                             *
    777  *    This is the counterpart to Overlap_Down and is used to remove the overlap flag for the   *
    778  *    specified unit on the cell.                                                              *
    779  *                                                                                             *
    780  * INPUT:   object   -- The object to remove the overlap flag for.                             *
    781  *                                                                                             *
    782  * OUTPUT:  none                                                                               *
    783  *                                                                                             *
    784  * WARNINGS:   none                                                                            *
    785  *                                                                                             *
    786  * HISTORY:                                                                                    *
    787  *   07/18/1994 JLB : Created.                                                                 *
    788  *=============================================================================================*/
    789 void CellClass::Overlap_Up(ObjectClass *object)
    790 {
    791 	Validate();
    792 	for (int index = 0; index < sizeof(Overlapper)/sizeof(Overlapper[0]); index++) {
    793 		if (Overlapper[index] == object) {
    794 			Overlapper[index] = 0;
    795 			break;
    796 		}
    797 	}
    798 
    799 	//Map.Validate();
    800 }
    801 
    802 
    803 /***********************************************************************************************
    804  * CellClass::Cell_Unit -- Returns with pointer to unit occupying cell.                        *
    805  *                                                                                             *
    806  *    This routine will determine if a unit is occupying the cell and if so, return a pointer  *
    807  *    to it. If there is no unit occupying the cell, then NULL is returned.                    *
    808  *                                                                                             *
    809  * INPUT:   none                                                                               *
    810  *                                                                                             *
    811  * OUTPUT:  Returns with pointer to unit occupying cell, else NULL.                            *
    812  *                                                                                             *
    813  * WARNINGS:   none                                                                            *
    814  *                                                                                             *
    815  * HISTORY:                                                                                    *
    816  *   07/18/1994 JLB : Created.                                                                 *
    817  *=============================================================================================*/
    818 UnitClass * CellClass::Cell_Unit(void) const
    819 {
    820 	Validate();
    821 	return((UnitClass*)Cell_Find_Object(RTTI_UNIT));
    822 }
    823 
    824 
    825 /***********************************************************************************************
    826  * CellClass::Cell_Infantry -- Returns with pointer of first infantry unit occupying the cell. *
    827  *                                                                                             *
    828  *    This routine examines the cell and returns a pointer to the first infantry unit          *
    829  *    that occupies it. If there is no infantry unit in the cell, then NULL is returned.       *
    830  *                                                                                             *
    831  * INPUT:   none                                                                               *
    832  *                                                                                             *
    833  * OUTPUT:  Returns with pointer to infantry unit occupying the cell or NULL if none are       *
    834  *          present.                                                                           *
    835  *                                                                                             *
    836  * WARNINGS:   none                                                                            *
    837  *                                                                                             *
    838  * HISTORY:                                                                                    *
    839  *   12/21/1994 JLB : Created.                                                                 *
    840  *=============================================================================================*/
    841 InfantryClass * CellClass::Cell_Infantry(void) const
    842 {
    843 	Validate();
    844 	return((InfantryClass*)Cell_Find_Object(RTTI_INFANTRY));
    845 }
    846 
    847 
    848 
    849 /***********************************************************************************************
    850  * CellClass::Get_Template_Info -- Get some info about a template for external use             *
    851  *                                                                                             *
    852  *                                                                                             *
    853  *                                                                                             *
    854  *                                                                                             *
    855  * INPUT:   Ref to info required                                                               *
    856  *                                                                                             *
    857  * OUTPUT:  True if image info available                                                       *
    858  *                                                                                             *
    859  *                                                                                             *
    860  * WARNINGS:   none                                                                            *
    861  *                                                                                             *
    862  * HISTORY:                                                                                    *
    863  *   1/10/2019 5:57PM ST : Created.                                                            *
    864  *=============================================================================================*/
    865 bool CellClass::Get_Template_Info(char *template_name, int &icon, void *&image_data)
    866 {
    867 	TemplateTypeClass const *ttype = NULL;
    868 	
    869 	if (TType != TEMPLATE_NONE) {
    870 		ttype = &TemplateTypeClass::As_Reference(TType);
    871 		icon = TIcon;
    872 	} else {
    873 		ttype = &TemplateTypeClass::As_Reference(TEMPLATE_CLEAR1);
    874 		icon = Clear_Icon();
    875 	}
    876 			  
    877 	if (ttype) {
    878 
    879 		strcpy(template_name, ttype->IniName);
    880 		image_data = (void*) ttype->ImageData;
    881 
    882 		return true;
    883 	}
    884 
    885 	return false;
    886 }
    887 
    888 
    889 
    890 
    891 /***********************************************************************************************
    892  * CellClass::Draw_It -- Draws the cell imagery at the location specified.                     *
    893  *                                                                                             *
    894  *    This is the gruntwork cell rendering code. It draws the cell at the screen location      *
    895  *    specified. This routine doesn't draw any overlapping or occupying units. It only         *
    896  *    deals with the ground (cell) layer -- icon level.                                        *
    897  *                                                                                             *
    898  * INPUT:   x,y   -- The screen coordinates to render the cell imagery at.                     *
    899  *                                                                                             *
    900  * OUTPUT:  none                                                                               *
    901  *                                                                                             *
    902  * WARNINGS:   none                                                                            *
    903  *                                                                                             *
    904  * HISTORY:                                                                                    *
    905  *   07/18/1994 JLB : Created.                                                                 *
    906  *   08/21/1994 JLB : Revised for simple template objects.                                     *
    907  *   11/01/1994 BRR : Updated placement cursor; draws actual object                            *
    908  *   11/14/1994 BRR : Added remapping code to show passable areas                              *
    909  *   12/02/1994 BRR : Added trigger display                                                    *
    910  *   12/11/1994 JLB : Mixes up clear terrain through pseudo-random table.                      *
    911  *   04/25/1995 JLB : Smudges drawn BELOW overlays.                                            *
    912  *=============================================================================================*/
    913 void CellClass::Draw_It(int x, int y, int draw_type) const
    914 {
    915 	Validate();
    916 	TemplateTypeClass const *ttype = 0;
    917 	int	icon;		// The icon number to use from the template set.
    918 	CELL	cell = Cell_Number();
    919 	void * remap = NULL;
    920 #ifdef SCENARIO_EDITOR
    921 	TemplateTypeClass * tptr;
    922 	TriggerClass * trig;
    923 	int i;
    924 	char waypt[2];
    925 #endif
    926 
    927 	/*
    928 	**	Fetch a pointer to the template type associated with this cell.
    929 	*/
    930 	if (TType != TEMPLATE_NONE) {
    931 		ttype = &TemplateTypeClass::As_Reference(TType);
    932 		icon = TIcon;
    933 	} else {
    934 		ttype = &TemplateTypeClass::As_Reference(TEMPLATE_CLEAR1);
    935 		icon = Clear_Icon();
    936 	}
    937 
    938 
    939 	/*
    940 	**	Draw the stamp of the template.
    941 	*/
    942 	if (Debug_Icon) {
    943 		LogicPage->Fill_Rect(Map.TacPixelX+x, Map.TacPixelY+y, Map.TacPixelX+x+ICON_PIXEL_W-1, Map.TacPixelY+y+ICON_PIXEL_H-1, Sim_Random_Pick(1, 254));
    944 		FontXSpacing -= 2;
    945 		Fancy_Text_Print("%d\r%2X%c\r%02X.%02X", Map.TacPixelX+x+(ICON_PIXEL_W>>1), Map.TacPixelY+y, WHITE, TBLACK, TPF_6POINT|TPF_NOSHADOW|TPF_CENTER, cell, Flag.Composite, (Cell_Occupier() ? '*' : ' '), Overlay, OverlayData);
    946 		FontXSpacing += 2;
    947 	} else {
    948 
    949 
    950 		if (!draw_type || draw_type == CELL_BLIT_ONLY){
    951 
    952 
    953 #ifdef SCENARIO_EDITOR
    954 			/*
    955 			**	Set up the remap table for this icon.
    956 			*/
    957 			if (Debug_Map && Debug_Passable) {
    958 				if (::Ground[Land].Cost[0] == 0 || (Cell_Occupier() != NULL &&
    959 					Cell_Occupier()->What_Am_I() != RTTI_INFANTRY)) {	// impassable
    960 					remap = Map.FadingRed;
    961 				} else {
    962 					if (::Ground[Land].Cost[0] > 0x70) {	// pretty passable
    963 						remap = Map.FadingGreen;
    964 					} else {
    965 						remap = Map.FadingYellow;				// moderately passable
    966 					}
    967 				}
    968 			}
    969 #endif
    970 
    971 	// ****** maybe this icon shouldn't be drawn if it is known that the cell will be covered
    972 	//			 with shadow.
    973 			/*
    974 			**	This is the underlying terrain icon.
    975 			*/
    976 			if (ttype->Get_Image_Data()) {
    977 				LogicPage->Draw_Stamp(ttype->Get_Image_Data(), icon, x, y, NULL, WINDOW_TACTICAL);
    978 				if (remap) {
    979 					LogicPage->Remap(x+Map.TacPixelX, y+Map.TacPixelY, ICON_PIXEL_W, ICON_PIXEL_H, remap);
    980 				}
    981 			}
    982 
    983 
    984 #ifdef SCENARIO_EDITOR
    985 			/*
    986 			**	Draw the map editor's "current" cell. This is the cell that can be
    987 			**	assigned attributes such as tag labels.
    988 			**	This must be draw before the placement cursor, but after drawing the
    989 			**	objects in the cell.
    990 			*/
    991 			if (Debug_Map && CurrentCell == Cell_Number()) {
    992 				LogicPage->Draw_Rect(x+Map.TacPixelX, y+Map.TacPixelY, Map.TacPixelX + x + CELL_PIXEL_W - 1, Map.TacPixelY + y + CELL_PIXEL_H - 1, YELLOW);
    993 			}
    994 #endif
    995 
    996 #ifdef NEVER
    997 			/*
    998 			**	Special concrete render. It always renders over the underlying
    999 			**	terrain unless this concrete piece will cover the entire terrain
   1000 			**	piece.
   1001 			*/
   1002 			if (Concrete) {
   1003 				LogicPage->Draw_Stamp(TemplateTypeClass::As_Pointer(TEMPLATE_CONCRETE_GDI)->Get_Image_Data(), Concrete-1, x, y, NULL, WINDOW_TACTICAL);
   1004 			}
   1005 #endif
   1006 		}
   1007 
   1008 		/*
   1009 		**	Redraw any smudge.
   1010 		*/
   1011 		if (Smudge != SMUDGE_NONE) {
   1012 #ifdef NEVER
   1013 			switch (Smudge) {
   1014 				case SMUDGE_BIB1:
   1015 					CC_Draw_Shape(Bib1, SmudgeData, x, y, WINDOW_TACTICAL, SHAPE_WIN_REL);
   1016 					break;
   1017 
   1018 				case SMUDGE_BIB2:
   1019 					CC_Draw_Shape(Bib2, SmudgeData, x, y, WINDOW_TACTICAL, SHAPE_WIN_REL);
   1020 					break;
   1021 
   1022 				case SMUDGE_BIB3:
   1023 					CC_Draw_Shape(Bib3, SmudgeData, x, y, WINDOW_TACTICAL, SHAPE_WIN_REL);
   1024 					break;
   1025 			}
   1026 #endif
   1027 			SmudgeTypeClass::As_Reference(Smudge).Draw_It(x, y, SmudgeData);
   1028 		}
   1029 
   1030 
   1031 		if (!draw_type || draw_type == CELL_DRAW_ONLY){
   1032 
   1033 			/*
   1034 			**	Draw the overlay object.
   1035 			*/
   1036 			if (Overlay != OVERLAY_NONE) {
   1037 				OverlayTypeClass const & otype = OverlayTypeClass::As_Reference(Overlay);
   1038 				IsTheaterShape = (bool)otype.IsTheater;
   1039 				CC_Draw_Shape(otype.Get_Image_Data(), OverlayData, (x+(CELL_PIXEL_W>>1)), (y+(CELL_PIXEL_H>>1)), WINDOW_TACTICAL, SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST, NULL, Map.UnitShadow);
   1040 				IsTheaterShape = false;
   1041 			}
   1042 
   1043 	#ifdef SCENARIO_EDITOR
   1044 			if (Debug_Map) {
   1045 				/*
   1046 				**	Draw the cell's Trigger mnemonic, if it has a trigger
   1047 				*/
   1048 				if (IsTrigger) {
   1049 					trig = Get_Trigger();
   1050 					Fancy_Text_Print(trig->Get_Name(), x+Map.TacPixelX, y+Map.TacPixelY, PINK, TBLACK, TPF_NOSHADOW|TPF_6POINT);
   1051 				}
   1052 
   1053 				/*
   1054 				**	Draw the cell's Waypoint designation if there is one.
   1055 				*/
   1056 				if (IsWaypoint) {
   1057 					for (i = 0; i < 26; i++) {
   1058 						if (Waypoint[i]==Cell_Number()) {
   1059 							waypt[0] = 'A' + i;
   1060 							waypt[1] = 0;
   1061 							Fancy_Text_Print(waypt, Map.TacPixelX + x + CELL_PIXEL_W / 2,
   1062 								Map.TacPixelY + y + (CELL_PIXEL_H / 2) - 3, YELLOW, TBLACK,
   1063 								TPF_NOSHADOW | TPF_6POINT | TPF_CENTER);
   1064 							break;
   1065 						}
   1066 					}
   1067 					if (Waypoint[WAYPT_HOME] == Cell_Number()) {
   1068 							Fancy_Text_Print("Home", Map.TacPixelX + x, Map.TacPixelY + y + (CELL_PIXEL_H) - 7,
   1069 							WHITE, TBLACK, TPF_NOSHADOW | TPF_6POINT);
   1070 					}
   1071 					if (Waypoint[WAYPT_REINF] == Cell_Number()) {
   1072 							Fancy_Text_Print("Reinf", Map.TacPixelX + x, Map.TacPixelY + y + (CELL_PIXEL_H) - 7,
   1073 							WHITE, TBLACK, TPF_NOSHADOW | TPF_6POINT);
   1074 					}
   1075 				}
   1076 			}
   1077 	#endif
   1078 
   1079 			/*
   1080 			**	Draw the placement cursor:
   1081 			**	- First, draw the hash-mark cursor, so it will appear underneath
   1082 			**	  any cursor being drawn
   1083 			**	- If the PendingObject is a template, overlay, or smudge, draw it
   1084 			**	- Otherwise, it's up to the Display.Refresh_Map() routine to draw it
   1085 			*/
   1086 			if (IsCursorHere) {
   1087 
   1088 				/*
   1089 				**	Draw the hash-mark cursor:
   1090 				*/
   1091 				if (Map.ProximityCheck && Is_Generally_Clear()) {
   1092 					LogicPage->Draw_Stamp(Map.TransIconset, 0, x, y, NULL, WINDOW_TACTICAL);
   1093 				} else {
   1094 					LogicPage->Draw_Stamp(Map.TransIconset, 2, x, y, NULL, WINDOW_TACTICAL);
   1095 				}
   1096 
   1097 	#ifdef SCENARIO_EDITOR
   1098 				if (Debug_Map && Map.PendingObject) {
   1099 
   1100 					switch (Map.PendingObject->What_Am_I()) {
   1101 
   1102 						/*
   1103 						**	Draw a template:
   1104 						**	- Compute the icon offset of this cell for this template, using
   1105 						**	  ZoneCell+ZoneOffset to get the upper-left corner of the placement
   1106 						**	  cursor
   1107 						**	- Draw the icon
   1108 						*/
   1109 						case RTTI_TEMPLATETYPE:
   1110 							tptr = (TemplateTypeClass *)Map.PendingObject;
   1111 							if (tptr->Get_Image_Data()) {
   1112 								icon = (Cell_X(cell) - Cell_X(Map.ZoneCell + Map.ZoneOffset)) +
   1113 									(Cell_Y(cell) - Cell_Y(Map.ZoneCell + Map.ZoneOffset)) *
   1114 									tptr->Width;
   1115 								LogicPage->Draw_Stamp(tptr->Get_Image_Data(), icon, x, y, NULL, WINDOW_TACTICAL);
   1116 							}
   1117 							break;
   1118 
   1119 						/*
   1120 						**	Draw an overlay; just use the existing 'OverlayData' even though
   1121 						**	it means nothing.
   1122 						*/
   1123 						case RTTI_OVERLAYTYPE:
   1124 							OverlayTypeClass::As_Reference(((OverlayTypeClass *)Map.PendingObject)->Type).Draw_It(x, y, OverlayData);
   1125 							break;
   1126 
   1127 						/*
   1128 						**	Draw a smudge
   1129 						*/
   1130 						case RTTI_SMUDGETYPE:
   1131 							SmudgeTypeClass::As_Reference(((SmudgeTypeClass *)Map.PendingObject)->Type).Draw_It(x, y, 0);
   1132 							break;
   1133 					}
   1134 				}
   1135 	#endif
   1136 			}
   1137 		}
   1138 	}
   1139 }
   1140 
   1141 
   1142 /***********************************************************************************************
   1143  * CellClass::Concrete_Calc -- Calculates the concrete icon to use for the cell.               *
   1144  *                                                                                             *
   1145  *    This routine examines the cells around the current one and from this, determines what    *
   1146  *    concrete icon shape to use (if any). The cell data is adjusted and the cell is marked    *
   1147  *    for redraw if the icon changed.                                                          *
   1148  *                                                                                             *
   1149  * INPUT:   none                                                                               *
   1150  *                                                                                             *
   1151  * OUTPUT:  none                                                                               *
   1152  *                                                                                             *
   1153  * WARNINGS:   none                                                                            *
   1154  *                                                                                             *
   1155  * HISTORY:                                                                                    *
   1156  *   08/01/1994 JLB : Created.                                                                 *
   1157  *=============================================================================================*/
   1158 void CellClass::Concrete_Calc(void)
   1159 {
   1160 	Validate();
   1161 	static FacingType _even[5] = {FACING_N, FACING_S, FACING_SW, FACING_W, FACING_NW};
   1162 	static FacingType _odd[5] = {FACING_N, FACING_NE, FACING_E, FACING_SE, FACING_S};
   1163 	FacingType *ptr;		// Working pointer into adjacent cell list.
   1164 	int	index;	// Constructed bit index.
   1165 	int	icon;		// Icon number.
   1166 	bool	isodd;	// Is this for the odd column?
   1167 
   1168 #define	OF_N	0x01
   1169 #define	OF_NE	0x02
   1170 #define	OF_E	0x04
   1171 #define	OF_SE	0x08
   1172 #define	OF_S	0x10
   1173 
   1174 #define	EF_N	0x01
   1175 #define	EF_NW	0x10
   1176 #define	EF_W	0x08
   1177 #define	EF_SW	0x04
   1178 #define	EF_S	0x02
   1179 
   1180 	/*
   1181 	**	Determine if the even or odd row logic is necessary.
   1182 	*/
   1183 	isodd = ((Cell_Number() & 0x01) != 0);
   1184 
   1185 	/*
   1186 	**	Fetch correct pointer depending on whether this is for an
   1187 	**	odd or even row.
   1188 	*/
   1189 	ptr = (isodd) ? _odd : _even;
   1190 
   1191 	/*
   1192 	**	Build an index according to the presence of concrete in the special
   1193 	**	adjacent cells. This is a short list of adjacent cell flags since
   1194 	**	only 5 adjacent cells need to be examined. The choice of which 5
   1195 	**	depends on whether this is for an even or odd column.
   1196 	*/
   1197 	index = 0;
   1198 	for (int i = 0; i < (sizeof(_even)/sizeof(_even[0])); i++) {
   1199 		CellClass * cellptr = Adjacent_Cell(*ptr++);
   1200 
   1201 //		if ((cellptr->IsConcrete) ||
   1202 //					cellptr->Concrete == C_UPDOWN_RIGHT ||
   1203 //					cellptr->Concrete == C_UPDOWN_LEFT) {
   1204 
   1205 		if (cellptr && cellptr->Overlay == OVERLAY_CONCRETE) {
   1206 			index |= (1<<i);
   1207 		}
   1208 	}
   1209 
   1210 	/*
   1211 	**	Special logic occurs for cells that are concrete filled.
   1212 	*/
   1213 	if (Overlay == OVERLAY_CONCRETE) {
   1214 
   1215 		/*
   1216 		**	Process the index value and place the appropriate concrete icon
   1217 		**	in the cell.
   1218 		*/
   1219 		if (isodd) {
   1220 			switch (index) {
   1221 				case OF_NE:
   1222 				case OF_N|OF_NE:
   1223 				case OF_E|OF_N:
   1224 				case OF_E|OF_NE:
   1225 				case OF_N|OF_NE|OF_E:
   1226 				case OF_S|OF_N|OF_NE:
   1227 					icon = C_RIGHT_UP;		// right - up
   1228 					break;
   1229 
   1230 				case OF_SE:
   1231 				case OF_E|OF_SE:
   1232 				case OF_S|OF_SE:
   1233 				case OF_S|OF_E:
   1234 				case OF_S|OF_SE|OF_E:
   1235 				case OF_S|OF_SE|OF_N:
   1236 					icon = C_RIGHT_DOWN;		// right - down
   1237 					break;
   1238 
   1239 				case OF_SE|OF_NE:
   1240 				case OF_SE|OF_NE|OF_N:
   1241 				case OF_SE|OF_NE|OF_S:
   1242 				case OF_SE|OF_NE|OF_S|OF_N:
   1243 				case OF_SE|OF_E|OF_N:
   1244 				case OF_SE|OF_E|OF_NE|OF_N:
   1245 				case OF_S|OF_E|OF_N:
   1246 				case OF_S|OF_E|OF_NE:
   1247 				case OF_S|OF_E|OF_NE|OF_N:
   1248 				case OF_S|OF_SE|OF_E|OF_N:
   1249 				case OF_S|OF_SE|OF_E|OF_NE|OF_N:
   1250 				case OF_S|OF_SE|OF_E|OF_NE:
   1251 					icon = C_RIGHT_UPDOWN;		// right - up - down
   1252 					break;
   1253 
   1254 				default:
   1255 					icon = C_RIGHT;		// right
   1256 					break;
   1257 			}
   1258 		} else {
   1259 			switch (index) {
   1260 				case EF_NW:
   1261 				case EF_NW|EF_N:
   1262 				case EF_W|EF_N:
   1263 				case EF_NW|EF_W|EF_N:
   1264 				case EF_NW|EF_W:
   1265 				case EF_NW|EF_S|EF_N:
   1266 					icon = C_LEFT_UP;		// left - up
   1267 					break;
   1268 
   1269 				case EF_SW:
   1270 				case EF_SW|EF_S:
   1271 				case EF_W|EF_S:
   1272 				case EF_W|EF_SW|EF_S:
   1273 				case EF_W|EF_SW:
   1274 				case EF_SW|EF_S|EF_N:
   1275 					icon = C_LEFT_DOWN;		// left - down
   1276 					break;
   1277 
   1278 				case EF_NW|EF_SW:
   1279 				case EF_NW|EF_SW|EF_N:
   1280 				case EF_NW|EF_SW|EF_S:
   1281 				case EF_NW|EF_SW|EF_S|EF_N:
   1282 				case EF_W|EF_S|EF_N:
   1283 				case EF_W|EF_SW|EF_N:
   1284 				case EF_W|EF_SW|EF_S|EF_N:
   1285 				case EF_NW|EF_W|EF_S:
   1286 				case EF_NW|EF_W|EF_S|EF_N:
   1287 				case EF_NW|EF_W|EF_SW|EF_S|EF_N:
   1288 				case EF_NW|EF_W|EF_SW|EF_N:
   1289 				case EF_NW|EF_W|EF_SW|EF_S:
   1290 					icon = C_LEFT_UPDOWN;		// left - up - down
   1291 					break;
   1292 
   1293 				default:
   1294 					icon = C_LEFT;		// left
   1295 					break;
   1296 			}
   1297 		}
   1298 
   1299 	} else {
   1300 
   1301 		// Presume that no concrete piece is needed.
   1302 		icon = C_NONE;
   1303 		if (isodd) {
   1304 			index &= ~(OF_NE|OF_SE);		// Ignore diagonals.
   1305 			switch (index) {
   1306 				case OF_N|OF_E:
   1307 					icon = C_UP_RIGHT;		// up right
   1308 					break;
   1309 
   1310 				case OF_E|OF_S:
   1311 					icon = C_DOWN_RIGHT;		// down right
   1312 					break;
   1313 
   1314 				case OF_N|OF_E|OF_S:
   1315 					icon = C_UPDOWN_RIGHT;	// up/down right
   1316 					break;
   1317 
   1318 				default:
   1319 					break;
   1320 			}
   1321 		} else {
   1322 			index &= ~(EF_NW|EF_SW);		// Ignore diagonals.
   1323 			switch (index) {
   1324 				case EF_N|EF_W:
   1325 					icon = C_UP_LEFT;		// up left
   1326 					break;
   1327 
   1328 				case EF_W|EF_S:
   1329 					icon = C_DOWN_LEFT;		// down left
   1330 					break;
   1331 
   1332 				case EF_N|EF_W|EF_S:
   1333 					icon = C_UPDOWN_LEFT;		// up/down left
   1334 					break;
   1335 
   1336 				default:
   1337 					break;
   1338 			}
   1339 		}
   1340 
   1341 		/*
   1342 		**	If any kind of fixup piece is needed, then add concrete
   1343 		**	to this location RECURSIVELY!
   1344 		*/
   1345 		if (icon != C_NONE) {
   1346 			OverlayTypeClass::As_Reference(OVERLAY_CONCRETE).Create_And_Place(Cell_Number());
   1347 			icon = C_NONE;
   1348 		}
   1349 
   1350 	}
   1351 
   1352 	/*
   1353 	**	Update the icon on the map.
   1354 	*/
   1355 	if (icon != C_NONE && OverlayData != icon) {
   1356 		OverlayData = icon;
   1357 		//Array[cell].Base = 0;
   1358 		Redraw_Objects();
   1359 	}
   1360 }
   1361 
   1362 
   1363 /***********************************************************************************************
   1364  * CellClass::Wall_Update -- Updates the imagery for wall objects in cell.                     *
   1365  *                                                                                             *
   1366  *    This routine will examine the cell and the adjacent cells to determine what the wall     *
   1367  *    should look like with the cell. It will then update the wall's imagery value and flag    *
   1368  *    the cell to be redrawn if necessary. This routine should be called whenever the wall     *
   1369  *    or an adjacent wall is created or destroyed.                                             *
   1370  *                                                                                             *
   1371  * INPUT:   none                                                                               *
   1372  *                                                                                             *
   1373  * OUTPUT:  none                                                                               *
   1374  *                                                                                             *
   1375  * WARNINGS:   none                                                                            *
   1376  *                                                                                             *
   1377  * HISTORY:                                                                                    *
   1378  *   09/19/1994 JLB : Created.                                                                 *
   1379  *   09/19/1994 BWG : Updated to handle partially-damaged walls.                               *
   1380  *=============================================================================================*/
   1381 void CellClass::Wall_Update(void)
   1382 {
   1383 	Validate();
   1384 	static FacingType _offsets[5] = {FACING_N, FACING_E, FACING_S, FACING_W, FACING_NONE};
   1385 
   1386 	if (Overlay == OVERLAY_NONE) {
   1387 		return;
   1388 	}
   1389 
   1390 	OverlayTypeClass const & wall = OverlayTypeClass::As_Reference(Overlay);
   1391 	if (!wall.IsWall) {
   1392 		return;
   1393 	}
   1394 
   1395 	for (unsigned index = 0; index < (sizeof(_offsets)/sizeof(_offsets[0])); index++) {
   1396 		CellClass * newcell = Adjacent_Cell(_offsets[index]);
   1397 
   1398 		if (newcell && newcell->Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(newcell->Overlay).IsWall) {
   1399 			int	icon = 0;
   1400 
   1401 			/*
   1402 			**	Build the icon number according to walls located in the adjacent
   1403 			**	cells.
   1404 			*/
   1405 			for (unsigned i = 0; i < 4; i++) {
   1406 				CellClass * adjcell = newcell->Adjacent_Cell(_offsets[i]);
   1407 				if (adjcell && adjcell->Overlay == newcell->Overlay) {
   1408 					icon |= 1 << i;
   1409 				}
   1410 			}
   1411 			newcell->OverlayData = (newcell->OverlayData & 0xFFF0) | icon;
   1412 //			newcell->OverlayData = icon;
   1413 
   1414 			/*
   1415 			**	Handle special cases for the incomplete damaged wall sets. If a damage stage
   1416 			**	is calculated, but there is no artwork for it, then consider the wall to be
   1417 			**	completely destroyed.
   1418 			*/
   1419 			if (newcell->Overlay == OVERLAY_BRICK_WALL && newcell->OverlayData == 48) {
   1420 				newcell->Overlay = OVERLAY_NONE;
   1421 				newcell->OverlayData = 0;
   1422 				ObjectClass::Detach_This_From_All(::As_Target(newcell->Cell_Number()), true);
   1423 			}
   1424 			if (newcell->Overlay == OVERLAY_SANDBAG_WALL && newcell->OverlayData == 16) {
   1425 				newcell->Overlay = OVERLAY_NONE;
   1426 				newcell->OverlayData = 0;
   1427 				ObjectClass::Detach_This_From_All(::As_Target(newcell->Cell_Number()), true);
   1428 			}
   1429 			if (newcell->Overlay == OVERLAY_CYCLONE_WALL && newcell->OverlayData == 32) {
   1430 				newcell->Overlay = OVERLAY_NONE;
   1431 				newcell->OverlayData = 0;
   1432 				ObjectClass::Detach_This_From_All(::As_Target(newcell->Cell_Number()), true);
   1433 			}
   1434 			if (newcell->Overlay == OVERLAY_BARBWIRE_WALL && newcell->OverlayData == 16) {
   1435 				newcell->Overlay = OVERLAY_NONE;
   1436 				newcell->OverlayData = 0;
   1437 				ObjectClass::Detach_This_From_All(::As_Target(newcell->Cell_Number()), true);
   1438 			}
   1439 
   1440 			newcell->Recalc_Attributes();
   1441 			newcell->Redraw_Objects();
   1442 		}
   1443 	}
   1444 }
   1445 
   1446 
   1447 /***********************************************************************************************
   1448  * CellClass::Cell_Coord -- Returns the coordinate of this cell.                               *
   1449  *                                                                                             *
   1450  *    This support function will determine the coordinate of this cell and return it.          *
   1451  *                                                                                             *
   1452  * INPUT:   none                                                                               *
   1453  *                                                                                             *
   1454  * OUTPUT:  Returns with coordinate value of cell.                                             *
   1455  *                                                                                             *
   1456  * WARNINGS:   none                                                                            *
   1457  *                                                                                             *
   1458  * HISTORY:                                                                                    *
   1459  *   09/19/1994 JLB : Created.                                                                 *
   1460  *=============================================================================================*/
   1461 COORDINATE CellClass::Cell_Coord(void) const
   1462 {
   1463 	Validate();
   1464 	return(::Cell_Coord(Cell_Number()));
   1465 }
   1466 
   1467 
   1468 /***********************************************************************************************
   1469  * CellClass::Reduce_Tiberium -- Reduces the tiberium in the cell by the amount specified.     *
   1470  *                                                                                             *
   1471  *    This routine will lower the tiberium level in the cell. It is used by the harvesting     *
   1472  *    process as well as by combat damage to the tiberium fields.                              *
   1473  *                                                                                             *
   1474  * INPUT:   levels   -- The number of levels to reduce the tiberium.                           *
   1475  *                                                                                             *
   1476  * OUTPUT:  bool; Was the tiberium level reduced by at least one level?                        *
   1477  *                                                                                             *
   1478  * WARNINGS:   none                                                                            *
   1479  *                                                                                             *
   1480  * HISTORY:                                                                                    *
   1481  *   09/19/1994 JLB : Created.                                                                 *
   1482  *=============================================================================================*/
   1483 int CellClass::Reduce_Tiberium(int levels)
   1484 {
   1485 	Validate();
   1486 	int reducer = 0;
   1487 
   1488 	if (levels && Land == LAND_TIBERIUM) {
   1489 		if (OverlayData > levels) {
   1490 			OverlayData -= levels;
   1491 			reducer = levels;
   1492 		} else {
   1493 			Overlay = OVERLAY_NONE;
   1494 			reducer = OverlayData;
   1495 			OverlayData = 0;
   1496 			Recalc_Attributes();
   1497 		}
   1498 	}
   1499 	return(reducer);
   1500 }
   1501 
   1502 
   1503 /***********************************************************************************************
   1504  * CellClass::Reduce_Wall -- Damages a wall, if damage is high enough.                         *
   1505  *                                                                                             *
   1506  *    This routine will change the wall shape used for a wall if it's damaged.                 *
   1507  *                                                                                             *
   1508  *                                                                                             *
   1509  * INPUT:   damage   -- The number of damage points the wall was hit with.                     *
   1510  *                                                                                             *
   1511  * OUTPUT:  bool; Was the wall destroyed?                                                      *
   1512  *                                                                                             *
   1513  * WARNINGS:   none                                                                            *
   1514  *                                                                                             *
   1515  * HISTORY:                                                                                    *
   1516  *   03/15/1995 BWG : Created.                                                                 *
   1517  *   03/19/1995 JLB : Updates cell information if wall was destroyed.                          *
   1518  *=============================================================================================*/
   1519 int CellClass::Reduce_Wall(int damage)
   1520 {
   1521 	Validate();
   1522 	if (Overlay != OVERLAY_NONE) {
   1523 		bool destroyed = false;
   1524 		OverlayTypeClass const & wall = OverlayTypeClass::As_Reference(Overlay);
   1525 
   1526 		if (wall.IsWall) {
   1527 
   1528 			/*
   1529 			**	If the damage was great enough to ensure wall destruction, reduce the wall by one
   1530 			**	level (no more). Otherwise determine wall reduction based on a percentage chance
   1531 			**	proportional to the damage received and the wall's strength.
   1532 			*/
   1533 			if (damage >= wall.DamagePoints) {
   1534 				destroyed = true;
   1535 			} else {
   1536 				destroyed = Random_Pick(0, wall.DamagePoints) < damage;
   1537 			}
   1538 
   1539 			if (destroyed) {
   1540 				OverlayData+=16;
   1541 				if ((OverlayData>>4) >= wall.DamageLevels) {
   1542 					ObjectClass::Detach_This_From_All(As_Target());
   1543 					Owner = HOUSE_NONE;
   1544 					Overlay = OVERLAY_NONE;
   1545 					OverlayData = 0;
   1546 					Recalc_Attributes();
   1547 					Redraw_Objects();
   1548 					CellClass * ncell = Adjacent_Cell(FACING_N);
   1549 					if (ncell) ncell->Wall_Update();
   1550 					CellClass * wcell = Adjacent_Cell(FACING_W);
   1551 					if (wcell) wcell->Wall_Update();
   1552 					CellClass * scell = Adjacent_Cell(FACING_S);
   1553 					if (scell) scell->Wall_Update();
   1554 					CellClass * ecell = Adjacent_Cell(FACING_E);
   1555 					if (ecell) ecell->Wall_Update();
   1556 					return(true);
   1557 				}
   1558 			}
   1559 		}
   1560 	}
   1561 	return(false);
   1562 }
   1563 
   1564 
   1565 /***********************************************************************************************
   1566  * CellClass::Get_Trigger -- retrieves reference to the cell's trigger                         *
   1567  *                                                                                             *
   1568  * INPUT:                                                                                      *
   1569  *      none.                                                                                  *
   1570  *                                                                                             *
   1571  * OUTPUT:                                                                                     *
   1572  *      TriggerClass reference                                                                 *
   1573  *                                                                                             *
   1574  * WARNINGS:                                                                                   *
   1575  *      Never call this function unless the IsTrigger flag is set for the cell!                *
   1576  *                                                                                             *
   1577  * HISTORY:                                                                                    *
   1578  *   12/01/1994 BR : Created.                                                                  *
   1579  *=============================================================================================*/
   1580 TriggerClass * CellClass::Get_Trigger(void) const
   1581 {
   1582 	Validate();
   1583 	if (IsTrigger) {
   1584 		return(CellTriggers[Cell_Number()]);
   1585 	}
   1586 	return(NULL);
   1587 }
   1588 
   1589 
   1590 /***********************************************************************************************
   1591  * CellClass::Spot_Index -- returns cell sub-coord index for given COORD                       *
   1592  *                                                                                             *
   1593  * INPUT:                                                                                      *
   1594  *      coord      COORD to compute index for                                                  *
   1595  *                                                                                             *
   1596  * OUTPUT:                                                                                     *
   1597  *      index into StoppingCoord that's closest to this coord                                  *
   1598  *                                                                                             *
   1599  * WARNINGS:                                                                                   *
   1600  *      none.                                                                                  *
   1601  *                                                                                             *
   1602  * HISTORY:                                                                                    *
   1603  *   11/21/1994 BR : Created.                                                                  *
   1604  *   12/10/1994 JLB : Uses alternate sub-position algorithm.                                   *
   1605  *=============================================================================================*/
   1606 int CellClass::Spot_Index(COORDINATE coord)
   1607 {
   1608 	COORDINATE rel = coord & 0x00FF00FFL;		// Sub coordinate value within cell.
   1609 
   1610 	/*
   1611 	**	If the coordinate is close enough to the center of the cell, then return
   1612 	**	the center position index.
   1613 	*/
   1614 	if (Distance(rel, 0x00800080L) < 60) {
   1615 		return(0);
   1616 	}
   1617 
   1618 	/*
   1619 	**	Since the center cell position has been eliminated, a simple comparison
   1620 	**	as related to the center of the cell can be used to determine the sub
   1621 	**	position. Take advantage of the fact that the sub positions are organized
   1622 	**	from left to right, top to bottom.
   1623 	*/
   1624 	int index = 0;
   1625 	if (Coord_X(rel) > 0x80) index |= 0x01;
   1626 	if (Coord_Y(rel) > 0x80) index |= 0x02;
   1627 	return(index+1);
   1628 }
   1629 
   1630 
   1631 /***********************************************************************************************
   1632  * CellClass::Closest_Free_Spot -- returns free spot closest to given coord                    *
   1633  *                                                                                             *
   1634  * Similar to the CellClass::Free_Spot; this routine finds the spot in                         *
   1635  * the cell closest to the given coordinate, and returns the COORD of                          *
   1636  * that spot if it's available, NULL if it's not.                                              *
   1637  *                                                                                             *
   1638  * INPUT:                                                                                      *
   1639  *  coord   coordinate to check (only sub cell position examined)                              *
   1640  *                                                                                             *
   1641  *          any   -- If only the closest spot is desired regardless of whether it is free or   *
   1642  *                   not, then this parameter will be true.                                    *
   1643  *                                                                                             *
   1644  * OUTPUT:                                                                                     *
   1645  *  COORD of free spot, NULL if none. The coordinate return value does not alter the cell      *
   1646  *             coordinate data portions of the coordinate passed in. Only the lower sub-cell   *
   1647  *             data is altered.                                                                *
   1648  *                                                                                             *
   1649  * WARNINGS:                                                                                   *
   1650  *  none.                                                                                      *
   1651  *                                                                                             *
   1652  * HISTORY:                                                                                    *
   1653  *   11/08/1994 BR : Created.                                                                  *
   1654  *   12/10/1994 JLB : Picks best of closest stopping positions.                                *
   1655  *   12/21/1994 JLB : Adds a mix-up factor if center location is occupied.                     *
   1656  *=============================================================================================*/
   1657 COORDINATE CellClass::Closest_Free_Spot(COORDINATE coord, bool any) const
   1658 {
   1659 	Validate();
   1660 	int spot_index = Spot_Index(coord);
   1661 
   1662 	/*
   1663 	**	This precalculated sequence table records the closest spots to any given spot. Sequential
   1664 	**	examination of these spots for availability ensures that the closes available one is
   1665 	**	discovered first.
   1666 	*/
   1667 	static unsigned char _sequence[5][4] = {
   1668 		{1,2,3,4},
   1669 		{0,2,3,4},
   1670 		{0,1,4,3},
   1671 		{0,1,4,2},
   1672 		{0,2,3,1}
   1673 	};
   1674 
   1675 	/*
   1676 	**	In the case of the center coordinate being requested, but is occupied, then all other
   1677 	**	sublocations are equidistant. Instead of picking a static sequence of examination, the
   1678 	**	order is mixed up by way of this table.
   1679 	*/
   1680 	static unsigned char _alternate[4][4] = {
   1681 		{1,2,3,4},
   1682 		{2,3,4,1},
   1683 		{3,4,1,2},
   1684 		{4,1,2,3},
   1685 	};
   1686 	coord &= 0xFF00FF00L;
   1687 
   1688 	/*
   1689 	**	Cells occupied by buildings or vehicles don't have any free spots.
   1690 	*/
   1691 	if (!any && (Flag.Occupy.Vehicle || Flag.Occupy.Monolith)) {
   1692 		return(NULL);
   1693 	}
   1694 
   1695 	/*
   1696 	**	If just the nearest position is desired regardless of whether occupied or not,
   1697 	**	then just return with the stopping coordinate value.
   1698 	*/
   1699 	if (any || Is_Spot_Free(spot_index)) {
   1700 		return(Coord_Add(coord, StoppingCoordAbs[spot_index]));
   1701 	}
   1702 
   1703 	/*
   1704 	**	Scan through all available sub-locations in the cell in order to determine
   1705 	**	the closest one to the coordinate requested. Use precalculated table so that
   1706 	**	when the first free position is found, bail.
   1707 	*/
   1708 	unsigned char *sequence;
   1709 	if (spot_index == 0) {
   1710 		sequence = &_alternate[Random_Pick(0,3)][0];
   1711 	} else {
   1712 		sequence = &_sequence[spot_index][0];
   1713 	}
   1714 	for (int index = 0; index < 4; index++) {
   1715 		int pos = *sequence++;
   1716 
   1717 		if (Is_Spot_Free(pos)) {
   1718 			return(Coord_Add(coord, StoppingCoordAbs[pos]));
   1719 		}
   1720 	}
   1721 
   1722 	/*
   1723 	**	No free spot could be found so return a NULL coordinate.
   1724 	*/
   1725 	return(0x00000000L);
   1726 }
   1727 
   1728 
   1729 /***********************************************************************************************
   1730  * CellClass::Clear_Icon -- Calculates what the clear icon number should be.                   *
   1731  *                                                                                             *
   1732  *    This support routine will determine what the clear icon number would be for the cell.    *
   1733  *    The icon number is determined by converting the cell number into an index into a         *
   1734  *    lookup table. This yields what appears to be a randomized map without the necessity of   *
   1735  *    generating and recording randomized map numbers.                                         *
   1736  *                                                                                             *
   1737  * INPUT:   none                                                                               *
   1738  *                                                                                             *
   1739  * OUTPUT:  Returns with the icon number for clear terrain if it were displayed at the         *
   1740  *          cell.                                                                              *
   1741  *                                                                                             *
   1742  * WARNINGS:   none                                                                            *
   1743  *                                                                                             *
   1744  * HISTORY:                                                                                    *
   1745  *   12/26/1994 JLB : Created.                                                                 *
   1746  *   06/09/1995 JLB : Uses 16 entry scramble algorithm.                                        *
   1747  *=============================================================================================*/
   1748 int CellClass::Clear_Icon(void) const
   1749 {
   1750 	Validate();
   1751 	CELL cell = Cell_Number();
   1752 	return((cell & 0x03) | ((cell>>4) & 0x0C));
   1753 }
   1754 
   1755 
   1756 /***********************************************************************************************
   1757  * CellClass::Incoming -- Causes objects in cell to "run for cover".                           *
   1758  *                                                                                             *
   1759  *    This routine is called whenever a great, but slow moving, threat is presented to the     *
   1760  *    occupants of a cell. The occupants will, in most cases, stop what they are doing and     *
   1761  *    try to get out of the way.                                                               *
   1762  *                                                                                             *
   1763  * INPUT:   threat      -- The coordinate source of the threat.                                *
   1764  *                                                                                             *
   1765  *          forced      -- If this threat is so major that the occupants should stop what      *
   1766  *                         they are doing, then this parameter should be set to true.          *
   1767  *                                                                                             *
   1768  *          nokidding   -- Override the scatter to also affect human controlled objects.       *
   1769  *                                                                                             *
   1770  * OUTPUT:  none                                                                               *
   1771  *                                                                                             *
   1772  * WARNINGS:   none                                                                            *
   1773  *                                                                                             *
   1774  * HISTORY:                                                                                    *
   1775  *   01/10/1995 JLB : Created.                                                                 *
   1776  *=============================================================================================*/
   1777 void CellClass::Incoming(COORDINATE threat, bool forced, bool nokidding)
   1778 {
   1779 	Validate();
   1780 	ObjectClass * object = NULL;
   1781 
   1782 	object = Cell_Occupier();
   1783 	while (object) {
   1784 
   1785 		/*
   1786 		**	Special check to make sure that friendly units never scatter.
   1787 		*/
   1788 		if (nokidding || Special.IsScatter || (object->Is_Techno() && !((TechnoClass *)object)->House->IsHuman)) {
   1789 			if (object->What_Am_I() == RTTI_INFANTRY) {
   1790 				object->Scatter(threat, forced, nokidding);
   1791 			} else {
   1792 				object->Scatter(threat, forced, nokidding);
   1793 //				object->Scatter(threat, false);
   1794 			}
   1795 		}
   1796 		object = object->Next;
   1797 	}
   1798 }
   1799 
   1800 
   1801 /***********************************************************************************************
   1802  * CellClass::Adjacent_Cell -- Determines the adjacent cell according to facing.               *
   1803  *                                                                                             *
   1804  *    Use this routine to return a reference to the adjacent cell in the direction specified.  *
   1805  *                                                                                             *
   1806  * INPUT:   face  -- The direction to use when determining the adjacent cell.                  *
   1807  *                                                                                             *
   1808  * OUTPUT:  Returns with a reference to the adjacent cell.                                     *
   1809  *                                                                                             *
   1810  * WARNINGS:   If the facing value is invalid, then a reference to the same cell is returned.  *
   1811  *                                                                                             *
   1812  * HISTORY:                                                                                    *
   1813  *   03/19/1995 JLB : Created.                                                                 *
   1814  *=============================================================================================*/
   1815 CellClass const * CellClass::Adjacent_Cell(FacingType face) const
   1816 {
   1817 	Validate();
   1818 	if (face == FACING_NONE) {
   1819 		return(this);
   1820 	}
   1821 
   1822 	if ((unsigned)face >= FACING_COUNT) {
   1823 		return(NULL);
   1824 	}
   1825 
   1826 	CELL newcell = ::Adjacent_Cell(Cell_Number(), face);
   1827 	if ((unsigned)newcell >= MAP_CELL_TOTAL) {
   1828 		return(NULL);
   1829 	}
   1830 
   1831 	return &Map[newcell];
   1832 }
   1833 
   1834 
   1835 /***************************************************************************
   1836  * CellClass::Adjust_Threat -- Allows adjustment of threat at cell level   *
   1837  *                                                                         *
   1838  * INPUT:                                                                  *
   1839  *                                                                         *
   1840  * OUTPUT:                                                                 *
   1841  *                                                                         *
   1842  * WARNINGS:                                                               *
   1843  *                                                                         *
   1844  * HISTORY:                                                                *
   1845  *   04/24/1995 PWG : Created.                                             *
   1846  *=========================================================================*/
   1847 void CellClass::Adjust_Threat(HousesType house, int threat_value)
   1848 {
   1849 	Validate();
   1850 	int region = Map.Cell_Region(Cell_Number());
   1851 
   1852 	for (HousesType lp = HOUSE_FIRST; lp < HOUSE_COUNT; lp ++) {
   1853 		if (lp == house) continue;
   1854 
   1855 		HouseClass *house_ptr = HouseClass::As_Pointer(lp);
   1856 		if (house_ptr && (!house_ptr->IsHuman || !house_ptr->Is_Ally(house))) {
   1857 			house_ptr->Adjust_Threat(region, threat_value);
   1858 		}
   1859 	}
   1860 	if (Debug_Threat) {
   1861 		Map.Flag_To_Redraw(true);
   1862 	}
   1863 }
   1864 
   1865 
   1866 /***********************************************************************************************
   1867  * CellClass::Tiberium_Adjust -- Adjust the look of the Tiberium for smoothing purposes.       *
   1868  *                                                                                             *
   1869  *    This routine will adjust the level of the Tiberium in the cell so that it will           *
   1870  *    smoothly blend with the adjacent Tiberium. This routine should only be called for        *
   1871  *    new Tiberium cells. Existing cells that contain Tiberium follow a different growth       *
   1872  *    pattern.                                                                                 *
   1873  *                                                                                             *
   1874  * INPUT:   pregame  -- Is this a pregame call? Such a call will mixup the Tiberium overlay    *
   1875  *                      used.                                                                  *
   1876  *                                                                                             *
   1877  * OUTPUT:  Returns with the added Tiberium value that is now available for harvesting.        *
   1878  *                                                                                             *
   1879  * WARNINGS:   The return value is only valid for the initial placement. Tiberium growth will  *
   1880  *             increase the net worth of the existing Tiberium.                                *
   1881  *                                                                                             *
   1882  * HISTORY:                                                                                    *
   1883  *   05/16/1995 JLB : Created.                                                                 *
   1884  *=============================================================================================*/
   1885 long CellClass::Tiberium_Adjust(bool pregame)
   1886 {
   1887 	Validate();
   1888 	if (Overlay != OVERLAY_NONE) {
   1889 		if (OverlayTypeClass::As_Reference(Overlay).Land == LAND_TIBERIUM) {
   1890 			static int _adj[9] = {0,1,3,4,6,7,8,10,11};
   1891 			int	count = 0;
   1892 
   1893 			/*
   1894 			**	Mixup the Tiberium overlays so that they don't look the same.
   1895 			*/
   1896 			if (pregame) {
   1897 				Overlay = Random_Pick(OVERLAY_TIBERIUM1, OVERLAY_TIBERIUM12);
   1898 			}
   1899 
   1900 			/*
   1901 			**	Add up all adjacent cells that contain tiberium.
   1902 			** (Skip those cells which aren't on the map)
   1903 			*/
   1904 			for (FacingType face = FACING_FIRST; face < FACING_COUNT; face++) {
   1905 				CELL cell = Cell_Number() + AdjacentCell[face];
   1906 				if ((unsigned)cell >= MAP_CELL_TOTAL) continue;
   1907 
   1908 				CellClass * adj = Adjacent_Cell(face);
   1909 
   1910 				if (adj && adj->Overlay != OVERLAY_NONE &&
   1911 					OverlayTypeClass::As_Reference(adj->Overlay).Land == LAND_TIBERIUM) {
   1912 					count++;
   1913 				}
   1914 			}
   1915 
   1916 			OverlayData = _adj[count];
   1917 			return((OverlayData+1) * UnitTypeClass::TIBERIUM_STEP);
   1918 		}
   1919 	}
   1920 	return(0);
   1921 }
   1922 
   1923 
   1924 /***********************************************************************************************
   1925  * CellClass::Goodie_Check -- Performs crate discovery logic.                                  *
   1926  *                                                                                             *
   1927  *    Call this routine whenever an object enters a cell. It will check for the existance      *
   1928  *    of a crate and generate any "goodie" it might contain.                                   *
   1929  *                                                                                             *
   1930  * INPUT:   object   -- Pointer to the object that is triggering this crate.                   *
   1931  *                                                                                             *
   1932  * OUTPUT:  Can the object continue to enter this cell? A false return value means that the    *
   1933  *          cell is now occupied and must not be entered.                                      *
   1934  *                                                                                             *
   1935  * WARNINGS:   none                                                                            *
   1936  *                                                                                             *
   1937  * HISTORY:                                                                                    *
   1938  *   05/22/1995 JLB : Created.                                                                 *
   1939  *   07/08/1995 JLB : Added a bunch of goodies to the crates.                                  *
   1940  *=============================================================================================*/
   1941 bool CellClass::Goodie_Check(FootClass * object, bool check_steel)
   1942 {
   1943 	Validate();
   1944 	enum {
   1945 		MONEY,			// Cash award.
   1946 		UNIT,				// A free unit.
   1947 		NUKE,				// A nuclear device that explodes.
   1948 		ION,				// Calls forth an ion blast on discoverer.
   1949 		NUKE_MISSILE,	// Gets a one time nuclear missile options.
   1950 		ION_BLAST,		// Gets a one time ion blast option.
   1951 		AIR_STRIKE,		// Gets a one time air strike option.
   1952 		HEAL_BASE,		// Heals the player's entire base.
   1953 		CLOAK,			// Units in region gain cloak ability.
   1954 		EXPLOSION,		// Conventional explosion.
   1955 		NAPALM,			// A napalm explosion.
   1956 		SQUAD,			// A mixed squad of friendly infantry appear.
   1957 		VISCEROID,		// A visceroid appears!
   1958 		DARKNESS,		// Shroud the entire map.
   1959 		REVEAL,			// Reveal the entire map.
   1960 		TOTAL_CRATES,
   1961 	};
   1962 	static int _what[] = {
   1963 		DARKNESS,DARKNESS,
   1964 		REVEAL,REVEAL,
   1965 		NUKE,
   1966 //		ION,ION,
   1967 		NUKE_MISSILE,
   1968 		ION_BLAST,ION_BLAST,
   1969 		AIR_STRIKE,AIR_STRIKE,AIR_STRIKE,AIR_STRIKE,
   1970 		HEAL_BASE,HEAL_BASE,
   1971 		CLOAK,CLOAK,
   1972 		EXPLOSION,EXPLOSION,EXPLOSION,EXPLOSION,
   1973 		NAPALM,NAPALM,NAPALM,
   1974 		SQUAD,SQUAD,SQUAD,SQUAD,SQUAD,
   1975 		UNIT,UNIT,UNIT,UNIT,UNIT,
   1976 		VISCEROID
   1977 	};
   1978 
   1979 
   1980 	/*
   1981 	** Crate types are only defined here so it needs to match my new global crate total ST - 6/4/96 2:16PM
   1982 	*/
   1983 #if (TOTAL_CRATES) == (TOTAL_CRATE_TYPES)
   1984 
   1985 #else
   1986 	//Huge_Errrrror..... Oh NO!
   1987 
   1988 #endif
   1989 
   1990 
   1991 	if (object && Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Overlay).IsCrate) {
   1992 		bool steel = (Overlay == OVERLAY_STEEL_CRATE);
   1993 		COORDINATE coord;			// Temporary working coordinate value.
   1994 
   1995 		if (check_steel && steel) {
   1996 
   1997 			/*
   1998 			**	A triggered crate is automatically destroyed regardless of who or how
   1999 			**	it was triggered.
   2000 			*/
   2001 			Redraw_Objects();
   2002 			Overlay = OVERLAY_NONE;
   2003 			OverlayData = 0;
   2004 
   2005 			if (object->Owner() == HOUSE_BAD) {
   2006 				object->House->Add_Nuke_Piece();
   2007 				new AnimClass(ANIM_CRATE_EMPULSE, Cell_Coord());
   2008 			}
   2009 
   2010 		} else if(!check_steel && !steel) {
   2011 
   2012 			/*
   2013 			**	A triggered crate is automatically destroyed regardless of who or how
   2014 			**	it was triggered.
   2015 			*/
   2016 			Redraw_Objects();
   2017 			Overlay = OVERLAY_NONE;
   2018 			OverlayData = 0;
   2019 
   2020 			int index;
   2021 			UnitClass * unit = 0;
   2022 			unsigned damage = 0;
   2023 			int what = MONEY;
   2024 
   2025 			if (GameToPlay != GAME_NORMAL && (Random_Pick(1, 2) == 1 || !object->House->BScan)) {
   2026 				what = -1;
   2027 
   2028 				/*
   2029 				**	If the player has a construction yeard and practically no money and no legitmate means
   2030 				**	to make any more money, then give money to build a refinery.
   2031 				*/
   2032 				if ((object->House->BScan & (STRUCTF_CONST|STRUCTF_REFINERY)) == STRUCTF_CONST &&
   2033 					object->House->Available_Money() < BuildingTypeClass::As_Reference(STRUCT_REFINERY).Cost) {
   2034 
   2035 					what = MONEY;
   2036 				}
   2037 
   2038 				/*
   2039 				**	If the player should get an MCV replacement, then give it now (probably).
   2040 				*/
   2041 				if (Random_Pick(0, 1) == 0 &&
   2042 					MPlayerBases &&
   2043 					!(object->House->UScan & UNITF_MCV) &&
   2044 					object->House->BScan == 0 &&
   2045 					object->House->Available_Money() > ((BuildingTypeClass::As_Reference(STRUCT_REFINERY).Cost + BuildingTypeClass::As_Reference(STRUCT_POWER).Cost) * object->House->CostBias)) {
   2046 
   2047 					what = UNIT;
   2048 				}
   2049 
   2050 				bool allow_super = true;
   2051 				if (GameToPlay == GAME_GLYPHX_MULTIPLAYER && !Rule.AllowSuperWeapons) {
   2052 					allow_super = false;
   2053 				}
   2054 
   2055 				while (what == -1) {
   2056 					what = _what[Random_Pick((unsigned)0, sizeof(_what)/sizeof(_what[0])-1)];
   2057 
   2058 					if (what == REVEAL && object->House->IsVisionary) what = -1;
   2059 					if (what == AIR_STRIKE && (!allow_super || object->House->AirStrike.Is_Present())) what = -1;
   2060 					if (what == NUKE_MISSILE && (!allow_super || object->House->NukeStrike.Is_Present())) what = -1;
   2061 					if (what == ION_BLAST && (!allow_super || object->House->IonCannon.Is_Present())) what = -1;
   2062 					if (what == CLOAK && object->IsCloakable) what = -1;
   2063 				}
   2064 			}
   2065 
   2066 			/*
   2067 			** Keep track of the number of each type of crate found
   2068 			*/
   2069 			if (GameToPlay == GAME_INTERNET){
   2070 				object->House->TotalCrates->Increment_Unit_Total(what);
   2071 			}
   2072 
   2073 			/*
   2074 			**	Update the crate count and when all the crates have been discovered, flag
   2075 			**	to generate a new one.
   2076 			*/
   2077 			CrateCount--;
   2078 			if (!CrateMaker && CrateCount <= 0 && GameToPlay != GAME_NORMAL) {
   2079 				CrateMaker = true;
   2080 				CrateTimer = 1;
   2081 			}
   2082 
   2083 			/*
   2084 			**	Create the effect requested.
   2085 			*/
   2086 			switch (what) {
   2087 				default:
   2088 
   2089 				/*
   2090 				**	Give the player money.
   2091 				*/
   2092 				case MONEY:
   2093 					new AnimClass(ANIM_CRATE_DOLLAR, Cell_Coord());
   2094 					if (GameToPlay == GAME_NORMAL) {
   2095 						HouseClass::As_Pointer(object->Owner())->Refund_Money(2000);
   2096 					} else {
   2097 						HouseClass::As_Pointer(object->Owner())->Refund_Money(100 + (Random_Pick(0,19)*100));
   2098 					}
   2099 					break;
   2100 
   2101 				/*
   2102 				**	Shroud the world in blackness.
   2103 				*/
   2104 				case DARKNESS:
   2105 				{	
   2106 					new AnimClass(ANIM_CRATE_EMPULSE, Cell_Coord());
   2107 					bool shroud = false;
   2108 					if (GameToPlay != GAME_GLYPHX_MULTIPLAYER) {
   2109 						if (object->House == PlayerPtr) {
   2110 							shroud = true;
   2111 						}
   2112 					} else {
   2113 						if (object->House->IsHuman) {
   2114 							shroud = true;
   2115 						}
   2116 					}	
   2117 					if (shroud) {
   2118 						for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   2119 							CellClass * cellptr = &Map[cell];
   2120 							if (cellptr->Is_Mapped(object->House) || cellptr->Is_Visible(object->House)) {
   2121 								cellptr->Redraw_Objects();
   2122 								cellptr->Set_Mapped(object->House, false);
   2123 								cellptr->Set_Visible(object->House, false);
   2124 							}
   2125 						}
   2126 						HouseClass *find_house = object->House;
   2127 						for (int index = 0; index < Map.Layer[LAYER_GROUND].Count(); index++) {
   2128 							ObjectClass * object = Map.Layer[LAYER_GROUND][index];
   2129 							if (object && object->Is_Techno() && ((TechnoClass *)object)->House == find_house) {
   2130 								object->Look();
   2131 							}
   2132 						}
   2133 						Map.Flag_To_Redraw(true);
   2134 					}
   2135 					break;
   2136 				}
   2137 				/*
   2138 				**	Reveal the entire map.
   2139 				*/
   2140 				case REVEAL:
   2141 				{	
   2142 					bool reveal = false;
   2143 					if (GameToPlay != GAME_GLYPHX_MULTIPLAYER) {
   2144 						if (object->House == PlayerPtr) {
   2145 							reveal = true;
   2146 						}
   2147 					} else {
   2148 						if (object->House->IsHuman) {
   2149 							reveal = true;
   2150 						}
   2151 					}	
   2152 					
   2153 					new AnimClass(ANIM_CRATE_EMPULSE, Cell_Coord());
   2154 					object->House->IsVisionary = true;
   2155 					if (reveal) {
   2156 						for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   2157 							Map.Map_Cell(cell, object->House, true);
   2158 						}
   2159 					}
   2160 					break;
   2161 				}
   2162 				/*
   2163 				**	Try to create a unit where the crate was.
   2164 				*/
   2165 				case UNIT: {
   2166 					UnitTypeClass const * utp = NULL;
   2167 
   2168 					/*
   2169 					**	Give the player an MCV if he has no base left but does have more than enough
   2170 					**	money to rebuild a new base. Of course, if he already has an MCV, then don't
   2171 					**	give him another one.
   2172 					*/
   2173 					if (MPlayerBases &&
   2174 						!(object->House->UScan & UNITF_MCV) &&
   2175 						object->House->BScan == 0 &&
   2176 						object->House->Available_Money() > (BuildingTypeClass::As_Reference(STRUCT_REFINERY).Cost + BuildingTypeClass::As_Reference(STRUCT_POWER).Cost)) {
   2177 
   2178 						utp = &UnitTypeClass::As_Reference(UNIT_MCV);
   2179 					}
   2180 
   2181 					/*
   2182 					**	If the player has a base and a refinery, but no harvester, then give him
   2183 					**	a free one.
   2184 					*/
   2185 					if (!utp && (object->House->BScan & STRUCTF_REFINERY) && !(object->House->UScan & UNITF_HARVESTER)) {
   2186 						utp = &UnitTypeClass::As_Reference(UNIT_HARVESTER);
   2187 					}
   2188 
   2189 					while (!utp) {
   2190 						UnitType utype = Random_Pick(UNIT_FIRST, (UnitType)(UNIT_COUNT-1));
   2191 						if (utype != UNIT_MCV || MPlayerBases) {
   2192 							utp = &UnitTypeClass::As_Reference(utype);
   2193 							if (utp->IsCrateGoodie && (utp->Ownable & (1 << object->Owner())) && utp->Level <= BuildLevel+2) break;
   2194 							utp = NULL;
   2195 						}
   2196 					}
   2197 
   2198 					UnitClass * unit = (UnitClass *)utp->Create_One_Of(object->House);
   2199 					if (unit) {
   2200 						if (unit->Unlimbo(Cell_Coord())) {
   2201 							return(false);
   2202 						}
   2203 						delete unit;
   2204 					}
   2205 				}
   2206 				break;
   2207 
   2208 				/*
   2209 				**	Create a squad of miscellanous composition.
   2210 				*/
   2211 				case SQUAD:
   2212 					for (index = 0; index < 5; index++) {
   2213 						static InfantryType _inf[] = {
   2214 							INFANTRY_E1,INFANTRY_E1,INFANTRY_E1,INFANTRY_E1,INFANTRY_E1,INFANTRY_E1,
   2215 							INFANTRY_E2,
   2216 							INFANTRY_E3,
   2217 							INFANTRY_E4,
   2218 							INFANTRY_E5,
   2219 							INFANTRY_E7,
   2220 							INFANTRY_RAMBO
   2221 						};
   2222 						InfantryTypeClass::As_Reference(_inf[Random_Pick((unsigned)0, sizeof(_inf)/sizeof(_inf[0])-1)]).Create_And_Place(Cell_Number(), object->Owner());
   2223 					}
   2224 					return(false);
   2225 
   2226 				/*
   2227 				**	Sometimes an explosion of great magnitude occurs.
   2228 				*/
   2229 				case NUKE:
   2230 					new AnimClass(ANIM_ATOM_BLAST, Cell_Coord());
   2231 					break;
   2232 
   2233 				/*
   2234 				**	Sometimes an explosion of great magnitude occurs.
   2235 				*/
   2236 				case ION:
   2237 					new AnimClass(ANIM_ION_CANNON, Cell_Coord());
   2238 					break;
   2239 
   2240 				/*
   2241 				**	A nuclear missile was discovered. Add it to the sidebar.
   2242 				*/
   2243 				case NUKE_MISSILE:
   2244 					new AnimClass(ANIM_CRATE_MISSILE, Cell_Coord());
   2245 					if (object->House->NukeStrike.Enable(true)) {
   2246 						// Add to Glyphx multiplayer sidebar. ST - 3/22/2019 1:50PM
   2247 						if (GameToPlay == GAME_GLYPHX_MULTIPLAYER) {
   2248 							if (object->House->IsHuman) {
   2249 								Sidebar_Glyphx_Add(RTTI_SPECIAL, SPC_NUCLEAR_BOMB, object->House);
   2250 							}
   2251 						} else {
   2252 							if (object->IsOwnedByPlayer) {
   2253 								Map.Add(RTTI_SPECIAL, SPC_NUCLEAR_BOMB);
   2254 								Map.Column[1].Flag_To_Redraw();
   2255 							}
   2256 						}
   2257 					}
   2258 					break;
   2259 
   2260 				/*
   2261 				**	A one time ion blast was discovered. Add it to the sidebar.
   2262 				*/
   2263 				case ION_BLAST:
   2264 					new AnimClass(ANIM_CRATE_EARTH, Cell_Coord());
   2265 					if (object->House->IonCannon.Enable(true)) {
   2266 						// Add to Glyphx multiplayer sidebar. ST - 3/22/2019 1:50PM
   2267 						if (GameToPlay == GAME_GLYPHX_MULTIPLAYER) {
   2268 							if (object->House->IsHuman) {
   2269 								Sidebar_Glyphx_Add(RTTI_SPECIAL, SPC_ION_CANNON, object->House);
   2270 							}
   2271 						} else {
   2272 							if (object->IsOwnedByPlayer) {
   2273 								Map.Add(RTTI_SPECIAL, SPC_ION_CANNON);
   2274 								Map.Column[1].Flag_To_Redraw();
   2275 							}
   2276 						}
   2277 					}
   2278 					break;
   2279 
   2280 				/*
   2281 				**	A one time air strike can be called int. Add it to the sidebar.
   2282 				*/
   2283 				case AIR_STRIKE:
   2284 					new AnimClass(ANIM_CRATE_DEVIATOR, Cell_Coord());
   2285 					if (object->House->AirStrike.Enable(true)) {
   2286 						// Add to Glyphx multiplayer sidebar. ST - 3/22/2019 1:50PM
   2287 						if (GameToPlay == GAME_GLYPHX_MULTIPLAYER) {
   2288 							if (object->House->IsHuman) {
   2289 								Sidebar_Glyphx_Add(RTTI_SPECIAL, SPC_AIR_STRIKE, object->House);
   2290 							}
   2291 						} else {
   2292 							if (object->IsOwnedByPlayer) {
   2293 								Map.Add(RTTI_SPECIAL, SPC_AIR_STRIKE);
   2294 								Map.Column[1].Flag_To_Redraw();
   2295 							}
   2296 						}
   2297 					}
   2298 					break;
   2299 
   2300 				/*
   2301 				**	A group of explosions are triggered around the crate.
   2302 				*/
   2303 				case EXPLOSION:
   2304 					damage = 400;
   2305 					object->Take_Damage((int&)damage, 0, WARHEAD_HE);
   2306 					for (index = 0; index < 5; index++) {
   2307 						COORDINATE coord = Coord_Scatter(Cell_Coord(), Random_Pick(0, 0x0200));
   2308 						new AnimClass(ANIM_FBALL1, coord);
   2309 						damage = 400;
   2310 						Explosion_Damage(coord, damage, NULL, WARHEAD_HE);
   2311 					}
   2312 					break;
   2313 
   2314 				/*
   2315 				**	A napalm blast is triggered.
   2316 				*/
   2317 				case NAPALM:
   2318 					coord = Coord_Mid(Cell_Coord(), object->Center_Coord());
   2319 					new AnimClass(ANIM_NAPALM3, coord);
   2320 					damage = 600;
   2321 					Explosion_Damage(coord, damage, NULL, WARHEAD_FIRE);
   2322 					break;
   2323 
   2324 				/*
   2325 				**	A visceroid appears and, boy, he's angry!
   2326 				*/
   2327 				case VISCEROID:
   2328 					unit = new UnitClass(UNIT_VICE, HOUSE_JP);
   2329 					if (unit) {
   2330 						if (unit->Unlimbo(Cell_Coord())) {
   2331 							return(false);
   2332 						}
   2333 						delete unit;
   2334 					}
   2335 					break;
   2336 
   2337 				/*
   2338 				**	All objects within a certain range will gain the ability to cloak.
   2339 				*/
   2340 				case CLOAK:
   2341 					new AnimClass(ANIM_CRATE_STEALTH, Cell_Coord());
   2342 					for (index = 0; index < Map.Layer[LAYER_GROUND].Count(); index++) {
   2343 						ObjectClass * obj = Map.Layer[LAYER_GROUND][index];
   2344 
   2345 						if (obj && obj->Is_Techno() && Distance(Cell_Coord(), obj->Center_Coord()) < 0x0300) {
   2346 							((TechnoClass *)obj)->IsCloakable = true;
   2347 						}
   2348 					}
   2349 					break;
   2350 
   2351 				/*
   2352 				**	All of the player's objects heal up.
   2353 				*/
   2354 				case HEAL_BASE:
   2355 					new AnimClass(ANIM_CRATE_INVUN, Cell_Coord());
   2356 					for (index = 0; index < Logic.Count(); index++) {
   2357 						ObjectClass * obj = Logic[index];
   2358 
   2359 						if (obj && object->Is_Techno() && object->House->Class->House == obj->Owner()) {
   2360 							obj->Strength = obj->Class_Of().MaxStrength;
   2361 						}
   2362 					}
   2363 					break;
   2364 
   2365 			}
   2366 		}
   2367 	}
   2368 	return(true);
   2369 }
   2370 
   2371 
   2372 /***********************************************************************************************
   2373  * CellClass::Flag_Place -- Places a house flag down on the cell.                              *
   2374  *                                                                                             *
   2375  *    This routine will place the house flag at this cell location.                            *
   2376  *                                                                                             *
   2377  * INPUT:   house -- The house that is having its flag placed here.                            *
   2378  *                                                                                             *
   2379  * OUTPUT:  Was the flag successfully placed here?                                             *
   2380  *                                                                                             *
   2381  * WARNINGS:   Failure to place means that the cell is impassable for some reason.             *
   2382  *                                                                                             *
   2383  * HISTORY:                                                                                    *
   2384  *   05/23/1995 JLB : Created.                                                                 *
   2385  *=============================================================================================*/
   2386 bool CellClass::Flag_Place(HousesType house)
   2387 {
   2388 	Validate();
   2389 	if (!IsFlagged && Is_Generally_Clear()) {
   2390 		IsFlagged = true;
   2391 		Owner = house;
   2392 		Flag_Update();
   2393 		Redraw_Objects();
   2394 		return(true);
   2395 	}
   2396 	return(false);
   2397 }
   2398 
   2399 
   2400 /***********************************************************************************************
   2401  * CellClass::Flag_Remove -- Removes the house flag from the cell.                             *
   2402  *                                                                                             *
   2403  *    This routine will free the cell of any house flag that may be located there.             *
   2404  *                                                                                             *
   2405  * INPUT:   none                                                                               *
   2406  *                                                                                             *
   2407  * OUTPUT:  Was there a flag here that was removed?                                            *
   2408  *                                                                                             *
   2409  * WARNINGS:   none                                                                            *
   2410  *                                                                                             *
   2411  * HISTORY:                                                                                    *
   2412  *   05/23/1995 JLB : Created.                                                                 *
   2413  *=============================================================================================*/
   2414 bool CellClass::Flag_Remove(void)
   2415 {
   2416 	Validate();
   2417 	if (IsFlagged) {
   2418 		IsFlagged = false;
   2419 		Owner = HOUSE_NONE;
   2420 		Flag_Update();
   2421 		Redraw_Objects();
   2422 		return(true);
   2423 	}
   2424 	return(false);
   2425 }
   2426 
   2427 
   2428 void CellClass::Flag_Update(void)
   2429 {
   2430 	if (IsFlagged && !CTFFlag) {
   2431 		Flag_Create();
   2432 	} else if (!IsFlagged && CTFFlag) {
   2433 		Flag_Destroy();
   2434 	}
   2435 }
   2436 
   2437 
   2438 void CellClass::Flag_Create(void)
   2439 {
   2440 	if (!CTFFlag) {
   2441 		CTFFlag = new AnimClass(ANIM_FLAG, Cell_Coord(), 0, 1, true);
   2442 		if (CTFFlag == NULL) {
   2443 			for (int i = 0; i < Anims.Count(); ++i) {
   2444 				AnimClass* anim = Anims.Ptr(i);
   2445 				if (*anim != ANIM_FLAG) {
   2446 					anim->Delete_This();
   2447 					break;
   2448 				}
   2449 			}
   2450 			CTFFlag = new AnimClass(ANIM_FLAG, Cell_Coord(), 0, 1, true);
   2451 		}
   2452 		assert(CTFFlag != NULL);
   2453 		CTFFlag->Set_Owner(Owner);
   2454 	}
   2455 }
   2456 
   2457 
   2458 void CellClass::Flag_Destroy(void)
   2459 {
   2460 	delete CTFFlag;
   2461 	CTFFlag = NULL;
   2462 }
   2463 
   2464 
   2465 /***********************************************************************************************
   2466  * CellClass::Shimmer -- Causes all objects in the cell to shimmer.                            *
   2467  *                                                                                             *
   2468  *    This routine is called when some event would cause a momentary disruption in the         *
   2469  *    cloaking device. All objects that are cloaked in the cell will have their cloaking       *
   2470  *    device shimmer.                                                                          *
   2471  *                                                                                             *
   2472  * INPUT:   none                                                                               *
   2473  *                                                                                             *
   2474  * OUTPUT:  none                                                                               *
   2475  *                                                                                             *
   2476  * WARNINGS:   none                                                                            *
   2477  *                                                                                             *
   2478  * HISTORY:                                                                                    *
   2479  *   07/29/1995 JLB : Created.                                                                 *
   2480  *=============================================================================================*/
   2481 void CellClass::Shimmer(void)
   2482 {
   2483 	Validate();
   2484 	ObjectClass * object = Cell_Occupier();
   2485 
   2486 	while (object) {
   2487 		object->Do_Shimmer();
   2488 		object = object->Next;
   2489 	}
   2490 }
   2491 
   2492 
   2493 /***********************************************************************************************
   2494  * CellClass::Cell_Occupier -- Fetches the occupier for the cell.                              *
   2495  *                                                                                             *
   2496  *    This routine returns with the first recorded occupier of this cell. A special validity   *
   2497  *    check is performed to ensure that there are no dead objects still marked on the          *
   2498  *    map.                                                                                     *
   2499  *                                                                                             *
   2500  * INPUT:   none                                                                               *
   2501  *                                                                                             *
   2502  * OUTPUT:  Returns with a pointer to the first occupier object.                               *
   2503  *                                                                                             *
   2504  * WARNINGS:   none                                                                            *
   2505  *                                                                                             *
   2506  * HISTORY:                                                                                    *
   2507  *   08/17/1995 JLB : Created.                                                                 *
   2508  *=============================================================================================*/
   2509 ObjectClass * CellClass::Cell_Occupier(void) const
   2510 {
   2511 	ObjectClass * ptr = OccupierPtr;
   2512 
   2513 	while (ptr && !ptr->IsActive) {
   2514 		ptr = ptr->Next;
   2515 		((ObjectClass *&)OccupierPtr) = 0;
   2516 	}
   2517 
   2518 	return(ptr);
   2519 }
   2520 
   2521 
   2522 
   2523 
   2524 
   2525 
   2526 
   2527 
   2528 
   2529 /*
   2530 **  Additions to CellClass to track visibility per-player. ST - 3/5/2019 3:08PM
   2531 ** 
   2532 ** 
   2533 ** 
   2534 ** 
   2535 ** 
   2536 */
   2537 
   2538 /***********************************************************************************************
   2539  * CellClass::Set_Mapped -- Set the cell mapped for the given player                           *
   2540  *                                                                                             *
   2541  *                                                                                             *
   2542  * HISTORY:                                                                                    *
   2543  *   3/5/2019 3:09PM - ST                                                                      *
   2544  *=============================================================================================*/
   2545 void CellClass::Set_Mapped(HousesType house, bool set)
   2546 {
   2547 	int shift = (int) house;
   2548 	if (set) {
   2549 		IsMappedByPlayerMask |= (1 << shift);
   2550 	} else {
   2551 		IsMappedByPlayerMask &= ~(1 << shift);
   2552 	}	
   2553 }			  
   2554 	
   2555 
   2556 /***********************************************************************************************
   2557  * CellClass::Set_Mapped -- Set the cell mapped for the given player                           *
   2558  *                                                                                             *
   2559  *                                                                                             *
   2560  * HISTORY:                                                                                    *
   2561  *   3/5/2019 3:09PM - ST                                                                      *
   2562  *=============================================================================================*/
   2563 void CellClass::Set_Mapped(HouseClass *player, bool set)
   2564 {
   2565 	if (player && player->Class) {
   2566 		Set_Mapped(player->Class->House, set);
   2567 		if (GameToPlay == GAME_NORMAL && player->IsHuman) {
   2568 			IsMapped = set;			// Also set the regular flag in single player
   2569 		}
   2570 	}
   2571 }			  
   2572 
   2573 /***********************************************************************************************
   2574  * CellClass::Is_Mapped -- Is the cell mapped for the given player                             *
   2575  *                                                                                             *
   2576  *                                                                                             *
   2577  * HISTORY:                                                                                    *
   2578  *   3/5/2019 3:13PM - ST                                                                      *
   2579  *=============================================================================================*/
   2580 bool CellClass::Is_Mapped(HousesType house) const
   2581 {
   2582 	int shift = (int) house;
   2583 	return (IsMappedByPlayerMask & (1 << shift)) ? true : false;
   2584 }			  
   2585 
   2586 /***********************************************************************************************
   2587  * CellClass::Is_Mapped -- Is the cell mapped for the given player                             *
   2588  *                                                                                             *
   2589  *                                                                                             *
   2590  * HISTORY:                                                                                    *
   2591  *   3/5/2019 3:13PM - ST                                                                      *
   2592  *=============================================================================================*/
   2593 bool CellClass::Is_Mapped(HouseClass *player) const
   2594 {
   2595 	if (player && player->Class) {
   2596 		return Is_Mapped(player->Class->House);
   2597 	}
   2598 	return false;
   2599 }			  
   2600 
   2601 /***********************************************************************************************
   2602  * CellClass::Set_Visible -- Set the cell visible for the given player                         *
   2603  *                                                                                             *
   2604  *                                                                                             *
   2605  * HISTORY:                                                                                    *
   2606  *   3/5/2019 3:16PM - ST                                                                      *
   2607  *=============================================================================================*/
   2608 void CellClass::Set_Visible(HousesType house, bool set)
   2609 {
   2610 	int shift = (int) house;
   2611 	if (set) {
   2612 		IsVisibleByPlayerMask |= (1 << shift);
   2613 	} else {
   2614 		IsVisibleByPlayerMask &= ~(1 << shift);
   2615 	}	
   2616 }			  
   2617 
   2618 
   2619 /***********************************************************************************************
   2620  * CellClass::Set_Visible -- Set the cell visible for the given player                         *
   2621  *                                                                                             *
   2622  *                                                                                             *
   2623  * HISTORY:                                                                                    *
   2624  *   3/5/2019 3:16PM - ST                                                                      *
   2625  *=============================================================================================*/
   2626 void CellClass::Set_Visible(HouseClass *player, bool set)
   2627 {
   2628 	if (player && player->Class) {
   2629 		Set_Visible(player->Class->House, set);
   2630 		if (GameToPlay == GAME_NORMAL && player->IsHuman) {
   2631 			IsVisible = set;			// Also set the regular flag in single player. This is needed for rendering
   2632 		}
   2633 	}
   2634 }			  
   2635 
   2636 /***********************************************************************************************
   2637  * CellClass::Is_Visible -- Is the cell visible for the given player                           *
   2638  *                                                                                             *
   2639  *                                                                                             *
   2640  * HISTORY:                                                                                    *
   2641  *   3/5/2019 3:16PM - ST                                                                      *
   2642  *=============================================================================================*/
   2643 bool CellClass::Is_Visible(HousesType house) const
   2644 {
   2645 	int shift = (int) house;
   2646 	return (IsVisibleByPlayerMask & (1 << shift)) ? true : false;
   2647 }			  
   2648 
   2649 /***********************************************************************************************
   2650  * CellClass::Is_Visible -- Is the cell visible for the given player                           *
   2651  *                                                                                             *
   2652  *                                                                                             *
   2653  * HISTORY:                                                                                    *
   2654  *   3/5/2019 3:16PM - ST                                                                      *
   2655  *=============================================================================================*/
   2656 bool CellClass::Is_Visible(HouseClass *player) const
   2657 {
   2658 	if (player && player->Class) {
   2659 		return Is_Visible(player->Class->House);
   2660 	}
   2661 	return false;
   2662 }			  
   2663 
   2664 void CellClass::Override_Land_Type(LandType type)
   2665 {
   2666 	OverrideLand = type;
   2667 }
   2668 
   2669 #ifdef USE_RA_AI
   2670 
   2671 /*
   2672 ** Addition from Red Alert for AI. ST - 7/24/2019 5:33PM
   2673 */
   2674 /***********************************************************************************************
   2675  * CellClass::Is_Clear_To_Move -- Determines if the cell is generally clear for travel         *
   2676  *                                                                                             *
   2677  *    This routine is called when determining general passability for purposes of zone         *
   2678  *    calculation. Only blockages that cannot be circumvented are considered to make a cell    *
   2679  *    impassable. All other obstructions can either be destroyed or are temporary.             *
   2680  *                                                                                             *
   2681  * INPUT:   loco     -- The locomotion type to use when determining passablility.              *
   2682  *                                                                                             *
   2683  *          ignoreinfantry -- Should infantry in the cell be ignored for movement purposes?    *
   2684  *                                                                                             *
   2685  *          ignorevehicles -- If vehicles should be ignored, then this flag will be true.      *
   2686  *                                                                                             *
   2687  *          zone     -- If specified, the zone must match this value or else movement is       *
   2688  *                      presumed disallowed.                                                   *
   2689  *                                                                                             *
   2690  *          check    -- This specifies the zone type that this check applies to.               *
   2691  *                                                                                             *
   2692  * OUTPUT:  Is the cell generally passable to ground targeting?                                *
   2693  *                                                                                             *
   2694  * WARNINGS:   none                                                                            *
   2695  *                                                                                             *
   2696  * HISTORY:                                                                                    *
   2697  *   09/25/1995 JLB : Created.                                                                 *
   2698  *   06/25/1996 JLB : Uses tracked vehicles as a basis for zone check.                         *
   2699  *   10/05/1996 JLB : Allows checking for crushable blockages.                                 *
   2700  *=============================================================================================*/
   2701 bool CellClass::Is_Clear_To_Move(bool ignoreinfantry, bool ignorevehicles) const
   2702 {
   2703 	//assert((unsigned)Cell_Number() <= MAP_CELL_TOTAL);
   2704 
   2705 	/*
   2706 	**	Flying objects always consider every cell passable since they can fly over everything.
   2707 	*/
   2708 	//if (loco == SPEED_WINGED) {
   2709 	//	return(true);
   2710 	//}
   2711 
   2712 	/*
   2713 	**	If a zone was specified, then see if the cell is in a legal
   2714 	**	zone to allow movement.
   2715 	*/
   2716 	//if (zone != -1) {
   2717 	//	if (zone != Zones[check]) {
   2718 	//		return(false);
   2719 	//	}
   2720 	//}
   2721 
   2722 	/*
   2723 	**	Check the occupy bits for passable legality. If ignore infantry is true, then
   2724 	**	don't consider infnatry.
   2725 	*/
   2726 	int composite = Flag.Composite;
   2727 	if (ignoreinfantry) {
   2728 		composite &= 0xE0;			// Drop the infantry occupation bits.
   2729 	}
   2730 	if (ignorevehicles) {
   2731 		composite &= 0x5F;			// Drop the vehicle/building bit.
   2732 	}
   2733 	if (composite != 0) {
   2734 		return(false);
   2735 	}
   2736 
   2737 	/*
   2738 	**	Fetch the land type of the cell -- to be modified and used later.
   2739 	*/
   2740 	//LandType land = Land_Type();
   2741 
   2742 	/*
   2743 	**	Walls are always considered to block the terrain for general passability
   2744 	**	purposes unless this is a wall crushing check or if the checking object
   2745 	**	can destroy walls.
   2746 	*/
   2747 	OverlayTypeClass const * overlay = NULL;
   2748 	if (Overlay != OVERLAY_NONE) {
   2749 	 	overlay = &OverlayTypeClass::As_Reference(Overlay);
   2750 	}
   2751 	if (overlay != NULL && overlay->IsWall) {
   2752 		//if (check != MZONE_DESTROYER && (check != MZONE_CRUSHER || !overlay->IsCrushable)) {
   2753 			return(false);
   2754 		//}
   2755 
   2756 		/*
   2757 		**	Crushing objects consider crushable walls as clear rather than the
   2758 		**	typical LAND_WALL setting.
   2759 		*/
   2760 		//land = LAND_CLEAR;
   2761 	}
   2762 
   2763 	/*
   2764 	**	See if the ground type is impassable to this locomotion type and if
   2765 	**	so, return the error condition.
   2766 	*/
   2767 	//if (::Ground[land].Cost[loco] == 0) {
   2768 	//	return(false);
   2769 	//}
   2770 
   2771 	/*
   2772 	**	All checks passed, so this cell must be passable.
   2773 	*/
   2774 	return(true);
   2775 }
   2776 
   2777 #endif //USE_RA_AI