CnC_Remastered_Collection

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

TERRAIN.CPP (51674B)


      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\terrain.cpv   2.16   16 Oct 1995 16:51:44   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 : TERRAIN.CPP                                                  *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : April 29, 1994                                               *
     28  *                                                                                             *
     29  *                  Last Update : May 8, 1995 [JLB]                                            *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   TerrainClass::AI -- Process the terrain object AI.                                        *
     34  *   TerrainClass::As_Target -- Converts the terrain object into a target number.              *
     35  *   TerrainClass::Can_Enter_Cell -- Determines if the terrain object can exist in the cell.   *
     36  *   TerrainClass::Catch_Fire -- Catches the terrain object on fire.                           *
     37  *   TerrainClass::Center_Coord -- Fetches the center point coordinate for terrain object.     *
     38  *   TerrainClass::Debug_Dump -- Displays the status of the terrain object.                    *
     39  *   TerrainClass::Draw_It -- Renders the terrain object at the location specified.            *
     40  *   TerrainClass::Fire_Out -- Handles when fire has gone out.                                 *
     41  *   TerrainClass::Heath_Ratio -- Determines the health ratio for the terrain object.          *
     42  *   TerrainClass::Init -- Initialize the terrain object tracking system.                      *
     43  *   TerrainClass::Limbo -- Handles terrain specific limbo action.                             *
     44  *   TerrainClass::Mark -- Marks the terrain object on the map.                                *
     45  *   TerrainClass::Radar_Icon -- Fetches pointer to radar icon to use.                         *
     46  *   TerrainClass::Read_INI -- Reads terrain objects from INI file.                            *
     47  *   TerrainClass::Start_To_Crumble -- Initiates crumbling of terrain (tree) object.           *
     48  *   TerrainClass::Take_Damage -- Damages the terrain object as specified.                     *
     49  *   TerrainClass::TerrainClass -- Constructor for a terrain class object.                     *
     50  *   TerrainClass::TerrainClass -- This is the constructor for a terrain object.               *
     51  *   TerrainClass::Unlimbo -- Unlimbo terrain object onto the map.                             *
     52  *   TerrainClass::Write_INI -- Writes all terrain objects to the INI file.                    *
     53  *   TerrainClass::delete -- Deletes a terrain object.                                         *
     54  *   TerrainClass::new -- Creates a new terrain object.                                        *
     55  *   TerrainClass::~TerrainClass -- Default destructor for terrain class objects.              *
     56  *   TerrainClass::Validate -- validates terrain pointer													  *
     57  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     58 
     59 #include	"function.h"
     60 #include	"terrain.h"
     61 
     62 #define	BARNACLE_STAGE			22
     63 #define	FIRST_SPORE_STAGE		30
     64 #define	FIRST_SPORABLE_LEVEL	7
     65 
     66 /*
     67 ** This contains the value of the Virtual Function Table Pointer
     68 */
     69 void * TerrainClass::VTable;
     70 
     71 
     72 /***********************************************************************************************
     73  * TerrainClass::Validate -- validates terrain pointer													  *
     74  *                                                                                             *
     75  * INPUT:                                                                                      *
     76  *		none.																												  *
     77  *                                                                                             *
     78  * OUTPUT:                                                                                     *
     79  *		1 = ok, 0 = error																								  *
     80  *                                                                                             *
     81  * WARNINGS:                                                                                   *
     82  *		none.																												  *
     83  *                                                                                             *
     84  * HISTORY:                                                                                    *
     85  *   08/09/1995 BRR : Created.                                                                 *
     86  *=============================================================================================*/
     87 #ifdef CHEAT_KEYS
     88 int TerrainClass::Validate(void) const
     89 {
     90 	int num;
     91 
     92 	num = Terrains.ID(this);
     93 	if (num < 0 || num >= TERRAIN_MAX) {
     94 		Validate_Error("TERRAIN");
     95 		return (0);
     96 	}
     97 	else
     98 		return (1);
     99 }
    100 #else
    101 #define	Validate()
    102 #endif
    103 
    104 
    105 /***********************************************************************************************
    106  * TerrainClass::~TerrainClass -- Default destructor for terrain class objects.                *
    107  *                                                                                             *
    108  *    This is the default destructor for terrain objects. It will remove the object from the   *
    109  *    map and tracking systems, but only if the game is running. Otherwise, it does nothing.   *
    110  *                                                                                             *
    111  * INPUT:   none                                                                               *
    112  *                                                                                             *
    113  * OUTPUT:  none                                                                               *
    114  *                                                                                             *
    115  * WARNINGS:   none                                                                            *
    116  *                                                                                             *
    117  * HISTORY:                                                                                    *
    118  *   01/23/1995 JLB : Created.                                                                 *
    119  *=============================================================================================*/
    120 TerrainClass::~TerrainClass(void)
    121 {
    122 	if (GameActive && Class) {
    123 		TerrainClass::Limbo();
    124 	}
    125 }
    126 
    127 
    128 /***********************************************************************************************
    129  * TerrainClass::Take_Damage -- Damages the terrain object as specified.                       *
    130  *                                                                                             *
    131  *    This routine is called when damage is to be inflicted upon the terrain object. It is     *
    132  *    through this routine that terrain objects are attacked and thereby destroyed. Not all    *
    133  *    terrain objects can be damaged by this routine however.                                  *
    134  *                                                                                             *
    135  * INPUT:   damage      -- The damage points to inflict (raw).                                 *
    136  *                                                                                             *
    137  *          warhead     -- The warhead type the indicates the kind of damage. This is used to  *
    138  *                         determine if the terrain object is damaged and if so, by how much.  *
    139  *                                                                                             *
    140  * OUTPUT:  bool; Was the terrain object destroyed by this damage?                             *
    141  *                                                                                             *
    142  * WARNINGS:   none                                                                            *
    143  *                                                                                             *
    144  * HISTORY:                                                                                    *
    145  *   09/24/1994 JLB : Created.                                                                 *
    146  *   11/22/1994 JLB : Shares base damage handler for techno objects.                           *
    147  *   12/11/1994 JLB : Shortens attached burning animations.                                    *
    148  *=============================================================================================*/
    149 ResultType TerrainClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source)
    150 {
    151 	Validate();
    152 	ResultType res = RESULT_NONE;
    153 
    154 	/*
    155 	**	Small arms can never destroy a terrain element.
    156 	*/
    157 	if ((!IsOnFire || warhead == WARHEAD_FIRE) && warhead != WARHEAD_SA && !Class->IsImmune) {
    158 
    159 		res = ObjectClass::Take_Damage(damage, distance, warhead, source);
    160 
    161 		if (damage && warhead == WARHEAD_FIRE) {
    162 			Catch_Fire();
    163 		}
    164 
    165 		/*
    166 		**	If the terrain object is destroyed by this damage, then only remove it if it
    167 		**	currently isn't on fire and isn't in the process of crumbling.
    168 		*/
    169 		if (res == RESULT_DESTROYED) {
    170 
    171 			/*
    172 			**	Remove this terrain object from the targeting computers of all other
    173 			**	game objects. No use beating a dead horse.
    174 			*/
    175 			Detach_All();
    176 
    177 			if (IsOnFire) {
    178 
    179 				/*
    180 				**	Attached flame animation should be shortened as much as possible so that
    181 				**	crumbling can begin soon.
    182 				*/
    183 				Shorten_Attached_Anims(this);
    184 			} else {
    185 				Start_To_Crumble();
    186 			}
    187 		}
    188 	}
    189 	return(res);
    190 }
    191 
    192 
    193 /***********************************************************************************************
    194  * TerrainClass::As_Target -- Converts the terrain object into a target number.                *
    195  *                                                                                             *
    196  *    This routine will take the terrain object and generate a unique targeting number. This   *
    197  *    number is used for the NavCom and TarCom of other units.                                 *
    198  *                                                                                             *
    199  * INPUT:   none                                                                               *
    200  *                                                                                             *
    201  * OUTPUT:  Returns with the target number of this terrain object.                             *
    202  *                                                                                             *
    203  * WARNINGS:   none                                                                            *
    204  *                                                                                             *
    205  * HISTORY:                                                                                    *
    206  *   09/24/1994 JLB : Created.                                                                 *
    207  *=============================================================================================*/
    208 TARGET TerrainClass::As_Target(void) const
    209 {
    210 	Validate();
    211 	return(Build_Target(KIND_TERRAIN, Terrains.ID(this)));
    212 }
    213 
    214 
    215 /***********************************************************************************************
    216  * TerrainClass::new -- Creates a new terrain object.                                          *
    217  *                                                                                             *
    218  *    This routine creates a new terrain object by grabbing a free slot                        *
    219  *    out of the terrain object pool.                                                          *
    220  *                                                                                             *
    221  * INPUT:   none                                                                               *
    222  *                                                                                             *
    223  * OUTPUT:  Returns with a pointer to the terrain object allocated.                            *
    224  *                                                                                             *
    225  * WARNINGS:   none                                                                            *
    226  *                                                                                             *
    227  * HISTORY:                                                                                    *
    228  *   05/14/1994 JLB : Created.                                                                 *
    229  *=============================================================================================*/
    230 void * TerrainClass::operator new(size_t)
    231 {
    232 	void * ptr = Terrains.Allocate();
    233 	if (ptr) {
    234 		((TerrainClass *)ptr)->Set_Active();
    235 	}
    236 	return(ptr);
    237 }
    238 
    239 
    240 /***********************************************************************************************
    241  * TerrainClass::delete -- Deletes a terrain object.                                           *
    242  *                                                                                             *
    243  *    This routine deletes a terrain object by returning it to the                             *
    244  *    terrain object pool.                                                                     *
    245  *                                                                                             *
    246  * INPUT:   ptr   -- Pointer to the terrain object to delete.                                  *
    247  *                                                                                             *
    248  * OUTPUT:  none                                                                               *
    249  *                                                                                             *
    250  * WARNINGS:   none                                                                            *
    251  *                                                                                             *
    252  * HISTORY:                                                                                    *
    253  *   05/14/1994 JLB : Created.                                                                 *
    254  *=============================================================================================*/
    255 void TerrainClass::operator delete(void *ptr)
    256 {
    257 	if (ptr) {
    258 		((TerrainClass *)ptr)->IsActive = false;
    259 	}
    260 	Terrains.Free((TerrainClass *)ptr);
    261 }
    262 
    263 
    264 /***********************************************************************************************
    265  * TerrainClass::TerrainClass -- This is the constructor for a terrain object                  *
    266  *                                                                                             *
    267  *    This constructor for a terrain object will initialize the terrain                        *
    268  *    object with it's proper type and insert it into the access                               *
    269  *    tracking system.                                                                         *
    270  *                                                                                             *
    271  * INPUT:   type  -- The terrain object type.                                                  *
    272  *                                                                                             *
    273  *          cell  -- The location of the terrain object.                                       *
    274  *                                                                                             *
    275  * OUTPUT:  none                                                                               *
    276  *                                                                                             *
    277  * WARNINGS:   none                                                                            *
    278  *                                                                                             *
    279  * HISTORY:                                                                                    *
    280  *   05/02/1994 JLB : Created.                                                                 *
    281  *=============================================================================================*/
    282 TerrainClass::TerrainClass(TerrainType type, CELL cell) :
    283 	Class(&TerrainTypeClass::As_Reference(type))
    284 {
    285 	IsBlossoming = false;
    286 	IsBarnacled = false;
    287 	IsSporing = false;
    288 	IsCrumbling = false;
    289 	IsOnFire = false;
    290 	Strength = Class->MaxStrength;
    291 	if (cell != -1) {
    292 		if (!Unlimbo(Cell_Coord(cell))) {
    293 			delete this;
    294 		}
    295 	}
    296 	Set_Rate(0);	// turn off animation
    297 }
    298 
    299 
    300 /***********************************************************************************************
    301  * TerrainClass::Mark -- Marks the terrain object on the map.                                  *
    302  *                                                                                             *
    303  *    This routine will mark or remove the terrain object from the map                         *
    304  *    tracking system. This is typically called when the terrain object                        *
    305  *    is first created, when it is destroyed, and whenever it needs to be                      *
    306  *    redrawn.                                                                                 *
    307  *                                                                                             *
    308  * INPUT:   mark  -- The marking operation to perform.                                         *
    309  *                                                                                             *
    310  * OUTPUT:  bool; Was the terrain object successfully marked?                                  *
    311  *                                                                                             *
    312  * WARNINGS:   none                                                                            *
    313  *                                                                                             *
    314  * HISTORY:                                                                                    *
    315  *   05/02/1994 JLB : Created.                                                                 *
    316  *   12/23/1994 JLB : Performs low level legality check before proceeding.                     *
    317  *=============================================================================================*/
    318 bool TerrainClass::Mark(MarkType mark)
    319 {
    320 	Validate();
    321 	if (ObjectClass::Mark(mark)) {
    322 		short const *overlap = Class->Overlap_List();
    323 		short const *occupy = Class->Occupy_List();
    324 		CELL cell = Coord_Cell(Coord);
    325 
    326 		switch (mark) {
    327 			case MARK_UP:
    328 				Map.Pick_Up(cell, this);
    329 				break;
    330 
    331 			case MARK_DOWN:
    332 				Map.Place_Down(cell, this);
    333 				break;
    334 
    335 			default:
    336 				Map.Refresh_Cells(cell, overlap);
    337 				Map.Refresh_Cells(cell, occupy);
    338 				break;
    339 		}
    340 		return(true);
    341 	}
    342 	return(false);
    343 }
    344 
    345 
    346 /***********************************************************************************************
    347  * TerrainClass::Draw_It -- Renders the terrain object at the location specified.              *
    348  *                                                                                             *
    349  *    This routine is used to render the terrain object at the location specified and          *
    350  *    clipped to the window specified. This is the gruntwork drawing routine for the           *
    351  *    terrain objects as they are displayed on the map.                                        *
    352  *                                                                                             *
    353  * INPUT:   x,y      -- The coordinate to draw the terrain object at (centered).               *
    354  *                                                                                             *
    355  *          window   -- The clipping window to draw to.                                        *
    356  *                                                                                             *
    357  * OUTPUT:  none                                                                               *
    358  *                                                                                             *
    359  * WARNINGS:   none                                                                            *
    360  *                                                                                             *
    361  * HISTORY:                                                                                    *
    362  *   06/27/1994 JLB : Created.                                                                 *
    363  *   11/09/1994 JLB : Changed selected terrain highlight method.                               *
    364  *=============================================================================================*/
    365 void TerrainClass::Draw_It(int x, int y, WindowNumberType window)
    366 {
    367 	Validate();
    368 	void const * shapedata;
    369 
    370 	shapedata = Class->Get_Image_Data();
    371 	if (shapedata) {
    372 		int	shapenum = 0;
    373 
    374 		/*
    375 		**	Determine the animation stage to render the terrain object. If it is crumbling, then
    376 		**	it will display the crumbling animation.
    377 		*/
    378 		if (IsCrumbling || Class->IsTransformable) {
    379 			shapenum = Fetch_Stage()+IsCrumbling;
    380 		} else {
    381 			if (Strength < 2) {
    382 				shapenum++;
    383 			}
    384 		}
    385 
    386 		ShapeFlags_Type flags = SHAPE_NORMAL;
    387 		if (Is_Selected_By_Player() && Debug_Map) flags = flags | SHAPE_FADING;
    388 
    389 		IsTheaterShape = true;
    390 		CC_Draw_Shape(this, shapedata, shapenum, x, y, window, flags|SHAPE_WIN_REL|SHAPE_GHOST, Map.FadingLight, Map.UnitShadow);
    391 		IsTheaterShape = false;
    392 	}
    393 }
    394 
    395 
    396 /***********************************************************************************************
    397  * TerrainClass::Init -- Initialize the terrain object tracking system.                        *
    398  *                                                                                             *
    399  *    This routine will clear out the terrain object system so that no terrain objects will    *
    400  *    exists. It is called prior to loading or starting a scenario.                            *
    401  *                                                                                             *
    402  * INPUT:   none                                                                               *
    403  *                                                                                             *
    404  * OUTPUT:  none                                                                               *
    405  *                                                                                             *
    406  * WARNINGS:   none                                                                            *
    407  *                                                                                             *
    408  * HISTORY:                                                                                    *
    409  *   09/24/1994 JLB : Created.                                                                 *
    410  *=============================================================================================*/
    411 void TerrainClass::Init(void)
    412 {
    413 	TerrainClass *ptr;
    414 
    415 	Terrains.Free_All();
    416 
    417 	ptr = new TerrainClass();
    418 	VTable = ((void **)(((char *)ptr) + sizeof(AbstractClass) - 4))[0];
    419 	delete ptr;
    420 }
    421 
    422 
    423 /***********************************************************************************************
    424  * TerrainClass::Can_Enter_Cell -- Determines if the terrain object can exist in the cell.     *
    425  *                                                                                             *
    426  *    This routine will examine the cell specified and determine if the the terrain object     *
    427  *    can legally exist there.                                                                 *
    428  *                                                                                             *
    429  * INPUT:   cell  -- The cell to examine.                                                      *
    430  *                                                                                             *
    431  * OUTPUT:  If the terrain object can be placed in the cell specified, then a value less than  *
    432  *          256 will be returned.                                                              *
    433  *                                                                                             *
    434  * WARNINGS:   none                                                                            *
    435  *                                                                                             *
    436  * HISTORY:                                                                                    *
    437  *   09/24/1994 JLB : Created.                                                                 *
    438  *   01/01/1995 JLB : Actually works now.                                                      *
    439  *=============================================================================================*/
    440 MoveType TerrainClass::Can_Enter_Cell(CELL cell, FacingType) const
    441 {
    442 	Validate();
    443 	short const	*offset;		// Pointer to cell offset list.
    444 
    445 	if ((unsigned)cell >= MAP_CELL_TOTAL) return(MOVE_NO);
    446 
    447 	offset = Occupy_List();
    448 	while (*offset != REFRESH_EOL) {
    449 		if (!Map[(CELL)(cell + *offset++)].Is_Generally_Clear()) {
    450 			return(MOVE_NO);
    451 		}
    452 	}
    453 	return(MOVE_OK);
    454 }
    455 
    456 
    457 /***********************************************************************************************
    458  * TerrainClass::Catch_Fire -- Catches the terrain object on fire.                             *
    459  *                                                                                             *
    460  *    This routine is called if the terrain object is supposed to catch on fire. The routine   *
    461  *    performs checking to make sure that only flammable terrain objects that aren't already   *
    462  *    on fire get caught on fire.                                                              *
    463  *                                                                                             *
    464  * INPUT:   none                                                                               *
    465  *                                                                                             *
    466  * OUTPUT:  bool; Was the terrain object caught on fire by this routine?                       *
    467  *                                                                                             *
    468  * WARNINGS:   none                                                                            *
    469  *                                                                                             *
    470  * HISTORY:                                                                                    *
    471  *   09/27/1994 JLB : Created.                                                                 *
    472  *   12/11/1994 JLB : Don't catch fire if already on fire or crumbling.                        *
    473  *=============================================================================================*/
    474 bool TerrainClass::Catch_Fire(void)
    475 {
    476 	Validate();
    477 	if (!IsCrumbling && !IsOnFire && Class->IsFlammable) {
    478 		AnimClass * anim = new AnimClass(ANIM_BURN_BIG, Coord_Add(Sort_Y(), 0xFFB00000L));
    479 		if (anim) {
    480 			anim->Attach_To(this);
    481 		}
    482 		anim = new AnimClass(ANIM_BURN_MED, Coord_Add(Sort_Y(), 0xFF200000L), 15);
    483 		if (anim) {
    484 			anim->Attach_To(this);
    485 		}
    486 		IsOnFire = true;
    487 		return(true);
    488 	}
    489 	return(false);
    490 }
    491 
    492 
    493 /***********************************************************************************************
    494  * TerrainClass::Fire_Out -- Handles when fire has gone out.                                   *
    495  *                                                                                             *
    496  *    When the fire has gone out on a burning terrain object, this routine is called. The      *
    497  *    animation has already been terminated prior to calling this routine. All this routine    *
    498  *    needs to perform is any necessary local flag updating.                                   *
    499  *                                                                                             *
    500  * INPUT:   none                                                                               *
    501  *                                                                                             *
    502  * OUTPUT:  none                                                                               *
    503  *                                                                                             *
    504  * WARNINGS:   none                                                                            *
    505  *                                                                                             *
    506  * HISTORY:                                                                                    *
    507  *   09/27/1994 JLB : Created.                                                                 *
    508  *=============================================================================================*/
    509 void TerrainClass::Fire_Out(void)
    510 {
    511 	Validate();
    512 	if (IsOnFire) {
    513 		IsOnFire = false;
    514 		if (!IsCrumbling && !Strength) {
    515 			Detach_All();
    516 			Mark();
    517 			Start_To_Crumble();
    518 			new AnimClass(ANIM_SMOKE_M, Coord_Add(Coord, Class->CenterBase));
    519 		}
    520 	}
    521 }
    522 
    523 
    524 /***********************************************************************************************
    525  * TerrainClass::AI -- Process the terrain object AI.                                          *
    526  *                                                                                             *
    527  *    This is used to handle any AI processing necessary for terrain objects. This might       *
    528  *    include animation effects.                                                               *
    529  *                                                                                             *
    530  * INPUT:   none                                                                               *
    531  *                                                                                             *
    532  * OUTPUT:  none                                                                               *
    533  *                                                                                             *
    534  * WARNINGS:   none                                                                            *
    535  *                                                                                             *
    536  * HISTORY:                                                                                    *
    537  *   09/27/1994 JLB : Created.                                                                 *
    538  *   09/28/1994 JLB : Crumbling animation.                                                     *
    539  *=============================================================================================*/
    540 void TerrainClass::AI(void)
    541 {
    542 	Validate();
    543 	ObjectClass::AI();
    544 
    545 	if (StageClass::Graphic_Logic()) {
    546 		Mark();
    547 
    548 		/*
    549 		**	If the terrain object is in the process of crumbling, then when at the
    550 		**	last stage of the crumbling animation, delete the terrain object.
    551 		*/
    552 		if (IsCrumbling && Fetch_Stage() == Get_Build_Frame_Count(Class->Get_Image_Data())-1) {
    553 			delete this;
    554 		}
    555 	}
    556 
    557 	/*
    558 	** if this is a blossom tree, let's update it at this time
    559 	*/
    560 	if (Class->IsTransformable) {
    561 		// If it's already blossomed, is it at barnacled stage?
    562 		if (IsBlossoming) {
    563 			// if it's not barnacled yet, check if we're at that stage
    564 			if (!IsBarnacled) {
    565 				if (Fetch_Stage() == BARNACLE_STAGE) {
    566 					IsBarnacled = true;
    567 					Set_Rate(0);	// turn off animation
    568 				}
    569 			} else {
    570 				/*
    571 				** If it's barnacled, see if it's pulsing and spore-ing
    572 				*/
    573 				if (IsSporing) {
    574 					if (Fetch_Stage() >= Get_Build_Frame_Count(Class->Get_Image_Data())-1) {
    575 						Explosion_Damage(Sort_Y(), 5, NULL, WARHEAD_SPORE);
    576 						Set_Stage(FIRST_SPORE_STAGE);
    577 						if (Random() & 1) {
    578 							IsSporing = false;
    579 							StageClass::Set_Rate(0);
    580 						}
    581 					}
    582 				} else {
    583 					if (Random() == 255) {	// is it time to start sporing?
    584 						IsSporing = true;
    585 						StageClass::Set_Rate(Options.Normalize_Delay(1));
    586 					}
    587 				}
    588 			}
    589 		} else {
    590 
    591 			// If it hasn't tried to blossom yet, can it do so now?
    592 			if (Random_Picky((int)1, (int)5000, (char*)NULL, (int)0) == 1) {
    593 				IsBlossoming = true;
    594 				StageClass::Set_Stage(1);
    595 				StageClass::Set_Rate(Options.Normalize_Delay(1));
    596 			}
    597 		}
    598 	}
    599 }
    600 
    601 
    602 #ifdef CHEAT_KEYS
    603 /***********************************************************************************************
    604  * TerrainClass::Debug_Dump -- Displays the status of the terrain object.                      *
    605  *                                                                                             *
    606  *    This debugging support routine is used to display the status of the terrain object to    *
    607  *    the debug screen.                                                                        *
    608  *                                                                                             *
    609  * INPUT:   mono  -- The mono screen to display the status to.                                 *
    610  *                                                                                             *
    611  * OUTPUT:  none                                                                               *
    612  *                                                                                             *
    613  * WARNINGS:   none                                                                            *
    614  *                                                                                             *
    615  * HISTORY:                                                                                    *
    616  *   09/27/1994 JLB : Created.                                                                 *
    617  *=============================================================================================*/
    618 void TerrainClass::Debug_Dump(MonoClass *mono) const
    619 {
    620 	Validate();
    621 	ObjectClass::Debug_Dump(mono);
    622 }
    623 #endif
    624 
    625 
    626 /***********************************************************************************************
    627  * TerrainClass::Unlimbo -- Unlimbo terrain object onto the map.                               *
    628  *                                                                                             *
    629  *    This routine is used to unlimbo the terrain object onto a location on the map. Normal    *
    630  *    unlimbo procedures are sufficient except that the coordinate location of a terrain       *
    631  *    object is based on the upper left corner of a cell rather than the center. Mask the      *
    632  *    coordinate value so that it snaps to the upper left corner and then proceed with a       *
    633  *    normal unlimbo process.                                                                  *
    634  *                                                                                             *
    635  * INPUT:   coord    -- The coordinate to mark as the terrain's location.                      *
    636  *                                                                                             *
    637  *          dir      -- unused                                                                 *
    638  *                                                                                             *
    639  * OUTPUT:  bool; Was the terrain object successful in the unlimbo process? Failure could be   *
    640  *                the result of illegal positioning.                                           *
    641  *                                                                                             *
    642  * WARNINGS:   none                                                                            *
    643  *                                                                                             *
    644  * HISTORY:                                                                                    *
    645  *   11/02/1994 JLB : Created.                                                                 *
    646  *   11/16/1994 JLB : Checks for theater legality.                                             *
    647  *=============================================================================================*/
    648 bool TerrainClass::Unlimbo(COORDINATE coord, DirType dir)
    649 {
    650 	Validate();
    651 	if (Class->Theater & (1 << Map.Theater)) {
    652 		return(ObjectClass::Unlimbo(coord, dir));
    653 	}
    654 	return(false);
    655 }
    656 
    657 
    658 /***********************************************************************************************
    659  * TerrainClass::Start_To_Crumble -- Initiates crumbling of terrain (tree) object.             *
    660  *                                                                                             *
    661  *    This routine is used to start the crumbling process for terrain object. This only        *
    662  *    applies to trees.                                                                        *
    663  *                                                                                             *
    664  * INPUT:   none                                                                               *
    665  *                                                                                             *
    666  * OUTPUT:  none                                                                               *
    667  *                                                                                             *
    668  * WARNINGS:   none                                                                            *
    669  *                                                                                             *
    670  * HISTORY:                                                                                    *
    671  *   12/22/1994 JLB : Created.                                                                 *
    672  *=============================================================================================*/
    673 void TerrainClass::Start_To_Crumble(void)
    674 {
    675 	Validate();
    676 	if (!IsCrumbling) {
    677 		IsCrumbling = true;
    678 		Set_Rate(2);
    679 		Set_Stage(0);
    680 	}
    681 }
    682 
    683 
    684 /***********************************************************************************************
    685  * TerrainClass::Limbo -- Handles terrain specific limbo action.                               *
    686  *                                                                                             *
    687  *    This routine (called as a part of the limbo process) will remove the terrain occupation  *
    688  *    flag in the cell it occupies.                                                            *
    689  *                                                                                             *
    690  * INPUT:   none                                                                               *
    691  *                                                                                             *
    692  * OUTPUT:  bool; Was the terrain object unlimboed?                                            *
    693  *                                                                                             *
    694  * WARNINGS:   none                                                                            *
    695  *                                                                                             *
    696  * HISTORY:                                                                                    *
    697  *   12/22/1994 JLB : Created.                                                                 *
    698  *=============================================================================================*/
    699 bool TerrainClass::Limbo(void)
    700 {
    701 	Validate();
    702 	if (!IsInLimbo) {
    703 		CELL cell = Coord_Cell(Coord);
    704 		Map[cell].Flag.Occupy.Monolith = false;
    705 	}
    706 	return(ObjectClass::Limbo());
    707 }
    708 
    709 
    710 /***********************************************************************************************
    711  * TerrainClass::Center_Coord -- Fetches the center point coordinate for terrain object.       *
    712  *                                                                                             *
    713  *    Use this routine to fetch the center point terrain                                       *
    714  *                                                                                             *
    715  * INPUT:                                                                                      *
    716  *                                                                                             *
    717  * OUTPUT:                                                                                     *
    718  *                                                                                             *
    719  * WARNINGS:                                                                                   *
    720  *                                                                                             *
    721  * HISTORY:                                                                                    *
    722  *   01/23/1995 JLB : Created.                                                                 *
    723  *=============================================================================================*/
    724 COORDINATE TerrainClass::Center_Coord(void) const
    725 {
    726 	Validate();
    727 	return(Coord_Add(Coord, Class->CenterBase));
    728 }
    729 
    730 
    731 /***********************************************************************************************
    732  * TerrainClass::TerrainClass -- Constructor for a terrain class object.                       *
    733  *                                                                                             *
    734  *    This is the default constructor for a terrain class object. It basically initializes     *
    735  *    the object to a null -- do nothing -- state.                                             *
    736  *                                                                                             *
    737  * INPUT:   none                                                                               *
    738  *                                                                                             *
    739  * OUTPUT:  none                                                                               *
    740  *                                                                                             *
    741  * WARNINGS:   none                                                                            *
    742  *                                                                                             *
    743  * HISTORY:                                                                                    *
    744  *   03/10/1995 JLB : Created.                                                                 *
    745  *=============================================================================================*/
    746 TerrainClass::TerrainClass(void) :
    747 	Class(0)
    748 {
    749 	IsOnFire = false;
    750 	IsCrumbling = false;
    751 	IsBlossoming = false;
    752 	IsBarnacled = false;
    753 	IsSporing = false;
    754 	Strength = 0;
    755 }
    756 
    757 
    758 /***********************************************************************************************
    759  * TerrainClass::Radar_Icon -- Fetches pointer to radar icon to use.                           *
    760  *                                                                                             *
    761  *    This routine will return with a pointer to the radar icon to use for the cell number     *
    762  *    specified.                                                                               *
    763  *                                                                                             *
    764  * INPUT:   cell  -- The cell number to use when determine what icon pointer to return.        *
    765  *                                                                                             *
    766  * OUTPUT:  Returns with a pointer to the 9 pixel values that make up the icon of this         *
    767  *          terrain object located at the cell specified.                                      *
    768  *                                                                                             *
    769  * WARNINGS:   none                                                                            *
    770  *                                                                                             *
    771  * HISTORY:                                                                                    *
    772  *   05/08/1995 JLB : Created.                                                                 *
    773  *=============================================================================================*/
    774 unsigned char * TerrainClass::Radar_Icon(CELL cell)
    775 {
    776 	Validate();
    777 	unsigned char *icon = (unsigned char *)Class->Get_Radar_Data();	// get a pointer to radar icons
    778 	int  width = *icon++;							// extract the width from data
    779 	int  height = *icon++;							// extract the width from data
    780 
    781 	/*
    782 	** Icon number that we need can be found by converting the cell and base
    783 	** cell to and x and y offset from the upper left of the cell, and then
    784 	** multiplying it by the width of the terrain in icons, which we
    785 	** conveniantly stored out as the first byte of every icon we made.
    786 	*/
    787 	int basecell = Coord_Cell(Coord);				// find the base cell of terrain
    788 	int ydiff = Cell_Y(cell) - Cell_Y(basecell);
    789 	int xdiff = Cell_X(cell) - Cell_X(basecell);
    790 	if (xdiff < width && ydiff < height) {
    791 		int iconnum = (ydiff * width) + xdiff;
    792 		return(icon + (iconnum * 9));
    793 	}
    794 	return(NULL);
    795 }
    796 
    797 
    798 /***********************************************************************************************
    799  * TerrainClass::Read_INI -- Reads terrain objects from INI file.                              *
    800  *                                                                                             *
    801  *    This routine reads a scenario control INI file and creates all                           *
    802  *    terrain objects specified therein. Objects so created are placed                         *
    803  *    upon the map.                                                                            *
    804  *                                                                                             *
    805  *      INI entry format:                                                                      *
    806  *      cellnum = TypeName, Triggername                                                        *
    807  *                                                                                             *
    808  * INPUT:   buffer   -- Pointer to the loaded scenario INI file data.                          *
    809  *                                                                                             *
    810  * OUTPUT:  none                                                                               *
    811  *                                                                                             *
    812  * WARNINGS:   none                                                                            *
    813  *                                                                                             *
    814  * HISTORY:                                                                                    *
    815  *   05/24/1994 JLB : Created.                                                                 *
    816  *=============================================================================================*/
    817 void TerrainClass::Read_INI(char *buffer)
    818 {
    819 	char	*tbuffer;	// Accumulation buffer of unit IDs.
    820 	int	len;			// Size of data in buffer.
    821 	char	buf[128];
    822 	TerrainClass * tptr;
    823 
    824 	len = strlen(buffer) + 2;
    825 	tbuffer = buffer + len;
    826 
    827 	WWGetPrivateProfileString(INI_Name(), NULL, NULL, tbuffer, ShapeBufferSize-len, buffer);
    828 	while (*tbuffer != '\0') {
    829 		TerrainType	terrain;		// Terrain type.
    830 		CELL			cell;
    831 
    832 		cell = atoi(tbuffer);
    833 		WWGetPrivateProfileString(INI_Name(), tbuffer, NULL, buf, sizeof(buf)-1, buffer);
    834 		terrain = TerrainTypeClass::From_Name(strtok(buf, ","));
    835 		if (terrain != TERRAIN_NONE) {
    836 			tptr = new TerrainClass(terrain, cell);
    837 			tptr->Trigger = TriggerClass::As_Pointer(strtok(NULL,","));
    838 			if (tptr->Trigger)
    839 				tptr->Trigger->AttachCount++;
    840 		}
    841 		tbuffer += strlen(tbuffer)+1;
    842 	}
    843 }
    844 
    845 
    846 /***********************************************************************************************
    847  * TerrainClass::Write_INI -- Writes all terrain objects to the INI file.                      *
    848  *                                                                                             *
    849  *    This routine is used to write all the terrain objects out to the INI file specified.     *
    850  *    It is used by the scenario editor to write out the map data.                             *
    851  *                                                                                             *
    852  *      INI entry format:                                                                      *
    853  *      cellnum = TypeName, Triggername                                                        *
    854  *                                                                                             *
    855  * INPUT:   buffer   -- Pointer to the INI file staging area.                                  *
    856  *                                                                                             *
    857  * OUTPUT:  none                                                                               *
    858  *                                                                                             *
    859  * WARNINGS:   none                                                                            *
    860  *                                                                                             *
    861  * HISTORY:                                                                                    *
    862  *   05/28/1994 JLB : Created.                                                                 *
    863  *=============================================================================================*/
    864 void TerrainClass::Write_INI(char *buffer)
    865 {
    866 	int	index;
    867 	char	uname[10];
    868 	char	buf[127];
    869 	char	*tbuffer;		// Accumulation buffer of unit IDs.
    870 
    871 	/*
    872 	**	First, clear out all existing terrain data from the ini file.
    873 	*/
    874 	tbuffer = buffer + strlen(buffer) + 2;
    875 	WWGetPrivateProfileString(INI_Name(), NULL, NULL, tbuffer, ShapeBufferSize-strlen(buffer), buffer);
    876 	while (*tbuffer != '\0') {
    877 		WWWritePrivateProfileString(INI_Name(), tbuffer, NULL, buffer);
    878 		tbuffer += strlen(tbuffer)+1;
    879 	}
    880 
    881 	/*
    882 	**	Write the terrain data out.
    883 	*/
    884 	for (index = 0; index < Terrains.Count(); index++) {
    885 		TerrainClass * terrain;
    886 
    887 		terrain = Terrains.Ptr(index);
    888 		if (!terrain->IsInLimbo && terrain->IsActive) {
    889 
    890 			sprintf(uname, "%d", Coord_Cell(terrain->Coord));
    891 			sprintf(buf, "%s,%s",
    892 				terrain->Class->IniName,
    893 				terrain->Trigger ? terrain->Trigger->Get_Name() : "None" );
    894 			WWWritePrivateProfileString(INI_Name(), uname, buf, buffer);
    895 		}
    896 	}
    897 }