CnC_Remastered_Collection

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

TEAM.CPP (127793B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/TEAM.CPP 1     3/03/97 10:25a 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 : TEAM.CPP                                                     *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : 12/11/94                                                     *
     28  *                                                                                             *
     29  *                  Last Update : August 27, 1996 [JLB]                                        *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   TeamClass::AI -- Process team logic.                                                      *
     34  *   TeamClass::Add -- Adds specified object to team.                                          *
     35  *   TeamClass::Assign_Mission_Target -- Sets teams mission target and clears old target       *
     36  *   TeamClass::Calc_Center -- Determines average location of team members.                    *
     37  *   TeamClass::Can_Add -- Determines if the specified object can be added to team.            *
     38  *   TeamClass::Control -- Updates control on a member unit.                                   *
     39  *   TeamClass::Coordinate_Attack -- Handles coordinating a team attack.                       *
     40  *   TeamClass::Coordinate_Conscript -- Gives orders to new recruit.                           *
     41  *   TeamClass::Coordinate_Do -- Handles the team performing specified mission.                *
     42  *   TeamClass::Coordinate_Move -- Handles team movement coordination.                         *
     43  *   TeamClass::Coordinate_Regroup -- Handles team idling (regrouping).                        *
     44  *   TeamClass::Debug_Dump -- Displays debug information about the team.                       *
     45  *   TeamClass::Detach -- Removes specified target from team tracking.                         *
     46  *   TeamClass::Fetch_A_Leader -- Looks for a suitable leader member of the team.              *
     47  *   TeamClass::Has_Entered_Map -- Determines if the entire team has entered the map.          *
     48  *   TeamClass::Init -- Initializes the team objects for scenario preparation.                 *
     49  *   TeamClass::Is_A_Member -- Tests if a unit is a member of a team                           *
     50  *   TeamClass::Is_Leaving_Map -- Checks if team is in process of leaving the map              *
     51  *   TeamClass::Lagging_Units -- Finds and orders any lagging units to catch up.               *
     52  *   TeamClass::Recruit -- Attempts to recruit members to the team for the given index ID.     *
     53  *   TeamClass::Remove -- Removes the specified object from the team.                          *
     54  *   TeamClass::Scan_Limit -- Force all members of the team to have limited scan range.        *
     55  *   TeamClass::Suspend_Teams -- Suspends activity for low priority teams                      *
     56  *   TeamClass::TMision_Patrol -- Handles patrolling from one location to another.             *
     57  *   TeamClass::TMission_Attack -- Perform the team attack mission command.                    *
     58  *   TeamClass::TMission_Follow -- Perform the "follow friendlies" team command.               *
     59  *   TeamClass::TMission_Formation -- Process team formation change command.                   *
     60  *   TeamClass::TMission_Invulnerable -- Makes the entire team invulnerable for a period of tim*
     61  *   TeamClass::TMission_Load -- Tells the team to load onto the transport now.                *
     62  *   TeamClass::TMission_Loop -- Causes the team mission processor to jump to new location.    *
     63  *   TeamClass::TMission_Set_Global -- Performs a set global flag operation.                   *
     64  *   TeamClass::TMission_Spy -- Perform the team spy mission.                                  *
     65  *   TeamClass::TMission_Unload -- Tells the team to unload passengers now.                    *
     66  *   TeamClass::TeamClass -- Constructor for the team object type.                             *
     67  *   TeamClass::Took_Damage -- Informs the team when the team member takes damage.             *
     68  *   TeamClass::operator delete -- Deallocates a team object.                                  *
     69  *   TeamClass::operator new -- Allocates a team object.                                       *
     70  *   TeamClass::~TeamClass -- Team object destructor.                                          *
     71  *   _Is_It_Breathing -- Checks to see if unit is an active team member.                       *
     72  *   _Is_It_Playing -- Determines if unit is active and an initiated team member.              *
     73  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     74 
     75 #include "function.h"
     76 #include "mission.h"
     77 
     78 
     79 /***********************************************************************************************
     80  * _Is_It_Breathing -- Checks to see if unit is an active team member.                         *
     81  *                                                                                             *
     82  *    A unit could be a team member, but not be active. Such a case would occur when a         *
     83  *    reinforcement team is inside a transport. It could also occur if a unit is in the        *
     84  *    process of dying. Call this routine to ensure that the specified unit is a will and      *
     85  *    able participant in the team.                                                            *
     86  *                                                                                             *
     87  * INPUT:   object   -- Pointer to the unit/infantry/aircraft that is to be checked.           *
     88  *                                                                                             *
     89  * OUTPUT:  bool; Is the specified unit active and able to be given commands by the team?      *
     90  *                                                                                             *
     91  * WARNINGS:   none                                                                            *
     92  *                                                                                             *
     93  * HISTORY:                                                                                    *
     94  *   03/11/1996 JLB : Created.                                                                 *
     95  *=============================================================================================*/
     96 static inline bool _Is_It_Breathing(FootClass const * object)
     97 {
     98 	/*
     99 	**	If the object is not present or appears to be dead, then it
    100 	**	certainly isn't an active member of the team.
    101 	*/
    102 	if (object == NULL || !object->IsActive || object->Strength == 0) return(false);
    103 
    104 	/*
    105 	**	If the object is in limbo, then it isn't an active team member either. However, if the
    106 	**	scenario init flag is on, then it is probably a reinforcement issue or scenario
    107 	**	creation situation. In such a case, the members are considered active because they need to
    108 	**	be given special orders and treatment.
    109 	*/
    110 	if (!ScenarioInit && object->IsInLimbo) return(false);
    111 
    112 	/*
    113 	**	Nothing eliminated this object from being considered an active member of the team (i.e.,
    114 	**	"breathing"), then return that it is ok.
    115 	*/
    116 	return(true);
    117 }
    118 
    119 
    120 /***********************************************************************************************
    121  * _Is_It_Playing -- Determines if unit is active and an initiated team member.                *
    122  *                                                                                             *
    123  *    Use this routine to determine if the specified unit is an active participant of the      *
    124  *    team. When a unit is first recruited to the team, it must travel to the team's location  *
    125  *    before it can become an active player. Call this routine to determine if the specified   *
    126  *    unit can be considered an active player.                                                 *
    127  *                                                                                             *
    128  * INPUT:   object   -- Pointer to the object that is to be checked to see if it is an         *
    129  *                      active player.                                                         *
    130  *                                                                                             *
    131  * OUTPUT:  bool; Is the specified unit an active, living, initiated member of the team?       *
    132  *                                                                                             *
    133  * WARNINGS:   none                                                                            *
    134  *                                                                                             *
    135  * HISTORY:                                                                                    *
    136  *   03/11/1996 JLB : Created.                                                                 *
    137  *=============================================================================================*/
    138 static inline bool _Is_It_Playing(FootClass const * object)
    139 {
    140 	/*
    141 	**	If the object is not active, then it certainly can be a participating member of the
    142 	**	team.
    143 	*/
    144 	if (!_Is_It_Breathing(object)) return(false);
    145 
    146 	/*
    147 	**	Only members that have been "Initiated" are considered "playing" participants of the
    148 	**	team. This results in the team members that are racing to regroup with the team (i.e.,
    149 	**	not initiated), will continue to catch up to the team even while the initiated team members
    150 	**	carry out their team specific orders.
    151 	*/
    152 	if (!object->IsInitiated && object->What_Am_I() != RTTI_AIRCRAFT) return(false);
    153 
    154 	/*
    155 	**	If it reaches this point, then nothing appears to disqualify the specified object from
    156 	**	being considered an active playing member of the team. In this case, return that
    157 	**	information.
    158 	*/
    159 	return(true);
    160 }
    161 
    162 
    163 #ifdef CHEAT_KEYS
    164 /***********************************************************************************************
    165  * TeamClass::Debug_Dump -- Displays debug information about the team.                         *
    166  *                                                                                             *
    167  *    This routine will display information about the team. This is useful for debugging       *
    168  *    purposes.                                                                                *
    169  *                                                                                             *
    170  * INPUT:   mono  -- Pointer to the monochrome screen that the debugging information will      *
    171  *                   be displayed on.                                                          *
    172  *                                                                                             *
    173  * OUTPUT:  none                                                                               *
    174  *                                                                                             *
    175  * WARNINGS:   none                                                                            *
    176  *                                                                                             *
    177  * HISTORY:                                                                                    *
    178  *   03/11/1996 JLB : Created.                                                                 *
    179  *=============================================================================================*/
    180 void TeamClass::Debug_Dump(MonoClass * mono) const
    181 {
    182 	mono->Set_Cursor(1, 20);mono->Printf("%8.8s", Class->IniName);
    183 	mono->Set_Cursor(10, 20);mono->Printf("%3d", Total);
    184 	mono->Set_Cursor(17, 20);mono->Printf("%3d", Quantity[Class->ID]);
    185 	if (CurrentMission != -1) {
    186 		mono->Set_Cursor(1, 22);
    187 		mono->Printf("%-29s", Class->MissionList[CurrentMission].Description(CurrentMission));
    188 	}
    189 	mono->Set_Cursor(40, 20);mono->Printf("%-10s", FormationName[Formation]);
    190 	mono->Set_Cursor(22, 20);mono->Printf("%08X", Zone);
    191 	mono->Set_Cursor(31, 20);mono->Printf("%08X", Target);
    192 
    193 	mono->Fill_Attrib(53, 20, 12, 1, IsUnderStrength ? MonoClass::INVERSE : MonoClass::NORMAL);
    194 	mono->Fill_Attrib(53, 21, 12, 1, IsFullStrength ? MonoClass::INVERSE : MonoClass::NORMAL);
    195 	mono->Fill_Attrib(53, 22, 12, 1, IsHasBeen ? MonoClass::INVERSE : MonoClass::NORMAL);
    196 
    197 	mono->Fill_Attrib(66, 20, 12, 1, IsMoving ? MonoClass::INVERSE : MonoClass::NORMAL);
    198 	mono->Fill_Attrib(66, 21, 12, 1, IsForcedActive ? MonoClass::INVERSE : MonoClass::NORMAL);
    199 	mono->Fill_Attrib(66, 22, 12, 1, IsReforming ? MonoClass::INVERSE : MonoClass::NORMAL);
    200 }
    201 #endif
    202 
    203 
    204 /***********************************************************************************************
    205  * TeamClass::Init -- Initializes the team objects for scenario preparation.                   *
    206  *                                                                                             *
    207  *    This routine clears out the team object array in preparation for starting a new          *
    208  *    scenario.                                                                                *
    209  *                                                                                             *
    210  * INPUT:   none                                                                               *
    211  *                                                                                             *
    212  * OUTPUT:  none                                                                               *
    213  *                                                                                             *
    214  * WARNINGS:   none                                                                            *
    215  *                                                                                             *
    216  * HISTORY:                                                                                    *
    217  *   12/29/1994 JLB : Created.                                                                 *
    218  *=============================================================================================*/
    219 void TeamClass::Init(void)
    220 {
    221 	Teams.Free_All();
    222 }
    223 
    224 
    225 /***********************************************************************************************
    226  * TeamClass::operator new -- Allocates a team object.                                         *
    227  *                                                                                             *
    228  *    This routine will allocate a team object from the team object pool.                      *
    229  *                                                                                             *
    230  * INPUT:   size  -- The size of the requested allocation.                                     *
    231  *                                                                                             *
    232  * OUTPUT:  Returns with a pointer to the freshly allocated team object. If an allocation      *
    233  *          could not be made, then NULL is returned.                                          *
    234  *                                                                                             *
    235  * WARNINGS:   none                                                                            *
    236  *                                                                                             *
    237  * HISTORY:                                                                                    *
    238  *   09/21/1995 JLB : Created.                                                                 *
    239  *=============================================================================================*/
    240 void * TeamClass::operator new(size_t)
    241 {
    242 	void * ptr = Teams.Allocate();
    243 	if (ptr != NULL) {
    244 		((TeamClass *)ptr)->Set_Active();
    245 	}
    246 	return(ptr);
    247 }
    248 
    249 
    250 /***********************************************************************************************
    251  * TeamClass::operator delete -- Deallocates a team object.                                    *
    252  *                                                                                             *
    253  *    This routine will return a team object to the team object pool.                          *
    254  *                                                                                             *
    255  * INPUT:   ptr   -- Pointer to the team object to deallocate.                                 *
    256  *                                                                                             *
    257  * OUTPUT:  none                                                                               *
    258  *                                                                                             *
    259  * WARNINGS:   none                                                                            *
    260  *                                                                                             *
    261  * HISTORY:                                                                                    *
    262  *   09/21/1995 JLB : Created.                                                                 *
    263  *=============================================================================================*/
    264 void TeamClass::operator delete(void * ptr)
    265 {
    266 	if (ptr != NULL) {
    267 		((TeamClass *)ptr)->IsActive = false;
    268 	}
    269 	Teams.Free((TeamClass *)ptr);
    270 }
    271 
    272 
    273 /***********************************************************************************************
    274  * TeamClass::~TeamClass -- Team object destructor.                                            *
    275  *                                                                                             *
    276  *    This routine is called when a team object is destroyed. It handles updating the total    *
    277  *    number count for this team object type.                                                  *
    278  *                                                                                             *
    279  * INPUT:   none                                                                               *
    280  *                                                                                             *
    281  * OUTPUT:  none                                                                               *
    282  *                                                                                             *
    283  * WARNINGS:   none                                                                            *
    284  *                                                                                             *
    285  * HISTORY:                                                                                    *
    286  *   09/21/1995 JLB : Created.                                                                 *
    287  *   07/04/1996 JLB : Keeps trigger if trigger still attached to objects.                      *
    288  *=============================================================================================*/
    289 TeamClass::~TeamClass(void)
    290 {
    291 	if (GameActive && Class.Is_Valid()) {
    292 		while (Member != NULL) {
    293 			Remove(Member);
    294 		}
    295 		Class->Number--;
    296 
    297 		/*
    298 		**	When the team dies, any trigger associated with it, dies as well. This will only occur
    299 		**	if there are no other objects linked to this trigger. Only player reinforcement
    300 		**	members that broke off of the team earlier will have this occur.
    301 		*/
    302 		if (Trigger.Is_Valid()) {
    303 			if (Trigger->AttachCount == 0) {
    304 				delete (TriggerClass *)Trigger;
    305 			}
    306 			Trigger = NULL;
    307 		}
    308 	}
    309 }
    310 
    311 
    312 /***********************************************************************************************
    313  * TeamClass::TeamClass -- Constructor for the team object type.                               *
    314  *                                                                                             *
    315  *    This routine is called when the team object is created.                                  *
    316  *                                                                                             *
    317  * INPUT:   type  -- Pointer to the team type to make this team object from.                   *
    318  *                                                                                             *
    319  *          owner -- The owner of this team.                                                   *
    320  *                                                                                             *
    321  * OUTPUT:  none                                                                               *
    322  *                                                                                             *
    323  * WARNINGS:   none                                                                            *
    324  *                                                                                             *
    325  * HISTORY:                                                                                    *
    326  *   09/21/1995 JLB : Created.                                                                 *
    327  *=============================================================================================*/
    328 TeamClass::TeamClass(TeamTypeClass const * type, HouseClass * owner) :
    329 	AbstractClass(RTTI_TEAM, Teams.ID(this)),
    330 	Class((TeamTypeClass *)type),
    331 	House(owner),
    332 	IsForcedActive(false),
    333 	IsHasBeen(false),
    334 	IsFullStrength(false),
    335 	IsUnderStrength(true),
    336 	IsReforming(false),
    337 	IsLagging(false),
    338 	IsAltered(true),
    339 	JustAltered(false),
    340 	IsMoving(false),
    341 	IsNextMission(true),
    342 	IsLeaveMap(false),
    343 	Suspended(false),
    344 	Trigger(NULL),
    345 	Zone(TARGET_NONE),
    346 	ClosestMember(TARGET_NONE),
    347 	MissionTarget(TARGET_NONE),
    348 	Target(TARGET_NONE),
    349 	Total(0),
    350 	Risk(0),
    351 	Formation(FORMATION_NONE),
    352 	SuspendTimer(0),
    353 	CurrentMission(-1),
    354 	TimeOut(0),
    355 	Member(0)
    356 {
    357 	assert(Class);
    358 	assert(Class->IsActive);
    359 	assert(Class->ClassCount > 0);
    360 
    361 	if (owner == NULL) {
    362 		House = HouseClass::As_Pointer(Class->House);
    363 	}
    364 
    365 	memset(Quantity, 0, sizeof(Quantity));
    366 	if (Class->Origin != -1) {
    367 		Zone = ::As_Target(Scen.Waypoint[Class->Origin]);
    368 	}
    369 	Class->Number++;
    370 
    371 	/*
    372 	**	If there is a trigger tightly associated with this team, then
    373 	**	create an instance of that trigger and attach it to the team.
    374 	*/
    375 	if (Class->Trigger.Is_Valid()) {
    376 		Trigger = new TriggerClass(Class->Trigger);
    377 	}
    378 }
    379 
    380 
    381 /***************************************************************************
    382  * TeamClass::Assign_Mission_Target -- Sets mission target and clears old  *
    383  *                                                                         *
    384  * INPUT:                                                                  *
    385  *                                                                         *
    386  * OUTPUT:                                                                 *
    387  *                                                                         *
    388  * WARNINGS:                                                               *
    389  *                                                                         *
    390  * HISTORY:                                                                *
    391  *   05/16/1995 PWG : Created.                                             *
    392  *=========================================================================*/
    393 void TeamClass::Assign_Mission_Target(TARGET new_target)
    394 {
    395 	assert(IsActive);
    396 	assert(Teams.ID(this) == ID);
    397 
    398 	/*
    399 	** First go through and find anyone who is currently targeting
    400 	** the old mission target and clear their Tarcom.
    401 	*/
    402 	FootClass * unit = Member;
    403 	if (MissionTarget != TARGET_NONE) {
    404 		while (unit != NULL) {
    405 			bool tar = (unit->TarCom == MissionTarget);
    406 			bool nav = (unit->NavCom == MissionTarget);
    407 			if (tar || nav) {
    408 
    409 				/*
    410 				** If the unit was doing something related to the team mission
    411 				** then we kick him into guard mode so that he is easy to change
    412 				** missions for.
    413 				*/
    414 				unit->Assign_Mission(MISSION_GUARD);
    415 
    416 				/*
    417 				** If the unit's tarcom is set to the old mission target, then
    418 				** clear it, so that it will be reset by whatever happens next.
    419 				*/
    420 				if (nav) {
    421 					unit->Assign_Destination(TARGET_NONE);
    422 				}
    423 
    424 				/*
    425 				** If the unit's navcom is set to the old mission target, then
    426 				** clear it, so that it will be reset by whatever happens next.
    427 				*/
    428 				if (tar) {
    429 					unit->Assign_Target(TARGET_NONE);
    430 				}
    431 			}
    432 			unit = unit->Member;
    433 		}
    434 	}
    435 
    436 	/*
    437 	**	If there is not currently an override on the current mission target
    438 	** then assign both MissionTarget and Target to the new target.  If
    439 	** there is an override, allow the team to keep fighting the override but
    440 	** make sure they pick up on the new mission when they are ready.
    441 	*/
    442 	if (Target == MissionTarget || !Target_Legal(Target)) {
    443 		MissionTarget = Target = new_target;
    444 	} else {
    445 		MissionTarget = new_target;
    446 	}
    447 }
    448 
    449 
    450 /***********************************************************************************************
    451  * TeamClass::AI -- Process team logic.                                                        *
    452  *                                                                                             *
    453  *    General purpose team logic is handled by this routine. It should be called once per      *
    454  *    active team per game tick. This routine handles recruitment and assigning orders to      *
    455  *    member units.                                                                            *
    456  *                                                                                             *
    457  * INPUT:   none                                                                               *
    458  *                                                                                             *
    459  * OUTPUT:  none                                                                               *
    460  *                                                                                             *
    461  * WARNINGS:   none                                                                            *
    462  *                                                                                             *
    463  * HISTORY:                                                                                    *
    464  *   12/29/1994 JLB : Created.                                                                 *
    465  *   01/06/1995 JLB : Choreographed gesture.                                                   *
    466  *=============================================================================================*/
    467 void TeamClass::AI(void)
    468 {
    469 	assert(IsActive);
    470 	assert(Teams.ID(this) == ID);
    471 
    472 	int	desired		= 0;
    473 	int	old_under	= IsUnderStrength;
    474 	int	old_full		= IsFullStrength;
    475 
    476 	/*
    477 	** If the team has been suspended then we need to check if it's time for
    478 	** us to reactivate the team.  If not, no team logic will be processed
    479 	** for this team.
    480 	*/
    481 	if (Suspended) {
    482 		if (SuspendTimer != 0) {
    483 			return;
    484 		}
    485 		Suspended = false;
    486 	}
    487 
    488 	/*
    489 	**	If this team senses that its composition has been altered, then it should
    490 	**	recalculate the under strength and full strength flags.
    491 	*/
    492 	if (IsAltered) {
    493 
    494 		/*
    495 		**	Figure out the total number of objects that this team type requires.
    496 		*/
    497 		for (int index = 0; index < Class->ClassCount; index++) {
    498 			desired += Class->Members[index].Quantity;
    499 		}
    500 		assert(desired != 0);
    501 
    502 		if (Total) {
    503 			IsFullStrength = (Total == desired);
    504 			if (IsFullStrength) {
    505 				IsHasBeen = true;
    506 			}
    507 
    508 			/*
    509 			**	Reinforceable teams will revert (or snap out of) the under strength
    510 			**	mode when the members transition the magic 1/3 strength threshold.
    511 			*/
    512 			if (Class->IsReinforcable) {
    513 				if (desired > 2) {
    514 					IsUnderStrength = (Total <= desired / 3);
    515 				} else {
    516 					IsUnderStrength = (Total < desired);
    517 				}
    518 			} else {
    519 
    520 				/*
    521 				**	Teams that are not flagged as reinforceable are never considered under
    522 				**	strength if the team has already started its main mission. This
    523 				**	ensures that once the team has started, it won't dally to pick up
    524 				**	new members.
    525 				*/
    526 				IsUnderStrength = !IsHasBeen;
    527 			}
    528 
    529 			IsAltered = JustAltered = false;
    530 		} else {
    531 			IsUnderStrength = true;
    532 			IsFullStrength = false;
    533 			Zone = TARGET_NONE;
    534 
    535 			/*
    536 			**	A team that exists on the player's side is automatically destroyed
    537 			**	when there are no team members left. This team was created as a
    538 			**	result of reinforcement logic and no longer needs to exist when there
    539 			**	are no more team members.
    540 			*/
    541 			if (IsHasBeen || Session.Type != GAME_NORMAL) {
    542 
    543 				/*
    544 				**	If this team had no members (i.e., the team object wasn't terminated by some
    545 				**	outside means), then pass through the logic triggers to see if one that
    546 				**	depends on this team leaving the map should be sprung.
    547 				*/
    548 				if (IsLeaveMap) {
    549 					for (int index = 0; index < LogicTriggers.Count(); index++) {
    550 						TriggerClass * trig = LogicTriggers[index];
    551 						if (trig->Spring(TEVENT_LEAVES_MAP)) {
    552 							index--;
    553 							if (LogicTriggers.Count() == 0) break;
    554 						}
    555 					}
    556 				}
    557 				delete this;
    558 				return;
    559 			}
    560 		}
    561 
    562 		/*
    563 		** If the team has gone from under strength to no longer under
    564 		** strength than the team needs to reform.
    565 		*/
    566 		if (old_under != IsUnderStrength) {
    567 			IsReforming = true;
    568 		}
    569 	}
    570 
    571 	/*
    572 	**	If the team is under strength, then flag it to regroup.
    573 	*/
    574 	if (IsMoving && IsUnderStrength) {
    575 		IsMoving			= false;
    576 		CurrentMission	= -1;
    577 		if (Total) {
    578 			Calc_Center(Zone, ClosestMember);
    579 
    580 			/*
    581 			** When a team is badly damaged and needs to regroup it should
    582 			** pick a friendly building to go and regroup at.  Its first preference
    583 			** should be somewhere near repair factory.  If it cannot find a repair
    584 			** factory then it should pick another structure that is friendly to
    585 			** its side.
    586 			*/
    587 			CELL 	dest	= As_Cell(Zone);
    588 			int 	max	= 0x7FFFFFFF;
    589 
    590 			for (int index = 0; index < Buildings.Count(); index++) {
    591 				BuildingClass * b = Buildings.Ptr(index);
    592 
    593 				if (b != NULL && !b->IsInLimbo && b->House == House && b->Class->PrimaryWeapon == NULL) {
    594 					CELL cell = Coord_Cell(b->Center_Coord());
    595 					int dist = ::Distance(b->Center_Coord(), As_Coord(Zone)) * (Map.Cell_Threat(cell, House->Class->House) + 1);
    596 
    597 					if (*b == STRUCT_REPAIR) {
    598 						dist /= 2;
    599 					}
    600 					if (dist < max) {
    601 						cell = Fetch_A_Leader()->Safety_Point(As_Cell(Zone), cell, 2, 4);
    602 //						cell = Member->Safety_Point(As_Cell(Zone), cell, 2, 4);
    603 						if (cell != -1) {
    604 							max = dist;
    605 							dest = cell;
    606 						}
    607 					}
    608 				}
    609 			}
    610 
    611 			// Should calculate a regroup location.
    612 			Target = ::As_Target(dest);
    613 			Coordinate_Move();
    614 			return;
    615 		} else {
    616 			Zone = TARGET_NONE;
    617 		}
    618 	}
    619 
    620 	/*
    621 	**	Flag this team into action when it gets to full strength. Human owned teams are only
    622 	**	used for reinforcement purposes -- always consider them at full strength.
    623 	*/
    624 	if (!IsMoving && (IsFullStrength || IsForcedActive)) {
    625 		IsMoving = true;
    626 		IsHasBeen = true;
    627 		IsUnderStrength = false;
    628 
    629 		/*
    630 		**	Infantry can do a gesture when they start their mission. Pick
    631 		**	a gesture at random.
    632 		*/
    633 		FootClass * techno = Member;
    634 		DoType doaction = Percent_Chance(50) ? DO_GESTURE1 : DO_GESTURE2;
    635 		while (techno) {
    636 			if (_Is_It_Breathing(techno) && techno->What_Am_I() == RTTI_INFANTRY) {
    637 				((InfantryClass *)techno)->Do_Action(doaction);
    638 			}
    639 
    640 			if (IsReforming || IsForcedActive) {
    641 				techno->IsInitiated = true;
    642 			}
    643 
    644 			techno = techno->Member;
    645 		}
    646 		CurrentMission	= -1;
    647 		IsNextMission	= true;
    648 //		IsForcedActive = false;
    649 	}
    650 
    651 	/*
    652 	**	If the team is moving or if there is no center position for
    653 	**	the team, then the center position must be recalculated.
    654 	*/
    655 	if (IsReforming || IsMoving || Zone == TARGET_NONE || ClosestMember == TARGET_NONE) {
    656 		Calc_Center(Zone, ClosestMember);
    657 	}
    658 
    659 	/*
    660 	**	Try to recruit members if there is room to do so for this team.
    661 	**	Only try to recruit members for a non player controlled team.
    662 	*/
    663 	if ((!IsMoving || (!IsFullStrength && Class->IsReinforcable)) && ((!House->IsHuman || !IsHasBeen) && Session.Type == GAME_NORMAL)) {
    664 //	if ((!IsMoving || (!IsFullStrength && Class->IsReinforcable)) && ((/*!House->IsHuman ||*/ !IsHasBeen) && Session.Type == GAME_NORMAL)) {
    665 		for (int index = 0; index < Class->ClassCount; index++) {
    666 			if (Quantity[index] < Class->Members[index].Quantity) {
    667 				Recruit(index);
    668 			}
    669 		}
    670 	}
    671 
    672 	/*
    673 	**	If there are no members of the team and the team has reached
    674 	**	full strength at one time, then delete the team.
    675 	*/
    676 	if (Member == NULL && IsHasBeen) {
    677 
    678 		/*
    679 		**	If this team had no members (i.e., the team object wasn't terminated by some
    680 		**	outside means), then pass through the logic triggers to see if one that
    681 		**	depends on this team leaving the map should be sprung.
    682 		*/
    683 		if (IsLeaveMap) {
    684 			for (int index = 0; index < LogicTriggers.Count(); index++) {
    685 				TriggerClass * trig = LogicTriggers[index];
    686 				if (trig->Spring(TEVENT_LEAVES_MAP)) {
    687 					index--;
    688 					if (LogicTriggers.Count() == 0) break;
    689 				}
    690 			}
    691 		}
    692 		delete this;
    693 		return;
    694 	}
    695 
    696 	/*
    697 	**	If the mission should be advanced to the next entry, then do so at
    698 	**	this time. Various events may cause the mission to advance, but it
    699 	**	all boils down to the following change-mission code.
    700 	*/
    701 	if (IsMoving && !IsReforming && IsNextMission) {
    702 		IsNextMission = false;
    703 		CurrentMission++;
    704 		if (CurrentMission < Class->MissionCount) {
    705 			TeamMissionClass const * mission = &Class->MissionList[CurrentMission];
    706 
    707 			TimeOut = mission->Data.Value * (TICKS_PER_MINUTE/10);
    708 			Target = TARGET_NONE;
    709 			switch (mission->Mission) {
    710 
    711 				case TMISSION_MOVECELL:
    712 					Assign_Mission_Target(::As_Target((CELL)(mission->Data.Value)));
    713 					break;
    714 
    715 				case TMISSION_MOVE:
    716 					if ((unsigned)mission->Data.Value < WAYPT_COUNT && Member != NULL) {
    717 						FootClass * leader = Fetch_A_Leader();
    718 						CELL movecell = Scen.Waypoint[mission->Data.Value];
    719 						if (!Is_Leaving_Map()) {
    720 							if (leader->Can_Enter_Cell(movecell) != MOVE_OK) {
    721 								movecell = Map.Nearby_Location(movecell, leader->Techno_Type_Class()->Speed);
    722 							}
    723 						}
    724 						Assign_Mission_Target(::As_Target(movecell));
    725 						Target = ::As_Target(movecell);
    726 					}
    727 					break;
    728 
    729 				case TMISSION_ATT_WAYPT:
    730 				case TMISSION_PATROL:
    731 				case TMISSION_SPY:
    732 					if ((unsigned)mission->Data.Value < WAYPT_COUNT) {
    733 						Assign_Mission_Target(::As_Target(Scen.Waypoint[mission->Data.Value]));
    734 					}
    735 					break;
    736 
    737 				case TMISSION_ATTACKTARCOM:
    738 					Assign_Mission_Target(mission->Data.Value);
    739 					break;
    740 
    741 				case TMISSION_UNLOAD:
    742 				default:
    743 					Assign_Mission_Target(TARGET_NONE);
    744 					break;
    745 			}
    746 		} else {
    747 			delete this;
    748 			return;
    749 		}
    750 	}
    751 
    752 	/*
    753 	**	Perform mission of the team. This depends on the mission list.
    754 	*/
    755 	if (Member != NULL && IsMoving && !IsReforming && !IsUnderStrength) {
    756 
    757 		/*
    758 		** If the current Target has been dealt with but the mission target
    759 		** has not, then the current target needs to be reset to the mission
    760 		** target.
    761 		*/
    762 		if (!Target_Legal(Target)) {
    763 			Target = MissionTarget;
    764 		}
    765 
    766 		/*
    767 		**	If the current mission is one that times out, then check for
    768 		**	this case. If it has timed out then advance to the next
    769 		**	mission in the list or disband the team.
    770 		*/
    771 		TeamMissionClass const * mission = &Class->MissionList[CurrentMission];
    772 //		FootClass	* member = Member;
    773 
    774 		switch (mission->Mission) {
    775 			case TMISSION_PATROL:
    776 				TMission_Patrol();
    777 				break;
    778 
    779 			case TMISSION_FORMATION:
    780 				TMission_Formation();
    781 				break;
    782 
    783 			case TMISSION_ATTACKTARCOM:
    784 			case TMISSION_ATTACK:
    785 				TMission_Attack();
    786 				break;
    787 
    788 			case TMISSION_LOAD:
    789 				TMission_Load();
    790 				break;
    791 
    792 			case TMISSION_DEPLOY:
    793 				TMission_Deploy();
    794 				break;
    795 
    796 			case TMISSION_UNLOAD:
    797 				TMission_Unload();
    798 				break;
    799 
    800 			case TMISSION_MOVE:
    801 			case TMISSION_MOVECELL:
    802 				Coordinate_Move();
    803 				break;
    804 
    805 			/*
    806 			**	All members of this team become invulnerable as if by magic.
    807 			*/
    808 			case TMISSION_INVULNERABLE:
    809 				TMission_Invulnerable();
    810 				break;
    811 
    812 			case TMISSION_GUARD:
    813 				Coordinate_Regroup();
    814 				break;
    815 
    816 			case TMISSION_DO:
    817 				Coordinate_Do();
    818 				break;
    819 
    820 			case TMISSION_SET_GLOBAL:
    821 				TMission_Set_Global();
    822 				break;
    823 
    824 			case TMISSION_ATT_WAYPT:
    825 				if (!Target_Legal(MissionTarget)) {
    826 					Assign_Mission_Target(TARGET_NONE);
    827 					IsNextMission = true;
    828 				} else {
    829 					Coordinate_Attack();
    830 				}
    831 				break;
    832 
    833 			case TMISSION_SPY:
    834 				TMission_Spy();
    835 				break;
    836 
    837 			case TMISSION_HOUND_DOG:
    838 				TMission_Follow();
    839 				break;
    840 
    841 			case TMISSION_LOOP:
    842 				TMission_Loop();
    843 				break;
    844 		}
    845 
    846 		/*
    847 		**	Check for mission time out condition. If the mission does in fact time out, then
    848 		**	flag it so that the team mission list will advance.
    849 		*/
    850 		switch (mission->Mission) {
    851 //			case TMISSION_UNLOAD:
    852 			case TMISSION_GUARD:
    853 				if (TimeOut == 0) {
    854 					IsNextMission = true;
    855 				}
    856 				break;
    857 		}
    858 
    859 	} else {
    860 
    861 		if (IsMoving) {
    862 			IsReforming = !Coordinate_Regroup();
    863 		} else {
    864 			Coordinate_Move();
    865 		}
    866 	}
    867 }
    868 
    869 
    870 /***********************************************************************************************
    871  * TeamClass::Add -- Adds specified object to team.                                            *
    872  *                                                                                             *
    873  *    Use this routine to add the specified object to the team. The object is checked to make  *
    874  *    sure that it can be assigned to the team. If it can't, then the object will be left      *
    875  *    alone and false will be returned.                                                        *
    876  *                                                                                             *
    877  * INPUT:   obj      -- Pointer to the object that is to be assigned to this team.             *
    878  *                                                                                             *
    879  * OUTPUT:  bool; Was the unit added to the team?                                              *
    880  *                                                                                             *
    881  * WARNINGS:   none                                                                            *
    882  *                                                                                             *
    883  * HISTORY:                                                                                    *
    884  *   12/29/1994 JLB : Created.                                                                 *
    885  *   01/02/1995 JLB : Initiation flag setup.                                                   *
    886  *   08/06/1995 JLB : Allows member stealing from lesser priority teams.                       *
    887  *=============================================================================================*/
    888 bool TeamClass::Add(FootClass * obj)
    889 {
    890 	assert(IsActive);
    891 	assert(Teams.ID(this) == ID);
    892 	if (!obj) return(false);
    893 
    894 	int typeindex;
    895 	if (!Can_Add(obj, typeindex)) return(false);
    896 
    897 	/*
    898 	**	All is ok to add the object to the team, but if the object is already part of
    899 	**	another team, then it must be removed from that team first.
    900 	*/
    901 	if (obj->Team.Is_Valid()) {
    902 		obj->Team->Remove(obj);
    903 	}
    904 
    905 	/*
    906 	**	Actually add the object to the team.
    907 	*/
    908 	Quantity[typeindex]++;
    909 	obj->IsInitiated = (Member == NULL);
    910 	obj->Member = Member;
    911 	Member = obj;
    912 	obj->Team = this;
    913 
    914 	/*
    915 	**	If a common trigger is designated for this team type, then attach the
    916 	**	trigger to this team member.
    917 	*/
    918 	if (Trigger.Is_Valid()) {
    919 		obj->Attach_Trigger(Trigger);
    920 	}
    921 
    922 	Total++;
    923 	Risk += obj->Risk();
    924 	if (Zone == TARGET_NONE) {
    925 		Calc_Center(Zone, ClosestMember);
    926 	}
    927 
    928 	/*
    929 	**	Return with success, since the object was added to the team.
    930 	*/
    931 	IsAltered = JustAltered = true;
    932 	return(true);
    933 }
    934 
    935 
    936 /***********************************************************************************************
    937  * TeamClass::Can_Add -- Determines if the specified object can be added to team.              *
    938  *                                                                                             *
    939  *    This routine will examine the team and determine if the specified object can be          *
    940  *    properly added to this team. This is a security check to filter out those objects that   *
    941  *    should not be added because of conflicting priorities or other restrictions.             *
    942  *                                                                                             *
    943  * INPUT:   obj      -- Pointer to the candidate object that is being checked for legal        *
    944  *                      adding to this team.                                                   *
    945  *                                                                                             *
    946  *          typeindex-- The class index number (according to the team type's class array) that *
    947  *                      the candidate object is classified as. The routine processes much      *
    948  *                      faster if you can provide this information, but if you don't, the      *
    949  *                      routine will figure it out.                                            *
    950  *                                                                                             *
    951  * OUTPUT:  bool; Can the specified object be added to this team?                              *
    952  *                                                                                             *
    953  * WARNINGS:   none                                                                            *
    954  *                                                                                             *
    955  * HISTORY:                                                                                    *
    956  *   02/27/1996 JLB : Created.                                                                 *
    957  *=============================================================================================*/
    958 bool TeamClass::Can_Add(FootClass * obj, int & typeindex) const
    959 {
    960 	assert(IsActive);
    961 	assert(Teams.ID(this) == ID);
    962 
    963 	/*
    964 	**	Trying to add the team member to itself is an error condition.
    965 	*/
    966 	if (obj->Team == this) {
    967 		return(false);
    968 	}
    969 
    970 	/*
    971 	**	The object must be active, a member of this house. A special dispensation is given to
    972 	**	units that are in radio contact. It is presumed that they are very busy and should
    973 	**	not be disturbed.
    974 	*/
    975 	if (!_Is_It_Breathing(obj) || obj->In_Radio_Contact() || obj->House != House) {
    976 		return(false);
    977 	}
    978 
    979 	/*
    980 	**	If the object is doing some mission that precludes it from joining
    981 	**	a team then don't add it.
    982 	*/
    983 	if (obj->Mission != MISSION_NONE && !MissionClass::Is_Recruitable_Mission(obj->Mission)) {
    984 		return(false);
    985 	}
    986 
    987 	/*
    988 	**	If this object is part of another team, then check to make sure that it
    989 	**	is permitted to leave the other team in order to join this one. If not,
    990 	**	then no further processing is allowed -- bail.
    991 	*/
    992 	if (obj->Team.Is_Valid() && (obj->Team->Class->RecruitPriority >= Class->RecruitPriority)) {
    993 		return(false);
    994 	}
    995 
    996 	/*
    997 	**	Aircraft that have no ammo for their weapons cannot be recruited into a team.
    998 	*/
    999 	if (obj->What_Am_I() == RTTI_AIRCRAFT && obj->Techno_Type_Class()->PrimaryWeapon != NULL && !obj->Ammo) {
   1000 		return(false);
   1001 	}
   1002 
   1003 	/*
   1004 	**	Search for the exact member index that the candidate object matches.
   1005 	**	If no match could be found, then adding the object to the team cannot
   1006 	**	occur.
   1007 	*/
   1008 	for (typeindex = 0; typeindex < Class->ClassCount; typeindex++) {
   1009 		if (Class->Members[typeindex].Class == &obj->Class_Of()) {
   1010 			break;
   1011 		}
   1012 	}
   1013 	if (typeindex == Class->ClassCount) {
   1014 		return(false);
   1015 	}
   1016 
   1017 	/*
   1018 	**	If the team is already full of this type, then adding the object is not allowed.
   1019 	**	Return with a failure flag in this case.
   1020 	*/
   1021 	if (Quantity[typeindex] >= Class->Members[typeindex].Quantity) {
   1022 		return(false);
   1023 	}
   1024 
   1025 	return(true);
   1026 }
   1027 
   1028 
   1029 
   1030 /***********************************************************************************************
   1031  * TeamClass::Remove -- Removes the specified object from the team.                            *
   1032  *                                                                                             *
   1033  *    Use this routine to remove an object from a team. Objects removed from the team are      *
   1034  *    then available to be recruited by other teams, or even by the same team at a later time. *
   1035  *                                                                                             *
   1036  * INPUT:   obj      -- Pointer to the object that is to be removed from this team.            *
   1037  *                                                                                             *
   1038  *          typeindex-- Optional index of where this object type is specified in the type      *
   1039  *                      type class. This parameter can be omitted. It only serves to make      *
   1040  *                      the removal process faster.                                            *
   1041  *                                                                                             *
   1042  * OUTPUT:  bool; Was the object removed from this team?                                       *
   1043  *                                                                                             *
   1044  * WARNINGS:   none                                                                            *
   1045  *                                                                                             *
   1046  * HISTORY:                                                                                    *
   1047  *   12/29/1994 JLB : Created.                                                                 *
   1048  *   01/02/1995 JLB : Initiation tracking and team captain selection.                          *
   1049  *=============================================================================================*/
   1050 bool TeamClass::Remove(FootClass * obj, int typeindex)
   1051 {
   1052 	assert(IsActive);
   1053 	assert(Teams.ID(this) == ID);
   1054 
   1055 	/*
   1056 	**	Make sure that the object is in fact a member of this team. If not, then it can't
   1057 	**	be removed. Return success because the end result is the same.
   1058 	*/
   1059 	if (this != obj->Team) {
   1060 		return(true);
   1061 	}
   1062 
   1063 	/*
   1064 	**	Detach the common trigger for this team type. Only current and active members of the
   1065 	**	team have that trigger attached. The exception is for player team members that
   1066 	**	get removed from a reinforcement team.
   1067 	*/
   1068 	if (obj->Trigger == Trigger && !obj->House->IsPlayerControl) {
   1069 		obj->Attach_Trigger(NULL);
   1070 	}
   1071 
   1072 	/*
   1073 	**	If the proper team index was not provided, then find it in the type type class. The
   1074 	**	team type class will not be set if the appropriate type could not be found
   1075 	**	for this object. This indicates that the object was illegally added. Continue to
   1076 	**	process however, since removing this object from the team is a good idea.
   1077 	*/
   1078 	if (typeindex == -1) {
   1079 		for (typeindex = 0; typeindex < Class->ClassCount; typeindex++) {
   1080 			if (Class->Members[typeindex].Class == &obj->Class_Of()) {
   1081 				break;
   1082 			}
   1083 		}
   1084 	}
   1085 
   1086 	/*
   1087 	**	Decrement the counter for the team class. There is now one less of this object type.
   1088 	*/
   1089 	if (typeindex < Class->ClassCount) {
   1090 		Quantity[typeindex]--;
   1091 	}
   1092 
   1093 	/*
   1094 	**	Actually remove the object from the team. Scan through the team members
   1095 	**	looking for the one that matches the one specified. If it is found, it
   1096 	**	is unlinked from the member chain. During this scan, a check is made to
   1097 	**	ensure that at least one remaining member is still initiated. If not, then
   1098 	**	a new team captain must be chosen.
   1099 	*/
   1100 	bool initiated = false;
   1101 	FootClass * prev = 0;
   1102 	FootClass * curr = Member;
   1103 	bool found = false;
   1104 	while (curr != NULL && (!found || !initiated)) {
   1105 		if (curr == obj) {
   1106 			if (prev != NULL) {
   1107 				prev->Member = curr->Member;
   1108 			} else {
   1109 				Member = curr->Member;
   1110 			}
   1111 			FootClass * temp = curr->Member;
   1112 			curr->Member = 0;
   1113 			curr->Team = 0;
   1114 			curr->SuspendedMission = MISSION_NONE;
   1115 			curr->SuspendedNavCom = TARGET_NONE;
   1116 			curr->SuspendedTarCom = TARGET_NONE;
   1117 			curr = temp;
   1118 			Total--;
   1119 			found = true;
   1120 			Risk -= obj->Risk();
   1121 			continue;
   1122 		}
   1123 
   1124 		/*
   1125 		**	If this (remaining) member is initiated, then keep a record of this.
   1126 		*/
   1127 		initiated |= curr->IsInitiated;
   1128 
   1129 		prev = curr;
   1130 		curr = curr->Member;
   1131 	}
   1132 
   1133 	/*
   1134 	**	A unit that breaks off of a team will enter idle mode.
   1135 	*/
   1136 	obj->Enter_Idle_Mode();
   1137 
   1138 	/*
   1139 	**	If, after removing the team member, there are no initiated members left
   1140 	**	in the team, then just make the first remaining member of the team the
   1141 	**	team captain. Mark the center location of the team as invalid so that
   1142 	**	it will be centered around the captain.
   1143 	*/
   1144 	if (!initiated && Member != NULL) {
   1145 		Member->IsInitiated = true;
   1146 		Zone = TARGET_NONE;
   1147 	}
   1148 
   1149 	/*
   1150 	**	Must record that the team composition has changed. At the next opportunity,
   1151 	**	the team members will be counted and appropriate AI adjustments made.
   1152 	*/
   1153 	IsAltered = JustAltered = true;
   1154 	return(true);
   1155 }
   1156 
   1157 
   1158 /***********************************************************************************************
   1159  * TeamClass::Recruit -- Attempts to recruit members to the team for the given index ID.       *
   1160  *                                                                                             *
   1161  *    This routine will take the given index ID and scan for available objects of that type    *
   1162  *    to recruit to the team. Recruiting will continue until that object type has either       *
   1163  *    been exhausted or if the team's requirement for that type has been filled.               *
   1164  *                                                                                             *
   1165  * INPUT:   typeindex   -- The index for the object type to recruit. The index is used to      *
   1166  *                         look into the type type's array of object types that make up this   *
   1167  *                         team.                                                               *
   1168  *                                                                                             *
   1169  * OUTPUT:  Returns with the number of objects added to this team.                             *
   1170  *                                                                                             *
   1171  * WARNINGS:   none                                                                            *
   1172  *                                                                                             *
   1173  * HISTORY:                                                                                    *
   1174  *   12/29/1994 JLB : Created.                                                                 *
   1175  *   04/10/1995 JLB : Scans for units too.                                                     *
   1176  *=============================================================================================*/
   1177 int TeamClass::Recruit(int typeindex)
   1178 {
   1179 	assert(IsActive);
   1180 	assert(Teams.ID(this) == ID);
   1181 	COORDINATE center = As_Coord(Zone);
   1182 
   1183 	if (Class->Origin != -1) {
   1184 		center = Cell_Coord(Scen.Waypoint[Class->Origin]);
   1185 	}
   1186 
   1187 	int added = 0;				// Total number added to team.
   1188 
   1189 	/*
   1190 	**	Quick check to see if recruiting is really allowed for this index or not.
   1191 	*/
   1192 	if (Class->Members[typeindex].Quantity > Quantity[typeindex]) {
   1193 		switch (Class->Members[typeindex].Class->What_Am_I()) {
   1194 
   1195 			/*
   1196 			**	For infantry objects, sweep through the infantry in the game looking for
   1197 			**	ones owned by the house that owns the team. When found, try to add.
   1198 			*/
   1199 			case RTTI_INFANTRYTYPE:
   1200 			case RTTI_INFANTRY:
   1201 				{
   1202 					InfantryClass * best = 0;
   1203 					int bestdist = -1;
   1204 
   1205 					for (int index = 0; index < Infantry.Count(); index++) {
   1206 						InfantryClass * infantry = Infantry.Ptr(index);
   1207 						int d = infantry->Distance(center);
   1208 
   1209 						if ((d < bestdist || bestdist == -1) && Can_Add(infantry, typeindex)) {
   1210 							best = infantry;
   1211 							bestdist = d;
   1212 						}
   1213 					}
   1214 
   1215 					if (best) {
   1216 						best->Assign_Target(TARGET_NONE);
   1217 						Add(best);
   1218 						added++;
   1219 					}
   1220 				}
   1221 				break;
   1222 
   1223 			case RTTI_AIRCRAFTTYPE:
   1224 			case RTTI_AIRCRAFT:
   1225 				{
   1226 					AircraftClass * best = 0;
   1227 					int bestdist = -1;
   1228 
   1229 					for (int index = 0; index < Aircraft.Count(); index++) {
   1230 						AircraftClass * aircraft = Aircraft.Ptr(index);
   1231 						int d = aircraft->Distance(center);
   1232 
   1233 						if ((d < bestdist || bestdist == -1) && Can_Add(aircraft, typeindex)) {
   1234 							best = aircraft;
   1235 							bestdist = d;
   1236 						}
   1237 					}
   1238 
   1239 					if (best) {
   1240 						best->Assign_Target(TARGET_NONE);
   1241 						Add(best);
   1242 						added++;
   1243 					}
   1244 				}
   1245 				break;
   1246 
   1247 			case RTTI_UNITTYPE:
   1248 			case RTTI_UNIT:
   1249 				{
   1250 					UnitClass * best = 0;
   1251 					int bestdist = -1;
   1252 
   1253 					for (int index = 0; index < Units.Count(); index++) {
   1254 						UnitClass * unit = Units.Ptr(index);
   1255 						int d = unit->Distance(center);
   1256 
   1257 						if (unit->House == House && unit->Class == Class->Members[typeindex].Class) {
   1258 
   1259 							if ((d < bestdist || bestdist == -1) && Can_Add(unit, typeindex)) {
   1260 								best = unit;
   1261 								bestdist = d;
   1262 							}
   1263 
   1264 						}
   1265 
   1266 						if (best) {
   1267 							best->Assign_Target(TARGET_NONE);
   1268 							Add(best);
   1269 							added++;
   1270 
   1271 							/*
   1272 							**	If a transport is added to the team, the occupants
   1273 							**	are added by default.
   1274 							*/
   1275 							FootClass * f = best->Attached_Object();
   1276 							while (f) {
   1277 								Add(f);
   1278 								f = (FootClass *)(ObjectClass *)f->Next;
   1279 							}
   1280 						}
   1281 					}
   1282 				}
   1283 				break;
   1284 
   1285 			case RTTI_VESSELTYPE:
   1286 			case RTTI_VESSEL:
   1287 				{
   1288 					VesselClass * best = 0;
   1289 					int bestdist = -1;
   1290 
   1291 					for (int index = 0; index < Vessels.Count(); index++) {
   1292 						VesselClass * vessel = Vessels.Ptr(index);
   1293 						int d = vessel->Distance(center);
   1294 
   1295 						if (vessel->House == House && vessel->Class == Class->Members[typeindex].Class) {
   1296 
   1297 							if ((d < bestdist || bestdist == -1) && Can_Add(vessel, typeindex)) {
   1298 								best = vessel;
   1299 								bestdist = d;
   1300 							}
   1301 
   1302 						}
   1303 
   1304 						if (best) {
   1305 							best->Assign_Target(TARGET_NONE);
   1306 							Add(best);
   1307 							added++;
   1308 
   1309 							/*
   1310 							**	If a transport is added to the team, the occupants
   1311 							**	are added by default.
   1312 							*/
   1313 							FootClass * f = best->Attached_Object();
   1314 							while (f) {
   1315 								Add(f);
   1316 								f = (FootClass *)(ObjectClass *)f->Next;
   1317 							}
   1318 						}
   1319 					}
   1320 				}
   1321 				break;
   1322 		}
   1323 	}
   1324 	return(added);
   1325 }
   1326 
   1327 
   1328 /***********************************************************************************************
   1329  * TeamClass::Detach -- Removes specified target from team tracking.                           *
   1330  *                                                                                             *
   1331  *    When a target object is about to be removed from the game (e.g., it was killed), then    *
   1332  *    any team that is looking at that target must abort from that target.                     *
   1333  *                                                                                             *
   1334  * INPUT:   target   -- The target object that is going to be removed from the game.           *
   1335  *                                                                                             *
   1336  *          all      -- Is the target going away for good as opposed to just cloaking/hiding?  *
   1337  *                                                                                             *
   1338  * OUTPUT:  none                                                                               *
   1339  *                                                                                             *
   1340  * WARNINGS:   none                                                                            *
   1341  *                                                                                             *
   1342  * HISTORY:                                                                                    *
   1343  *   12/29/1994 JLB : Created.                                                                 *
   1344  *=============================================================================================*/
   1345 void TeamClass::Detach(TARGET target, bool )
   1346 {
   1347 	assert(IsActive);
   1348 	assert(Teams.ID(this) == ID);
   1349 
   1350 	/*
   1351 	**	If the target to detach matches the target of this team, then remove
   1352 	**	the target from this team's Tar/Nav com and let the chips fall
   1353 	**	where they may.
   1354 	*/
   1355 	if (Target == target) {
   1356 		Target = TARGET_NONE;
   1357 	}
   1358 	if (MissionTarget == target) {
   1359 		MissionTarget = TARGET_NONE;
   1360 	}
   1361 	if (Trigger.Is_Valid() && Trigger->As_Target() == target) {
   1362 		Trigger = 0;
   1363 	}
   1364 }
   1365 
   1366 
   1367 /***********************************************************************************************
   1368  * TeamClass::Calc_Center -- Determines average location of team members.                      *
   1369  *                                                                                             *
   1370  *    Use this routine to calculate the "center" location of the team. This is the average     *
   1371  *    position of all members of the team. Using this center value it is possible to tell      *
   1372  *    if a team member is too far away and where to head to in order to group up.              *
   1373  *                                                                                             *
   1374  * INPUT:   center   -- Average center target location of the team. Only initiated members     *
   1375  *                      will be considered.                                                    *
   1376  *                                                                                             *
   1377  *          close_member--Location (as target) of the unit that is closest to the team's       *
   1378  *                      target.                                                                *
   1379  *                                                                                             *
   1380  * OUTPUT:  none                                                                               *
   1381  *                                                                                             *
   1382  * WARNINGS:   none                                                                            *
   1383  *                                                                                             *
   1384  * HISTORY:                                                                                    *
   1385  *   12/29/1994 JLB : Created.                                                                 *
   1386  *=============================================================================================*/
   1387 void TeamClass::Calc_Center(TARGET & center, TARGET & close_member) const
   1388 {
   1389 	assert(IsActive);
   1390 	assert(Teams.ID(this) == ID);
   1391 
   1392 	/*
   1393 	**	Presume there is no center. This will be confirmed in the following scanning
   1394 	**	operation.
   1395 	*/
   1396 	close_member = TARGET_NONE;
   1397 	center = TARGET_NONE;
   1398 
   1399 	FootClass const * team_member = Member;		// Working team member pointer.
   1400 
   1401 	/*
   1402 	**	If there are no members of the team, then there can be no center point of the team.
   1403 	*/
   1404 	if (team_member == NULL) return;
   1405 
   1406 	/*
   1407 	**	If the team is supposed to follow a nearby friendly unit, then the
   1408 	**	team's "center" will actually be that unit. Otherwise, calculated the
   1409 	**	average center location for the team.
   1410 	*/
   1411 	if (Class->MissionList[CurrentMission].Mission == TMISSION_HOUND_DOG) {
   1412 
   1413 		/*
   1414 		**	First pick a member of the team. The closest friendly object to that member
   1415 		**	will be picked.
   1416 		*/
   1417 		if (!team_member) return;
   1418 
   1419 		FootClass const * closest = NULL;	// Current closest friendly object.
   1420 		int distance = -1;					// Record of last closest distance calc.
   1421 
   1422 		/*
   1423 		**	Scan through all vehicles.
   1424 		*/
   1425 		for (int unit_index = 0; unit_index < Units.Count(); unit_index++) {
   1426 			FootClass const * trial_unit = Units.Ptr(unit_index);
   1427 
   1428 			if (_Is_It_Breathing(trial_unit) && trial_unit->House->Is_Ally(House) && trial_unit->Team != this) {
   1429 				int trial_distance = team_member->Distance(trial_unit);
   1430 
   1431 				if (distance == -1 || trial_distance < distance) {
   1432 					distance = trial_distance;
   1433 					closest = trial_unit;
   1434 				}
   1435 			}
   1436 		}
   1437 
   1438 		/*
   1439 		**	Scan through all infantry.
   1440 		*/
   1441 		for (int infantry_index = 0; infantry_index < Infantry.Count(); infantry_index++) {
   1442 			FootClass const * trial_infantry = Infantry.Ptr(infantry_index);
   1443 
   1444 			if (_Is_It_Breathing(trial_infantry) && trial_infantry->House->Is_Ally(House) && trial_infantry->Team != this) {
   1445 				int trial_distance = team_member->Distance(trial_infantry);
   1446 
   1447 				if (distance == -1 || trial_distance < distance) {
   1448 					distance = trial_distance;
   1449 					closest = trial_infantry;
   1450 				}
   1451 			}
   1452 		}
   1453 
   1454 		/*
   1455 		**	Scan through all vessels.
   1456 		*/
   1457 		for (int vessel_index = 0; vessel_index < Vessels.Count(); vessel_index++) {
   1458 			FootClass const * trial_vessel = Vessels.Ptr(vessel_index);
   1459 
   1460 			if (_Is_It_Breathing(trial_vessel) && trial_vessel->House->Is_Ally(House) && trial_vessel->Team != this) {
   1461 				int trial_distance = team_member->Distance(trial_vessel);
   1462 
   1463 				if (distance == -1 || trial_distance < distance) {
   1464 					distance = trial_distance;
   1465 					closest = trial_vessel;
   1466 				}
   1467 			}
   1468 		}
   1469 
   1470 		/*
   1471 		**	Set the center location as actually the friendly object that is closest. If there
   1472 		**	is no friendly object, then don't set any center location at all.
   1473 		*/
   1474 		if (closest) {
   1475 			center = closest->As_Target();
   1476 			close_member = Member->As_Target();
   1477 		}
   1478 
   1479 	} else {
   1480 
   1481 		long	x = 0;								// Accumulated X coordinate.
   1482 		long	y = 0;								// Accumulated Y coordinate.
   1483 		int   dist = 0;							// Closest recorded distance to team target.
   1484 		int	quantity = 0;						// Number of team members counted.
   1485 		FootClass const * closest = 0;		// Closest member to target.
   1486 
   1487 		/*
   1488 		**	Scan through all team members and accumulate the X and Y component of their
   1489 		**	location. Only team members that are active will be considered. Also keep
   1490 		**	track of the team member that is closest to the team's target.
   1491 		*/
   1492 		while (team_member != NULL) {
   1493 			if (_Is_It_Playing(team_member)) {
   1494 
   1495 				/*
   1496 				**	Accumulate X and Y components of qualified team members.
   1497 				*/
   1498 				x += Coord_X(team_member->Coord);
   1499 				y += Coord_Y(team_member->Coord);
   1500 				quantity++;
   1501 
   1502 				/*
   1503 				**	Keep a record of the team member that is nearest to the team's
   1504 				**	target.
   1505 				*/
   1506 				int try_dist = team_member->Distance(Target);
   1507 				if (!dist || try_dist < dist) {
   1508 					dist = try_dist;
   1509 					closest = team_member;
   1510 				}
   1511 			}
   1512 
   1513 			team_member = team_member->Member;
   1514 		}
   1515 
   1516 		/*
   1517 		**	If there were any qualifying members, then the team's center point can be
   1518 		**	determined.
   1519 		*/
   1520 		if (quantity) {
   1521 			x /= quantity;
   1522 			y /= quantity;
   1523 			COORDINATE coord = XY_Coord((int)x, (int)y);
   1524 			center = ::As_Target(coord);
   1525 
   1526 
   1527 			/*
   1528 			**	If the center location is impassable, then just pick the location of
   1529 			** one of the team members.
   1530 			*/
   1531 			if (!closest->Can_Enter_Cell(As_Cell(center))) {
   1532 //				if (Class->Origin != -1) {
   1533 //					center = ::As_Target(Scen.Waypoint[Class->Origin]);
   1534 //				} else {
   1535 					center = ::As_Target(Coord_Cell(closest->Center_Coord()));
   1536 //				}
   1537 			}
   1538 		}
   1539 
   1540 		/*
   1541 		**	Record the position of the closest member to the team's target and
   1542 		**	that will be used as the regroup point.
   1543 		*/
   1544 		if (closest != NULL) {
   1545 			close_member = ::As_Target(Coord_Cell(closest->Center_Coord()));
   1546 		}
   1547 	}
   1548 }
   1549 
   1550 
   1551 /***********************************************************************************************
   1552  * TeamClass::Took_Damage -- Informs the team when the team member takes damage.               *
   1553  *                                                                                             *
   1554  *    This routine is used when a team member takes damage. Usually the team will react in     *
   1555  *    some fashion to the attack. This reaction can range from running away to assigning this  *
   1556  *    new target as the team's target.                                                         *
   1557  *                                                                                             *
   1558  * INPUT:   obj      -- The team member that was damaged.                                      *
   1559  *                                                                                             *
   1560  *          result   -- The severity of the damage taken.                                      *
   1561  *                                                                                             *
   1562  *          source   -- The perpetrator of the damage.                                         *
   1563  *                                                                                             *
   1564  * OUTPUT:  none                                                                               *
   1565  *                                                                                             *
   1566  * WARNINGS:   none                                                                            *
   1567  *                                                                                             *
   1568  * HISTORY:                                                                                    *
   1569  *   12/29/1994 JLB : Created.                                                                 *
   1570  *=============================================================================================*/
   1571 void TeamClass::Took_Damage(FootClass * , ResultType result, TechnoClass * source)
   1572 {
   1573 	assert(IsActive);
   1574 	assert(Teams.ID(this) == ID);
   1575 
   1576 	if ((result != RESULT_NONE) && (!Class->IsSuicide)) {
   1577 		if (!IsMoving) {
   1578 
   1579 			// TCTCTC
   1580 			// Should run to a better hiding place or disband into a group of hunting units.
   1581 
   1582 		} else {
   1583 			/*
   1584 			** Respond to the attack, but not if we're an aircraft or a LST.
   1585 			*/
   1586 			if (source && !Is_A_Member(source) && Member && Member->What_Am_I() != RTTI_AIRCRAFT && (Member->What_Am_I() != RTTI_VESSEL || *(VesselClass *)((FootClass *)Member) != VESSEL_TRANSPORT)) {
   1587 				if (Target != source->As_Target()) {
   1588 
   1589 					/*
   1590 					**	Don't change target if the team's target is one that can fire as well. There is
   1591 					**	no point in endlessly shuffling between targets that have firepower.
   1592 					*/
   1593 					if (Target_Legal(Target)) {
   1594 						TechnoClass * techno = As_Techno(Target);
   1595 
   1596 						if (techno && ((TechnoTypeClass const &)techno->Class_Of()).PrimaryWeapon != NULL) {
   1597 							if (techno->In_Range(As_Coord(Zone), 0)) {
   1598 								return;
   1599 							}
   1600 						}
   1601 					}
   1602 
   1603 					/*
   1604 					**	Don't change target to aggressor if the aggressor cannot normally be attacked.
   1605 					*/
   1606 					if (source->What_Am_I() == RTTI_AIRCRAFT || (source->What_Am_I() == RTTI_VESSEL && (Member->What_Am_I() == RTTI_UNIT || Member->What_Am_I() == RTTI_INFANTRY))) {
   1607 						return;
   1608 					}
   1609 
   1610 					Target = source->As_Target();
   1611 				}
   1612 			}
   1613 		}
   1614 	}
   1615 }
   1616 
   1617 
   1618 /***********************************************************************************************
   1619  * TeamClass::Coordinate_Attack -- Handles coordinating a team attack.                         *
   1620  *                                                                                             *
   1621  *    This function is called when the team knows what it should attack. This routine will     *
   1622  *    give the necessary orders to the members of the team.                                    *
   1623  *                                                                                             *
   1624  * INPUT:   none                                                                               *
   1625  *                                                                                             *
   1626  * OUTPUT:  none                                                                               *
   1627  *                                                                                             *
   1628  * WARNINGS:   none                                                                            *
   1629  *                                                                                             *
   1630  * HISTORY:                                                                                    *
   1631  *   04/06/1995 JLB : Created.                                                                 *
   1632  *=============================================================================================*/
   1633 void TeamClass::Coordinate_Attack(void)
   1634 {
   1635 	assert(IsActive);
   1636 	assert(Teams.ID(this) == ID);
   1637 
   1638 	if (!Target_Legal(Target)) {
   1639 		Target = MissionTarget;
   1640 	}
   1641 
   1642 	/*
   1643 	** Check if they're attacking a cell.  If the contents of the cell are
   1644 	** a bridge or a building/unit/techno, then it's a valid target.  Otherwise,
   1645 	** the target is invalid. This only applies to non-aircraft teams. An aircraft team
   1646 	**	can "attack" an empty cell and this is perfectly ok (paratrooper drop and parabombs
   1647 	**	are prime examples).
   1648 	*/
   1649 	if (Is_Target_Cell(Target) && Member != NULL && Fetch_A_Leader()->What_Am_I() != RTTI_AIRCRAFT) {
   1650 		CellClass *cellptr = &Map[As_Cell(Target)];
   1651 		TemplateType tt = cellptr->TType;
   1652 		if (cellptr->Cell_Object()) {
   1653 			Target = cellptr->Cell_Object()->As_Target();
   1654 		} else {
   1655 			if (tt != TEMPLATE_BRIDGE1   && tt != TEMPLATE_BRIDGE2   &&
   1656 				 tt != TEMPLATE_BRIDGE1H  && tt != TEMPLATE_BRIDGE2H  &&
   1657 				 tt != TEMPLATE_BRIDGE_1A && tt != TEMPLATE_BRIDGE_1B &&
   1658 				 tt != TEMPLATE_BRIDGE_2A && tt != TEMPLATE_BRIDGE_2B &&
   1659 				 tt != TEMPLATE_BRIDGE_3A && tt != TEMPLATE_BRIDGE_3B ) {
   1660 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   1661 	FootClass *unit = Member;
   1662 	TeamMissionClass const * mission = &Class->MissionList[CurrentMission];
   1663 	if(unit->What_Am_I() != RTTI_UNIT || 
   1664 		*(UnitClass *)unit != UNIT_CHRONOTANK || 
   1665 		mission->Mission != TMISSION_SPY)
   1666 #endif
   1667 				Target = 0;		// invalidize the target so it'll go to next mission.
   1668 			}
   1669 		}
   1670 	}
   1671 
   1672 	if (!Target_Legal(Target)) {
   1673 		IsNextMission = true;
   1674 
   1675 	} else {
   1676 
   1677 		TeamMissionClass const * mission = &Class->MissionList[CurrentMission];
   1678 
   1679 		FootClass * unit = Member;
   1680 		while (unit != NULL) {
   1681 
   1682 			Coordinate_Conscript(unit);
   1683 
   1684 			if (_Is_It_Playing(unit)) {
   1685 				if (mission->Mission == TMISSION_SPY && unit->What_Am_I() == RTTI_INFANTRY && *(InfantryClass *)unit == INFANTRY_SPY) {
   1686 					unit->Assign_Mission(MISSION_CAPTURE);
   1687 					unit->Assign_Target(Target);
   1688 				} else {
   1689 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   1690 				if (mission->Mission == TMISSION_SPY && unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_CHRONOTANK) {
   1691 					UnitClass *tank = (UnitClass *)unit;
   1692 					tank->Teleport_To(::As_Cell(Target));
   1693 					tank->MoebiusCountDown = ChronoTankDuration * TICKS_PER_MINUTE;
   1694 					Scen.Do_BW_Fade();
   1695 					Sound_Effect(VOC_CHRONOTANK1, unit->Coord);
   1696 					tank->Assign_Target(TARGET_NONE);
   1697 					tank->Assign_Mission(MISSION_GUARD);
   1698 				} else {
   1699 #endif
   1700 					if (unit->Mission != MISSION_ATTACK && unit->Mission != MISSION_ENTER && unit->Mission != MISSION_CAPTURE) {
   1701 						unit->Transmit_Message(RADIO_OVER_OUT);
   1702 						unit->Assign_Mission(MISSION_ATTACK);
   1703 						unit->Assign_Target(TARGET_NONE);
   1704 						unit->Assign_Destination(TARGET_NONE);
   1705 					}
   1706 				}
   1707 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   1708 				}
   1709 #endif
   1710 				if (unit->TarCom != Target) {
   1711 					unit->Assign_Target(Target);
   1712 				}
   1713 			}
   1714 
   1715 			unit = unit->Member;
   1716 		}
   1717 	}
   1718 }
   1719 
   1720 
   1721 /***********************************************************************************************
   1722  * TeamClass::Coordinate_Regroup -- Handles team idling (regrouping).                          *
   1723  *                                                                                             *
   1724  *    This routine is called when the team must delay at its current location. Team members    *
   1725  *    are grouped together by this function. It is called when the team needs to sit and       *
   1726  *    wait.                                                                                    *
   1727  *                                                                                             *
   1728  * INPUT:   none                                                                               *
   1729  *                                                                                             *
   1730  * OUTPUT:  bool; Has the team completely regrouped?                                           *
   1731  *                                                                                             *
   1732  * WARNINGS:   none                                                                            *
   1733  *                                                                                             *
   1734  * HISTORY:                                                                                    *
   1735  *   04/06/1995 JLB : Created.                                                                 *
   1736  *=============================================================================================*/
   1737 bool TeamClass::Coordinate_Regroup(void)
   1738 {
   1739 	assert(IsActive);
   1740 	assert(Teams.ID(this) == ID);
   1741 
   1742 	FootClass * unit   = Member;
   1743 	bool retval = true;
   1744 
   1745 	/*
   1746 	**	Regroup default logic.
   1747 	*/
   1748 	while (unit != NULL) {
   1749 
   1750 		Coordinate_Conscript(unit);
   1751 
   1752 		if (_Is_It_Playing(unit)) {
   1753 
   1754 			if (unit->Distance(Zone) > Rule.StrayDistance && (unit->Mission != MISSION_GUARD_AREA || !Target_Legal(unit->TarCom))) {
   1755 				if (!Target_Legal(unit->NavCom)) {
   1756 // TCTCTC
   1757 //				if (!Target_Legal(unit->NavCom) || ::Distance(unit->NavCom, Zone) > Rule.StrayDistance) {
   1758 					unit->Assign_Mission(MISSION_MOVE);
   1759 					unit->Assign_Destination(Zone);
   1760 
   1761 					retval = false;
   1762 					if (!unit->IsFormationMove) {
   1763 						unit->Assign_Mission(MISSION_MOVE);
   1764 						CELL dest = unit->Adjust_Dest(As_Cell(Zone));
   1765 						unit->Assign_Destination(::As_Target(dest));
   1766 					} else {
   1767 						retval = true;	// formations are always considered regrouped.
   1768 					}
   1769 				}
   1770 			} else {
   1771 
   1772 				/*
   1773 				**	The team is regrouping, so just sit here and wait.
   1774 				*/
   1775 				if (unit->Mission != MISSION_GUARD_AREA) {
   1776 					unit->Assign_Mission(MISSION_GUARD);
   1777 					unit->Assign_Destination(TARGET_NONE);
   1778 				}
   1779 			}
   1780 
   1781 		}
   1782 
   1783 		unit = unit->Member;
   1784 	}
   1785 	return(retval);
   1786 }
   1787 
   1788 
   1789 /***********************************************************************************************
   1790  * TeamClass::Coordinate_Do -- Handles the team performing specified mission.                  *
   1791  *                                                                                             *
   1792  *    This will assign the specified mission to the team. If there are team members that are   *
   1793  *    too far away from the center of the team, then they will be told to move to the team's   *
   1794  *    location.                                                                                *
   1795  *                                                                                             *
   1796  * INPUT:   none                                                                               *
   1797  *                                                                                             *
   1798  * OUTPUT:  none                                                                               *
   1799  *                                                                                             *
   1800  * WARNINGS:   This only works if the special mission the team members are to perform does not *
   1801  *             require extra parameters. The ATTACK and MOVE missions are particularly bad.    *
   1802  *                                                                                             *
   1803  * HISTORY:                                                                                    *
   1804  *   05/11/1996 JLB : Created.                                                                 *
   1805  *=============================================================================================*/
   1806 void TeamClass::Coordinate_Do(void)
   1807 {
   1808 	assert(IsActive);
   1809 	assert(Teams.ID(this) == ID);
   1810 
   1811 	FootClass * unit = Member;
   1812 	MissionType do_mission = Class->MissionList[CurrentMission].Data.Mission;
   1813 
   1814 	/*
   1815 	**	For each unit either head it back to the team center or give it the main
   1816 	**	team mission order as appropriate.
   1817 	*/
   1818 	while (unit != NULL) {
   1819 
   1820 		Coordinate_Conscript(unit);
   1821 
   1822 		if (_Is_It_Playing(unit)) {
   1823 
   1824 			if (!Target_Legal(unit->TarCom) && !Target_Legal(unit->NavCom) && unit->Distance(Zone) > Rule.StrayDistance * 2) {
   1825 
   1826 				/*
   1827 				**	Only if the unit isn't already heading to regroup with the team, will it
   1828 				**	be given orders to do so.
   1829 				*/
   1830 				unit->Assign_Mission(MISSION_MOVE);
   1831 				unit->Assign_Destination(Zone);
   1832 				unit->Assign_Mission(MISSION_MOVE);
   1833 				CELL dest = unit->Adjust_Dest(As_Cell(Zone));
   1834 				unit->Assign_Destination(::As_Target(dest));
   1835 
   1836 			} else {
   1837 
   1838 				/*
   1839 				**	The team is regrouping, so just sit here and wait.
   1840 				*/
   1841 				if (!Target_Legal(unit->TarCom) && !Target_Legal(unit->NavCom) && unit->Mission != do_mission) {
   1842 					unit->ArchiveTarget = TARGET_NONE;
   1843 					unit->Assign_Mission(do_mission);
   1844 					unit->Assign_Target(TARGET_NONE);
   1845 					unit->Assign_Destination(TARGET_NONE);
   1846 				}
   1847 			}
   1848 
   1849 		}
   1850 
   1851 		unit = unit->Member;
   1852 	}
   1853 }
   1854 
   1855 
   1856 /***********************************************************************************************
   1857  * TeamClass::Coordinate_Move -- Handles team movement coordination.                           *
   1858  *                                                                                             *
   1859  *    This routine is called when the team must move to a new location. Movement and grouping  *
   1860  *    commands associated with this task are initiated here.                                   *
   1861  *                                                                                             *
   1862  * INPUT:   none                                                                               *
   1863  *                                                                                             *
   1864  * OUTPUT:  none                                                                               *
   1865  *                                                                                             *
   1866  * WARNINGS:   none                                                                            *
   1867  *                                                                                             *
   1868  * HISTORY:                                                                                    *
   1869  *   04/06/1995 JLB : Created.                                                                 *
   1870  *=============================================================================================*/
   1871 void TeamClass::Coordinate_Move(void)
   1872 {
   1873 	assert(IsActive);
   1874 	assert(Teams.ID(this) == ID);
   1875 
   1876 	FootClass * unit = Member;
   1877 	bool finished = true;
   1878 	bool found = false;
   1879 
   1880 	if (!Target_Legal(Target)) {
   1881 		Target = MissionTarget;
   1882 	}
   1883 
   1884 	if (Target_Legal(Target)) {
   1885 
   1886 		if (!Lagging_Units()) {
   1887 
   1888 			while (unit != NULL) {
   1889 
   1890 				/*
   1891 				**	Tell the unit, if necessary, that it should regroup
   1892 				**	with the main team location. If the unit is regrouping, then
   1893 				**	the team should continue NOT qualify as fully reaching the desired
   1894 				**	location.
   1895 				*/
   1896 				if (Coordinate_Conscript(unit)) {
   1897 					finished = false;
   1898 				}
   1899 
   1900 				if (unit->Mission == MISSION_UNLOAD || unit->MissionQueue == MISSION_UNLOAD) {
   1901 					finished = false;
   1902 				}
   1903 
   1904 				if (_Is_It_Playing(unit) && unit->Mission != MISSION_UNLOAD && unit->MissionQueue != MISSION_UNLOAD) {
   1905 					int stray = Rule.StrayDistance;
   1906 					if (unit->What_Am_I() == RTTI_AIRCRAFT) {
   1907 						stray *= 3;
   1908 					}
   1909 					if (unit->What_Am_I() == RTTI_INFANTRY && ((InfantryClass const *)unit)->Class->IsDog) {
   1910 						if (Target_Legal(unit->TarCom)) stray = unit->Techno_Type_Class()->ThreatRange;
   1911 						if (Target_Legal(unit->TarCom) && unit->Distance(unit->TarCom) > stray) {
   1912 							unit->Assign_Target(TARGET_NONE);
   1913 						}
   1914 					}
   1915 					found = true;
   1916 
   1917 					int dist = unit->Distance(Target);
   1918 					if (unit->IsFormationMove) {
   1919 						if (::As_Target(Coord_Cell(unit->Coord)) != unit->NavCom) {
   1920 							dist = Rule.StrayDistance + 1;	// formation moves must be exact.
   1921 						}
   1922 					}
   1923 
   1924 					if (dist > stray ||
   1925 						(unit->What_Am_I() == RTTI_AIRCRAFT &&
   1926 //						(unit->In_Which_Layer() == LAYER_TOP &&
   1927 						((AircraftClass *)unit)->Height > 0 &&
   1928 						Coord_Cell(unit->Center_Coord()) != As_Cell(Target) &&
   1929 						!((AircraftClass *)unit)->Class->IsFixedWing &&
   1930 						Class->MissionList[CurrentMission+1].Mission != TMISSION_MOVE)) {
   1931 
   1932 						bool wasform = false;
   1933 
   1934 
   1935 						if (unit->Mission != MISSION_MOVE) {
   1936 							unit->Assign_Mission(MISSION_MOVE);
   1937 						}
   1938 
   1939 						if (unit->NavCom != Target) {
   1940 
   1941 							/*
   1942 							** Check if this destination should be adjusted for
   1943 							** a formation move
   1944 							*/
   1945 							if (Is_Target_Cell(Target) && unit->IsFormationMove) {
   1946 								CELL newcell = unit->Adjust_Dest(As_Cell(Target));
   1947 								if (Coord_Cell(unit->Coord) != newcell) {
   1948 									unit->Assign_Destination(::As_Target(newcell));
   1949 								} else {
   1950 									unit->Assign_Mission(MISSION_GUARD);
   1951 									unit->Assign_Destination(TARGET_NONE);
   1952 									wasform = true;
   1953 								}
   1954 							} else {
   1955 								unit->Assign_Destination(Target);
   1956 							}
   1957 						}
   1958 
   1959 						if (!wasform) {
   1960 							finished = false;
   1961 						}
   1962 
   1963 					} else {
   1964 						if (unit->Mission == MISSION_MOVE && (!Target_Legal(unit->NavCom) || Distance(unit->NavCom) < CELL_LEPTON_W)) {
   1965 							unit->Assign_Destination(TARGET_NONE);
   1966 							unit->Enter_Idle_Mode();
   1967 						}
   1968 					}
   1969 
   1970 					/*
   1971 					**	If any member still has a valid NavCom then consider this
   1972 					**	movement mission to still be in progress. This will ensure
   1973 					**	that the members come to a complete stop before the next
   1974 					**	mission commences. Without this, the team will prematurely
   1975 					**	start on the next mission even when all members aren't yet
   1976 					**	in their proper spot.
   1977 					*/
   1978 					if (Target_Legal(unit->NavCom)) {
   1979 						finished = false;
   1980 					}
   1981 				}
   1982 
   1983 				unit = unit->Member;
   1984 			}
   1985 		} else {
   1986 			finished = false;
   1987 		}
   1988 	}
   1989 
   1990 	/*
   1991 	**	If there are no initiated members to this team, then it certainly
   1992 	**	could not have managed to move to the target destination.
   1993 	*/
   1994 	if (!found) {
   1995 		finished = false;
   1996 	}
   1997 
   1998 	/*
   1999 	**	If all the team members are close enough to the desired destination, then
   2000 	**	move to the next mission.
   2001 	*/
   2002 	if (finished && IsMoving) {
   2003 		IsNextMission = true;
   2004 	}
   2005 }
   2006 
   2007 
   2008 /***********************************************************************************************
   2009  * TeamClass::Lagging_Units -- Finds and orders any lagging units to catch up.                 *
   2010  *                                                                                             *
   2011  *    This routine will examine the team and find any lagging units. The units are then        *
   2012  *    ordered to catch up to the team member that is closest to the team's destination. This   *
   2013  *    routine will not do anything unless lagging members are suspected. This fact is          *
   2014  *    indicated by setting the IsLagging flag. The flag is set by some outside agent.          *
   2015  *                                                                                             *
   2016  * INPUT:   none                                                                               *
   2017  *                                                                                             *
   2018  * OUTPUT:  none                                                                               *
   2019  *                                                                                             *
   2020  * WARNINGS:   Be sure to set IsLagging for the team if a lagging member is suspected.         *
   2021  *                                                                                             *
   2022  * HISTORY:                                                                                    *
   2023  *   08/01/1995 PWG : Created.                                                                 *
   2024  *   04/11/1996 JLB : Modified.                                                                *
   2025  *=============================================================================================*/
   2026 bool TeamClass::Lagging_Units(void)
   2027 {
   2028 	assert(IsActive);
   2029 	assert(Teams.ID(this) == ID);
   2030 
   2031 	FootClass * unit = Member;
   2032 	bool lag = false;
   2033 
   2034 	//BG: HACK - if it's in a formation move, then disable the check for
   2035 	// VG added NULL check 	 laggers, 'cause they're all moving simultaneously.
   2036 	if (unit != NULL && unit->IsFormationMove) IsLagging = false;
   2037 
   2038 	/*
   2039 	** If the IsLagging bit is not set, then obviously there are no lagging
   2040 	** units.
   2041 	*/
   2042 	if (!IsLagging) return(false);
   2043 
   2044 	/*
   2045 	**	Scan through all of the units, searching for units who are having
   2046 	** trouble keeping up with the pack.
   2047 	*/
   2048 	while (unit != NULL) {
   2049 
   2050 		if (_Is_It_Playing(unit)) {
   2051 			int stray = Rule.StrayDistance;
   2052 			if (unit->What_Am_I() ==  RTTI_AIRCRAFT) {
   2053 				stray *= 3;
   2054 			}
   2055 
   2056 			/*
   2057 			** If we find a unit who has fallen too far away from the center of
   2058 			** the pack, then we need to order that unit to catch up with the
   2059 			** first unit.
   2060 			*/
   2061 			if (unit->Distance(ClosestMember) > stray) {
   2062 // TCTCTC
   2063 				if (!Target_Legal(unit->NavCom)) {
   2064 //				if (!Target_Legal(unit->NavCom) || ::Distance(unit->NavCom, ClosestMember) > Rule.StrayDistance) {
   2065 					unit->Assign_Mission(MISSION_MOVE);
   2066 					unit->Assign_Destination(ClosestMember);
   2067 				}
   2068 				lag = true;
   2069 
   2070 			} else {
   2071 				/*
   2072 				** We need to order all of the other units to hold their
   2073 				** position until all lagging units catch up.
   2074 				*/
   2075 				if (unit->Mission != MISSION_GUARD) {
   2076 					unit->Assign_Mission(MISSION_GUARD);
   2077 					unit->Assign_Destination(TARGET_NONE);
   2078 				}
   2079 			}
   2080 		}
   2081 		unit = unit->Member;
   2082 	}
   2083 
   2084 	/*
   2085 	** Once we have handled the loop we know whether there are any lagging
   2086 	** units or not.
   2087 	*/
   2088 	IsLagging = lag;
   2089 	return(lag);
   2090 }
   2091 
   2092 
   2093 /***********************************************************************************************
   2094  * TeamClass::TMission_Unload -- Tells the team to unload passengers now.                      *
   2095  *                                                                                             *
   2096  *    This routine tells all transport vehicles to unload passengers now.                      *
   2097  *                                                                                             *
   2098  * INPUT:   none                                                                               *
   2099  *                                                                                             *
   2100  * OUTPUT:  none                                                                               *
   2101  *                                                                                             *
   2102  * WARNINGS:   none                                                                            *
   2103  *                                                                                             *
   2104  * HISTORY:                                                                                    *
   2105  *   06/14/1995 JLB : Created.                                                                 *
   2106  *=============================================================================================*/
   2107 int TeamClass::TMission_Unload(void)
   2108 {
   2109 	assert(IsActive);
   2110 	assert(Teams.ID(this) == ID);
   2111 
   2112 	FootClass * unit = Member;
   2113 	bool finished = true;
   2114 
   2115 	while (unit != NULL) {
   2116 
   2117 		Coordinate_Conscript(unit);
   2118 
   2119 		if (_Is_It_Playing(unit)) {
   2120 			/*
   2121 			** Only assign the mission if the unit is carrying a passenger, OR
   2122 			** if the unit is a minelayer, with mines in it, and the cell it's
   2123 			** on doesn't have a building (read: mine) in it already.
   2124 			*/
   2125 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2126 			/* Also, allow unload if it's a MAD Tank. */
   2127 			if (unit->Is_Something_Attached() || (unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_MINELAYER && unit->Ammo) || (unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_MAD )) {
   2128 #else
   2129 			if (unit->Is_Something_Attached() || (unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_MINELAYER && unit->Ammo) ) {
   2130 #endif
   2131 				if (unit->Is_Something_Attached()) {
   2132 					/*
   2133 					** Passenger-carrying vehicles will always return false until
   2134 					** they've unloaded all passengers.
   2135 					*/
   2136 					finished = false;
   2137 				}
   2138 
   2139 				/*
   2140 				**	The check for a building is located here because the mine layer may have
   2141 				**	already unloaded the mine but is still in the process of retracting
   2142 				**	the mine layer. During this time, it should not be considered to have
   2143 				**	finished its unload mission.
   2144 				*/
   2145 				if (Map[unit->Center_Coord()].Cell_Building() == NULL && unit->Mission != MISSION_UNLOAD) {
   2146 					unit->Assign_Destination(TARGET_NONE);
   2147 					unit->Assign_Target(TARGET_NONE);
   2148 					unit->Assign_Mission(MISSION_UNLOAD);
   2149 					finished = false;
   2150 				}
   2151 
   2152 			} else {
   2153 
   2154 				/*
   2155 				**	A loaner transport should vacate the map when all transported objects
   2156 				**	have been offloaded.
   2157 				*/
   2158 				if (unit->IsALoaner) {
   2159 					Remove(unit);
   2160 					unit->Assign_Mission(MISSION_RETREAT);
   2161 					unit->Commence();
   2162 				}
   2163 			}
   2164 		}
   2165 
   2166 		unit = unit->Member;
   2167 	}
   2168 
   2169 	if (finished) {
   2170 		IsNextMission = true;
   2171 	}
   2172 	return(1);
   2173 }
   2174 
   2175 
   2176 /***********************************************************************************************
   2177  * TeamClass::TMission_Load -- Tells the team to load onto the transport now.                  *
   2178  *                                                                                             *
   2179  *    This routine tells all non-transport units in the team to climb onto the transport in the*
   2180  *    team.  Note the transport must be a member of this team.                                 *
   2181  *                                                                                             *
   2182  * INPUT:   none                                                                               *
   2183  *                                                                                             *
   2184  * OUTPUT:  none                                                                               *
   2185  *                                                                                             *
   2186  * WARNINGS:   none                                                                            *
   2187  *                                                                                             *
   2188  * HISTORY:                                                                                    *
   2189  *   06/28/1996 BWG : Created.                                                                 *
   2190  *=============================================================================================*/
   2191 int TeamClass::TMission_Load(void)
   2192 {
   2193 	assert(IsActive);
   2194 	assert(Teams.ID(this) == ID);
   2195 
   2196 	FootClass * unit = Member;
   2197 	FootClass * trans = 0;
   2198 
   2199 	/*
   2200 	** First locate the transport in the team, if there is one.  There should
   2201 	** only be one transport in the team.
   2202 	*/
   2203 	while(unit != NULL && trans == NULL) {
   2204 		if (unit->Techno_Type_Class()->Max_Passengers() > 0) {
   2205 			trans = unit;
   2206 			break;
   2207 		}
   2208 		unit = unit->Member;
   2209 	}
   2210 
   2211 	/*
   2212 	**	In the case of no transport available, then consider the mission complete
   2213 	**	since it can never complete otherwise.
   2214 	*/
   2215 	if (trans == NULL) {
   2216 		IsNextMission = true;
   2217 		return(1);
   2218 	}
   2219 
   2220 	/*
   2221 	**	If the transport is already in radio contact, then this means that
   2222 	**	it is in the process of loading. During this time, don't bother to assign
   2223 	**	the enter mission to the other team members.
   2224 	*/
   2225 	if (trans->In_Radio_Contact()) {
   2226 		return(1);
   2227 	}
   2228 
   2229 	/*
   2230 	**	Find a member to assign the entry logic for.
   2231 	*/
   2232 	bool finished = true;
   2233 	unit = Member;	// re-point at the first member of the team again.
   2234 	while (unit != NULL && Total > 1) {
   2235 		Coordinate_Conscript(unit);
   2236 
   2237 		/*
   2238 		** Only assign the mission if the unit is not the transport.
   2239 		*/
   2240 		if (_Is_It_Playing(unit) && unit != trans) {
   2241 			if (unit->Mission != MISSION_ENTER) {
   2242 				unit->Assign_Mission(MISSION_ENTER);
   2243 				unit->Assign_Target(TARGET_NONE);
   2244 				unit->Assign_Destination(trans->As_Target());
   2245 				finished = false;
   2246 				break;
   2247 			}
   2248 			finished = false;
   2249 		}
   2250 
   2251 		unit = unit->Member;
   2252 	}
   2253 
   2254 	if (finished) {
   2255 		IsNextMission = true;
   2256 	}
   2257 	return(1);
   2258 }
   2259 
   2260 
   2261 /***********************************************************************************************
   2262  * TeamClass::Coordinate_Conscript -- Gives orders to new recruit.                             *
   2263  *                                                                                             *
   2264  *    This routine will give the movement orders to the conscript so that it will group        *
   2265  *    with the other members of the team.                                                      *
   2266  *                                                                                             *
   2267  * INPUT:   unit  -- Pointer to the conscript unit.                                            *
   2268  *                                                                                             *
   2269  * OUTPUT:  bool; Is the unit still scurrying to reach the team's current location?            *
   2270  *                                                                                             *
   2271  * WARNINGS:   none                                                                            *
   2272  *                                                                                             *
   2273  * HISTORY:                                                                                    *
   2274  *   04/06/1995 JLB : Created.                                                                 *
   2275  *=============================================================================================*/
   2276 bool TeamClass::Coordinate_Conscript(FootClass * unit)
   2277 {
   2278 	assert(IsActive);
   2279 	assert(Teams.ID(this) == ID);
   2280 
   2281 	if (_Is_It_Breathing(unit) && !unit->IsInitiated) {
   2282 		if (unit->Distance(Zone) > Rule.StrayDistance) {
   2283 			if (!Target_Legal(unit->NavCom)) {
   2284 				unit->Assign_Mission(MISSION_MOVE);
   2285 				unit->Assign_Target(TARGET_NONE);
   2286 				unit->IsFormationMove = false;
   2287 				unit->Assign_Destination(Zone);
   2288 			}
   2289 			return(true);
   2290 
   2291 		} else {
   2292 
   2293 			/*
   2294 			**	This unit has gotten close enough to the team center so that it is
   2295 			**	now considered initiated. An initiated unit is considered when calculating
   2296 			**	the center of the team.
   2297 			*/
   2298 			unit->IsInitiated = true;
   2299 		}
   2300 	}
   2301 	return(false);
   2302 }
   2303 
   2304 
   2305 /***************************************************************************
   2306  * TeamClass::Is_A_Member -- Tests if a unit is a member of a team         *
   2307  *                                                                         *
   2308  * INPUT:		none                                                        *
   2309  *                                                                         *
   2310  * OUTPUT:     none                                                        *
   2311  *                                                                         *
   2312  * WARNINGS:                                                               *
   2313  *                                                                         *
   2314  * HISTORY:                                                                *
   2315  *   05/16/1995 PWG : Created.                                             *
   2316  *=========================================================================*/
   2317 bool TeamClass::Is_A_Member(void const * who) const
   2318 {
   2319 	assert(IsActive);
   2320 	assert(Teams.ID(this) == ID);
   2321 
   2322 	FootClass * unit = Member;
   2323 	while (unit != NULL) {
   2324 		if (unit == who) {
   2325 			return(true);
   2326 		}
   2327 		unit = unit->Member;
   2328 	}
   2329 	return(false);
   2330 }
   2331 
   2332 
   2333 /***************************************************************************
   2334  * TeamClass::Suspend_Teams -- Suspends activity for low priority teams    *
   2335  *                                                                         *
   2336  * INPUT:	int priority - determines what is considered low priority.     *
   2337  *                                                                         *
   2338  * OUTPUT:                                                                 *
   2339  *                                                                         *
   2340  * WARNINGS:                                                               *
   2341  *                                                                         *
   2342  * HISTORY:                                                                *
   2343  *   06/19/1995 PWG : Created.                                             *
   2344  *=========================================================================*/
   2345 void TeamClass::Suspend_Teams(int priority, HouseClass const * house)
   2346 {
   2347 	for (int index = 0; index < Teams.Count(); index++) {
   2348 		TeamClass * team = Teams.Ptr(index);
   2349 
   2350 		/*
   2351 		**	If a team is below the "survival priority level", then it gets
   2352 		**	destroyed. The team members are then free to be reassigned.
   2353 		*/
   2354 		if (team != NULL && team->House == house && team->Class->RecruitPriority < priority) {
   2355 			FootClass * unit = team->Member;
   2356 			while (team->Member) {
   2357 				team->Remove(team->Member);
   2358 			}
   2359 			team->IsAltered = team->JustAltered = true;
   2360 			team->SuspendTimer = Rule.SuspendDelay * TICKS_PER_MINUTE;
   2361 			team->Suspended = true;
   2362 		}
   2363 	}
   2364 }
   2365 
   2366 
   2367 /***********************************************************************************************
   2368  * TeamClass::Is_Leaving_Map -- Checks if team is in process of leaving the map                *
   2369  *                                                                                             *
   2370  *    This routine is used to see if the team is leaving the map. A team that is leaving the   *
   2371  *    map gives implicit permission for its members to leave the map.                          *
   2372  *                                                                                             *
   2373  * INPUT:   none                                                                               *
   2374  *                                                                                             *
   2375  * OUTPUT:  bool; Is this team trying to leave the map?                                        *
   2376  *                                                                                             *
   2377  * WARNINGS:   none                                                                            *
   2378  *                                                                                             *
   2379  * HISTORY:                                                                                    *
   2380  *   04/30/1996 JLB : Created.                                                                 *
   2381  *=============================================================================================*/
   2382 bool TeamClass::Is_Leaving_Map(void) const
   2383 {
   2384 	assert(IsActive);
   2385 	assert(Teams.ID(this) == ID);
   2386 
   2387 	if (IsMoving && CurrentMission >= 0) {
   2388 		TeamMissionClass const * mission = &Class->MissionList[CurrentMission];
   2389 
   2390 		if (mission->Mission == TMISSION_MOVE && !Map.In_Radar(Scen.Waypoint[mission->Data.Value])) {
   2391 			return(true);
   2392 		}
   2393 	}
   2394 	return(false);
   2395 }
   2396 
   2397 
   2398 /***********************************************************************************************
   2399  * TeamClass::Has_Entered_Map -- Determines if the entire team has entered the map.            *
   2400  *                                                                                             *
   2401  *    This will examine all team members and only if all of them have entered the map, will    *
   2402  *    it return true. This routine is used to recognize the case of a team that has been       *
   2403  *    generated off map and one that has already entered game play. This knowledge can lead    *
   2404  *    to more intelligent behavior regarding team and member disposition.                      *
   2405  *                                                                                             *
   2406  * INPUT:   none                                                                               *
   2407  *                                                                                             *
   2408  * OUTPUT:  bool; Have all members of this team entered the map?                               *
   2409  *                                                                                             *
   2410  * WARNINGS:   none                                                                            *
   2411  *                                                                                             *
   2412  * HISTORY:                                                                                    *
   2413  *   07/26/1996 JLB : Created.                                                                 *
   2414  *=============================================================================================*/
   2415 bool TeamClass::Has_Entered_Map(void) const
   2416 {
   2417 	bool ok = true;
   2418 	FootClass * foot = Member;
   2419 	while (foot != NULL) {
   2420 		if (!foot->IsLocked) {
   2421 			ok = false;
   2422 			break;
   2423 		}
   2424 		foot = (FootClass *)(ObjectClass *)(foot->Next);
   2425 	}
   2426 	return(ok);
   2427 }
   2428 
   2429 
   2430 /***********************************************************************************************
   2431  * TeamClass::Scan_Limit -- Force all members of the team to have limited scan range.          *
   2432  *                                                                                             *
   2433  *    This routine is used when one of the team members cannot get within range of the team's  *
   2434  *    target. In such a case, the team must be assigned a new target and all members of that   *
   2435  *    team must recognize that a restricted target scan is required. This is done by clearing  *
   2436  *    out the team's target so that it will be forced to search for a new one. Also, since the *
   2437  *    members are flagged for short scanning, whichever team member is picked to scan for a    *
   2438  *    target will scan for one that is within range.                                           *
   2439  *                                                                                             *
   2440  * INPUT:   none                                                                               *
   2441  *                                                                                             *
   2442  * OUTPUT:  none                                                                               *
   2443  *                                                                                             *
   2444  * WARNINGS:   The team will reassign its target as a result of this routine.                  *
   2445  *                                                                                             *
   2446  * HISTORY:                                                                                    *
   2447  *   07/26/1996 JLB : Created.                                                                 *
   2448  *=============================================================================================*/
   2449 void TeamClass::Scan_Limit(void)
   2450 {
   2451 	Assign_Mission_Target(TARGET_NONE);
   2452 	FootClass * foot = Member;
   2453 	while (foot != NULL) {
   2454 		foot->Assign_Target(TARGET_NONE);
   2455 		foot->IsScanLimited = true;
   2456 		foot = foot->Member;
   2457 	}
   2458 }
   2459 
   2460 
   2461 /***********************************************************************************************
   2462  * TeamClass::TMission_Formation -- Process team formation change command.                     *
   2463  *                                                                                             *
   2464  *    This routine will change the team's formation to that specified in the team command      *
   2465  *    parameter. It is presumed that the team will have further movement orders so that the    *
   2466  *    formation can serve some purpose. Merely changing the formation doesn't alter the        *
   2467  *    member's location. The team must be given a movement order before team member            *
   2468  *    repositioning will occur.                                                                *
   2469  *                                                                                             *
   2470  * INPUT:   none                                                                               *
   2471  *                                                                                             *
   2472  * OUTPUT:  Returns with the time to delay before further team actions should occur.           *
   2473  *                                                                                             *
   2474  * WARNINGS:   none                                                                            *
   2475  *                                                                                             *
   2476  * HISTORY:                                                                                    *
   2477  *   08/06/1996 JLB : Created.                                                                 *
   2478  *=============================================================================================*/
   2479 int TeamClass::TMission_Formation(void)
   2480 {
   2481 	FootClass * member = Member;
   2482 	TeamMissionClass const * mission = &Class->MissionList[CurrentMission];
   2483 	Formation = mission->Data.Formation;
   2484 	int group = ID + 10;
   2485 	int xdir = 0;
   2486 	int ydir = 0;
   2487 	bool evenodd = 1;
   2488 	HousesType house = (member != NULL) ? member->Owner() : HOUSE_NONE;
   2489 
   2490 	/*
   2491 	**	Assign appropriate formation offsets for each of the members
   2492 	**	of this team.
   2493 	*/
   2494 	switch (Formation) {
   2495 		case FORMATION_NONE:
   2496 			while (member != NULL) {
   2497 				member->Group = 0xFF;
   2498 				member->XFormOffset = 0x80000000;
   2499 				member->YFormOffset = 0x80000000;
   2500 				member->IsFormationMove = false;
   2501 				member = member->Member;
   2502 			}
   2503 			break;
   2504 		case FORMATION_TIGHT:
   2505 			while (member != NULL) {
   2506 				member->Group = group;
   2507 				member->XFormOffset = 0;
   2508 				member->YFormOffset = 0;
   2509 				member->IsFormationMove = true;
   2510 				member = member->Member;
   2511 			}
   2512 			break;
   2513 		case FORMATION_LOOSE:
   2514 			break;
   2515 		case FORMATION_WEDGE_N:
   2516 			ydir = -(Total / 2);
   2517 			xdir = 0;
   2518 			while (member != NULL) {
   2519 				member->Group = group;
   2520 				member->XFormOffset = xdir;
   2521 				member->YFormOffset = ydir;
   2522 				member->IsFormationMove = true;
   2523 				xdir = -xdir;
   2524 				evenodd ^= 1;
   2525 				if (!evenodd) {
   2526 					xdir -= 2;
   2527 					ydir += 2;
   2528 				}
   2529 				member = member->Member;
   2530 			}
   2531 			break;
   2532 		case FORMATION_WEDGE_E:
   2533 			xdir = (Total / 2);
   2534 			ydir = 0;
   2535 			while (member != NULL) {
   2536 				member->Group = group;
   2537 				member->XFormOffset = xdir;
   2538 				member->YFormOffset = ydir;
   2539 				member->IsFormationMove = true;
   2540 				ydir = -ydir;
   2541 				evenodd ^= 1;
   2542 				if (!evenodd) {
   2543 					xdir -= 2;
   2544 					ydir -= 2;
   2545 				}
   2546 				member = member->Member;
   2547 			}
   2548 			break;
   2549 		case FORMATION_WEDGE_S:
   2550 			ydir = (Total / 2);
   2551 			xdir = 0;
   2552 			while (member != NULL) {
   2553 				member->Group = group;
   2554 				member->XFormOffset = xdir;
   2555 				member->YFormOffset = ydir;
   2556 				member->IsFormationMove = true;
   2557 				xdir = -xdir;
   2558 				evenodd ^= 1;
   2559 				if (!evenodd) {
   2560 					xdir -= 2;
   2561 					ydir -= 2;
   2562 				}
   2563 				member = member->Member;
   2564 			}
   2565 			break;
   2566 		case FORMATION_WEDGE_W:
   2567 			xdir = -(Total / 2);
   2568 			ydir = 0;
   2569 			while (member != NULL) {
   2570 				member->Group = group;
   2571 				member->XFormOffset = xdir;
   2572 				member->YFormOffset = ydir;
   2573 				member->IsFormationMove = true;
   2574 				ydir = -ydir;
   2575 				evenodd ^= 1;
   2576 				if (!evenodd) {
   2577 					xdir += 2;
   2578 					ydir -= 2;
   2579 				}
   2580 				member = member->Member;
   2581 			}
   2582 			break;
   2583 		case FORMATION_LINE_NS:
   2584 			ydir = -(Total/2);
   2585 			while (member != NULL) {
   2586 				member->Group = group;
   2587 				member->XFormOffset = 0;
   2588 				member->YFormOffset = ydir;
   2589 				member->IsFormationMove = true;
   2590 				member = member->Member;
   2591 				ydir += 2;
   2592 			}
   2593 			break;
   2594 		case FORMATION_LINE_EW:
   2595 			xdir = -(Total/2);
   2596 			while (member != NULL) {
   2597 				member->Group = group;
   2598 				member->XFormOffset = xdir;
   2599 				member->YFormOffset = 0;
   2600 				member->IsFormationMove = true;
   2601 				member = member->Member;
   2602 				xdir += 2;
   2603 			}
   2604 			break;
   2605 	}
   2606 
   2607 	/*
   2608 	** Now calculate the group's movement type and speed
   2609 	*/
   2610 	if (Formation != FORMATION_NONE && house != HOUSE_NONE) {
   2611 		TeamFormDataStruct& team_form_data = TeamFormData[house];
   2612 		team_form_data.TeamSpeed[group] = SPEED_WHEEL;
   2613 		team_form_data.TeamMaxSpeed[group] = MPH_LIGHT_SPEED;
   2614 		member = Member;
   2615 		while (member != NULL) {
   2616 			RTTIType mytype = member->What_Am_I();
   2617 			SpeedType	memspeed;
   2618 			MPHType		memmax;
   2619 			bool			speedcheck = false;
   2620 
   2621 			if (mytype == RTTI_INFANTRY) {
   2622 				memspeed = SPEED_FOOT;
   2623 				memmax = ((InfantryClass *)member)->Class->MaxSpeed;
   2624 				speedcheck = true;
   2625 			}
   2626 			if (mytype == RTTI_UNIT) {
   2627 				memspeed = ((UnitClass *)member)->Class->Speed;
   2628 				memmax = ((UnitClass *)member)->Class->MaxSpeed;
   2629 				speedcheck = true;
   2630 			}
   2631 
   2632 			if (mytype == RTTI_VESSEL) {
   2633 				memspeed = ((VesselClass *)member)->Class->Speed;
   2634 				memmax = ((VesselClass *)member)->Class->MaxSpeed;
   2635 				speedcheck = true;
   2636 			}
   2637 
   2638 			if (speedcheck) {
   2639 				if (memmax < team_form_data.TeamMaxSpeed[group]) {
   2640 					team_form_data.TeamMaxSpeed[group] = memmax;
   2641 					team_form_data.TeamSpeed[group] = memspeed;
   2642 				}
   2643 			}
   2644 			member = member->Member;
   2645 		}
   2646 
   2647 		/*
   2648 		** Now that it's all calculated, assign the movement type and
   2649 		** speed to every member of the team.
   2650 		*/
   2651 		member = Member;
   2652 		while (member != NULL) {
   2653 			member->FormationSpeed = team_form_data.TeamSpeed[group];
   2654 			member->FormationMaxSpeed = team_form_data.TeamMaxSpeed[group];
   2655 			if (member->What_Am_I() == RTTI_INFANTRY) {
   2656 				member->FormationSpeed = SPEED_FOOT;
   2657 				member->FormationMaxSpeed = MPH_SLOW_ISH;
   2658 			}
   2659 			member = member->Member;
   2660 		}
   2661 	}
   2662 
   2663 	// Advance past the formation-setting command.
   2664 	IsNextMission = true;
   2665 
   2666 	return(1);
   2667 }
   2668 
   2669 
   2670 /***********************************************************************************************
   2671  * TeamClass::TMission_Attack -- Perform the team attack mission command.                      *
   2672  *                                                                                             *
   2673  *    This will tell the team to attack the quarry specified in the team command. If the team  *
   2674  *    already has a target, this it is presumed that this target take precidence and it won't  *
   2675  *    be changed.                                                                              *
   2676  *                                                                                             *
   2677  * INPUT:   none                                                                               *
   2678  *                                                                                             *
   2679  * OUTPUT:  Returns with the delay before the next team logic operation should occur.          *
   2680  *                                                                                             *
   2681  * WARNINGS:   none                                                                            *
   2682  *                                                                                             *
   2683  * HISTORY:                                                                                    *
   2684  *   08/06/1996 JLB : Created.                                                                 *
   2685  *=============================================================================================*/
   2686 int TeamClass::TMission_Attack(void)
   2687 {
   2688 	if (!Target_Legal(MissionTarget) && Member != NULL) {
   2689 		TeamMissionClass const * mission = &Class->MissionList[CurrentMission];
   2690 
   2691 		/*
   2692 		**	Pick a team leader that has a weapon. Only in the case of no
   2693 		**	team members having any weapons, will a member without a weapon
   2694 		**	be chosen.
   2695 		*/
   2696 		FootClass const * candidate = Fetch_A_Leader();
   2697 
   2698 		/*
   2699 		**	Have the team leader pick what the next team target will be.
   2700 		*/
   2701 		switch (mission->Data.Quarry) {
   2702 			case QUARRY_ANYTHING:
   2703 				Assign_Mission_Target(candidate->Greatest_Threat(THREAT_NORMAL));
   2704 				break;
   2705 
   2706 			case QUARRY_BUILDINGS:
   2707 				Assign_Mission_Target(candidate->Greatest_Threat(THREAT_BUILDINGS));
   2708 				break;
   2709 
   2710 			case QUARRY_HARVESTERS:
   2711 				Assign_Mission_Target(candidate->Greatest_Threat(THREAT_TIBERIUM));
   2712 				break;
   2713 
   2714 			case QUARRY_INFANTRY:
   2715 				Assign_Mission_Target(candidate->Greatest_Threat(THREAT_INFANTRY));
   2716 				break;
   2717 
   2718 			case QUARRY_VEHICLES:
   2719 				Assign_Mission_Target(candidate->Greatest_Threat(THREAT_VEHICLES));
   2720 				break;
   2721 
   2722 			case QUARRY_FACTORIES:
   2723 				Assign_Mission_Target(candidate->Greatest_Threat(THREAT_FACTORIES));
   2724 				break;
   2725 
   2726 			case QUARRY_DEFENSE:
   2727 				Assign_Mission_Target(candidate->Greatest_Threat(THREAT_BASE_DEFENSE));
   2728 				break;
   2729 
   2730 			case QUARRY_THREAT:
   2731 				Assign_Mission_Target(candidate->Greatest_Threat(THREAT_NORMAL));
   2732 				break;
   2733 
   2734 			case QUARRY_POWER:
   2735 				Assign_Mission_Target(candidate->Greatest_Threat(THREAT_POWER));
   2736 				break;
   2737 
   2738 			case QUARRY_FAKES:
   2739 				Assign_Mission_Target(candidate->Greatest_Threat(THREAT_FAKES));
   2740 				break;
   2741 
   2742 			default:
   2743 				break;
   2744 		}
   2745 		if (!Target_Legal(MissionTarget)) IsNextMission = true;
   2746 	}
   2747 	Coordinate_Attack();
   2748 	return(1);
   2749 }
   2750 
   2751 
   2752 /***********************************************************************************************
   2753  * TeamClass::TMission_Spy -- Perform the team spy mission.                                    *
   2754  *                                                                                             *
   2755  *    This will give the team a spy mission to the location specified. It is presumed that     *
   2756  *    the location of the team mission actually resides under the building to be spied. If     *
   2757  *    no building exists at the location, then the spy operation is presumed to be a mere      *
   2758  *    move operation.                                                                          *
   2759  *                                                                                             *
   2760  * INPUT:   none                                                                               *
   2761  *                                                                                             *
   2762  * OUTPUT:  Returns with the delay before the next team logic operation should occur.          *
   2763  *                                                                                             *
   2764  * WARNINGS:   none                                                                            *
   2765  *                                                                                             *
   2766  * HISTORY:                                                                                    *
   2767  *   08/06/1996 JLB : Created.                                                                 *
   2768  *=============================================================================================*/
   2769 int TeamClass::TMission_Spy(void)
   2770 {
   2771 	if (Is_Target_Cell(MissionTarget))
   2772 		{
   2773 		CELL cell = ::As_Cell(MissionTarget);
   2774 		CellClass * cellptr = &Map[cell];
   2775 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2776 		ObjectClass * bldg = cellptr->Cell_Building();
   2777 #else
   2778 		ObjectClass * bldg = cellptr->Cell_Object();
   2779 #endif
   2780 		if (bldg != NULL)
   2781 			{
   2782 			Assign_Mission_Target(bldg->As_Target());
   2783 			Coordinate_Attack();
   2784 			}
   2785 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2786 		else
   2787 			{
   2788 			FootClass *member = Member;
   2789 			if(member->What_Am_I() == RTTI_UNIT && *(UnitClass *)member == UNIT_CHRONOTANK)
   2790 				{
   2791 				bool finished = true;
   2792 				while (member)
   2793 					{
   2794 					if ( !((UnitClass *)member)->MoebiusCountDown) finished = false;
   2795 					member = member->Member;
   2796 					}
   2797 				
   2798 				if (!finished)
   2799 					{
   2800 					Coordinate_Attack();
   2801 					}
   2802 				else
   2803 					{
   2804 					Assign_Mission_Target(TARGET_NONE);
   2805 					IsNextMission = true;
   2806 					}
   2807 				}
   2808 			}
   2809 #endif
   2810 		}
   2811 	else
   2812 		{
   2813 		if (!Target_Legal(MissionTarget))
   2814 			{
   2815 			Assign_Mission_Target(TARGET_NONE);
   2816 			IsNextMission = true;
   2817 			}
   2818 		else
   2819 			{
   2820 			Coordinate_Attack();
   2821 			}
   2822 		}
   2823 	return(1);
   2824 }
   2825 
   2826 
   2827 /***********************************************************************************************
   2828  * TeamClass::TMission_Follow -- Perform the "follow friendlies" team command.                 *
   2829  *                                                                                             *
   2830  *    This will cause the team members to search out and follow the nearest friendly object.   *
   2831  *                                                                                             *
   2832  * INPUT:   none                                                                               *
   2833  *                                                                                             *
   2834  * OUTPUT:  Returns with the delay before the next team logic operation should be performed.   *
   2835  *                                                                                             *
   2836  * WARNINGS:   none                                                                            *
   2837  *                                                                                             *
   2838  * HISTORY:                                                                                    *
   2839  *   08/06/1996 JLB : Created.                                                                 *
   2840  *=============================================================================================*/
   2841 int TeamClass::TMission_Follow(void)
   2842 {
   2843 	Calc_Center(Zone, ClosestMember);
   2844 	Target = Zone;
   2845 	Coordinate_Move();
   2846 	return(1);
   2847 }
   2848 
   2849 
   2850 /***********************************************************************************************
   2851  * TeamClass::TMission_Loop -- Causes the team mission processor to jump to new location.      *
   2852  *                                                                                             *
   2853  *    This is equivalent to a jump or goto command. It will alter the team command processing  *
   2854  *    such that it will continue processing at the command number specified.                   *
   2855  *                                                                                             *
   2856  * INPUT:   none                                                                               *
   2857  *                                                                                             *
   2858  * OUTPUT:  Returns with the delay before the next team logic operation should be performed.   *
   2859  *                                                                                             *
   2860  * WARNINGS:   none                                                                            *
   2861  *                                                                                             *
   2862  * HISTORY:                                                                                    *
   2863  *   08/06/1996 JLB : Created.                                                                 *
   2864  *=============================================================================================*/
   2865 int TeamClass::TMission_Loop(void)
   2866 {
   2867 	TeamMissionClass const * mission = &Class->MissionList[CurrentMission];
   2868 	CurrentMission = mission->Data.Value-1;
   2869 	IsNextMission = true;
   2870 	return(1);
   2871 }
   2872 
   2873 
   2874 /***********************************************************************************************
   2875  * TeamClass::TMission_Invulnerable -- Makes the entire team invulnerable for a period of time *
   2876  *                                                                                             *
   2877  *    This is a team mission that simulates the Iron Curtain device. It will make all team     *
   2878  *    members invlunerable for a temporary period of time.                                     *
   2879  *                                                                                             *
   2880  * INPUT:   none                                                                               *
   2881  *                                                                                             *
   2882  * OUTPUT:  Returns with the time delay before the next team logic operation should occur.     *
   2883  *                                                                                             *
   2884  * WARNINGS:   none                                                                            *
   2885  *                                                                                             *
   2886  * HISTORY:                                                                                    *
   2887  *   08/06/1996 JLB : Created.                                                                 *
   2888  *=============================================================================================*/
   2889 int TeamClass::TMission_Invulnerable(void)
   2890 {
   2891 	FootClass * foot = Member;
   2892 	while (foot != NULL) {
   2893 		foot->IronCurtainCountDown = Rule.IronCurtainDuration * TICKS_PER_MINUTE;
   2894 		foot->Mark(MARK_CHANGE);
   2895 		foot = foot->Member;
   2896 	}
   2897 	IsNextMission = true;
   2898 	return(1);
   2899 }
   2900 
   2901 
   2902 /***********************************************************************************************
   2903  * TeamClass::TMission_Set_Global -- Performs a set global flag operation.                     *
   2904  *                                                                                             *
   2905  *    This routine is used by the team to set a global variable but otherwise perform no       *
   2906  *    visible effect on the team. By using this routine, sophisticated trigger dependencies    *
   2907  *    can be implemented.                                                                      *
   2908  *                                                                                             *
   2909  * INPUT:   none                                                                               *
   2910  *                                                                                             *
   2911  * OUTPUT:  Returns with the delay before the next team logic operation should occur.          *
   2912  *                                                                                             *
   2913  * WARNINGS:   none                                                                            *
   2914  *                                                                                             *
   2915  * HISTORY:                                                                                    *
   2916  *   08/06/1996 JLB : Created.                                                                 *
   2917  *=============================================================================================*/
   2918 int TeamClass::TMission_Set_Global(void)
   2919 {
   2920 	TeamMissionClass const * mission = &Class->MissionList[CurrentMission];
   2921 	Scen.Set_Global_To(mission->Data.Value, true);
   2922 	IsNextMission = true;
   2923 	return(1);
   2924 }
   2925 
   2926 
   2927 /***********************************************************************************************
   2928  * TeamClass::TMision_Patrol -- Handles patrolling from one location to another.               *
   2929  *                                                                                             *
   2930  *    A patrolling team will move to the designated waypoint, but along the way it will        *
   2931  *    periodically scan for nearby enemies. If an enemy is found, the patrol mission turns     *
   2932  *    into an attack mission until the target is destroyed -- after which it resumes its       *
   2933  *    patrol duties.                                                                           *
   2934  *                                                                                             *
   2935  * INPUT:   none                                                                               *
   2936  *                                                                                             *
   2937  * OUTPUT:  Returns with the delay before the next call to this routine is needed.             *
   2938  *                                                                                             *
   2939  * WARNINGS:   none                                                                            *
   2940  *                                                                                             *
   2941  * HISTORY:                                                                                    *
   2942  *   08/12/1996 JLB : Created.                                                                 *
   2943  *=============================================================================================*/
   2944 int TeamClass::TMission_Patrol(void)
   2945 {
   2946 	/*
   2947 	**	Reassign the movement destination if the target has been prematurely
   2948 	**	cleared (probably because the object has been destroyed).
   2949 	*/
   2950 	if (!Target_Legal(Target)) {
   2951 		TeamMissionClass const * mission = &Class->MissionList[CurrentMission];
   2952 		if ((unsigned)mission->Data.Value < WAYPT_COUNT) {
   2953 			Assign_Mission_Target(::As_Target(Scen.Waypoint[mission->Data.Value]));
   2954 		}
   2955 	}
   2956 
   2957 	/*
   2958 	**	Every so often, scan for a nearby enemy.
   2959 	*/
   2960 	if (Frame % (Rule.PatrolTime * TICKS_PER_MINUTE) == 0) {
   2961 		FootClass * leader = Fetch_A_Leader();
   2962 		if (leader != NULL) {
   2963 			TARGET target = leader->Greatest_Threat(THREAT_NORMAL|THREAT_RANGE);
   2964 
   2965 			if (Target_Legal(target)) {
   2966 				Assign_Mission_Target(target);
   2967 			} else {
   2968 				Assign_Mission_Target(TARGET_NONE);
   2969 			}
   2970 		}
   2971 	}
   2972 
   2973 	/*
   2974 	**	If the mission target looks like it should be attacked, then do so, otherwise
   2975 	**	treat it as a movement destination.
   2976 	*/
   2977 	if (Is_Target_Object(Target)) {
   2978 		Coordinate_Attack();
   2979 	} else {
   2980 		Coordinate_Move();
   2981 	}
   2982 	return(1);
   2983 }
   2984 
   2985 
   2986 int TeamClass::TMission_Deploy(void)
   2987 {
   2988 	assert(IsActive);
   2989 	assert(Teams.ID(this) == ID);
   2990 
   2991 	FootClass * unit = Member;
   2992 	bool finished = true;
   2993 
   2994 	while (unit != NULL) {
   2995 
   2996 		Coordinate_Conscript(unit);
   2997 
   2998 		if (_Is_It_Playing(unit)) {
   2999 
   3000 			if (unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_MCV) {
   3001 				if (unit->Mission != MISSION_UNLOAD) {
   3002 					unit->Assign_Destination(TARGET_NONE);
   3003 					unit->Assign_Target(TARGET_NONE);
   3004 					unit->Assign_Mission(MISSION_UNLOAD);
   3005 					finished = false;
   3006 				}
   3007 			}
   3008 
   3009 			if (unit->What_Am_I() == RTTI_UNIT && *(UnitClass *)unit == UNIT_MINELAYER && unit->Ammo != 0) {
   3010 				/*
   3011 				**	The check for a building is located here because the mine layer may have
   3012 				**	already unloaded the mine but is still in the process of retracting
   3013 				**	the mine layer. During this time, it should not be considered to have
   3014 				**	finished its unload mission.
   3015 				*/
   3016 				if (!Map[unit->Center_Coord()].Cell_Building() && unit->Mission != MISSION_UNLOAD) {
   3017 					unit->Assign_Destination(TARGET_NONE);
   3018 					unit->Assign_Target(TARGET_NONE);
   3019 					unit->Assign_Mission(MISSION_UNLOAD);
   3020 					finished = false;
   3021 				}
   3022 			}
   3023 
   3024 		}
   3025 
   3026 		unit = unit->Member;
   3027 	}
   3028 
   3029 	if (finished) {
   3030 		IsNextMission = true;
   3031 	}
   3032 	return(1);
   3033 }
   3034 
   3035 
   3036 /***********************************************************************************************
   3037  * TeamClass::Fetch_A_Leader -- Looks for a suitable leader member of the team.                *
   3038  *                                                                                             *
   3039  *    This will scan through the team members looking for one that is suitable as a leader     *
   3040  *    type. A team can sometimes contain limboed or unarmed members. These members are not     *
   3041  *    suitable for leadership roles.                                                           *
   3042  *                                                                                             *
   3043  * INPUT:   none                                                                               *
   3044  *                                                                                             *
   3045  * OUTPUT:  Returns with a suitable leader type unit.                                          *
   3046  *                                                                                             *
   3047  * WARNINGS:   none                                                                            *
   3048  *                                                                                             *
   3049  * HISTORY:                                                                                    *
   3050  *   08/27/1996 JLB : Created.                                                                 *
   3051  *=============================================================================================*/
   3052 FootClass * TeamClass::Fetch_A_Leader(void) const
   3053 {
   3054 	FootClass * leader = Member;
   3055 
   3056 	/*
   3057 	**	Scan through the team members trying to find one that is an active member and
   3058 	**	is equipped with a weapon.
   3059 	*/
   3060 	while (leader != NULL) {
   3061 		if (_Is_It_Playing(leader) && leader->Is_Weapon_Equipped()) break;
   3062 		leader = leader->Member;
   3063 	}
   3064 
   3065 	/*
   3066 	**	If no suitable leader was found, then just return with the first conveniently
   3067 	**	accessable team member. This presumes that some member is better than no member
   3068 	**	at all.
   3069 	*/
   3070 	if (leader == NULL) {
   3071 		leader = Member;
   3072 	}
   3073 
   3074 	return(leader);
   3075 }