MAPEDSEL.CPP 19 KB

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