COMBAT.CPP 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. ** Command & Conquer(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: F:\projects\c&c\vcs\code\combat.cpv 2.17 16 Oct 1995 16:48:32 JOE_BOSTIC $ */
  19. /***********************************************************************************************
  20. *** 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 ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Command & Conquer *
  24. * *
  25. * File Name : COMBAT.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : September 19, 1994 *
  30. * *
  31. * Last Update : January 1, 1995 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * Explosion_Damage -- Inflict an explosion damage affect. *
  36. * Modify_Damage -- Adjusts damage to reflect the nature of the target. *
  37. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  38. #include "function.h"
  39. int Modify_Damage(int damage, WarheadType warhead, ArmorType armor);
  40. void Explosion_Damage(COORDINATE coord, unsigned strength, TechnoClass *source, WarheadType warhead);
  41. /***********************************************************************************************
  42. * Modify_Damage -- Adjusts damage to reflect the nature of the target. *
  43. * *
  44. * This routine is the core of combat tactics. It implements the *
  45. * affect various armor types have against various weapon types. By *
  46. * careful exploitation of this table, tactical advantage can be *
  47. * obtained. *
  48. * *
  49. * INPUT: damage -- The damage points to process. *
  50. * *
  51. * warhead -- The source of the damage points. *
  52. * *
  53. * armor -- The type of armor defending against the damage. *
  54. * *
  55. * distance -- The distance (in leptons) from the source of the damage. *
  56. * *
  57. * OUTPUT: Returns with the adjusted damage points to inflict upon the *
  58. * target. *
  59. * *
  60. * WARNINGS: none *
  61. * *
  62. * HISTORY: *
  63. * 04/16/1994 JLB : Created. *
  64. * 04/17/1994 JLB : Always does a minimum of damage. *
  65. * 01/01/1995 JLB : Takes into account distance from damage source. *
  66. *=============================================================================================*/
  67. int Modify_Damage(int damage, WarheadType warhead, ArmorType armor, int distance)
  68. {
  69. /*
  70. ** If there is no raw damage value to start with, then
  71. ** there can be no modified damage either.
  72. */
  73. if (Special.IsInert || !damage || warhead == WARHEAD_NONE) return(0);
  74. WarheadTypeClass const * whead = &Warheads[warhead];
  75. damage = Fixed_To_Cardinal(damage, whead->Modifier[armor]);
  76. /*
  77. ** Reduce damage according to the distance from the impact point.
  78. */
  79. if (damage) {
  80. // if (distance < 0x0010) damage *= 2; // Double damage for direct hits.
  81. distance >>= whead->SpreadFactor;
  82. distance = Bound(distance, 0, 16);
  83. damage >>= distance;
  84. }
  85. /*
  86. ** If damage was indicated, then it should never drop below one damage point regardless
  87. ** of modifiers. This allows a very weak attacker to eventually destroy anything it
  88. ** fires upon, given enough time.
  89. */
  90. return(damage);
  91. }
  92. /***********************************************************************************************
  93. * Explosion_Damage -- Inflict an explosion damage affect. *
  94. * *
  95. * Processes the collateral damage affects typically caused by an *
  96. * explosion. *
  97. * *
  98. * INPUT: coord -- The coordinate of ground zero. *
  99. * *
  100. * strength -- Raw damage points at ground zero. *
  101. * *
  102. * source -- Source of the explosion (who is responsible). *
  103. * *
  104. * warhead -- The kind of explosion to process. *
  105. * *
  106. * OUTPUT: none *
  107. * *
  108. * WARNINGS: This routine can consume some time and will affect the AI *
  109. * of nearby enemy units (possibly). *
  110. * *
  111. * HISTORY: *
  112. * 08/16/1991 JLB : Created. *
  113. * 11/30/1991 JLB : Uses coordinate system. *
  114. * 12/27/1991 JLB : Radius of explosion damage effect. *
  115. * 04/13/1994 JLB : Streamlined. *
  116. * 04/16/1994 JLB : Warhead damage type modifier. *
  117. * 04/17/1994 JLB : Cleaned up. *
  118. * 06/20/1994 JLB : Uses object pointers to distribute damage. *
  119. * 06/20/1994 JLB : Source is a pointer. *
  120. *=============================================================================================*/
  121. void Explosion_Damage(COORDINATE coord, unsigned strength, TechnoClass * source, WarheadType warhead)
  122. {
  123. CELL cell; // Cell number under explosion.
  124. ObjectClass * object; // Working object pointer.
  125. ObjectClass * objects[32]; // Maximum number of objects that can be damaged.
  126. int distance; // Distance to unit.
  127. int range; // Damage effect radius.
  128. int index;
  129. int count; // Number of vehicle IDs in list.
  130. if (!strength || Special.IsInert || warhead == WARHEAD_NONE) return;
  131. WarheadTypeClass const * whead = &Warheads[warhead];
  132. range = ICON_LEPTON_W + (ICON_LEPTON_W >> 1);
  133. cell = Coord_Cell(coord);
  134. if ((unsigned)cell >= MAP_CELL_TOTAL) return;
  135. // if (!Map.In_Radar(cell)) return;
  136. CellClass * cellptr = &Map[cell];
  137. ObjectClass * impacto = cellptr->Cell_Occupier();
  138. /*
  139. ** Fill the list of unit IDs that will have damage
  140. ** assessed upon them. The units can be lifted from
  141. ** the cell data directly.
  142. */
  143. count = 0;
  144. for (FacingType i = FACING_NONE; i < FACING_COUNT; i++) {
  145. /*
  146. ** Fetch a pointer to the cell to examine. This is either
  147. ** an adjacent cell or the center cell. Damage never spills
  148. ** further than one cell away.
  149. */
  150. if (i != FACING_NONE) {
  151. cellptr = &Map[cell].Adjacent_Cell(i);
  152. }
  153. /*
  154. ** Add all objects in this cell to the list of objects to possibly apply
  155. ** damage to. The list stops building when the object pointer list becomes
  156. ** full. Do not include overlapping objects; selection state can affect
  157. ** the overlappers, and this causes multiplayer games to go out of sync.
  158. */
  159. object = cellptr->Cell_Occupier();
  160. while (object) {
  161. if (!object->IsToDamage && object != source) {
  162. object->IsToDamage = true;
  163. objects[count++] = object;
  164. if (count >= (sizeof(objects)/sizeof(objects[0]))) break;
  165. }
  166. object = object->Next;
  167. }
  168. if (count >= (sizeof(objects)/sizeof(objects[0]))) break;
  169. }
  170. /*
  171. ** Sweep through the units to be damaged and damage them. When damaging
  172. ** buildings, consider a hit on any cell the building occupies as if it
  173. ** were a direct hit on the building's center.
  174. */
  175. for (index = 0; index < count; index++) {
  176. object = objects[index];
  177. object->IsToDamage = false;
  178. if (object->What_Am_I() == RTTI_BUILDING && impacto == object) {
  179. distance = 0;
  180. } else {
  181. distance = Distance(coord, object->Center_Coord());
  182. }
  183. if (object->IsDown && !object->IsInLimbo && distance < range) {
  184. int damage = strength;
  185. /*
  186. ** High explosive does double damage against aircraft.
  187. */
  188. if (warhead == WARHEAD_HE && object->What_Am_I() == RTTI_AIRCRAFT) {
  189. damage *= 2;
  190. }
  191. /*
  192. ** Apply the damage to the object.
  193. */
  194. if (damage) {
  195. object->Take_Damage(damage, distance, warhead, source);
  196. }
  197. }
  198. }
  199. /*
  200. ** If there is a wall present at this location, it may be destroyed. Check to
  201. ** make sure that the warhead is of the kind that can destroy walls.
  202. */
  203. cellptr = &Map[cell];
  204. cellptr->Reduce_Tiberium(strength / 10);
  205. if (cellptr->Overlay != OVERLAY_NONE) {
  206. OverlayTypeClass const * optr = &OverlayTypeClass::As_Reference(cellptr->Overlay);
  207. if (optr->IsWall) {
  208. if (whead->IsWallDestroyer || (whead->IsWoodDestroyer && optr->IsWooden)) {
  209. Map[cell].Reduce_Wall(strength);
  210. }
  211. }
  212. }
  213. }