TERRAIN.CPP 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  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: F:\projects\c&c\vcs\code\terrain.cpv 2.16 16 Oct 1995 16:51:44 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 : TERRAIN.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : April 29, 1994 *
  26. * *
  27. * Last Update : May 8, 1995 [JLB] *
  28. * *
  29. *---------------------------------------------------------------------------------------------*
  30. * Functions: *
  31. * TerrainClass::AI -- Process the terrain object AI. *
  32. * TerrainClass::As_Target -- Converts the terrain object into a target number. *
  33. * TerrainClass::Can_Enter_Cell -- Determines if the terrain object can exist in the cell. *
  34. * TerrainClass::Catch_Fire -- Catches the terrain object on fire. *
  35. * TerrainClass::Center_Coord -- Fetches the center point coordinate for terrain object. *
  36. * TerrainClass::Debug_Dump -- Displays the status of the terrain object. *
  37. * TerrainClass::Draw_It -- Renders the terrain object at the location specified. *
  38. * TerrainClass::Fire_Out -- Handles when fire has gone out. *
  39. * TerrainClass::Heath_Ratio -- Determines the health ratio for the terrain object. *
  40. * TerrainClass::Init -- Initialize the terrain object tracking system. *
  41. * TerrainClass::Limbo -- Handles terrain specific limbo action. *
  42. * TerrainClass::Mark -- Marks the terrain object on the map. *
  43. * TerrainClass::Radar_Icon -- Fetches pointer to radar icon to use. *
  44. * TerrainClass::Read_INI -- Reads terrain objects from INI file. *
  45. * TerrainClass::Start_To_Crumble -- Initiates crumbling of terrain (tree) object. *
  46. * TerrainClass::Take_Damage -- Damages the terrain object as specified. *
  47. * TerrainClass::TerrainClass -- Constructor for a terrain class object. *
  48. * TerrainClass::TerrainClass -- This is the constructor for a terrain object. *
  49. * TerrainClass::Unlimbo -- Unlimbo terrain object onto the map. *
  50. * TerrainClass::Write_INI -- Writes all terrain objects to the INI file. *
  51. * TerrainClass::delete -- Deletes a terrain object. *
  52. * TerrainClass::new -- Creates a new terrain object. *
  53. * TerrainClass::~TerrainClass -- Default destructor for terrain class objects. *
  54. * TerrainClass::Validate -- validates terrain pointer *
  55. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  56. #include "function.h"
  57. #include "terrain.h"
  58. #define BARNACLE_STAGE 22
  59. #define FIRST_SPORE_STAGE 30
  60. #define FIRST_SPORABLE_LEVEL 7
  61. /*
  62. ** This contains the value of the Virtual Function Table Pointer
  63. */
  64. void * TerrainClass::VTable;
  65. /***********************************************************************************************
  66. * TerrainClass::Validate -- validates terrain pointer *
  67. * *
  68. * INPUT: *
  69. * none. *
  70. * *
  71. * OUTPUT: *
  72. * 1 = ok, 0 = error *
  73. * *
  74. * WARNINGS: *
  75. * none. *
  76. * *
  77. * HISTORY: *
  78. * 08/09/1995 BRR : Created. *
  79. *=============================================================================================*/
  80. #ifdef CHEAT_KEYS
  81. int TerrainClass::Validate(void) const
  82. {
  83. int num;
  84. num = Terrains.ID(this);
  85. if (num < 0 || num >= TERRAIN_MAX) {
  86. Validate_Error("TERRAIN");
  87. return (0);
  88. }
  89. else
  90. return (1);
  91. }
  92. #else
  93. #define Validate()
  94. #endif
  95. /***********************************************************************************************
  96. * TerrainClass::~TerrainClass -- Default destructor for terrain class objects. *
  97. * *
  98. * This is the default destructor for terrain objects. It will remove the object from the *
  99. * map and tracking systems, but only if the game is running. Otherwise, it does nothing. *
  100. * *
  101. * INPUT: none *
  102. * *
  103. * OUTPUT: none *
  104. * *
  105. * WARNINGS: none *
  106. * *
  107. * HISTORY: *
  108. * 01/23/1995 JLB : Created. *
  109. *=============================================================================================*/
  110. TerrainClass::~TerrainClass(void)
  111. {
  112. if (GameActive && Class) {
  113. TerrainClass::Limbo();
  114. }
  115. }
  116. /***********************************************************************************************
  117. * TerrainClass::Take_Damage -- Damages the terrain object as specified. *
  118. * *
  119. * This routine is called when damage is to be inflicted upon the terrain object. It is *
  120. * through this routine that terrain objects are attacked and thereby destroyed. Not all *
  121. * terrain objects can be damaged by this routine however. *
  122. * *
  123. * INPUT: damage -- The damage points to inflict (raw). *
  124. * *
  125. * warhead -- The warhead type the indicates the kind of damage. This is used to *
  126. * determine if the terrain object is damaged and if so, by how much. *
  127. * *
  128. * OUTPUT: bool; Was the terrain object destroyed by this damage? *
  129. * *
  130. * WARNINGS: none *
  131. * *
  132. * HISTORY: *
  133. * 09/24/1994 JLB : Created. *
  134. * 11/22/1994 JLB : Shares base damage handler for techno objects. *
  135. * 12/11/1994 JLB : Shortens attached burning animations. *
  136. *=============================================================================================*/
  137. ResultType TerrainClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source)
  138. {
  139. Validate();
  140. ResultType res = RESULT_NONE;
  141. /*
  142. ** Small arms can never destroy a terrain element.
  143. */
  144. if ((!IsOnFire || warhead == WARHEAD_FIRE) && warhead != WARHEAD_SA && !Class->IsImmune) {
  145. res = ObjectClass::Take_Damage(damage, distance, warhead, source);
  146. if (damage && warhead == WARHEAD_FIRE) {
  147. Catch_Fire();
  148. }
  149. /*
  150. ** If the terrain object is destroyed by this damage, then only remove it if it
  151. ** currently isn't on fire and isn't in the process of crumbling.
  152. */
  153. if (res == RESULT_DESTROYED) {
  154. /*
  155. ** Remove this terrain object from the targeting computers of all other
  156. ** game objects. No use beating a dead horse.
  157. */
  158. Detach_All();
  159. if (IsOnFire) {
  160. /*
  161. ** Attached flame animation should be shortened as much as possible so that
  162. ** crumbling can begin soon.
  163. */
  164. Shorten_Attached_Anims(this);
  165. } else {
  166. Start_To_Crumble();
  167. }
  168. }
  169. }
  170. return(res);
  171. }
  172. /***********************************************************************************************
  173. * TerrainClass::As_Target -- Converts the terrain object into a target number. *
  174. * *
  175. * This routine will take the terrain object and generate a unique targeting number. This *
  176. * number is used for the NavCom and TarCom of other units. *
  177. * *
  178. * INPUT: none *
  179. * *
  180. * OUTPUT: Returns with the target number of this terrain object. *
  181. * *
  182. * WARNINGS: none *
  183. * *
  184. * HISTORY: *
  185. * 09/24/1994 JLB : Created. *
  186. *=============================================================================================*/
  187. TARGET TerrainClass::As_Target(void) const
  188. {
  189. Validate();
  190. return(Build_Target(KIND_TERRAIN, Terrains.ID(this)));
  191. }
  192. /***********************************************************************************************
  193. * TerrainClass::new -- Creates a new terrain object. *
  194. * *
  195. * This routine creates a new terrain object by grabbing a free slot *
  196. * out of the terrain object pool. *
  197. * *
  198. * INPUT: none *
  199. * *
  200. * OUTPUT: Returns with a pointer to the terrain object allocated. *
  201. * *
  202. * WARNINGS: none *
  203. * *
  204. * HISTORY: *
  205. * 05/14/1994 JLB : Created. *
  206. *=============================================================================================*/
  207. void * TerrainClass::operator new(size_t)
  208. {
  209. void * ptr = Terrains.Allocate();
  210. if (ptr) {
  211. ((TerrainClass *)ptr)->Set_Active();
  212. }
  213. return(ptr);
  214. }
  215. /***********************************************************************************************
  216. * TerrainClass::delete -- Deletes a terrain object. *
  217. * *
  218. * This routine deletes a terrain object by returning it to the *
  219. * terrain object pool. *
  220. * *
  221. * INPUT: ptr -- Pointer to the terrain object to delete. *
  222. * *
  223. * OUTPUT: none *
  224. * *
  225. * WARNINGS: none *
  226. * *
  227. * HISTORY: *
  228. * 05/14/1994 JLB : Created. *
  229. *=============================================================================================*/
  230. void TerrainClass::operator delete(void *ptr)
  231. {
  232. if (ptr) {
  233. ((TerrainClass *)ptr)->IsActive = false;
  234. }
  235. Terrains.Free((TerrainClass *)ptr);
  236. }
  237. /***********************************************************************************************
  238. * TerrainClass::TerrainClass -- This is the constructor for a terrain object *
  239. * *
  240. * This constructor for a terrain object will initialize the terrain *
  241. * object with it's proper type and insert it into the access *
  242. * tracking system. *
  243. * *
  244. * INPUT: type -- The terrain object type. *
  245. * *
  246. * cell -- The location of the terrain object. *
  247. * *
  248. * OUTPUT: none *
  249. * *
  250. * WARNINGS: none *
  251. * *
  252. * HISTORY: *
  253. * 05/02/1994 JLB : Created. *
  254. *=============================================================================================*/
  255. TerrainClass::TerrainClass(TerrainType type, CELL cell) :
  256. Class(&TerrainTypeClass::As_Reference(type))
  257. {
  258. IsBlossoming = false;
  259. IsBarnacled = false;
  260. IsSporing = false;
  261. IsCrumbling = false;
  262. IsOnFire = false;
  263. Strength = Class->MaxStrength;
  264. if (cell != -1) {
  265. if (!Unlimbo(Cell_Coord(cell))) {
  266. delete this;
  267. }
  268. }
  269. Set_Rate(0); // turn off animation
  270. }
  271. /***********************************************************************************************
  272. * TerrainClass::Mark -- Marks the terrain object on the map. *
  273. * *
  274. * This routine will mark or remove the terrain object from the map *
  275. * tracking system. This is typically called when the terrain object *
  276. * is first created, when it is destroyed, and whenever it needs to be *
  277. * redrawn. *
  278. * *
  279. * INPUT: mark -- The marking operation to perform. *
  280. * *
  281. * OUTPUT: bool; Was the terrain object successfully marked? *
  282. * *
  283. * WARNINGS: none *
  284. * *
  285. * HISTORY: *
  286. * 05/02/1994 JLB : Created. *
  287. * 12/23/1994 JLB : Performs low level legality check before proceeding. *
  288. *=============================================================================================*/
  289. bool TerrainClass::Mark(MarkType mark)
  290. {
  291. Validate();
  292. if (ObjectClass::Mark(mark)) {
  293. short const *overlap = Class->Overlap_List();
  294. short const *occupy = Class->Occupy_List();
  295. CELL cell = Coord_Cell(Coord);
  296. switch (mark) {
  297. case MARK_UP:
  298. Map.Pick_Up(cell, this);
  299. break;
  300. case MARK_DOWN:
  301. Map.Place_Down(cell, this);
  302. break;
  303. default:
  304. Map.Refresh_Cells(cell, overlap);
  305. Map.Refresh_Cells(cell, occupy);
  306. break;
  307. }
  308. return(true);
  309. }
  310. return(false);
  311. }
  312. /***********************************************************************************************
  313. * TerrainClass::Draw_It -- Renders the terrain object at the location specified. *
  314. * *
  315. * This routine is used to render the terrain object at the location specified and *
  316. * clipped to the window specified. This is the gruntwork drawing routine for the *
  317. * terrain objects as they are displayed on the map. *
  318. * *
  319. * INPUT: x,y -- The coordinate to draw the terrain object at (centered). *
  320. * *
  321. * window -- The clipping window to draw to. *
  322. * *
  323. * OUTPUT: none *
  324. * *
  325. * WARNINGS: none *
  326. * *
  327. * HISTORY: *
  328. * 06/27/1994 JLB : Created. *
  329. * 11/09/1994 JLB : Changed selected terrain highlight method. *
  330. *=============================================================================================*/
  331. void TerrainClass::Draw_It(int x, int y, WindowNumberType window)
  332. {
  333. Validate();
  334. void const * shapedata;
  335. shapedata = Class->Get_Image_Data();
  336. if (shapedata) {
  337. int shapenum = 0;
  338. /*
  339. ** Determine the animation stage to render the terrain object. If it is crumbling, then
  340. ** it will display the crumbling animation.
  341. */
  342. if (IsCrumbling || Class->IsTransformable) {
  343. shapenum = Fetch_Stage()+IsCrumbling;
  344. } else {
  345. if (Strength < 2) {
  346. shapenum++;
  347. }
  348. }
  349. ShapeFlags_Type flags = SHAPE_NORMAL;
  350. if (Is_Selected_By_Player() && Debug_Map) flags = flags | SHAPE_FADING;
  351. IsTheaterShape = true;
  352. CC_Draw_Shape(this, shapedata, shapenum, x, y, window, flags|SHAPE_WIN_REL|SHAPE_GHOST, Map.FadingLight, Map.UnitShadow);
  353. IsTheaterShape = false;
  354. }
  355. }
  356. /***********************************************************************************************
  357. * TerrainClass::Init -- Initialize the terrain object tracking system. *
  358. * *
  359. * This routine will clear out the terrain object system so that no terrain objects will *
  360. * exists. It is called prior to loading or starting a scenario. *
  361. * *
  362. * INPUT: none *
  363. * *
  364. * OUTPUT: none *
  365. * *
  366. * WARNINGS: none *
  367. * *
  368. * HISTORY: *
  369. * 09/24/1994 JLB : Created. *
  370. *=============================================================================================*/
  371. void TerrainClass::Init(void)
  372. {
  373. TerrainClass *ptr;
  374. Terrains.Free_All();
  375. ptr = new TerrainClass();
  376. VTable = ((void **)(((char *)ptr) + sizeof(AbstractClass) - 4))[0];
  377. delete ptr;
  378. }
  379. /***********************************************************************************************
  380. * TerrainClass::Can_Enter_Cell -- Determines if the terrain object can exist in the cell. *
  381. * *
  382. * This routine will examine the cell specified and determine if the the terrain object *
  383. * can legally exist there. *
  384. * *
  385. * INPUT: cell -- The cell to examine. *
  386. * *
  387. * OUTPUT: If the terrain object can be placed in the cell specified, then a value less than *
  388. * 256 will be returned. *
  389. * *
  390. * WARNINGS: none *
  391. * *
  392. * HISTORY: *
  393. * 09/24/1994 JLB : Created. *
  394. * 01/01/1995 JLB : Actually works now. *
  395. *=============================================================================================*/
  396. MoveType TerrainClass::Can_Enter_Cell(CELL cell, FacingType) const
  397. {
  398. Validate();
  399. short const *offset; // Pointer to cell offset list.
  400. if ((unsigned)cell >= MAP_CELL_TOTAL) return(MOVE_NO);
  401. offset = Occupy_List();
  402. while (*offset != REFRESH_EOL) {
  403. if (!Map[(CELL)(cell + *offset++)].Is_Generally_Clear()) {
  404. return(MOVE_NO);
  405. }
  406. }
  407. return(MOVE_OK);
  408. }
  409. /***********************************************************************************************
  410. * TerrainClass::Catch_Fire -- Catches the terrain object on fire. *
  411. * *
  412. * This routine is called if the terrain object is supposed to catch on fire. The routine *
  413. * performs checking to make sure that only flammable terrain objects that aren't already *
  414. * on fire get caught on fire. *
  415. * *
  416. * INPUT: none *
  417. * *
  418. * OUTPUT: bool; Was the terrain object caught on fire by this routine? *
  419. * *
  420. * WARNINGS: none *
  421. * *
  422. * HISTORY: *
  423. * 09/27/1994 JLB : Created. *
  424. * 12/11/1994 JLB : Don't catch fire if already on fire or crumbling. *
  425. *=============================================================================================*/
  426. bool TerrainClass::Catch_Fire(void)
  427. {
  428. Validate();
  429. if (!IsCrumbling && !IsOnFire && Class->IsFlammable) {
  430. AnimClass * anim = new AnimClass(ANIM_BURN_BIG, Coord_Add(Sort_Y(), 0xFFB00000L));
  431. if (anim) {
  432. anim->Attach_To(this);
  433. }
  434. anim = new AnimClass(ANIM_BURN_MED, Coord_Add(Sort_Y(), 0xFF200000L), 15);
  435. if (anim) {
  436. anim->Attach_To(this);
  437. }
  438. IsOnFire = true;
  439. return(true);
  440. }
  441. return(false);
  442. }
  443. /***********************************************************************************************
  444. * TerrainClass::Fire_Out -- Handles when fire has gone out. *
  445. * *
  446. * When the fire has gone out on a burning terrain object, this routine is called. The *
  447. * animation has already been terminated prior to calling this routine. All this routine *
  448. * needs to perform is any necessary local flag updating. *
  449. * *
  450. * INPUT: none *
  451. * *
  452. * OUTPUT: none *
  453. * *
  454. * WARNINGS: none *
  455. * *
  456. * HISTORY: *
  457. * 09/27/1994 JLB : Created. *
  458. *=============================================================================================*/
  459. void TerrainClass::Fire_Out(void)
  460. {
  461. Validate();
  462. if (IsOnFire) {
  463. IsOnFire = false;
  464. if (!IsCrumbling && !Strength) {
  465. Detach_All();
  466. Mark();
  467. Start_To_Crumble();
  468. new AnimClass(ANIM_SMOKE_M, Coord_Add(Coord, Class->CenterBase));
  469. }
  470. }
  471. }
  472. /***********************************************************************************************
  473. * TerrainClass::AI -- Process the terrain object AI. *
  474. * *
  475. * This is used to handle any AI processing necessary for terrain objects. This might *
  476. * include animation effects. *
  477. * *
  478. * INPUT: none *
  479. * *
  480. * OUTPUT: none *
  481. * *
  482. * WARNINGS: none *
  483. * *
  484. * HISTORY: *
  485. * 09/27/1994 JLB : Created. *
  486. * 09/28/1994 JLB : Crumbling animation. *
  487. *=============================================================================================*/
  488. void TerrainClass::AI(void)
  489. {
  490. Validate();
  491. ObjectClass::AI();
  492. if (StageClass::Graphic_Logic()) {
  493. Mark();
  494. /*
  495. ** If the terrain object is in the process of crumbling, then when at the
  496. ** last stage of the crumbling animation, delete the terrain object.
  497. */
  498. if (IsCrumbling && Fetch_Stage() == Get_Build_Frame_Count(Class->Get_Image_Data())-1) {
  499. delete this;
  500. }
  501. }
  502. /*
  503. ** if this is a blossom tree, let's update it at this time
  504. */
  505. if (Class->IsTransformable) {
  506. // If it's already blossomed, is it at barnacled stage?
  507. if (IsBlossoming) {
  508. // if it's not barnacled yet, check if we're at that stage
  509. if (!IsBarnacled) {
  510. if (Fetch_Stage() == BARNACLE_STAGE) {
  511. IsBarnacled = true;
  512. Set_Rate(0); // turn off animation
  513. }
  514. } else {
  515. /*
  516. ** If it's barnacled, see if it's pulsing and spore-ing
  517. */
  518. if (IsSporing) {
  519. if (Fetch_Stage() >= Get_Build_Frame_Count(Class->Get_Image_Data())-1) {
  520. Explosion_Damage(Sort_Y(), 5, NULL, WARHEAD_SPORE);
  521. Set_Stage(FIRST_SPORE_STAGE);
  522. if (Random() & 1) {
  523. IsSporing = false;
  524. StageClass::Set_Rate(0);
  525. }
  526. }
  527. } else {
  528. if (Random() == 255) { // is it time to start sporing?
  529. IsSporing = true;
  530. StageClass::Set_Rate(Options.Normalize_Delay(1));
  531. }
  532. }
  533. }
  534. } else {
  535. // If it hasn't tried to blossom yet, can it do so now?
  536. if (Random_Picky((int)1, (int)5000, (char*)NULL, (int)0) == 1) {
  537. IsBlossoming = true;
  538. StageClass::Set_Stage(1);
  539. StageClass::Set_Rate(Options.Normalize_Delay(1));
  540. }
  541. }
  542. }
  543. }
  544. #ifdef CHEAT_KEYS
  545. /***********************************************************************************************
  546. * TerrainClass::Debug_Dump -- Displays the status of the terrain object. *
  547. * *
  548. * This debugging support routine is used to display the status of the terrain object to *
  549. * the debug screen. *
  550. * *
  551. * INPUT: mono -- The mono screen to display the status to. *
  552. * *
  553. * OUTPUT: none *
  554. * *
  555. * WARNINGS: none *
  556. * *
  557. * HISTORY: *
  558. * 09/27/1994 JLB : Created. *
  559. *=============================================================================================*/
  560. void TerrainClass::Debug_Dump(MonoClass *mono) const
  561. {
  562. Validate();
  563. ObjectClass::Debug_Dump(mono);
  564. }
  565. #endif
  566. /***********************************************************************************************
  567. * TerrainClass::Unlimbo -- Unlimbo terrain object onto the map. *
  568. * *
  569. * This routine is used to unlimbo the terrain object onto a location on the map. Normal *
  570. * unlimbo procedures are sufficient except that the coordinate location of a terrain *
  571. * object is based on the upper left corner of a cell rather than the center. Mask the *
  572. * coordinate value so that it snaps to the upper left corner and then proceed with a *
  573. * normal unlimbo process. *
  574. * *
  575. * INPUT: coord -- The coordinate to mark as the terrain's location. *
  576. * *
  577. * dir -- unused *
  578. * *
  579. * OUTPUT: bool; Was the terrain object successful in the unlimbo process? Failure could be *
  580. * the result of illegal positioning. *
  581. * *
  582. * WARNINGS: none *
  583. * *
  584. * HISTORY: *
  585. * 11/02/1994 JLB : Created. *
  586. * 11/16/1994 JLB : Checks for theater legality. *
  587. *=============================================================================================*/
  588. bool TerrainClass::Unlimbo(COORDINATE coord, DirType dir)
  589. {
  590. Validate();
  591. if (Class->Theater & (1 << Map.Theater)) {
  592. return(ObjectClass::Unlimbo(coord, dir));
  593. }
  594. return(false);
  595. }
  596. /***********************************************************************************************
  597. * TerrainClass::Start_To_Crumble -- Initiates crumbling of terrain (tree) object. *
  598. * *
  599. * This routine is used to start the crumbling process for terrain object. This only *
  600. * applies to trees. *
  601. * *
  602. * INPUT: none *
  603. * *
  604. * OUTPUT: none *
  605. * *
  606. * WARNINGS: none *
  607. * *
  608. * HISTORY: *
  609. * 12/22/1994 JLB : Created. *
  610. *=============================================================================================*/
  611. void TerrainClass::Start_To_Crumble(void)
  612. {
  613. Validate();
  614. if (!IsCrumbling) {
  615. IsCrumbling = true;
  616. Set_Rate(2);
  617. Set_Stage(0);
  618. }
  619. }
  620. /***********************************************************************************************
  621. * TerrainClass::Limbo -- Handles terrain specific limbo action. *
  622. * *
  623. * This routine (called as a part of the limbo process) will remove the terrain occupation *
  624. * flag in the cell it occupies. *
  625. * *
  626. * INPUT: none *
  627. * *
  628. * OUTPUT: bool; Was the terrain object unlimboed? *
  629. * *
  630. * WARNINGS: none *
  631. * *
  632. * HISTORY: *
  633. * 12/22/1994 JLB : Created. *
  634. *=============================================================================================*/
  635. bool TerrainClass::Limbo(void)
  636. {
  637. Validate();
  638. if (!IsInLimbo) {
  639. CELL cell = Coord_Cell(Coord);
  640. Map[cell].Flag.Occupy.Monolith = false;
  641. }
  642. return(ObjectClass::Limbo());
  643. }
  644. /***********************************************************************************************
  645. * TerrainClass::Center_Coord -- Fetches the center point coordinate for terrain object. *
  646. * *
  647. * Use this routine to fetch the center point terrain *
  648. * *
  649. * INPUT: *
  650. * *
  651. * OUTPUT: *
  652. * *
  653. * WARNINGS: *
  654. * *
  655. * HISTORY: *
  656. * 01/23/1995 JLB : Created. *
  657. *=============================================================================================*/
  658. COORDINATE TerrainClass::Center_Coord(void) const
  659. {
  660. Validate();
  661. return(Coord_Add(Coord, Class->CenterBase));
  662. }
  663. /***********************************************************************************************
  664. * TerrainClass::TerrainClass -- Constructor for a terrain class object. *
  665. * *
  666. * This is the default constructor for a terrain class object. It basically initializes *
  667. * the object to a null -- do nothing -- state. *
  668. * *
  669. * INPUT: none *
  670. * *
  671. * OUTPUT: none *
  672. * *
  673. * WARNINGS: none *
  674. * *
  675. * HISTORY: *
  676. * 03/10/1995 JLB : Created. *
  677. *=============================================================================================*/
  678. TerrainClass::TerrainClass(void) :
  679. Class(0)
  680. {
  681. IsOnFire = false;
  682. IsCrumbling = false;
  683. IsBlossoming = false;
  684. IsBarnacled = false;
  685. IsSporing = false;
  686. Strength = 0;
  687. }
  688. /***********************************************************************************************
  689. * TerrainClass::Radar_Icon -- Fetches pointer to radar icon to use. *
  690. * *
  691. * This routine will return with a pointer to the radar icon to use for the cell number *
  692. * specified. *
  693. * *
  694. * INPUT: cell -- The cell number to use when determine what icon pointer to return. *
  695. * *
  696. * OUTPUT: Returns with a pointer to the 9 pixel values that make up the icon of this *
  697. * terrain object located at the cell specified. *
  698. * *
  699. * WARNINGS: none *
  700. * *
  701. * HISTORY: *
  702. * 05/08/1995 JLB : Created. *
  703. *=============================================================================================*/
  704. unsigned char * TerrainClass::Radar_Icon(CELL cell)
  705. {
  706. Validate();
  707. unsigned char *icon = (unsigned char *)Class->Get_Radar_Data(); // get a pointer to radar icons
  708. int width = *icon++; // extract the width from data
  709. int height = *icon++; // extract the width from data
  710. /*
  711. ** Icon number that we need can be found by converting the cell and base
  712. ** cell to and x and y offset from the upper left of the cell, and then
  713. ** multiplying it by the width of the terrain in icons, which we
  714. ** conveniantly stored out as the first byte of every icon we made.
  715. */
  716. int basecell = Coord_Cell(Coord); // find the base cell of terrain
  717. int ydiff = Cell_Y(cell) - Cell_Y(basecell);
  718. int xdiff = Cell_X(cell) - Cell_X(basecell);
  719. if (xdiff < width && ydiff < height) {
  720. int iconnum = (ydiff * width) + xdiff;
  721. return(icon + (iconnum * 9));
  722. }
  723. return(NULL);
  724. }
  725. /***********************************************************************************************
  726. * TerrainClass::Read_INI -- Reads terrain objects from INI file. *
  727. * *
  728. * This routine reads a scenario control INI file and creates all *
  729. * terrain objects specified therein. Objects so created are placed *
  730. * upon the map. *
  731. * *
  732. * INI entry format: *
  733. * cellnum = TypeName, Triggername *
  734. * *
  735. * INPUT: buffer -- Pointer to the loaded scenario INI file data. *
  736. * *
  737. * OUTPUT: none *
  738. * *
  739. * WARNINGS: none *
  740. * *
  741. * HISTORY: *
  742. * 05/24/1994 JLB : Created. *
  743. *=============================================================================================*/
  744. void TerrainClass::Read_INI(char *buffer)
  745. {
  746. char *tbuffer; // Accumulation buffer of unit IDs.
  747. int len; // Size of data in buffer.
  748. char buf[128];
  749. TerrainClass * tptr;
  750. len = strlen(buffer) + 2;
  751. tbuffer = buffer + len;
  752. WWGetPrivateProfileString(INI_Name(), NULL, NULL, tbuffer, ShapeBufferSize-len, buffer);
  753. while (*tbuffer != '\0') {
  754. TerrainType terrain; // Terrain type.
  755. CELL cell;
  756. cell = atoi(tbuffer);
  757. WWGetPrivateProfileString(INI_Name(), tbuffer, NULL, buf, sizeof(buf)-1, buffer);
  758. terrain = TerrainTypeClass::From_Name(strtok(buf, ","));
  759. if (terrain != TERRAIN_NONE) {
  760. tptr = new TerrainClass(terrain, cell);
  761. tptr->Trigger = TriggerClass::As_Pointer(strtok(NULL,","));
  762. if (tptr->Trigger)
  763. tptr->Trigger->AttachCount++;
  764. }
  765. tbuffer += strlen(tbuffer)+1;
  766. }
  767. }
  768. /***********************************************************************************************
  769. * TerrainClass::Write_INI -- Writes all terrain objects to the INI file. *
  770. * *
  771. * This routine is used to write all the terrain objects out to the INI file specified. *
  772. * It is used by the scenario editor to write out the map data. *
  773. * *
  774. * INI entry format: *
  775. * cellnum = TypeName, Triggername *
  776. * *
  777. * INPUT: buffer -- Pointer to the INI file staging area. *
  778. * *
  779. * OUTPUT: none *
  780. * *
  781. * WARNINGS: none *
  782. * *
  783. * HISTORY: *
  784. * 05/28/1994 JLB : Created. *
  785. *=============================================================================================*/
  786. void TerrainClass::Write_INI(char *buffer)
  787. {
  788. int index;
  789. char uname[10];
  790. char buf[127];
  791. char *tbuffer; // Accumulation buffer of unit IDs.
  792. /*
  793. ** First, clear out all existing terrain data from the ini file.
  794. */
  795. tbuffer = buffer + strlen(buffer) + 2;
  796. WWGetPrivateProfileString(INI_Name(), NULL, NULL, tbuffer, ShapeBufferSize-strlen(buffer), buffer);
  797. while (*tbuffer != '\0') {
  798. WWWritePrivateProfileString(INI_Name(), tbuffer, NULL, buffer);
  799. tbuffer += strlen(tbuffer)+1;
  800. }
  801. /*
  802. ** Write the terrain data out.
  803. */
  804. for (index = 0; index < Terrains.Count(); index++) {
  805. TerrainClass * terrain;
  806. terrain = Terrains.Ptr(index);
  807. if (!terrain->IsInLimbo && terrain->IsActive) {
  808. sprintf(uname, "%d", Coord_Cell(terrain->Coord));
  809. sprintf(buf, "%s,%s",
  810. terrain->Class->IniName,
  811. terrain->Trigger ? terrain->Trigger->Get_Name() : "None" );
  812. WWWritePrivateProfileString(INI_Name(), uname, buf, buffer);
  813. }
  814. }
  815. }