CnC_Remastered_Collection

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

MAPEDSEL.CPP (19526B)


      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/MAPEDSEL.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 : MAPEDSEL.CPP                             *
     24  *                                                                         *
     25  *                   Programmer : Bill Randolph                            *
     26  *                                                                         *
     27  *                   Start Date : November 18, 1994                        *
     28  *                                                                         *
     29  *                  Last Update : April 30, 1996 [JLB]                     *
     30  *                                                                         *
     31  *-------------------------------------------------------------------------*
     32  * Object-selection & manipulation routines                                *
     33  *-------------------------------------------------------------------------*
     34  * Functions:                                                              *
     35  *   MapEditClass::Change_House -- changes CurrentObject's house           *
     36  *   MapEditClass::Grab_Object -- grabs the current object                 *
     37  *   MapEditClass::Move_Grabbed_Object -- moves the grabbed object         *
     38  *   MapEditClass::Popup_Controls -- shows/hides the pop-up object controls*
     39  *   MapEditClass::Select_Next -- selects next object on the map           *
     40  *   MapEditClass::Select_Object -- selects an object for processing       *
     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 = Keyboard->MouseQX;
     74 	y = Keyboard->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 			/*
     99 			**	Unselect all current objects
    100 			*/
    101 			Unselect_All();
    102 
    103 			/*
    104 			**	Turn off object controls
    105 			*/
    106 			Popup_Controls();
    107 		}
    108 		rc = -1;
    109 	} else {
    110 
    111 		/*
    112 		**	Select object only if it's different
    113 		*/
    114 		if (!CurrentObject.Count() || (CurrentObject.Count() && object != CurrentObject[0])) {
    115 
    116 			/*
    117 			**	Unselect all current objects
    118 			*/
    119 			Unselect_All();
    120 			object->Select();
    121 
    122 			/*
    123 			**	Set mouse shape back to normal
    124 			*/
    125 			Set_Default_Mouse(MOUSE_NORMAL);
    126 			Override_Mouse_Shape(MOUSE_NORMAL);
    127 
    128 			/*
    129 			**	Show the popup controls
    130 			*/
    131 			Popup_Controls();
    132 		}
    133 	}
    134 
    135 	/*
    136 	**	Force map to redraw
    137 	*/
    138 	HidPage.Clear();
    139 	Flag_To_Redraw(true);
    140 
    141 	return(rc);
    142 }
    143 
    144 
    145 /***************************************************************************
    146  * MapEditClass::Select_Next -- selects next object on the map             *
    147  *                                                                         *
    148  * INPUT:                                                                  *
    149  *   none.                                                                 *
    150  *                                                                         *
    151  * OUTPUT:                                                                 *
    152  *   none                                                                  *
    153  *                                                                         *
    154  * WARNINGS:                                                               *
    155  *   none.                                                                 *
    156  *                                                                         *
    157  * HISTORY:                                                                *
    158  *   11/22/1994 BR : Created.                                              *
    159  *=========================================================================*/
    160 void MapEditClass::Select_Next(void)
    161 {
    162 	ObjectClass * obj;
    163 	CELL obj_cell;
    164 	int smap_w;						// screen map width in icons
    165 	int smap_h;						// screen map height in icons
    166 	int cell_x;						// cell-x of next object
    167 	int cell_y;						// cell-y of next object
    168 	int tcell_x;					// cell-x of TacticalCell
    169 	int tcell_y;					// cell-y of TacticalCell
    170 
    171 	/*
    172 	**	Get next object on the map
    173 	*/
    174 	obj = Map.Next_Object(CurrentObject[0]);
    175 
    176 	if (obj) {
    177 		/*
    178 		**	Unselect current object if there is one
    179 		*/
    180 		Unselect_All();
    181 
    182 	 	/*
    183 		**	Select this object
    184 		*/
    185 		obj->Select();
    186 	}
    187 
    188 	/*
    189 	**	Restore mouse shape to normal
    190 	*/
    191 	Set_Default_Mouse(MOUSE_NORMAL);
    192 	Override_Mouse_Shape(MOUSE_NORMAL);
    193 
    194 	/*
    195 	**	Show pop-up controls
    196 	*/
    197 	Popup_Controls();
    198 
    199 	/*
    200 	**	Make sure object is shown on the screen
    201 	*/
    202 	/*
    203 	**	compute screen map dimensions
    204 	*/
    205 	smap_w = Lepton_To_Cell(TacLeptonWidth);
    206 	smap_h = Lepton_To_Cell(TacLeptonHeight);
    207 
    208 	/*
    209 	**	compute x,y of object's cell
    210 	*/
    211 	obj_cell = Coord_Cell(CurrentObject[0]->Coord);
    212 	cell_x = Cell_X(obj_cell);
    213 	cell_y = Cell_Y(obj_cell);
    214 	tcell_x = Coord_XCell(TacticalCoord);
    215 	tcell_y = Coord_YCell(TacticalCoord);
    216 
    217 	/*
    218 	**	If object is off-screen, move map
    219 	*/
    220 	if (cell_x < tcell_x) {
    221 		tcell_x = cell_x;
    222 	} else {
    223 		if (cell_x >= tcell_x + smap_w) {
    224 			tcell_x = cell_x - smap_w + 1;
    225 		}
    226 	}
    227 
    228 	if (cell_y < tcell_y) {
    229 		tcell_y = cell_y;
    230 	} else {
    231 		if (cell_y >= tcell_y + smap_h) {
    232 			tcell_y = cell_y - smap_h + 1;
    233 		}
    234 	}
    235 
    236 	ScenarioInit++;
    237 	Set_Tactical_Position(XY_Coord(Cell_To_Lepton(tcell_x), Cell_To_Lepton(tcell_y)));
    238 	ScenarioInit--;
    239 
    240 	/*
    241 	**	Force map to redraw
    242 	*/
    243 	HidPage.Clear();
    244 	Flag_To_Redraw(true);
    245 }
    246 
    247 
    248 /***************************************************************************
    249  * MapEditClass::Popup_Controls -- shows/hides the pop-up object controls  *
    250  *                                                                         *
    251  * Call this routine whenever the CurrentObject changes. The routine will  *
    252  * selectively enable or disable the popup controls based on whether       *
    253  * CurrentObject is NULL, or if it's a Techno object, or what type of      *
    254  * Techno object it is.                                                    *
    255  *                                                                         *
    256  * INPUT:                                                                  *
    257  *      none.                                                              *
    258  *                                                                         *
    259  * OUTPUT:                                                                 *
    260  *      none.                                                              *
    261  *                                                                         *
    262  * WARNINGS:                                                               *
    263  *      none.                                                              *
    264  *                                                                         *
    265  * HISTORY:                                                                *
    266  *   11/22/1994 BR : Created.                                              *
    267  *   04/30/1996 JLB : Revamped for new buttons and stuff.                  *
    268  *=========================================================================*/
    269 void MapEditClass::Popup_Controls(void)
    270 {
    271 	const TechnoTypeClass * objtype = NULL;
    272 	HousesType owner;							// object's current owner
    273 	int mission_index;						// object's current mission
    274 	int strength;								// object's 0-255 strength value
    275 	int i;
    276 
    277 	/*
    278 	**	Remove all buttons from GScreen's button list (so none of them provide
    279 	**	input any more); then, destroy the list by Zapping each button.  Then,
    280 	**	we'll have to add at least the MapArea button back to the Input button
    281 	**	list before we return, plus any other buttons to process input for.  We
    282 	**	always must add MapArea LAST in the list, so it doesn't intercept the
    283 	**	other buttons' input.
    284 	*/
    285 	Remove_A_Button(*HouseList);
    286 	Remove_A_Button(*MissionList);
    287 	Remove_A_Button(*HealthGauge);
    288 	Remove_A_Button(*HealthText);
    289 	Remove_A_Button(*FacingDial);
    290 	Remove_A_Button(*BaseGauge);
    291 	Remove_A_Button(*BaseLabel);
    292 	Remove_A_Button(*MapArea);
    293 
    294 	Remove_A_Button(*Sellable);
    295 	Remove_A_Button(*Rebuildable);
    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()*256;
    330 
    331 	switch (objtype->What_Am_I()) {
    332 		case RTTI_VESSELTYPE:
    333 		case RTTI_UNITTYPE:
    334 		case RTTI_INFANTRYTYPE:
    335 		case RTTI_AIRCRAFTTYPE:
    336 			MissionList->Set_Selected_Index(mission_index);
    337 			HealthGauge->Set_Value(strength);
    338 			sprintf(HealthBuf, "%d", CurrentObject[0]->Strength);
    339 			FacingDial->Set_Direction(((TechnoClass *)CurrentObject[0])->PrimaryFacing);
    340 
    341 			/*
    342 			**	Make the list.
    343 			*/
    344 			Add_A_Button(*HealthGauge);
    345 			Add_A_Button(*HouseList);
    346 			HouseList->Set_Selected_Index(owner);
    347 			Add_A_Button(*MissionList);
    348 			Add_A_Button(*HealthText);
    349 			Add_A_Button(*FacingDial);
    350 			break;
    351 
    352 		case RTTI_BUILDINGTYPE:
    353 			HealthGauge->Set_Value(strength);
    354 			sprintf(HealthBuf, "%d", CurrentObject[0]->Strength);
    355 			Add_A_Button(*HealthGauge);
    356 			Add_A_Button(*HouseList);
    357 			HouseList->Set_Selected_Index(owner);
    358 			Add_A_Button(*HealthText);
    359 
    360 			Add_A_Button(*Sellable);
    361 			if (((BuildingClass*)CurrentObject[0])->IsAllowedToSell) {
    362 				Sellable->Turn_On();
    363 			} else {
    364 				Sellable->Turn_Off();
    365 			}
    366 			Add_A_Button(*Rebuildable);
    367 			if (((BuildingClass*)CurrentObject[0])->IsToRebuild) {
    368 				Rebuildable->Turn_On();
    369 			} else {
    370 				Rebuildable->Turn_Off();
    371 			}
    372 
    373 			if (objtype->IsTurretEquipped) {
    374 				FacingDial->Set_Direction(((TechnoClass *) CurrentObject[0])->PrimaryFacing);
    375 				Add_A_Button(*FacingDial);
    376 			}
    377 			break;
    378 	}
    379 
    380 	/*
    381 	**	Add the map area last, so it's "underneath" the other buttons, and won't
    382 	**	intercept input for those buttons.
    383 	*/
    384 	Add_A_Button(*BaseGauge);
    385 	Add_A_Button(*BaseLabel);
    386 	Add_A_Button(*MapArea);
    387 }
    388 
    389 
    390 /***************************************************************************
    391  * MapEditClass::Grab_Object -- grabs the current object                   *
    392  *                                                                         *
    393  * INPUT:                                                                  *
    394  *      none.                                                              *
    395  *                                                                         *
    396  * OUTPUT:                                                                 *
    397  *      none.                                                              *
    398  *                                                                         *
    399  * WARNINGS:                                                               *
    400  *      none.                                                              *
    401  *                                                                         *
    402  * HISTORY:                                                                *
    403  *   11/07/1994 BR : Created.                                              *
    404  *=========================================================================*/
    405 void MapEditClass::Grab_Object(void)
    406 {
    407 	CELL cell;
    408 
    409 	if (CurrentObject.Count()) {
    410 		GrabbedObject = CurrentObject[0];
    411 
    412 		/*
    413 		**	Find out which cell 'ZoneCell' is in relation to the object's current cell
    414 		*/
    415 		cell = Coord_Cell(GrabbedObject->Coord);
    416 		GrabOffset = cell - ZoneCell;
    417 	}
    418 }
    419 
    420 
    421 /***************************************************************************
    422  * MapEditClass::Move_Grabbed_Object -- moves the grabbed object           *
    423  *                                                                         *
    424  * INPUT:                                                                  *
    425  *      none.                                                              *
    426  *                                                                         *
    427  * OUTPUT:                                                                 *
    428  *      0 = object moved, -1 = it didn't                                   *
    429  *                                                                         *
    430  * WARNINGS:                                                               *
    431  *      none.                                                              *
    432  *                                                                         *
    433  * HISTORY:                                                                *
    434  *   11/07/1994 BR : Created.                                              *
    435  *=========================================================================*/
    436 int MapEditClass::Move_Grabbed_Object(void)
    437 {
    438 	COORDINATE new_coord = 0;
    439 	int retval = -1;
    440 
    441 	/*
    442 	**	Lift up the object
    443 	*/
    444 	GrabbedObject->Mark(MARK_UP);
    445 
    446 	/*
    447 	**	If infantry, use a free spot in this cell
    448 	*/
    449 	if (GrabbedObject->Is_Infantry()) {
    450 
    451 		if (Is_Spot_Free(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()))) {
    452 			new_coord = Closest_Free_Spot(Pixel_To_Coord(Get_Mouse_X(), Get_Mouse_Y()));
    453 
    454 			/*
    455 			**	Clear the occupied bit in this infantry's cell.
    456 			*/
    457 			((InfantryClass *)GrabbedObject)->Clear_Occupy_Bit(GrabbedObject->Coord);
    458 		} else {
    459 			new_coord = NULL;
    460 		}
    461 
    462 	} else {
    463 
    464 		/*
    465 		**	Non-infantry: use cell's center coordinate
    466 		*/
    467 		new_coord = Cell_Coord(ZoneCell + GrabOffset);
    468 
    469 		if (GrabbedObject->What_Am_I() == RTTI_BUILDING ||
    470 			GrabbedObject->What_Am_I() == RTTI_TERRAIN) {
    471 
    472 			new_coord = Coord_Whole(new_coord);
    473 		}
    474 
    475 		/*
    476 		**	Try to place object at new coordinate
    477 		*/
    478 		if (GrabbedObject->Can_Enter_Cell(Coord_Cell(new_coord)) != MOVE_OK) {
    479 			new_coord = NULL;
    480 		}
    481 	}
    482 	if (new_coord != NULL) {
    483 
    484 		/*
    485 		** If this object is part of the AI's Base list, change the coordinate
    486 		** in the Base's Node list.
    487 		*/
    488 		if (GrabbedObject->What_Am_I()==RTTI_BUILDING &&
    489 			Base.Get_Node((BuildingClass *)GrabbedObject))
    490 				Base.Get_Node((BuildingClass *)GrabbedObject)->Cell = Coord_Cell(new_coord);
    491 
    492 		GrabbedObject->Coord = new_coord;
    493 		retval = 0;
    494 	}
    495 	GrabbedObject->Mark(MARK_DOWN);
    496 
    497 	/*
    498 	**	For infantry, set the bit in its new cell marking that spot as occupied.
    499 	*/
    500 	if (GrabbedObject->Is_Infantry()) {
    501 		((InfantryClass *)GrabbedObject)->Set_Occupy_Bit(new_coord);
    502 	}
    503 
    504 	/*
    505 	**	Re-select the object, and reset the mouse pointer
    506 	*/
    507 	Set_Default_Mouse(MOUSE_NORMAL);
    508 	Override_Mouse_Shape(MOUSE_NORMAL);
    509 
    510 	Flag_To_Redraw(true);
    511 
    512 	return(retval);
    513 }
    514 
    515 
    516 /***************************************************************************
    517  * MapEditClass::Change_House -- changes CurrentObject's house             *
    518  *                                                                         *
    519  * INPUT:                                                                  *
    520  *      newhouse      house to change to                                   *
    521  *                                                                         *
    522  * OUTPUT:                                                                 *
    523  *      1 = house was changed, 0 = it wasn't                               *
    524  *                                                                         *
    525  * WARNINGS:                                                               *
    526  *      none.                                                              *
    527  *                                                                         *
    528  * HISTORY:                                                                *
    529  *   11/17/1994 BR : Created.                                              *
    530  *=========================================================================*/
    531 bool MapEditClass::Change_House(HousesType newhouse)
    532 {
    533 	TechnoClass *tp;
    534 
    535 	/*
    536 	**	Return if no current object
    537 	*/
    538 	if (!CurrentObject.Count()) {
    539 		return(false);
    540 	}
    541 
    542 	/*
    543 	**	Only techno objects can be owned by a house; return if not a techno
    544 	*/
    545 	if (!CurrentObject[0]->Is_Techno()) {
    546 		return(false);
    547 	}
    548 
    549 	/*
    550 	**	You can't change the house if the object is part of the AI's Base.
    551 	*/
    552 	if (CurrentObject[0]->What_Am_I()==RTTI_BUILDING && Base.Is_Node((BuildingClass *)CurrentObject[0])) {
    553 		return(false);
    554 	}
    555 
    556 	/*
    557 	**	Verify that the target house exists
    558 	*/
    559 	if (HouseClass::As_Pointer(newhouse)==NULL) {
    560 		return(false);
    561 	}
    562 
    563 	/*
    564 	**	Verify that this is a valid owner
    565 	*/
    566 //	if (!Verify_House(newhouse, &CurrentObject[0]->Class_Of())) {
    567 //		return(false);
    568 //	}
    569 
    570 	/*
    571 	**	Change the house
    572 	*/
    573 	tp = (TechnoClass *)CurrentObject[0];
    574 	tp->House = HouseClass::As_Pointer(newhouse);
    575 
    576 	tp->IsOwnedByPlayer = false;
    577 	if (tp->House == PlayerPtr) {
    578 		tp->IsOwnedByPlayer = true;
    579 	}
    580 
    581 	return(true);
    582 }
    583 
    584 
    585 #endif