CnC_Remastered_Collection

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

MAPEDSEL.CPP (23372B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\mapedsel.cpv   2.18   16 Oct 1995 16:49:58   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 : MAPEDSEL.CPP                             *
     24  *                                                                         *
     25  *                   Programmer : Bill Randolph                            *
     26  *                                                                         *
     27  *                   Start Date : November 18, 1994                        *
     28  *                                                                         *
     29  *                  Last Update : February 2, 1995   [BR]                  *
     30  *                                                                         *
     31  *-------------------------------------------------------------------------*
     32  * Object-selection & manipulation routines                                *
     33  *-------------------------------------------------------------------------*
     34  * Functions:                                                              *
     35  *   MapEditClass::Select_Object -- selects an object for processing       *
     36  *   MapEditClass::Select_Next -- selects next object on the map           *
     37  *   MapEditClass::Popup_Controls -- shows/hides the pop-up object controls*
     38  *   MapEditClass::Grab_Object -- grabs the current object                 *
     39  *   MapEditClass::Move_Grabbed_Object -- moves the grabbed object         *
     40  *   MapEditClass::Change_House -- changes CurrentObject's house           *
     41  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     42 
     43 #include	"function.h"
     44 
     45 #ifdef SCENARIO_EDITOR
     46 
     47 
     48 /***************************************************************************
     49  * Select_Object -- selects an object for processing                       *
     50  *                                                                         *
     51  * INPUT:                                                                  *
     52  *   none.                                                                 *
     53  *                                                                         *
     54  * OUTPUT:                                                                 *
     55  *   0 = object selected, -1 = none                                        *
     56  *                                                                         *
     57  * WARNINGS:                                                               *
     58  *   none.                                                                 *
     59  *                                                                         *
     60  * HISTORY:                                                                *
     61  *   11/04/1994 BR : Created.                                              *
     62  *=========================================================================*/
     63 int MapEditClass::Select_Object(void)
     64 {
     65 	ObjectClass	*object=NULL;		// Generic object clicked on.
     66 	int			x,y;
     67 	CELL			cell;					// Cell that was selected.
     68 	int			rc=0;
     69 
     70 	/*
     71 	-------------------- See if an object was clicked on ---------------------
     72 	*/
     73 	x = _Kbd->MouseQX;
     74 	y = _Kbd->MouseQY;
     75 
     76 	/*
     77 	............................ Get cell for x,y ............................
     78 	*/
     79 	cell = Click_Cell_Calc(x, y);
     80 
     81 	/*
     82 	............... Convert x,y to offset from cell upper-left ...............
     83 	*/
     84 	x = (x-TacPixelX) % ICON_PIXEL_W;
     85 	y = (y-TacPixelY) % ICON_PIXEL_H;
     86 
     87 	/*
     88 	......................... Get object at that x,y .........................
     89 	*/
     90 	object = Cell_Object(cell, x, y);
     91 
     92 	/*
     93 	----------------- If no object, unselect the current one -----------------
     94 	*/
     95 	if (!object) {
     96 		if (CurrentObject.Count()) {
     97 			/*
     98 			................... Unselect all current objects ...................
     99 			*/
    100 			Unselect_All();
    101 
    102 			/*
    103 			..................... Turn off object controls .....................
    104 			*/
    105 			Popup_Controls();
    106 		}
    107 		rc = -1;
    108 	} else {
    109 
    110 		/*
    111 		------------------ Select object only if it's different ------------------
    112 		*/
    113 		if (!CurrentObject.Count() || (CurrentObject.Count() && object != CurrentObject[0])) {
    114 			/*
    115 			..................... Unselect all current objects ....................
    116 			*/
    117 			Unselect_All();
    118 			object->Select();
    119 
    120 			/*
    121 			................... Set mouse shape back to normal ....................
    122 			*/
    123 			Set_Default_Mouse(MOUSE_NORMAL);
    124 			Override_Mouse_Shape(MOUSE_NORMAL);
    125 
    126 			/*
    127 			....................... Show the popup controls .......................
    128 			*/
    129 			Popup_Controls();
    130 		}
    131 	}
    132 
    133 	/*
    134 	-------------------------- Force map to redraw ---------------------------
    135 	*/
    136 	HiddenPage.Clear();
    137 	Flag_To_Redraw(true);
    138 
    139 	return(rc);
    140 }
    141 
    142 
    143 /***************************************************************************
    144  * MapEditClass::Select_Next -- selects next object on the map             *
    145  *                                                                         *
    146  * INPUT:                                                                  *
    147  *   none.                                                                 *
    148  *                                                                         *
    149  * OUTPUT:                                                                 *
    150  *   none                                                                  *
    151  *                                                                         *
    152  * WARNINGS:                                                               *
    153  *   none.                                                                 *
    154  *                                                                         *
    155  * HISTORY:                                                                *
    156  *   11/22/1994 BR : Created.                                              *
    157  *=========================================================================*/
    158 void MapEditClass::Select_Next(void)
    159 {
    160 	ObjectClass * obj;
    161 	CELL obj_cell;
    162 	int smap_w;						// screen map width in icons
    163 	int smap_h;						// screen map height in icons
    164 	int cell_x;						// cell-x of next object
    165 	int cell_y;						// cell-y of next object
    166 	int tcell_x;					// cell-x of TacticalCell
    167 	int tcell_y;					// cell-y of TacticalCell
    168 
    169 	/*
    170 	----------------------- Get next object on the map -----------------------
    171 	*/
    172 	obj = Map.Next_Object(CurrentObject[0]);
    173 
    174 	if (obj) {
    175 		/*
    176 		............... Unselect current object if there is one ...............
    177 		*/
    178 		Unselect_All();
    179 
    180 	 	/*
    181 		......................... Select this object ..........................
    182 		*/
    183 		obj->Select();
    184 	}
    185 
    186 	/*
    187 	--------------------- Restore mouse shape to normal ----------------------
    188 	*/
    189 	Set_Default_Mouse(MOUSE_NORMAL);
    190 	Override_Mouse_Shape(MOUSE_NORMAL);
    191 
    192 	/*
    193 	-------------------------- Show pop-up controls --------------------------
    194 	*/
    195 	Popup_Controls();
    196 
    197 	/*
    198 	---------------- Make sure object is shown on the screen -----------------
    199 	*/
    200 	/*
    201 	..................... compute screen map dimensions ......................
    202 	*/
    203 	smap_w = Lepton_To_Cell(TacLeptonWidth);
    204 	smap_h = Lepton_To_Cell(TacLeptonHeight);
    205 
    206 	/*
    207 	...................... compute x,y of object's cell ......................
    208 	*/
    209 	obj_cell = Coord_Cell(CurrentObject[0]->Coord);
    210 	cell_x = Cell_X(obj_cell);
    211 	cell_y = Cell_Y(obj_cell);
    212 	tcell_x = Coord_XCell(TacticalCoord);
    213 	tcell_y = Coord_YCell(TacticalCoord);
    214 
    215 	/*
    216 	................... If object is off-screen, move map ....................
    217 	*/
    218 	if (cell_x < tcell_x) {
    219 		tcell_x = cell_x;
    220 	} else {
    221 		if (cell_x >= tcell_x + smap_w) {
    222 			tcell_x = cell_x - smap_w + 1;
    223 		}
    224 	}
    225 
    226 	if (cell_y < tcell_y) {
    227 		tcell_y = cell_y;
    228 	} else {
    229 		if (cell_y >= tcell_y + smap_h) {
    230 			tcell_y = cell_y - smap_h + 1;
    231 		}
    232 	}
    233 
    234 	ScenarioInit++;
    235 	Set_Tactical_Position(XY_Coord(Cell_To_Lepton(tcell_x), Cell_To_Lepton(tcell_y)));
    236 	ScenarioInit--;
    237 
    238 	/*
    239 	-------------------------- Force map to redraw ---------------------------
    240 	*/
    241 	HiddenPage.Clear();
    242 	Flag_To_Redraw(true);
    243 }
    244 
    245 
    246 /***************************************************************************
    247  * MapEditClass::Popup_Controls -- shows/hides the pop-up object controls  *
    248  *                                                                         *
    249  * Call this routine whenever the CurrentObject changes. The routine will  *
    250  * selectively enable or disable the popup controls based on whether       *
    251  * CurrentObject is NULL, or if it's a Techno object, or what type of      *
    252  * Techno object it is.                                                    *
    253  *                                                                         *
    254  * INPUT:                                                                  *
    255  *      none.                                                              *
    256  *                                                                         *
    257  * OUTPUT:                                                                 *
    258  *      none.                                                              *
    259  *                                                                         *
    260  * WARNINGS:                                                               *
    261  *      none.                                                              *
    262  *                                                                         *
    263  * HISTORY:                                                                *
    264  *   11/22/1994 BR : Created.                                              *
    265  *=========================================================================*/
    266 void MapEditClass::Popup_Controls(void)
    267 {
    268 	const TechnoTypeClass * objtype = NULL;
    269 	HousesType owner;							// object's current owner
    270 	int mission_index;						// object's current mission
    271 	int strength;								// object's 0-255 strength value
    272 	int i;
    273 
    274 	/*------------------------------------------------------------------------
    275 	Remove all buttons from GScreen's button list (so none of them provide
    276 	input any more); then, destroy the list by Zapping each button.  Then,
    277 	we'll have to add at least the MapArea button back to the Input button
    278 	list before we return, plus any other buttons to process input for.  We
    279 	always must add MapArea LAST in the list, so it doesn't intercept the
    280 	other buttons' input.
    281 	------------------------------------------------------------------------*/
    282 	Remove_A_Button(*GDIButton);
    283 	Remove_A_Button(*NODButton);
    284 	Remove_A_Button(*NeutralButton);
    285 	Remove_A_Button(*Multi1Button);
    286 	Remove_A_Button(*Multi2Button);
    287 	Remove_A_Button(*Multi3Button);
    288 	Remove_A_Button(*Multi4Button);
    289 	Remove_A_Button(*MissionList);
    290 	Remove_A_Button(*HealthGauge);
    291 	Remove_A_Button(*HealthText);
    292 	Remove_A_Button(*FacingDial);
    293 	Remove_A_Button(*BaseGauge);
    294 	Remove_A_Button(*BaseLabel);
    295 	Remove_A_Button(*MapArea);
    296 
    297 	/*
    298 	------------------ If no current object, hide the list -------------------
    299 	*/
    300 	if (!CurrentObject.Count()) {
    301 		Add_A_Button(*BaseGauge);
    302 		Add_A_Button(*BaseLabel);
    303 		Add_A_Button(*MapArea);
    304 		return;
    305 	}
    306 
    307 	/*
    308 	--------------- If not Techno, no need for editing buttons ---------------
    309 	*/
    310 	if (!CurrentObject[0]->Is_Techno()) {
    311 		Add_A_Button(*BaseGauge);
    312 		Add_A_Button(*BaseLabel);
    313 		Add_A_Button(*MapArea);
    314 		return;
    315 	}
    316 
    317 	objtype = (TechnoTypeClass const *)&CurrentObject[0]->Class_Of();
    318 
    319 	/*
    320 	---------------------- Get object's current values -----------------------
    321 	*/
    322 	owner = CurrentObject[0]->Owner();
    323 	mission_index = 0;
    324 	for (i = 0; i < NUM_EDIT_MISSIONS; i++) {
    325 		if (CurrentObject[0]->Get_Mission() == MapEditMissions[i]) {
    326 			mission_index = i;
    327 		}
    328 	}
    329 	strength = CurrentObject[0]->Health_Ratio();
    330 
    331 
    332 	/*
    333 	----------------------------- House buttons ------------------------------
    334 	*/
    335 	if (ScenPlayer == SCEN_PLAYER_MPLAYER) {
    336 		if (Verify_House(HOUSE_NEUTRAL, &CurrentObject[0]->Class_Of())) {
    337 			Add_A_Button(*NeutralButton);
    338 		}
    339 		if (Verify_House(HOUSE_MULTI1, &CurrentObject[0]->Class_Of())) {
    340 			Add_A_Button(*Multi1Button);
    341 		}
    342 		if (Verify_House(HOUSE_MULTI2, &CurrentObject[0]->Class_Of())) {
    343 			Add_A_Button(*Multi2Button);
    344 		}
    345 		if (Verify_House(HOUSE_MULTI3, &CurrentObject[0]->Class_Of())) {
    346 			Add_A_Button(*Multi3Button);
    347 		}
    348 		if (Verify_House(HOUSE_MULTI4, &CurrentObject[0]->Class_Of())) {
    349 			Add_A_Button(*Multi4Button);
    350 		}
    351 	} else {
    352 		if (Verify_House(HOUSE_NEUTRAL, &CurrentObject[0]->Class_Of())) {
    353 			Add_A_Button(*NeutralButton);
    354 		}
    355 		if (Verify_House(HOUSE_BAD, &CurrentObject[0]->Class_Of())) {
    356 			Add_A_Button(*NODButton);
    357 		}
    358 		if (Verify_House(HOUSE_GOOD, &CurrentObject[0]->Class_Of())) {
    359 			Add_A_Button(*GDIButton);
    360 		}
    361 	}
    362 
    363 	/*
    364 	........................ Set house button states .........................
    365 	*/
    366 	if (Buttons) {
    367 		Set_House_Buttons(owner, Buttons, POPUP_GDI);
    368 	}
    369 
    370 	switch (objtype->What_Am_I()) {
    371 		case RTTI_UNITTYPE:
    372 		case RTTI_INFANTRYTYPE:
    373 		case RTTI_AIRCRAFTTYPE:
    374 			MissionList->Set_Selected_Index(mission_index);
    375 			HealthGauge->Set_Value(strength);
    376 			sprintf(HealthBuf, "%d", CurrentObject[0]->Strength);
    377 			FacingDial->Set_Direction(((TechnoClass *)CurrentObject[0])->PrimaryFacing);
    378 
    379 			/*
    380 			**	Make the list.
    381 			*/
    382 			Add_A_Button(*MissionList);
    383 			Add_A_Button(*HealthGauge);
    384 			Add_A_Button(*HealthText);
    385 			Add_A_Button(*FacingDial);
    386 			break;
    387 
    388 		case RTTI_BUILDINGTYPE:
    389 			HealthGauge->Set_Value(strength);
    390 			sprintf(HealthBuf, "%d", CurrentObject[0]->Strength);
    391 			Add_A_Button(*HealthGauge);
    392 			Add_A_Button(*HealthText);
    393 
    394 			if (objtype->IsTurretEquipped) {
    395 				FacingDial->Set_Direction(((TechnoClass *) CurrentObject[0])->PrimaryFacing);
    396 				Add_A_Button(*FacingDial);
    397 			}
    398 			break;
    399 	}
    400 
    401 	/*------------------------------------------------------------------------
    402 	Add the map area last, so it's "underneath" the other buttons, and won't
    403 	intercept input for those buttons.
    404 	------------------------------------------------------------------------*/
    405 	Add_A_Button(*BaseGauge);
    406 	Add_A_Button(*BaseLabel);
    407 	Add_A_Button(*MapArea);
    408 }
    409 
    410 
    411 /***************************************************************************
    412  * MapEditClass::Grab_Object -- grabs the current object                   *
    413  *                                                                         *
    414  * INPUT:                                                                  *
    415  *      none.                                                              *
    416  *                                                                         *
    417  * OUTPUT:                                                                 *
    418  *      none.                                                              *
    419  *                                                                         *
    420  * WARNINGS:                                                               *
    421  *      none.                                                              *
    422  *                                                                         *
    423  * HISTORY:                                                                *
    424  *   11/07/1994 BR : Created.                                              *
    425  *=========================================================================*/
    426 void MapEditClass::Grab_Object(void)
    427 {
    428 	CELL cell;
    429 
    430 	if (CurrentObject.Count()) {
    431 		GrabbedObject = CurrentObject[0];
    432 
    433 		/*------------------------------------------------------------------------
    434 		Find out which cell 'ZoneCell' is in relation to the object's current cell
    435 		------------------------------------------------------------------------*/
    436 		cell = Coord_Cell(GrabbedObject->Coord);
    437 		GrabOffset = cell - ZoneCell;
    438 	}
    439 }
    440 
    441 
    442 /***************************************************************************
    443  * MapEditClass::Move_Grabbed_Object -- moves the grabbed object           *
    444  *                                                                         *
    445  * INPUT:                                                                  *
    446  *      none.                                                              *
    447  *                                                                         *
    448  * OUTPUT:                                                                 *
    449  *      0 = object moved, -1 = it didn't                                   *
    450  *                                                                         *
    451  * WARNINGS:                                                               *
    452  *      none.                                                              *
    453  *                                                                         *
    454  * HISTORY:                                                                *
    455  *   11/07/1994 BR : Created.                                              *
    456  *=========================================================================*/
    457 int MapEditClass::Move_Grabbed_Object(void)
    458 {
    459 	COORDINATE new_coord = 0;
    460 	int retval = -1;
    461 
    462 	/*
    463 	--------------------------- Lift up the object ---------------------------
    464 	*/
    465 	GrabbedObject->Mark(MARK_UP);
    466 
    467 	/*------------------------------------------------------------------------
    468 	If infantry, use a free spot in this cell
    469 	------------------------------------------------------------------------*/
    470 	if (GrabbedObject->Is_Infantry()) {
    471 
    472 		if (Is_Spot_Free(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()))) {
    473 			new_coord = Closest_Free_Spot(Pixel_To_Coord(Get_Mouse_X(),
    474 				Get_Mouse_Y()));
    475 			/*..................................................................
    476 			Clear the occupied bit in this infantry's cell.
    477 			..................................................................*/
    478 			((InfantryClass *)GrabbedObject)->Clear_Occupy_Bit(GrabbedObject->Coord);
    479 //			Map[Coord_Cell(GrabbedObject->Coord)].Flag.Composite &=
    480 //				~(1 << CellClass::Spot_Index(GrabbedObject->Coord));
    481 		} else {
    482 			new_coord = NULL;
    483 		}
    484 
    485 	} else {
    486 
    487 		/*------------------------------------------------------------------------
    488 		Non-infantry: use cell's center coordinate
    489 		------------------------------------------------------------------------*/
    490 		new_coord = Cell_Coord(ZoneCell + GrabOffset);
    491 
    492 		if (GrabbedObject->What_Am_I() == RTTI_BUILDING ||
    493 			GrabbedObject->What_Am_I() == RTTI_TERRAIN) {
    494 
    495 			new_coord &= 0xFF00FF00L;
    496 		}
    497 
    498 		/*
    499 		................ Try to place object at new coordinate ................
    500 		*/
    501 		if (GrabbedObject->Can_Enter_Cell(Coord_Cell(new_coord)) != MOVE_OK) {
    502 			new_coord = NULL;
    503 		}
    504 	}
    505 	if (new_coord != NULL) {
    506 		/*
    507 		** If this object is part of the AI's Base list, change the coordinate
    508 		** in the Base's Node list.
    509 		*/
    510 		if (GrabbedObject->What_Am_I()==RTTI_BUILDING &&
    511 			Base.Get_Node((BuildingClass *)GrabbedObject))
    512 				Base.Get_Node((BuildingClass *)GrabbedObject)->Coord = new_coord;
    513 
    514 		GrabbedObject->Coord = new_coord;
    515 		retval = 0;
    516 	}
    517 	GrabbedObject->Mark(MARK_DOWN);
    518 
    519 	/*------------------------------------------------------------------------
    520 	For infantry, set the bit in its new cell marking that spot as occupied.
    521 	------------------------------------------------------------------------*/
    522 	if (GrabbedObject->Is_Infantry()) {
    523 		((InfantryClass *)GrabbedObject)->Set_Occupy_Bit(new_coord);
    524 //		Map[Coord_Cell(new_coord)].Flag.Composite |=
    525 //			(1 << CellClass::Spot_Index(new_coord));
    526 	}
    527 
    528 	/*------------------------------------------------------------------------
    529 	Re-select the object, and reset the mouse pointer
    530 	------------------------------------------------------------------------*/
    531 	Set_Default_Mouse(MOUSE_NORMAL);
    532 	Override_Mouse_Shape(MOUSE_NORMAL);
    533 
    534 	Flag_To_Redraw(true);
    535 
    536 	return(retval);
    537 }
    538 
    539 
    540 /***************************************************************************
    541  * MapEditClass::Change_House -- changes CurrentObject's house             *
    542  *                                                                         *
    543  * INPUT:                                                                  *
    544  *      newhouse      house to change to                                   *
    545  *                                                                         *
    546  * OUTPUT:                                                                 *
    547  *      1 = house was changed, 0 = it wasn't                               *
    548  *                                                                         *
    549  * WARNINGS:                                                               *
    550  *      none.                                                              *
    551  *                                                                         *
    552  * HISTORY:                                                                *
    553  *   11/17/1994 BR : Created.                                              *
    554  *=========================================================================*/
    555 bool MapEditClass::Change_House(HousesType newhouse)
    556 {
    557 	TechnoClass *tp;
    558 
    559 	/*------------------------------------------------------------------------
    560 	Return if no current object
    561 	------------------------------------------------------------------------*/
    562 	if (!CurrentObject.Count()) {
    563 		return(false);
    564 	}
    565 
    566 	/*------------------------------------------------------------------------
    567 	Only techno objects can be owned by a house; return if not a techno
    568 	------------------------------------------------------------------------*/
    569 	if (!CurrentObject[0]->Is_Techno()) {
    570 		return(false);
    571 	}
    572 
    573 	/*------------------------------------------------------------------------
    574 	You can't change the house if the object is part of the AI's Base.
    575 	------------------------------------------------------------------------*/
    576 	if (CurrentObject[0]->What_Am_I()==RTTI_BUILDING && Base.Is_Node((BuildingClass *)CurrentObject[0])) {
    577 		return(false);
    578 	}
    579 
    580 	/*------------------------------------------------------------------------
    581 	Verify that the target house exists
    582 	------------------------------------------------------------------------*/
    583 	if (HouseClass::As_Pointer(newhouse)==NULL) {
    584 		return(false);
    585 	}
    586 
    587 	/*------------------------------------------------------------------------
    588 	Verify that this is a valid owner
    589 	------------------------------------------------------------------------*/
    590 	if (!Verify_House(newhouse, &CurrentObject[0]->Class_Of())) {
    591 		return(false);
    592 	}
    593 
    594 	/*------------------------------------------------------------------------
    595 	Change the house
    596 	------------------------------------------------------------------------*/
    597 	tp = (TechnoClass *)CurrentObject[0];
    598 	tp->House = HouseClass::As_Pointer(newhouse);
    599 
    600 	return(true);
    601 }
    602 
    603 
    604 #endif