CnC_Remastered_Collection

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

REINF.CPP (32033B)


      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/REINF.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 : REINF.CPP                                                    *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : May 24, 1994                                                 *
     28  *                                                                                             *
     29  *                  Last Update : July 26, 1996 [JLB]                                          *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   Create_Air_Reinforcement -- Creates air strike reinforcement                              *
     34  *   Create_Special_Reinforcement -- Ad hoc reinforcement handler.                             *
     35  *   Do_Reinforcements -- Create and place a reinforcement team.                               *
     36  *   _Consists_Only_Of_Infantry -- Determine if this group consists only of infantry.          *
     37  *   _Create_Group -- Create a group given team specification.                                 *
     38  *   _Pop_Group_Out_Of_Object -- Process popping the group out of the object.                  *
     39  *   _Who_Can_Pop_Out_Of -- Find a suitable host for these reinforcements.                     *
     40  *   _Need_To_Take -- Examines unit to determine if it should be confiscated.                  *
     41  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     42 
     43 #include	"function.h"
     44 
     45 
     46 /***********************************************************************************************
     47  * _Pop_Group_Out_Of_Object -- Process popping the group out of the object.                    *
     48  *                                                                                             *
     49  *    This routine will cause the group to pop out of the object specified.                    *
     50  *                                                                                             *
     51  * INPUT:   group    -- Pointer to the first object in the group to be popped out.             *
     52  *                                                                                             *
     53  *          object   -- Pointer to the object that the group is to pop out of.                 *
     54  *                                                                                             *
     55  * OUTPUT:  bool; Was the group popped out of the specified object?                            *
     56  *                                                                                             *
     57  * WARNINGS:   none                                                                            *
     58  *                                                                                             *
     59  * HISTORY:                                                                                    *
     60  *   06/25/1996 JLB : Created.                                                                 *
     61  *=============================================================================================*/
     62 static bool _Pop_Group_Out_Of_Object(FootClass * group, TechnoClass * object)
     63 {
     64 	assert(group != NULL && object != NULL);
     65 	int quantity = 0;
     66 
     67 	/*
     68 	**	Take every infantry member of this group and detach it from the group list
     69 	**	and then make it pop out of the candidate source.
     70 	*/
     71 	while (group != NULL) {
     72 		TechnoClass * todo = group;
     73 		group = (FootClass *)(ObjectClass *)group->Next;
     74 		todo->Next = NULL;
     75 
     76 		switch (object->What_Am_I()) {
     77 
     78 			/*
     79 			**	The infantry just walks out of a building.
     80 			*/
     81 			case RTTI_BUILDING:
     82 				if (object->Exit_Object(todo) != 2) {
     83 					delete todo;
     84 				} else {
     85 					++quantity;
     86 				}
     87 				break;
     88 
     89 			/*
     90 			**	Infantry get attached to transport vehicles and then unload.
     91 			*/
     92 			case RTTI_UNIT:
     93 			case RTTI_VESSEL:
     94 			case RTTI_AIRCRAFT:
     95 				object->Attach((FootClass *)todo);
     96 				object->Assign_Mission(MISSION_UNLOAD);
     97 				++quantity;
     98 				break;
     99 
    100 			default:
    101 				delete todo;
    102 				break;
    103 		}
    104 	}
    105 
    106 	return (quantity != 0);
    107 }
    108 
    109 
    110 /***********************************************************************************************
    111  * _Need_To_Take -- Examines unit to determine if it should be confiscated.                    *
    112  *                                                                                             *
    113  *    The unit is examined and if the owning house needs to confiscate it, then this routine   *
    114  *    will return TRUE. In other cases, the unit should be left to its own devices.            *
    115  *                                                                                             *
    116  * INPUT:   unit  -- Pointer to the object to examine.                                         *
    117  *                                                                                             *
    118  * OUTPUT:  bool; Should the object be confiscated by the player so that it becomes one of     *
    119  *                his normal game objects?                                                     *
    120  *                                                                                             *
    121  * WARNINGS:   none                                                                            *
    122  *                                                                                             *
    123  * HISTORY:                                                                                    *
    124  *   07/26/1996 JLB : Created.                                                                 *
    125  *=============================================================================================*/
    126 bool _Need_To_Take(AircraftClass const * air)
    127 {
    128 	if (*air == AIRCRAFT_YAK || *air == AIRCRAFT_MIG) {
    129 		int deficit = air->House->Get_Quantity(STRUCT_AIRSTRIP);
    130 //		int deficit = air->House->Get_Quantity(STRUCT_AIRSTRIP) - (air->House->Get_Quantity(AIRCRAFT_YAK)+air->House->Get_Quantity(AIRCRAFT_MIG));
    131 
    132 		/*
    133 		**	Loop through all aircraft and subtract all the ones that are NOT loaners.
    134 		*/
    135 		for (int index = 0; index < Aircraft.Count(); index++) {
    136 			AircraftClass const * airptr = Aircraft.Ptr(index);
    137 			if ((*airptr == AIRCRAFT_YAK || *airptr == AIRCRAFT_MIG) && airptr->IsOwnedByPlayer && !airptr->IsALoaner && airptr != air) {
    138 				deficit -= 1;
    139 				if (deficit == 0) break;
    140 			}
    141 		}
    142 
    143 		if (deficit > 0) return(true);
    144 	}
    145 	return(false);
    146 }
    147 
    148 
    149 /***********************************************************************************************
    150  * _Create_Group -- Create a group given team specification.                                   *
    151  *                                                                                             *
    152  *    This routine will create all members of the group as specified by the team type.         *
    153  *                                                                                             *
    154  * INPUT:   teamtype -- Pointer to the team type that specifies what objects should be         *
    155  *                      created in this group.                                                 *
    156  *                                                                                             *
    157  * OUTPUT:  Returns with a pointer to the first member of the group created.                   *
    158  *                                                                                             *
    159  * WARNINGS:   none                                                                            *
    160  *                                                                                             *
    161  * HISTORY:                                                                                    *
    162  *   06/25/1996 JLB : Created.                                                                 *
    163  *=============================================================================================*/
    164 static FootClass * _Create_Group(TeamTypeClass const * teamtype)
    165 {
    166 	assert(teamtype != NULL);
    167 
    168 	TeamClass * team = new TeamClass(teamtype);
    169 	if (team != NULL) {
    170 		team->Force_Active();
    171 	}
    172 
    173 	bool hasunload = false;
    174 	for (int tm = 0; tm < teamtype->MissionCount; tm++) {
    175 		if (teamtype->MissionList[tm].Mission == TMISSION_UNLOAD) {
    176 			hasunload = true;
    177 			break;
    178 		}
    179 	}
    180 
    181 	/*
    182 	**	Now that the official source for the reinforcement has been determined, the
    183 	**	objects themselves must be created.
    184 	*/
    185 	FootClass * transport = NULL;
    186 	FootClass * object = NULL;
    187 	for (int index = 0; index < teamtype->ClassCount; index++) {
    188 		TechnoTypeClass const * tclass = teamtype->Members[index].Class;
    189 
    190 		for (int sub = 0; sub < teamtype->Members[index].Quantity; sub++) {
    191 			ScenarioInit++;
    192 			FootClass * temp = (FootClass *)tclass->Create_One_Of(HouseClass::As_Pointer(teamtype->House));
    193 			ScenarioInit--;
    194 
    195 			if (temp != NULL) {
    196 
    197 				/*
    198 				**	Add the member to the team.
    199 				*/
    200 				if (team != NULL) {
    201 					ScenarioInit++;
    202 					bool ok = team->Add(temp);
    203 //Mono_Printf("Added to team = %d.\n", ok);Keyboard->Get();
    204 
    205 					ScenarioInit--;
    206 					temp->IsInitiated = true;
    207 				}
    208 
    209 				if (temp->What_Am_I() == RTTI_AIRCRAFT && !_Need_To_Take((AircraftClass const *)temp)) {
    210 					temp->IsALoaner = true;
    211 				}
    212 
    213 				/*
    214 				**	Build the list of transporters and passengers.
    215 				*/
    216 				if (tclass->Max_Passengers() > 0) {
    217 
    218 					/*
    219 					**	Link to the list of transports.
    220 					*/
    221 					temp->Next = transport;
    222 					transport = temp;
    223 
    224 				} else {
    225 
    226 					/*
    227 					**	Link to the list of normal objects.
    228 					*/
    229 					temp->Next = object;
    230 					object = temp;
    231 				}
    232 			}
    233 		}
    234 	}
    235 
    236 	/*
    237 	**	If the group consists of transports and normal objects, then assign the normal
    238 	**	objects to be passengers on the transport.
    239 	*/
    240 	if (transport != NULL && object != NULL) {
    241 		transport->Attach(object);
    242 
    243 		/*
    244 		**	HACK ALERT! If the this team has an unload mission, then flag the transport
    245 		**	as a loaner so that it will exit from the map when the unload process is
    246 		**	complete, but only if the transport is an aircraft type.
    247 		*/
    248 		if (hasunload && (transport->What_Am_I() == RTTI_AIRCRAFT || transport->What_Am_I() == RTTI_VESSEL)) {
    249 			transport->IsALoaner = true;
    250 		}
    251 	}
    252 
    253 	/*
    254 	**	For JUST transport helicopters, consider the loaner a gift if there are
    255 	**	no passengers.
    256 	*/
    257 	if (transport != NULL && object == NULL && transport->What_Am_I() == RTTI_AIRCRAFT && *((AircraftClass *)transport) == AIRCRAFT_TRANSPORT) {
    258 		transport->IsALoaner = false;
    259 	}
    260 
    261 	if (transport == 0 && object == 0) {
    262 		if (team != NULL) delete team;
    263 		return(NULL);
    264 	}
    265 
    266 	/*
    267 	**	If this group consists only of non-transport object, then just return with a pointer
    268 	**	to the first member of the group.
    269 	*/
    270 	if (transport == NULL) {
    271 		return(object);
    272 	}
    273 
    274 	return(transport);
    275 }
    276 
    277 
    278 /***********************************************************************************************
    279  * _Consists_Only_Of_Infantry -- Determine if this group consists only of infantry.            *
    280  *                                                                                             *
    281  *    Use this to determine if the specified group only contains infantry. Such a reinforcement*
    282  *    group is a candidate for popping out of a building or transport vehicle rather than      *
    283  *    driving/walking/sailing/flying onto the map under its own power.                         *
    284  *                                                                                             *
    285  * INPUT:   first -- Pointer to the first object in the group to examine.                      *
    286  *                                                                                             *
    287  * OUTPUT:  bool; Is the entire group composed of infantry type units?                         *
    288  *                                                                                             *
    289  * WARNINGS:   none                                                                            *
    290  *                                                                                             *
    291  * HISTORY:                                                                                    *
    292  *   06/25/1996 JLB : Created.                                                                 *
    293  *=============================================================================================*/
    294 static bool _Consists_Only_Of_Infantry(FootClass const * first)
    295 {
    296 	while (first != NULL) {
    297 		if (first->What_Am_I() != RTTI_INFANTRY) {
    298 			return(false);
    299 		}
    300 		first = (FootClass const *)((ObjectClass *)first->Next);
    301 	}
    302 	return(true);
    303 }
    304 
    305 
    306 /***********************************************************************************************
    307  * _Who_Can_Pop_Out_Of -- Find a suitable host for these reinforcements.                       *
    308  *                                                                                             *
    309  *    This routine is used to scan nearby locations to determine if there is a suitable host   *
    310  *    for these reinforcements to "pop out of" (apologies to Aliens). Typical hosts include    *
    311  *    buildings and transport vehicles (of any kind).                                          *
    312  *                                                                                             *
    313  * INPUT:   origin   -- The cell that should be scanned from. Only this location and immediate *
    314  *                      adjacent locations will be scanned.                                    *
    315  *                                                                                             *
    316  * OUTPUT:  Returns with a pointer to a suitable host. If none could be found then NULL is     *
    317  *          returned.                                                                          *
    318  *                                                                                             *
    319  * WARNINGS:   none                                                                            *
    320  *                                                                                             *
    321  * HISTORY:                                                                                    *
    322  *   06/25/1996 JLB : Created.                                                                 *
    323  *=============================================================================================*/
    324 static TechnoClass * _Who_Can_Pop_Out_Of(CELL origin)
    325 {
    326 	CellClass * cellptr = &Map[origin];
    327 	TechnoClass * candidate = NULL;
    328 
    329 	for (int f = -1; f < 8; f++) {
    330 		CellClass * ptr = cellptr;
    331 		if (f != -1) {
    332 			ptr = ptr->Adjacent_Cell(FacingType(f));
    333 			if (!ptr) continue;
    334 		}
    335 
    336 		BuildingClass * building = ptr->Cell_Building();
    337 		if (building && building->Strength > 0) {
    338 			candidate = building;
    339 		}
    340 
    341 		UnitClass * unit = ptr->Cell_Unit();
    342 		if (unit && unit->Strength && unit->Class->Max_Passengers() > 0) {
    343 			return(unit);
    344 		}
    345 	}
    346 	return(candidate);
    347 }
    348 
    349 
    350 /***********************************************************************************************
    351  * Do_Reinforcements -- Create and place a reinforcement team.                                 *
    352  *                                                                                             *
    353  *    This routine is called when a reinforcement team must be created and placed on the map.  *
    354  *    It will create all members of the team and place them at the location determined from    *
    355  *    the team composition. The reinforcement team should follow team orders until overridden  *
    356  *    by AI or player intervention.                                                            *
    357  *                                                                                             *
    358  * INPUT:   teamtype -- Pointer to the team type to create as a reinforcement.                 *
    359  *                                                                                             *
    360  * OUTPUT:  Was the reinforcement successfully created and placed?                             *
    361  *                                                                                             *
    362  * WARNINGS:   none                                                                            *
    363  *                                                                                             *
    364  * HISTORY:                                                                                    *
    365  *   05/08/1995 JLB : Created.                                                                 *
    366  *   05/18/1995 JLB : Returns success or failure condition.                                    *
    367  *   06/19/1995 JLB : Announces reinforcements.                                                *
    368  *   02/15/1996 JLB : Recognizes team reinforcement location.                                  *
    369  *=============================================================================================*/
    370 bool Do_Reinforcements(TeamTypeClass const * teamtype)
    371 {
    372 	assert(teamtype != 0);
    373 
    374 	/*
    375 	**	perform some preliminary checks for validity.
    376 	*/
    377 	if (!teamtype || !teamtype->ClassCount) return(false);
    378 
    379 	/*
    380 	**	HACK ALERT!
    381 	**	Give this team an attack waypoint mission that will attack the waypoint location of this
    382 	**	team if there are no team missions previously assigned.
    383 	*/
    384 	if (teamtype->MissionCount == 0) {
    385 		TeamTypeClass * tt = (TeamTypeClass *)teamtype;
    386 		tt->MissionCount = 1;
    387 		tt->MissionList[0].Mission = TMISSION_ATT_WAYPT;
    388 		tt->MissionList[0].Data.Value = teamtype->Origin;
    389 	}
    390 
    391 	FootClass * object = _Create_Group(teamtype);
    392 
    393 
    394 //Mono_Printf("%d-%s (object=%p, team=%d).\n", __LINE__, __FILE__, object, object->Team.Is_Valid());Keyboard->Get();
    395 
    396 
    397 	/*
    398 	**	Bail on this reinforcement if no reinforcements could be created.
    399 	**	This is probably because the object maximum was reached.
    400 	*/
    401 	if (!object) {
    402 		return(false);
    403 	}
    404 
    405 	/*
    406 	**	Special case code to handle infantry types that run from a building. This presumes
    407 	**	that infantry are never a transport (which is safe to do).
    408 	*/
    409 	if (object != NULL && teamtype->Origin != -1 && _Consists_Only_Of_Infantry(object)) {
    410 
    411 		/*
    412 		**	Search for an object that these infantry can pop out of.
    413 		*/
    414 		TechnoClass * candidate = _Who_Can_Pop_Out_Of(Scen.Waypoint[teamtype->Origin]);
    415 
    416 		if (candidate != NULL) {
    417 			return(_Pop_Group_Out_Of_Object(object, candidate));
    418 		}
    419 	}
    420 
    421 	/*
    422 	**	The reinforcements must be delivered the old fashioned way -- by moving onto the
    423 	**	map using their own power. First order of business is to determine where they
    424 	**	should arrive from.
    425 	*/
    426 	SourceType source = HouseClass::As_Pointer(teamtype->House)->Control.Edge;
    427 	if (source == SOURCE_NONE) {
    428 		source = SOURCE_NORTH;
    429 	}
    430 
    431 	/*
    432 	**	Pick the location where the reinforcements appear and then place
    433 	**	them there.
    434 	*/
    435 	bool placed = false;
    436 
    437 	FacingType eface = (FacingType)(source << 1);	// Facing to enter map.
    438 
    439 	CELL cell = Map.Calculated_Cell(source, teamtype->Origin, -1, object->Techno_Type_Class()->Speed);
    440 #ifdef FIXIT_ANTS
    441 	/*
    442 	**	For the ants, they will pop out of the ant hill directly.
    443 	*/
    444 	if (teamtype->Origin != -1 && object->What_Am_I() == RTTI_UNIT && 
    445 			(*((UnitClass*)object) == UNIT_ANT1 ||
    446 			*((UnitClass*)object) == UNIT_ANT2 ||
    447 			*((UnitClass*)object) == UNIT_ANT3))  {
    448 		CELL newcell = Scen.Waypoint[teamtype->Origin];
    449 		if (newcell != -1)  {
    450 			if (Map[newcell].TType == TEMPLATE_HILL01)  {
    451 				cell = newcell;
    452 			}
    453 		}
    454 	}
    455 #endif
    456 
    457 	CELL newcell = cell;
    458 
    459 	FootClass * o = (FootClass *)(ObjectClass *)object->Next;
    460 	object->Next = 0;
    461 	bool okvoice = false;
    462 	while (newcell > 0 && object != NULL) {
    463 		DirType desiredfacing = Facing_Dir(eface);
    464 		if (object->What_Am_I() == RTTI_AIRCRAFT) {
    465 			desiredfacing = Random_Pick(DIR_N, DIR_MAX);
    466 		}
    467 
    468 		ScenarioInit++;
    469 		if (object->Unlimbo(Cell_Coord(newcell), desiredfacing)) {
    470 			okvoice = true;
    471 
    472 			/*
    473 			**	If this object is part of a team, then the mission for this
    474 			**	object will be guard. The team handler will assign the proper
    475 			**	mission that it should follow.
    476 			*/
    477 			if (object->What_Am_I() != RTTI_AIRCRAFT) {
    478 				object->Assign_Mission(MISSION_GUARD);
    479 				object->Commence();
    480 			}
    481 
    482 		} else {
    483 
    484 			/*
    485 			**	Could not unlimbo at location specified so find an adjacent location that it can
    486 			**	be unlimboed at. If this fails, then abort the whole placement process.
    487 			*/
    488 			FacingType adj;
    489 			for (adj = FACING_N; adj < FACING_COUNT; adj++) {
    490 				CELL trycell = Adjacent_Cell(newcell, adj);
    491 				if (!Map.In_Radar(trycell) && object->Can_Enter_Cell(trycell, adj) == MOVE_OK) {
    492 					newcell = trycell;
    493 					break;
    494 				}
    495 			}
    496 			if (adj < FACING_COUNT) continue;
    497 			newcell = 0;
    498 		}
    499 		ScenarioInit--;
    500 
    501 		object = o;
    502 		if (object != NULL) {
    503 			o = (FootClass *)(ObjectClass *)object->Next;
    504 			object->Next = 0;
    505 		}
    506 	}
    507 
    508 	/*
    509 	**	If there are still objects that could not be placed, then delete them.
    510 	*/
    511 	if (o != NULL) {
    512 		while (o != NULL) {
    513 			FootClass * old = o;
    514 			o = (FootClass *)(ObjectClass *)o->Next;
    515 			old->Next = 0;
    516 
    517 			delete old;
    518 		}
    519 	}
    520 
    521 	/*
    522 	**	Announce when the reinforcements have arrived.
    523 	*/
    524 	if (okvoice && teamtype->House == PlayerPtr->Class->House) {
    525 		Speak(VOX_REINFORCEMENTS, NULL, newcell ? Cell_Coord(newcell) : 0);
    526 	}
    527 
    528 	return(true);
    529 }
    530 
    531 
    532 /***********************************************************************************************
    533  * Create_Special_Reinforcement -- Ad hoc reinforcement handler.                               *
    534  *                                                                                             *
    535  *    Use this routine to bring on a reinforcement that hasn't been anticipated by the trigger *
    536  *    system. An example of this would be replacement harvesters or airfield ordered units.    *
    537  *    The appropriate transport is created (if necessary) and a mission is assigned such that  *
    538  *    the object will legally bring itself onto the playing field.                             *
    539  *                                                                                             *
    540  * INPUT:   house    -- The owner of this reinforcement.                                       *
    541  *                                                                                             *
    542  *          type     -- The object to bring on.                                                *
    543  *                                                                                             *
    544  *          another  -- This is reserved for the transport class in those cases where the      *
    545  *                      transport MUST be forced to a specific type.                           *
    546  *                                                                                             *
    547  *          mission  -- The mission to assign this reinforcement team.                         *
    548  *                                                                                             *
    549  *          argument -- Optional team mission argument (usually a waypoint).                   *
    550  *                                                                                             *
    551  * OUTPUT:  Was the special reinforcement created without error?                               *
    552  *                                                                                             *
    553  * WARNINGS:   This routine will fail if a team type cannot be created.                        *
    554  *                                                                                             *
    555  * HISTORY:                                                                                    *
    556  *   07/04/1995 JLB : Created.                                                                 *
    557  *=============================================================================================*/
    558 bool Create_Special_Reinforcement(HouseClass * house, TechnoTypeClass const * type, TechnoTypeClass const * another, TeamMissionType mission, int argument)
    559 {
    560 	assert(house != 0);
    561 	assert(type != 0);
    562 
    563 	if (house && type) {
    564 		TeamTypeClass * team = new TeamTypeClass();
    565 
    566 		if (team) {
    567 
    568 			/*
    569 			**	If there is no overridden mission assign to this special reinforcement, then
    570 			**	we must assign something. If not, the reinforcement will just sit at the edge
    571 			**	of the map.
    572 			*/
    573 			if (!another && mission == TMISSION_NONE) {
    574 				mission = TMISSION_MOVECELL;
    575 				argument = Map.Calculated_Cell(house->Control.Edge);
    576 			}
    577 
    578 			/*
    579 			**	Fill in the team characteristics.
    580 			*/
    581 			strcpy((char *)&team->IniName[0], "TEMP");
    582 			team->IsReinforcable = false;
    583 			team->IsTransient = true;
    584 			team->ClassCount = 1;
    585 			team->Members[0].Class = type;
    586 			team->Members[0].Quantity = 1;
    587 			team->MissionCount = 1;
    588 			if (mission == TMISSION_NONE) {
    589 				team->MissionList[0].Mission	= TMISSION_UNLOAD;
    590 				team->MissionList[0].Data.Value = WAYPT_REINF;
    591 			} else {
    592 				team->MissionList[0].Mission	= mission;
    593 				team->MissionList[0].Data.Value = argument;
    594 			}
    595 			team->House = house->Class->House;
    596 			if (another) {
    597 				team->ClassCount++;
    598 				team->Members[1].Class = another;
    599 				team->Members[1].Quantity = 1;
    600 			}
    601 
    602 			bool ok = Do_Reinforcements(team);
    603 			if (!ok) delete team;
    604 			return(ok);
    605 		}
    606 	}
    607 	return(false);
    608 }
    609 
    610 
    611 /***********************************************************************************************
    612  * Create_Air_Reinforcement -- Creates air strike reinforcement                                *
    613  *                                                                                             *
    614  *    This routine is used to launch an airstrike. It will create the necessary aircraft and   *
    615  *    assign them to attack the target specified. This routine bypasses the normal             *
    616  *    reinforcement logic since it doesn't need the sophistication of unloading and following  *
    617  *    team mission lists.                                                                      *
    618  *                                                                                             *
    619  * INPUT:   house    -- The perpetrator of this air strike.                                    *
    620  *                                                                                             *
    621  *          air      -- The type of aircraft to make up this airstrike.                        *
    622  *                                                                                             *
    623  *          number   -- The number of aircraft in this airstrike.                              *
    624  *                                                                                             *
    625  *          mission  -- The mission to assign the aircraft.                                    *
    626  *                                                                                             *
    627  *          tarcom   -- The target to assign these aircraft.                                   *
    628  *                                                                                             *
    629  *          navcom   -- The navigation target to assign (if necessary).                        *
    630  *                                                                                             *
    631  * OUTPUT:  Returns the number of aircraft created for this airstrike.                         *
    632  *                                                                                             *
    633  * WARNINGS:   none                                                                            *
    634  *                                                                                             *
    635  * HISTORY:                                                                                    *
    636  *   07/04/1995 JLB : Commented.                                                               *
    637  *=============================================================================================*/
    638 int Create_Air_Reinforcement(HouseClass * house, AircraftType air, int number, MissionType mission, TARGET tarcom, TARGET navcom, InfantryType passenger)
    639 {
    640 	assert(house != 0);
    641 	assert((unsigned)air < AIRCRAFT_COUNT);
    642 	assert(number != 0);
    643 	assert((unsigned)mission < MISSION_COUNT);
    644 	/*
    645 	** Get a pointer to the class of the object that we are going to create.
    646 	*/
    647 	TechnoTypeClass const * type = (TechnoTypeClass *)&AircraftTypeClass::As_Reference(air);
    648 
    649 	/*
    650 	** Abort the airstrike if Tanya is the passenger and she's dead.
    651 	*/
    652 	if (passenger == INFANTRY_TANYA && IsTanyaDead) {
    653 		number = 0;
    654 	}
    655 
    656 	/*
    657 	** Loop through the number of objects we are supposed to create and
    658 	** 	create and place them on the map.
    659 	*/
    660 	int sub;
    661 	for (sub = 0; sub < number; sub++) {
    662 
    663 		/*
    664 		** Create one of the required objects.  If this fails we could have
    665 		** a real problem.
    666 		*/
    667 		ScenarioInit++;
    668 		TechnoClass * obj = (TechnoClass *)type->Create_One_Of(house);
    669 		ScenarioInit--;
    670 		if (!obj) return(sub);
    671 
    672 		/*
    673 		** Flying objects always have the IsALoaner bit set.
    674 		*/
    675 		obj->IsALoaner = true;
    676 
    677 		/*
    678 		** Find a cell for the object to come in on.  This is stolen from the
    679 		** the code that handles a SOURCE_AIR in the normal logic.
    680 		*/
    681 		SourceType source = house->Control.Edge;
    682 		switch (source) {
    683 			case SOURCE_NORTH:
    684 			case SOURCE_EAST:
    685 			case SOURCE_SOUTH:
    686 			case SOURCE_WEST:
    687 				break;
    688 
    689 			default:
    690 				source = SOURCE_NORTH;
    691 				break;
    692 		}
    693 		CELL newcell = Map.Calculated_Cell(source, -1, -1, SPEED_WINGED);
    694 
    695 		/*
    696 		** Try and place the object onto the map.
    697 		*/
    698 		ScenarioInit++;
    699 		int placed = obj->Unlimbo(Cell_Coord(newcell), DIR_N);
    700 		ScenarioInit--;
    701 		if (placed) {
    702 
    703 			/*
    704 			** If we succeeded in placing the obj onto the map then
    705 			** now we need to give it a mission and destination.
    706 			*/
    707 			obj->Assign_Mission(mission);
    708 
    709 			/*
    710 			** If a navcom was specified then set it.
    711 			*/
    712 			if (navcom != TARGET_NONE) {
    713 				obj->Assign_Destination(navcom);
    714 			}
    715 
    716 			/*
    717 			** If a tarcom was specified then set it.
    718 			*/
    719 			if (tarcom != TARGET_NONE) {
    720 				obj->Assign_Target(tarcom);
    721 			}
    722 
    723 			/*
    724 			**	Assign generic passenger value here. This value is used to determine
    725 			**	if this aircraft should drop parachute reinforcements.
    726 			*/
    727 			if (obj->What_Am_I() == RTTI_AIRCRAFT) {
    728 				AircraftClass * aircraft = (AircraftClass *)obj;
    729 				if (passenger != INFANTRY_NONE) {
    730 					aircraft->Passenger = passenger;
    731 				}
    732 //				if (Passenger == INFANTRY_TANYA) {
    733 //					aircraft->Ammo = 1;
    734 					//aircraft->AttacksRemaining = 1;
    735 //				}
    736 			}
    737 
    738 			/*
    739 			** Start the object into action.
    740 			*/
    741 			obj->Commence();
    742 		} else {
    743 			delete obj;
    744 			sub--;
    745 			return(sub);
    746 		}
    747 	}
    748 	return(sub);
    749 }