CnC_Remastered_Collection

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

TEAMTYPE.CPP (76202B)


      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/TEAMTYPE.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 : TEAMTYPE.CPP                                                 *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : 06/28/96                                                     *
     28  *                                                                                             *
     29  *                  Last Update : July 30, 1996 [JLB]                                          *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   TeamMissionClass::Description -- Compose a text description of team mi                    *
     34  *   TeamMissionClass::Draw_It -- Draws a team mission list box entry.                         *
     35  *   TeamMission_Needs -- Determines what extra data is needed by team miss                    *
     36  *   TeamTypeClass::As_Pointer -- gets ptr for team type with given name                       *
     37  *   TeamTypeClass::Build_INI_Entry -- Builds the INI entry for this team type.                *
     38  *   TeamTypeClass::Create_One_Of -- Creates a team of this type.                              *
     39  *   TeamTypeClass::Description -- Builds a description of the team.                           *
     40  *   TeamTypeClass::Destroy_All_Of -- Destroy all teams of this type.                          *
     41  *   TeamTypeClass::Detach -- Detach the specified target from this team type.                 *
     42  *   TeamTypeClass::Draw_It -- Display the team type in a list box.                            *
     43  *   TeamTypeClass::Edit -- Edit the team type.                                                *
     44  *   TeamTypeClass::Fill_In -- fills in trigger from the given INI entry                       *
     45  *   TeamTypeClass::From_Name -- Converts a name into a team type pointer.                     *
     46  *   TeamTypeClass::Init -- pre-scenario initialization                                        *
     47  *   TeamTypeClass::Member_Description -- Builds a member description string                   *
     48  *   TeamTypeClass::Mission_From_Name -- returns mission for given name                        *
     49  *   TeamTypeClass::Name_From_Mission -- returns name for given mission                        *
     50  *   TeamTypeClass::Read_INI -- reads INI data                                                 *
     51  *   TeamTypeClass::Suggested_New_Team -- Suggests a new team to create.                       *
     52  *   TeamTypeClass::TeamTypeClass -- class constructor                                         *
     53  *   TeamTypeClass::Write_INI -- Write out the team types to the INI database.                 *
     54  *   TeamTypeClass::operator delete -- 'delete' operator                                       *
     55  *   TeamTypeClass::operator new -- 'new' operator                                             *
     56  *   TeamTypeClass::~TeamTypeClass -- class destructor                                         *
     57  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     58 
     59 #include "function.h"
     60 
     61 
     62 TeamMissionClass TeamMissions[TMISSION_COUNT] = {
     63 	{TMISSION_ATTACK},
     64 	{TMISSION_ATT_WAYPT},
     65 	{TMISSION_FORMATION},
     66 	{TMISSION_MOVE},
     67 	{TMISSION_MOVECELL},
     68 	{TMISSION_GUARD},
     69 	{TMISSION_LOOP},
     70 	{TMISSION_ATTACKTARCOM},
     71 	{TMISSION_UNLOAD},
     72 	{TMISSION_DEPLOY},
     73 	{TMISSION_HOUND_DOG},
     74 	{TMISSION_DO},
     75 	{TMISSION_SET_GLOBAL},
     76 	{TMISSION_LOAD},
     77 	{TMISSION_SPY},
     78 	{TMISSION_PATROL},
     79 };
     80 
     81 
     82 
     83 int atoh(char * str);
     84 
     85 
     86 #if defined(CHEAT_KEYS) || defined(SCENARIO_EDITOR)
     87 /***********************************************************************************************
     88  * TeamTypeClass::Draw_It -- Display the team type in a list box.                              *
     89  *                                                                                             *
     90  *    This is a helper routine that is used when this team type is stored into a list box      *
     91  *    and must be displayed. It will display the team type as a single line of text.           *
     92  *                                                                                             *
     93  * INPUT:   see below...                                                                       *
     94  *                                                                                             *
     95  * OUTPUT:  none                                                                               *
     96  *                                                                                             *
     97  * WARNINGS:   none                                                                            *
     98  *                                                                                             *
     99  * HISTORY:                                                                                    *
    100  *   07/30/1996 JLB : Created.                                                                 *
    101  *=============================================================================================*/
    102 void TeamTypeClass::Draw_It(int , int x, int y, int width, int height, bool selected, TextPrintType flags) const
    103 {
    104 	RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
    105 	static int _tabs[] = {35, 60, 80, 100};
    106 	if ((flags & 0x0F) == TPF_6PT_GRAD || (flags & 0x0F) == TPF_EFNT) {
    107 
    108 		if (selected) {
    109 			flags = flags | TPF_BRIGHT_COLOR;
    110 			LogicPage->Fill_Rect(x, y, x + width - 1, y + height - 1, scheme->Shadow);
    111 		} else {
    112 			if (!(flags & TPF_USE_GRAD_PAL)) {
    113 				flags = flags | TPF_MEDIUM_COLOR;
    114 			}
    115 		}
    116 
    117 		Conquer_Clip_Text_Print(Description(), x, y, scheme, TBLACK, flags, width, _tabs);
    118 	} else {
    119 		Conquer_Clip_Text_Print(Description(), x, y, (selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, flags, width, _tabs);
    120 	}
    121 }
    122 #endif
    123 
    124 
    125 /*
    126 ********************************** Globals **********************************
    127 */
    128 char const * TeamTypeClass::TMissions[TMISSION_COUNT] = {
    129 	"Attack...",
    130 	"Attack Waypoint...",
    131 	"Change Formation to...",
    132 	"Move to waypoint...",
    133 	"Move to Cell...",
    134 	"Guard area (1/10th min)...",
    135 	"Jump to line #...",
    136 	"Attack Tarcom",
    137 	"Unload",
    138 	"Deploy",
    139 	"Follow friendlies",
    140 	"Do this...",
    141 	"Set global...",
    142 	"Invulnerable",
    143 	"Load onto Transport",
    144 	"Spy on bldg @ waypt...",
    145 	"Patrol to waypoint..."
    146 };
    147 
    148 
    149 /***************************************************************************
    150  * TeamTypeClass::TeamTypeClass -- class constructor                       *
    151  *                                                                         *
    152  * INPUT:                                                                  *
    153  *                                                                         *
    154  * OUTPUT:                                                                 *
    155  *                                                                         *
    156  * WARNINGS:                                                               *
    157  *                                                                         *
    158  * HISTORY:                                                                *
    159  *   12/07/1994 BR : Created.                                              *
    160  *   11/22/1995 JLB : Uses initializer constructor method.                 *
    161  *=========================================================================*/
    162 TeamTypeClass::TeamTypeClass(void) :
    163 	AbstractTypeClass(RTTI_TEAMTYPE, TeamTypes.ID(this), TXT_NONE, ""),
    164 	IsRoundAbout(false),
    165 	IsSuicide(false),
    166 	IsAutocreate(false),
    167 	IsPrebuilt(true),
    168 	IsReinforcable(true),
    169 	IsTransient(false),
    170 	RecruitPriority(7),
    171 	InitNum(0),
    172 	MaxAllowed(0),
    173 	Fear(0),
    174 	House(HOUSE_NONE),
    175 	Trigger(0),
    176 	Origin(-1),
    177 	Number(0),
    178 	MissionCount(0),
    179 	ClassCount(0)
    180 {
    181 	for (int i = 0; i < MAX_TEAM_CLASSCOUNT; i++) {
    182 		Members[i].Class = NULL;
    183 		Members[i].Quantity = 0;
    184 	}
    185 }
    186 
    187 
    188 /***************************************************************************
    189  * TeamTypeClass::Init -- pre-scenario initialization                      *
    190  *                                                                         *
    191  * INPUT:                                                                  *
    192  *                                                                         *
    193  * OUTPUT:                                                                 *
    194  *                                                                         *
    195  * WARNINGS:                                                               *
    196  *                                                                         *
    197  * HISTORY:                                                                *
    198  *   12/07/1994 BR : Created.                                              *
    199  *=========================================================================*/
    200 void TeamTypeClass::Init(void)
    201 {
    202 	TeamTypes.Free_All();
    203 }
    204 
    205 
    206 /***************************************************************************
    207  * TeamTypeClass::As_Pointer -- gets ptr for team type with given name     *
    208  *                                                                         *
    209  * INPUT:                                                                  *
    210  *      name      name of teamtype                                         *
    211  *                                                                         *
    212  * OUTPUT:                                                                 *
    213  *      ptr to TeamType with that name                                     *
    214  *                                                                         *
    215  * WARNINGS:                                                               *
    216  *      none.                                                              *
    217  *                                                                         *
    218  * HISTORY:                                                                *
    219  *   12/07/1994 BR : Created.                                              *
    220  *=========================================================================*/
    221 TeamTypeClass * TeamTypeClass::As_Pointer(char const * name)
    222 {
    223 	if (name) {
    224 		for (int index = 0; index < TeamTypes.Count(); index++) {
    225 			if (!stricmp(name, TeamTypes.Ptr(index)->IniName)) {
    226 				return(TeamTypes.Ptr(index));
    227 			}
    228 		}
    229 	}
    230 	return(NULL);
    231 }
    232 
    233 
    234 /***************************************************************************
    235  * TeamTypeClass::Mission_From_Name -- returns team mission for given name *
    236  *                                                                         *
    237  * INPUT:                                                                  *
    238  *      name         name to compare                                       *
    239  *                                                                         *
    240  * OUTPUT:                                                                 *
    241  *      mission for that name                                              *
    242  *                                                                         *
    243  * WARNINGS:                                                               *
    244  *      none.                                                              *
    245  *                                                                         *
    246  * HISTORY:                                                                *
    247  *   12/13/1994 BR : Created.                                              *
    248  *=========================================================================*/
    249 TeamMissionType TeamTypeClass::Mission_From_Name(char const * name)
    250 {
    251 	if (name) {
    252 		for (TeamMissionType order = TMISSION_FIRST; order < TMISSION_COUNT; order++) {
    253 			if (stricmp(TMissions[order], name) == 0) {
    254 				return(order);
    255 			}
    256 		}
    257 	}
    258 
    259 	return(TMISSION_NONE);
    260 }
    261 
    262 
    263 /***************************************************************************
    264  * TeamTypeClass::Name_From_Mission -- returns name for given mission      *
    265  *                                                                         *
    266  * INPUT:                                                                  *
    267  *      order      mission to get name for                                 *
    268  *                                                                         *
    269  * OUTPUT:                                                                 *
    270  *      name of mission                                                    *
    271  *                                                                         *
    272  * WARNINGS:                                                               *
    273  *      none.                                                              *
    274  *                                                                         *
    275  * HISTORY:                                                                *
    276  *   12/13/1994 BR : Created.                                              *
    277  *=========================================================================*/
    278 char const * TeamTypeClass::Name_From_Mission(TeamMissionType order)
    279 {
    280 	assert((unsigned)order < TMISSION_COUNT);
    281 
    282 	return(TMissions[order]);
    283 }
    284 
    285 
    286 /***************************************************************************
    287  * TeamTypeClass::operator new -- 'new' operator                           *
    288  *                                                                         *
    289  * INPUT:                                                                  *
    290  *      none.                                                              *
    291  *                                                                         *
    292  * OUTPUT:                                                                 *
    293  *      pointer to new TeamType                                            *
    294  *                                                                         *
    295  * WARNINGS:                                                               *
    296  *      none.                                                              *
    297  *                                                                         *
    298  * HISTORY:                                                                *
    299  *   11/28/1994 BR : Created.                                              *
    300  *=========================================================================*/
    301 void * TeamTypeClass::operator new(size_t )
    302 {
    303 	void * ptr = TeamTypes.Allocate();
    304 	if (ptr) {
    305 		((TeamTypeClass *)ptr)->IsActive = true;
    306 	}
    307 	return(ptr);
    308 }
    309 
    310 
    311 /***************************************************************************
    312  * TeamTypeClass::operator delete -- 'delete' operator                     *
    313  *                                                                         *
    314  * INPUT:                                                                  *
    315  *      ptr      pointer to delete                                         *
    316  *                                                                         *
    317  * OUTPUT:                                                                 *
    318  *      none.                                                              *
    319  *                                                                         *
    320  * WARNINGS:                                                               *
    321  *      none.                                                              *
    322  *                                                                         *
    323  * HISTORY:                                                                *
    324  *   11/28/1994 BR : Created.                                              *
    325  *=========================================================================*/
    326 void TeamTypeClass::operator delete(void * ptr)
    327 {
    328 	if (ptr) {
    329 		((TeamTypeClass *)ptr)->IsActive = false;
    330 	}
    331 	TeamTypes.Free((TeamTypeClass *)ptr);
    332 }
    333 
    334 
    335 /***********************************************************************************************
    336  * TeamTypeClass::Create_One_Of -- Creates a team of this type.                                *
    337  *                                                                                             *
    338  *    Use this routine to create a team object from this team type.                            *
    339  *                                                                                             *
    340  * INPUT:   none                                                                               *
    341  *                                                                                             *
    342  * OUTPUT:  Returns with a pointer to the newly created team object. If one could not be       *
    343  *          created, then NULL is returned.                                                    *
    344  *                                                                                             *
    345  * WARNINGS:   none                                                                            *
    346  *                                                                                             *
    347  * HISTORY:                                                                                    *
    348  *   09/21/1995 JLB : Created.                                                                 *
    349  *=============================================================================================*/
    350 TeamClass * TeamTypeClass::Create_One_Of(void) const
    351 {
    352 	if (ScenarioInit || Number < MaxAllowed) {
    353 //	if (ScenarioInit || TeamClass::Number[ID] < MaxAllowed) {
    354 		return(new TeamClass(this, HouseClass::As_Pointer(House)));
    355 	}
    356 	return(NULL);
    357 }
    358 
    359 
    360 /***********************************************************************************************
    361  * TeamTypeClass::Destroy_All_Of -- Destroy all teams of this type.                            *
    362  *                                                                                             *
    363  *    This routine will destroy all teams of this type. Typical use of this is from a trigger  *
    364  *    event.                                                                                   *
    365  *                                                                                             *
    366  * INPUT:   none                                                                               *
    367  *                                                                                             *
    368  * OUTPUT:  none                                                                               *
    369  *                                                                                             *
    370  * WARNINGS:   none                                                                            *
    371  *                                                                                             *
    372  * HISTORY:                                                                                    *
    373  *   09/21/1995 JLB : Created.                                                                 *
    374  *=============================================================================================*/
    375 void TeamTypeClass::Destroy_All_Of(void) const
    376 {
    377 	for (int index = 0; index < Teams.Count(); index++) {
    378 		TeamClass * team = Teams.Ptr(index);
    379 
    380 		if (team->Class == this) {
    381 			delete team;
    382 			index--;
    383 		}
    384 	}
    385 }
    386 
    387 
    388 /***********************************************************************************************
    389  * TeamTypeClass::Suggested_New_Team -- Suggests a new team to create.                         *
    390  *                                                                                             *
    391  *    This routine will scan through the team types available and create teams of the          *
    392  *    type that can best utilize the existing unit mix.                                        *
    393  *                                                                                             *
    394  * INPUT:   house    -- Pointer to the house that this team is to be created for.              *
    395  *                                                                                             *
    396  *          atypes   -- A bit mask of the aircraft types available for this house.             *
    397  *                                                                                             *
    398  *          utypes   -- A bit mask of the unit types available for this house.                 *
    399  *                                                                                             *
    400  *          itypes   -- A bit mask of the infantry types available for this house.             *
    401  *                                                                                             *
    402  *          vtypes   -- A bit mask of the vessel types available for this house.               *
    403  *                                                                                             *
    404  *          alerted  -- Is this house alerted? If true, then the Autocreate teams will be      *
    405  *                      considered in the selection process.                                   *
    406  *                                                                                             *
    407  * OUTPUT:  Returns with a pointer to the team type that should be created. If no team should  *
    408  *          be created, then it returns NULL.                                                  *
    409  *                                                                                             *
    410  * WARNINGS:   none                                                                            *
    411  *                                                                                             *
    412  * HISTORY:                                                                                    *
    413  *   07/13/1995 JLB : Created.                                                                 *
    414  *   07/21/1995 JLB : Will autocreate team even if no members in field.                        *
    415  *=============================================================================================*/
    416 TeamTypeClass const * TeamTypeClass::Suggested_New_Team(HouseClass * house, long , long , long , long , bool alerted)
    417 //TeamTypeClass const * TeamTypeClass::Suggested_New_Team(HouseClass * house, long atypes, long utypes, long itypes, long vtypes, bool alerted)
    418 {
    419 //	TeamTypeClass const * best = NULL;
    420 //	int bestvalue = 0;
    421 
    422 	TeamTypeClass const * choices[20];
    423 	int choicecount = 0;
    424 
    425 	for (int index = 0; index < TeamTypes.Count(); index++) {
    426 		TeamTypeClass const * ttype = TeamTypes.Ptr(index);
    427 
    428 		assert(ttype != NULL);
    429 
    430 		int maxnum = ttype->MaxAllowed;
    431 		if ((alerted && !ttype->IsAutocreate) || (!alerted && ttype->IsAutocreate)) {
    432 			maxnum = 0;
    433 		}
    434 
    435 		if (choicecount >= ARRAY_SIZE(choices)) break;
    436 
    437 		if (ttype != NULL && ttype->House == house->Class->House && ttype->Number < maxnum) {
    438 
    439 			choices[choicecount++] = ttype;
    440 
    441 #ifdef OBSOLETE
    442 			/*
    443 			**	Determine what kind of units this team requires.
    444 			*/
    445 			long uneeded = 0;
    446 			long ineeded = 0;
    447 			long vneeded = 0;
    448 			long aneeded = 0;
    449 			for (int ctype = 0; ctype < ttype->ClassCount; ctype++) {
    450 				switch (ttype->Members[ctype].Class->What_Am_I()) {
    451 					case RTTI_INFANTRYTYPE:
    452 						ineeded |= (1 << ((InfantryTypeClass *)ttype->Members[ctype].Class)->Type);
    453 						break;
    454 
    455 					case RTTI_UNITTYPE:
    456 						uneeded |= (1 << ((UnitTypeClass *)ttype->Members[ctype].Class)->Type);
    457 						break;
    458 
    459 					case RTTI_VESSELTYPE:
    460 						vneeded |= (1 << ((VesselTypeClass *)ttype->Members[ctype].Class)->Type);
    461 						break;
    462 
    463 					case RTTI_AIRCRAFTTYPE:
    464 						aneeded |= (1 << ((AircraftTypeClass *)ttype->Members[ctype].Class)->Type);
    465 						break;
    466 				}
    467 			}
    468 
    469 			/*
    470 			**	If this team can use the types required, then consider it a possible
    471 			**	team type to create.
    472 			*/
    473 			int value = 0;
    474 			if ((aneeded & atypes) != 0 || (ineeded & itypes) != 0 || (uneeded & utypes) != 0 || (vneeded & vtypes) != 0) {
    475 				value = ttype->RecruitPriority;
    476 			} else {
    477 				value = ttype->RecruitPriority/2;
    478 			}
    479 
    480 			if (best == NULL || bestvalue < value) {
    481 				bestvalue = value;
    482 				best = ttype;
    483 			}
    484 #endif
    485 		}
    486 	}
    487 
    488 	if (choicecount > 0) {
    489 		return(choices[Random_Pick(0, choicecount-1)]);
    490 	}
    491 	return(NULL);
    492 
    493 //	return(best);
    494 }
    495 
    496 
    497 /***********************************************************************************************
    498  * TeamTypeClass::From_Name -- Converts a name into a team type pointer.                       *
    499  *                                                                                             *
    500  *    This routine is used to convert an ASCII name of a team type into the corresponding      *
    501  *    team type pointer.                                                                       *
    502  *                                                                                             *
    503  * INPUT:   name  -- Pointer to the ASCII name of the team type.                               *
    504  *                                                                                             *
    505  * OUTPUT:  Returns with a pointer to the team type that this ASCII name represents. If there  *
    506  *          is no match, the NULL is returned.                                                 *
    507  *                                                                                             *
    508  * WARNINGS:   none                                                                            *
    509  *                                                                                             *
    510  * HISTORY:                                                                                    *
    511  *   01/26/1996 JLB : Created.                                                                 *
    512  *=============================================================================================*/
    513 TeamTypeClass * TeamTypeClass::From_Name(char const * name)
    514 {
    515 	if (name) {
    516 		for (int index = 0; index < TeamTypes.Count(); index++) {
    517 			if (stricmp(name, TeamTypes.Ptr(index)->IniName) == 0) {
    518 				return(TeamTypes.Ptr(index));
    519 			}
    520 		}
    521 	}
    522 	return(0);
    523 }
    524 
    525 
    526 /***********************************************************************************************
    527  * TeamMission_Needs -- Determines what extra data is needed by team mission.                  *
    528  *                                                                                             *
    529  *    This routine will return the required extra data that the specified team mission will    *
    530  *    need.                                                                                    *
    531  *                                                                                             *
    532  * INPUT:   tmtype   -- The team mission type to check.                                        *
    533  *                                                                                             *
    534  * OUTPUT:  Returns with the data type needed for this team mission.                           *
    535  *                                                                                             *
    536  * WARNINGS:   none                                                                            *
    537  *                                                                                             *
    538  * HISTORY:                                                                                    *
    539  *   01/26/1996 JLB : Created.                                                                 *
    540  *=============================================================================================*/
    541 NeedType TeamMission_Needs(TeamMissionType tmtype)
    542 {
    543 	switch (tmtype) {
    544 		/*
    545 		**	Requires a formation type.
    546 		*/
    547 		case TMISSION_FORMATION:
    548 			return(NEED_FORMATION);
    549 
    550 		/*
    551 		**	Team mission requires a target quarry value.
    552 		*/
    553 		case TMISSION_ATTACK:
    554 			return(NEED_QUARRY);
    555 
    556 		/*
    557 		**	Team mission requires a data value.
    558 		*/
    559 		case TMISSION_MOVECELL:
    560 			return(NEED_HEX_NUMBER);
    561 
    562 		case TMISSION_SET_GLOBAL:
    563 		case TMISSION_GUARD:
    564 		case TMISSION_LOOP:
    565 			return(NEED_NUMBER);
    566 
    567 		/*
    568 		**	Team mission requires a waypoint.
    569 		*/
    570 		case TMISSION_PATROL:
    571 		case TMISSION_MOVE:
    572 		case TMISSION_ATT_WAYPT:
    573 		case TMISSION_SPY:
    574 			return(NEED_WAYPOINT);
    575 
    576 		/*
    577 		**	Team mission requires a general mission type.
    578 		*/
    579 		case TMISSION_DO:
    580 			return(NEED_MISSION);
    581 
    582 		default:
    583 			break;
    584 	}
    585 	return(NEED_NONE);
    586 }
    587 
    588 
    589 #ifdef SCENARIO_EDITOR
    590 /***********************************************************************************************
    591  * TeamMissionClass::Draw_It -- Draws a team mission list box entry.                           *
    592  *                                                                                             *
    593  *    This routine will display a team mission list box entry. It converts the index number    *
    594  *    into the appropriate text string and then displays the text at the coordinates           *
    595  *    specified.                                                                               *
    596  *                                                                                             *
    597  * INPUT:   index    -- The index number to use when rendering the team mission.               *
    598  *                                                                                             *
    599  *          x,y      -- The X,Y coordinate to use when drawing the team mission entry.         *
    600  *                                                                                             *
    601  *          width, height  -- The dimensions of the area that the description can be           *
    602  *                            rendered into.                                                   *
    603  *                                                                                             *
    604  *          selected -- Is this entry currently selected? If so, then it should be rendered    *
    605  *                      differently.                                                           *
    606  *                                                                                             *
    607  *          flags    -- Text print control flags used for when the text is printed.            *
    608  *                                                                                             *
    609  * OUTPUT:  none                                                                               *
    610  *                                                                                             *
    611  * WARNINGS:   none                                                                            *
    612  *                                                                                             *
    613  * HISTORY:                                                                                    *
    614  *   01/05/1996 JLB : Created.                                                                 *
    615  *=============================================================================================*/
    616 void TeamMissionClass::Draw_It(int index, int x, int y, int width, int height, bool selected, TextPrintType flags)
    617 {
    618 	RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
    619 	static int _tabs[] = {13,40};
    620 	if ((flags & 0x0F) == TPF_6PT_GRAD || (flags & 0x0F) == TPF_EFNT) {
    621 
    622 		if (selected) {
    623 			flags = flags | TPF_BRIGHT_COLOR;
    624 			LogicPage->Fill_Rect(x, y, x + width - 1, y + height - 1,
    625 				scheme->Shadow);
    626 		} else {
    627 			if (!(flags & TPF_USE_GRAD_PAL)) {
    628 				flags = flags | TPF_MEDIUM_COLOR;
    629 			}
    630 		}
    631 
    632 		Conquer_Clip_Text_Print(Description(index), x, y, scheme, TBLACK, flags, width, _tabs);
    633 	} else {
    634 		Conquer_Clip_Text_Print(Description(index), x, y,
    635 			(selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, flags, width, _tabs);
    636 	}
    637 }
    638 
    639 
    640 /***********************************************************************************************
    641  * TeamTypeClass::Edit -- Edit the team type.                                                  *
    642  *                                                                                             *
    643  *    This routine handles the editing dialog box for the team type.                           *
    644  *                                                                                             *
    645  * INPUT:   none                                                                               *
    646  *                                                                                             *
    647  * OUTPUT:  Was the team type edited? A FALSE indicates that the dialog was canceled.          *
    648  *                                                                                             *
    649  * WARNINGS:   none                                                                            *
    650  *                                                                                             *
    651  * HISTORY:                                                                                    *
    652  *   01/05/1996 JLB : Created.                                                                 *
    653  *=============================================================================================*/
    654 bool TeamTypeClass::Edit(void)
    655 {
    656 	/*
    657 	**	Dialog & button dimensions
    658 	*/
    659 	enum {
    660 		D_DIALOG_W = 400,
    661 		D_DIALOG_H = 250,
    662 		D_DIALOG_X = 0,
    663 		D_DIALOG_Y = 0,
    664 
    665 		D_NAME_X=D_DIALOG_X+35,
    666 		D_NAME_Y=D_DIALOG_Y+27,
    667 		ED_WIDTH=40,
    668 
    669 		D_CHECK_X=D_DIALOG_X+35,							// Start of check box attribute list.
    670 		D_CHECK_Y=D_NAME_Y+25,
    671 
    672 		CB_SPACING_Y=9,										// Vertical spacing between check box lines.
    673 		CB_SPACING_X=8,										// Horizontal spacing for check box description text.
    674 		D_SPACING_X=9,											// Horizontal spacing between data entry fields.
    675 
    676 		D_CANCEL_W = 50,
    677 		D_CANCEL_H = 9,
    678 		D_CANCEL_X = D_DIALOG_X + D_DIALOG_W - (D_CANCEL_W+35),
    679 		D_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - (D_CANCEL_H+20),
    680 
    681 		D_OK_W = 50,
    682 		D_OK_H = 9,
    683 		D_OK_X = D_DIALOG_X + D_DIALOG_W - (D_OK_W+18)*2,
    684 		D_OK_Y = D_CANCEL_Y
    685 	};
    686 
    687 	/*
    688 	**	Button enumerations:
    689 	*/
    690 	enum {
    691 		BUTTON_NAME=100,
    692 		BUTTON_RECRUIT,
    693 		BUTTON_MAXNUM,
    694 		BUTTON_INITNUM,
    695 		BUTTON_HOUSE,
    696 		BUTTON_ROUNDABOUT,
    697 		BUTTON_LEARNING,
    698 		BUTTON_SUICIDE,
    699 		BUTTON_AUTO,
    700 		BUTTON_PREBUILT,
    701 		BUTTON_REINFORCE,
    702 		BUTTON_MISSION1,
    703 		BUTTON_MISSION2,
    704 		BUTTON_ADD,
    705 		BUTTON_INSERT,
    706 		BUTTON_DELETE,
    707 		BUTTON_REPLACE,
    708 		BUTTON_ARG,
    709 		BUTTON_FORMATION,
    710 		BUTTON_MEMBERS,
    711 		BUTTON_MISSION,
    712 		BUTTON_TRIGGER,
    713 		BUTTON_ORIGIN,
    714 		BUTTON_OK,
    715 		BUTTON_CANCEL,
    716 		BUTTON_QUARRY,
    717 	};
    718 
    719 	/*
    720 	**	Dialog variables:
    721 	*/
    722 	ControlClass * commands = 0;
    723 	RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
    724 
    725 	/*
    726 	**	Team name edit field.
    727 	*/
    728 	char name_buf[10];
    729 	EditClass name_edt(BUTTON_NAME, name_buf, sizeof(name_buf),
    730 		TPF_EFNT | TPF_NOSHADOW,
    731 		D_NAME_X, D_NAME_Y, ED_WIDTH, 9, EditClass::ALPHANUMERIC);
    732 	strcpy(name_buf, IniName);
    733 	commands = &name_edt;
    734 
    735 	/*
    736 	**	House ownership of this team.
    737 	*/
    738 	char housetext[25] = "";
    739 	DropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext),
    740 		TPF_EFNT | TPF_NOSHADOW,
    741 		name_edt.X+name_edt.Width+D_SPACING_X, name_edt.Y, 55, 8*5,
    742 		MFCD::Retrieve("EBTN-UP.SHP"),
    743 		MFCD::Retrieve("EBTN-DN.SHP"));
    744 	for (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
    745 		housebtn.Add_Item(HouseTypeClass::As_Reference(house).IniName);
    746 	}
    747 	if (House == HOUSE_NONE) House = HOUSE_GOOD;
    748 	housebtn.Set_Selected_Index(House);
    749 	housebtn.Add(*commands);
    750 
    751 	/*
    752 	**	Recruit priority for this team.
    753 	*/
    754 	char recr_buf[4];
    755 	EditClass recr_edt(BUTTON_RECRUIT, recr_buf, sizeof(recr_buf),
    756 		TPF_EFNT | TPF_NOSHADOW,
    757 		housebtn.X+housebtn.Width+5+D_SPACING_X, housebtn.Y, ED_WIDTH, 9, EditClass::NUMERIC);
    758 	sprintf(recr_buf, "%d", RecruitPriority);
    759 	recr_edt.Add(*commands);
    760 
    761 	/*
    762 	**	Maximum allowed for this team type.
    763 	*/
    764 	char maxnum_buf[4];
    765 	EditClass maxnum_edt(BUTTON_MAXNUM, maxnum_buf, sizeof(maxnum_buf),
    766 		TPF_EFNT | TPF_NOSHADOW,
    767 		recr_edt.X+recr_edt.Width+D_SPACING_X, recr_edt.Y, ED_WIDTH, 9, EditClass::NUMERIC);
    768 	sprintf(maxnum_buf, "%d", MaxAllowed);
    769 	maxnum_edt.Add(*commands);
    770 
    771 	/*
    772 	**	Initial number for this team type.
    773 	*/
    774 	char initnum_buf[4];
    775 	EditClass initnum_edt(BUTTON_INITNUM, initnum_buf, sizeof(initnum_buf),
    776 		TPF_EFNT | TPF_NOSHADOW,
    777 		maxnum_edt.X+maxnum_edt.Width+D_SPACING_X, maxnum_edt.Y, ED_WIDTH, 9, EditClass::NUMERIC);
    778 	sprintf(initnum_buf, "%d", InitNum);
    779 	initnum_edt.Add(*commands);
    780 
    781 	/*
    782 	**	Waypoint preference to create/reinforce this team.
    783 	*/
    784 	char origin[4];
    785 	EditClass originbtn(BUTTON_ORIGIN, origin, sizeof(origin),
    786 		TPF_EFNT | TPF_NOSHADOW,
    787 		initnum_edt.X+initnum_edt.Width+D_SPACING_X, initnum_edt.Y, 20, 9, EditClass::ALPHA);
    788 	*originbtn.Get_Text() = '\0';
    789 	if (Origin != -1) {
    790 		if (Origin < 26) {
    791 			sprintf(originbtn.Get_Text(), "%c", Origin + 'A');
    792 		} else {
    793 			sprintf(originbtn.Get_Text(), "%c%c", (Origin/26) + 'A'-1, Origin % 26 + 'A');
    794 		}
    795 	}
    796 	originbtn.Add(*commands);
    797 
    798 	/*
    799 	**	Members of this team control button.
    800 	*/
    801 	TextButtonClass membersbtn(BUTTON_MEMBERS, "Members", TPF_EBUTTON, name_edt.X, name_edt.Y+12, 50);
    802 	membersbtn.Add(*commands);
    803 
    804 	/*
    805 	**	Trigger to assign to each member of this team (when object joins team).
    806 	*/
    807 	char trigtext[25] = "";
    808 	DropListClass triggerbtn(BUTTON_TRIGGER, trigtext, sizeof(trigtext),
    809 		TPF_EFNT | TPF_NOSHADOW,
    810 		D_DIALOG_X+D_DIALOG_W-95, membersbtn.Y, 60, 8*5,
    811 		MFCD::Retrieve("EBTN-UP.SHP"),
    812 		MFCD::Retrieve("EBTN-DN.SHP"));
    813 	triggerbtn.Add_Item("<NONE>");
    814 	for (int index = 0; index < TriggerTypes.Count(); index++) {
    815 		triggerbtn.Add_Item(TriggerTypes.Ptr(index)->IniName);
    816 	}
    817 	if (Trigger.Is_Valid()) {
    818 		triggerbtn.Set_Selected_Index(Trigger->Name());
    819 	} else {
    820 		triggerbtn.Set_Selected_Index(0);
    821 	}
    822 	triggerbtn.Add(*commands);
    823 
    824 	/*
    825 	**	Roundabout travel logic attribute for this team.
    826 	*/
    827 	CheckBoxClass roundbtn(BUTTON_ROUNDABOUT, D_CHECK_X, D_CHECK_Y);
    828 	if (IsRoundAbout) {
    829 		roundbtn.Turn_On();
    830 	} else {
    831 		roundbtn.Turn_Off();
    832 	}
    833 	roundbtn.Add(*commands);
    834 
    835 	/*
    836 	**	Suicide travel to target attribute.
    837 	*/
    838 	CheckBoxClass suicidebtn(BUTTON_SUICIDE, D_CHECK_X, roundbtn.Y+CB_SPACING_Y);
    839 	if (IsSuicide) {
    840 		suicidebtn.Turn_On();
    841 	} else {
    842 		suicidebtn.Turn_Off();
    843 	}
    844 	suicidebtn.Add(*commands);
    845 
    846 	/*
    847 	**	Autocreate attribute for this team.
    848 	*/
    849 	CheckBoxClass autocreatebtn(BUTTON_AUTO, D_CHECK_X, suicidebtn.Y+CB_SPACING_Y);
    850 	if (IsAutocreate) {
    851 		autocreatebtn.Turn_On();
    852 	} else {
    853 		autocreatebtn.Turn_Off();
    854 	}
    855 	autocreatebtn.Add(*commands);
    856 
    857 	/*
    858 	**	Prebuild team members attribute for this team.
    859 	*/
    860 	CheckBoxClass prebuildbtn(BUTTON_PREBUILT, D_CHECK_X, autocreatebtn.Y+CB_SPACING_Y);
    861 	if (IsPrebuilt) {
    862 		prebuildbtn.Turn_On();
    863 	} else {
    864 		prebuildbtn.Turn_Off();
    865 	}
    866 	prebuildbtn.Add(*commands);
    867 
    868 	/*
    869 	**	Reinforce this team in progress attribute.
    870 	*/
    871 	CheckBoxClass reinforcebtn(BUTTON_REINFORCE, D_CHECK_X, prebuildbtn.Y+CB_SPACING_Y);
    872 	if (IsReinforcable) {
    873 		reinforcebtn.Turn_On();
    874 	} else {
    875 		reinforcebtn.Turn_Off();
    876 	}
    877 	reinforcebtn.Add(*commands);
    878 
    879 	/*
    880 	**	Create drop box of possible team missions. This is used when building/editing the
    881 	**	team mission list.
    882 	*/
    883 	char droptext[45];
    884 	DropListClass missionlist1(BUTTON_MISSION1, droptext, sizeof(droptext),
    885 		TPF_EFNT | TPF_NOSHADOW,
    886 		reinforcebtn.X, reinforcebtn.Y+15, 170, 8*8,
    887 		MFCD::Retrieve("EBTN-UP.SHP"),
    888 		MFCD::Retrieve("EBTN-DN.SHP"));
    889 	for (TeamMissionType tm = TMISSION_FIRST; tm < TMISSION_COUNT; tm++) {
    890 		missionlist1.Add_Item(TeamTypeClass::Name_From_Mission(tm));
    891 	}
    892 	missionlist1.Set_Selected_Index(0);
    893 	missionlist1.Add_Tail(*commands);
    894 
    895 	/*
    896 	**	Optional mission argument entry field.
    897 	*/
    898 	char arg_buf[6] = {0};
    899 	EditClass arg_edt(BUTTON_ARG, arg_buf, sizeof(arg_buf),
    900 		TPF_EFNT | TPF_NOSHADOW,
    901 		missionlist1.X + missionlist1.Width + 15, missionlist1.Y, 60, -1, EditClass::ALPHANUMERIC);
    902 //	arg_edt.Add(*commands);
    903 
    904 	char qtext[55];
    905 	DropListClass qlist(BUTTON_QUARRY, qtext, sizeof(qtext),
    906 		TPF_EFNT | TPF_NOSHADOW,
    907 		missionlist1.X + missionlist1.Width + 15, missionlist1.Y, 100, 5*8,
    908 		MFCD::Retrieve("EBTN-UP.SHP"),
    909 		MFCD::Retrieve("EBTN-DN.SHP"));
    910 	for (QuarryType q = QUARRY_FIRST; q < QUARRY_COUNT; q++) {
    911 		qlist.Add_Item(QuarryName[q]);
    912 	}
    913 	qlist.Set_Selected_Index(0);
    914 	qlist.Add_Tail(*commands);
    915 
    916 	char ftext[55];
    917 	DropListClass flist(BUTTON_FORMATION, ftext, sizeof(ftext),
    918 		TPF_EFNT | TPF_NOSHADOW,
    919 		missionlist1.X + missionlist1.Width + 15, missionlist1.Y, 100, 5*8,
    920 		MFCD::Retrieve("EBTN-UP.SHP"),
    921 		MFCD::Retrieve("EBTN-DN.SHP"));
    922 	for (FormationType f = FORMATION_FIRST; f < FORMATION_COUNT; f++) {
    923 		flist.Add_Item(FormationName[f]);
    924 	}
    925 	flist.Set_Selected_Index(0);
    926 	flist.Add_Tail(*commands);
    927 
    928 	char mtext[55];
    929 	DropListClass mlist(BUTTON_MISSION, mtext, sizeof(mtext),
    930 		TPF_EFNT | TPF_NOSHADOW,
    931 		missionlist1.X + missionlist1.Width + 15, missionlist1.Y, 100, 5*8,
    932 		MFCD::Retrieve("EBTN-UP.SHP"),
    933 		MFCD::Retrieve("EBTN-DN.SHP"));
    934 	for (MissionType m = MISSION_FIRST; m < MISSION_COUNT; m++) {
    935 		mlist.Add_Item(MissionClass::Mission_Name(m));
    936 	}
    937 	mlist.Set_Selected_Index(0);
    938 	mlist.Add_Tail(*commands);
    939 
    940 	TListClass<TeamMissionClass *> missionlist2(BUTTON_MISSION2, missionlist1.X+60, missionlist1.Y+22, 240, 8*7,
    941 		TPF_EFNT | TPF_NOSHADOW,
    942 		MFCD::Retrieve("EBTN-UP.SHP"),
    943 		MFCD::Retrieve("EBTN-DN.SHP"));
    944 	for (index = 0; index < MissionCount; index++) {
    945 		missionlist2.Add_Item(new TeamMissionClass(MissionList[index]));
    946 //		missionlist2.Add_Item(&TeamMissions[MissionList[index].Mission]);
    947 	}
    948 	static int tabs[] = {13, 40};		// list box tab stops
    949 	missionlist2.Set_Tabs(tabs);
    950 	missionlist2.Add_Tail(*commands);
    951 
    952 	/*
    953 	**	Mission editing command buttons.
    954 	*/
    955 	TextButtonClass addbtn(BUTTON_ADD, "Append", TPF_EBUTTON, D_NAME_X, missionlist1.Y+missionlist1.Height+1, 50);
    956 	addbtn.Add(*commands);
    957 
    958 	TextButtonClass insertbtn(BUTTON_INSERT, "Insert", TPF_EBUTTON, addbtn.X, addbtn.Y+10, 50);
    959 	insertbtn.Add(*commands);
    960 
    961 	TextButtonClass delbtn(BUTTON_DELETE, "Delete", TPF_EBUTTON, insertbtn.X, insertbtn.Y+10, 50);
    962 	delbtn.Add(*commands);
    963 
    964 	TextButtonClass repbtn(BUTTON_REPLACE, "Replace", TPF_EBUTTON, delbtn.X, delbtn.Y+10, 50);
    965 	repbtn.Add(*commands);
    966 
    967 
    968 	TextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);
    969 	TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);
    970 
    971 	/*
    972 	**	Initialize
    973 	*/
    974 	Set_Logic_Page(SeenBuff);
    975 
    976 	/*
    977 	**	Create the list
    978 	*/
    979 	okbtn.Add(*commands);
    980 	cancelbtn.Add_Tail(*commands);
    981 
    982 	/*
    983 	**	Main Processing Loop
    984 	*/
    985 	int lastindex = -1;
    986 	int lastcount = -1;
    987 	int lastbutton = -1;
    988 	bool cancel = false;
    989 	bool display = true;
    990 	bool process = true;
    991 	while (process) {
    992 
    993 		/*
    994 		**	Invoke game callback
    995 		*/
    996 		Call_Back();
    997 
    998 		/*
    999 		**	Refresh display if needed
   1000 		*/
   1001 		if (display) {
   1002 
   1003 			/*
   1004 			**	Add the optional data entry field as necessary.
   1005 			*/
   1006 			arg_edt.Remove();
   1007 			qlist.Remove();
   1008 			flist.Remove();
   1009 			mlist.Remove();
   1010 			switch (TeamMission_Needs(TeamMissionType(missionlist1.Current_Index()))) {
   1011 				default:
   1012 					break;
   1013 
   1014 				case NEED_MISSION:
   1015 					mlist.Add(*commands);
   1016 					break;
   1017 
   1018 				case NEED_FORMATION:
   1019 					flist.Add(*commands);
   1020 					break;
   1021 
   1022 				case NEED_WAYPOINT:
   1023 				case NEED_NUMBER:
   1024 				case NEED_HEX_NUMBER:
   1025 					arg_edt.Add(*commands);
   1026 					break;
   1027 
   1028 				case NEED_QUARRY:
   1029 					qlist.Add(*commands);
   1030 					break;
   1031 			}
   1032 
   1033 			/*
   1034 			**	Display the dialog box
   1035 			*/
   1036 			Hide_Mouse();
   1037 			Dialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);
   1038 
   1039 			Draw_Caption(TXT_TEAM_EDIT, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);
   1040 
   1041 			/*
   1042 			**	Draw the captions
   1043 			*/
   1044 			Fancy_Text_Print("Name:", name_edt.X, name_edt.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1045 			Fancy_Text_Print("House:", housebtn.X, housebtn.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1046 			Fancy_Text_Print("Pri:", recr_edt.X, recr_edt.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1047 			Fancy_Text_Print("Max:", maxnum_edt.X, maxnum_edt.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1048 			Fancy_Text_Print("Num:", initnum_edt.X, initnum_edt.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1049 			Fancy_Text_Print("Loc:", originbtn.X, originbtn.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1050 			Fancy_Text_Print("#  Team Mission", missionlist2.X, missionlist2.Y-7, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1051 			Fancy_Text_Print("Trigger:", triggerbtn.X-4, triggerbtn.Y+1, scheme, TBLACK, TPF_RIGHT | TPF_EFNT | TPF_NOSHADOW);
   1052 
   1053 			Fancy_Text_Print(Member_Description(), membersbtn.X + membersbtn.Width + 3, membersbtn.Y+1, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1054 
   1055 			Fancy_Text_Print("Use safest, possibly longer, route to target?", roundbtn.X+CB_SPACING_X, roundbtn.Y, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1056 			Fancy_Text_Print("Charge toward target ignoring distractions?", suicidebtn.X+CB_SPACING_X, suicidebtn.Y, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1057 			Fancy_Text_Print("Only 'Autocreate A.I.' uses this team type?", autocreatebtn.X+CB_SPACING_X, autocreatebtn.Y, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1058 			Fancy_Text_Print("Prebuild team members before team is created?", prebuildbtn.X+CB_SPACING_X, prebuildbtn.Y, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1059 			Fancy_Text_Print("Automatically reinforce team whenever possible?", reinforcebtn.X+CB_SPACING_X, reinforcebtn.Y, scheme, TBLACK, TPF_EFNT | TPF_NOSHADOW);
   1060 
   1061 			/*
   1062 			**	Redraw the buttons
   1063 			*/
   1064 			commands->Draw_All();
   1065 			Show_Mouse();
   1066 
   1067 			display = false;
   1068 		}
   1069 
   1070 		/*
   1071 		**	Get user input
   1072 		*/
   1073 		KeyNumType input = commands->Input();
   1074 
   1075 		/*
   1076 		**	Process input
   1077 		*/
   1078 		switch (input) {
   1079 
   1080 			/*
   1081 			**	Select a Mission on the right-hand mission list; update the Argument
   1082 			**	field to reflect the current value. This only serves as an aide to editing
   1083 			**	the team mission list.
   1084 			*/
   1085 			case BUTTON_MISSION2 | KN_BUTTON:
   1086 				if (missionlist2.Count() && lastcount == missionlist2.Count() && lastbutton == BUTTON_MISSION2 && lastindex == missionlist2.Current_Index()) {
   1087 					missionlist1.Set_Selected_Index(missionlist2.Current_Item()->Mission);
   1088 
   1089 					switch (TeamMission_Needs(missionlist2.Current_Item()->Mission)) {
   1090 						case NEED_MISSION:
   1091 							mlist.Set_Selected_Index(missionlist2.Current_Item()->Data.Mission);
   1092 							break;
   1093 
   1094 						case NEED_FORMATION:
   1095 							flist.Set_Selected_Index(missionlist2.Current_Item()->Data.Formation);
   1096 							break;
   1097 
   1098 						case NEED_NUMBER:
   1099 							sprintf(arg_edt.Get_Text(), "%d", missionlist2.Current_Item()->Data.Value);
   1100 							break;
   1101 
   1102 						case NEED_HEX_NUMBER:
   1103 							sprintf(arg_edt.Get_Text(), "%x", missionlist2.Current_Item()->Data.Value);
   1104 							break;
   1105 
   1106 						case NEED_QUARRY:
   1107 							strcpy(qlist.Get_Text(), QuarryName[missionlist2.Current_Item()->Data.Quarry]);
   1108 							break;
   1109 
   1110 						case NEED_WAYPOINT:
   1111 							if (missionlist2.Current_Item()->Data.Value < 26) {
   1112 								sprintf(arg_edt.Get_Text(), "%c", missionlist2.Current_Item()->Data.Value + 'A');
   1113 							} else {
   1114 								sprintf(arg_edt.Get_Text(), "%c%c", (missionlist2.Current_Item()->Data.Value)/26 + 'A'-1, (missionlist2.Current_Item()->Data.Value % 26) + 'A');
   1115 							}
   1116 							break;
   1117 					}
   1118 				}
   1119 				lastindex = missionlist2.Current_Index();
   1120 				lastcount = missionlist2.Count();
   1121 				display = true;
   1122 				break;
   1123 
   1124 			/*
   1125 			**	Add current mission data to current position of team mission list. Any
   1126 			**	subsequent missions get moved downward.
   1127 			*/
   1128 			case BUTTON_INSERT | KN_BUTTON:
   1129 				if (missionlist2.Count() < MAX_TEAM_MISSIONS) {
   1130 					TeamMissionClass * tm = new TeamMissionClass;
   1131 					tm->Mission = TeamMissionType(missionlist1.Current_Index());
   1132 					tm->Data.Value = 0;
   1133 					switch (TeamMission_Needs(tm->Mission)) {
   1134 						case NEED_MISSION:
   1135 							tm->Data.Mission = MissionType(mlist.Current_Index());
   1136 							break;
   1137 
   1138 						case NEED_FORMATION:
   1139 							tm->Data.Formation = FormationType(flist.Current_Index());
   1140 							break;
   1141 
   1142 						case NEED_QUARRY:
   1143 							tm->Data.Quarry = QuarryType(qlist.Current_Index());
   1144 							break;
   1145 
   1146 						case NEED_NUMBER:
   1147 							tm->Data.Value = atoi(arg_edt.Get_Text());
   1148 							break;
   1149 
   1150 						case NEED_HEX_NUMBER:
   1151 							tm->Data.Value = atoh(arg_edt.Get_Text());
   1152 							break;
   1153 
   1154 						case NEED_WAYPOINT:
   1155 							tm->Data.Value = toupper(*arg_edt.Get_Text()) - 'A';
   1156 							if ( *((arg_edt.Get_Text())+1)) {
   1157 								tm->Data.Value = (tm->Data.Value+1)*26;
   1158 								tm->Data.Value += toupper(*((arg_edt.Get_Text())+1)) - 'A';;
   1159 							}
   1160 							if ((unsigned)tm->Data.Value >= WAYPT_HOME) {
   1161 								tm->Data.Value = 0;
   1162 							}
   1163 							break;
   1164 
   1165 						default:
   1166 							tm->Data.Value = 0;
   1167 							break;
   1168 					}
   1169 					missionlist2.Insert_Item(tm);
   1170 				}
   1171 				display = true;
   1172 				break;
   1173 
   1174 			/*
   1175 			**	Add mission data to the end of the mission list.
   1176 			*/
   1177 			case BUTTON_ADD | KN_BUTTON:
   1178 				if (missionlist2.Count() < MAX_TEAM_MISSIONS) {
   1179 					TeamMissionClass * tm = new TeamMissionClass;
   1180 					tm->Mission = TeamMissionType(missionlist1.Current_Index());
   1181 					tm->Data.Value = 0;
   1182 					switch (TeamMission_Needs(tm->Mission)) {
   1183 						case NEED_MISSION:
   1184 							tm->Data.Mission = MissionType(mlist.Current_Index());
   1185 							break;
   1186 
   1187 						case NEED_FORMATION:
   1188 							tm->Data.Formation = FormationType(flist.Current_Index());
   1189 							break;
   1190 
   1191 						case NEED_QUARRY:
   1192 							tm->Data.Quarry = QuarryType(qlist.Current_Index());
   1193 							break;
   1194 
   1195 						case NEED_NUMBER:
   1196 							tm->Data.Value = atoi(arg_edt.Get_Text());
   1197 							break;
   1198 
   1199 						case NEED_HEX_NUMBER:
   1200 							tm->Data.Value = atoh(arg_edt.Get_Text());
   1201 							break;
   1202 
   1203 						case NEED_WAYPOINT:
   1204 							tm->Data.Value = toupper(*arg_edt.Get_Text()) - 'A';;
   1205 							if ( *((arg_edt.Get_Text())+1)) {
   1206 								tm->Data.Value = (tm->Data.Value+1)*26;
   1207 								tm->Data.Value += toupper(*((arg_edt.Get_Text())+1)) - 'A';;
   1208 							}
   1209 							if ((unsigned)tm->Data.Value >= WAYPT_HOME) {
   1210 								tm->Data.Value = 0;
   1211 							}
   1212 							break;
   1213 
   1214 						default:
   1215 							tm->Data.Value = 0;
   1216 							break;
   1217 					}
   1218 					missionlist2.Add_Item(tm);
   1219 					display = true;
   1220 				}
   1221 				break;
   1222 
   1223 			/*
   1224 			**	Replace the currently selected mission with the work mission data.
   1225 			*/
   1226 			case BUTTON_REPLACE | KN_BUTTON:
   1227 				if (missionlist2.Count()) {
   1228 					TeamMissionClass * tm = missionlist2.Current_Item();
   1229 					tm->Mission = TeamMissionType(missionlist1.Current_Index());
   1230 					tm->Data.Value = 0;
   1231 					switch (TeamMission_Needs(tm->Mission)) {
   1232 						case NEED_MISSION:
   1233 							tm->Data.Mission = MissionType(mlist.Current_Index());
   1234 							break;
   1235 
   1236 						case NEED_FORMATION:
   1237 							tm->Data.Formation = FormationType(flist.Current_Index());
   1238 							break;
   1239 
   1240 						case NEED_QUARRY:
   1241 							tm->Data.Quarry = QuarryType(qlist.Current_Index());
   1242 							break;
   1243 
   1244 						case NEED_NUMBER:
   1245 							tm->Data.Value = atoi(arg_edt.Get_Text());
   1246 							break;
   1247 
   1248 						case NEED_HEX_NUMBER:
   1249 							tm->Data.Value = atoh(arg_edt.Get_Text());
   1250 							break;
   1251 
   1252 						case NEED_WAYPOINT:
   1253 							tm->Data.Value = toupper(*arg_edt.Get_Text()) - 'A';
   1254 							if ( *((arg_edt.Get_Text())+1)) {
   1255 								tm->Data.Value = (tm->Data.Value+1)*26;
   1256 								tm->Data.Value += toupper(*((arg_edt.Get_Text())+1)) - 'A';
   1257 							}
   1258 							if ((unsigned)tm->Data.Value >= WAYPT_HOME) {
   1259 								tm->Data.Value = 0;
   1260 							}
   1261 							break;
   1262 
   1263 						default:
   1264 							tm->Data.Value = 0;
   1265 							break;
   1266 					}
   1267 					missionlist2[missionlist2.Current_Index()] = tm;
   1268 				}
   1269 				display = true;
   1270 				break;
   1271 
   1272 			/*
   1273 			**	Delete the currently selected mission.
   1274 			*/
   1275 			case BUTTON_DELETE | KN_BUTTON:
   1276 				if (missionlist2.Count()) {
   1277 					TeamMissionClass * tm = missionlist2.Current_Item();
   1278 					missionlist2.Remove_Index(missionlist2.Current_Index());
   1279 					delete tm;
   1280 				}
   1281 				display = true;
   1282 				break;
   1283 
   1284 			/*
   1285 			**	Invoke the members dialog
   1286 			*/
   1287 			case BUTTON_MEMBERS | KN_BUTTON:
   1288 
   1289 				/*
   1290 				**	Take editor focus away
   1291 				*/
   1292 				membersbtn.Turn_Off();
   1293 
   1294 				/*
   1295 				**	Invoke the dialog
   1296 				*/
   1297 				Map.Team_Members(HousesType(housebtn.Current_Index()));
   1298 
   1299 				/*
   1300 				**	Redraw
   1301 				*/
   1302 				display = true;
   1303 				break;
   1304 
   1305 			/*
   1306 			**	When the OK button is selected, lift the values from the dialog box
   1307 			**	and place them into the team type object.
   1308 			*/
   1309 			case BUTTON_OK | KN_BUTTON:
   1310 				strtrim(name_edt.Get_Text());
   1311 				if (strlen(name_edt.Get_Text()) != 0) {
   1312 					strcpy(IniName, name_edt.Get_Text());
   1313 				} else {
   1314 					strcpy(IniName, "----");
   1315 				}
   1316 
   1317 				IsRoundAbout = roundbtn.IsOn;
   1318 				IsSuicide = suicidebtn.IsOn;
   1319 				IsAutocreate = autocreatebtn.IsOn;
   1320 				IsPrebuilt = prebuildbtn.IsOn;
   1321 				IsReinforcable = reinforcebtn.IsOn;
   1322 
   1323 				RecruitPriority = atoi(recr_edt.Get_Text());
   1324 				InitNum = atoi(initnum_edt.Get_Text());
   1325 				MaxAllowed = atoi(maxnum_edt.Get_Text());
   1326 				House = HousesType(housebtn.Current_Index());
   1327 				Trigger = NULL;
   1328 				if (triggerbtn.Current_Index() > 0) {
   1329 					Trigger = TriggerTypes.Ptr(triggerbtn.Current_Index()-1);
   1330 				}
   1331 
   1332 				MissionCount = missionlist2.Count();
   1333 				for (index = 0; index < MissionCount; index++) {
   1334 					MissionList[index].Data.Value = 0;				// Clears extra bits.
   1335 					MissionList[index] = *missionlist2[index];
   1336 				}
   1337 
   1338 #ifdef TOFIX
   1339 // the mission class objects pointed to in the list should be deleted?
   1340 #endif
   1341 
   1342 				if (strlen(originbtn.Get_Text())) {
   1343 					if (strlen(originbtn.Get_Text()) == 1) {
   1344 						Origin = toupper(*originbtn.Get_Text()) - 'A';
   1345 					} else {
   1346 						Origin = (toupper(*originbtn.Get_Text())+1 - 'A' ) * 26;
   1347 						Origin += toupper(*(originbtn.Get_Text()+1)) - 'A';
   1348 					}
   1349 				} else {
   1350 					Origin = -1;
   1351 				}
   1352 				cancel = false;
   1353 				process = false;
   1354 				break;
   1355 
   1356 			/*
   1357 			**	Cancel: return
   1358 			*/
   1359 			case BUTTON_CANCEL | KN_BUTTON:
   1360 				cancel = true;
   1361 				process = false;
   1362 				break;
   1363 
   1364 			/*
   1365 			**	Unrecognized events are ignored. If any button related event is
   1366 			**	detected, then collapse any drop down list boxes. This keeps the
   1367 			**	dialog box clean.
   1368 			*/
   1369 			default:
   1370 				if (input & KN_BUTTON) {
   1371 					housebtn.Collapse();
   1372 					missionlist1.Collapse();
   1373 					triggerbtn.Collapse();
   1374 					display = true;
   1375 				}
   1376 				break;
   1377 		}
   1378 
   1379 		/*
   1380 		**	Record the last dialog control touched so that a double click
   1381 		**	can be detected.
   1382 		*/
   1383 		if (input & KN_BUTTON) {
   1384 			lastbutton = (input & ~KN_BUTTON);
   1385 		}
   1386 	}
   1387 
   1388 	return(!cancel);
   1389 }
   1390 
   1391 
   1392 int atoh(char * str)
   1393 {
   1394 	int retval = 0;
   1395 	while (*str) {
   1396 		retval *= 16;
   1397 		if (*str >= '0' && *str <= '9') {
   1398 			retval += *str-'0';
   1399 		} else {
   1400 			if (*str >= 'a' && *str <= 'f') {
   1401 				retval += 10 + (*str - 'a');
   1402 			} else {
   1403 				if (*str >= 'A' && *str <= 'F') {
   1404 					retval += 10 + (*str - 'A');
   1405 				}
   1406 			}
   1407 		}
   1408 		str++;
   1409 	}
   1410 	return(retval);
   1411 }
   1412 
   1413 #endif
   1414 
   1415 
   1416 #if defined(CHEAT_KEYS) || defined(SCENARIO_EDITOR)
   1417 /***********************************************************************************************
   1418  * TeamTypeClass::Member_Description -- Builds a member description string.                    *
   1419  *                                                                                             *
   1420  *    This routine will build a team member description string. The string will be composed    *
   1421  *    of the team member type and quantity. As many team member types will be listed that      *
   1422  *    can fit within a reasonable size.                                                        *
   1423  *                                                                                             *
   1424  * INPUT:   none                                                                               *
   1425  *                                                                                             *
   1426  * OUTPUT:  Returns with a pointer to the text string that contains a description of the team  *
   1427  *          type members.                                                                      *
   1428  *                                                                                             *
   1429  * WARNINGS:   The return string may be truncated if necessary to fit within reasonable size   *
   1430  *             limits.                                                                         *
   1431  *                                                                                             *
   1432  * HISTORY:                                                                                    *
   1433  *   01/05/1996 JLB : Created.                                                                 *
   1434  *=============================================================================================*/
   1435 char const * TeamTypeClass::Member_Description(void) const
   1436 {
   1437 	static char buffer[128];
   1438 
   1439 	buffer[0] = '\0';
   1440 
   1441 	/*
   1442 	**	Fill in class & count for all classes
   1443 	*/
   1444 	for (int index = 0; index < ClassCount; index++) {
   1445 		char txt[10];
   1446 
   1447 		strcat(buffer, Members[index].Class->IniName);
   1448 		strcat(buffer, ":");
   1449 
   1450 		sprintf(txt, "%d", Members[index].Quantity);
   1451 		strcat(buffer, txt);
   1452 
   1453 		if (index < ClassCount-1) {
   1454 			strcat(buffer, ",");
   1455 		}
   1456 	}
   1457 
   1458 	if (strlen(buffer) > 25) {
   1459 		strcpy(&buffer[25-3], "...");
   1460 	}
   1461 
   1462 	return(buffer);
   1463 }
   1464 
   1465 
   1466 /***********************************************************************************************
   1467  * TeamTypeClass::Description -- Builds a description of the team.                             *
   1468  *                                                                                             *
   1469  *    This routine will build a brief description of the team type. This description is used   *
   1470  *    in the team type list.                                                                   *
   1471  *                                                                                             *
   1472  * INPUT:   none                                                                               *
   1473  *                                                                                             *
   1474  * OUTPUT:  Returns with the composed text string that represents the team type.               *
   1475  *                                                                                             *
   1476  * WARNINGS:   none                                                                            *
   1477  *                                                                                             *
   1478  * HISTORY:                                                                                    *
   1479  *   01/05/1996 JLB : Created.                                                                 *
   1480  *=============================================================================================*/
   1481 char const * TeamTypeClass::Description(void) const
   1482 {
   1483 	static char _buffer[128];
   1484 	char extra = ' ';
   1485 	char loc[3];
   1486 
   1487 	loc[0] = loc[1] = loc[2] = 0;
   1488 	if (IsAutocreate) extra = '*';
   1489 	if (Origin > -1) {
   1490 //	if (Origin != -1) {
   1491 		if (Origin < 26) {
   1492 			loc[0] = 'A' + Origin;
   1493 		} else {
   1494 			loc[0] = Origin / 26 + 'A'-1;
   1495 			loc[1] = Origin % 26 + 'A';
   1496 		}
   1497 	}
   1498 
   1499 	sprintf(_buffer, "%s\t%s\t%c%s\t%d\t%s", IniName, HouseTypeClass::As_Reference(House).Suffix, extra, loc, MissionCount, Member_Description());
   1500 	return(_buffer);
   1501 }
   1502 
   1503 
   1504 /***********************************************************************************************
   1505  * TeamMissionClass::Description -- Compose a text description of team mission.                *
   1506  *                                                                                             *
   1507  *    This routine will create a text representation of a team mission. This description will  *
   1508  *    be used in the list of team missions for display purposes.                               *
   1509  *                                                                                             *
   1510  * INPUT:   index -- The index to assign to this team. The index is used since some team       *
   1511  *                   missions refer to the another team mission by index number.               *
   1512  *                                                                                             *
   1513  * OUTPUT:  Returns with a pointer to the team mission text.                                   *
   1514  *                                                                                             *
   1515  * WARNINGS:   none                                                                            *
   1516  *                                                                                             *
   1517  * HISTORY:                                                                                    *
   1518  *   01/05/1996 JLB : Created.                                                                 *
   1519  *=============================================================================================*/
   1520 char const * TeamMissionClass::Description(int index) const
   1521 {
   1522 	static char buffer[64];
   1523 
   1524 	sprintf(buffer, "%d\t%s", index, TeamTypeClass::Name_From_Mission(Mission));
   1525 
   1526 	switch (TeamMission_Needs(Mission)) {
   1527 		case NEED_MISSION:
   1528 			strcat(buffer, MissionClass::Mission_Name(Data.Mission));
   1529 			break;
   1530 
   1531 		case NEED_FORMATION:
   1532 			strcat(buffer, FormationName[Data.Quarry]);
   1533 			break;
   1534 
   1535 		case NEED_NUMBER:
   1536 			sprintf(&buffer[strlen(buffer)], "%d", Data.Value);
   1537 			break;
   1538 
   1539 		case NEED_HEX_NUMBER:
   1540 			sprintf(&buffer[strlen(buffer)], "%x", Data.Value);
   1541 			break;
   1542 
   1543 		case NEED_QUARRY:
   1544 			strcat(buffer, QuarryName[Data.Quarry]);
   1545 			break;
   1546 
   1547 		case NEED_WAYPOINT:
   1548 			if (Data.Value < 26) {
   1549 				sprintf(&buffer[strlen(buffer)], "%c", Data.Value + 'A');
   1550 			} else {
   1551 				sprintf(&buffer[strlen(buffer)], "%c%c", (Data.Value/26) + 'A'-1, (Data.Value % 26) + 'A');
   1552 			}
   1553 			break;
   1554 
   1555 	}
   1556 
   1557 	return(buffer);
   1558 }
   1559 #endif
   1560 
   1561 
   1562 /***********************************************************************************************
   1563  * TeamTypeClass::Detach -- Detach the specified target from this team type.                   *
   1564  *                                                                                             *
   1565  *    This routine is called when some object is about to be removed from the game system and  *
   1566  *    all references to it must be severed. This will check to see if the specified object     *
   1567  *    is a trigger that this team refers to. If so, then the reference will be cleared.        *
   1568  *                                                                                             *
   1569  * INPUT:   target   -- The target object to remove references to.                             *
   1570  *                                                                                             *
   1571  * OUTPUT:  none                                                                               *
   1572  *                                                                                             *
   1573  * WARNINGS:   none                                                                            *
   1574  *                                                                                             *
   1575  * HISTORY:                                                                                    *
   1576  *   07/30/1996 JLB : Created.                                                                 *
   1577  *=============================================================================================*/
   1578 void TeamTypeClass::Detach(TARGET target, bool)
   1579 {
   1580 	if (Is_Target_TriggerType(target) && Trigger.Is_Valid() && Trigger == As_TriggerType(target)) {
   1581 		Trigger = NULL;
   1582 	}
   1583 }
   1584 
   1585 
   1586 /***************************************************************************
   1587  * TeamTypeClass::Read_INI -- reads INI data                               *
   1588  *                                                                         *
   1589  * INI entry format:                                                       *
   1590  *      TeamName = Housename,Roundabout,Learning,Suicide,Spy,Mercenary,    *
   1591  *       RecruitPriority,MaxAllowed,InitNum,Fear,                          *
   1592  *       ClassCount,Class:Num,Class:Num,...,                               *
   1593  *       MissionCount,Mission:Arg,Mission:Arg,Mission:Arg,...              *
   1594  *                                                                         *
   1595  * INPUT:                                                                  *
   1596  *      buffer      buffer to hold the INI data                            *
   1597  *                                                                         *
   1598  * OUTPUT:                                                                 *
   1599  *      none.                                                              *
   1600  *                                                                         *
   1601  * WARNINGS:                                                               *
   1602  *      none.                                                              *
   1603  *                                                                         *
   1604  * HISTORY:                                                                *
   1605  *   12/07/1994 BR : Created.                                              *
   1606  *   02/01/1995 BR : No del team if no classes (editor needs empty teams!) *
   1607  *=========================================================================*/
   1608 void TeamTypeClass::Read_INI(CCINIClass & ini)
   1609 {
   1610 	TeamTypeClass * team;					// Working team pointer.
   1611 	char buf[500];								// INI entry buffer
   1612 
   1613 	int len = ini.Entry_Count(INI_Name());
   1614 
   1615 	/*
   1616 	**	Loop for all team entries, create and fill in.
   1617 	*/
   1618 	for (int index = 0; index < len; index++) {
   1619 		team = new TeamTypeClass();
   1620 		if (team != NULL) {
   1621 			char const * entry = ini.Get_Entry(INI_Name(), index);
   1622 			ini.Get_String(INI_Name(), entry, NULL, buf, sizeof(buf));
   1623 			team->Fill_In((char *)entry, buf);
   1624 		}
   1625 	}
   1626 }
   1627 
   1628 
   1629 /***********************************************************************************************
   1630  * TeamTypeClass::Fill_In -- fills in trigger from the given INI entry                         *
   1631  *                                                                                             *
   1632  * This routine fills in the given teamtype with the given name, and values from               *
   1633  * the given INI entry.                                                                        *
   1634  *                                                                                             *
   1635  * (This routine is used by the scenario editor, to import teams from the MASTER.INI file.)    *
   1636  *                                                                                             *
   1637  *    INI entry format:                                                                        *
   1638  *      TeamName = Housename,Roundabout,Learning,Suicide,Spy,Mercenary,                        *
   1639  *       RecruitPriority,MaxAllowed,InitNum,Fear,                                              *
   1640  *       ClassCount,Class:Num,Class:Num,...,                                                   *
   1641  *       MissionCount,Mission:Arg,Mission:Arg,Mission:Arg,...                                  *
   1642  *                                                                                             *
   1643  * INPUT:                                                                                      *
   1644  *      name      mnemonic for the desired trigger                                             *
   1645  *      entry      INI entry to parse                                                          *
   1646  *                                                                                             *
   1647  * OUTPUT:                                                                                     *
   1648  *      none.                                                                                  *
   1649  *                                                                                             *
   1650  * WARNINGS:                                                                                   *
   1651  *      none.                                                                                  *
   1652  *                                                                                             *
   1653  * HISTORY:                                                                                    *
   1654  *   11/28/1994 BR : Created.                                                                  *
   1655  *   11/29/1995 JLB : Revamped to use new team class.                                          *
   1656  *=============================================================================================*/
   1657 void TeamTypeClass::Fill_In(char * name, char * entry)
   1658 {
   1659 	assert(TeamTypes.ID(this) == ID);
   1660 
   1661 	/*
   1662 	**	Set its name
   1663 	*/
   1664 	Set_Name(name);
   1665 
   1666 	House = HousesType(atoi(strtok(entry, ",")));
   1667 
   1668 	int code;
   1669 	switch (NewINIFormat) {
   1670 		default:
   1671 			code = atoi(strtok(NULL, ","));
   1672 			IsRoundAbout = ((code & 0x0001) != 0);
   1673 			IsSuicide = ((code & 0x0002) != 0);
   1674 			IsAutocreate = ((code & 0x0004) != 0);
   1675 			IsPrebuilt = ((code & 0x0008) != 0);
   1676 			IsReinforcable = ((code & 0x0010) != 0);
   1677 			break;
   1678 
   1679 		case 0:
   1680 		case 1:
   1681 			IsRoundAbout = atoi(strtok(NULL, ","));
   1682 			IsSuicide = atoi(strtok(NULL, ","));
   1683 			IsAutocreate = atoi(strtok(NULL, ","));
   1684 			IsPrebuilt = atoi(strtok(NULL, ","));
   1685 			IsReinforcable = atoi(strtok(NULL, ","));
   1686 			break;
   1687 	}
   1688 
   1689 	RecruitPriority = atoi(strtok(NULL, ","));
   1690 	InitNum = atoi(strtok(NULL, ","));
   1691 	MaxAllowed = atoi(strtok(NULL, ","));
   1692 	Origin = atoi(strtok(NULL, ","));
   1693 
   1694 	switch (NewINIFormat) {
   1695 		default:
   1696 			Trigger.Set_Raw(atoi(strtok(NULL, ",")));
   1697 			break;
   1698 
   1699 		case 0:
   1700 		case 1:
   1701 			// Throw this token away -- it isn't used.
   1702 			strtok(NULL, ",");
   1703 			break;
   1704 	}
   1705 
   1706 	/*
   1707 	**	Fetch the team member types and quantity values.
   1708 	*/
   1709 	ClassCount = atoi(strtok(NULL, ","));
   1710 	for (int index = 0; index < ClassCount; index++) {
   1711 		char * p1 = strtok(NULL, ",:");
   1712 		char * p2 = strtok(NULL, ",:");
   1713 		TechnoTypeClass const * otype = NULL;
   1714 
   1715 		/*
   1716 		**	See if this is an infantry name
   1717 		*/
   1718 		InfantryType i_id = InfantryTypeClass::From_Name(p1);
   1719 		if (i_id != INFANTRY_NONE) {
   1720 			otype = &InfantryTypeClass::As_Reference(i_id);
   1721 		} else {
   1722 
   1723 			/*
   1724 			**	See if this is a unit name
   1725 			*/
   1726 			UnitType u_id = UnitTypeClass::From_Name(p1);
   1727 			if (u_id != UNIT_NONE) {
   1728 				otype = &UnitTypeClass::As_Reference(u_id);
   1729 			} else {
   1730 
   1731 				/*
   1732 				**	See if this is an aircraft name
   1733 				*/
   1734 				AircraftType a_id = AircraftTypeClass::From_Name(p1);
   1735 				if (a_id != AIRCRAFT_NONE) {
   1736 					otype = &AircraftTypeClass::As_Reference(a_id);
   1737 				} else {
   1738 
   1739 					/*
   1740 					**	See if this is a vessel name.
   1741 					*/
   1742 					VesselType v_id = VesselTypeClass::From_Name(p1);
   1743 					if (v_id != VESSEL_NONE) {
   1744 						otype = &VesselTypeClass::As_Reference(v_id);
   1745 					}
   1746 				}
   1747 			}
   1748 		}
   1749 
   1750 		/*
   1751 		**	If the name was resolved, add this class
   1752 		*/
   1753 		if (otype) {
   1754 			if (index < MAX_TEAM_CLASSCOUNT) {
   1755 				Members[index].Class = otype;
   1756 				Members[index].Quantity = atoi(p2);
   1757 			}
   1758 		} else {
   1759 			ClassCount--;
   1760 			if (index == 0) break;
   1761 			index--;
   1762 		}
   1763 	}
   1764 	ClassCount = min(MAX_TEAM_CLASSCOUNT, ClassCount);
   1765 
   1766 	/*
   1767 	**	Fetch the missions assigned to this team type.
   1768 	*/
   1769 	MissionCount = atoi(strtok(NULL, ","));
   1770 	for (int index = 0; index < MissionCount; index++) {
   1771 		MissionList[index].Mission = TeamMissionType(atoi(strtok(NULL, ",:")));
   1772 		MissionList[index].Data.Value = atoi(strtok(NULL, ",:"));
   1773 	}
   1774 
   1775 	if (NewINIFormat < 2) {
   1776 		/*
   1777 		**	Fetch the trigger ID.
   1778 		*/
   1779 		Trigger.Set_Raw(atoi(strtok(NULL, ",")));
   1780 	}
   1781 }
   1782 
   1783 
   1784 /***********************************************************************************************
   1785  * TeamTypeClass::Write_INI -- Write out the team types to the INI database.                   *
   1786  *                                                                                             *
   1787  *    This routine will take all team types and write them out to the INI database specified.  *
   1788  *                                                                                             *
   1789  * INPUT:   ini   -- Reference to the INI database that will hold al the teams.                *
   1790  *                                                                                             *
   1791  * OUTPUT:  none                                                                               *
   1792  *                                                                                             *
   1793  * WARNINGS:   All preexisting team data in the database will be erased by this routine.       *
   1794  *                                                                                             *
   1795  * HISTORY:                                                                                    *
   1796  *   07/30/1996 JLB : Created.                                                                 *
   1797  *=============================================================================================*/
   1798 void TeamTypeClass::Write_INI(CCINIClass & ini)
   1799 {
   1800 	ini.Clear("TeamTypes");
   1801 	ini.Clear(INI_Name());
   1802 
   1803 	/*
   1804 	**	Now write all the team data out
   1805 	*/
   1806 	for (int index = 0; index < TeamTypes.Count(); index++) {
   1807 //	for (int index = TeamTypes.Count()-1; index >= 0; index--) {
   1808 		TeamTypeClass * team = TeamTypes.Ptr(index);
   1809 		char buf[256];
   1810 
   1811 		buf[0] = 0;
   1812 		team->Build_INI_Entry(buf);
   1813 		ini.Put_String(INI_Name(), team->IniName, buf);
   1814 	}
   1815 }
   1816 
   1817 
   1818 /***********************************************************************************************
   1819  * TeamTypeClass::Build_INI_Entry -- Builds the INI entry for this team type.                  *
   1820  *                                                                                             *
   1821  *    This routine is used to build the text string that will go into the INI database for     *
   1822  *    a team of this type. This text string will be parsed back into a team object when the    *
   1823  *    scenario INI is read in.                                                                 *
   1824  *                                                                                             *
   1825  * INPUT:   buf   -- Pointer to a buffer that will hold the team text entry.                   *
   1826  *                                                                                             *
   1827  * OUTPUT:  none                                                                               *
   1828  *                                                                                             *
   1829  * WARNINGS:   Be sure that the buffer can hold the string build. A size of 80 or so is        *
   1830  *             usually sufficient.                                                             *
   1831  *                                                                                             *
   1832  * HISTORY:                                                                                    *
   1833  *   07/30/1996 JLB : Created.                                                                 *
   1834  *=============================================================================================*/
   1835 void TeamTypeClass::Build_INI_Entry(char * buf)
   1836 {
   1837 	int code = 0;
   1838 	code |= IsRoundAbout ? 0x0001 : 0;
   1839 	code |= IsSuicide ? 0x0002 : 0;
   1840 	code |= IsAutocreate ? 0x0004 : 0;
   1841 	code |= IsPrebuilt ? 0x0008 : 0;
   1842 	code |= IsReinforcable ? 0x0010 : 0;
   1843 
   1844 	/*
   1845 	**	Output the general data for this team type.
   1846 	*/
   1847 	sprintf(buf, "%d,%d,%d,%d,%d,%d,%d",
   1848 		House,
   1849 		code,
   1850 		RecruitPriority,
   1851 		InitNum,
   1852 		MaxAllowed,
   1853 		Origin,
   1854 		TriggerTypes.Logical_ID(Trigger)
   1855 		);
   1856 	buf += strlen(buf);
   1857 
   1858 	/*
   1859 	**	For every class in the team, record the class's name & desired count
   1860 	*/
   1861 	sprintf (buf, ",%d", ClassCount);
   1862 	buf += strlen(buf);
   1863 	for (int i = 0; i < ClassCount; i++) {
   1864 		sprintf (buf, ",%s:%d", Members[i].Class->IniName, Members[i].Quantity);
   1865 		buf += strlen(buf);
   1866 	}
   1867 
   1868 	/*
   1869 	**	Record the # of missions, and each mission name & argument value.
   1870 	*/
   1871 	sprintf(buf, ",%d", MissionCount);
   1872 	buf += strlen(buf);
   1873 	for (int i = 0; i < MissionCount; i++) {
   1874 		sprintf (buf, ",%d:%d", MissionList[i].Mission, MissionList[i].Data.Value);
   1875 		buf += strlen(buf);
   1876 	}
   1877 }
   1878 
   1879