CnC_Remastered_Collection

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

INFANTRY.CPP (143612B)


      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\infantry.cpv   2.19   16 Oct 1995 16:50:30   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 : INFANTRY.CPP                                                 *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : August 15, 1994                                              *
     28  *                                                                                             *
     29  *                  Last Update : August 15, 1995   [JLB]                                      *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   InfantryClass::AI -- Handles the infantry non-graphic related AI processing.              *
     34  *   InfantryClass::Active_Click_With -- Handles action when clicking with infantry soldier.   *
     35  *   InfantryClass::As_Target -- Converts the infantry unit into a target value.               *
     36  *   InfantryClass::Assign_Destination -- Gives the infantry a movement destination.           *
     37  *   InfantryClass::Assign_Mission -- Make sure he's out of boxing mode first                  *
     38  *   InfantryClass::Assign_Target -- Gives the infantry a combat target.                       *
     39  *   InfantryClass::Can_Enter_Cell -- Determines if the infantry can enter the cell specified. *
     40  *   InfantryClass::Can_Fire -- Can the infantry fire its weapon?                              *
     41  *   InfantryClass::Clear_Occupy_Bit -- Clears occupy bit and given cell                       *
     42  *   InfantryClass::Debug_Dump -- Displays debug information about infantry unit.              *
     43  *   InfantryClass::Detach -- Removes the specified target from targeting computer.            *
     44  *   InfantryClass::Do_Action -- Launches the infantry into an animation sequence.             *
     45  *   InfantryClass::Draw_It -- Draws a unit object.                                            *
     46  *   InfantryClass::Enter_Idle_Mode -- The infantry unit enters idle mode by this routine.     *
     47  *   InfantryClass::Fire_At -- Fires projectile from infantry unit.                            *
     48  *   InfantryClass::Fire_Coord -- Calculates the origin point for projectiles fired.           *
     49  *   InfantryClass::Greatest_Threat -- Determines greatest threat (target) for infantry unit.  *
     50  *   InfantryClass::InfantryClass -- The constructor for infantry objects.                     *
     51  *   InfantryClass::Init -- Initialize the infantry object system.                             *
     52  *   InfantryClass::Limbo -- Performs cleanup operations needed when limboing.                 *
     53  *   InfantryClass::Look -- The infantry performs a look operation.                            *
     54  *   InfantryClass::Made_A_Kill -- Marks a kill caused by this infantry soldier.               *
     55  *   InfantryClass::Overlap_List -- The list of cells that the infantry overlaps, but doesn't occ*
     56  *   InfantryClass::Per_Cell_Process -- Handles special operations that occur once per cell.   *
     57  *   InfantryClass::Random_Animate -- Randomly animate the infantry (maybe)                    *
     58  *   InfantryClass::Read_INI -- Reads units from scenario INI file.                            *
     59  *   InfantryClass::Rearm_Delay -- Return Arming delay for infantry if boxing                  *
     60  *   InfantryClass::Receive_Message -- Process radio messages                                  *
     61  *   InfantryClass::Response_Attack -- Plays infantry audio response to attack order.          *
     62  *   InfantryClass::Response_Move -- Plays infantry response to movement order.                *
     63  *   InfantryClass::Response_Select -- Plays infantry audio response due to being selected.    *
     64  *   InfantryClass::Scatter -- Causes the infantry to scatter to nearby cell.                  *
     65  *   InfantryClass::Set_Occupy_Bit -- Sets the occupy bit cell and bit pos	                    *
     66  *   InfantryClass::Set_Primary_Facing -- Change infantry primary facing -- always and instantl*
     67  *   InfantryClass::Start_Driver -- Handles giving immediate destination and move orders.      *
     68  *   InfantryClass::Stop_Driver -- Stops the infantry from moving any further.                 *
     69  *   InfantryClass::Take_Damage -- Applies damage to the infantry unit.                        *
     70  *   InfantryClass::Unlimbo -- Unlimbo infantry unit in legal sub-location.                    *
     71  *   InfantryClass::What_Action -- Infantry units might be able to capture -- check.           *
     72  *   InfantryClass::Write_INI -- Writes all the infantry out to an INI file.                   *
     73  *   InfantryClass::operator delete -- Returns the infantry object back to the free pool       *
     74  *   InfantryClass::operator new -- Allocates an infantry object from the free pool.           *
     75  *   InfantryClass::~InfantryClass -- Default destructor for infantry units.                   *
     76  *   InfantryClass::Full_Name -- Fetches the full name of the infantry unit.                   *
     77  *   InfantryClass::Mission_Attack -- Intercept attack mission for special handling.           *
     78  *   InfantryClass::Validate -- validates infantry pointer.												  *
     79  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     80 
     81 #include	"function.h"
     82 
     83 
     84 int const InfantryClass::HumanShape[32] = {0,0,7,7,7,7,6,6,6,6,5,5,5,5,5,4,4,4,3,3,3,3,2,2,2,2,1,1,1,1,1,0};
     85 
     86 int Infantry_Kick_Damage[]  = {10,15};
     87 int Infantry_Punch_Damage[] = { 4, 7};
     88 
     89 /*
     90 ** This contains the value of the Virtual Function Table Pointer
     91 */
     92 void * InfantryClass::VTable;
     93 
     94 
     95 /***************************************************************************
     96 ** This is the array of constant data associated with infantry maneuvers. It
     97 **	specifies the frame rate as well as if the animation can be aborted.
     98 */
     99 // interruptable, mobile, randomstart, rate
    100 DoStruct const InfantryClass::MasterDoControls[DO_COUNT] = {
    101 	{true,	false,	false,	0},	// DO_STAND_READY
    102 	{true,	false,	false,	0},	// DO_STAND_GUARD
    103 	{true,	false,	false,	0},	// DO_PRONE
    104 	{true,	true,		true,		2},	// DO_WALK
    105 	{true,	false,	false,	1},	// DO_FIRE_WEAPON
    106 	{false,	true,		false,	2},	// DO_LIE_DOWN
    107 	{true,	true,		true,		2},	// DO_CRAWL
    108 	{false,	false,	false,	3},	// DO_GET_UP
    109 	{true,	false,	false,	1},	// DO_FIRE_PRONE
    110 	{true,	false,	false,	2},	// DO_IDLE1
    111 	{true,	false,	false,	2},	// DO_IDLE2
    112 	{false,	false,	false,	2},	// DO_ON_GUARD
    113 	{true,	false,	false,	2},	// DO_FIGHT_READY
    114 	{false,	false,	false,	2},	// DO_PUNCH
    115 	{false,	false,	false,	2},	// DO_KICK
    116 	{false,	false,	false,	2},	// DO_PUNCH_HIT1
    117 	{false,	false,	false,	2},	// DO_PUNCH_HIT2
    118 	{false,	false,	false,	1},	// DO_PUNCH_DEATH
    119 	{false,	false,	false,	2},	// DO_KICK_HIT1
    120 	{false,	false,	false,	2},	// DO_KICK_HIT2
    121 	{false,	false,	false,	1},	// DO_KICK_DEATH
    122 	{false,	false,	false,	2},	// DO_READY_WEAPON
    123 	{false,	false,	false,	2},	// DO_GUN_DEATH
    124 	{false,	false,	false,	2},	// DO_EXPLOSION_DEATH
    125 	{false,	false,	false,	2},	// DO_EXPLOSION2_DEATH
    126 	{false,	false,	false,	2},	// DO_GRENADE_DEATH
    127 	{false,	false,	false,	2},	// DO_FIRE_DEATH
    128 	{false,	false,	false,	2},	// DO_GESTURE1
    129 	{false,	false,	false,	2},	// DO_SALUTE1
    130 	{false,	false,	false,	2},	// DO_GESTURE2
    131 	{false,	false,	false,	2},	// DO_SALUTE2
    132 	{true,	false,	false,	2},	// DO_PULL_GUN
    133 	{true,	false,	false,	2},	// DO_PLEAD
    134 	{true,	false,	false,	2},	// DO_PLEAD_DEATH
    135 };
    136 
    137 
    138 /***********************************************************************************************
    139  * InfantryClass::Validate -- validates infantry pointer.												  *
    140  *                                                                                             *
    141  * INPUT:                                                                                      *
    142  *		none.																												  *
    143  *                                                                                             *
    144  * OUTPUT:                                                                                     *
    145  *		1 = ok, 0 = error																								  *
    146  *                                                                                             *
    147  * WARNINGS:                                                                                   *
    148  *		none.																												  *
    149  *                                                                                             *
    150  * HISTORY:                                                                                    *
    151  *   08/09/1995 BRR : Created.                                                                 *
    152  *=============================================================================================*/
    153 #ifdef CHEAT_KEYS
    154 int InfantryClass::Validate(void) const
    155 {
    156 	int num;
    157 
    158 	num = Infantry.ID(this);
    159 	if (num < 0 || num >= INFANTRY_MAX) {
    160 		Validate_Error("INFANTRY");
    161 		return (0);
    162 	}
    163 	else
    164 		return (1);
    165 }
    166 #else
    167 #define	Validate()
    168 #endif
    169 
    170 
    171 #ifdef CHEAT_KEYS
    172 /***********************************************************************************************
    173  * InfantryClass::Debug_Dump -- Displays debug information about infantry unit.                *
    174  *                                                                                             *
    175  *    This routine is used by the debug version to display pertinent information about the     *
    176  *    infantry unit.                                                                           *
    177  *                                                                                             *
    178  * INPUT:   mono  -- The monochrome screen to display the debug information to.                *
    179  *                                                                                             *
    180  * OUTPUT:  none                                                                               *
    181  *                                                                                             *
    182  * WARNINGS:   none                                                                            *
    183  *                                                                                             *
    184  * HISTORY:                                                                                    *
    185  *   09/01/1994 JLB : Created.                                                                 *
    186  *=============================================================================================*/
    187 void InfantryClass::Debug_Dump(MonoClass *mono) const
    188 {
    189 	Validate();
    190 	mono->Set_Cursor(0, 0);mono->Print(
    191 		"ÚName:ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂMission:ÄÄÄÂTarCom:ÂNavCom:ÂRadio:ÂCoord:ÄÄÂHeadTo:ÄÂSt:Ä¿\n"
    192 		"³                   ³           ³       ³       ³      ³        ³        ³    ³\n"
    193 		"ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂNÂYÂHealth:ÄÂBody:ÂTurret:ÂSpeed:ÂPath:ÁÄÄÄÄÄÄÂCargo:ÄÄÄÄÁÄÄÄÄ´\n"
    194 		"³Active........³ ³ ³        ³     ³       ³      ³            ³               ³\n"
    195 		"³Limbo.........³ ³ ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´\n"
    196 		"³Owned.........³ ³ ³Last Message:                                             ³\n"
    197 		"³Discovered....³ ³ ÃTimer:ÂArm:ÂTrack:ÂTiberium:ÂFlash:ÂStage:ÂTeam:ÄÄÄÄÂArch:´\n"
    198 		"³Selected......³ ³ ³      ³    ³      ³         ³      ³      ³         ³     ³\n"
    199 		"³Teathered.....³ ³ ÃÄÄÄÄÄÄÁÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÙ\n"
    200 		"³Locked on Map.³ ³ ³                                                           \n"
    201 		"³Is Prone......³ ³ ³                                                           \n"
    202 		"³Is A Loner....³ ³ ³                                                           \n"
    203 		"³Deploying.....³ ³ ³                                                           \n"
    204 		"³Rotating......³ ³ ³                                                           \n"
    205 		"³Firing........³ ³ ³                                                           \n"
    206 		"³Driving.......³ ³ ³                                                           \n"
    207 		"³To Look.......³ ³ ³                                                           \n"
    208 		"³Recoiling.....³ ³ ³                                                           \n"
    209 		"³To Display....³ ³ ³                                                           \n"
    210 		"ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÁÄÙ                                                           \n");
    211 	mono->Set_Cursor(1, 1);mono->Printf("%s:%s", House->Class->IniName, Class->IniName);
    212 	mono->Text_Print("X", 16 + (IsProne?2:0), 10);
    213 	mono->Set_Cursor(33, 7);mono->Printf("%2d", Fear);
    214 	mono->Set_Cursor(41, 7);mono->Printf("%2d", Doing);
    215 	FootClass::Debug_Dump(mono);
    216 }
    217 #endif
    218 
    219 InfantryClass::InfantryClass(void) : Class(0) {};		// Default constructor does nothing.
    220 
    221 
    222 /***********************************************************************************************
    223  * InfantryClass::InfantryClass -- The constructor for infantry objects.                       *
    224  *                                                                                             *
    225  *    This is the constructor used when creating an infantry unit. All values are required     *
    226  *    except for facing and position. If these are absent, then the infantry is created in     *
    227  *    a state of limbo -- not placed upon the map.                                             *
    228  *                                                                                             *
    229  * INPUT:   see below...                                                                       *
    230  *                                                                                             *
    231  * OUTPUT:  none                                                                               *
    232  *                                                                                             *
    233  * WARNINGS:   none                                                                            *
    234  *                                                                                             *
    235  * HISTORY:                                                                                    *
    236  *   09/01/1994 JLB : Created.                                                                 *
    237  *=============================================================================================*/
    238 InfantryClass::InfantryClass(InfantryType classid, HousesType house) :
    239 	Class(&InfantryTypeClass::As_Reference(classid)),
    240 	FootClass(house)
    241 {
    242 
    243 	/*
    244 	**	For two shooters, clear out the second shot flag -- it will be set the first time
    245 	**	the object fires. For non two shooters, set the flag since it will never be cleared
    246 	**	and the second shot flag tells the system that normal rearm times apply -- this is
    247 	**	what is desired for non two shooters.
    248 	*/
    249 	if (Class->IsTwoShooter) {
    250 		IsSecondShot = false;
    251 	} else {
    252 		IsSecondShot = true;
    253 	}
    254 	Doing = DO_NOTHING;
    255 	Fear = 0;			// Starts completely brave.
    256 	IsProne = false;
    257 	IsStoked = false;
    258 	IsBoxing = false;
    259 	IsTechnician = false;
    260 	Strength = Class->MaxStrength;
    261 
    262 	/*
    263 	**	Civilians carry much less ammo than soldiers do.
    264 	*/
    265 	Ammo = Class->MaxAmmo;
    266 
    267 	/*
    268 	** Keep count of the number of units created. Dont track civilians.
    269 	*/
    270 	if (!Class->IsCivilian && GameToPlay == GAME_INTERNET){
    271 		House->InfantryTotals->Increment_Unit_Total((int)classid);
    272 	}
    273 
    274 #ifdef USE_RA_AI
    275 	//
    276 	// Added for RA AI in TD. ST - 7/26/2019 9:12AM
    277 	//
    278 	House->Tracking_Add(this);
    279 #endif // USE_RA_AI
    280 
    281 	StopDriverFrame = -1;
    282 }
    283 
    284 
    285 /***********************************************************************************************
    286  * InfantryClass::~InfantryClass -- Default destructor for infantry units.                     *
    287  *                                                                                             *
    288  *    This is the default destructor for infantry type units. It will put the infantry into    *
    289  *    a limbo state if it isn't already in that state and the game is still active.            *
    290  *                                                                                             *
    291  * INPUT:   none                                                                               *
    292  *                                                                                             *
    293  * OUTPUT:  none                                                                               *
    294  *                                                                                             *
    295  * WARNINGS:   none                                                                            *
    296  *                                                                                             *
    297  * HISTORY:                                                                                    *
    298  *   01/10/1995 JLB : Created.                                                                 *
    299  *=============================================================================================*/
    300 InfantryClass::~InfantryClass(void)
    301 {
    302 	if (GameActive && Class) {
    303 #ifdef USE_RA_AI
    304 		//
    305 		// Added for RA AI in TD. ST - 7/26/2019 9:12AM
    306 		//
    307 		House->Tracking_Remove(this);
    308 #endif //USE_RA_AI
    309 		Limbo();
    310 	}
    311 	if (GameActive && Team) Team->Remove(this);
    312 }
    313 
    314 
    315 /***********************************************************************************************
    316  * InfantryClass::operator new -- Allocates an infantry object from the free pool.             *
    317  *                                                                                             *
    318  *    This will allocate an infantry object from the infantry object free pool. If there is    *
    319  *    no available slot, then NULL is returned.                                                *
    320  *                                                                                             *
    321  * INPUT:   none                                                                               *
    322  *                                                                                             *
    323  * OUTPUT:  Returns with a pointer to the allocated infantry object or NULL if none could be   *
    324  *          allocated.                                                                         *
    325  *                                                                                             *
    326  * WARNINGS:   none                                                                            *
    327  *                                                                                             *
    328  * HISTORY:                                                                                    *
    329  *   09/01/1994 JLB : Created.                                                                 *
    330  *=============================================================================================*/
    331 void * InfantryClass::operator new(size_t)
    332 {
    333 	void * ptr = Infantry.Allocate();
    334 	if (ptr) {
    335 		((InfantryClass *)ptr)->Set_Active();
    336 	}
    337 	return(ptr);
    338 }
    339 
    340 
    341 /***********************************************************************************************
    342  * InfantryClass::operator delete -- Returns the infantry object back to the free pool         *
    343  *                                                                                             *
    344  *    This routine is used return an infantry object back to the system.                       *
    345  *                                                                                             *
    346  * INPUT:   ptr   -- Pointer to the infantry object to delete.                                 *
    347  *                                                                                             *
    348  * OUTPUT:  none                                                                               *
    349  *                                                                                             *
    350  * WARNINGS:   none                                                                            *
    351  *                                                                                             *
    352  * HISTORY:                                                                                    *
    353  *   09/08/1994 JLB : Created.                                                                 *
    354  *=============================================================================================*/
    355 void InfantryClass::operator delete(void *ptr)
    356 {
    357 	if (ptr) {
    358 		((InfantryClass *)ptr)->IsActive = false;
    359 	}
    360 	Infantry.Free((InfantryClass *)ptr);
    361 
    362 	//Map.Validate();
    363 }
    364 
    365 
    366 /***********************************************************************************************
    367  * InfantryClass::Take_Damage -- Applies damage to the infantry unit.                          *
    368  *                                                                                             *
    369  *    This routine applies the damage specified to the infantry object. It is possible that    *
    370  *    this routine will DESTROY the infantry unit in the process.                              *
    371  *                                                                                             *
    372  * INPUT:   damage   -- The damage points to inflict.                                          *
    373  *                                                                                             *
    374  *          distance -- The distance from the damage center point to the object's center point.*
    375  *                                                                                             *
    376  *          warhead  -- The warhead type that is inflicting the damage.                        *
    377  *                                                                                             *
    378  *          source   -- Who is responsible for inflicting the damage.                          *
    379  *                                                                                             *
    380  * OUTPUT:  bool; Was the infantry unit destroyed by this damage?                              *
    381  *                                                                                             *
    382  * WARNINGS:   Since the infantry unit could be destroyed by this routine, be sure to check    *
    383  *             for this in the code that follows the call to Take_Damage().                    *
    384  *                                                                                             *
    385  * HISTORY:                                                                                    *
    386  *   09/08/1994 JLB : Created.                                                                 *
    387  *   11/22/1994 JLB : Shares base damage handler for techno objects.                           *
    388  *   03/31/1995 JLB : Revenge factor.                                                          *
    389  *=============================================================================================*/
    390 ResultType InfantryClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source)
    391 {
    392 	Validate();
    393 	ResultType res = RESULT_NONE;
    394 
    395 	IsFiring = false;
    396 
    397 	/*
    398 	**	Prone infantry take only half damage, but never below one damage point.
    399 	*/
    400 	if (IsProne && damage) {
    401 		damage >>= 1;
    402 //		damage = MAX(damage, 1);
    403 	}
    404 
    405 
    406 //Mono_Printf("Infantry Take_Damage(%d, %d, %d, %p)\r", damage, distance, warhead, source);
    407 //Get_Key();
    408 
    409 	res = FootClass::Take_Damage(damage, distance, warhead, source);
    410 
    411 	/*
    412 	**	Flame thrower guys take more damage because of the exposed pilot light
    413 	**	on their flame gun.
    414 	*/
    415 	if (damage && res != RESULT_DESTROYED && *this == INFANTRY_E4) {
    416 		damage = 5;
    417 		ResultType newres = FootClass::Take_Damage(damage, distance, warhead, source);
    418 		res = MAX(res, newres);
    419 	}
    420 
    421 	if (res == RESULT_NONE) return(res);
    422 
    423 	if (res == RESULT_DESTROYED) {
    424 		Death_Announcement(source);
    425 		Stop_Driver();
    426 		Stun();
    427 		Mission = MISSION_NONE;
    428 		Assign_Mission(MISSION_GUARD);
    429 		Commence();
    430 
    431 		/*
    432 		**	Flame thrower infantry always go out with a bang.
    433 		*/
    434 		if (*this == INFANTRY_E4) {
    435 			new AnimClass(ANIM_NAPALM1, Coord);
    436 			Explosion_Damage(Coord, 80, 0, WARHEAD_FIRE);
    437 		}
    438 
    439 		if (*this == INFANTRY_E2) {
    440 			new AnimClass(ANIM_ART_EXP1, Coord);
    441 			Explosion_Damage(Coord, 30, 0, WARHEAD_HE);
    442 		}
    443 
    444 		if (*this == INFANTRY_E5) {
    445 			new AnimClass(ANIM_CHEM_BALL, Coord);
    446 			Explosion_Damage(Coord, 80, 0, WARHEAD_HE);
    447 		}
    448 
    449 		VocType sound;
    450 		VocType altsound;
    451 		if (*this == INFANTRY_RAMBO) {
    452 //			if (Sim_Random_Pick(0, 3) != 1) {
    453 				sound = VOC_RAMBO_YELL;
    454 //			} else {
    455 //				sound = VOC_RAMBO_OHSH;
    456 //			}
    457 			altsound = sound;
    458 		} else {
    459 			sound = Sim_Random_Pick(VOC_SCREAM1, VOC_SCREAM5);
    460 			altsound = VOC_YELL1;
    461 		}
    462 
    463 		/*
    464 		**	The type of warhead determines the animation the infantry
    465 		**	will perform when killed.
    466 		*/
    467 		switch (warhead) {
    468 			case WARHEAD_FEEDME:
    469 				if (source) {
    470 					source->Strength += 30;
    471 					if (source->Strength > source->Class_Of().MaxStrength) {
    472 						source->Strength = source->Class_Of().MaxStrength;
    473 					}
    474 				}
    475 				// Fall thru to WARHEAD_SA:
    476 
    477 			case WARHEAD_HEADBUTT:
    478 			case WARHEAD_SPORE:
    479 			case WARHEAD_HOLLOW_POINT:
    480 			case WARHEAD_SA:
    481 				Sound_Effect(sound, Coord);
    482 				Do_Action(DO_GUN_DEATH, true);
    483 				break;
    484 
    485 			case WARHEAD_HE:
    486 				Sound_Effect(sound, Coord);
    487 				Do_Action(DO_EXPLOSION_DEATH, true);
    488 				break;
    489 
    490 			case WARHEAD_AP:
    491 				Sound_Effect(sound, Coord);
    492 				Do_Action(DO_GRENADE_DEATH, true);
    493 				break;
    494 
    495 			case WARHEAD_PB:
    496 			case WARHEAD_LASER:
    497 			case WARHEAD_FIRE:
    498 				Sound_Effect(altsound, Coord);
    499 				Do_Action(DO_FIRE_DEATH, true);
    500 				break;
    501 
    502 			case WARHEAD_FIST:
    503 				Sound_Effect(sound, Coord);
    504 				Do_Action(DO_PUNCH_DEATH,true);
    505 				break;
    506 
    507 			case WARHEAD_FOOT:
    508 				Sound_Effect(sound, Coord);
    509 				Do_Action(DO_KICK_DEATH,true);
    510 				break;
    511 		}
    512 
    513 		return(res);
    514 	}
    515 
    516 	/*
    517 	**	When infantry gets hit, it gets scared.
    518 	*/
    519 	if (res != RESULT_DESTROYED) {
    520 		COORDINATE c4 = (source) ? source->Coord : NULL;
    521 		if (source) {
    522 			Scatter(c4);
    523 		}
    524 
    525 #ifdef BOXING
    526 		if (IsBoxing) {
    527 			int addval = 0;
    528 
    529 			switch (warhead) {
    530 				case WARHEAD_FIST:
    531 					if (damage == Infantry_Punch_Damage[1]) addval++;
    532 					Do_Action( (DoType) ( (int)DO_PUNCH_HIT1 + addval),true);
    533 					break;
    534 
    535 				case WARHEAD_FOOT:
    536 					if (damage == Infantry_Kick_Damage[1]) addval++;
    537 					Do_Action( (DoType) ( (int)DO_KICK_HIT1 + addval),true);
    538 					break;
    539 			}
    540 		} else {
    541 #endif
    542 			if (source && Fear < FEAR_SCARED) {
    543 				if (Class->IsFraidyCat) {
    544 					Fear = FEAR_PANIC;
    545 				} else {
    546 					Fear = FEAR_SCARED;
    547 				}
    548 			} else {
    549 				int morefear = FEAR_ANXIOUS;
    550 				if (Health_Ratio() > 0x0080) morefear /= 4;
    551 				Fear = MIN((int)Fear + morefear, FEAR_MAXIMUM);
    552 			}
    553 #ifdef BOXING
    554 		}
    555 #endif
    556 	}
    557 	return(res);
    558 }
    559 
    560 
    561 /***********************************************************************************************
    562  * InfantryClass::Draw_It -- Draws a unit object.                                              *
    563  *                                                                                             *
    564  *    This routine is the one that actually draws a unit object. It displays the unit          *
    565  *    according to its current state flags and centered at the location specified.             *
    566  *                                                                                             *
    567  * INPUT:   x,y   -- The X and Y coordinate of where to draw the unit.                         *
    568  *                                                                                             *
    569  *          window   -- The clipping window to use.                                            *
    570  *                                                                                             *
    571  * OUTPUT:  none                                                                               *
    572  *                                                                                             *
    573  * WARNINGS:   none                                                                            *
    574  *                                                                                             *
    575  * HISTORY:                                                                                    *
    576  *   06/20/1994 JLB : Created.                                                                 *
    577  *   06/27/1994 JLB : Takes a window parameter.                                                *
    578  *   08/15/1994 JLB : Converted to infantry support.                                           *
    579  *=============================================================================================*/
    580 void InfantryClass::Draw_It(int x, int y, WindowNumberType window)
    581 {
    582 	Validate();
    583 	void const * shapefile;		// Working shape file pointer.
    584 	int facing = Facing_To_32(PrimaryFacing.Current());
    585 
    586 	/*
    587 	**	Verify the legality of the unit class.
    588 	*/
    589 	shapefile = Class->Get_Image_Data();
    590 	if (!shapefile) return;
    591 
    592 	y += 4;
    593 	x -= 2;
    594 
    595 	/*
    596 	**	Fetch the basic body shape pointer. This requires taking into account
    597 	**	the current animation stage.
    598 	*/
    599 	int	shapenum;
    600 	int	facenum;
    601 
    602 	shapenum = 0;
    603 	facenum = HumanShape[facing];
    604 
    605 	/*
    606 	**	Fetch the shape pointer to use for the infantry. This is controlled by what
    607 	**	choreograph sequence the infantry is performing, it's facing, and whether it
    608 	**	is prone.
    609 	*/
    610 	DoType doit = Doing;
    611 	if (doit == DO_NOTHING) doit = DO_STAND_READY;
    612 
    613 	/*
    614 	** Hold the walk pose for a couple of frames after we come to a stop to try and avoid the problem where a moving infantry
    615 	** goes into the stand pose for a single frame when pausing in the assigned cell destination. ST - 9/4/2019 1:39PM
    616 	*/
    617 	if (doit == DO_STAND_READY) {
    618 		if (window == WINDOW_VIRTUAL) {
    619 			if (StopDriverFrame != -1) {
    620 				if (Frame - StopDriverFrame <= 2) {
    621 					if (Path[0] != FACING_NONE) {
    622 						doit = DO_WALK;
    623 					}
    624 				}
    625 			}
    626 		}					  
    627 	}
    628 
    629 	shapenum = Class->DoControls[doit].Count;
    630 	shapenum = Fetch_Stage() % MAX(shapenum, 1);
    631 	if (Class->DoControls[doit].Jump) {
    632 		shapenum += facenum * Class->DoControls[doit].Jump;
    633 	}
    634 	shapenum += Class->DoControls[doit].Frame;
    635 
    636 #ifdef BOXING
    637 // BG hack to get him to face right when he's supposed to.
    638 	if (IsBoxing && BodyFacing<128) shapenum += 47;
    639 #endif
    640 
    641 	/*
    642 	**	Actually draw the root body of the unit.
    643 	*/
    644 	Techno_Draw_Object(shapefile, shapenum, x, y, window);
    645 //	CC_Draw_Shape(shapefile, shapenum, x, y, window, SHAPE_FADING|SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST, House->Remap_Table(IsBlushing, true), Map.UnitShadow);
    646 
    647 	FootClass::Draw_It(x, y, window);
    648 }
    649 
    650 
    651 /***********************************************************************************************
    652  * InfantryClass::Per_Cell_Process -- Handles special operations that occur once per cell.     *
    653  *                                                                                             *
    654  *    This routine will handle any special operations that need to be performed once each      *
    655  *    cell travelled. This includes radioing a transport that is is now clear and the          *
    656  *    transport is free to leave.                                                              *
    657  *                                                                                             *
    658  * INPUT:   none                                                                               *
    659  *                                                                                             *
    660  * OUTPUT:  none                                                                               *
    661  *                                                                                             *
    662  * WARNINGS:   none                                                                            *
    663  *                                                                                             *
    664  * HISTORY:                                                                                    *
    665  *   09/08/1994 JLB : Created.                                                                 *
    666  *   03/01/1995 JLB : Capture building options.                                                *
    667  *   05/31/1995 JLB : Capture is always successful now.                                        *
    668  *=============================================================================================*/
    669 void InfantryClass::Per_Cell_Process(bool center)
    670 {
    671 	Validate();
    672 	CellClass *cellptr = &Map[Coord_Cell(Coord)];
    673 
    674 	/*
    675 	**	If the infantry unit is entering a cell that contains the building it is trying to
    676 	**	capture, then capture it.
    677 	*/
    678 	if (center && Mission == MISSION_CAPTURE) {
    679 		TechnoClass * tech = cellptr->Cell_Techno();
    680 		if (tech && tech->As_Target() == NavCom && tech->What_Am_I() == RTTI_BUILDING && !tech->Can_Capture()) {
    681 			tech = NULL;
    682 			Assign_Destination(TARGET_NONE);
    683 		}
    684 		if (tech && tech->As_Target() == NavCom) {
    685 			tech->Captured(House);
    686 			Delete_This();
    687 			return;
    688 		} else {
    689 //#ifdef NEVER
    690 			if (!Target_Legal(NavCom)) {
    691 				Enter_Idle_Mode();
    692 				if (Map[Coord_Cell(Coord)].Cell_Building()) {
    693 					Scatter(0, true);
    694 				}
    695 			}
    696 //#endif
    697 		}
    698 	}
    699 
    700 	/*
    701 	**	Infantry entering a transport vehicle will break radio contact
    702 	**	at attach itself to the transporter.
    703 	*/
    704 	TechnoClass * techno = Contact_With_Whom();
    705 	if (center && Mission == MISSION_ENTER && techno && Coord_Cell(Coord) == Coord_Cell(techno->Coord) && techno == As_Techno(NavCom)) {
    706 		if (Transmit_Message(RADIO_IM_IN) == RADIO_ATTACH) {
    707 			Limbo();
    708 			techno->Attach(this);
    709 		}
    710 		return;
    711 	}
    712 
    713 	/*
    714 	**	If the infantry unit is entering a cell that contains the building it is trying to
    715 	**	sabotage, then sabotage it.
    716 	*/
    717 	if (center && Mission == MISSION_SABOTAGE) {
    718 		BuildingClass *building = cellptr->Cell_Building();
    719 		if (building && building->As_Target() == NavCom) {
    720 			int temp = Special.IsScatter;
    721 
    722 			building->IsGoingToBlow = true;
    723 			building->Clicked_As_Target(PlayerPtr->Class->House, 20); // 2019/09/20 JAS - Added record of who clicked on the object
    724 			building->Clicked_As_Target(building->Owner(), 20);
    725 			building->CountDown.Set(20);
    726 			building->WhomToRepay = As_Target();
    727 			Special.IsScatter = true;
    728 			NavCom = TARGET_NONE;
    729 			Do_Uncloak();
    730 			Arm = Rearm_Delay(true);
    731 			Scatter(building->Center_Coord(), true);	// RUN AWAY!
    732 			Special.IsScatter = temp;
    733 			return;
    734 		}
    735 	}
    736 
    737 	/*
    738 	**	If this unit is on a teather, then cut it at this time so that
    739 	**	the "parent" unit is free to proceed. Note that the parent
    740 	**	unit might actually be a building.
    741 	*/
    742 	if (center && IsTethered) {
    743 		Transmit_Message(RADIO_UNLOADED);
    744 		if (House->Class->House == HOUSE_GOOD) {
    745 			Do_Action(DO_GESTURE1);
    746 		} else  {
    747 			Do_Action(DO_GESTURE2);
    748 		}
    749 
    750 		/*
    751 		**	Rambo types give a gung-ho comment when unloaded.
    752 		*/
    753 		if (*this == INFANTRY_RAMBO) {
    754 			Sound_Effect(VOC_RAMBO_ROCK, Coord);
    755 		}
    756 
    757 		/*
    758 		**	If the cell is now full of infantry, tell them all to scatter
    759 		**	in order to make room for more.
    760 		*/
    761 		if ((cellptr->Flag.Composite & 0x01F) == 0x01F) {
    762 			cellptr->Incoming(0, true);
    763 		}
    764 	}
    765 
    766 	/*
    767 	**	When the infantry reaches the center of the cell, it may begin a new mission.
    768 	*/
    769 	if (center) {
    770 		Commence();
    771 	}
    772 
    773 	Look(true);
    774 	FootClass::Per_Cell_Process(center);
    775 
    776 	/*
    777 	**	If over Tiberium, then this infantry unit will take damage.
    778 	*/
    779 	if (IsActive && !IsInLimbo && center && cellptr->Land_Type() == LAND_TIBERIUM && *this != INFANTRY_E5) {
    780 		int damage = 2;
    781 		Take_Damage(damage, 0, WARHEAD_FIRE);
    782 	}
    783 }
    784 
    785 
    786 /***********************************************************************************************
    787  * InfantryClass::Detach -- Removes the specified target from targeting computer.              *
    788  *                                                                                             *
    789  *    This is a support routine that removes the target specified from any targeting or        *
    790  *    navigation computers. When a target is destroyed or removed from the game system,        *
    791  *    the target must be removed from any tracking systems of the other units. This routine    *
    792  *    handles removal for infantry units.                                                      *
    793  *                                                                                             *
    794  * INPUT:   target   -- The target to remove from the infantry unit's tracking systems.        *
    795  *                                                                                             *
    796  *          all      -- Is the target going away for good as opposed to just cloaking/hiding?  *
    797  *                                                                                             *
    798  * OUTPUT:  none                                                                               *
    799  *                                                                                             *
    800  * WARNINGS:   none                                                                            *
    801  *                                                                                             *
    802  * HISTORY:                                                                                    *
    803  *   09/08/1994 JLB : Created.                                                                 *
    804  *=============================================================================================*/
    805 void InfantryClass::Detach(TARGET target, bool all)
    806 {
    807 	Validate();
    808 	if (TarCom == target) {
    809 		IsFiring = false;
    810 	}
    811 	FootClass::Detach(target, all);
    812 }
    813 
    814 
    815 /***********************************************************************************************
    816  * InfantryClass::As_Target -- Converts the infantry unit into a target value.                 *
    817  *                                                                                             *
    818  *    This support routine is used to convert the infantry object (as a pointer) into a target *
    819  *    value (which is a number).                                                               *
    820  *                                                                                             *
    821  * INPUT:   none                                                                               *
    822  *                                                                                             *
    823  * OUTPUT:  Returns the infantry unit as a target value.                                       *
    824  *                                                                                             *
    825  * WARNINGS:   none                                                                            *
    826  *                                                                                             *
    827  * HISTORY:                                                                                    *
    828  *   09/08/1994 JLB : Created.                                                                 *
    829  *=============================================================================================*/
    830 TARGET InfantryClass::As_Target(void) const
    831 {
    832 	Validate();
    833 	return(Build_Target(KIND_INFANTRY, Infantry.ID(this)));
    834 }
    835 
    836 
    837 /***********************************************************************************************
    838  * InfantryClass::Init -- Initialize the infantry object system.                               *
    839  *                                                                                             *
    840  *    This routine will force the infantry object system into its empty initial state. It      *
    841  *    is called when the scenario needs to be cleared in preparation for a scenario load.      *
    842  *                                                                                             *
    843  * INPUT:   none                                                                               *
    844  *                                                                                             *
    845  * OUTPUT:  none                                                                               *
    846  *                                                                                             *
    847  * WARNINGS:   none                                                                            *
    848  *                                                                                             *
    849  * HISTORY:                                                                                    *
    850  *   09/08/1994 JLB : Created.                                                                 *
    851  *=============================================================================================*/
    852 void InfantryClass::Init(void)
    853 {
    854 	InfantryClass *ptr;
    855 
    856 	Infantry.Free_All();
    857 
    858 	ptr = new InfantryClass();
    859 	VTable = ((void **)(((char *)ptr) + sizeof(AbstractClass) - 4))[0];
    860 	delete ptr;
    861 }
    862 
    863 
    864 /***********************************************************************************************
    865  * InfantryClass::Look -- The infantry performs a look operation.                              *
    866  *                                                                                             *
    867  *    This routine will cause the infantry unit to "look". For player owned infantry, this     *
    868  *    causes the dark shroud to be pushed back.                                                *
    869  *                                                                                             *
    870  * INPUT:   incremental -- If it is known that the infantry performed a look in the last cell  *
    871  *                         it was in AND it has only moved one cell, then setting this         *
    872  *                         parameter to true will perform a faster "incremental" look          *
    873  *                         operation.                                                          *
    874  *                                                                                             *
    875  * OUTPUT:  none                                                                               *
    876  *                                                                                             *
    877  * WARNINGS:   This is a relatively slow routine. Call ONLY when necessary.                    *
    878  *                                                                                             *
    879  * HISTORY:                                                                                    *
    880  *   09/08/1994 JLB : Created.                                                                 *
    881  *=============================================================================================*/
    882 void InfantryClass::Look(bool incremental)
    883 {
    884 	Validate();
    885 	int	sight;		// Number of cells to sight.
    886 
    887 	if (!IsInLimbo) {
    888 		//if (IsOwnedByPlayer) {			// Changed for multiple player mapping. ST - 3/6/2019 1:27PM
    889 		if (House->IsHuman || GameToPlay != GAME_NORMAL) {
    890 			sight = Class->SightRange;
    891 
    892 			if (sight) {
    893 				Map.Sight_From(House, Coord_Cell(Coord), sight, incremental);		// Passed our house into Map.Sight_From since it now needs to know who it is performing the action on behalf of. ST - 3/28/2019 2:55PM
    894 			}
    895 		}
    896 	}
    897 }
    898 
    899 
    900 /***********************************************************************************************
    901  * InfantryClass::Assign_Destination -- Gives the infantry a movement destination.             *
    902  *                                                                                             *
    903  *    This routine updates the infantry's navigation computer so that the infantry will        *
    904  *    travel to the destination target specified.                                              *
    905  *                                                                                             *
    906  * INPUT:   target   -- The target to have the infantry unit move to.                          *
    907  *                                                                                             *
    908  * OUTPUT:  none                                                                               *
    909  *                                                                                             *
    910  * WARNINGS:   none                                                                            *
    911  *                                                                                             *
    912  * HISTORY:                                                                                    *
    913  *   09/08/1994 JLB : Created.                                                                 *
    914  *=============================================================================================*/
    915 void InfantryClass::Assign_Destination(TARGET target)
    916 {
    917 	Validate();
    918 	/*
    919 	**	Special flag so that infantry will start heading in the right direction immediately.
    920 	*/
    921 	if (Target_Legal(target)) {
    922 		Stop_Driver();
    923 	}
    924 
    925 	/*
    926 	**	When telling an infantry soldier to move to a location twice, then this
    927 	**	means that movement is more important than safety. Get up and run!
    928 	*/
    929 	if (House->IsHuman && Target_Legal(target) && NavCom == target && IsProne && !Class->IsFraidyCat) {
    930 		Do_Action(DO_GET_UP);
    931 	}
    932 
    933 	/*
    934 	**	Handle entry logic here.
    935 	*/
    936 	if (Mission == MISSION_ENTER || MissionQueue == MISSION_ENTER) {
    937 
    938 		/*
    939 		**	If not already in radio contact (presumed with the transport), then
    940 		**	either try to establish contact if allowed, or just move close and
    941 		**	wait until radio contact can be established.
    942 		*/
    943 		if (!In_Radio_Contact()) {
    944 			TechnoClass * techno = As_Techno(target);
    945 
    946 			if (techno) {
    947 
    948 				/*
    949 				**	Determine if the transport is already in radio contact. If so, then just move
    950 				**	toward the transport and try to establish contact at a later time.
    951 				*/
    952 				if (techno->In_Radio_Contact()) {
    953 
    954 // TCTCTC -- call for an update from the transport to get a good rondezvous position.
    955 
    956 					ArchiveTarget = target;
    957 				} else {
    958 					if (Transmit_Message(RADIO_HELLO, techno) == RADIO_ROGER) {
    959 						if (Transmit_Message(RADIO_DOCKING) != RADIO_ROGER) {
    960 							Transmit_Message(RADIO_OVER_OUT);
    961 							Assign_Mission(MISSION_MOVE);
    962 						}
    963 					} else {
    964 						Assign_Mission(MISSION_MOVE);
    965 					}
    966 				}
    967 			}
    968 		} else {
    969 			Path[0] = FACING_NONE;
    970 		}
    971 	} else {
    972 		Path[0] = FACING_NONE;
    973 	}
    974 	FootClass::Assign_Destination(target);
    975 }
    976 
    977 
    978 /***********************************************************************************************
    979  * InfantryClass::Assign_Target -- Gives the infantry a combat target.                         *
    980  *                                                                                             *
    981  *    This routine will update the infantry's targeting computer so that it will try to        *
    982  *    attack the target specified. This might result in it moving to be within range and thus  *
    983  *    also cause adjustment of the navigation computer.                                        *
    984  *                                                                                             *
    985  * INPUT:   target   -- The target that this infantry should attack.                           *
    986  *                                                                                             *
    987  * OUTPUT:  none                                                                               *
    988  *                                                                                             *
    989  * WARNINGS:   none                                                                            *
    990  *                                                                                             *
    991  * HISTORY:                                                                                    *
    992  *   09/08/1994 JLB : Created.                                                                 *
    993  *   06/30/1995 JLB : Tries to capture target if possible.                                     *
    994  *=============================================================================================*/
    995 void InfantryClass::Assign_Target(TARGET target)
    996 {
    997 	Validate();
    998 	Path[0] = FACING_NONE;
    999 	FootClass::Assign_Target(target);
   1000 
   1001 	/*
   1002 	**	If this is an infantry that can only capture, then also assign its destination to the
   1003 	**	target specified.
   1004 	*/
   1005 	if (!Target_Legal(NavCom) && Class->IsCapture && Class->Primary == WEAPON_NONE) {
   1006 		BuildingClass const * building = As_Building(target);
   1007 		if (building && building->Can_Capture()) {
   1008 			Assign_Destination(target);
   1009 		}
   1010 	}
   1011 }
   1012 
   1013 
   1014 /***********************************************************************************************
   1015  * InfantryClass::AI -- Handles the infantry non-graphic related AI processing.                *
   1016  *                                                                                             *
   1017  *    This routine is used to handle the non-graphic AI processing the infantry requires.      *
   1018  *    Call this routine ONCE per game frame.                                                   *
   1019  *                                                                                             *
   1020  * INPUT:   none                                                                               *
   1021  *                                                                                             *
   1022  * OUTPUT:  none                                                                               *
   1023  *                                                                                             *
   1024  * WARNINGS:   none                                                                            *
   1025  *                                                                                             *
   1026  * HISTORY:                                                                                    *
   1027  *   09/08/1994 JLB : Created.                                                                 *
   1028  *=============================================================================================*/
   1029 void InfantryClass::AI(void)
   1030 {
   1031 	Validate();
   1032 	FootClass::AI();
   1033 
   1034 	if (IsUnloading) Mark(MARK_CHANGE);
   1035 
   1036 	/*
   1037 	**	Special hack to make sure that if this infantry is in firing animation, but the
   1038 	**	stage class isn't set, then abort the firing flag.
   1039 	*/
   1040 	if (IsFiring && !Fetch_Rate()) {
   1041 		IsFiring = false;
   1042 	}
   1043 
   1044 	/*
   1045 	**	Delete this unit if it finds itself off the edge of the map and it is in
   1046 	**	guard or other static mission mode.
   1047 	*/
   1048 	if (!Team && Mission == MISSION_GUARD && !Map.In_Radar(Coord_Cell(Coord))) {
   1049 		Stun();
   1050 		Delete_This();
   1051 		return;
   1052 	}
   1053 
   1054 	/*
   1055 	**	Act on new orders if the unit is at a good position to do so.
   1056 	*/
   1057 	if (!IsDriving && (Doing == DO_NOTHING || MasterDoControls[Doing].Interrupt)) {
   1058 		Commence();
   1059 	}
   1060 
   1061 	/*
   1062 	**	After a time, the infantry will gain courage.
   1063 	*/
   1064 	if (Fear) {
   1065 
   1066 		/*
   1067 		**	Nikumba is really a coward at heart. He never becomes un-afraid.
   1068 		*/
   1069 		if (*this != INFANTRY_C10) {
   1070 			Fear--;
   1071 
   1072 			/*
   1073 			**	When an armed civilian becomes unafraid, he will then reload
   1074 			**	another clip into his pistol.
   1075 			*/
   1076 			if (Fear == 0 && Ammo == 0 && Class->Primary != WEAPON_NONE) {
   1077 				Ammo = Class->MaxAmmo;
   1078 			}
   1079 		}
   1080 
   1081 		/*
   1082 		**	Stand up if brave and lie down if afraid.
   1083 		*/
   1084 		if (IsProne) {
   1085 			if (Fear < FEAR_ANXIOUS) {
   1086 				Do_Action(DO_GET_UP);
   1087 			}
   1088 		} else  {
   1089 
   1090 			/*
   1091 			**	Drop to the ground if anxious. Don't drop to the ground while moving
   1092 			**	and the special elite flag is active.
   1093 			*/
   1094 			if (Fear >= FEAR_ANXIOUS && ((!Target_Legal(NavCom) && !IsDriving) || !Special.IsDefenderAdvantage)) {
   1095 				Do_Action(DO_LIE_DOWN);
   1096 			}
   1097 		}
   1098 	}
   1099 
   1100 	/*
   1101 	**	When is darkness or in doubt,
   1102 	**		run in circles, scream, and shout.
   1103 	*/
   1104 	if (Class->IsFraidyCat && Fear > FEAR_ANXIOUS && !IsDriving && !Target_Legal(NavCom)) {
   1105 		Scatter(0);
   1106 	}
   1107 
   1108 	/*
   1109 	**	Scatter infantry off buildings in guard modes.
   1110 	*/
   1111 	if (!IsTethered && !IsFiring && !IsDriving && !IsRotating && (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA) && MissionQueue == MISSION_NONE && Map[Coord_Cell(Coord)].Cell_Building() != NULL) {
   1112 		Scatter(0, true, true);
   1113 	}
   1114 
   1115 	/*
   1116 	**	Special victory dance action.
   1117 	*/
   1118 	if (!Target_Legal(NavCom) && !IsProne && IsStoked && Comment.Expired()) {
   1119 		IsStoked = false;
   1120 		Do_Action((Random_Pick(0, 1) == 0) ? DO_GESTURE1 : DO_GESTURE2);
   1121 		if (*this == INFANTRY_RAMBO) {
   1122 			VocType _response[] = {
   1123 				VOC_RAMBO_LEFTY,
   1124 				VOC_RAMBO_LAUGH,
   1125 				VOC_RAMBO_COMIN,
   1126 				VOC_RAMBO_TUFF
   1127 			};
   1128 			Sound_Effect(_response[Sim_Random_Pick(0, (int)(sizeof(_response) / sizeof(_response[0]))-1)], Coord);
   1129 		}
   1130 	}
   1131 
   1132 	/*
   1133 	**	Determine if this infantry unit should fire off an
   1134 	**	attack or not.
   1135 	*/
   1136 	switch (Can_Fire(TarCom, 0)) {
   1137 		case FIRE_CLOAKED:
   1138 			Do_Uncloak();
   1139 			break;
   1140 
   1141 		case FIRE_OK:
   1142 #ifdef BOXING
   1143 			ObjectClass *object = As_Object(TarCom);
   1144 
   1145 			if (object) {
   1146 				/* If we're engaged in hand-to-hand combat, keep boxing */
   1147 				if (IsBoxing) {
   1148 					IsFiring = true;
   1149 					if (((InfantryClass *)object)->Doing == DO_FIGHT_READY) {
   1150 						Do_Action((DoType) ((int)DO_PUNCH + (DoType)(Random_Pick(0, 1) == 1)),true);
   1151 					}
   1152 				} else {
   1153 
   1154 					if (Is_Target_Infantry(TarCom) && (Distance(TarCom)<=0x80) && (Coord_Y(Coord) == Coord_Y(object->Coord))) {
   1155 
   1156 						// Too close to shoot, so start hand-to-hand combat
   1157 						if (Establish_Contact((TechnoClass *)object)) {
   1158 							if (Transmit_Message(RADIO_PREPARE_TO_BOX) == RADIO_ROGER) {
   1159 								IsBoxing = true;
   1160 								Do_Action(DO_ON_GUARD,true);
   1161 							}
   1162 						}
   1163 					} else {
   1164 #endif
   1165 
   1166 						/*
   1167 						**	Start firing animation.
   1168 						*/
   1169 						if (IsProne) {
   1170 							Do_Action(DO_FIRE_PRONE);
   1171 							IsFiring = true;
   1172 						} else {
   1173 							Do_Action(DO_FIRE_WEAPON);
   1174 							IsFiring = true;
   1175 						}
   1176 #ifdef BOXING
   1177 					}
   1178 #endif
   1179 
   1180 					PrimaryFacing.Set(Direction8(Center_Coord(), As_Coord(TarCom)));
   1181 
   1182 					/*
   1183 					**	If the target is in range, and the NavCom is the same, then just
   1184 					**	stop and keep firing.
   1185 					*/
   1186 					if (TarCom == NavCom) {
   1187 						NavCom = TARGET_NONE;
   1188 						Path[0] = FACING_NONE;
   1189 					}
   1190 #ifdef BOXING
   1191 				}
   1192 			}
   1193 #endif
   1194 			break;
   1195 	}
   1196 
   1197 	/*
   1198 	**	If in the middle of firing animation, then only
   1199 	**	process that. Infantry cannot fire and move simultaneously.
   1200 	**	At some point in the firing animation process, a projectile
   1201 	**	will be launched. When the required animation frames have
   1202 	**	been completed, the firing animation stops.
   1203 	*/
   1204 	int firestage = Class->FireLaunch;
   1205 	if (IsProne) firestage = Class->ProneLaunch;
   1206 
   1207 #ifdef BOXING
   1208 	if (IsBoxing) {
   1209 		firestage = 1;
   1210 		if (Doing == DO_KICK) firestage = 2;
   1211 	}
   1212 #endif
   1213 
   1214 	if (IsFiring && Fetch_Stage() == firestage) {
   1215 		Fire_At(TarCom, 0);
   1216 
   1217 		if (Class->Primary == WEAPON_GRENADE) {
   1218 			Map[::As_Cell(TarCom)].Incoming(Coord, true);
   1219 		}
   1220 	}
   1221 
   1222 	/*
   1223 	**	Handle the completion of the animation sequence.
   1224 	*/
   1225 
   1226 	if (Doing == DO_NOTHING || Fetch_Stage() >= Class->DoControls[Doing].Count) {
   1227 		switch (Doing) {
   1228 			default:
   1229 				if (IsDriving) {
   1230 					if (IsProne) {
   1231 						Do_Action(DO_CRAWL, true);
   1232 					} else {
   1233 						Do_Action(DO_WALK, true);
   1234 					}
   1235 				} else {
   1236 					if (IsProne) {
   1237 						Do_Action(DO_PRONE, true);
   1238 					} else {
   1239 						Do_Action(DO_STAND_READY, true);
   1240 					}
   1241 				}
   1242 				break;
   1243 
   1244 #ifdef BOXING
   1245 			case DO_FIGHT_READY:
   1246 			case DO_ON_GUARD:
   1247 			case DO_PUNCH:
   1248 			case DO_KICK:
   1249 			case DO_PUNCH_HIT1:
   1250 			case DO_PUNCH_HIT2:
   1251 			case DO_KICK_HIT1:
   1252 			case DO_KICK_HIT2:
   1253 				if (In_Radio_Contact()) {
   1254 					Do_Action(DO_FIGHT_READY, true);
   1255 				} else {
   1256 					IsBoxing = false;
   1257 					Do_Action(DO_READY_WEAPON);
   1258 				}
   1259 				break;
   1260 #endif
   1261 
   1262 			/*
   1263 			**	When death is due to hand-to-hand combat, use the gunfire death
   1264 			**	decay animation since there is no custom animation available - yet.
   1265 			*/
   1266 			case DO_PUNCH_DEATH:
   1267 			case DO_KICK_DEATH:
   1268 				// Fall into next case.
   1269 
   1270 			case DO_GUN_DEATH:
   1271 			case DO_EXPLOSION_DEATH:
   1272 			case DO_EXPLOSION2_DEATH:
   1273 			case DO_GRENADE_DEATH:
   1274 			case DO_FIRE_DEATH:
   1275 				Delete_This();
   1276 				return;
   1277 		}
   1278 	}
   1279 
   1280 	/*
   1281 	**	Perform movement operations at this time.
   1282 	*/
   1283 	if (!IsFiring /*&& !IsBoxing*/) {
   1284 		if (!IsDriving) {
   1285 
   1286 			/*
   1287 			**	When in guard mode, never allow a valid navcom.
   1288 			*/
   1289 			if (Mission == MISSION_GUARD && MissionQueue == MISSION_NONE && Target_Legal(NavCom)) {
   1290 				Assign_Destination(TARGET_NONE);
   1291 //				if (IsTethered) Scatter(0, true);
   1292 			}
   1293 
   1294 			/*
   1295 			**	A head to coordinate is needed. If there is no path
   1296 			**	available, then create one.
   1297 			*/
   1298 			if (Target_Legal(NavCom) && Strength && Mission != MISSION_GUARD) {
   1299 
   1300 				/*
   1301 				**	Determine if the next cell in the list is available
   1302 				**	to be entered. If not, then abort the path and try
   1303 				**	again.
   1304 				*/
   1305 				if (Path[0] != FACING_NONE && Can_Enter_Cell(Adjacent_Cell(Coord_Cell(Center_Coord()), Path[0])) != MOVE_OK) {
   1306 					Path[0] = FACING_NONE;
   1307 				}
   1308 
   1309 				/*
   1310 				**	Check to see if the target is closer than expected. This occurs
   1311 				**	when heading toward a moving object and that object is heading
   1312 				**	toward the unit. Shorten the precalculated path to be no longer
   1313 				**	than the distance to the target.
   1314 				*/
   1315 				int d = Lepton_To_Cell(Distance(NavCom));
   1316 				if (d < CONQUER_PATH_MAX) {
   1317 					Path[d] = FACING_NONE;
   1318 				}
   1319 
   1320 				/*
   1321 				**	Find a path to follow if one isn't already calculated.
   1322 				*/
   1323 				if (Path[0] == FACING_NONE) {
   1324 
   1325 					/*
   1326 					**	Calculate the path from the current location to the
   1327 					**	destination indicated by the navigation computer. If there
   1328 					**	was a fundamental error with finding a path, then this
   1329 					**	indicates that basic path & movement logic needs to be
   1330 					**	aborted.
   1331 					*/
   1332 					if (!PathDelay.Expired()) {
   1333 						return;
   1334 					}
   1335 					if (!Basic_Path()) {
   1336 //Mono_Printf("Infantry Basic_Path is failing.\n");Get_Key();
   1337 						if (Distance(NavCom) < 0x0280 && !IsTethered) {
   1338 							Assign_Destination(TARGET_NONE);
   1339 						} else {
   1340 							if (TryTryAgain) {
   1341 								TryTryAgain--;
   1342 							} else {
   1343 								if (IsNewNavCom) Sound_Effect(VOC_SCOLD);
   1344 								IsNewNavCom = false;
   1345 
   1346 								//If we're trying to enter a transport we need to fail so others can try to enter. - LLL 4/17/2020
   1347 								if (Mission == MISSION_ENTER) {
   1348 									Mission = MISSION_NONE;
   1349 									Assign_Mission(MISSION_GUARD);
   1350 									Commence();
   1351 
   1352 									Transmit_Message(RADIO_OVER_OUT);
   1353 								}
   1354 							}
   1355 						}
   1356 						Stop_Driver();
   1357 						return;
   1358 					}
   1359 					TryTryAgain = PATH_RETRY;
   1360 				}
   1361 
   1362 				/*
   1363 				**	Determine the coordinate to head to based on the infantry's
   1364 				**	current location and the next location in the path.
   1365 				*/
   1366 				COORDINATE acoord = Adjacent_Cell(Coord, Path[0]);
   1367 				CELL acell = Coord_Cell(acoord);
   1368 
   1369 				if (Can_Enter_Cell(acell) != MOVE_OK) {
   1370 
   1371 					if ((Mission == MISSION_MOVE || Mission == MISSION_ENTER) && !IsTethered && House->IsHuman && Distance(NavCom) < 0x0200) {
   1372 						Assign_Destination(TARGET_NONE);
   1373 					}
   1374 
   1375 					/*
   1376 					** If blocked by a moving block then just exit start of move and
   1377 					** try again next tick.
   1378 					*/
   1379 					if (Can_Enter_Cell(acell) == MOVE_DESTROYABLE) {
   1380 						if (Map[acell].Cell_Object()) {
   1381 							if (!House->Is_Ally(Map[acell].Cell_Object())) {
   1382 								Override_Mission(MISSION_ATTACK, Map[acell].Cell_Object()->As_Target(), TARGET_NONE);
   1383 							}
   1384 						} else {
   1385 							if (Map[acell].Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Map[acell].Overlay).IsWall) {
   1386 								Override_Mission(MISSION_ATTACK, ::As_Target(acell), TARGET_NONE);
   1387 							}
   1388 						}
   1389 					}
   1390 
   1391 					Path[0] = FACING_NONE;
   1392 					Stop_Driver();
   1393 					if (IsNewNavCom) Sound_Effect(VOC_SCOLD);
   1394 					IsNewNavCom = false;
   1395 
   1396 				} else {
   1397 					if (Start_Driver(acoord)) {
   1398 						PrimaryFacing.Set(Direction8(Center_Coord(), Head_To_Coord()));
   1399 						Set_Speed(0xFF);
   1400 						if (IsProne) {
   1401 							Do_Action(DO_CRAWL);
   1402 						} else {
   1403 							Do_Action(DO_WALK);
   1404 						}
   1405 					}
   1406 				}
   1407 			}
   1408 
   1409 		} else {
   1410 
   1411 			/*
   1412 			**	The infantry knows where it should be headed, so head there. Check
   1413 			**	to see if the infantry is "close enough" to the desired location that
   1414 			**	it should just consider itself to have arrived. In this case, force
   1415 			**	the infantry to the destination location and mark this path step
   1416 			**	as complete.
   1417 			*/
   1418 			Mark(MARK_UP);
   1419 			if (Distance(Head_To_Coord()) < 0x0010) {
   1420 
   1421 				memcpy(&Path[0], &Path[1], sizeof(Path)-sizeof(Path[0]));
   1422 				Path[(sizeof(Path)/sizeof(Path[0]))-1] = FACING_NONE;
   1423 				Coord = Head_To_Coord();
   1424 				Stop_Driver();
   1425 				Per_Cell_Process(true);
   1426 
   1427 				if (!IsActive || IsInLimbo) return;
   1428 
   1429 				if (Coord_Cell(Coord) == As_Cell(NavCom)) {
   1430 					NavCom = TARGET_NONE;
   1431 					if (Mission == MISSION_MOVE) {
   1432 						Enter_Idle_Mode();
   1433 					}
   1434 					//Stop_Driver();
   1435 					Path[0] = FACING_NONE;
   1436 				}
   1437 			} else {
   1438 				int	movespeed = Speed;
   1439 
   1440 				/*
   1441 				**	When prone, the infantry moves at half speed or double
   1442 				**	speed. This depends on whether the infantry actually has
   1443 				**	prone animation stages. Civilians don't, and so they
   1444 				**	run instead.
   1445 				*/
   1446 				if (IsProne) {
   1447 					if (Class->IsFraidyCat && !Class->IsCrawling) {
   1448 						movespeed = Speed*2;
   1449 					} else {
   1450 						movespeed = Speed/2;
   1451 					}
   1452 				}
   1453 
   1454 				if (IsTethered) {
   1455 					Transmit_Message(RADIO_REDRAW);
   1456 				}
   1457 
   1458 				/*
   1459 				**	Advance the infantry as far as it should go.
   1460 				*/
   1461 				MPHType maxspeed = MPHType(min((unsigned)(Class->MaxSpeed * House->GroundspeedBias), MPH_LIGHT_SPEED));
   1462 				Coord = Coord_Move(Coord, Direction(Head_To_Coord()), Fixed_To_Cardinal(maxspeed, movespeed));
   1463 			}
   1464 			Mark(MARK_DOWN);
   1465 		}
   1466 		IsNewNavCom = false;
   1467 	}
   1468 }
   1469 
   1470 
   1471 #ifdef NEVER
   1472 /***************************************************************************
   1473  * InfantryClass::Blocking_Object -- Determines how a object blocks an inf *
   1474  *                                                                         *
   1475  * INPUT:		TechnoClass * pointer to object that is blocking unit       *
   1476  *					CELL			  the cell the unit is being blocked in			*
   1477  *                                                                         *
   1478  * OUTPUT:		MoveBitType the way that the object is blocking the unit    *
   1479  *                                                                         *
   1480  * HISTORY:                                                                *
   1481  *   06/08/1995 PWG : Created.                                             *
   1482  *=========================================================================*/
   1483 MoveBitType InfantryClass::Blocking_Object(TechnoClass const *techno, CELL cell) const
   1484 {
   1485 	Validate();
   1486 	bool inf  = (techno->What_Am_I() == RTTI_INFANTRY);
   1487 	bool unit = (techno->What_Am_I() == RTTI_UNIT) || inf;
   1488 
   1489 	CellClass const * cellptr = &Map[cell];
   1490 
   1491 	if (House->Is_Ally(techno)) {
   1492 
   1493 		/*
   1494 		** Logic to handle a trasport type object.
   1495 		*/
   1496 		if (NavCom == techno->As_Target() && Contact_With_Whom() == techno) {
   1497 			return(MOVEF_OK);
   1498 		}
   1499 
   1500 		/*
   1501 		** If the object is of type infantry, then the square is blocked only
   1502 		** if the cell is completely full of infantry.
   1503 		*/
   1504 		if (inf && ((cellptr->Flag.Composite & 0x1f) != 0x1f)) {
   1505 			return(MOVEF_OK);
   1506 		}
   1507 
   1508 		if (unit) {
   1509 
   1510 			/*
   1511 			** If the unit in question has a destination than we should
   1512 			** be prepared to wait for the unit to get out of our way.
   1513 			*/
   1514 			if (((FootClass *)techno)->NavCom != TARGET_NONE) {
   1515 				return(MOVEF_MOVING_BLOCK);
   1516 			}
   1517 			return(MOVEF_TEMP);
   1518 		}
   1519 	} else {
   1520 
   1521 		/*
   1522 		** If its an enemy unit, things are dealt with a little differently
   1523 		*/
   1524 		if (unit) {
   1525 
   1526 
   1527 			/*
   1528 			**	If the object is cloaked, then consider it passable for findpath purposes,
   1529 			**	but not so for all other cases.
   1530 			*/
   1531 			if (techno->Cloak == CLOAKED) {
   1532 				if (IsFindPath) return(MOVEF_OK);
   1533 				return(MOVEF_CLOAK);
   1534 			}
   1535 
   1536 			/*
   1537 			**	If our vehicle is weapon equipped, then report that the cell occupier
   1538 			**	needs only to be destroyed in order to make the cell passable.
   1539 			*/
   1540 			if (Class->Primary != WEAPON_NONE) {
   1541 				return(MOVEF_DESTROYABLE);
   1542 			}
   1543 		}
   1544 	}
   1545 	return(MOVEF_NO);
   1546 }
   1547 #endif
   1548 
   1549 
   1550 
   1551 /***********************************************************************************************
   1552  * InfantryClass::Can_Enter_Cell -- Determines if the infantry can enter the cell specified.   *
   1553  *                                                                                             *
   1554  *    This routine is used to examine the cell specified and determine if the infantry is      *
   1555  *    allowed to enter it. It is used by the path finding algorithm.                           *
   1556  *                                                                                             *
   1557  * INPUT:   cell  -- The cell to examine.                                                      *
   1558  *                                                                                             *
   1559  * OUTPUT:  Returns the type of blockage in the cell.                                          *
   1560  *                                                                                             *
   1561  * WARNINGS:   none                                                                            *
   1562  *                                                                                             *
   1563  * HISTORY:                                                                                    *
   1564  *   09/01/1994 JLB : Created.                                                                 *
   1565  *=============================================================================================*/
   1566 MoveType InfantryClass::Can_Enter_Cell(CELL cell, FacingType ) const
   1567 {
   1568 	Validate();
   1569 	/*
   1570 	** If we are moving into an illegal cell, then we can't do that.
   1571 	*/
   1572 	if ((unsigned)cell >= MAP_CELL_TOTAL) return(MOVE_NO);
   1573 
   1574 	/*
   1575 	**	If moving off the edge of the map, then consider that an illegal move.
   1576 	*/
   1577 	if (IsLocked && !IsALoaner && !ScenarioInit && !Map.In_Radar(cell)) {
   1578 		return(MOVE_NO);
   1579 	}
   1580 	CellClass * cellptr = &Map[cell];
   1581 
   1582 	/*
   1583 	**	Walls are considered impassable for infantry UNLESS the wall has a hole
   1584 	**	in it.
   1585 	*/
   1586 	if (cellptr->Overlay != OVERLAY_NONE) {
   1587 		OverlayTypeClass const & otype = OverlayTypeClass::As_Reference(cellptr->Overlay);
   1588 
   1589 		if (otype.IsCrate && !House->IsHuman) {
   1590 			return(MOVE_NO);
   1591 		}
   1592 
   1593 		if (otype.IsWall) {
   1594 			if ((cellptr->OverlayData / 16) != otype.DamageLevels) {
   1595 				return(MOVE_NO);
   1596 			}
   1597 		}
   1598 	}
   1599 
   1600 	/*
   1601 	** Loop through all of the objects in the square setting a bit
   1602 	** for how they affect movement.
   1603 	*/
   1604 	MoveType retval = MOVE_OK;
   1605 	ObjectClass *obj = cellptr->Cell_Occupier();
   1606 	while (obj) {
   1607 
   1608 		if (obj != this) {
   1609 
   1610 			/*
   1611 			**	Special case check so that a landed aircraft that is in radio contact, will not block
   1612 			**	a capture attempt. It is presumed that this case happens when a helicopter is landed
   1613 			**	at a helipad.
   1614 			*/
   1615 			if ((Mission != MISSION_CAPTURE && Mission != MISSION_SABOTAGE) || obj->What_Am_I() != RTTI_AIRCRAFT || !((AircraftClass *)obj)->In_Radio_Contact()) {
   1616 
   1617 				/*
   1618 				**	Special check to always allow entry into the building that this infantry
   1619 				**	is trying to capture.
   1620 				*/
   1621 				if (obj->What_Am_I() == RTTI_BUILDING || obj->What_Am_I() == RTTI_AIRCRAFT) {
   1622 					if ((Mission == MISSION_CAPTURE || Mission == MISSION_SABOTAGE) && (obj->As_Target() == NavCom || obj->As_Target() == TarCom)) {
   1623 						return(MOVE_OK);
   1624 					}
   1625 				}
   1626 
   1627 				/*
   1628 				**	Special check to always allow entry into the building that this infantry
   1629 				**	is trying to capture.
   1630 				*/
   1631 				if (Mission == MISSION_ENTER && obj->As_Target() == NavCom && IsTethered) {
   1632 					return(MOVE_OK);
   1633 				}
   1634 
   1635 				/*
   1636 				**	Allied objects block movement using different rules than for enemy
   1637 				**	objects.
   1638 				*/
   1639 				if (House->Is_Ally(obj)) {
   1640 					switch (obj->What_Am_I()) {
   1641 
   1642 						/*
   1643 						**	A unit blocks as either a moving blockage or a stationary temp blockage.
   1644 						**	This depends on whether the unit is currently moving or not.
   1645 						*/
   1646 						case RTTI_UNIT:
   1647 							if (((UnitClass *)obj)->IsDriving || Target_Legal(((UnitClass *)obj)->NavCom)) {
   1648 								if (retval < MOVE_MOVING_BLOCK) retval = MOVE_MOVING_BLOCK;
   1649 							} else {
   1650 								if (retval < MOVE_TEMP) retval = MOVE_TEMP;
   1651 							}
   1652 							break;
   1653 
   1654 						/*
   1655 						**	Aircraft and buildings always block movement. If for some reason there is an
   1656 						**	allied terrain object, that blocks movement as well.
   1657 						*/
   1658 						case RTTI_TERRAIN:
   1659 						case RTTI_AIRCRAFT:
   1660 						case RTTI_BUILDING:
   1661 							return(MOVE_NO);
   1662 
   1663 						default:
   1664 							break;
   1665 					}
   1666 
   1667 				} else {
   1668 
   1669 					/*
   1670 					**	Cloaked enemy objects are not considered if this is a Find_Path()
   1671 					**	call.
   1672 					*/
   1673 					if (!obj->Is_Techno() || !((TechnoClass *)obj)->Is_Cloaked(this)) {
   1674 
   1675 						/*
   1676 						**	Any non-allied blockage is considered impassible if the infantry
   1677 						**	is not equipped with a weapon.
   1678 						*/
   1679 						if (Class->Primary == WEAPON_NONE) return(MOVE_NO);
   1680 
   1681 						/*
   1682 						**	Some kinds of terrain are considered destroyable if the infantry is equipped
   1683 						**	with the weapon that can destroy it. Otherwise, the terrain is considered
   1684 						**	impassable.
   1685 						*/
   1686 						switch (obj->What_Am_I()) {
   1687 							case RTTI_TERRAIN:
   1688 								if (((TerrainClass *)obj)->Class->IsFlammable &&
   1689 										BulletTypeClass::As_Reference(Weapons[Class->Primary].Fires).Warhead == WARHEAD_FIRE) {
   1690 
   1691 									if (retval < MOVE_DESTROYABLE) retval = MOVE_DESTROYABLE;
   1692 								} else {
   1693 									return(MOVE_NO);
   1694 								}
   1695 								break;
   1696 
   1697 							default:
   1698 								if (retval < MOVE_DESTROYABLE) retval = MOVE_DESTROYABLE;
   1699 								break;
   1700 						}
   1701 					} else {
   1702 						if (retval < MOVE_CLOAK) retval = MOVE_CLOAK;
   1703 					}
   1704 				}
   1705 			}
   1706 		}
   1707 
   1708 		/*
   1709 		**	Move to next object in chain.
   1710 		*/
   1711 		obj = obj->Next;
   1712 	}
   1713 
   1714 	/*
   1715 	**	If foot soldiers cannot travel on the cell -- consider it impassible.
   1716 	*/
   1717 	if (retval == MOVE_OK && !IsTethered && !Ground[cellptr->Land_Type()].Cost[SPEED_FOOT]) {
   1718 		return(MOVE_NO);
   1719 	}
   1720 
   1721 	/*
   1722 	** if a unit has the cell reserved then we just can't go in there.
   1723 	*/
   1724 	if (retval == MOVE_OK && cellptr->Flag.Occupy.Vehicle) {
   1725 		return(MOVE_NO);
   1726 	}
   1727 
   1728 	/*
   1729 	** if a block of infantry has the cell reserved then there are two
   1730 	** possibilities...
   1731 	*/
   1732 	if (cellptr->InfType != HOUSE_NONE) {
   1733 		if (House->Is_Ally(cellptr->InfType)) {
   1734 			if ((cellptr->Flag.Composite & 0x1F) == 0x1f) {
   1735 				if (retval < MOVE_MOVING_BLOCK) retval = MOVE_MOVING_BLOCK;
   1736 			}
   1737 		} else {
   1738 			if (Class->Primary != WEAPON_NONE) {
   1739 				if (retval < MOVE_DESTROYABLE) retval = MOVE_DESTROYABLE;
   1740 			} else {
   1741 				return(MOVE_NO);
   1742 			}
   1743 		}
   1744 	}
   1745 
   1746 	/*
   1747 	**	If it is still ok to move the infantry, then perform the last check
   1748 	**	to see if the cell is already full of infantry.
   1749 	*/
   1750 	if (retval == MOVE_OK && (cellptr->Flag.Composite & 0x1F) == 0x1F) {
   1751 		return(MOVE_NO);
   1752 	}
   1753 
   1754 	/*
   1755 	**	Return with the most severe reason why this cell would be impassable.
   1756 	*/
   1757 	return(retval);
   1758 }
   1759 
   1760 
   1761 /***********************************************************************************************
   1762  * InfantryClass::Overlap_List -- The list of cells that the infantry overlaps, but doesn't occ*
   1763  *                                                                                             *
   1764  *    This is a rendering support routine that will return a pointer to a list of cell offsets *
   1765  *    that specify the cells the infantry unit is currently overlapping (graphic wise) but     *
   1766  *    is not considered to occupy. This list is used to update the map display.                *
   1767  *                                                                                             *
   1768  * INPUT:   none                                                                               *
   1769  *                                                                                             *
   1770  * OUTPUT:  Returns a pointer to an offset list for cells that the unit overlaps but doesn't   *
   1771  *          occupy.                                                                            *
   1772  *                                                                                             *
   1773  * WARNINGS:   none                                                                            *
   1774  *                                                                                             *
   1775  * HISTORY:                                                                                    *
   1776  *   09/01/1994 JLB : Created.                                                                 *
   1777  *=============================================================================================*/
   1778 short const * InfantryClass::Overlap_List(void) const
   1779 {
   1780 	Validate();
   1781 	//return(Coord_Spillage_List(Coord, 24 + ((IsSelected || Doing > DO_WALK)?12:0)));
   1782 	return(Coord_Spillage_List(Coord, 24 + ((Doing > DO_WALK || Is_Selected_By_Player())?12:0)));
   1783 //	return(Coord_Spillage_List(Coord, (IsSelected ? 24 : 14))+1);
   1784 }
   1785 
   1786 
   1787 /***********************************************************************************************
   1788  * InfantryClass::Can_Fire -- Can the infantry fire its weapon?                                *
   1789  *                                                                                             *
   1790  *    Determines if the infantry unit can fire on the target. If it can't fire, then the       *
   1791  *    reason why is returned.                                                                  *
   1792  *                                                                                             *
   1793  * INPUT:   target   -- The target to determine if the infantry can fire upon.                 *
   1794  *                                                                                             *
   1795  * OUTPUT:  Returns the fire error type that indicates if the infantry can fire and if it      *
   1796  *          can't, why not.                                                                    *
   1797  *                                                                                             *
   1798  * WARNINGS:   none                                                                            *
   1799  *                                                                                             *
   1800  * HISTORY:                                                                                    *
   1801  *   09/01/1994 JLB : Created.                                                                 *
   1802  *   06/27/1995 JLB : Flame thrower can fire while prone now.                                  *
   1803  *=============================================================================================*/
   1804 FireErrorType InfantryClass::Can_Fire(TARGET target, int which) const
   1805 {
   1806 	Validate();
   1807 	WeaponTypeClass const * weapon = (which == 0) ? &Weapons[Class->Primary] : &Weapons[Class->Secondary];
   1808 
   1809 #ifdef BOXING
   1810 	/*
   1811 	** If in hand-to-hand, and we're currently playing a got-hit animation,
   1812 	** then we can't punch back yet.
   1813 	*/
   1814 	if (IsBoxing) {
   1815 		if ( (Doing>=DO_PUNCH_HIT1 && Doing<=DO_KICK_DEATH) || (Doing == DO_ON_GUARD) ) return FIRE_BUSY;
   1816 		if (Arm) return(FIRE_BUSY);	// don't let fire if still re-arming
   1817 	}
   1818 #endif
   1819 
   1820 	/*
   1821 	**	Don't allow firing if the turret is not ready.
   1822 	*/
   1823 	if (IsFiring) return(FIRE_REARM);
   1824 
   1825 #ifdef OBSOLETE
   1826 	if (weapon->Fires == BULLET_FLAME && IsProne) return(FIRE_ILLEGAL);
   1827 #endif
   1828 
   1829 	/*
   1830 	**	The target must still be legal.
   1831 	*/
   1832 	if (!Target_Legal(target)) {
   1833 		return(FIRE_ILLEGAL);
   1834 	}
   1835 
   1836 	/*
   1837 	**	If this unit cannot fire while moving, then bail.
   1838 	*/
   1839 	if ((IsDriving && Special.IsDefenderAdvantage) || (Doing != DO_NOTHING && !MasterDoControls[Doing].Interrupt)) {
   1840 		return(FIRE_MOVING);
   1841 	}
   1842 
   1843 	/*
   1844 	** If we're moving, but not facing the right direction, then exit.
   1845 	*/
   1846 	if (!Special.IsDefenderAdvantage && IsDriving) {
   1847 		int diff = PrimaryFacing.Difference(Direction(TarCom));
   1848 		if (ABS(diff) >= 32) {
   1849 			return(FIRE_MOVING);
   1850 		}
   1851 	}
   1852 
   1853 	return(FootClass::Can_Fire(target, which));
   1854 }
   1855 
   1856 
   1857 /***********************************************************************************************
   1858  * InfantryClass::Enter_Idle_Mode -- The infantry unit enters idle mode by this routine.       *
   1859  *                                                                                             *
   1860  *    Use this routine when the infantry unit as accomplished its task and needs to find       *
   1861  *    something to do. The default behavior is to enter some idle state such as guarding.      *
   1862  *                                                                                             *
   1863  * INPUT:   initial  -- Is this called when the unit just leaves a factory or is initially     *
   1864  *                      or is initially placed on the map?                                     *
   1865  *                                                                                             *
   1866  * OUTPUT:  none                                                                               *
   1867  *                                                                                             *
   1868  * WARNINGS:   none                                                                            *
   1869  *                                                                                             *
   1870  * HISTORY:                                                                                    *
   1871  *   09/01/1994 JLB : Created.                                                                 *
   1872  *=============================================================================================*/
   1873 void InfantryClass::Enter_Idle_Mode(bool )
   1874 {
   1875 	Validate();
   1876 	MissionType order;
   1877 
   1878 	if (Target_Legal(TarCom)) {
   1879 		order = MISSION_ATTACK;
   1880 	} else {
   1881 		if (Target_Legal(NavCom)) {
   1882 			order = MISSION_MOVE;
   1883 		} else {
   1884 			if (GameToPlay == GAME_NORMAL || House->IsHuman) {
   1885 				order = MISSION_GUARD;
   1886 			} else {
   1887 #ifndef USE_RA_AI
   1888 				order = MISSION_HUNT;
   1889 
   1890 #else
   1891 				//
   1892 				// Added for RA AI in TD. ST - 7/26/2019 9:12AM
   1893 				//
   1894 				// This applies only to non-human houses in a non-normal game type
   1895 				//
   1896 
   1897 				order = MISSION_GUARD;
   1898 
   1899 				if (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA) {
   1900 					return;
   1901 				}
   1902 
   1903 				if (!Team) {
   1904 					if (House->IQ >= Rule.IQGuardArea) {
   1905 						if (Is_Weapon_Equipped()) {
   1906 							order = MISSION_GUARD_AREA;
   1907 						}
   1908 					}
   1909 				}
   1910 #endif
   1911 				
   1912 			}
   1913 		}
   1914 	}
   1915 	Assign_Mission(order);
   1916 }
   1917 
   1918 
   1919 /***********************************************************************************************
   1920  * InfantryClass::Random_Animate -- Randomly animate the infantry (maybe)                      *
   1921  *                                                                                             *
   1922  *    This routine is the random animator initiator for infantry units. This routine should    *
   1923  *    be called regularly. On occasion, it will cause the infantry to go into an idle          *
   1924  *    animation.                                                                               *
   1925  *                                                                                             *
   1926  * INPUT:   none                                                                               *
   1927  *                                                                                             *
   1928  * OUTPUT:  none                                                                               *
   1929  *                                                                                             *
   1930  * WARNINGS:   none                                                                            *
   1931  *                                                                                             *
   1932  * HISTORY:                                                                                    *
   1933  *   09/01/1994 JLB : Created.                                                                 *
   1934  *   12/13/1994 JLB : Does random facing change.                                               *
   1935  *   07/02/1995 JLB : Nikoomba special effects.                                                *
   1936  *=============================================================================================*/
   1937 void InfantryClass::Random_Animate(void)
   1938 {
   1939 	Validate();
   1940 	if (!IsDriving && !IsProne && (Doing == DO_STAND_GUARD || Doing == DO_STAND_READY) && !IsFiring) {
   1941 
   1942 		/*
   1943 		**	Scared infantry will always follow the golden rule of civilians;
   1944 		**		"When in darkness or in doubt, run in circles, scream, and shout!"
   1945 		*/
   1946 		if (Class->IsFraidyCat && !House->IsHuman && Fear > FEAR_ANXIOUS) {
   1947 			Scatter(NULL, true);
   1948 			return;
   1949 		}
   1950 
   1951 		/*
   1952 		**	If Nikoomba is not scared, then he will be doing his thing with random animations.
   1953 		*/
   1954 		if (*this == INFANTRY_C10) {
   1955 			switch (Random_Pick(0, 3)) {
   1956 				case 0:
   1957 					Do_Action(DO_IDLE2);
   1958 					break;
   1959 
   1960 				default:
   1961 					break;
   1962 			}
   1963 		}
   1964 
   1965 		switch (Random_Picky((int)0, (int)55, (char*)NULL, (int)0)) {
   1966 			case 10:
   1967 				Do_Action(DO_SALUTE1);
   1968 				break;
   1969 
   1970 			case 11:
   1971 				Do_Action(DO_SALUTE2);
   1972 				break;
   1973 
   1974 			case 12:
   1975 				Do_Action(DO_GESTURE1);
   1976 				break;
   1977 
   1978 			case 13:
   1979 				Do_Action(DO_GESTURE2);
   1980 				break;
   1981 
   1982 			case 4:
   1983 			case 3:
   1984 			case 0:
   1985 				PrimaryFacing.Set(Facing_Dir(Random_Pick(FACING_N, FACING_NW)));
   1986 				Mark(MARK_CHANGE);
   1987 				break;
   1988 
   1989 			case 1:
   1990 				Do_Action(DO_IDLE1);
   1991 				PrimaryFacing.Set(Facing_Dir(Random_Pick(FACING_N, FACING_NW)));
   1992 				if (Sim_Random_Pick(1,20) == 1 && !Is_Selected_By_Player() && *this == INFANTRY_MOEBIUS && IsDiscoveredByPlayer) {
   1993 					static VocType _response[] = {
   1994 //						VOC_EXCELLENT1,
   1995 //						VOC_EXCELLENT2,
   1996 						VOC_EXCELLENT3,
   1997 //						VOC_EXCELLENT4,
   1998 //						VOC_EXCELLENT5,
   1999 						VOC_QUIP1,
   2000 //						VOC_QUIP2
   2001 					};
   2002 					Sound_Effect(_response[Sim_Random_Pick(0, (int)(sizeof(_response) / sizeof(_response[0]))-1)], Coord);
   2003 				}
   2004 				break;
   2005 
   2006 			case 2:
   2007 				Do_Action(DO_IDLE2);
   2008 				PrimaryFacing.Set(Facing_Dir(Random_Pick(FACING_N, FACING_NW)));
   2009 				if (!Is_Selected_By_Player() && IsOwnedByPlayer && *this == INFANTRY_RAMBO && Sim_Random_Pick(0, 2) == 0) {
   2010 					Sound_Effect(VOC_RAMBO_CMON, Coord);
   2011 				}
   2012 				break;
   2013 
   2014 			/*
   2015 			**	On occasion, civilian types will wander about.
   2016 			*/
   2017 			case 5:
   2018 			case 6:
   2019 			case 7:
   2020 			case 8:
   2021 			case 9:
   2022 				if (!House->IsHuman && Class->IsFraidyCat) {
   2023 					Scatter(NULL, true);
   2024 				}
   2025 				break;
   2026 		}
   2027 	}
   2028 }
   2029 
   2030 
   2031 /***********************************************************************************************
   2032  * InfantryClass::Scatter -- Causes the infantry to scatter to nearby cell.                    *
   2033  *                                                                                             *
   2034  *    This routine is used when the infantry should scatter to a nearby cell. Scattering       *
   2035  *    occurs as an occasional consequence of being fired upon. It is one of the features       *
   2036  *    that makes infantry so "charming".                                                       *
   2037  *                                                                                             *
   2038  * INPUT:   threat   -- The coordinate source of the threat that is causing the infantry to    *
   2039  *                      scatter. If the threat isn't from a particular direction, then this    *
   2040  *                      parameter will be NULL.                                                *
   2041  *                                                                                             *
   2042  * OUTPUT:  none                                                                               *
   2043  *                                                                                             *
   2044  * WARNINGS:   none                                                                            *
   2045  *                                                                                             *
   2046  * HISTORY:                                                                                    *
   2047  *   09/24/1994 JLB : Created.                                                                 *
   2048  *   12/12/1994 JLB : Flame thrower infantry always scatter.                                   *
   2049  *=============================================================================================*/
   2050 void InfantryClass::Scatter(COORDINATE threat, bool forced, bool nokidding)
   2051 {
   2052 	Validate();
   2053 
   2054 	/*
   2055 	**	A unit that is in the process of going somewhere will never scatter.
   2056 	*/
   2057 	if (IsDriving || Target_Legal(NavCom)) forced = false;
   2058 
   2059 	/*
   2060 	**	If the infantry is currently engaged in legitimate combat, then don't
   2061 	**	scatter unless forced to.
   2062 	*/
   2063 	if (!Class->IsFraidyCat && Target_Legal(TarCom) && !forced) return;
   2064 
   2065 	/*
   2066 	**	Don't scatter if performing an action that can't be interrupted.
   2067 	*/
   2068 	if (Doing != DO_NOTHING && !MasterDoControls[Doing].Interrupt) return;
   2069 
   2070 	/*
   2071 	**	For human players, don't scatter the infantry, if the special
   2072 	**	flag has not been enabled that allows infantry scatter.
   2073 	*/
   2074 	if (!Special.IsScatter && !nokidding && House->IsHuman && !forced && !Team) return;
   2075 
   2076 	if (forced || Class->IsFraidyCat /*|| !(Random_Pick(1, 4) == 1)*/) {
   2077 		FacingType	toface;
   2078 		FacingType	newface;
   2079 		CELL			newcell;
   2080 
   2081 		if (threat) {
   2082 			toface = Dir_Facing(Direction8(threat, Coord));
   2083 			toface = toface + (Random_Pick(0, 4)-2);
   2084 		} else {
   2085 			COORDINATE	coord = Coord & 0x00FF00FFL;
   2086 
   2087 			if (coord != 0x00800080L) {
   2088 				toface = Dir_Facing((DirType)Desired_Facing8(0x0080, 0x0080, Coord_X(coord), Coord_Y(coord)));
   2089 			} else {
   2090 				toface = Dir_Facing(PrimaryFacing.Current());
   2091 			}
   2092 			toface = toface + (Random_Pick(0, 4)-2);
   2093 		}
   2094 
   2095 		for (FacingType face = FACING_N; face < FACING_COUNT; face++) {
   2096 			newface = toface + face;
   2097 			newcell = Adjacent_Cell(Coord_Cell(Coord), newface);
   2098 
   2099 			if (Map.In_Radar(newcell) && Can_Enter_Cell(newcell) == MOVE_OK) {
   2100 				if (!Class->IsAvoidingTiberium ||
   2101 					Map[newcell].Overlay == OVERLAY_NONE ||
   2102 					OverlayTypeClass::As_Reference(Map[newcell].Overlay).Land != LAND_TIBERIUM) {
   2103 					Assign_Mission(MISSION_MOVE);
   2104 					Assign_Destination(::As_Target(newcell));
   2105 				}
   2106 			}
   2107 		}
   2108 	}
   2109 }
   2110 
   2111 
   2112 /***********************************************************************************************
   2113  * InfantryClass::Do_Action -- Launches the infantry into an animation sequence.               *
   2114  *                                                                                             *
   2115  *    This starts the infantry into a choreographed animation sequence. These sequences can    *
   2116  *    be as simple as standing up or lying down, but can also be complex, such as dying or     *
   2117  *    performing some idle animation.                                                          *
   2118  *                                                                                             *
   2119  * INPUT:   todo     -- The choreographed sequence to start.                                   *
   2120  *                                                                                             *
   2121  *          force    -- Force starting this animation even if the current animation is flagged *
   2122  *                      as uninterruptible. This is necessary for death animations.            *
   2123  *                                                                                             *
   2124  * OUTPUT:  bool; Was the animation started?                                                   *
   2125  *                                                                                             *
   2126  * WARNINGS:   none                                                                            *
   2127  *                                                                                             *
   2128  * HISTORY:                                                                                    *
   2129  *   09/24/1994 JLB : Created.                                                                 *
   2130  *=============================================================================================*/
   2131 bool InfantryClass::Do_Action(DoType todo, bool force)
   2132 {
   2133 	Validate();
   2134 	if (todo != Doing && (Doing == DO_NOTHING || force || MasterDoControls[Doing].Interrupt)) {
   2135 		Mark(MARK_CHANGE);
   2136 		//Mark(MARK_OVERLAP_UP);
   2137 		Doing = todo;
   2138 		//Mark(MARK_OVERLAP_DOWN);
   2139 		if (todo == DO_IDLE1 || todo == DO_IDLE2) {
   2140 			Set_Rate(Options.Normalize_Delay(MasterDoControls[Doing].Rate));
   2141 		} else {
   2142 			Set_Rate(MasterDoControls[Doing].Rate);
   2143 		}
   2144 		Set_Stage(0);
   2145 
   2146 		/*
   2147 		**	Kludge to make sure that if infantry is in the dying animation, it isn't still
   2148 		**	moving as well.
   2149 		*/
   2150 		if (!Strength) {
   2151 			Stop_Driver();
   2152 		}
   2153 
   2154 		/*
   2155 		**	Since the animation sequence might be interrupted. Set any flags
   2156 		**	necessary so that if interrupted, the affect on the infantry is
   2157 		**	still accomplished.
   2158 		*/
   2159 		switch (todo) {
   2160 			case DO_LIE_DOWN:
   2161 				IsProne = true;
   2162 				break;
   2163 
   2164 			case DO_GET_UP:
   2165 				IsProne = false;
   2166 				break;
   2167 
   2168 			case DO_READY_WEAPON:
   2169 				IsBoxing = false;
   2170 				break;
   2171 
   2172 			case DO_ON_GUARD:
   2173 				IsBoxing = true;
   2174 				PrimaryFacing.Set(Direction8(Center_Coord(), As_Coord(TarCom)));
   2175 				Path[0] = FACING_NONE;
   2176 				break;
   2177 
   2178 			default:
   2179 				break;
   2180 		}
   2181 
   2182 		return(true);
   2183 	}
   2184 
   2185 	return(false);
   2186 }
   2187 
   2188 
   2189 /***********************************************************************************************
   2190  * InfantryClass::Stop_Driver -- Stops the infantry from moving any further.                   *
   2191  *                                                                                             *
   2192  *    This is used to stop the infantry from animating in movement. This function will stop    *
   2193  *    the infantry moving and revert it to either a prone or standing.                         *
   2194  *                                                                                             *
   2195  * INPUT:   none                                                                               *
   2196  *                                                                                             *
   2197  * OUTPUT:  bool; Was the driving stopped?                                                     *
   2198  *                                                                                             *
   2199  * WARNINGS:   none                                                                            *
   2200  *                                                                                             *
   2201  * HISTORY:                                                                                    *
   2202  *   09/24/1994 JLB : Created.                                                                 *
   2203  *=============================================================================================*/
   2204 bool InfantryClass::Stop_Driver(void)
   2205 {
   2206 	Validate();
   2207 	if (Head_To_Coord()) {
   2208 
   2209 		/*
   2210 		**	Remove the "reservation" bit in the destination location.
   2211 		*/
   2212 		Clear_Occupy_Bit(Head_To_Coord());
   2213 	}
   2214 
   2215 	/*
   2216 	**	Set the occupation bit at the current location.
   2217 	*/
   2218 	Set_Occupy_Bit(Coord);
   2219 
   2220 	if (Doing != DO_STAND_READY) {
   2221 		StopDriverFrame = Frame;
   2222 	}
   2223 
   2224 	if (IsProne) {
   2225 		Do_Action(DO_PRONE);
   2226 	} else {
   2227 		Do_Action(DO_STAND_READY);
   2228 	}
   2229 
   2230 	return(FootClass::Stop_Driver());
   2231 }
   2232 
   2233 
   2234 /***********************************************************************************************
   2235  * InfantryClass::Start_Driver -- Handles giving immediate destination and move orders.        *
   2236  *                                                                                             *
   2237  *    Use this routine to being the infantry moving toward the destination specified. The      *
   2238  *    destination is first checked to see if there is a free spot available. Then the infantry *
   2239  *    reserves that spot and begins movement toward it.                                        *
   2240  *                                                                                             *
   2241  * INPUT:   headto   -- The coordinate location desired for the infantry to head to.           *
   2242  *                                                                                             *
   2243  * OUTPUT:  bool; Was the infantry successfully started on its journey? Failure may be because *
   2244  *                the specified destination could not contain the infantry unit.               *
   2245  *                                                                                             *
   2246  * WARNINGS:   none                                                                            *
   2247  *                                                                                             *
   2248  * HISTORY:                                                                                    *
   2249  *   12/21/1994 JLB : Created.                                                                 *
   2250  *   05/14/1995 JLB : Tries to move to closest spot possible.                                  *
   2251  *   05/15/1995 JLB : Uses closest spot if moving onto transport.                              *
   2252  *=============================================================================================*/
   2253 bool InfantryClass::Start_Driver(COORDINATE & headto)
   2254 {
   2255 	Validate();
   2256 	COORDINATE old = headto;
   2257 
   2258 	/*
   2259 	**	Convert the head to coordinate to a legal sub-position location.
   2260 	*/
   2261 	headto = Map[Coord_Cell(headto)].Closest_Free_Spot(Coord_Move(headto, Direction(headto)+DIR_S, 0x007C));
   2262 	if (!headto && Can_Enter_Cell(Coord_Cell(old)) == MOVE_OK) {
   2263 		headto = Map[Coord_Cell(old)].Closest_Free_Spot(Coord_Move(old, Direction(headto)+DIR_S, 0x0080), true);
   2264 	}
   2265 
   2266 	/*
   2267 	**	If the infantry started moving, then fixup the occupation bits.
   2268 	*/
   2269 	if (headto && FootClass::Start_Driver(headto)) {
   2270 		/*
   2271 		**	Remove the occupation bit from the infantry's current location.
   2272 		*/
   2273   		Clear_Occupy_Bit(Coord);
   2274 
   2275 		/*
   2276 		**	Set the occupation bit for the new headto location.
   2277 		*/
   2278 		Set_Occupy_Bit(headto);
   2279 		return(true);
   2280 	}
   2281 
   2282 	return(false);
   2283 }
   2284 
   2285 
   2286 #ifdef NEVER
   2287 /***********************************************************************************************
   2288  * InfantryClass::Set_Primary_Facing -- Change infantry primary facing -- always and instantly *
   2289  *                                                                                             *
   2290  *    This routine ensures that when the infantry primary facing is changes, it is changed     *
   2291  *    instantly and always. There is no provision for infantry facing changing slowly over     *
   2292  *    time as the other vehicles usually do.                                                   *
   2293  *                                                                                             *
   2294  * INPUT:   facing   -- The desired facing for the infantry unit.                              *
   2295  *                                                                                             *
   2296  * OUTPUT:  none                                                                               *
   2297  *                                                                                             *
   2298  * WARNINGS:   none                                                                            *
   2299  *                                                                                             *
   2300  * HISTORY:                                                                                    *
   2301  *   12/11/1994 JLB : Created.                                                                 *
   2302  *=============================================================================================*/
   2303 void InfantryClass::Set_Primary_Facing(DirType facing, bool )
   2304 {
   2305 	Validate();
   2306 	FootClass::Set_Primary_Facing(facing, true);
   2307 }
   2308 #endif
   2309 
   2310 
   2311 /***********************************************************************************************
   2312  * InfantryClass::Limbo -- Performs cleanup operations needed when limboing.                   *
   2313  *                                                                                             *
   2314  *    This routine will clean up the infantry occupation bits (as necessary) as well as stop   *
   2315  *    the infantry movement process when it gets limboed.                                      *
   2316  *                                                                                             *
   2317  * INPUT:   none                                                                               *
   2318  *                                                                                             *
   2319  * OUTPUT:  bool; Was the infantry unit limboed?                                               *
   2320  *                                                                                             *
   2321  * WARNINGS:   none                                                                            *
   2322  *                                                                                             *
   2323  * HISTORY:                                                                                    *
   2324  *   12/22/1994 JLB : Created.                                                                 *
   2325  *=============================================================================================*/
   2326 bool InfantryClass::Limbo(void)
   2327 {
   2328 	Validate();
   2329 	if (!IsInLimbo) {
   2330 		Stop_Driver();
   2331 
   2332 		Clear_Occupy_Bit(Coord);
   2333 	}
   2334 	return(FootClass::Limbo());
   2335 }
   2336 
   2337 
   2338 /***********************************************************************************************
   2339  * InfantryClass::Fire_At -- Fires projectile from infantry unit.                              *
   2340  *                                                                                             *
   2341  *    Use this routine when the infantry unit wishes to fire a projectile. This routine        *
   2342  *    will launch the projectile and perform any other necessary infantry specific operations. *
   2343  *                                                                                             *
   2344  * INPUT:   target   -- The target of the attack.                                              *
   2345  *                                                                                             *
   2346  *          which    -- Which weapon to use for firing. 0=primary, 1=secondary.                *
   2347  *                                                                                             *
   2348  * OUTPUT:  Returns with pointer to the projectile launched. If none could be launched, then   *
   2349  *          NULL is returned. If there is already the maximum bullet objects in play, then     *
   2350  *          this could happen.                                                                 *
   2351  *                                                                                             *
   2352  * WARNINGS:   none                                                                            *
   2353  *                                                                                             *
   2354  * HISTORY:                                                                                    *
   2355  *   12/26/1994 JLB : Created.                                                                 *
   2356  *=============================================================================================*/
   2357 BulletClass * InfantryClass::Fire_At(TARGET target, int which)
   2358 {
   2359 	Validate();
   2360 	BulletClass * bullet = NULL;
   2361 	WeaponTypeClass const * weapon = (which == 0) ? &Weapons[Class->Primary] : &Weapons[Class->Secondary];
   2362 
   2363 	IsFiring = false;
   2364 
   2365 #ifdef BOXING
   2366 	if (IsBoxing) {
   2367 		RadioMessageType	hitaction = (Doing == DO_KICK) ? RADIO_KICK : RADIO_PUNCH;
   2368 
   2369 		/*
   2370 		**	When fighting, verify that the target is legal to proceed. If there is some
   2371 		**	error, then abort fightning mode. Otherwise, tell the target that it has
   2372 		**	just been hit.
   2373 		*/
   2374 		if (In_Radio_Contact() && Target_Legal(target) && Transmit_Message(hitaction) == RADIO_ROGER) {
   2375 			Arm = Rearm_Delay(true);
   2376 		} else {
   2377 
   2378 			/*
   2379 			** Fighting done for some reason, so pick up gun
   2380 			*/
   2381 			IsBoxing = false;
   2382 			Do_Action(DO_READY_WEAPON,true);
   2383 		}
   2384 	} else {
   2385 #endif
   2386 
   2387 		bullet = FootClass::Fire_At(target, which);
   2388 		if (bullet) {
   2389 
   2390 			/*
   2391 			**	For fraidycat infantry that run out of ammo, always go into
   2392 			**	a maximum fear state at that time.
   2393 			*/
   2394 			if (Class->IsFraidyCat && !Ammo) {
   2395 				Fear = FEAR_MAXIMUM;
   2396 				if (Mission == MISSION_ATTACK || Mission == MISSION_HUNT) {
   2397 					Assign_Mission(MISSION_GUARD);
   2398 				}
   2399 			}
   2400 
   2401 			/*
   2402 			**	Create the projectile. Then process any special operations that
   2403 			**	need to be performed according to the style of projectile
   2404 			**	created.
   2405 			*/
   2406 			Sound_Effect(weapon->Sound, Coord);
   2407 		}
   2408 
   2409 #ifdef BOXING
   2410 	}
   2411 #endif
   2412 	return(bullet);
   2413 }
   2414 
   2415 
   2416 /***********************************************************************************************
   2417  * InfantryClass::Unlimbo -- Unlimbo infantry unit in legal sub-location.                      *
   2418  *                                                                                             *
   2419  *    This will attempt to unlimbo the infantry unit at the designated coordinate, but will    *
   2420  *    ensure that the coordinate is a legal subposition.                                       *
   2421  *                                                                                             *
   2422  * INPUT:   coord    -- The coordinate to unimbo the infantry at.                              *
   2423  *                                                                                             *
   2424  *          facing   -- The desired initial facing for the infantry unit.                      *
   2425  *                                                                                             *
   2426  *          strength -- The desired initial strength for the infantry unit.                    *
   2427  *                                                                                             *
   2428  *          mission  -- The desired initial mission for the infantry unit.                     *
   2429  *                                                                                             *
   2430  * OUTPUT:  bool; Was the infantry unlimboed successfully?                                     *
   2431  *                                                                                             *
   2432  * WARNINGS:   none                                                                            *
   2433  *                                                                                             *
   2434  * HISTORY:                                                                                    *
   2435  *   12/26/1994 JLB : Created.                                                                 *
   2436  *=============================================================================================*/
   2437 bool InfantryClass::Unlimbo(COORDINATE coord, DirType facing)
   2438 {
   2439 	Validate();
   2440 	/*
   2441 	**	Make sure that the infantry start in a legal position on the map.
   2442 	*/
   2443 	coord = Map[Coord_Cell(coord)].Closest_Free_Spot(coord, ScenarioInit);
   2444 	if (coord == NULL) {
   2445 		return(false);
   2446 	}
   2447 
   2448 	if (FootClass::Unlimbo(coord, facing)) {
   2449 
   2450 		/*
   2451 		**	Ensure that the owning house knows about the
   2452 		**	new object.
   2453 		*/
   2454 		House->IScan |= (1L << Class->Type);
   2455 		House->ActiveIScan |= (1L << Class->Type);
   2456 
   2457 		/*
   2458 		**	If there is no sight range, then this object isn't discovered by the player unless
   2459 		**	it actually appears in a cell mapped by the player.
   2460 		*/
   2461 		if (Class->SightRange == 0 && GameToPlay == GAME_NORMAL && !House->IsHuman && !Map[Coord_Cell(coord)].Is_Visible(PlayerPtr)) {
   2462 			IsDiscoveredByPlayerMask &= ~(1 << (int)PlayerPtr->Class->House);
   2463 			IsDiscoveredByPlayer = false;
   2464 		}
   2465 
   2466 		Set_Occupy_Bit(coord);
   2467 		return(true);
   2468 	}
   2469 	return(false);
   2470 }
   2471 
   2472 
   2473 /***********************************************************************************************
   2474  * InfantryClass::Greatest_Threat -- Determines greatest threat (target) for infantry unit.    *
   2475  *                                                                                             *
   2476  *    This routine intercepts the Greatest_Threat request and adds the appropriate target      *
   2477  *    types to search for. For regular infantry, this consists of all the ground types. For    *
   2478  *    rocket launching infantry, this also includes aircraft.                                  *
   2479  *                                                                                             *
   2480  * INPUT:   threat   -- The basic threat control value.                                        *
   2481  *                                                                                             *
   2482  * OUTPUT:  Returns with the best target for this infantry unit to attack. If no suitable      *
   2483  *          target could be found, then TARGET_NONE is returned.                               *
   2484  *                                                                                             *
   2485  * WARNINGS:   none                                                                            *
   2486  *                                                                                             *
   2487  * HISTORY:                                                                                    *
   2488  *   01/01/1995 JLB : Created.                                                                 *
   2489  *=============================================================================================*/
   2490 TARGET InfantryClass::Greatest_Threat(ThreatType threat) const
   2491 {
   2492 	Validate();
   2493 	/*
   2494 	**	Engineers consider only buildings that can be captures as being a threat. All others
   2495 	**	are ignored.
   2496 	*/
   2497 	if (Class->IsCapture && Class->Primary == WEAPON_NONE) {
   2498 		threat = threat | THREAT_CAPTURE;
   2499 	}
   2500 
   2501 	switch (Class->Primary) {
   2502 		case WEAPON_NONE:
   2503 			if (*this != INFANTRY_E7) {
   2504 				return(TARGET_NONE);
   2505 			}
   2506 			// fall into next case.
   2507 
   2508 			//
   2509 			// ^
   2510 			// | Original comment above.
   2511 			//
   2512 			// Crash here because INFANTRY_E7 has no primary weapon and WEAPON_NONE == -1, so we will reference a -ve index into the Weapons array.
   2513 			// Assume original intent was to fall out of the switch and call the base class Greatest_Threat, so adding a break here.
   2514 			// ST - 4/24/2019 11:01AM
   2515 			//
   2516 			break;		                   // Added. ST - 4/24/2019 11:02AM
   2517 
   2518 		/*
   2519 		**	Dragon missile equiped soldiers are also assumed to carry a Stinger missile. As such,
   2520 		**	they will consider aircraft a legal target.
   2521 		*/
   2522 		default:
   2523 			if (BulletTypeClass::As_Reference(Weapons[Class->Primary].Fires).IsAntiAircraft) {
   2524 				threat = threat | THREAT_AIR;
   2525 			}
   2526 			break;
   2527 
   2528 		/*
   2529 		**	The sniper rifle equipped soldier doesn't go hunting for targets
   2530 		**	unless specifically in hunt mode.
   2531 		*/
   2532 		case WEAPON_RIFLE:
   2533 			if (House->IsHuman && (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA)) {
   2534 				return(TARGET_NONE);
   2535 			}
   2536 			return(TechnoClass::Greatest_Threat(threat | THREAT_INFANTRY|THREAT_BUILDINGS));
   2537 	}
   2538 	return(FootClass::Greatest_Threat(threat));
   2539 }
   2540 
   2541 
   2542 /***********************************************************************************************
   2543  * InfantryClass::Response_Select -- Plays infantry audio response due to being selected.      *
   2544  *                                                                                             *
   2545  *    This routine handles playing an audio response as a result of the player selecting the   *
   2546  *    infantry unit. This occurs prior to giving it an order and may not be followed by any    *
   2547  *    order at all.                                                                            *
   2548  *                                                                                             *
   2549  * INPUT:   none                                                                               *
   2550  *                                                                                             *
   2551  * OUTPUT:  none                                                                               *
   2552  *                                                                                             *
   2553  * WARNINGS:   none                                                                            *
   2554  *                                                                                             *
   2555  * HISTORY:                                                                                    *
   2556  *   01/01/1995 JLB : Created.                                                                 *
   2557  *   05/05/1995 JLB : Rambo response types added.                                              *
   2558  *=============================================================================================*/
   2559 void InfantryClass::Response_Select(void)
   2560 {
   2561 	Validate();
   2562 	VocType response;
   2563 	if (*this == INFANTRY_RAMBO) {
   2564 		static VocType _response[] = {
   2565 			VOC_RAMBO_YEA,
   2566 			VOC_RAMBO_YES,
   2567 			VOC_RAMBO_YO
   2568 		};
   2569 		response = _response[Sim_Random_Pick(0, (int)(sizeof(_response) / sizeof(_response[0]))-1)];
   2570 	} else {
   2571 		if (Class->IsCivilian) {
   2572 			if (*this == INFANTRY_MOEBIUS) {
   2573 				static VocType _response[] = {
   2574 					VOC_YES,
   2575 					VOC_COMMANDER,
   2576 					VOC_HELLO,
   2577 					VOC_HMMM
   2578 				};
   2579 				response = _response[Sim_Random_Pick(0, (int)(sizeof(_response) / sizeof(_response[0]))-1)];
   2580 			} else {
   2581 				if (Class->IsFemale) {
   2582 					response = VOC_GIRL_YEAH;
   2583 				} else {
   2584 					response = VOC_GUY_YEAH;
   2585 				}
   2586 			}
   2587 		} else {
   2588 			static VocType _response[] = {
   2589 				VOC_ACKNOWL,
   2590 				VOC_REPORT,
   2591 				VOC_REPORT,
   2592 				VOC_YESSIR,
   2593 				VOC_YESSIR,
   2594 				VOC_READY,
   2595 				VOC_AWAIT
   2596 			};
   2597 			response = _response[Sim_Random_Pick(0, (int)(sizeof(_response) / sizeof(_response[0]))-1)];
   2598 		}
   2599 	}
   2600 	if (AllowVoice) {
   2601 		Sound_Effect(response, 0, Infantry.ID(this)+1);
   2602 	}
   2603 }
   2604 
   2605 
   2606 /***********************************************************************************************
   2607  * InfantryClass::Response_Move -- Plays infantry response to movement order.                  *
   2608  *                                                                                             *
   2609  *    When the infantry is given the order to move, this routine handles the audio repsonse    *
   2610  *    generated by the infantry unit.                                                          *
   2611  *                                                                                             *
   2612  * INPUT:   none                                                                               *
   2613  *                                                                                             *
   2614  * OUTPUT:  none                                                                               *
   2615  *                                                                                             *
   2616  * WARNINGS:   none                                                                            *
   2617  *                                                                                             *
   2618  * HISTORY:                                                                                    *
   2619  *   01/01/1995 JLB : Created.                                                                 *
   2620  *   05/05/1995 JLB : Rambo response types added.                                              *
   2621  *=============================================================================================*/
   2622 void InfantryClass::Response_Move(void)
   2623 {
   2624 	Validate();
   2625 	VocType response;
   2626 	if (*this == INFANTRY_RAMBO) {
   2627 		static VocType _response[] = {
   2628 			VOC_RAMBO_UGOTIT,
   2629 			VOC_RAMBO_ONIT,
   2630 			VOC_RAMBO_NOPROB
   2631 		};
   2632 		response = _response[Sim_Random_Pick(0, (int)(sizeof(_response) / sizeof(_response[0]))-1)];
   2633 	} else {
   2634 		if (Class->IsCivilian) {
   2635 			if (*this == INFANTRY_MOEBIUS) {
   2636 				static VocType _response[] = {
   2637 					VOC_OF_COURSE,
   2638 					VOC_YESYES
   2639 				};
   2640 				response = _response[Sim_Random_Pick(0, (int)(sizeof(_response) / sizeof(_response[0]))-1)];
   2641 			} else {
   2642 				if (Class->IsFemale) {
   2643 					response = VOC_GIRL_OKAY;
   2644 				} else {
   2645 					response = VOC_GUY_OKAY;
   2646 				}
   2647 			}
   2648 		} else {
   2649 			static VocType _response[] = {
   2650 				VOC_MOVEOUT,
   2651 				VOC_MOVEOUT,
   2652 				VOC_MOVEOUT,
   2653 				VOC_ROGER,
   2654 				VOC_RIGHT_AWAY,
   2655 				VOC_UGOTIT,
   2656 				VOC_AFFIRM,
   2657 				VOC_AFFIRM
   2658 			};
   2659 			response = _response[Sim_Random_Pick(0, (int)(sizeof(_response) / sizeof(_response[0]))-1)];
   2660 		}
   2661 	}
   2662 	if (AllowVoice) {
   2663 		Sound_Effect(response, 0, Infantry.ID(this)+1);
   2664 	}
   2665 }
   2666 
   2667 
   2668 /***********************************************************************************************
   2669  * InfantryClass::Response_Attack -- Plays infantry audio response to attack order.            *
   2670  *                                                                                             *
   2671  *    When the player gives an infantry unit the order to attack, this routine handles         *
   2672  *    the audio response by that unit.                                                         *
   2673  *                                                                                             *
   2674  * INPUT:   none                                                                               *
   2675  *                                                                                             *
   2676  * OUTPUT:  none                                                                               *
   2677  *                                                                                             *
   2678  * WARNINGS:   none                                                                            *
   2679  *                                                                                             *
   2680  * HISTORY:                                                                                    *
   2681  *   01/01/1995 JLB : Created.                                                                 *
   2682  *   05/05/1995 JLB : Rambo response types added.                                              *
   2683  *=============================================================================================*/
   2684 void InfantryClass::Response_Attack(void)
   2685 {
   2686 	Validate();
   2687 	VocType response;
   2688 	if (*this == INFANTRY_RAMBO) {
   2689 		static VocType _response[] = {
   2690 			VOC_RAMBO_NOPROB,
   2691 			VOC_RAMBO_UGOTIT,
   2692 			VOC_RAMBO_NOPROB,
   2693 			VOC_RAMBO_ONIT
   2694 		};
   2695 		response = _response[Sim_Random_Pick(0, (int)(sizeof(_response) / sizeof(_response[0]))-1)];
   2696 	} else {
   2697 		if (Class->IsCivilian) {
   2698 			if (Class->IsFemale) {
   2699 				response = VOC_GIRL_OKAY;
   2700 			} else {
   2701 				response = VOC_GUY_OKAY;
   2702 			}
   2703 		} else {
   2704 			static VocType _response[] = {
   2705 				VOC_RIGHT_AWAY,
   2706 				VOC_AFFIRM,
   2707 				VOC_AFFIRM,
   2708 				VOC_UGOTIT,
   2709 				VOC_NO_PROB,
   2710 				VOC_YESSIR,
   2711 				VOC_YESSIR,
   2712 				VOC_YESSIR
   2713 			};
   2714 			response = _response[Sim_Random_Pick(0, (int)(sizeof(_response) / sizeof(_response[0]))-1)];
   2715 		}
   2716 	}
   2717 
   2718 	if (AllowVoice) {
   2719 		Sound_Effect(response, 0, Infantry.ID(this)+1);
   2720 	}
   2721 }
   2722 
   2723 
   2724 /***********************************************************************************************
   2725  * InfantryClass::Fire_Coord -- Calculates the origin point for projectiles fired.             *
   2726  *                                                                                             *
   2727  *    This routine will return with the point of origin for any firing projectiles. Typically, *
   2728  *    this only includes the rocket launcher and the grenade thrower. The other infantry       *
   2729  *    have either invisible projectiles or special animations.                                 *
   2730  *                                                                                             *
   2731  * INPUT:   none                                                                               *
   2732  *                                                                                             *
   2733  * OUTPUT:  Returns with the coordinate where the projectile will appear as it is fired.       *
   2734  *                                                                                             *
   2735  * WARNINGS:   none                                                                            *
   2736  *                                                                                             *
   2737  * HISTORY:                                                                                    *
   2738  *   01/04/1995 JLB : Created.                                                                 *
   2739  *=============================================================================================*/
   2740 COORDINATE InfantryClass::Fire_Coord(int) const
   2741 {
   2742 	Validate();
   2743 	if (Class->Type == INFANTRY_E4) {
   2744 		return(Coord);	// special case for flame thrower guy
   2745 	} else {
   2746 		return(Coord_Add(Coord, XYP_COORD(0, -5)));
   2747 	}
   2748 }
   2749 
   2750 
   2751 /***************************************************************************
   2752  * InfantryClass::Receive_Message -- Process radio messages                *
   2753  *                                                                         *
   2754  *    If the infantry's boxing, it needs to return to a normal state when  *
   2755  *    his opponent moves away.  Otherwise fall thru to FootClass processing*
   2756  *                                                                         *
   2757  * INPUT:   from    - Pointer to the originator of this message.           *
   2758  *                                                                         *
   2759  *          message - the message to process                               *
   2760  *                                                                         *
   2761  *          param    -- Reference to an optional parameter that can be     *
   2762  *                      used to transfer more information than is          *
   2763  *                      possible with the simple radio message values.     *
   2764  *                                                                         *
   2765  * OUTPUT:  an appropriate response message                                *
   2766  *                                                                         *
   2767  * WARNINGS:                                                               *
   2768  *                                                                         *
   2769  * HISTORY:                                                                *
   2770  *   01/19/1995 BWG : Created.                                             *
   2771  *   05/14/1995 JLB : Handles loading maneuver messages.                   *
   2772  *=========================================================================*/
   2773 RadioMessageType InfantryClass::Receive_Message(RadioClass * from, RadioMessageType message, long & param)
   2774 {
   2775 	Validate();
   2776 	int damage;
   2777 
   2778 	switch (message) {
   2779 
   2780 		case	RADIO_OVER_OUT:
   2781 #ifdef BOXING
   2782 			if (IsBoxing) Do_Action(DO_READY_WEAPON);
   2783 #endif
   2784 			break;
   2785 
   2786 		/*
   2787 		**	Request a fisticuff fight. If this infantry is already involved in a fight,
   2788 		**	then refuse the offer.
   2789 		*/
   2790 		case	RADIO_PREPARE_TO_BOX:
   2791 #ifdef BOXING
   2792 			if (IsBoxing) break;
   2793 #endif
   2794 			if (Contact_With_Whom() == from) {
   2795 				Do_Action(DO_ON_GUARD, true);
   2796 				Assign_Target(Contact_With_Whom()->As_Target());
   2797 				return(RADIO_ROGER);
   2798 			}
   2799 			return(RADIO_NEGATIVE);
   2800 
   2801 		/*
   2802 		**	Just received a kick! Take some damage.
   2803 		*/
   2804 		case	RADIO_KICK:
   2805 			damage = Infantry_Kick_Damage[Random_Pick(0, (int)(sizeof(Infantry_Kick_Damage) / sizeof(Infantry_Kick_Damage[0])))];
   2806 			if (Take_Damage(damage, 0, WARHEAD_FOOT, this) == RESULT_DESTROYED) return(RADIO_STATIC);
   2807 			return(RADIO_ROGER);
   2808 
   2809 		/*
   2810 		**	Just recieved a punch! Take some damage.
   2811 		*/
   2812 		case	RADIO_PUNCH:
   2813 			damage = Infantry_Punch_Damage[Random_Pick(0, (int)(sizeof(Infantry_Punch_Damage) / sizeof(Infantry_Punch_Damage[0])))];
   2814 			if (Take_Damage(damage, 0, WARHEAD_FIST, this) == RESULT_DESTROYED) return(RADIO_STATIC);
   2815 			return(RADIO_ROGER);
   2816 
   2817 	}
   2818 	return(FootClass::Receive_Message(from, message, param));
   2819 }
   2820 
   2821 
   2822 /***************************************************************************
   2823  * InfantryClass::Rearm_Delay -- Return Arming delay for infantry if boxing*
   2824  *                                                                         *
   2825  *    If the infantry's in a boxing mode, return an appropriate re-arming  *
   2826  *    delay.  Otherwise return the default return val.                     *
   2827  *                                                                         *
   2828  * INPUT:   second   -- bool; see TechnoClass...                           *
   2829  *                                                                         *
   2830  * OUTPUT:  Returns with the # of game frames to delay before shooting     *
   2831  *                                                                         *
   2832  * WARNINGS:   none                                                        *
   2833  *                                                                         *
   2834  * HISTORY:                                                                *
   2835  *   01/16/1995 BWG : Created.                                             *
   2836  *=========================================================================*/
   2837 int InfantryClass::Rearm_Delay(bool second) const
   2838 {
   2839 	Validate();
   2840 #ifdef BOXING
   2841 	if (IsBoxing) {
   2842 		return(Random_Pick(5, 50));
   2843 	}
   2844 #endif
   2845 	return(FootClass::Rearm_Delay(second));
   2846 }
   2847 
   2848 
   2849 /***********************************************************************************************
   2850  * InfantryClass::Assign_Mission -- Assign mission to infantry object.                         *
   2851  *                                                                                             *
   2852  *    When a new mission is assigned, make sure he gets out of boxing mode.                    *
   2853  *                                                                                             *
   2854  * INPUT:   order -- The new mission to assign to the unit.                                    *
   2855  *                                                                                             *
   2856  * OUTPUT:  none                                                                               *
   2857  *                                                                                             *
   2858  * WARNINGS:   none                                                                            *
   2859  *                                                                                             *
   2860  * HISTORY:                                                                                    *
   2861  *   12/29/1994 JLB : Created.                                                                 *
   2862  *=============================================================================================*/
   2863 void InfantryClass::Assign_Mission(MissionType order)
   2864 {
   2865 	Validate();
   2866 	if (order == MISSION_SABOTAGE) {
   2867 		Sound_Effect(VOC_RAMBO_PRESENT, Coord);
   2868 	}
   2869 
   2870 	IsBoxing = false;
   2871 	FootClass::Assign_Mission(order);
   2872 }
   2873 
   2874 
   2875 /***********************************************************************************************
   2876  * InfantryClass::What_Action -- Infantry units might be able to capture -- check.             *
   2877  *                                                                                             *
   2878  *    This routine checks to see if the infantry unit can capture the specified object rather  *
   2879  *    than merely attacking it. If this is the case, then ACTION_CAPTURE will be returned.     *
   2880  *                                                                                             *
   2881  * INPUT:   object   -- The object that the mouse is currently over.                           *
   2882  *                                                                                             *
   2883  * OUTPUT:  Returns the action that will be performed if the mouse were clicked over the       *
   2884  *          object specified.                                                                  *
   2885  *                                                                                             *
   2886  * WARNINGS:   none                                                                            *
   2887  *                                                                                             *
   2888  * HISTORY:                                                                                    *
   2889  *   03/01/1995 JLB : Created.                                                                 *
   2890  *=============================================================================================*/
   2891 ActionType InfantryClass::What_Action(ObjectClass * object) const
   2892 {
   2893 	Validate();
   2894 	ActionType action = FootClass::What_Action(object);
   2895 
   2896 	/*
   2897 	**	First see if it's a commando, and if he's attacking a building, have him return ACTION_SABOTAGE instead
   2898 	*/
   2899 	if (*this == INFANTRY_RAMBO && action == ACTION_ATTACK && object->What_Am_I() == RTTI_BUILDING) {
   2900 		return(ACTION_SABOTAGE);
   2901 	}
   2902 
   2903 	/*
   2904 	**	There is no self-select action available for infantry types.
   2905 	*/
   2906 	if (action == ACTION_SELF) {
   2907 		action = ACTION_NONE;
   2908 	}
   2909 
   2910 	/*
   2911 	**	Check to see if it can enter a transporter.
   2912 	*/
   2913 	if (
   2914 		House->Is_Ally(object) &&
   2915 		Is_Owned_By_Player() &&			// Changed for multiplayer. ST - 3/13/2019 5:37PM
   2916 		//IsOwnedByPlayer &&
   2917 		object->Is_Techno() &&
   2918 		//IsOwnedByPlayer &&
   2919 		((InfantryClass *)this)->Transmit_Message(RADIO_CAN_LOAD, (TechnoClass*)object) == RADIO_ROGER) {
   2920 //	if (object->Owner() == Owner() && object->What_Am_I() == RTTI_UNIT && ((UnitClass *)object)->Class->IsTransporter && ((UnitClass *)object)->How_Many() < 5) {
   2921 		action = ACTION_ENTER;
   2922 	}
   2923 
   2924 	if (Class->IsCapture && action == ACTION_ATTACK) {
   2925 		if (object->Owner() != Owner() &&
   2926 			((object->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass *)object)->Pip_Count() == 0 && *((AircraftClass *)object) == AIRCRAFT_TRANSPORT) ||
   2927 			(object->What_Am_I() == RTTI_BUILDING &&
   2928 				((BuildingClass *)object)->Can_Capture()))
   2929 			) {
   2930 
   2931 			action = ACTION_CAPTURE;
   2932 		} else {
   2933 			if (Class->Primary == WEAPON_NONE) {
   2934 				action = ACTION_NONE;
   2935 			}
   2936 		}
   2937 	}
   2938 	return(action);
   2939 }
   2940 
   2941 
   2942 /***********************************************************************************************
   2943  * InfantryClass::Read_INI -- Reads units from scenario INI file.                              *
   2944  *                                                                                             *
   2945  *    This routine is used to read all the starting units from the                             *
   2946  *    scenario control INI file. The units are created and placed on the                       *
   2947  *    map by this routine.                                                                     *
   2948  *                                                                                             *
   2949  *    INI entry format:                                                                        *
   2950  *      Housename, Typename, Strength, Cellnum, CellSublocation, Missionname,                  *
   2951  *         Facingnum, Triggername                                                              *
   2952  *                                                                                             *
   2953  * INPUT:   buffer   -- Pointer to the loaded scenario INI file.                               *
   2954  *                                                                                             *
   2955  * OUTPUT:  none                                                                               *
   2956  *                                                                                             *
   2957  * WARNINGS:   none                                                                            *
   2958  *                                                                                             *
   2959  * HISTORY:                                                                                    *
   2960  *   05/24/1994 JLB : Created.                                                                 *
   2961  *=============================================================================================*/
   2962 void InfantryClass::Read_INI(char *buffer)
   2963 {
   2964 	InfantryClass	*infantry;			// Working infantry pointer.
   2965 	char				*tbuffer;		// Accumulation buffer of infantry IDs.
   2966 	HousesType		inhouse;			// Infantry house.
   2967 	InfantryType	classid;			// Infantry class.
   2968 	int				len;				// Length of data in buffer.
   2969 	char				buf[128];
   2970 
   2971 	len = strlen(buffer) + 2;
   2972 	tbuffer = buffer + len;
   2973 
   2974 	/*------------------------------------------------------------------------
   2975 	Read the entire INFANTRY INI section into HIDBUF
   2976 	------------------------------------------------------------------------*/
   2977 	WWGetPrivateProfileString(INI_Name(), NULL, NULL, tbuffer, ShapeBufferSize-len, buffer);
   2978 
   2979 	while (*tbuffer != '\0') {
   2980 
   2981 		/*
   2982 		**	Get an infantry entry
   2983 		*/
   2984 		WWGetPrivateProfileString(INI_Name(), tbuffer, NULL, buf, sizeof(buf)-1, buffer);
   2985 
   2986 		/*
   2987 		**	1st token: house name.
   2988 		*/
   2989 		inhouse = HouseTypeClass::From_Name(strtok(buf, ",\n\r"));
   2990 		if (inhouse != HOUSE_NONE) {
   2991 
   2992 			/*
   2993 			**	2nd token: infantry type name.
   2994 			*/
   2995 			classid = InfantryTypeClass::From_Name(strtok(NULL, ",\n\r"));
   2996 
   2997 			/*
   2998 			**	Special case: replace C7 with C5 on scg08eb
   2999 			*/
   3000 			if (GameToPlay == GAME_NORMAL && PlayerPtr->ActLike == HOUSE_GOOD && Scenario == 8 && ScenVar == SCEN_VAR_B && classid == INFANTRY_C7) {
   3001 				classid = INFANTRY_C5;
   3002 			}
   3003 
   3004 			if (classid != INFANTRY_NONE) {
   3005 
   3006 				if (HouseClass::As_Pointer(inhouse) != NULL) {
   3007 					infantry = new InfantryClass(classid, inhouse);
   3008 					if (infantry) {
   3009 
   3010 						/*
   3011 						**	3rd token: strength.
   3012 						*/
   3013 						int strength = atoi(strtok(NULL, ",\n\r"));
   3014 
   3015 						/*
   3016 						**	4th token: cell #.
   3017 						*/
   3018 						COORDINATE coord = Cell_Coord((CELL)atoi(strtok(NULL, ",\n\r")));
   3019 
   3020 						/*
   3021 						**	5th token: cell sub-location.
   3022 						*/
   3023 						coord = Coord_Add(coord & 0xFF00FF00L, StoppingCoordAbs[atoi(strtok(NULL, ","))]);
   3024 
   3025 						/*
   3026 						**	Fetch the mission and facing.
   3027 						*/
   3028 						MissionType mission = MissionClass::Mission_From_Name(strtok(NULL, ",\n\r"));
   3029 						DirType dir = (DirType)atoi(strtok(NULL,",\n\r"));
   3030 						infantry->Trigger = TriggerClass::As_Pointer(strtok(NULL,",\n\r"));
   3031 						if (infantry->Trigger) {
   3032 							infantry->Trigger->AttachCount++;
   3033 						}
   3034 
   3035 						/*
   3036 						**	Special case: delete pre-placed Chan on scb10ea; he will spawn from the Tech Center.
   3037 						*/
   3038 						bool is_scb10ea_chan = GameToPlay == GAME_NORMAL && PlayerPtr->ActLike == HOUSE_BAD && Scenario == 10 && ScenVar == SCEN_VAR_A && *infantry == INFANTRY_CHAN;
   3039 
   3040 						if (!is_scb10ea_chan && infantry->Unlimbo(coord, dir)) {
   3041 							infantry->Strength = Fixed_To_Cardinal(infantry->Class_Of().MaxStrength, strength);
   3042 							if (GameToPlay == GAME_NORMAL || infantry->House->IsHuman) {
   3043 								infantry->Assign_Mission(mission);
   3044 								infantry->Commence();
   3045 							} else {
   3046 								infantry->Enter_Idle_Mode();
   3047 							}
   3048 						} else {
   3049 
   3050 							/*
   3051 							**	If the infantry could not be unlimboed, then this is a big error.
   3052 							**	Delete the infantry.
   3053 							*/
   3054 							delete infantry;
   3055 						}
   3056 					}
   3057 				}
   3058 			}
   3059 		}
   3060 		tbuffer += strlen(tbuffer)+1;
   3061 	}
   3062 }
   3063 
   3064 
   3065 /***********************************************************************************************
   3066  * InfantryClass::Write_INI -- Writes all the infantry out to an INI file.                     *
   3067  *                                                                                             *
   3068  *    This routine writes all of the infantry in the game out to an INI file. This is used     *
   3069  *    in the scenario editor when the game needs to be saved.                                  *
   3070  *                                                                                             *
   3071  *    INI entry format:                                                                        *
   3072  *      Housename, Typename, Strength, Cellnum, CellSublocation, Missionname,                  *
   3073  *         Facingnum, Triggername                                                              *
   3074  *                                                                                             *
   3075  * INPUT:   buffer   -- A pointer to the loaded INI file staging area.                         *
   3076  *                                                                                             *
   3077  * OUTPUT:  none                                                                               *
   3078  *                                                                                             *
   3079  * WARNINGS:   none                                                                            *
   3080  *                                                                                             *
   3081  * HISTORY:                                                                                    *
   3082  *   05/28/1994 JLB : Created.                                                                 *
   3083  *=============================================================================================*/
   3084 void InfantryClass::Write_INI(char *buffer)
   3085 {
   3086 	int			index;
   3087 	char			uname[10];
   3088 	char			buf[128];
   3089 	char			*tbuffer;		// Accumulation buffer of infantry IDs.
   3090 
   3091 	/*
   3092 	**	First, clear out all existing infantry data from the ini file.
   3093 	*/
   3094 	tbuffer = buffer + strlen(buffer) + 2;
   3095 	WWGetPrivateProfileString(INI_Name(), NULL, NULL, tbuffer, ShapeBufferSize-strlen(buffer), buffer);
   3096 	while (*tbuffer != '\0') {
   3097 		WWWritePrivateProfileString(INI_Name(), tbuffer, NULL, buffer);
   3098 		tbuffer += strlen(tbuffer)+1;
   3099 	}
   3100 
   3101 	/*
   3102 	**	Write the infantry data out.
   3103 	*/
   3104 	for (index = 0; index < Infantry.Count(); index++) {
   3105 		InfantryClass * infantry;
   3106 
   3107 		infantry = Infantry.Ptr(index);
   3108 		if (!infantry->IsInLimbo) {
   3109 
   3110 			sprintf(uname, "%03d", index);
   3111 			sprintf(buf, "%s,%s,%d,%u,%d,%s,%d,%s",
   3112 					infantry->House->Class->IniName,
   3113 					infantry->Class->IniName,
   3114 					infantry->Health_Ratio(),
   3115 					Coord_Cell(infantry->Coord),
   3116 					CellClass::Spot_Index(infantry->Coord),
   3117 					MissionClass::Mission_Name((infantry->Mission == MISSION_NONE) ?
   3118 						infantry->MissionQueue : infantry->Mission),
   3119 					infantry->PrimaryFacing.Current(),
   3120 					infantry->Trigger ? infantry->Trigger->Get_Name() : "None"
   3121 				);
   3122 			WWWritePrivateProfileString(INI_Name(), uname, buf, buffer);
   3123 		}
   3124 	}
   3125 }
   3126 
   3127 
   3128 /***********************************************************************************************
   3129  * InfantryClass::Active_Click_With -- Handles action when clicking with infantry soldier.     *
   3130  *                                                                                             *
   3131  *    This routine is called when the player clicks over an object while this infantry soldier *
   3132  *    is selected. Capture attempts are prohibited if the infantry cannot capture. The         *
   3133  *    command might respond if told to sabotage something.                                     *
   3134  *                                                                                             *
   3135  * INPUT:   action   -- The action that is nominally to be performed.                          *
   3136  *                                                                                             *
   3137  *          object   -- The object over which the mouse was clicked.                           *
   3138  *                                                                                             *
   3139  * OUTPUT:  none                                                                               *
   3140  *                                                                                             *
   3141  * WARNINGS:   none                                                                            *
   3142  *                                                                                             *
   3143  * HISTORY:                                                                                    *
   3144  *   05/08/1995 JLB : Created.                                                                 *
   3145  *=============================================================================================*/
   3146 void InfantryClass::Active_Click_With(ActionType action, ObjectClass * object)
   3147 {
   3148 	Validate();
   3149 	if (What_Action(object) != action) {
   3150 		switch (action) {
   3151 			case ACTION_SABOTAGE:
   3152 			case ACTION_CAPTURE:
   3153 				action = ACTION_ATTACK;
   3154 				break;
   3155 
   3156 			case ACTION_ENTER:
   3157 				action = ACTION_MOVE;
   3158 				break;
   3159 
   3160 			default:
   3161 				action = ACTION_NONE;
   3162 				break;
   3163 		}
   3164 	}
   3165 
   3166 	FootClass::Active_Click_With(action, object);
   3167 }
   3168 
   3169 
   3170 /***********************************************************************************************
   3171  * InfantryClass::Made_A_Kill -- Marks a kill caused by this infantry soldier.                 *
   3172  *                                                                                             *
   3173  *    When the infantry soldier is responsible for a kill, this routine is called. It checks   *
   3174  *    to see if the soldier should make some comment or perform some action. The commando      *
   3175  *    infantry is most likely to respond.                                                      *
   3176  *                                                                                             *
   3177  * INPUT:   none                                                                               *
   3178  *                                                                                             *
   3179  * OUTPUT:  Returns the number of kills this infantry soldier has made.                        *
   3180  *                                                                                             *
   3181  * WARNINGS:   none                                                                            *
   3182  *                                                                                             *
   3183  * HISTORY:                                                                                    *
   3184  *   05/08/1995 JLB : Created.                                                                 *
   3185  *=============================================================================================*/
   3186 int InfantryClass::Made_A_Kill(void)
   3187 {
   3188 	Validate();
   3189 	if (*this == INFANTRY_RAMBO || Random_Pick(0, 5) < Kills) {
   3190 		IsStoked = true;
   3191 		Comment = TICKS_PER_SECOND*2;
   3192 	}
   3193 	return(FootClass::Made_A_Kill());
   3194 }
   3195 
   3196 
   3197 /***********************************************************************************************
   3198  * InfantryClass::Set_Occupy_Bit -- Sets the occupy bit cell and bit pos                       *
   3199  *                                                                                             *
   3200  * INPUT:      CELL      - the cell we are setting the bit in                                  *
   3201  *                                                                                             *
   3202  *               int      - the spot index we are setting the bit for                          *
   3203  *                                                                                             *
   3204  * OUTPUT:     none                                                                            *
   3205  *                                                                                             *
   3206  * HISTORY:                                                                                    *
   3207  *   06/08/1995 PWG : Created.                                                                 *
   3208  *=============================================================================================*/
   3209 void InfantryClass::Set_Occupy_Bit(CELL cell, int spot_index)
   3210 {
   3211 	Validate();
   3212 
   3213 	if ((unsigned)cell >= MAP_CELL_TOTAL) {
   3214 		return;
   3215 	}
   3216 
   3217 	/*
   3218 	** Set the occupy postion for the spot that we passed in
   3219 	*/
   3220 	Map[cell].Flag.Composite |= (1 << spot_index);
   3221 
   3222 	/*
   3223 	** Record the type of infantry that now owns the cell
   3224 	*/
   3225 	Map[cell].InfType = Owner();
   3226 }
   3227 
   3228 
   3229 /***************************************************************************
   3230  * InfantryClass::Clear_Occupy_Bit -- Clears occupy bit and given cell		*
   3231  *                                                                         *
   3232  * INPUT:                                                                  *
   3233  *                                                                         *
   3234  * OUTPUT:                                                                 *
   3235  *                                                                         *
   3236  * WARNINGS:                                                               *
   3237  *                                                                         *
   3238  * HISTORY:                                                                *
   3239  *   06/08/1995 PWG : Created.                                             *
   3240  *=========================================================================*/
   3241 void InfantryClass::Clear_Occupy_Bit(CELL cell, int spot_index)
   3242 {
   3243 	Validate();
   3244 
   3245 	if ((unsigned)cell >= MAP_CELL_TOTAL) {
   3246 		return;
   3247 	}
   3248 
   3249 	/*
   3250 	** Clear the occupy bit for the infantry in that cell
   3251 	*/
   3252 	Map[cell].Flag.Composite &= ~(1 << spot_index);
   3253 
   3254 	/*
   3255 	** If he was the last infantry recorded in the cell then
   3256 	** remove the infantry ownership flag.
   3257 	*/
   3258 	if (!(Map[cell].Flag.Composite & 0x1F)) {
   3259 		Map[cell].InfType = HOUSE_NONE;
   3260 	}
   3261 }
   3262 
   3263 
   3264 /***********************************************************************************************
   3265  * InfantryClass::Full_Name -- Fetches the full name of the infantry unit.                     *
   3266  *                                                                                             *
   3267  *    This routine will return with the full name (as a text number) for this infantry         *
   3268  *    unit. Typically, this is the normal name, but in cases of civilian type survivors from   *
   3269  *    a building explosion, it might be a technician instead. In such a case, the special      *
   3270  *    technician name number is returned instead.                                              *
   3271  *                                                                                             *
   3272  * INPUT:   none                                                                               *
   3273  *                                                                                             *
   3274  * OUTPUT:  Returns with the full name to use for this infantry unit.                          *
   3275  *                                                                                             *
   3276  * WARNINGS:   none                                                                            *
   3277  *                                                                                             *
   3278  * HISTORY:                                                                                    *
   3279  *   06/30/1995 JLB : Created.                                                                 *
   3280  *=============================================================================================*/
   3281 int InfantryClass::Full_Name(void) const
   3282 {
   3283 	Validate();
   3284 	if (IsTechnician) {
   3285 		return(TXT_TECHNICIAN);
   3286 	}
   3287 	return(Class->Full_Name());
   3288 }
   3289 
   3290 
   3291 /***********************************************************************************************
   3292  * InfantryClass::Mission_Attack -- Intercept attack mission for special handling.             *
   3293  *                                                                                             *
   3294  *    This routine intercepts the normal attack mission and if an engineer is detected and the *
   3295  *    target is a building, then the engineer will be automatically assigned the capture       *
   3296  *    mission. In other cases, the normal attack logic will proceed.                           *
   3297  *                                                                                             *
   3298  * INPUT:   none                                                                               *
   3299  *                                                                                             *
   3300  * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *
   3301  *                                                                                             *
   3302  * WARNINGS:   none                                                                            *
   3303  *                                                                                             *
   3304  * HISTORY:                                                                                    *
   3305  *   08/07/1995 JLB : Created.                                                                 *
   3306  *=============================================================================================*/
   3307 int InfantryClass::Mission_Attack(void)
   3308 {
   3309 	Validate();
   3310 	if (*this == INFANTRY_E7 && As_Building(TarCom)) {
   3311 		Assign_Destination(TarCom);
   3312 		Assign_Mission(MISSION_CAPTURE);
   3313 		return(1);
   3314 	}
   3315 	return(FootClass::Mission_Attack());
   3316 }
   3317 
   3318 
   3319 RTTIType InfantryClass::What_Am_I(void) const
   3320 {
   3321 	Validate();
   3322 	return(RTTI_INFANTRY);
   3323 }
   3324 
   3325 ActionType InfantryClass::What_Action(CELL cell) const
   3326 {
   3327 	Validate();
   3328 	return FootClass::What_Action(cell);
   3329 }
   3330 
   3331 ObjectTypeClass const & InfantryClass::Class_Of(void) const
   3332 {
   3333 	Validate();
   3334 	return(*Class);
   3335 }
   3336 
   3337 bool InfantryClass::Is_Infantry(void) const
   3338 {
   3339 	Validate();
   3340 	return(true);
   3341 }