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