Damage.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /*
  2. ** Command & Conquer Generals(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. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: Damage.h /////////////////////////////////////////////////////////////////////////////////
  24. // Author: Colin Day, November 2001
  25. // Desc: Damage description
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #pragma once
  28. #ifndef __DAMAGE_H_
  29. #define __DAMAGE_H_
  30. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  31. #include "Common/GameType.h"
  32. #include "Common/Snapshot.h"
  33. // FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
  34. class Object;
  35. class INI;
  36. //-------------------------------------------------------------------------------------------------
  37. /** Damage types, keep this in sync with TheDamageNames[] */
  38. //-------------------------------------------------------------------------------------------------
  39. enum DamageType
  40. {
  41. DAMAGE_EXPLOSION = 0,
  42. DAMAGE_CRUSH = 1,
  43. DAMAGE_ARMOR_PIERCING = 2,
  44. DAMAGE_SMALL_ARMS = 3,
  45. DAMAGE_GATTLING = 4,
  46. DAMAGE_RADIATION = 5,
  47. DAMAGE_FLAME = 6,
  48. DAMAGE_LASER = 7,
  49. DAMAGE_SNIPER = 8,
  50. DAMAGE_POISON = 9,
  51. DAMAGE_HEALING = 10,
  52. DAMAGE_UNRESISTABLE = 11, // this is for scripting to cause 'armorproof' damage
  53. DAMAGE_WATER = 12,
  54. DAMAGE_DEPLOY = 13, // for transports to deploy units and order them to all attack.
  55. // this stays, even if ALLOW_SURRENDER is not defed, since flashbangs still use 'em
  56. DAMAGE_SURRENDER = 14, // if something "dies" to surrender damage, they surrender.... duh!
  57. DAMAGE_HACK = 15,
  58. DAMAGE_KILLPILOT = 16, // special snipe attack that kills the pilot and renders a vehicle unmanned.
  59. DAMAGE_PENALTY = 17, // from game penalty (you won't receive radar warnings BTW)
  60. DAMAGE_FALLING = 18,
  61. DAMAGE_MELEE = 19, // Blades, clubs...
  62. DAMAGE_DISARM = 20, // "special" damage type used for disarming mines, bombs, etc (NOT for "disarming" an opponent!)
  63. DAMAGE_HAZARD_CLEANUP = 21, // special damage type for cleaning up hazards like radiation or bio-poison.
  64. DAMAGE_PARTICLE_BEAM = 22, // Incinerates virtually everything (insanely powerful orbital beam)
  65. DAMAGE_TOPPLING = 23, // damage from getting toppled.
  66. DAMAGE_INFANTRY_MISSILE = 24,
  67. DAMAGE_AURORA_BOMB = 25,
  68. DAMAGE_LAND_MINE = 26,
  69. DAMAGE_JET_MISSILES = 27,
  70. DAMAGE_STEALTHJET_MISSILES = 28,
  71. DAMAGE_MOLOTOV_COCKTAIL = 29,
  72. DAMAGE_COMANCHE_VULCAN = 30,
  73. DAMAGE_FLESHY_SNIPER = 31, // like DAMAGE_SNIPER, but (generally) does no damage to vehicles.
  74. // Please note: There is a string array below this enum, and when you change them,
  75. // you need to search on the array names to find all the stuff that generates names
  76. // based on these strings. (eg DamageFX does a strcat to make its array of names so
  77. // change DamageFX.ini and its Default)
  78. // !!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  79. // !!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  80. // !!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  81. //
  82. // if you add additional damage types, you will PROBABLY HAVE TO
  83. // ENLARGE A BITMASK IN WEAPONSET.
  84. //
  85. // !!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  86. // !!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  87. // !!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  88. DAMAGE_NUM_TYPES // keep this last
  89. };
  90. #ifdef DEFINE_DAMAGE_NAMES
  91. static const char *TheDamageNames[] =
  92. {
  93. "EXPLOSION",
  94. "CRUSH",
  95. "ARMOR_PIERCING",
  96. "SMALL_ARMS",
  97. "GATTLING",
  98. "RADIATION",
  99. "FLAME",
  100. "LASER",
  101. "SNIPER",
  102. "POISON",
  103. "HEALING",
  104. "UNRESISTABLE",
  105. "WATER",
  106. "DEPLOY",
  107. "SURRENDER",
  108. "HACK",
  109. "KILL_PILOT",
  110. "PENALTY",
  111. "FALLING",
  112. "MELEE",
  113. "DISARM",
  114. "HAZARD_CLEANUP",
  115. "PARTICLE_BEAM",
  116. "TOPPLING",
  117. "INFANTRY_MISSILE",
  118. "AURORA_BOMB",
  119. "LAND_MINE",
  120. "JET_MISSILES",
  121. "STEALTHJET_MISSILES",
  122. "MOLOTOV_COCKTAIL",
  123. "COMANCHE_VULCAN",
  124. "FLESHY_SNIPER",
  125. NULL
  126. };
  127. #endif // end DEFINE_DAMAGE_NAMES
  128. //-------------------------------------------------------------------------------------------------
  129. //-------------------------------------------------------------------------------------------------
  130. typedef UnsignedInt DamageTypeFlags;
  131. const DamageTypeFlags DAMAGE_TYPE_FLAGS_ALL = 0xffffffff;
  132. const DamageTypeFlags DAMAGE_TYPE_FLAGS_NONE = 0x00000000;
  133. inline Bool getDamageTypeFlag(DamageTypeFlags flags, DamageType dt)
  134. {
  135. return (flags & (1UL << (dt - 1))) != 0;
  136. }
  137. inline DamageTypeFlags setDamageTypeFlag(DamageTypeFlags flags, DamageType dt)
  138. {
  139. return (flags | (1UL << (dt - 1)));
  140. }
  141. inline DamageTypeFlags clearDamageTypeFlag(DamageTypeFlags flags, DamageType dt)
  142. {
  143. return (flags & ~(1UL << (dt - 1)));
  144. }
  145. //-------------------------------------------------------------------------------------------------
  146. /** Death types, keep this in sync with TheDeathNames[] */
  147. //-------------------------------------------------------------------------------------------------
  148. enum DeathType
  149. {
  150. // note that these DELIBERATELY have (slightly) different names from the damage names,
  151. // since there isn't necessarily a one-to-one correspondence. e.g., DEATH_BURNED
  152. // can come from DAMAGE_FLAME but also from DAMAGE_PARTICLE_BEAM.
  153. DEATH_NORMAL = 0,
  154. DEATH_NONE = 1, ///< this is a "special case" that can't normally cause death
  155. DEATH_CRUSHED = 2,
  156. DEATH_BURNED = 3,
  157. DEATH_EXPLODED = 4,
  158. DEATH_POISONED = 5,
  159. DEATH_TOPPLED = 6,
  160. DEATH_FLOODED = 7,
  161. DEATH_SUICIDED = 8,
  162. DEATH_LASERED = 9,
  163. DEATH_DETONATED = 10, /**< this is the "death" that occurs when a missile/warhead/etc detonates normally,
  164. as opposed to being shot down, etc */
  165. DEATH_SPLATTED = 11, /**< the death that results from DAMAGE_FALLING */
  166. DEATH_POISONED_BETA = 12,
  167. // these are the "extra" types for yet-to-be-defined stuff. Don't bother renaming or adding
  168. // or removing these; they are reserved for modders :-)
  169. DEATH_EXTRA_2 = 13,
  170. DEATH_EXTRA_3 = 14,
  171. DEATH_EXTRA_4 = 15,
  172. DEATH_EXTRA_5 = 16,
  173. DEATH_EXTRA_6 = 17,
  174. DEATH_EXTRA_7 = 18,
  175. DEATH_EXTRA_8 = 19,
  176. DEATH_NUM_TYPES // keep this last
  177. };
  178. #ifdef DEFINE_DEATH_NAMES
  179. static const char *TheDeathNames[] =
  180. {
  181. "NORMAL",
  182. "NONE",
  183. "CRUSHED",
  184. "BURNED",
  185. "EXPLODED",
  186. "POISONED",
  187. "TOPPLED",
  188. "FLOODED",
  189. "SUICIDED",
  190. "LASERED",
  191. "DETONATED",
  192. "SPLATTED",
  193. "POISONED_BETA",
  194. "EXTRA_2",
  195. "EXTRA_3",
  196. "EXTRA_4",
  197. "EXTRA_5",
  198. "EXTRA_6",
  199. "EXTRA_7",
  200. "EXTRA_8",
  201. NULL
  202. };
  203. #endif // end DEFINE_DEATH_NAMES
  204. //-------------------------------------------------------------------------------------------------
  205. //-------------------------------------------------------------------------------------------------
  206. typedef UnsignedInt DeathTypeFlags;
  207. const DeathTypeFlags DEATH_TYPE_FLAGS_ALL = 0xffffffff;
  208. const DeathTypeFlags DEATH_TYPE_FLAGS_NONE = 0x00000000;
  209. inline Bool getDeathTypeFlag(DeathTypeFlags flags, DeathType dt)
  210. {
  211. return (flags & (1UL << (dt - 1))) != 0;
  212. }
  213. inline DeathTypeFlags setDeathTypeFlag(DeathTypeFlags flags, DeathType dt)
  214. {
  215. return (flags | (1UL << (dt - 1)));
  216. }
  217. inline DeathTypeFlags clearDeathTypeFlag(DeathTypeFlags flags, DeathType dt)
  218. {
  219. return (flags & ~(1UL << (dt - 1)));
  220. }
  221. //-------------------------------------------------------------------------------------------------
  222. /** Damage info inputs */
  223. //-------------------------------------------------------------------------------------------------
  224. class DamageInfoInput : public Snapshot
  225. {
  226. public:
  227. DamageInfoInput( void )
  228. {
  229. m_sourceID = INVALID_ID;
  230. m_sourcePlayerMask = 0;
  231. m_damageType = DAMAGE_EXPLOSION;
  232. m_deathType = DEATH_NORMAL;
  233. m_amount = 0;
  234. }
  235. ObjectID m_sourceID; ///< source of the damage
  236. PlayerMaskType m_sourcePlayerMask; ///< Player mask of m_sourceID.
  237. DamageType m_damageType; ///< type of damage
  238. DeathType m_deathType; ///< if this kills us, death type to be used
  239. Real m_amount; ///< # value of how much damage to inflict
  240. protected:
  241. // snapshot methods
  242. virtual void crc( Xfer *xfer ) { }
  243. virtual void xfer( Xfer *xfer );
  244. virtual void loadPostProcess( void ) { }
  245. };
  246. const Real HUGE_DAMAGE_AMOUNT = 999999.0f;
  247. //-------------------------------------------------------------------------------------------------
  248. /** Damage into outputs */
  249. //-------------------------------------------------------------------------------------------------
  250. class DamageInfoOutput : public Snapshot
  251. {
  252. public:
  253. DamageInfoOutput( void )
  254. {
  255. m_actualDamageDealt = 0;
  256. m_actualDamageClipped = 0;
  257. m_noEffect = false;
  258. }
  259. /**
  260. m_actualDamageDealt is the damage we tried to apply to object (after multipliers and such).
  261. m_actualDamageClipped is the value of m_actualDamageDealt, but clipped to the max health remaining of the obj.
  262. example:
  263. a mammoth tank fires a round at a small tank, attempting 100 damage.
  264. the small tank has a damage multiplier of 50%, meaning that only 50 damage is applied.
  265. furthermore, the small tank has only 30 health remaining.
  266. so: m_actualDamageDealt = 50, m_actualDamageClipped = 30.
  267. this distinction is useful, since visual fx really wants to do the fx for "50 damage",
  268. even though it was more than necessary to kill this object; game logic, on the other hand,
  269. may want to know the "clipped" damage for ai purposes.
  270. */
  271. Real m_actualDamageDealt;
  272. Real m_actualDamageClipped; ///< (see comment for m_actualDamageDealt)
  273. Bool m_noEffect; ///< if true, no damage was done at all (generally due to being InactiveBody)
  274. protected:
  275. // snapshot methods
  276. virtual void crc( Xfer *xfer ) { }
  277. virtual void xfer( Xfer *xfer );
  278. virtual void loadPostProcess( void ) { }
  279. };
  280. //-------------------------------------------------------------------------------------------------
  281. /** DamageInfo is a descriptor of damage we're trying to inflict. The structure
  282. * is divided up into two parts, inputs and outputs.
  283. *
  284. * INPUTS: You must provide valid values for these fields in order for damage
  285. * calculation to correctly take place
  286. * OUTPUT: Upon returning from damage issuing functions, the output fields
  287. * will be filled with the results of the damage occurrence
  288. */
  289. //-------------------------------------------------------------------------------------------------
  290. class DamageInfo : public Snapshot
  291. {
  292. public:
  293. DamageInfoInput in; ///< inputs for the damage info
  294. DamageInfoOutput out; ///< results for the damage occurrence
  295. protected:
  296. virtual void crc( Xfer *xfer ) { }
  297. virtual void xfer( Xfer *xfer );
  298. virtual void loadPostProcess( void ){ }
  299. };
  300. #endif // __DAMAGE_H_