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