CnC_Remastered_Collection

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

MAPEDPLC.CPP (59083B)


      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/MAPEDPLC.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 : MAPEDPLC.CPP                             *
     24  *                                                                         *
     25  *                   Programmer : Bill Randolph                            *
     26  *                                                                         *
     27  *                   Start Date : November 18, 1994                        *
     28  *                                                                         *
     29  *                  Last Update : May 12, 1996 [JLB]                       *
     30  *                                                                         *
     31  *-------------------------------------------------------------------------*
     32  * Object-placement routines                                               *
     33  *-------------------------------------------------------------------------*
     34  * Functions:                                                              *
     35  *   MapEditClass::Build_Base_To -- builds the AI base to the given percent*
     36  *   MapEditClass::Cancel_Base_Building -- stops base-building mode        *
     37  *   MapEditClass::Cancel_Placement -- cancels placement mode              *
     38  *   MapEditClass::Place_Home -- homes the placement object                *
     39  *   MapEditClass::Place_Next -- while placing object, goes to next        *
     40  *   MapEditClass::Place_Next_Category -- places next object category      *
     41  *   MapEditClass::Place_Object -- attempts to place the current object    *
     42  *   MapEditClass::Place_Prev -- while placing object, goes to previous    *
     43  *   MapEditClass::Place_Prev_Category -- places previous object category  *
     44  *   MapEditClass::Place_Trigger -- assigns trigger to object or cell      *
     45  *   MapEditClass::Placement_Dialog -- adds an object to the scenario      *
     46  *   MapEditClass::Set_House_Buttons -- toggles house buttons for btn list *
     47  *   MapEditClass::Start_Base_Building -- starts base-building mode        *
     48  *   MapEditClass::Start_Placement -- enters placement mode                *
     49  *   MapEditClass::Start_Trigger_Placement -- enters trigger placement mode*
     50  *   MapEditClass::Stop_Trigger_Placement -- exits trigger placement mode  *
     51  *   MapEditClass::Toggle_House -- toggles current placement object's house*
     52  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     53 
     54 #include	"function.h"
     55 
     56 #ifdef SCENARIO_EDITOR
     57 
     58 
     59 /***************************************************************************
     60  * MapEditClass::Placement_Dialog -- adds an object to the scenario        *
     61  *                                                                         *
     62  * This function sets LastChoice & LastHouse to the values chosen          *
     63  * by the user. It's up to the caller to call Start_Placement to enter     *
     64  * placement mode.                                                         *
     65  *   This routine does not modify PendingObject or PendingHouse.           *
     66  *                                                                         *
     67  *  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿                   *
     68  *  ³   [GDI]  [NOD]  [Neutral]                        ³                   *
     69  *  ³                                                  ³                   *
     70  *  ³   ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿              ³                   *
     71  *  ³   ³                               ³ [Template]   ³                   *
     72  *  ³   ³                               ³ [Overlay ]   ³                   *
     73  *  ³   ³                               ³ [Smudge  ]   ³                   *
     74  *  ³   ³                               ³ [Terrain ]   ³                   *
     75  *  ³   ³      (Object picture)         ³ [Unit    ]   ³                   *
     76  *  ³   ³                               ³ [Infantry]   ³                   *
     77  *  ³   ³                               ³ [Aircraft]   ³                   *
     78  *  ³   ³                               ³ [Building]   ³                   *
     79  *  ³   ³                               ³              ³                   *
     80  *  ³   ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ     ÚÄÄÄÄÄÄ¿ ³                   *
     81  *  ³             [<-]  [->]                  ³(Grid)³ ³                   *
     82  *  ³                                         ³      ³ ³                   *
     83  *  ³         [OK]        [Cancel]            ÀÄÄÄÄÄÄÙ ³                   *
     84  *  ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ                   *
     85  *                                                                         *
     86  * INPUT:                                                                  *
     87  *      none.                                                              *
     88  *                                                                         *
     89  * OUTPUT:                                                                 *
     90  *      0 = OK, -1 = cancel                                                *
     91  *                                                                         *
     92  * WARNINGS:                                                               *
     93  *      none.                                                              *
     94  *                                                                         *
     95  * HISTORY:                                                                *
     96  *   10/21/1994 BR : Created.                                              *
     97  *   12/13/1995 JLB : Fixed house buttons to handle expanded house list.   *
     98  *   05/12/1996 JLB : Handles hi-res.                                      *
     99  *=========================================================================*/
    100 int MapEditClass::Placement_Dialog(void)
    101 {
    102 	HousesType house;
    103 	RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
    104 
    105 	/*
    106 	**	Dialog & button dimensions
    107 	*/
    108 	enum {
    109 		D_DIALOG_W = 400,
    110 		D_DIALOG_H = 180,
    111 		D_DIALOG_X = 0,
    112 		D_DIALOG_Y = 0,
    113 		D_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),
    114 
    115 		D_TXT8_H = 11,
    116 		D_MARGIN = 7,
    117 
    118 		D_PICTURE_W = 152,					// must be divisible by 8!
    119 		D_PICTURE_H = 105,
    120 		D_PICTURE_X = D_DIALOG_X + 35,		// must start on a byte boundary!
    121 		D_PICTURE_Y = D_DIALOG_Y + D_MARGIN + D_TXT8_H + D_MARGIN,
    122 		D_PICTURE_CX = D_PICTURE_X + D_PICTURE_W / 2,
    123 
    124 		D_GDI_W = 65,
    125 		D_GDI_H = 9,
    126 		D_GDI_X = D_PICTURE_X+D_PICTURE_W+5,
    127 		D_GDI_Y = D_PICTURE_Y,
    128 
    129 		D_LEFT_W = 45,
    130 		D_LEFT_H = 9,
    131 		D_LEFT_X = D_PICTURE_CX - 5 - D_LEFT_W,
    132 		D_LEFT_Y = D_PICTURE_Y + D_PICTURE_H + D_MARGIN,
    133 
    134 		D_RIGHT_W = 45,
    135 		D_RIGHT_H = 9,
    136 		D_RIGHT_X = D_PICTURE_CX + 5,
    137 		D_RIGHT_Y = D_PICTURE_Y + D_PICTURE_H + D_MARGIN,
    138 
    139 		D_TEMPLATE_W = 70,
    140 		D_TEMPLATE_H = 9,
    141 		D_TEMPLATE_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_TEMPLATE_W - 30,
    142 		D_TEMPLATE_Y = D_PICTURE_Y,
    143 
    144 		D_OVERLAY_W = 70,
    145 		D_OVERLAY_H = 9,
    146 		D_OVERLAY_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_OVERLAY_W - 30,
    147 		D_OVERLAY_Y = D_TEMPLATE_Y + D_TEMPLATE_H,
    148 
    149 		D_SMUDGE_W = 70,
    150 		D_SMUDGE_H = 9,
    151 		D_SMUDGE_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_SMUDGE_W - 30,
    152 		D_SMUDGE_Y = D_OVERLAY_Y + D_OVERLAY_H,
    153 
    154 		D_TERRAIN_W = 70,
    155 		D_TERRAIN_H = 9,
    156 		D_TERRAIN_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_TERRAIN_W - 30,
    157 		D_TERRAIN_Y = D_SMUDGE_Y + D_SMUDGE_H,
    158 
    159 		D_UNIT_W = 70,
    160 		D_UNIT_H = 9,
    161 		D_UNIT_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_UNIT_W - 30,
    162 		D_UNIT_Y = D_TERRAIN_Y + D_TERRAIN_H,
    163 
    164 		D_INFANTRY_W = 70,
    165 		D_INFANTRY_H = 9,
    166 		D_INFANTRY_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_INFANTRY_W - 30,
    167 		D_INFANTRY_Y = D_UNIT_Y + D_UNIT_H,
    168 
    169 		D_AIRCRAFT_W = 70,
    170 		D_AIRCRAFT_H = 9,
    171 		D_AIRCRAFT_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_AIRCRAFT_W - 30,
    172 		D_AIRCRAFT_Y = D_INFANTRY_Y + D_INFANTRY_H,
    173 
    174 		D_BUILDING_W = 70,
    175 		D_BUILDING_H = 9,
    176 		D_BUILDING_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_BUILDING_W - 30,
    177 		D_BUILDING_Y = D_AIRCRAFT_Y + D_AIRCRAFT_H,
    178 
    179 		D_AIR_W = 70,
    180 		D_AIR_H = 9,
    181 		D_AIR_X = D_DIALOG_X + D_DIALOG_W - D_MARGIN - D_AIR_W - 30,
    182 		D_AIR_Y = D_BUILDING_Y + D_BUILDING_H,
    183 
    184 		D_OK_W = 45,
    185 		D_OK_H = 9,
    186 		D_OK_X = D_PICTURE_CX - D_OK_W - 5,
    187 		D_OK_Y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - D_MARGIN - 15,
    188 
    189 		D_CANCEL_W = 45,
    190 		D_CANCEL_H = 9,
    191 		D_CANCEL_X = D_PICTURE_CX + 5,
    192 		D_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - D_MARGIN - 15,
    193 
    194 		GRIDSIZE = 10,
    195 		GRIDBLOCK_W = 3,
    196 		GRIDBLOCK_H = 3,
    197 		D_GRID_X = D_DIALOG_X + D_DIALOG_W - (GRIDSIZE * GRIDBLOCK_W) - D_MARGIN - 35,
    198 		D_GRID_Y = D_DIALOG_Y + D_DIALOG_H - (GRIDSIZE * GRIDBLOCK_H) - D_MARGIN - 35,
    199 	};
    200 
    201 	/*
    202 	**	Button enumerations:
    203 	*/
    204 	enum {
    205 		BUTTON_GDI=100,
    206 		BUTTON_HOUSE,
    207 		BUTTON_NEXT,
    208 		BUTTON_PREV,
    209 		BUTTON_OK,
    210 		BUTTON_CANCEL,
    211 		BUTTON_TEMPLATE,
    212 		BUTTON_OVERLAY,
    213 		BUTTON_SMUDGE,
    214 		BUTTON_TERRAIN,
    215 		BUTTON_UNIT,
    216 		BUTTON_INFANTRY,
    217 		BUTTON_AIRCRAFT,
    218 		BUTTON_BUILDING,
    219 		BUTTON_AIR,
    220 	};
    221 
    222 	/*
    223 	**	Dialog variables
    224 	*/
    225 	bool cancel = false;							// true = user cancels
    226 	const ObjectTypeClass * curobj;			// Working object pointer.
    227 	int x,y;											// for drawing the grid
    228 	KeyNumType input;								// user input
    229 	short const * occupy;							// ptr into object's OccupyList
    230 	int cell;										// cell index for parsing OccupyList
    231 	int i;
    232 	int typeindex;									// index of class type
    233 
    234 	/*
    235 	**	Buttons
    236 	*/
    237 	ControlClass * commands;
    238 
    239 	ListClass housebtn(BUTTON_HOUSE,
    240 		D_GDI_X, D_GDI_Y, 60, 8*16,
    241 		TPF_EFNT | TPF_NOSHADOW,
    242 		MFCD::Retrieve("EBTN-UP.SHP"),
    243 		MFCD::Retrieve("EBTN-DN.SHP"));
    244 	for (house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
    245 		housebtn.Add_Item(HouseTypeClass::As_Reference(house).IniName);
    246 	}
    247 	house = HOUSE_FIRST;
    248 
    249 	TextButtonClass nextbtn(BUTTON_NEXT, TXT_RIGHT, TPF_EBUTTON, D_RIGHT_X, D_RIGHT_Y, D_RIGHT_W, D_RIGHT_H);
    250 	TextButtonClass prevbtn(BUTTON_PREV, TXT_LEFT, TPF_EBUTTON, D_LEFT_X, D_LEFT_Y, D_LEFT_W, D_LEFT_H);
    251 	TextButtonClass okbtn(BUTTON_OK, "OK", TPF_EBUTTON, D_OK_X, D_OK_Y, D_OK_W, D_OK_H);
    252 	TextButtonClass cancelbtn(BUTTON_CANCEL, "Cancel", TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W, D_CANCEL_H);
    253 	TextButtonClass templatebtn(BUTTON_TEMPLATE, "Template", TPF_EBUTTON, D_TEMPLATE_X, D_TEMPLATE_Y, D_TEMPLATE_W, D_TEMPLATE_H);
    254 	TextButtonClass overlaybtn(BUTTON_OVERLAY, "Overlay", TPF_EBUTTON, D_OVERLAY_X, D_OVERLAY_Y, D_OVERLAY_W, D_OVERLAY_H);
    255 	TextButtonClass smudgebtn(BUTTON_SMUDGE, "Smudge", TPF_EBUTTON, D_SMUDGE_X, D_SMUDGE_Y, D_SMUDGE_W, D_SMUDGE_H);
    256 	TextButtonClass terrainbtn(BUTTON_TERRAIN, "Terrain", TPF_EBUTTON, D_TERRAIN_X, D_TERRAIN_Y, D_TERRAIN_W, D_TERRAIN_H);
    257 	TextButtonClass unitbtn(BUTTON_UNIT, "Unit", TPF_EBUTTON, D_UNIT_X, D_UNIT_Y, D_UNIT_W, D_UNIT_H);
    258 	TextButtonClass infantrybtn(BUTTON_INFANTRY, "Infantry", TPF_EBUTTON, D_INFANTRY_X, D_INFANTRY_Y, D_INFANTRY_W, D_INFANTRY_H);
    259 	TextButtonClass aircraftbtn(BUTTON_AIRCRAFT, "Ships", TPF_EBUTTON, D_AIRCRAFT_X, D_AIRCRAFT_Y, D_AIRCRAFT_W, D_AIRCRAFT_H);
    260 	TextButtonClass buildingbtn(BUTTON_BUILDING, "Building", TPF_EBUTTON, D_BUILDING_X, D_BUILDING_Y, D_BUILDING_W, D_BUILDING_H);
    261 	TextButtonClass airbtn(BUTTON_AIR, "Aircraft", TPF_EBUTTON, D_AIR_X, D_AIR_Y, D_AIR_W, D_AIR_H);
    262 
    263 	/*
    264 	**	Initialize addable objects list; we must do this every time in case one
    265 	**	of the object pools has become exhausted; that object won't be available
    266 	**	for adding.  (Skip aircraft, since they won't be used in the editor.)
    267 	*/
    268 	Clear_List();
    269 	TemplateTypeClass::Prep_For_Add();
    270 	OverlayTypeClass::Prep_For_Add();
    271 	SmudgeTypeClass::Prep_For_Add();
    272 	TerrainTypeClass::Prep_For_Add();
    273 	UnitTypeClass::Prep_For_Add();
    274 	InfantryTypeClass::Prep_For_Add();
    275 	VesselTypeClass::Prep_For_Add();
    276 	BuildingTypeClass::Prep_For_Add();
    277 	AircraftTypeClass::Prep_For_Add();
    278 
    279 	/*
    280 	**	Compute offset of each class type in the Objects array
    281 	*/
    282 	TypeOffset[0] = 0;
    283 	for (i = 1; i < NUM_EDIT_CLASSES; i++) {
    284 		TypeOffset[i] = TypeOffset[i-1] + NumType[i-1];
    285 	}
    286 
    287 	/*
    288 	**	Return if no objects to place
    289 	*/
    290 	if (!ObjCount)  {
    291 		return(-1);
    292 	}
    293 
    294 	/*
    295 	**	Initialize
    296 	*/
    297 	Set_Logic_Page(SeenBuff);
    298 	if (LastChoice >= ObjCount) {
    299 		LastChoice = 0;
    300 	}
    301 	curobj = Objects[LastChoice];		// current object to choose
    302 
    303 	commands = &nextbtn;
    304 	housebtn.Add_Tail(*commands);
    305 	prevbtn.Add_Tail(*commands);
    306 	okbtn.Add_Tail(*commands);
    307 	cancelbtn.Add_Tail(*commands);
    308 	templatebtn.Add_Tail(*commands);
    309 	overlaybtn.Add_Tail(*commands);
    310 	smudgebtn.Add_Tail(*commands);
    311 	terrainbtn.Add_Tail(*commands);
    312 	unitbtn.Add_Tail(*commands);
    313 	infantrybtn.Add_Tail(*commands);
    314 	aircraftbtn.Add_Tail(*commands);
    315 	buildingbtn.Add_Tail(*commands);
    316 	airbtn.Add_Tail(*commands);
    317 
    318 	/*
    319 	**	Make sure the recorded house selection matches the house list
    320 	**	box selection.
    321 	*/
    322 	LastHouse = HousesType(housebtn.Current_Index());
    323 
    324 	/*
    325 	**	Main processing loop
    326 	*/
    327 	bool display = true;
    328 	bool process = true;
    329 	while (process) {
    330 
    331 		/*
    332 		**	Invoke game callback
    333 		*/
    334 		Call_Back();
    335 
    336 		/*
    337 		**	Refresh display if needed
    338 		*/
    339 		if (display) {
    340 
    341 			/*
    342 			**	Display the dialog box
    343 			*/
    344 			Hide_Mouse();
    345 			Dialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);
    346 			Draw_Caption(TXT_PLACE_OBJECT, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);
    347 
    348 			/*
    349 			**	Display the current object:
    350 			**	- save the current window dimensions
    351 			**	- adjust the window size to the actual drawable area
    352 			**	- draw the shape
    353 			**	- reset the window dimensions
    354 			*/
    355 			WindowList[WINDOW_EDITOR][WINDOWX] = D_PICTURE_X;
    356 			WindowList[WINDOW_EDITOR][WINDOWY] = D_PICTURE_Y;
    357 			WindowList[WINDOW_EDITOR][WINDOWWIDTH] = D_PICTURE_W;
    358 			WindowList[WINDOW_EDITOR][WINDOWHEIGHT] = D_PICTURE_H;
    359 			Change_Window((int)WINDOW_EDITOR);
    360 			Draw_Box(D_PICTURE_X, D_PICTURE_Y, D_PICTURE_W, D_PICTURE_H, BOXSTYLE_DOWN, false);
    361 			curobj->Display(WinW/2, WinH>>1, WINDOW_EDITOR, LastHouse);
    362 //			curobj->Display(WinW<<2, WinH>>1, WINDOW_EDITOR, LastHouse);
    363 
    364 			/*
    365 			**	Erase the grid
    366 			*/
    367 			LogicPage->Fill_Rect(D_GRID_X - GRIDBLOCK_W * 2, D_GRID_Y,
    368 				D_GRID_X + GRIDSIZE * GRIDBLOCK_W,
    369 				D_GRID_Y + GRIDSIZE * GRIDBLOCK_H, BLACK);
    370 
    371 			/*
    372 			**	Draw a box for every cell occupied
    373 			*/
    374 			occupy = curobj->Occupy_List();
    375 			while ( (*occupy) != REFRESH_EOL) {
    376 				cell = (*occupy);
    377 				occupy++;
    378 				x = D_GRID_X + ((cell % MAP_CELL_W) * GRIDBLOCK_W);
    379 				y = D_GRID_Y + ((cell / MAP_CELL_W) * GRIDBLOCK_H);
    380 				LogicPage->Fill_Rect(x, y, x + GRIDBLOCK_W - 1, y + GRIDBLOCK_H - 1, scheme->Bright);
    381 			}
    382 
    383 			/*
    384 			**	Draw the grid itself
    385 			*/
    386 			for (y = 0; y <= GRIDSIZE; y++) {
    387 				for (x = 0; x <= GRIDSIZE; x++) {
    388 					LogicPage->Draw_Line(D_GRID_X + x * GRIDBLOCK_W, D_GRID_Y,
    389 						D_GRID_X + x * GRIDBLOCK_W,
    390 						D_GRID_Y + GRIDSIZE * GRIDBLOCK_H, scheme->Shadow);
    391 				}
    392 				LogicPage->Draw_Line(D_GRID_X, D_GRID_Y + y * GRIDBLOCK_H,
    393 					D_GRID_X + GRIDSIZE * GRIDBLOCK_W, D_GRID_Y + y * GRIDBLOCK_H,
    394 					scheme->Shadow);
    395 			}
    396 
    397 			/*
    398 			**	Print the object's label from the class's Full_Name().
    399 			**	Warning: Text_String returns an EMS pointer, so standard string
    400 			**	functions won't work!
    401 			*/
    402 			Fancy_Text_Print (curobj->Full_Name(),
    403 				D_PICTURE_CX, D_PICTURE_Y + D_MARGIN, scheme, TBLACK,
    404 				TPF_CENTER | TPF_EFNT | TPF_NOSHADOW);
    405 
    406 			/*
    407 			**	Redraw buttons
    408 			**	Figure out which class category we're in & highlight that button
    409 			**	This updates 'typeindex', which is used below, and it also updates
    410 			**	the category button states.
    411 			*/
    412 			i = 0;
    413 			for (typeindex = 0; typeindex < NUM_EDIT_CLASSES; typeindex++) {
    414 				i += NumType[typeindex];
    415 				if (LastChoice < i) break;
    416 			}
    417 			templatebtn.Turn_Off();
    418 			overlaybtn.Turn_Off();
    419 			smudgebtn.Turn_Off();
    420 			terrainbtn.Turn_Off();
    421 			unitbtn.Turn_Off();
    422 			infantrybtn.Turn_Off();
    423 			aircraftbtn.Turn_Off();
    424 			airbtn.Turn_Off();
    425 			buildingbtn.Turn_Off();
    426 			switch (typeindex + BUTTON_TEMPLATE) {
    427 				case BUTTON_TEMPLATE:
    428 					templatebtn.Turn_On();
    429 					break;
    430 
    431 				case BUTTON_OVERLAY:
    432 					overlaybtn.Turn_On();
    433 					break;
    434 
    435 				case BUTTON_SMUDGE:
    436 					smudgebtn.Turn_On();
    437 					break;
    438 
    439 				case BUTTON_TERRAIN:
    440 					terrainbtn.Turn_On();
    441 					break;
    442 
    443 				case BUTTON_UNIT:
    444 					unitbtn.Turn_On();
    445 					break;
    446 
    447 				case BUTTON_INFANTRY:
    448 					infantrybtn.Turn_On();
    449 					break;
    450 
    451 				case BUTTON_AIRCRAFT:
    452 					aircraftbtn.Turn_On();
    453 					break;
    454 
    455 				case BUTTON_AIR:
    456 					airbtn.Turn_On();
    457 					break;
    458 
    459 				case BUTTON_BUILDING:
    460 					buildingbtn.Turn_On();
    461 					break;
    462 			}
    463 
    464 			/*
    465 			**	Redraw buttons
    466 			*/
    467 			commands->Draw_All();
    468 			Show_Mouse();
    469 			display = false;
    470 
    471 		}
    472 
    473 		/*
    474 		**	Get user input
    475 		*/
    476 		input = commands->Input();
    477 
    478 		/*
    479 		**	Process user input
    480 		*/
    481 		switch (input) {
    482 
    483 			/*
    484 			**	GDI House
    485 			*/
    486 			case (BUTTON_HOUSE | KN_BUTTON):
    487 				house = HousesType(housebtn.Current_Index());
    488 
    489 				/*
    490 				**	Set flags & buttons
    491 				*/
    492 				LastHouse = house;
    493 				display = true;
    494 				break;
    495 
    496 			/*
    497 			**	Next in list
    498 			*/
    499 			case (KN_RIGHT):
    500 			case (BUTTON_NEXT | KN_BUTTON):
    501 				/*
    502 				**	Increment to next obj
    503 				*/
    504 				LastChoice++;
    505 				if (LastChoice == ObjCount) {
    506 					LastChoice = 0;
    507 				}
    508 				curobj = Objects[LastChoice];
    509 
    510 				nextbtn.Turn_Off();
    511 				display = true;
    512 				break;
    513 
    514 			/*
    515 			**	Previous in list
    516 			*/
    517 			case (KN_LEFT):
    518 			case (BUTTON_PREV | KN_BUTTON):
    519 
    520 				/*
    521 				**	Decrement to prev obj
    522 				*/
    523 				LastChoice--;
    524 				if (LastChoice < 0) {
    525 					LastChoice = ObjCount-1;
    526 				}
    527 				curobj = Objects[LastChoice];
    528 				prevbtn.Turn_Off();
    529 				display = true;
    530 				break;
    531 
    532 			/*
    533 			**	Select a class type
    534 			*/
    535 			case (BUTTON_TEMPLATE | KN_BUTTON):
    536 			case (BUTTON_OVERLAY | KN_BUTTON):
    537 			case (BUTTON_SMUDGE | KN_BUTTON):
    538 			case (BUTTON_TERRAIN | KN_BUTTON):
    539 			case (BUTTON_UNIT | KN_BUTTON):
    540 			case (BUTTON_INFANTRY | KN_BUTTON):
    541 			case (BUTTON_AIRCRAFT | KN_BUTTON):
    542 			case (BUTTON_BUILDING | KN_BUTTON):
    543 			case (BUTTON_AIR | KN_BUTTON):
    544 
    545 				/*
    546 				**	Find index of class
    547 				*/
    548 				typeindex = input - (BUTTON_TEMPLATE | KN_BUTTON);
    549 
    550 				/*
    551 				**	If no objects of that type, do nothing
    552 				*/
    553 				if (NumType[typeindex]==0) {
    554 					display = true;
    555 					break;
    556 				}
    557 
    558 				/*
    559 				**	Set current object
    560 				*/
    561 				LastChoice = TypeOffset[typeindex];
    562 				curobj = Objects[LastChoice];
    563 				display = true;
    564 				break;
    565 
    566 			/*
    567 			**	Next category
    568 			*/
    569 			case KN_PGDN:
    570 				typeindex++;
    571 				if (typeindex==NUM_EDIT_CLASSES) {
    572 					typeindex = 0;
    573 				}
    574 
    575 				/*
    576 				**	Set current object
    577 				*/
    578 				LastChoice = TypeOffset[typeindex];
    579 				curobj = Objects[LastChoice];
    580 				display = true;
    581 				break;
    582 
    583 			/*
    584 			**	Previous category
    585 			*/
    586 			case KN_PGUP:
    587 				typeindex--;
    588 				if (typeindex < 0) {
    589 					typeindex = NUM_EDIT_CLASSES - 1;
    590 				}
    591 
    592 				/*
    593 				**	Set current object
    594 				*/
    595 				LastChoice = TypeOffset[typeindex];
    596 				curobj = Objects[LastChoice];
    597 				display = true;
    598 				break;
    599 
    600 			/*
    601 			**	Jump to 1st choice
    602 			*/
    603 			case KN_HOME:
    604 				LastChoice = 0;
    605 
    606 				/*
    607 				**	Set current object
    608 				*/
    609 				curobj = Objects[LastChoice];
    610 				display = true;
    611 				break;
    612 
    613 			/*
    614 			**	OK
    615 			*/
    616 			case (KN_RETURN):
    617 			case (BUTTON_OK | KN_BUTTON):
    618 				cancel = false;
    619 				process = false;
    620 				break;
    621 
    622 			/*
    623 			**	Cancel
    624 			*/
    625 			case (KN_ESC):
    626 			case (BUTTON_CANCEL | KN_BUTTON):
    627 				cancel = true;
    628 				process = false;
    629 				break;
    630 
    631 			default:
    632 				break;
    633 		}
    634 
    635 	}
    636 
    637 	/*
    638 	**	Redraw the display
    639 	*/
    640 	HidPage.Clear();
    641 	Flag_To_Redraw(true);
    642 	Render();
    643 
    644 	if (cancel) {
    645 		return(-1);
    646 	}
    647 
    648 	return(0);
    649 }
    650 
    651 
    652 /***************************************************************************
    653  * MapEditClass::Start_Placement -- enters placement mode                  *
    654  *                                                                         *
    655  * INPUT:                                                                  *
    656  *      none.                                                              *
    657  *                                                                         *
    658  * OUTPUT:                                                                 *
    659  *      none.                                                              *
    660  *                                                                         *
    661  * WARNINGS:                                                               *
    662  *      none.                                                              *
    663  *                                                                         *
    664  * HISTORY:                                                                *
    665  *   11/04/1994 BR : Created.                                              *
    666  *=========================================================================*/
    667 void MapEditClass::Start_Placement(void)
    668 {
    669 
    670 	/*
    671 	**	Initialize addable objects list; we must do this every time in case one
    672 	**	of the object pools has become exhausted; that object won't be available
    673 	**	for adding. These must be added in the same order expected by the
    674 	**	object selection dialog (same as button order).
    675 	*/
    676 	Clear_List();
    677 	TemplateTypeClass::Prep_For_Add();
    678 	OverlayTypeClass::Prep_For_Add();
    679 	SmudgeTypeClass::Prep_For_Add();
    680 	TerrainTypeClass::Prep_For_Add();
    681 	UnitTypeClass::Prep_For_Add();
    682 	InfantryTypeClass::Prep_For_Add();
    683 	VesselTypeClass::Prep_For_Add();
    684 	BuildingTypeClass::Prep_For_Add();
    685 	AircraftTypeClass::Prep_For_Add();
    686 
    687 	/*
    688 	**	Compute offset of each class type in the Objects array
    689 	*/
    690 	TypeOffset[0] = 0;
    691 	for (int i = 1; i < NUM_EDIT_CLASSES; i++) {
    692 		TypeOffset[i] = TypeOffset[i-1] + NumType[i-1];
    693 	}
    694 
    695 	/*
    696 	**	Create the placement object:
    697 	**	- For normal placement mode, use the last-used index into Objects
    698 	**	  (LastChoice), and the last-used house (LastHouse).
    699 	**	- For base-building mode, force the object to be a building, and use the
    700 	**	  House specified in the Base object
    701 	*/
    702 	if (!BaseBuilding) {
    703 		if (LastChoice >= ObjCount) {
    704 			LastChoice = ObjCount - 1;
    705 		}
    706 		PendingObject = Objects[LastChoice];
    707 		PendingHouse = LastHouse;
    708 		PendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(LastHouse));
    709 	} else {
    710 		if (LastChoice < TypeOffset[7]) {
    711 			LastChoice = TypeOffset[7];
    712 		}
    713 		if (LastChoice >= ObjCount) {
    714 			LastChoice = ObjCount - 1;
    715 		}
    716 		PendingObject = Objects[LastChoice];
    717 		PendingHouse = LastHouse = Base.House;
    718 		PendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(LastHouse));
    719 	}
    720 
    721 	/*
    722 	**	Error if no more objects available
    723 	*/
    724 	if (!PendingObjectPtr) {
    725 		WWMessageBox().Process("No more objects of this type available.");
    726 		HidPage.Clear();
    727 		Flag_To_Redraw(true);
    728 		Render();
    729 		PendingObject = NULL;
    730 		if (BaseBuilding) {
    731 			Cancel_Base_Building();
    732 		}
    733 		return;
    734 	}
    735 
    736 	/*
    737 	**	Set the placement cursor
    738 	*/
    739 	Set_Cursor_Pos();
    740 	Set_Cursor_Shape(PendingObject->Occupy_List());
    741 }
    742 
    743 
    744 /***************************************************************************
    745  * MapEditClass::Place_Object -- attempts to place the current object      *
    746  *                                                                         *
    747  * Placement of "real" objects is simply checked via their Unlimbo routine.*
    748  * Placement of templates is more complex:                                 *
    749  * - for every cell in the template's OccupyList, check for objects        *
    750  *     already in that cell by looking at the cell's OccupyList &          *
    751  *     OverlapList                                                         *
    752  * - "lift" all the objects in the cell by Mark'ing them                   *
    753  * - temporarily place the template in that cell                           *
    754  * - try to Unlimbo all the objects that were in the cell. If any          *
    755  *     objects fail to Unlimbo onto that template, the template cannot     *
    756  *     be placed here                                                      *
    757  *                                                                         *
    758  * It is assumed that the object being placed is a "new" object; the       *
    759  * object's strength & mission are not set during Unlimbo.                 *
    760  *                                                                         *
    761  * INPUT:                                                                  *
    762  *      none.                                                              *
    763  *                                                                         *
    764  * OUTPUT:                                                                 *
    765  *      0 = OK, -1 = unable to place                                       *
    766  *                                                                         *
    767  * WARNINGS:                                                               *
    768  *      none.                                                              *
    769  *                                                                         *
    770  * HISTORY:                                                                *
    771  *   11/04/1994 BR : Created.                                              *
    772  *=========================================================================*/
    773 int MapEditClass::Place_Object(void)
    774 {
    775 	CELL template_cell;						// cell being checked for template
    776 	COORDINATE obj_coord;							// coord of occupier object
    777 	int okflag;									// OK to place a template?
    778 	short const * occupy;						// ptr into template's OccupyList
    779 	ObjectClass * occupier;					// occupying object
    780 	TemplateType save_ttype;				// for saving cell's TType
    781 	unsigned char save_ticon;				// for saving cell's TIcon
    782 //	BaseNodeClass node;						// for adding to an AI Base
    783 
    784 	/*
    785 	**	Placing a template:
    786 	**	- first lift up any objects in the cell
    787 	**	- place the template, and try to replace the objects; if they won't go
    788 	**	  back, the template can't go there
    789 	*/
    790 	//ScenarioInit++;
    791 	if (PendingObject->What_Am_I() == RTTI_TEMPLATETYPE) {
    792 
    793 		/*
    794 		**	Loop through all cells this template will occupy
    795 		*/
    796 		okflag = true;
    797 		occupy = PendingObject->Occupy_List();
    798 		while ((*occupy) != REFRESH_EOL) {
    799 
    800 			/*
    801 			**	Check this cell for an occupier
    802 			*/
    803 			template_cell = (ZoneCell+ZoneOffset) + (*occupy);
    804 			if ((*this)[template_cell].Cell_Occupier()) {
    805 				occupier = (*this)[template_cell].Cell_Occupier();
    806 
    807 				/*
    808 				**	Save object's coordinates
    809 				*/
    810 				obj_coord = occupier->Coord;
    811 
    812 				/*
    813 				**	Place the object in limbo
    814 				*/
    815 				occupier->Mark(MARK_UP);
    816 
    817 				/*
    818 				**	Set the cell's template values
    819 				*/
    820 				save_ttype = (*this)[template_cell].TType;
    821 				save_ticon = (*this)[template_cell].TIcon;
    822 				(*this)[template_cell].TType =
    823 					((TemplateTypeClass *)PendingObject)->Type;
    824 				(*this)[template_cell].TIcon = Cell_X(*occupy) + Cell_Y(*occupy) *
    825 					((TemplateTypeClass *)PendingObject)->Width;
    826 				(*this)[template_cell].Recalc_Attributes();
    827 
    828 				/*
    829 				**	Try to put the object back down
    830 				*/
    831 				if (occupier->Can_Enter_Cell(Coord_Cell(obj_coord)) != MOVE_OK) {
    832 					okflag = false;
    833 				}
    834 
    835 				/*
    836 				**	Put everything back the way it was
    837 				*/
    838 				(*this)[template_cell].TType = save_ttype;
    839 				(*this)[template_cell].TIcon = save_ticon;
    840 				(*this)[template_cell].Recalc_Attributes();
    841 
    842 				/*
    843 				**	Major error if can't replace the object now
    844 				*/
    845 				occupier->Mark(MARK_DOWN);
    846 			}
    847 			occupy++;
    848 		}
    849 
    850 		/*
    851 		**	If it's still OK after ALL THAT, place the template
    852 		*/
    853 		if (okflag) {
    854 			if (PendingObjectPtr->Unlimbo(Cell_Coord(ZoneCell + ZoneOffset))) {
    855 
    856 				/*
    857 				**	Loop through all cells occupied by this template, and clear the
    858 				**	smudge & overlay.
    859 				*/
    860 				occupy = PendingObject->Occupy_List();
    861 				while ((*occupy) != REFRESH_EOL) {
    862 
    863 					/*
    864 					**	Get cell for this occupy item
    865 					*/
    866 					template_cell = (ZoneCell+ZoneOffset) + (*occupy);
    867 
    868 					/*
    869 					**	Clear smudge & overlay
    870 					*/
    871 					(*this)[template_cell].Overlay = OVERLAY_NONE;
    872 					(*this)[template_cell].OverlayData = 0;
    873 					(*this)[template_cell].Smudge = SMUDGE_NONE;
    874 
    875 					/*
    876 					**	make adjacent cells recalc attrib's
    877 					*/
    878 					(*this)[template_cell].Recalc_Attributes();
    879 					(*this)[template_cell].Wall_Update();
    880 					(*this)[template_cell].Concrete_Calc();
    881 
    882 					occupy++;
    883 				}
    884 
    885 				/*
    886 				**	Set flags etc
    887 				*/
    888 				PendingObjectPtr = 0;
    889 				PendingObject = 0;
    890 				PendingHouse = HOUSE_NONE;
    891 				Set_Cursor_Shape(0);
    892 				//ScenarioInit--;
    893 				TotalValue = Overpass();
    894 				Flag_To_Redraw(false);
    895 				return(0);
    896 			}
    897 
    898 			/*
    899 			**	Failure to deploy results in a returned failure code.
    900 			*/
    901 			//ScenarioInit--;
    902 			return(-1);
    903 		}
    904 
    905 		/*
    906 		**	Not OK; return error
    907 		*/
    908 		//ScenarioInit--;
    909 		return(-1);
    910 	}
    911 
    912 	/*
    913 	**	Placing infantry: Infantry can go into cell sub-positions, so find the
    914 	**	sub-position closest to the mouse & put him there
    915 	*/
    916 	if (PendingObject->What_Am_I() == RTTI_INFANTRYTYPE) {
    917 
    918 		/*
    919 		**	Find cell sub-position
    920 		*/
    921 		if (Is_Spot_Free(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()))) {
    922 			obj_coord = Closest_Free_Spot(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()));
    923 		} else {
    924 			obj_coord = NULL;
    925 		}
    926 
    927 		/*
    928 		**	No free spots; don't place the object
    929 		*/
    930 		if (obj_coord == NULL) {
    931 			//ScenarioInit--;
    932 			return(-1);
    933 		}
    934 
    935 		/*
    936 		**	Unlimbo the object
    937 		*/
    938 		if (PendingObjectPtr->Unlimbo(obj_coord)) {
    939 			((InfantryClass *)PendingObjectPtr)->Set_Occupy_Bit(obj_coord);
    940 //			Map[obj_coord].Flag.Composite |=
    941 //				(1 << CellClass::Spot_Index(obj_coord));
    942 			PendingObjectPtr = 0;
    943 			PendingObject = 0;
    944 			PendingHouse = HOUSE_NONE;
    945 			Set_Cursor_Shape(0);
    946 			//ScenarioInit--;
    947 			return(0);
    948 		}
    949 
    950 		//ScenarioInit--;
    951 		return(-1);
    952 	}
    953 
    954 	/*
    955 	**	Placing an object
    956 	*/
    957 	if (PendingObjectPtr->Unlimbo(Cell_Coord(ZoneCell + ZoneOffset))) {
    958 
    959 		/*
    960 		** Update the Tiberium computation if we're placing an overlay
    961 		*/
    962 		if (PendingObject->What_Am_I() == RTTI_OVERLAYTYPE &&
    963 			((OverlayTypeClass *)PendingObject)->IsTiberium) {
    964 			TotalValue = Overpass();
    965 			Flag_To_Redraw(false);
    966 		}
    967 
    968 		/*
    969 		** If we're building a base, add this building to the base's Node list.
    970 		*/
    971 		if (BaseBuilding && PendingObject->What_Am_I() == RTTI_BUILDINGTYPE) {
    972 //			node.Type = ((BuildingTypeClass *)PendingObject)->Type;
    973 //			node.Cell = Coord_Cell(PendingObjectPtr->Coord);
    974 			Base.Nodes.Add(BaseNodeClass(((BuildingTypeClass *)PendingObject)->Type, Coord_Cell(PendingObjectPtr->Coord)));
    975 		}
    976 
    977 		PendingObjectPtr = 0;
    978 		PendingObject = 0;
    979 		PendingHouse = HOUSE_NONE;
    980 		Set_Cursor_Shape(0);
    981 		//ScenarioInit--;
    982 		return(0);
    983 	}
    984 
    985 	return(-1);
    986 }
    987 
    988 
    989 /***************************************************************************
    990  * MapEditClass::Cancel_Placement -- cancels placement mode                *
    991  *                                                                         *
    992  * INPUT:                                                                  *
    993  *      none.                                                              *
    994  *                                                                         *
    995  * OUTPUT:                                                                 *
    996  *      none.                                                              *
    997  *                                                                         *
    998  * WARNINGS:                                                               *
    999  *      none.                                                              *
   1000  *                                                                         *
   1001  * HISTORY:                                                                *
   1002  *   11/04/1994 BR : Created.                                              *
   1003  *=========================================================================*/
   1004 void MapEditClass::Cancel_Placement(void)
   1005 {
   1006 	/*
   1007 	**	Delete the placement object
   1008 	*/
   1009 	delete PendingObjectPtr;
   1010 	PendingObject = 0;
   1011 	PendingObjectPtr = 0;
   1012 	PendingHouse = HOUSE_NONE;
   1013 
   1014 	/*
   1015 	**	Restore cursor shape
   1016 	*/
   1017 	Set_Cursor_Shape(0);
   1018 
   1019 	/*
   1020 	**	Redraw the map to erase old leftovers
   1021 	*/
   1022 	HidPage.Clear();
   1023 	Flag_To_Redraw(true);
   1024 	Render();
   1025 }
   1026 
   1027 
   1028 /***************************************************************************
   1029  * MapEditClass::Place_Next -- while placing object, goes to next          *
   1030  *                                                                         *
   1031  * - Deletes the current 'PendingObjectPtr'                                *
   1032  * - Increments LastChoice                                                 *
   1033  * - Tries to create a new 'PendingObjectPtr'; if fails, keeps             *
   1034  *   incrementing until it gets it                                         *
   1035  *                                                                         *
   1036  * INPUT:                                                                  *
   1037  *      none.                                                              *
   1038  *                                                                         *
   1039  * OUTPUT:                                                                 *
   1040  *      none.                                                              *
   1041  *                                                                         *
   1042  * WARNINGS:                                                               *
   1043  *      none.                                                              *
   1044  *                                                                         *
   1045  * HISTORY:                                                                *
   1046  *   11/03/1994 BR : Created.                                              *
   1047  *=========================================================================*/
   1048 void MapEditClass::Place_Next(void)
   1049 {
   1050 	delete PendingObjectPtr;
   1051 	PendingObjectPtr = NULL;
   1052 	PendingObject = NULL;
   1053 
   1054 	/*
   1055 	**	Loop until we create a valid object
   1056 	*/
   1057 	while (!PendingObjectPtr) {
   1058 		/*
   1059 		**	Go to next object in Objects list
   1060 		*/
   1061 		LastChoice++;
   1062 		if (LastChoice == ObjCount) {
   1063 
   1064 			/*
   1065 			** If we're in normal placement mode, wrap to the 1st object;
   1066 			** if we're in base-building mode, wrap to the 1st building
   1067 			*/
   1068 			if (!BaseBuilding) {
   1069 				LastChoice = 0;
   1070 			} else {
   1071 				LastChoice = TypeOffset[7];
   1072 			}
   1073 		}
   1074 
   1075 		/*
   1076 		**	Create placement object
   1077 		*/
   1078 		PendingObject = Objects[LastChoice];
   1079 		PendingHouse = LastHouse;
   1080 		PendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));
   1081 		if (!PendingObjectPtr) {
   1082 			PendingObject = NULL;
   1083 		}
   1084 	}
   1085 
   1086 	/*
   1087 	**	Set the new cursor shape
   1088 	*/
   1089 	Set_Cursor_Pos();
   1090 	Set_Cursor_Shape(0);
   1091 	Set_Cursor_Shape(PendingObject->Occupy_List());
   1092 
   1093 	/*
   1094 	**	Redraw the map to erase old leftovers
   1095 	*/
   1096 	HidPage.Clear();
   1097 	Flag_To_Redraw(true);
   1098 	Render();
   1099 }
   1100 
   1101 
   1102 /***************************************************************************
   1103  * MapEditClass::Place_Prev -- while placing object, goes to previous      *
   1104  *                                                                         *
   1105  * - Deletes the current 'PendingObjectPtr'                                *
   1106  * - Decrements LastChoice                                                 *
   1107  * - Tries to create a new 'PendingObjectPtr'; if fails, keeps             *
   1108  *   decrementing until it gets it                                         *
   1109  *                                                                         *
   1110  * INPUT:                                                                  *
   1111  *      none.                                                              *
   1112  *                                                                         *
   1113  * OUTPUT:                                                                 *
   1114  *      none.                                                              *
   1115  *                                                                         *
   1116  * WARNINGS:                                                               *
   1117  *      none.                                                              *
   1118  *                                                                         *
   1119  * HISTORY:                                                                *
   1120  *   11/03/1994 BR : Created.                                              *
   1121  *=========================================================================*/
   1122 void MapEditClass::Place_Prev(void)
   1123 {
   1124 	delete PendingObjectPtr;
   1125 	PendingObjectPtr = NULL;
   1126 	PendingObject = NULL;
   1127 
   1128 	/*
   1129 	**	Loop until we create a valid object
   1130 	*/
   1131 	while (!PendingObjectPtr) {
   1132 
   1133 		/*
   1134 		**	Go to prev object in Objects list
   1135 		*/
   1136 		LastChoice--;
   1137 
   1138 		/*
   1139 		** If we're in normal placement mode, wrap at the 1st object.
   1140 		** If we're building a base, wrap at the 1st building.
   1141 		*/
   1142 		if (!BaseBuilding) {
   1143 			if (LastChoice < 0) {
   1144 				LastChoice = ObjCount - 1;
   1145 			}
   1146 		} else {
   1147 			if (LastChoice < TypeOffset[7]) {
   1148 				LastChoice = ObjCount - 1;
   1149 			}
   1150 		}
   1151 
   1152 		/*
   1153 		**	Create placement object
   1154 		*/
   1155 		PendingObject = Objects[LastChoice];
   1156 		PendingHouse = LastHouse;
   1157 		PendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));
   1158 		if (!PendingObjectPtr) {
   1159 			PendingObject = NULL;
   1160 		}
   1161 	}
   1162 
   1163 	/*
   1164 	**	Set the new cursor shape
   1165 	*/
   1166 	Set_Cursor_Pos();
   1167 	Set_Cursor_Shape(0);
   1168 	Set_Cursor_Shape(PendingObject->Occupy_List());
   1169 
   1170 	/*
   1171 	**	Redraw the map to erase old leftovers
   1172 	*/
   1173 	HidPage.Clear();
   1174 	Flag_To_Redraw(true);
   1175 	Render();
   1176 }
   1177 
   1178 
   1179 /***************************************************************************
   1180  * MapEditClass::Place_Next_Category -- places next category of object     *
   1181  *                                                                         *
   1182  * INPUT:                                                                  *
   1183  *      none.                                                              *
   1184  *                                                                         *
   1185  * OUTPUT:                                                                 *
   1186  *      none.                                                              *
   1187  *                                                                         *
   1188  * WARNINGS:                                                               *
   1189  *      none.                                                              *
   1190  *                                                                         *
   1191  * HISTORY:                                                                *
   1192  *   11/03/1994 BR : Created.                                              *
   1193  *=========================================================================*/
   1194 void MapEditClass::Place_Next_Category(void)
   1195 {
   1196 	int i;
   1197 
   1198 	/*
   1199 	** Don't allow this command if we're building a base; the only valid
   1200 	** category for base-building is buildings.
   1201 	*/
   1202 	if (BaseBuilding) {
   1203 		return;
   1204 	}
   1205 
   1206 	delete PendingObjectPtr;
   1207 	PendingObjectPtr = NULL;
   1208 	PendingObject = NULL;
   1209 
   1210 	/*
   1211 	**	Go to next category in Objects list
   1212 	*/
   1213 	i = LastChoice;
   1214 	while (Objects[i]->What_Am_I() == Objects[LastChoice]->What_Am_I()) {
   1215 		i++;
   1216 		if (i == ObjCount) {
   1217 			i = 0;
   1218 		}
   1219 	}
   1220 	LastChoice = i;
   1221 
   1222 	/*
   1223 	**	Loop until we create a valid object
   1224 	*/
   1225 	while (!PendingObjectPtr) {
   1226 
   1227 		/*
   1228 		**	Get house for this object type
   1229 		*/
   1230 //		if (!Verify_House(LastHouse, Objects[LastChoice])) {
   1231 //			LastHouse = Cycle_House(LastHouse, Objects[LastChoice]);
   1232 //		}
   1233 
   1234 		/*
   1235 		**	Create placement object
   1236 		*/
   1237 		PendingObject = Objects[LastChoice];
   1238 		PendingHouse = LastHouse;
   1239 		PendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));
   1240 
   1241 		/*
   1242 		**	If this one failed, try the next
   1243 		*/
   1244 		if (!PendingObjectPtr) {
   1245 			PendingObject = NULL;
   1246 			LastChoice++;
   1247 			if (LastChoice == ObjCount) {
   1248 				LastChoice = 0;
   1249 			}
   1250 		}
   1251 	}
   1252 
   1253 	/*
   1254 	**	Set the new cursor shape
   1255 	*/
   1256 	Set_Cursor_Pos();
   1257 	Set_Cursor_Shape(0);
   1258 	Set_Cursor_Shape(PendingObject->Occupy_List());
   1259 
   1260 	/*
   1261 	**	Redraw the map to erase old leftovers
   1262 	*/
   1263 	HidPage.Clear();
   1264 	Flag_To_Redraw(true);
   1265 	Render();
   1266 }
   1267 
   1268 
   1269 /***************************************************************************
   1270  * MapEditClass::Place_Prev_Category -- places previous category of object *
   1271  *                                                                         *
   1272  * INPUT:                                                                  *
   1273  *      none.                                                              *
   1274  *                                                                         *
   1275  * OUTPUT:                                                                 *
   1276  *      none.                                                              *
   1277  *                                                                         *
   1278  * WARNINGS:                                                               *
   1279  *      none.                                                              *
   1280  *                                                                         *
   1281  * HISTORY:                                                                *
   1282  *   11/03/1994 BR : Created.                                              *
   1283  *=========================================================================*/
   1284 void MapEditClass::Place_Prev_Category(void)
   1285 {
   1286 	int i;
   1287 
   1288 	/*
   1289 	** Don't allow this command if we're building a base; the only valid
   1290 	** category for base-building is buildings.
   1291 	*/
   1292 	if (BaseBuilding) {
   1293 		return;
   1294 	}
   1295 
   1296 	delete PendingObjectPtr;
   1297 	PendingObjectPtr = NULL;
   1298 	PendingObject = NULL;
   1299 
   1300 	/*
   1301 	**	Go to prev category in Objects list
   1302 	*/
   1303 	i = LastChoice;
   1304 
   1305 	/*
   1306 	**	Scan for start of this category
   1307 	*/
   1308 	while (Objects[i]->What_Am_I() == Objects[LastChoice]->What_Am_I()) {
   1309 		i--;
   1310 		if (i < 0) {
   1311 			i = ObjCount - 1;
   1312 		}
   1313 	}
   1314 
   1315 	i--;
   1316 	if (i < 0) i = ObjCount-1;
   1317 	LastChoice = i;
   1318 
   1319 	/*
   1320 	**	Scan for the previous category
   1321 	*/
   1322 	while (Objects[i]->What_Am_I() == Objects[LastChoice]->What_Am_I()) {
   1323 		i--;
   1324 		if (i < 0) {
   1325 			i = ObjCount - 1;
   1326 		}
   1327 	}
   1328 
   1329 	i++;
   1330 	if (i >= ObjCount) i = 0;
   1331 	LastChoice = i;
   1332 
   1333 	/*
   1334 	**	Loop until we create a valid object
   1335 	*/
   1336 	while (!PendingObjectPtr) {
   1337 
   1338 		/*
   1339 		**	Get house for this object type
   1340 		*/
   1341 //		if (!Verify_House(LastHouse, Objects[LastChoice])) {
   1342 //			LastHouse = Cycle_House(LastHouse, Objects[LastChoice]);
   1343 //		}
   1344 
   1345 		/*
   1346 		**	Create placement object
   1347 		*/
   1348 		PendingObject = Objects[LastChoice];
   1349 		PendingHouse = LastHouse;
   1350 		PendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));
   1351 
   1352 		/*
   1353 		**	If this one failed, try the next
   1354 		*/
   1355 		if (!PendingObjectPtr) {
   1356 			PendingObject = NULL;
   1357 			LastChoice--;
   1358 			if (LastChoice < 0) {
   1359 				LastChoice = ObjCount - 1;
   1360 			}
   1361 		}
   1362 	}
   1363 
   1364 	/*
   1365 	**	Set the new cursor shape
   1366 	*/
   1367 	Set_Cursor_Pos();
   1368 	Set_Cursor_Shape(0);
   1369 	Set_Cursor_Shape(PendingObject->Occupy_List());
   1370 
   1371 	/*
   1372 	**	Redraw the map to erase old leftovers
   1373 	*/
   1374 	HidPage.Clear();
   1375 	Flag_To_Redraw(true);
   1376 	Render();
   1377 }
   1378 
   1379 
   1380 /***************************************************************************
   1381  * MapEditClass::Place_Home -- homes the placement object                  *
   1382  *                                                                         *
   1383  * INPUT:                                                                  *
   1384  *      none.                                                              *
   1385  *                                                                         *
   1386  * OUTPUT:                                                                 *
   1387  *      none.                                                              *
   1388  *                                                                         *
   1389  * WARNINGS:                                                               *
   1390  *      none.                                                              *
   1391  *                                                                         *
   1392  * HISTORY:                                                                *
   1393  *   11/03/1994 BR : Created.                                              *
   1394  *=========================================================================*/
   1395 void MapEditClass::Place_Home(void)
   1396 {
   1397 	delete PendingObjectPtr;
   1398 	PendingObjectPtr = NULL;
   1399 	PendingObject = NULL;
   1400 
   1401 	/*
   1402 	** Don't allow this command if we're building a base; the only valid
   1403 	** category for base-building is buildings.
   1404 	*/
   1405 	if (BaseBuilding) {
   1406 		return;
   1407 	}
   1408 
   1409 	/*
   1410 	**	Loop until we create a valid object
   1411 	*/
   1412 	LastChoice = 0;
   1413 	while (!PendingObjectPtr) {
   1414 
   1415 		/*
   1416 		**	Get house for this object type
   1417 		*/
   1418 		if (!Verify_House(LastHouse, Objects[LastChoice])) {
   1419 			LastHouse = Cycle_House(LastHouse, Objects[LastChoice]);
   1420 		}
   1421 
   1422 		/*
   1423 		**	Create placement object
   1424 		*/
   1425 		PendingObject = Objects[LastChoice];
   1426 		PendingHouse = LastHouse;
   1427 		PendingObjectPtr = PendingObject->Create_One_Of(HouseClass::As_Pointer(PendingHouse));
   1428 
   1429 		/*
   1430 		**	If this one failed, try the next
   1431 		*/
   1432 		if (!PendingObjectPtr) {
   1433 			PendingObject = NULL;
   1434 			LastChoice++;
   1435 			if (LastChoice == ObjCount) {
   1436 				LastChoice = 0;
   1437 			}
   1438 		}
   1439 	}
   1440 
   1441 	/*
   1442 	**	Set the new cursor shape
   1443 	*/
   1444 	Set_Cursor_Pos();
   1445 	Set_Cursor_Shape(0);
   1446 	Set_Cursor_Shape(PendingObject->Occupy_List());
   1447 
   1448 	/*
   1449 	**	Redraw the map to erase old leftovers
   1450 	*/
   1451 	HidPage.Clear();
   1452 	Flag_To_Redraw(true);
   1453 	Render();
   1454 }
   1455 
   1456 
   1457 /***************************************************************************
   1458  * MapEditClass::Toggle_House -- toggles current placement object's house  *
   1459  *                                                                         *
   1460  * INPUT:                                                                  *
   1461  *                                                                         *
   1462  * OUTPUT:                                                                 *
   1463  *                                                                         *
   1464  * WARNINGS:                                                               *
   1465  *                                                                         *
   1466  * HISTORY:                                                                *
   1467  *   11/04/1994 BR : Created.                                              *
   1468  *=========================================================================*/
   1469 void MapEditClass::Toggle_House(void)
   1470 {
   1471 	TechnoClass *tp;
   1472 
   1473 	/*
   1474 	** Don't allow this command if we're building a base; the only valid
   1475 	** house for base-building is the one assigned to the base.
   1476 	*/
   1477 	if (BaseBuilding) {
   1478 		return;
   1479 	}
   1480 
   1481 	/*
   1482 	**	Only techno objects can be owned by a house; return if not a techno
   1483 	*/
   1484 	if (!PendingObjectPtr->Is_Techno()) {
   1485 		return;
   1486 	}
   1487 
   1488 	/*
   1489 	**	Select the house that will own this object
   1490 	*/
   1491 	LastHouse = Cycle_House(PendingObjectPtr->Owner(), PendingObject);
   1492 
   1493 	/*
   1494 	**	Change the house
   1495 	*/
   1496 	tp = (TechnoClass *)PendingObjectPtr;
   1497 	tp->House = HouseClass::As_Pointer(LastHouse);
   1498 
   1499 	/*
   1500 	**	Set house variables to new house
   1501 	*/
   1502 	PendingHouse = LastHouse;
   1503 }
   1504 
   1505 
   1506 /***************************************************************************
   1507  * MapEditClass::Set_House_Buttons -- toggles house buttons for btn list   *
   1508  *                                                                         *
   1509  * Looks in the given button list for the given GDI, NOD & Neutral button  *
   1510  * id's. Sets the On/Off state of the buttons based on the given house,    *
   1511  * only if that button is found in the list.                               *
   1512  *                                                                         *
   1513  * INPUT:                                                                  *
   1514  *      house            house to set buttons to                           *
   1515  *      btnlist         ptr to button list to search                       *
   1516  *      base_id         button ID for GDI; assumes other id's are sequential*
   1517  *                                                                         *
   1518  * OUTPUT:                                                                 *
   1519  *      none.                                                              *
   1520  *                                                                         *
   1521  * WARNINGS:                                                               *
   1522  *      none.                                                              *
   1523  *                                                                         *
   1524  * HISTORY:                                                                *
   1525  *   11/23/1994 BR : Created.                                              *
   1526  *   01/26/1996 JLB : Uses new house selection list method.                *
   1527  *=========================================================================*/
   1528 void MapEditClass::Set_House_Buttons(HousesType house, GadgetClass *, int )
   1529 //void MapEditClass::Set_House_Buttons(HousesType house, GadgetClass * btnlist, int base_id)
   1530 {
   1531 	HouseList->Set_Selected_Index(house);
   1532 
   1533 #ifdef NEVER
   1534 	HousesType h;
   1535 	int id;
   1536 	TextButtonClass * btn;
   1537 
   1538 	/*
   1539 	**	Loop through all houses, searching the button list for each one.
   1540 	*/
   1541 	for (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {
   1542 
   1543 		/*
   1544 		**	Compute the desired button ID; get a pointer to the button
   1545 		*/
   1546 		id = (int)h + base_id;
   1547 		btn = (TextButtonClass *)btnlist->Extract_Gadget(id);
   1548 		if (btn) {
   1549 
   1550 			/*
   1551 			**	If this house value is the desired one, turn the button on;
   1552 			**	otherwise, turn it off.
   1553 			*/
   1554 			if (h == house) {
   1555 				btn->Turn_On();
   1556 			} else {
   1557 				btn->Turn_Off();
   1558 			}
   1559 		}
   1560 	}
   1561 #endif
   1562 }
   1563 
   1564 
   1565 /***************************************************************************
   1566  * MapEditClass::Start_Trigger_Placement -- enters trigger placement mode  *
   1567  *                                                                         *
   1568  * INPUT:                                                                  *
   1569  *                                                                         *
   1570  * OUTPUT:                                                                 *
   1571  *                                                                         *
   1572  * WARNINGS:                                                               *
   1573  *                                                                         *
   1574  * HISTORY:                                                                *
   1575  *   12/01/1994 BR : Created.                                              *
   1576  *=========================================================================*/
   1577 void MapEditClass::Start_Trigger_Placement(void)
   1578 {
   1579 	Set_Default_Mouse(MOUSE_CAN_MOVE);
   1580 	Override_Mouse_Shape(MOUSE_CAN_MOVE);
   1581 }
   1582 
   1583 
   1584 /***************************************************************************
   1585  * MapEditClass::Stop_Trigger_Placement -- exits trigger placement mode    *
   1586  *                                                                         *
   1587  * INPUT:                                                                  *
   1588  *      none.                                                              *
   1589  *                                                                         *
   1590  * OUTPUT:                                                                 *
   1591  *      none.                                                              *
   1592  *                                                                         *
   1593  * WARNINGS:                                                               *
   1594  *      none.                                                              *
   1595  *                                                                         *
   1596  * HISTORY:                                                                *
   1597  *   12/01/1994 BR : Created.                                              *
   1598  *=========================================================================*/
   1599 void MapEditClass::Stop_Trigger_Placement(void)
   1600 {
   1601 	CurTrigger = NULL;
   1602 	Set_Default_Mouse(MOUSE_NORMAL);
   1603 	Override_Mouse_Shape(MOUSE_NORMAL);
   1604 }
   1605 
   1606 
   1607 /***************************************************************************
   1608  * MapEditClass::Place_Trigger -- assigns trigger to object or cell        *
   1609  *                                                                         *
   1610  * INPUT:                                                                  *
   1611  *      none.                                                              *
   1612  *                                                                         *
   1613  * OUTPUT:                                                                 *
   1614  *      none.                                                              *
   1615  *                                                                         *
   1616  * WARNINGS:                                                               *
   1617  *      none.                                                              *
   1618  *                                                                         *
   1619  * HISTORY:                                                                *
   1620  *   12/01/1994 BR : Created.                                              *
   1621  *=========================================================================*/
   1622 void MapEditClass::Place_Trigger(void)
   1623 {
   1624 	ObjectClass * object=NULL;		// Generic object clicked on.
   1625 	int x,y;
   1626 	CELL cell;									// Cell that was selected.
   1627 
   1628 	/*
   1629 	**	See if an object was clicked on
   1630 	*/
   1631 	x = Keyboard->MouseQX;
   1632 	y = Keyboard->MouseQY;
   1633 
   1634 	/*
   1635 	**	Get cell for x,y
   1636 	*/
   1637 	cell = Click_Cell_Calc(x, y);
   1638 
   1639 	/*
   1640 	**	Convert x,y to offset from cell upper-left
   1641 	*/
   1642 	x = (x-TacPixelX) % ICON_PIXEL_W;
   1643 	y = (y-TacPixelY) % ICON_PIXEL_H;
   1644 
   1645 	/*
   1646 	**	Get object at that x,y
   1647 	*/
   1648 	object = Cell_Object(cell, x, y);
   1649 
   1650 	/*
   1651 	**	Assign trigger to an object
   1652 	*/
   1653 	AttachType a1 = CurTrigger->Attaches_To();
   1654 	if (object && (a1 & ATTACH_OBJECT) != 0) {
   1655 		if (CurTrigger) {
   1656 			TriggerClass * tt = Find_Or_Make(CurTrigger);
   1657 			if (tt) {
   1658 				object->Trigger = tt;
   1659 			}
   1660 		}
   1661 	} else {
   1662 
   1663 		/*
   1664 		**	Assign trigger to a cell
   1665 		*/
   1666 		if ((a1 & ATTACH_CELL) != 0) {
   1667 			if (CurTrigger) {
   1668 				TriggerClass * tt = Find_Or_Make(CurTrigger);
   1669 				Map[cell].Trigger = tt;
   1670 			}
   1671 //			CellTriggers[cell] = CurTrigger;
   1672 		}
   1673 	}
   1674 
   1675 	/*
   1676 	**	Force map to redraw
   1677 	*/
   1678 	HidPage.Clear();
   1679 	Flag_To_Redraw(true);
   1680 }
   1681 
   1682 
   1683 /***************************************************************************
   1684  * MapEditClass::Start_Base_Building -- starts base-building mode          *
   1685  *                                                                         *
   1686  * INPUT:                                                                  *
   1687  *      none.                                                              *
   1688  *                                                                         *
   1689  * OUTPUT:                                                                 *
   1690  *      none.                                                              *
   1691  *                                                                         *
   1692  * WARNINGS:                                                               *
   1693  *      none.                                                              *
   1694  *                                                                         *
   1695  * HISTORY:                                                                *
   1696  *   12/01/1994 BR : Created.                                              *
   1697  *=========================================================================*/
   1698 void MapEditClass::Start_Base_Building(void)
   1699 {
   1700 	/*
   1701 	** Fully build the base so the user can edit it
   1702 	*/
   1703 	Build_Base_To(100);
   1704 
   1705 	/*
   1706 	** Start placement mode
   1707 	*/
   1708 	BaseBuilding = true;
   1709 	Start_Placement();
   1710 
   1711 	/*
   1712 	** Force map to redraw
   1713 	*/
   1714 	HidPage.Clear();
   1715 	Flag_To_Redraw(true);
   1716 }
   1717 
   1718 
   1719 /***************************************************************************
   1720  * MapEditClass::Cancel_Base_Building -- stops base-building mode          *
   1721  *                                                                         *
   1722  * INPUT:                                                                  *
   1723  *      none.                                                              *
   1724  *                                                                         *
   1725  * OUTPUT:                                                                 *
   1726  *      none.                                                              *
   1727  *                                                                         *
   1728  * WARNINGS:                                                               *
   1729  *      none.                                                              *
   1730  *                                                                         *
   1731  * HISTORY:                                                                *
   1732  *   12/01/1994 BR : Created.                                              *
   1733  *=========================================================================*/
   1734 void MapEditClass::Cancel_Base_Building(void)
   1735 {
   1736 	/*
   1737 	** Build the base to the proper amount
   1738 	*/
   1739 	Build_Base_To(Scen.Percent);
   1740 
   1741 	/*
   1742 	** Cancel placement mode
   1743 	*/
   1744 	Cancel_Placement();
   1745 	BaseBuilding = false;
   1746 
   1747 	/*
   1748 	** Force map to redraw
   1749 	*/
   1750 	HidPage.Clear();
   1751 	Flag_To_Redraw(true);
   1752 }
   1753 
   1754 
   1755 /***************************************************************************
   1756  * MapEditClass::Build_Base_To -- builds the AI base to the given percent  *
   1757  *                                                                         *
   1758  * INPUT:                                                                  *
   1759  *      percent      percentage to build base to                           *
   1760  *                                                                         *
   1761  * OUTPUT:                                                                 *
   1762  *      none.                                                              *
   1763  *                                                                         *
   1764  * WARNINGS:                                                               *
   1765  *      none.                                                              *
   1766  *                                                                         *
   1767  * HISTORY:                                                                *
   1768  *   12/01/1994 BR : Created.                                              *
   1769  *=========================================================================*/
   1770 void MapEditClass::Build_Base_To(int percent)
   1771 {
   1772 	int i;
   1773 	int num_buildings;
   1774 	BuildingTypeClass const * objtype;
   1775 	BuildingClass * obj;
   1776 
   1777 	//ScenarioInit++;
   1778 
   1779 	/*
   1780 	** Completely dismantle the base, so we start at a known point
   1781 	*/
   1782 	for (i = 0; i < Base.Nodes.Count(); i++) {
   1783 		if (Base.Is_Built(i)) {
   1784 			obj = Base.Get_Building(i);
   1785 			delete obj;
   1786 		}
   1787 	}
   1788 
   1789 	/*
   1790 	** Compute number of buildings to build
   1791 	*/
   1792 	num_buildings = (Base.Nodes.Count() * percent) / 100;
   1793 
   1794 	/*
   1795 	** Build the base to the desired amount
   1796 	*/
   1797 	for (i = 0; i < num_buildings; i++) {
   1798 		/*
   1799 		** Get a ptr to the type of building to build, create one, and unlimbo it.
   1800 		*/
   1801 		objtype = &BuildingTypeClass::As_Reference(Base.Nodes[i].Type);
   1802 		obj = (BuildingClass *)objtype->Create_One_Of(HouseClass::As_Pointer(Base.House));
   1803 
   1804 		/*
   1805 		** If unlimbo fails, error out
   1806 		*/
   1807 		ScenarioInit++;
   1808 		if (!obj->Unlimbo(Cell_Coord(Base.Nodes[i].Cell))) {
   1809 			delete obj;
   1810 			WWMessageBox().Process("Unable to build base!");
   1811 			ScenarioInit--;
   1812 			return;
   1813 		}
   1814 		ScenarioInit--;
   1815 	}
   1816 
   1817 	//ScenarioInit--;
   1818 }
   1819 
   1820 
   1821 #endif