OBJECT.CPP (100712B)
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\object.cpv 2.17 16 Oct 1995 16:49:22 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 : OBJECT.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : April 29, 1994 * 28 * * 29 * Last Update : August 13, 1995 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * ObjectClass::Debug_Dump -- Displays status of the object class to the mono monitor. * 34 * ObjectClass::Detach_All -- Removes the object from all tracking systems. * 35 * ObjectClass::Detach_This_From_All -- Detatches this object from all others. * 36 * ObjectClass::Fire_Out -- Informs object that attached animation has finished. * 37 * ObjectClass::Get_Mission -- Fetches the current mission of this object. * 38 * ObjectClass::Init -- Initializes the basic object system. * 39 * ObjectClass::Limbo -- Brings the object into a state of limbo. * 40 * ObjectClass::Mark -- Handles basic marking logic. * 41 * ObjectClass::Mark_For_Redraw -- Marks object and system for redraw. * 42 * ObjectClass::Move -- Moves (by force) the object in the desired direction. * 43 * ObjectClass::ObjectClass -- Default constructor for objects. * 44 * ObjectClass::Passive_Click_With -- Right mouse button click process. * 45 * ObjectClass::Receive_Message -- Processes an incoming radio message. * 46 * ObjectClass::Render -- Displays the object onto the map. * 47 * ObjectClass::Repair -- Handles object repair control. * 48 * ObjectClass::Revealed -- Reveals this object to the house specified. * 49 * ObjectClass::Select -- Try to make this object the "selected" object. * 50 * ObjectClass::Sell_Back -- Sells the object -- if possible. * 51 * ObjectClass::Take_Damage -- Applies damage to the object. * 52 * ObjectClass::Unlimbo -- Brings the object into the game system. * 53 * ObjectClass::Unselect -- This will un-select the object if it was selected. * 54 * ObjectClass::Value -- Fetches the target value of this object. * 55 * ObjectClass::What_Action -- Deteremines what action to perform on specified object. * 56 * ObjectClass::What_Am_I -- RTTI query of this object type. * 57 * ObjectTypeClass::Cost_Of -- Returns the cost to buy this unit. * 58 * ObjectTypeClass::Dimensions -- Gets the dimensions of the object in pixels. * 59 * ObjectTypeClass::Get_Cameo_Data -- Fetches pointer to cameo data for this object type. * 60 * ObjectTypeClass::Max_Pips -- Fetches the maximum pips allowed for this object. * 61 * ObjectTypeClass::ObjectTypeClass -- Normal constructor for object type class objects. * 62 * ObjectTypeClass::Occupy_List -- Returns with simple occupation list for object. * 63 * ObjectTypeClass::One_Time -- Handles one time processing for object types. * 64 * ObjectTypeClass::Overlap_List -- Returns a pointer to a simple overlap list. * 65 * ObjectTypeClass::Time_To_Build -- Fetches the time to construct this object. * 66 * ObjectTypeClass::Who_Can_Build_Me -- Finds the factory building that can build this object* 67 * ObjectClass::What_Action -- Returns with the action to perform for this object. * 68 * ObjectClass::In_Which_Layer -- Fetches what layer this object is located in. * 69 * ObjectClass::Is_Techno -- Checks to see if this object is a techno type. * 70 * ObjectClass::Get_Ownable -- Fetches the house owner legality options for this object. * 71 * ObjectClass::Can_Repair -- Queries whether this object can be repaired. * 72 * ObjectClass::Can_Demolish -- Queries whether this object can be sold back. * 73 * ObjectClass::Can_Player_Fire -- Can the player give this object an attack mission? * 74 * ObjectClass::Can_Player_Move -- Can the player give this object a movement mission? * 75 * ObjectClass::Target_Coord -- Fetches the coordinate if this object is a target. * 76 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 77 78 #include "function.h" 79 80 81 /* 82 ** Selected objects have a special marking box around them. This is the shapes that are 83 ** used for this purpose. 84 */ 85 void const * ObjectTypeClass::SelectShapes = 0; 86 87 void const * ObjectTypeClass::PipShapes = 0; 88 89 90 bool ObjectClass::Is_Infantry(void) const 91 { 92 return(false); 93 } 94 95 96 97 /*********************************************************************************************** 98 * ObjectTypeClass::ObjectTypeClass -- Normal constructor for object type class objects. * 99 * * 100 * This is the base constructor that is used when constructing the object type classes. * 101 * Every tangible game piece type calls this constructor for the ObjectTypeClass. This * 102 * class holds static information that is common to objects in general. * 103 * * 104 * INPUT: see below... * 105 * * 106 * OUTPUT: none * 107 * * 108 * WARNINGS: none * 109 * * 110 * HISTORY: * 111 * 03/23/1995 JLB : Created. * 112 *=============================================================================================*/ 113 ObjectTypeClass::ObjectTypeClass( 114 bool is_sentient, 115 bool is_flammable, 116 bool is_crushable, 117 bool is_stealthy, 118 bool is_selectable, 119 bool is_legal_target, 120 bool is_insignificant, 121 bool is_immune, 122 int name, 123 char const *ini, 124 ArmorType armor, 125 unsigned short strength) : 126 AbstractTypeClass(name, ini) 127 { 128 IsSentient = is_sentient; 129 IsFlammable = is_flammable; 130 IsCrushable = is_crushable; 131 IsStealthy = is_stealthy; 132 IsSelectable = is_selectable; 133 IsLegalTarget = is_legal_target; 134 IsInsignificant = is_insignificant; 135 IsImmune = is_immune; 136 Armor = armor; 137 MaxStrength = strength; 138 ImageData = NULL; 139 //RadarIcon = NULL; 140 } 141 142 143 /*********************************************************************************************** 144 * ObjectTypeClass::Max_Pips -- Fetches the maximum pips allowed for this object. * 145 * * 146 * This routine will return the maximum number of pips that can be displayed for this * 147 * object. When dealing with generic objects, this value is always zero. * 148 * * 149 * INPUT: none * 150 * * 151 * OUTPUT: Returns with the number of pip boxes (empty or otherwise) to display. * 152 * * 153 * WARNINGS: none * 154 * * 155 * HISTORY: * 156 * 07/19/1995 JLB : Created. * 157 *=============================================================================================*/ 158 int ObjectTypeClass::Max_Pips(void) const 159 { 160 return(0); 161 } 162 163 164 /*********************************************************************************************** 165 * ObjectTypeClass::Dimensions -- Gets the dimensions of the object in pixels. * 166 * * 167 * This routine will fetch the dimensions of this object expressed as pixels width and * 168 * pixels height. This information can be used to intelligently update the clipping * 169 * rectangles. * 170 * * 171 * INPUT: width -- Reference to the width variable that will be filled in. * 172 * * 173 * height -- Reference to the height variable that will be filled in. * 174 * * 175 * OUTPUT: none * 176 * * 177 * WARNINGS: none * 178 * * 179 * HISTORY: * 180 * 07/19/1995 JLB : Created. * 181 *=============================================================================================*/ 182 void ObjectTypeClass::Dimensions(int &width, int &height) const 183 { 184 width = 10; 185 height = 10; 186 } 187 188 189 /*********************************************************************************************** 190 * ObjectTypeClass::Cost_Of -- Returns the cost to buy this unit. * 191 * * 192 * This routine will return the cost to purchase this unit. This routine is expected to be * 193 * overridden by the objects that can actually be purchased. All other object types can * 194 * simply return zero since this value won't be used. * 195 * * 196 * INPUT: none * 197 * * 198 * OUTPUT: Returns the cost of the object. * 199 * * 200 * WARNINGS: none * 201 * * 202 * HISTORY: * 203 * 07/19/1995 JLB : Created. * 204 *=============================================================================================*/ 205 int ObjectTypeClass::Cost_Of(void) const 206 { 207 return(0); 208 } 209 210 211 /*********************************************************************************************** 212 * ObjectTypeClass::Time_To_Build -- Fetches the time to construct this object. * 213 * * 214 * This routine will fetch the time in takes to construct this object. Objects that can * 215 * be constructed will override this routine in order to return a useful value. * 216 * * 217 * INPUT: none * 218 * * 219 * OUTPUT: Returns with the time units (arbitrary) that it takes to construct this object. * 220 * * 221 * WARNINGS: none * 222 * * 223 * HISTORY: * 224 * 07/19/1995 JLB : Created. * 225 *=============================================================================================*/ 226 int ObjectTypeClass::Time_To_Build(HousesType ) const 227 { 228 return(0); 229 } 230 231 232 /*********************************************************************************************** 233 * ObjectTypeClass::Who_Can_Build_Me -- Finds the factory building that can build this object. * 234 * * 235 * This routine will search for a factory building that can build this object type. * 236 * * 237 * INPUT: <NA> this routine is just here to be overridden by other classes. * 238 * * 239 * OUTPUT: Returns with a pointer to the building that can construct the object specified. * 240 * * 241 * WARNINGS: none * 242 * * 243 * HISTORY: * 244 * 07/19/1995 JLB : Created. * 245 *=============================================================================================*/ 246 BuildingClass * ObjectTypeClass::Who_Can_Build_Me(bool, bool, HousesType) const 247 { 248 return(NULL); 249 } 250 251 252 /*********************************************************************************************** 253 * ObjectTypeClass::Get_Cameo_Data -- Fetches pointer to cameo data for this object type. * 254 * * 255 * This routine will return with the cameo data pointer for this object type. It is * 256 * expected that objects that can appear on the sidebar will override this routine in order * 257 * to provide proper cameo data pointer. * 258 * * 259 * INPUT: none * 260 * * 261 * OUTPUT: Returns with a pointer to the cameo shape data. * 262 * * 263 * WARNINGS: none * 264 * * 265 * HISTORY: * 266 * 07/19/1995 JLB : Created. * 267 *=============================================================================================*/ 268 void const * ObjectTypeClass::Get_Cameo_Data(void) const 269 { 270 return(NULL); 271 } 272 273 274 275 /*********************************************************************************************** 276 * ObjectClass::ObjectClass -- Default constructor for objects. * 277 * * 278 * This is the default constructor for objects. It is called as an inherent part of the * 279 * construction process for all the normal game objects instantiated. It serves merely to * 280 * initialize the object values to a common (default) state. * 281 * * 282 * INPUT: none * 283 * * 284 * OUTPUT: none * 285 * * 286 * WARNINGS: Objects always start in a state of limbo. They must be Unlimbo()ed before they * 287 * can be used. * 288 * * 289 * HISTORY: * 290 * 09/24/1994 JLB : Created. * 291 *=============================================================================================*/ 292 ObjectClass::ObjectClass(void) 293 { 294 Coord = 0xFFFFFFFFL; // Some bogus illegal value. 295 Next = 0; // Not part of any object list. 296 Trigger = 0; // No associated trigger. 297 IsToDamage = false; 298 IsToDisplay = false; // Redraw is presumed unnecessary. 299 IsInLimbo = true; // Always presumed to start in limbo state. 300 IsSelected = false; // Limboed units cannot be selected. 301 IsDown = false; // Limboed units cannot be on the map. 302 IsAnimAttached = false; // Anim is not attached. 303 Strength = 255; // nominal strength value 304 IsSelectedMask = 0; // Mask showing who has selected this object 305 } 306 307 308 /*********************************************************************************************** 309 * ObjectClass::What_Am_I -- RTTI query of this object type. * 310 * * 311 * This routine will never be called, but is here for completeness. Every object that * 312 * is derived from object class must overload this function and return their own proper * 313 * object RTTI value. * 314 * * 315 * INPUT: none * 316 * * 317 * OUTPUT: Returns with the RTTI value that coresponds to the object's type. * 318 * * 319 * WARNINGS: none * 320 * * 321 * HISTORY: * 322 * 07/19/1995 JLB : Created. * 323 *=============================================================================================*/ 324 RTTIType ObjectClass::What_Am_I(void) const 325 { 326 return(RTTI_OBJECT); 327 } 328 329 330 /*********************************************************************************************** 331 * ObjectClass::What_Action -- Deteremines what action to perform on specified object. * 332 * * 333 * This routine will return that action that this object could perform if the mouse were * 334 * clicked over the object specified. * 335 * * 336 * INPUT: object -- Pointer to the object to check this object against when determining * 337 * the action to perform. * 338 * * 339 * OUTPUT: It returns that action that will be performed if the mouse were clicked over the * 340 * object. Since non-derived objects cannot do anything, and cannot even be * 341 * instantiated, this routine will always return ACTION_NONE. * 342 * * 343 * WARNINGS: none * 344 * * 345 * HISTORY: * 346 * 07/19/1995 JLB : Created. * 347 *=============================================================================================*/ 348 ActionType ObjectClass::What_Action(ObjectClass *) const 349 { 350 return(ACTION_NONE); 351 } 352 353 354 /*********************************************************************************************** 355 * ObjectClass::What_Action -- Returns with the action to perform for this object. * 356 * * 357 * This routine is called when information on a potential action if the mouse were clicked * 358 * on the cell specified. This routine merely serves as a virtual placeholder so that * 359 * object types that can actually perform some action will override this routine to provide * 360 * true functionality. * 361 * * 362 * INPUT: cell -- The cell that the mouse is over and might be clicked on. * 363 * * 364 * OUTPUT: Returns with the action that this object would try to perform if the mouse were * 365 * clicked. Since objects at this level have no ability to do anything, this routine * 366 * will always returns ACTION_NONE unless it is overridden. * 367 * * 368 * WARNINGS: none * 369 * * 370 * HISTORY: * 371 * 08/13/1995 JLB : Created. * 372 *=============================================================================================*/ 373 ActionType ObjectClass::What_Action(CELL) const 374 { 375 return(ACTION_NONE); 376 } 377 378 379 /*********************************************************************************************** 380 * ObjectClass::In_Which_Layer -- Fetches what layer this object is located in. * 381 * * 382 * The default layer for object location is the LAYER_GROUND. Aircraft will override this * 383 * routine and make adjustments as necessary according to the aircraft's altitude. * 384 * * 385 * INPUT: none * 386 * * 387 * OUTPUT: Returns with the layer that this object is located in. * 388 * * 389 * WARNINGS: none * 390 * * 391 * HISTORY: * 392 * 08/13/1995 JLB : Created. * 393 *=============================================================================================*/ 394 LayerType ObjectClass::In_Which_Layer(void) const 395 { 396 return(LAYER_GROUND); 397 } 398 399 400 /*********************************************************************************************** 401 * ObjectClass::Is_Techno -- Checks to see if this object is a techno type. * 402 * * 403 * Most active objects in the game are of the techno type. This routine will return true * 404 * if called on an object that is derived from TechnoClass. The RTTI interface is * 405 * insufficient for this purpose -- hence the existence of this routine. * 406 * * 407 * INPUT: none * 408 * * 409 * OUTPUT: Is this object derived from the TechnoClass object? This is true for units, * 410 * infantry, aircraft, and buildings. * 411 * * 412 * WARNINGS: none * 413 * * 414 * HISTORY: * 415 * 08/13/1995 JLB : Created. * 416 *=============================================================================================*/ 417 bool ObjectClass::Is_Techno(void) const 418 { 419 return(false); 420 } 421 422 423 /*********************************************************************************************** 424 * ObjectClass::Get_Ownable -- Fetches the house owner legality options for this object. * 425 * * 426 * This routine will return the ownable bits for this object. Objects at this level can't * 427 * really be owned by anyone, but return the full spectrum of legality just to be safe. * 428 * * 429 * INPUT: none * 430 * * 431 * OUTPUT: Returns with the ownable flags (as a combined bitfield) for this object. * 432 * * 433 * WARNINGS: none * 434 * * 435 * HISTORY: * 436 * 08/13/1995 JLB : Created. * 437 *=============================================================================================*/ 438 unsigned char ObjectClass::Get_Ownable(void) const 439 { 440 return(0xff); 441 } 442 443 444 /*********************************************************************************************** 445 * ObjectClass::Can_Repair -- Queries whether this object can be repaired. * 446 * * 447 * Most objects cannot be repaired. This routine defaults to returning "false", but is * 448 * overridden by derived functions defined by object types that can support repair. * 449 * * 450 * INPUT: none * 451 * * 452 * OUTPUT: Can this object be repaired? * 453 * * 454 * WARNINGS: none * 455 * * 456 * HISTORY: * 457 * 08/13/1995 JLB : Created. * 458 *=============================================================================================*/ 459 bool ObjectClass::Can_Repair(void) const 460 { 461 return(false); 462 } 463 464 465 /*********************************************************************************************** 466 * ObjectClass::Can_Demolish -- Queries whether this object can be sold back. * 467 * * 468 * This routine is used to determine if this object can be sold. Most objects cannot be * 469 * but for those objects that can, this routine will be overridden as necessary. * 470 * * 471 * INPUT: none * 472 * * 473 * OUTPUT: Can this object be sold back? Typically, the answer is no. * 474 * * 475 * WARNINGS: none * 476 * * 477 * HISTORY: * 478 * 08/13/1995 JLB : Created. * 479 *=============================================================================================*/ 480 bool ObjectClass::Can_Demolish(void) const 481 { 482 return(false); 483 } 484 485 486 bool ObjectClass::Can_Demolish_Unit(void) const 487 { 488 return(false); 489 } 490 491 492 bool ObjectClass::Can_Capture(void) const 493 { 494 return(false); 495 } 496 497 498 /*********************************************************************************************** 499 * ObjectClass::Can_Player_Fire -- Can the player give this object an attack mission? * 500 * * 501 * This routine is used to determine if attacking is an option under player control with * 502 * respect to this unit. This routine will be overridden as necessary for those objects * 503 * that have the ability to attack. * 504 * * 505 * INPUT: none * 506 * * 507 * OUTPUT: Can this object be given an attack order by the player? * 508 * * 509 * WARNINGS: none * 510 * * 511 * HISTORY: * 512 * 08/13/1995 JLB : Created. * 513 *=============================================================================================*/ 514 bool ObjectClass::Can_Player_Fire(void) const 515 { 516 return(false); 517 } 518 519 520 /*********************************************************************************************** 521 * ObjectClass::Can_Player_Move -- Can the player give this object a movement mission? * 522 * * 523 * This routine is used to determine if the player has the ability to command this object * 524 * with a movement mission. This routine will be overridden as necessary to support this * 525 * ability. * 526 * * 527 * INPUT: none * 528 * * 529 * OUTPUT: Can this object be given a movement mission by the player? * 530 * * 531 * WARNINGS: none * 532 * * 533 * HISTORY: * 534 * 08/13/1995 JLB : Created. * 535 *=============================================================================================*/ 536 bool ObjectClass::Can_Player_Move(void) const 537 { 538 return(false); 539 } 540 541 542 /*********************************************************************************************** 543 * ObjectClass::Target_Coord -- Fetches the coordinate if this object is a target. * 544 * * 545 * When the coordinate to use when firing at this object is needed, this routine will * 546 * provide it. Normal objects just use the center of the object for this, but there are * 547 * some more sophisticated objects that are not fired upon the center. * 548 * * 549 * INPUT: none * 550 * * 551 * OUTPUT: Returns with the coordinate to fire at if this object is a target. * 552 * * 553 * WARNINGS: none * 554 * * 555 * HISTORY: * 556 * 08/13/1995 JLB : Created. * 557 *=============================================================================================*/ 558 COORDINATE ObjectClass::Target_Coord(void) const 559 { 560 return(Center_Coord()); 561 } 562 563 COORDINATE ObjectClass::Center_Coord(void) const {return Coord;}; 564 COORDINATE ObjectClass::Render_Coord(void) const {return(Center_Coord());} 565 COORDINATE ObjectClass::Docking_Coord(void) const {return(Center_Coord());} 566 COORDINATE ObjectClass::Sort_Y(void) const {return Coord;}; 567 FireDataType ObjectClass::Fire_Data(int which) const {return{Fire_Coord(which),0};} 568 COORDINATE ObjectClass::Fire_Coord(int ) const {return Coord;}; 569 void ObjectClass::Record_The_Kill(TechnoClass * ) {}; 570 void ObjectClass::Do_Shimmer(void) {}; 571 int ObjectClass::Exit_Object(TechnoClass *) {return 0;}; 572 void ObjectClass::Hidden(void) {}; 573 void ObjectClass::Look(bool ) {}; 574 void ObjectClass::Active_Click_With(ActionType , ObjectClass *) {}; 575 void ObjectClass::Active_Click_With(ActionType , CELL ) {}; 576 void ObjectClass::Clicked_As_Target(HousesType house, int) {}; // 2019/09/20 JAS - Added record of who clicked on the object 577 bool ObjectClass::In_Range(COORDINATE , int) const {return false;}; 578 int ObjectClass::Weapon_Range(int) const {return 0x0000;}; 579 TARGET ObjectClass::As_Target(void) const {return TARGET_NONE;}; 580 void ObjectClass::Scatter(COORDINATE , bool, bool) {}; 581 bool ObjectClass::Catch_Fire(void) {return false;}; 582 583 584 /*********************************************************************************************** 585 * ObjectClass::Fire_Out -- Informs object that attached animation has finished. * 586 * * 587 * This routine is called if there is an attached animation on this object and that * 588 * animation has finished. Typically, this is necessary for when trees are on fire. * 589 * * 590 * INPUT: none * 591 * * 592 * OUTPUT: none * 593 * * 594 * WARNINGS: none * 595 * * 596 * HISTORY: * 597 * 07/24/1995 JLB : Created. * 598 *=============================================================================================*/ 599 void ObjectClass::Fire_Out(void) 600 { 601 } 602 603 604 /*********************************************************************************************** 605 * ObjectClass::Value -- Fetches the target value of this object. * 606 * * 607 * This routine will return the target value of this object. The higher the number, the * 608 * better the object will be as a target. This routine is called when searching for * 609 * targets. Generic objects have no target potential, and this routine returns zero to * 610 * reflect that. Other object types will override this routine to return the appropriate * 611 * target value. * 612 * * 613 * INPUT: none * 614 * * 615 * OUTPUT: Returns with the value of this object as a target. Higher values mean better * 616 * target. * 617 * * 618 * WARNINGS: none * 619 * * 620 * HISTORY: * 621 * 07/24/1995 JLB : Created. * 622 *=============================================================================================*/ 623 int ObjectClass::Value(void) const 624 { 625 return(0); 626 } 627 628 629 /*********************************************************************************************** 630 * ObjectClass::Get_Mission -- Fetches the current mission of this object. * 631 * * 632 * Generic objects don't have a mission, so this routine will just return MISSION_NONE. * 633 * However, techno objects do have a mission and this routine is overloaded to handle * 634 * those objects in order to return the correct mission value. * 635 * * 636 * INPUT: none * 637 * * 638 * OUTPUT: Returns with the current mission being followed by this object. * 639 * * 640 * WARNINGS: none * 641 * * 642 * HISTORY: * 643 * 07/24/1995 JLB : Created. * 644 *=============================================================================================*/ 645 MissionType ObjectClass::Get_Mission(void) const 646 { 647 return(MISSION_NONE); 648 } 649 650 651 /*********************************************************************************************** 652 * ObjectClass::Repair -- Handles object repair control. * 653 * * 654 * This routine will control object repair mode. At the object level, no repair is * 655 * possible, so it is expected that any object that can repair will override this function * 656 * as necessary. * 657 * * 658 * INPUT: control -- The repair control parameter. * 659 * 0 = turn repair off * 660 * 1 = turn repair on * 661 * -1 = toggle repair state * 662 * * 663 * OUTPUT: none * 664 * * 665 * WARNINGS: none * 666 * * 667 * HISTORY: * 668 * 07/24/1995 JLB : Created. * 669 *=============================================================================================*/ 670 void ObjectClass::Repair(int ) 671 { 672 } 673 674 675 /*********************************************************************************************** 676 * ObjectClass::Sell_Back -- Sells the object -- if possible. * 677 * * 678 * This routine is called to sell back the object. Override this routine for the more * 679 * sophisticated objects that can actually be sold back. Normal objects can't be sold and * 680 * this routine does nothing as a consequence. * 681 * * 682 * INPUT: control -- How to control the sell state of this object. * 683 * 0 = stop selling. * 684 * 1 = start selling. * 685 * -1 = toggle selling state. * 686 * * 687 * OUTPUT: none * 688 * * 689 * WARNINGS: none * 690 * * 691 * HISTORY: * 692 * 07/19/1995 JLB : Created. * 693 *=============================================================================================*/ 694 void ObjectClass::Sell_Back(int ) 695 { 696 } 697 698 699 /*********************************************************************************************** 700 * ObjectClass::Move -- Moves (by force) the object in the desired direction. * 701 * * 702 * This routine will instantly move the object one cell in the specified direction. It * 703 * moves the object by force. This is typically ONLY used by the scenario editor * 704 * process. * 705 * * 706 * INPUT: facing -- The direction to move the object. * 707 * * 708 * OUTPUT: none * 709 * * 710 * WARNINGS: Naturally, this can cause illegal placement situations -- use with caution. * 711 * * 712 * HISTORY: * 713 * 06/19/1994 JLB : Created. * 714 *=============================================================================================*/ 715 void ObjectClass::Move(FacingType facing) 716 { 717 COORDINATE coord; 718 719 Mark(MARK_UP); 720 coord = Adjacent_Cell(Coord, facing); 721 if (Can_Enter_Cell(Coord_Cell(coord)) == MOVE_OK) { 722 Coord = coord; 723 } 724 Mark(MARK_DOWN); 725 } 726 727 // Object selection list is switched with player context for GlyphX. ST - 4/17/2019 9:42AM 728 extern void Logic_Switch_Player_Context(ObjectClass *object); 729 730 /*********************************************************************************************** 731 * ObjectClass::Unselect -- This will un-select the object if it was selected. * 732 * * 733 * This routine brings a currently selected object into an unselected state. This is * 734 * needed when another object becomes selected as well as if the object is destroyed. * 735 * * 736 * INPUT: none * 737 * * 738 * OUTPUT: none * 739 * * 740 * WARNINGS: none * 741 * * 742 * HISTORY: * 743 * 06/19/1994 JLB : Created. * 744 *=============================================================================================*/ 745 void ObjectClass::Unselect(void) 746 { 747 //if (IsSelected) { 748 // Updated to function for multiplayer - 6/26/2019 JAS 749 if (Is_Selected_By_Player()) { 750 751 if (In_Which_Layer()==LAYER_GROUND){ 752 Mark(MARK_OVERLAP_UP); 753 } 754 755 //IsSelected = false; 756 // Updated to function for multiplayer - 6/26/2019 JAS 757 Set_Unselected_By_Player(); 758 759 if (In_Which_Layer()==LAYER_GROUND){ 760 Mark(MARK_OVERLAP_DOWN); 761 } 762 } 763 } 764 765 /*********************************************************************************************** 766 * ObjectClass::Unselect_All_Players -- This will un-select the object if it was selected * 767 * from all players * 768 * * 769 * This routine brings a currently selected object into an unselected state for all players.* 770 * This is needed when the object is destroyed. * 771 * * 772 * INPUT: none * 773 * * 774 * OUTPUT: none * 775 * * 776 * WARNINGS: none * 777 * * 778 * HISTORY: * 779 * 06/25/2019 JAS : Created. * 780 *=============================================================================================*/ 781 void ObjectClass::Unselect_All_Players(void) 782 { 783 CurrentObject.Delete_All(this); 784 785 if (In_Which_Layer() == LAYER_GROUND) { 786 Mark(MARK_OVERLAP_UP); 787 } 788 789 IsSelected = false; 790 IsSelectedMask = 0; 791 792 if (In_Which_Layer() == LAYER_GROUND) { 793 Mark(MARK_OVERLAP_DOWN); 794 } 795 } 796 797 /*********************************************************************************************** 798 * ObjectClass::Unselect_All_Players_Except_Owner -- This will un-select the object if it was * 799 * selected for all players except for the object's owner * 800 * * 801 * This routine brings a currently selected object into an unselected state for all players.* 802 * This is needed when the object cloaks. * 803 * * 804 * INPUT: none * 805 * * 806 * OUTPUT: none * 807 * * 808 * WARNINGS: none * 809 * * 810 * HISTORY: * 811 * 06/28/2019 JAS : Created. * 812 *=============================================================================================*/ 813 void ObjectClass::Unselect_All_Players_Except_Owner(void) 814 { 815 CurrentObject.Delete_All_Except(this, Owner()); 816 817 if (In_Which_Layer() == LAYER_GROUND) { 818 Mark(MARK_OVERLAP_UP); 819 } 820 821 int owner_mask = 1 << Owner(); 822 if (IsSelectedMask & owner_mask) 823 { 824 IsSelected = true; 825 IsSelectedMask = owner_mask; 826 } 827 else 828 { 829 IsSelected = false; 830 IsSelectedMask = 0; 831 } 832 833 if (In_Which_Layer() == LAYER_GROUND) { 834 Mark(MARK_OVERLAP_DOWN); 835 } 836 } 837 838 839 /*********************************************************************************************** 840 * ObjectClass::Select -- Try to make this object the "selected" object. * 841 * * 842 * This routine is used to make this object into the one that is "selected". A selected * 843 * object usually displays a floating bar graph and is available to be given orders from * 844 * the player's I/O. * 845 * * 846 * INPUT: allow_mixed -- Allow a mix of player and non-player controlled units? * 847 * * 848 * OUTPUT: none * 849 * * 850 * WARNINGS: none * 851 * * 852 * HISTORY: * 853 * 06/19/1994 JLB : Created. * 854 * 06/12/1995 JLB : Cannot select a loaner object. * 855 * 07/23/1995 JLB : Adds to head or tail depending on leader type flag. * 856 *=============================================================================================*/ 857 bool ObjectClass::Select(bool allow_mixed) 858 { 859 // if (!Debug_Map && (IsSelected || !Class_Of().IsSelectable)) return(false); 860 // Updated to function for multiplayer - 6/26/2019 JAS 861 if (!Debug_Map && (Is_Selected_By_Player() || !Class_Of().IsSelectable)) return(false); 862 863 if (Can_Player_Move() && Is_Techno() && ((TechnoClass *)this)->IsALoaner) return(false); 864 865 /* 866 ** Don't allow selection of object when in building placement mode. 867 */ 868 if (Map.PendingObject) return(false); 869 870 if (!allow_mixed) { 871 /* 872 ** If selecting an object of a different house than the player's, make sure that 873 ** the entire selection list is cleared. 874 */ 875 for (int i = 0; i < CurrentObject.Count(); i++) { 876 if (Owner() != CurrentObject[i]->Owner()) { 877 Unselect_All(); 878 break; 879 } 880 } 881 } 882 883 if (In_Which_Layer()==LAYER_GROUND){ 884 Mark(MARK_OVERLAP_UP); 885 } 886 887 //IsSelected = true; 888 // Updated to function for multiplayer - 6/26/2019 JAS 889 Set_Selected_By_Player(); 890 891 if (In_Which_Layer()==LAYER_GROUND){ 892 Mark(MARK_OVERLAP_DOWN); 893 } 894 return(true); 895 } 896 897 898 /*********************************************************************************************** 899 * ObjectClass::Render -- Displays the object onto the map. * 900 * * 901 * This routine will determine the location of the object and if it is roughly on the * 902 * visible screen, it will display it. Not displaying objects that are not on the screen * 903 * will save valuable time. * 904 * * 905 * INPUT: bool; Should the render be forced regardless of whether the object is flagged to * 906 * be redrawn? * 907 * * 908 * OUTPUT: bool; Was the draw code called for this object? * 909 * * 910 * WARNINGS: none * 911 * * 912 * HISTORY: * 913 * 06/19/1994 JLB : Created. * 914 *=============================================================================================*/ 915 bool ObjectClass::Render(bool forced) 916 { 917 int x,y; 918 COORDINATE coord = Render_Coord(); 919 CELL cell = Coord_Cell(coord); 920 921 if (Debug_Map || Debug_Unshroud || ((forced || IsToDisplay) && IsDown && !IsInLimbo)) { 922 IsToDisplay = false; 923 924 /* 925 ** Draw the path as lines on the map if so directed and the object is one that 926 ** contains a path. 927 */ 928 929 //if (Special.IsShowPath && IsSelected) { 930 // Updated to function for multiplayer - 6/26/2019 JAS 931 if (Special.IsShowPath && Is_Selected_By_Player()) { 932 switch (What_Am_I()) { 933 case RTTI_INFANTRY: 934 case RTTI_UNIT: 935 FootClass * foot = (FootClass *)this; 936 CELL cell; 937 int oldx, oldy; 938 939 if (foot->Head_To_Coord() && foot->Path[0] != FACING_NONE) { 940 cell = Adjacent_Cell(Coord_Cell(foot->Head_To_Coord()), (FacingType)((foot->Path[0] + FACING_S) & FACING_NW)); 941 Map.Coord_To_Pixel(Cell_Coord(cell), oldx, oldy); 942 for (int index = 0; index < MAX_PATH; index++) { 943 if (foot->Path[index] == FACING_NONE) break; 944 cell = Adjacent_Cell(cell, foot->Path[index]); 945 if (Map.Coord_To_Pixel(Cell_Coord(cell), x, y)) { 946 LogicPage->Draw_Line(oldx, 8+oldy, x, 8+y, BLACK); 947 } 948 oldx = x; 949 oldy = y; 950 } 951 } 952 break; 953 } 954 } 955 956 if (Map.Coord_To_Pixel(coord, x, y)) { 957 958 /* 959 ** Draw the object itself 960 */ 961 Draw_It(x, y, WINDOW_TACTICAL); 962 963 #ifdef SCENARIO_EDITOR 964 /* 965 ** Draw the trigger attached to the object. Draw_It is window- 966 ** relative, so add the window's x-coord to 'x'. 967 */ 968 if (Debug_Map && Trigger) { 969 Fancy_Text_Print(Trigger->Get_Name(), x + (WinX<<3), y, PINK, TBLACK, TPF_CENTER | TPF_NOSHADOW | TPF_6POINT); 970 } 971 #endif 972 973 return(true); 974 } 975 } 976 return(false); 977 } 978 979 980 #ifdef CHEAT_KEYS 981 /*********************************************************************************************** 982 * ObjectClass::Debug_Dump -- Displays status of the object class to the mono monitor. * 983 * * 984 * This routine is used to display the current status of the object class to the mono * 985 * monitor. * 986 * * 987 * INPUT: none * 988 * * 989 * OUTPUT: none * 990 * * 991 * WARNINGS: none * 992 * * 993 * HISTORY: * 994 * 06/02/1994 JLB : Created. * 995 *=============================================================================================*/ 996 void ObjectClass::Debug_Dump(MonoClass *mono) const 997 { 998 mono->Text_Print("X", 16 + (IsToDisplay?2:0), 18); 999 mono->Text_Print("X", 16 + (IsActive?2:0), 3); 1000 mono->Text_Print("X", 16 + (IsInLimbo?2:0), 4); 1001 //mono->Text_Print("X", 16 + (IsSelected?2:0), 7); 1002 // Updated to function for multiplayer - 6/26/2019 JAS 1003 mono->Text_Print("X", 16 + (Is_Selected_By_Player() ?2:0), 7); 1004 mono->Set_Cursor(56, 1); 1005 mono->Printf("%08lX", Coord); 1006 mono->Set_Cursor(14, 1);mono->Printf("[%04X]", As_Target()); 1007 mono->Set_Cursor(20, 3);mono->Printf("%2d[%d]", Strength, Class_Of().MaxStrength); 1008 } 1009 #endif 1010 1011 1012 /*********************************************************************************************** 1013 * ObjectTypeClass::Occupy_List -- Returns with simple occupation list for object. * 1014 * * 1015 * This routine returns a pointer to a simple occupation list for this object. Since at * 1016 * this tier of the object class chain, the exact shape of the object is indeterminate, * 1017 * this function merely returns a single cell occupation list. This actually works for * 1018 * most vehicles. * 1019 * * 1020 * INPUT: none * 1021 * * 1022 * OUTPUT: Returns a pointer to a simple occupation list. * 1023 * * 1024 * WARNINGS: none * 1025 * * 1026 * HISTORY: * 1027 * 05/28/1994 JLB : Created. * 1028 *=============================================================================================*/ 1029 short const * ObjectTypeClass::Occupy_List(bool) const 1030 { 1031 static short const _list[] = {0, REFRESH_EOL}; 1032 return(_list); 1033 } 1034 1035 1036 /*********************************************************************************************** 1037 * ObjectTypeClass::Overlap_List -- Returns a pointer to a simple overlap list. * 1038 * * 1039 * This function returns a pointer to an overlap list for the object. An overlap list is * 1040 * the offsets from the object's cell to get the cells the imagery overlaps, but is object * 1041 * is not considered to occupy. Since at this stage, the overlap information is not * 1042 * available, this function merely returns a pointer to an empty list. * 1043 * * 1044 * INPUT: none * 1045 * * 1046 * OUTPUT: Returns a pointer to the generic overlap list. * 1047 * * 1048 * WARNINGS: none * 1049 * * 1050 * HISTORY: * 1051 * 05/28/1994 JLB : Created. * 1052 *=============================================================================================*/ 1053 short const * ObjectTypeClass::Overlap_List(void) const 1054 { 1055 static short const _list[] = {REFRESH_EOL}; 1056 return(_list); 1057 } 1058 1059 1060 /*********************************************************************************************** 1061 * ObjectTypeClass::One_Time -- Handles one time processing for object types. * 1062 * * 1063 * This routine is used to handle the once per game processing required for object types. * 1064 * This consists of loading any data and initializing any data tables the game requires. * 1065 * * 1066 * INPUT: none * 1067 * * 1068 * OUTPUT: none * 1069 * * 1070 * WARNINGS: This routine goes to disk. * 1071 * * 1072 * HISTORY: * 1073 * 11/01/1994 JLB : Created. * 1074 *=============================================================================================*/ 1075 void ObjectTypeClass::One_Time(void) 1076 { 1077 SelectShapes = MixFileClass::Retrieve("SELECT.SHP"); 1078 #if (FRENCH) 1079 PipShapes = Hires_Retrieve("PIPS_F.SHP"); 1080 #else 1081 #if (GERMAN) 1082 PipShapes = Hires_Retrieve("PIPS_G.SHP"); 1083 #else 1084 PipShapes = Hires_Retrieve("PIPS.SHP"); 1085 #endif 1086 #endif 1087 } 1088 1089 1090 /*********************************************************************************************** 1091 * ObjectClass::Mark_For_Redraw -- Marks object and system for redraw. * 1092 * * 1093 * This routine will mark the object and inform the display system * 1094 * that appropriate rendering is needed. Whenever it is determined * 1095 * that an object needs to be redrawn, call this routine. * 1096 * * 1097 * INPUT: none * 1098 * * 1099 * OUTPUT: none * 1100 * * 1101 * WARNINGS: This is a subordinate function to the function Mark(). If an object needs to * 1102 * be redrawn it is probably better to call the function Mark(MARK_CHANGE) rather * 1103 * than this function. This function does not inform the map system that * 1104 * overlapping objects are to be redrawn and thus unless you are really sure that * 1105 * this routine should be called, don't. * 1106 * * 1107 * HISTORY: * 1108 * 05/08/1994 JLB : Created. * 1109 * 12/23/1994 JLB : Flags map and flags unit only. * 1110 *=============================================================================================*/ 1111 void ObjectClass::Mark_For_Redraw(void) 1112 { 1113 if (!IsToDisplay) { 1114 IsToDisplay = true; 1115 1116 /* 1117 ** This tells the map rendering logic to "go through the motions" and call the 1118 ** rendering function. In the rendering function, it will sort out what gets 1119 ** rendered and what doesn't. 1120 */ 1121 Map.Flag_To_Redraw(false); 1122 } 1123 } 1124 1125 1126 /*********************************************************************************************** 1127 * ObjectClass::Limbo -- Brings the object into a state of limbo. * 1128 * * 1129 * An object brought into a state of limbo by this routine can be safely deleted. This * 1130 * routine will remove the object from all game lists and tracking systems. It is called * 1131 * prior to deleting the object or placing the object "on ice". * 1132 * * 1133 * INPUT: none * 1134 * * 1135 * OUTPUT: bool; Was the object successfully placed in limbo? * 1136 * * 1137 * WARNINGS: none * 1138 * * 1139 * HISTORY: * 1140 * 09/24/1994 JLB : Created. * 1141 *=============================================================================================*/ 1142 bool ObjectClass::Limbo(void) 1143 { 1144 if (GameActive && !IsInLimbo) { 1145 1146 //Unselect(); 1147 // Updated to function for multiplayer - 6/26/2019 JAS 1148 Unselect_All_Players(); 1149 1150 Detach_All(); 1151 Mark(MARK_UP); 1152 1153 /* 1154 ** Remove the object from the appropriate display list. 1155 */ 1156 Map.Remove(this, In_Which_Layer()); 1157 1158 /* 1159 ** Remove the object from the logic processing list. 1160 */ 1161 if (Class_Of().IsSentient) { 1162 Logic.Delete(this); 1163 } 1164 1165 Hidden(); 1166 IsInLimbo = true; 1167 IsToDisplay = false; 1168 return(true); 1169 } 1170 return(false); 1171 } 1172 1173 1174 /*********************************************************************************************** 1175 * ObjectClass::Unlimbo -- Brings the object into the game system. * 1176 * * 1177 * This routine will place the object into the game tracking and display systems. It is * 1178 * called as a consequence of creating the object. Every game object must be unlimboed at * 1179 * some point. * 1180 * * 1181 * INPUT: coord -- The coordinate to place the object into the game system. * 1182 * * 1183 * dir (optional) -- initial facing direction for this object * 1184 * * 1185 * OUTPUT: bool; Was the game object successfully unlimboed? * 1186 * * 1187 * WARNINGS: none * 1188 * * 1189 * HISTORY: * 1190 * 09/24/1994 JLB : Created. * 1191 * 12/23/1994 JLB : Sets object strength. * 1192 *=============================================================================================*/ 1193 bool ObjectClass::Unlimbo(COORDINATE coord, DirType ) 1194 { 1195 if (GameActive && IsInLimbo && !IsDown) { 1196 if (ScenarioInit || Can_Enter_Cell(Coord_Cell(coord), FACING_NONE) == MOVE_OK) { 1197 IsInLimbo = false; 1198 IsToDisplay = false; 1199 Coord = Class_Of().Coord_Fixup(coord); 1200 1201 if (Mark(MARK_DOWN)) { 1202 if (IsActive) { 1203 1204 /* 1205 ** Add the object to the appropriate map layer. This layer is used 1206 ** for rendering purposes. 1207 */ 1208 if (In_Which_Layer() != LAYER_NONE) { 1209 Map.Submit(this, In_Which_Layer()); 1210 } 1211 1212 if (Class_Of().IsSentient) { 1213 Logic.Submit(this); 1214 } 1215 } 1216 return(true); 1217 } 1218 } 1219 } 1220 return(false); 1221 } 1222 1223 1224 /*********************************************************************************************** 1225 * ObjectClass::Detach_All -- Removes the object from all tracking systems. * 1226 * * 1227 * This routine will take the object and see that it is removed from all miscellaneous * 1228 * tracking systems in the game. This operation is vital when deleting an object. It is * 1229 * necessary so that when the object is removed from the game, existing game objects won't * 1230 * be referencing a now invalid game object. This typically affects the targeting * 1231 * and navigation computers of other game objects. * 1232 * * 1233 * INPUT: none * 1234 * * 1235 * OUTPUT: none * 1236 * * 1237 * WARNINGS: none * 1238 * * 1239 * HISTORY: * 1240 * 09/24/1994 JLB : Created. * 1241 *=============================================================================================*/ 1242 void ObjectClass::Detach_All(bool all) 1243 { 1244 /* 1245 ** Unselect this object if it was selected. 1246 */ 1247 //if (all || Owner() != PlayerPtr->Class->House) { 1248 // Unselect(); 1249 //} 1250 1251 //Added some error handling incase there was an issue removing the object - JAS 6/28/2019 1252 if (all) { 1253 //Unselect(); 1254 // Updated to function for multiplayer - 6/28/2019 JAS 1255 Unselect_All_Players(); 1256 } 1257 else 1258 { 1259 Unselect_All_Players_Except_Owner(); 1260 } 1261 //End of change - JAS 6/28/2019 1262 1263 Map.Detach(this); 1264 1265 /* 1266 ** Remove from targeting computers. 1267 */ 1268 Detach_This_From_All(As_Target(), all); 1269 } 1270 1271 1272 /*********************************************************************************************** 1273 * ObjectClass::Detach_This_From_All -- Detatches this object from all others. * 1274 * * 1275 * This routine sweeps through all game objects and makes sure that it is no longer * 1276 * referenced by them. Typically, this is called in preparation for the object's death * 1277 * or limbo state. * 1278 * * 1279 * INPUT: target -- This object expressed as a target number. * 1280 * * 1281 * OUTPUT: none * 1282 * * 1283 * WARNINGS: none * 1284 * * 1285 * HISTORY: * 1286 * 05/08/1995 JLB : Created. * 1287 *=============================================================================================*/ 1288 void ObjectClass::Detach_This_From_All(TARGET target, bool all) 1289 { 1290 int index; 1291 if (Target_Legal(target)) { 1292 1293 for (index = 0; index < Houses.Count(); index++) { 1294 Houses.Ptr(index)->Detach(target, all); 1295 } 1296 for (index = 0; index < Teams.Count(); index++) { 1297 Teams.Ptr(index)->Detach(target, all); 1298 } 1299 for (index = 0; index < Units.Count(); index++) { 1300 Units.Ptr(index)->Detach(target, all); 1301 } 1302 for (index = 0; index < Infantry.Count(); index++) { 1303 Infantry.Ptr(index)->Detach(target, all); 1304 } 1305 for (index = 0; index < Aircraft.Count(); index++) { 1306 Aircraft.Ptr(index)->Detach(target, all); 1307 } 1308 for (index = 0; index < Buildings.Count(); index++) { 1309 Buildings.Ptr(index)->Detach(target, all); 1310 } 1311 for (index = 0; index < Bullets.Count(); index++) { 1312 Bullets.Ptr(index)->Detach(target, all); 1313 } 1314 for (index = 0; index < Anims.Count(); index++) { 1315 Anims.Ptr(index)->Detach(target, all); 1316 } 1317 } 1318 } 1319 1320 1321 /*********************************************************************************************** 1322 * ObjectClass::Receive_Message -- Processes an incoming radio message. * 1323 * * 1324 * Any radio message received that applies to objects in general are handled by this * 1325 * routine. Typically, this is the "redraw" message, which occurs when another object is * 1326 * loading or unloading and thus overlapping. * 1327 * * 1328 * INPUT: message -- The message received. * 1329 * * 1330 * OUTPUT: Returns with the appropriate radio response. If the message was recognized, then * 1331 * RADIO_ROGER is returned, otherwise, just RADIO_STATIC is returned. * 1332 * * 1333 * WARNINGS: none * 1334 * * 1335 * HISTORY: * 1336 * 09/24/1994 JLB : Created. * 1337 *=============================================================================================*/ 1338 RadioMessageType ObjectClass::Receive_Message(RadioClass *, RadioMessageType message, long & ) 1339 { 1340 switch (message) { 1341 1342 /* 1343 ** This message serves as a rendering convenience. It lets the system 1344 ** know that there might be a visual conflict and the unit in radio 1345 ** contact should be redrawn. This typically occurs when a vehicle 1346 ** is being unloaded from a hover lander. 1347 */ 1348 case RADIO_REDRAW: 1349 Mark(MARK_CHANGE); 1350 return(RADIO_ROGER); 1351 1352 default: 1353 break; 1354 } 1355 return(RADIO_STATIC); 1356 } 1357 1358 1359 /*********************************************************************************************** 1360 * ObjectClass::Take_Damage -- Applies damage to the object. * 1361 * * 1362 * This routine applies damage to the object according to the damage parameters. It handles * 1363 * reducing the strength of the object and also returns the result of that damage. The * 1364 * result value can be examined to determine if the object was destroyed, greatly damaged, * 1365 * or other results. * 1366 * * 1367 * INPUT: damage -- Reference to the damage number to apply. This number will be adjusted * 1368 * according to defensive armor and distance. Examine this value after * 1369 * the call to determine the actual amount of damage applied. * 1370 * * 1371 * distance -- The distance (in leptons) from the center of the damage causing * 1372 * explosion to the object itself. * 1373 * * 1374 * warhead -- The warhead type that is causing the damage. * 1375 * * 1376 * OUTPUT: Returns the ResultType that indicates what the affect of the damage was. * 1377 * * 1378 * WARNINGS: none * 1379 * * 1380 * HISTORY: * 1381 * 11/29/1994 JLB : Created. * 1382 * 12/27/1994 JLB : Trigger event processing for attacked or destroyed. * 1383 * 01/01/1995 JLB : Reduces damage greatly depending on range. * 1384 *=============================================================================================*/ 1385 ResultType ObjectClass::Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source) 1386 { 1387 ResultType result = RESULT_NONE; 1388 int oldstrength = Strength; 1389 1390 if (oldstrength && damage && !Class_Of().IsImmune) { 1391 int maxstrength = Class_Of().MaxStrength; 1392 1393 /* 1394 ** Modify damage based on the warhead type and the armor of the object. This results 1395 ** in a reduced damage value, but never below 1 damage point. 1396 */ 1397 damage = Modify_Damage(damage, warhead, Class_Of().Armor, distance); 1398 if (!damage) return(RESULT_NONE); 1399 1400 /* 1401 ** At this point, we KNOW that at least light damage has occurred. 1402 */ 1403 result = RESULT_LIGHT; 1404 1405 /* 1406 ** A non-fatal blow has occurred. Check to see if the object transitioned to below 1407 ** half strength or if it is now down to one hit point. 1408 */ 1409 if (oldstrength > damage) { 1410 1411 if (oldstrength >= (maxstrength >> 1) && (oldstrength-damage) < (maxstrength >> 1)) { 1412 result = RESULT_HALF; 1413 } 1414 } else { 1415 1416 /* 1417 ** When an object is damaged to destruction, it will instead stop at one 1418 ** damage point. This will prolong the damage state as well as 1419 ** give greater satisfaction when it is finally destroyed. 1420 */ 1421 damage = oldstrength; 1422 } 1423 1424 /* 1425 ** Apply the damage to the object. 1426 */ 1427 Strength = oldstrength - damage; 1428 1429 /* 1430 ** Check to see if the object is majorly damaged or destroyed. 1431 */ 1432 switch (Strength) { 1433 case 0: 1434 Record_The_Kill(source); 1435 result = RESULT_DESTROYED; 1436 Detach_All(); 1437 break; 1438 1439 case 1: 1440 result = RESULT_MAJOR; 1441 break; 1442 1443 default: 1444 break; 1445 } 1446 1447 /* 1448 ** Handle any trigger event associated with this object. 1449 */ 1450 if (source && Trigger && result != RESULT_DESTROYED) { 1451 Trigger->Spring(EVENT_ATTACKED, this); 1452 } 1453 1454 /* 1455 ** If any damage was assessed and this object is selected, then flag 1456 ** the object to be redrawn so that the health bar will be updated. 1457 */ 1458 //if (result != RESULT_NONE && IsSelected) { 1459 // Updated to function for multiplayer - 6/26/2019 JAS 1460 if (result != RESULT_NONE && Is_Selected_By_Player()) { 1461 Mark(MARK_CHANGE); 1462 } 1463 } 1464 1465 /* 1466 ** Return with the result of the damage taken. 1467 */ 1468 return(result); 1469 } 1470 1471 1472 /*********************************************************************************************** 1473 * ObjectClass::Mark -- Handles basic marking logic. * 1474 * * 1475 * This routine handles the base logic for marking an object up or down on the map. It * 1476 * manages the IsDown flag as well as flagging the object to be redrawn if necessary. * 1477 * Whenever an object is to be marked, it should call this base class function first. If * 1478 * this function returns true, then the higher level function should proceed with its own * 1479 * logic. * 1480 * * 1481 * INPUT: mark -- The marking method to use for this object. It can be either MARK_DOWN, * 1482 * MARK_UP, or MARK_CHANGE. * 1483 * * 1484 * OUTPUT: bool; Was the object marked successfully? * 1485 * * 1486 * WARNINGS: none * 1487 * * 1488 * HISTORY: * 1489 * 01/23/1995 JLB : Created. * 1490 *=============================================================================================*/ 1491 bool ObjectClass::Mark(MarkType mark) 1492 { 1493 TechnoClass *tech; 1494 CELL cell; 1495 int threat; 1496 HousesType house; 1497 1498 if (!IsInLimbo && IsActive) { 1499 1500 /* 1501 ** A mark for change is always successful UNLESS the object 1502 ** is not placed down or has already been flagged as changed 1503 ** this game frame. 1504 */ 1505 if (mark == MARK_CHANGE) { 1506 if (IsToDisplay) return(false); 1507 if (IsDown == true) { 1508 Mark_For_Redraw(); 1509 return(true); 1510 } 1511 return(false); 1512 } 1513 1514 /* 1515 ** Handle adding or removing the object in the cells' overlap lists 1516 */ 1517 if (mark == MARK_OVERLAP_UP) { 1518 if (IsDown == true) { 1519 Map.Overlap_Up(Coord_Cell(Coord),this); 1520 Mark_For_Redraw(); 1521 return(true); 1522 } 1523 } 1524 if (mark == MARK_OVERLAP_DOWN) { 1525 if (IsDown == true) { 1526 Map.Overlap_Down(Coord_Cell(Coord),this); 1527 Mark_For_Redraw(); 1528 return(true); 1529 } 1530 } 1531 1532 /* 1533 ** It is important to know whether the object is a techno class 1534 ** or not to see if we have to adjust the regional threat ratings 1535 */ 1536 if (Is_Techno()) { 1537 tech = (TechnoClass *)this; 1538 threat = tech->Risk(); 1539 house = tech->Owner(); 1540 cell = Coord_Cell(Coord); 1541 } else 1542 tech = NULL; 1543 1544 /* 1545 ** Marking down is only successful if the object isn't already 1546 ** placed down. 1547 */ 1548 if (mark == MARK_DOWN && !IsDown) { 1549 if (tech && GameToPlay == GAME_NORMAL) { 1550 Map[cell].Adjust_Threat(house, threat); 1551 } 1552 IsDown = true; 1553 Mark_For_Redraw(); 1554 return(true); 1555 } 1556 1557 /* 1558 ** Lifting up is only successful if the object isn't already 1559 ** lifted up from the map. 1560 */ 1561 if (mark == MARK_UP && IsDown) { 1562 if (tech && GameToPlay == GAME_NORMAL) { 1563 Map[cell].Adjust_Threat(house, -threat); 1564 } 1565 Map.Overlap_Up(Coord_Cell(Coord), this); 1566 IsDown = false; 1567 return(true); 1568 } 1569 } 1570 return(false); 1571 } 1572 1573 1574 /*********************************************************************************************** 1575 * ObjectClass::Init -- Initializes the basic object system. * 1576 * * 1577 * This routine should be called when the basic object system needs to be initialized. This * 1578 * occurs when the scenario is about to be loaded. * 1579 * * 1580 * INPUT: none * 1581 * * 1582 * OUTPUT: none * 1583 * * 1584 * WARNINGS: none * 1585 * * 1586 * HISTORY: * 1587 * 01/23/1995 JLB : Created. * 1588 *=============================================================================================*/ 1589 void ObjectClass::Init(void) 1590 { 1591 CurrentObject.Clear_All(); 1592 } 1593 1594 1595 /*********************************************************************************************** 1596 * ObjectClass::Revealed -- Reveals this object to the house specified. * 1597 * * 1598 * This routine is called when this object gets revealed to the house specified. * 1599 * * 1600 * INPUT: house -- Pointer to the house that this object is being revealed to. * 1601 * * 1602 * OUTPUT: Was this object revealed for the first time to this house? Generic objects always * 1603 * return true unless an invalid house pointer was specified. * 1604 * * 1605 * WARNINGS: none * 1606 * * 1607 * HISTORY: * 1608 * 07/19/1995 JLB : Created. * 1609 *=============================================================================================*/ 1610 bool ObjectClass::Revealed(HouseClass * house) 1611 { 1612 return(house != NULL); 1613 } 1614 1615 /*********************************************************************************************** 1616 * ObjectClass::Set_Selected_By_Player -- Set this object as selected by the given player or * 1617 * the default player. * 1618 * * 1619 * INPUT: Player pointer * 1620 * * 1621 * OUTPUT: * 1622 * * 1623 * WARNINGS: none * 1624 * * 1625 * HISTORY: * 1626 * 6/25/2019 - JAS * 1627 *=============================================================================================*/ 1628 void ObjectClass::Set_Selected_By_Player(HouseClass *player) 1629 { 1630 if (!player || !player->Class) { 1631 player = PlayerPtr; 1632 } 1633 1634 HousesType house = player->Class->House; 1635 if (((TechnoTypeClass const &)Class_Of()).IsLeader) { 1636 CurrentObject.Add_Head(house, this); 1637 } 1638 else { 1639 CurrentObject.Add(house, this); 1640 } 1641 1642 int shift = (int)house; 1643 IsSelectedMask |= (1 << shift); 1644 1645 if (GameToPlay == GAME_NORMAL && player == PlayerPtr) { 1646 IsSelected = true; 1647 } 1648 } 1649 1650 /*********************************************************************************************** 1651 * ObjectClass::Set_Unselected_By_Player -- Set this object as unselected by the given player * 1652 * orthe default player. * 1653 * * 1654 * INPUT: Player pointer * 1655 * * 1656 * OUTPUT: * 1657 * * 1658 * WARNINGS: none * 1659 * * 1660 * HISTORY: * 1661 * 6/25/2019 - JAS * 1662 *=============================================================================================*/ 1663 void ObjectClass::Set_Unselected_By_Player(HouseClass *player) 1664 { 1665 if (!player || !player->Class) { 1666 player = PlayerPtr; 1667 } 1668 1669 HousesType house = player->Class->House; 1670 CurrentObject.Delete(house, this); 1671 1672 int shift = (int)house; 1673 IsSelectedMask &= ~(1 << shift); 1674 1675 if (GameToPlay == GAME_NORMAL && player == PlayerPtr) { 1676 IsSelected = false; 1677 } 1678 } 1679 1680 /*********************************************************************************************** 1681 * ObjectClass::Is_Selected_By_Player -- Has this object been selected by the given player * 1682 * * 1683 * INPUT: Player pointer * 1684 * * 1685 * OUTPUT: True if selected by that player * 1686 * * 1687 * WARNINGS: none * 1688 * * 1689 * HISTORY: * 1690 * 6/25/2019 - JAS * 1691 *=============================================================================================*/ 1692 bool ObjectClass::Is_Selected_By_Player(HouseClass *player) const 1693 { 1694 if (player && player->Class) { 1695 int shift = (int)player->Class->House; 1696 return (IsSelectedMask & (1 << shift)) ? true : false; 1697 } 1698 else { 1699 int shift = (int)PlayerPtr->Class->House; 1700 return (IsSelectedMask & (1 << shift)) ? true : false; 1701 } 1702 return false; 1703 } 1704 1705 1706 1707 // These can't be made inline (for various reasons). 1708 short const * ObjectClass::Occupy_List(bool placement) const {return(Class_Of().Occupy_List(placement));}; 1709 short const * ObjectClass::Overlap_List(void) const {return(Class_Of().Overlap_List());}; 1710 BuildingClass * ObjectClass::Who_Can_Build_Me(bool intheory, bool legal) const {return(Class_Of().Who_Can_Build_Me(intheory, legal, Owner()));}; 1711 unsigned ObjectClass::Health_Ratio(void) const {return(Cardinal_To_Fixed(Class_Of().MaxStrength, Strength));}; 1712 int ObjectClass::Full_Name(void) const {return Class_Of().Full_Name();}; 1713