Damage.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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/BitFlags.h"
  32. #include "Common/GameType.h"
  33. #include "Common/ObjectStatusTypes.h" // Precompiled header anyway, no detangling possibility
  34. #include "Common/Snapshot.h"
  35. // FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
  36. class Object;
  37. class INI;
  38. class ThingTemplate;
  39. //-------------------------------------------------------------------------------------------------
  40. /** Damage types, keep this in sync with DamageTypeFlags::s_bitNameList[] */
  41. //-------------------------------------------------------------------------------------------------
  42. enum DamageType
  43. {
  44. DAMAGE_EXPLOSION = 0,
  45. DAMAGE_CRUSH = 1,
  46. DAMAGE_ARMOR_PIERCING = 2,
  47. DAMAGE_SMALL_ARMS = 3,
  48. DAMAGE_GATTLING = 4,
  49. DAMAGE_RADIATION = 5,
  50. DAMAGE_FLAME = 6,
  51. DAMAGE_LASER = 7,
  52. DAMAGE_SNIPER = 8,
  53. DAMAGE_POISON = 9,
  54. DAMAGE_HEALING = 10,
  55. DAMAGE_UNRESISTABLE = 11, // this is for scripting to cause 'armorproof' damage
  56. DAMAGE_WATER = 12,
  57. DAMAGE_DEPLOY = 13, // for transports to deploy units and order them to all attack.
  58. DAMAGE_SURRENDER = 14, // if something "dies" to surrender damage, they surrender.... duh!
  59. DAMAGE_HACK = 15,
  60. DAMAGE_KILLPILOT = 16, // special snipe attack that kills the pilot and renders a vehicle unmanned.
  61. DAMAGE_PENALTY = 17, // from game penalty (you won't receive radar warnings BTW)
  62. DAMAGE_FALLING = 18,
  63. DAMAGE_MELEE = 19, // Blades, clubs...
  64. DAMAGE_DISARM = 20, // "special" damage type used for disarming mines, bombs, etc (NOT for "disarming" an opponent!)
  65. DAMAGE_HAZARD_CLEANUP = 21, // special damage type for cleaning up hazards like radiation or bio-poison.
  66. DAMAGE_PARTICLE_BEAM = 22, // Incinerates virtually everything (insanely powerful orbital beam)
  67. DAMAGE_TOPPLING = 23, // damage from getting toppled.
  68. DAMAGE_INFANTRY_MISSILE = 24,
  69. DAMAGE_AURORA_BOMB = 25,
  70. DAMAGE_LAND_MINE = 26,
  71. DAMAGE_JET_MISSILES = 27,
  72. DAMAGE_STEALTHJET_MISSILES = 28,
  73. DAMAGE_MOLOTOV_COCKTAIL = 29,
  74. DAMAGE_COMANCHE_VULCAN = 30,
  75. DAMAGE_SUBDUAL_MISSILE = 31, ///< Damage that does not kill you, but produces some special effect based on your Body Module. Seperate HP from normal damage.
  76. DAMAGE_SUBDUAL_VEHICLE = 32,
  77. DAMAGE_SUBDUAL_BUILDING = 33,
  78. DAMAGE_SUBDUAL_UNRESISTABLE = 34,
  79. DAMAGE_MICROWAVE = 35, ///< Radiation that only affects infantry
  80. DAMAGE_KILL_GARRISONED = 36, ///< Kills Passengers up to the number specified in Damage
  81. DAMAGE_STATUS = 37, ///< Damage that gives a status condition, not that does hitpoint damage
  82. // Please note: There is a string array DamageTypeFlags::s_bitNameList[]
  83. DAMAGE_NUM_TYPES // keep this last
  84. };
  85. //-------------------------------------------------------------------------------------------------
  86. //-------------------------------------------------------------------------------------------------
  87. typedef BitFlags<DAMAGE_NUM_TYPES> DamageTypeFlags;
  88. inline Bool getDamageTypeFlag(DamageTypeFlags flags, DamageType dt)
  89. {
  90. return flags.test(dt);
  91. }
  92. inline DamageTypeFlags setDamageTypeFlag(DamageTypeFlags flags, DamageType dt)
  93. {
  94. flags.set(dt, TRUE);
  95. return flags;
  96. }
  97. inline DamageTypeFlags clearDamageTypeFlag(DamageTypeFlags flags, DamageType dt)
  98. {
  99. flags.set(dt, FALSE);
  100. return flags;
  101. }
  102. // Instead of checking against a single damage type, gather the question here so we can have more than one
  103. inline Bool IsSubdualDamage( DamageType type )
  104. {
  105. switch( type )
  106. {
  107. case DAMAGE_SUBDUAL_MISSILE:
  108. case DAMAGE_SUBDUAL_VEHICLE:
  109. case DAMAGE_SUBDUAL_BUILDING:
  110. case DAMAGE_SUBDUAL_UNRESISTABLE:
  111. return TRUE;
  112. }
  113. return FALSE;
  114. }
  115. /// Does this type of damage go to internalChangeHealth?
  116. inline Bool IsHealthDamagingDamage( DamageType type )
  117. {
  118. // The need for this function brought to you by "Have the guy with no game experience write the weapon code" Foundation.
  119. // Health Damage should be one type of WeaponEffect. Thinking "Weapons can only do damage" is why AoE is boring.
  120. switch( type )
  121. {
  122. case DAMAGE_STATUS:
  123. case DAMAGE_SUBDUAL_MISSILE:
  124. case DAMAGE_SUBDUAL_VEHICLE:
  125. case DAMAGE_SUBDUAL_BUILDING:
  126. case DAMAGE_SUBDUAL_UNRESISTABLE:
  127. case DAMAGE_KILLPILOT:
  128. case DAMAGE_KILL_GARRISONED:
  129. return FALSE;
  130. }
  131. return TRUE;
  132. }
  133. inline void SET_ALL_DAMAGE_TYPE_BITS(DamageTypeFlags& m)
  134. {
  135. m.clear();
  136. m.flip();
  137. }
  138. extern DamageTypeFlags DAMAGE_TYPE_FLAGS_NONE;
  139. extern DamageTypeFlags DAMAGE_TYPE_FLAGS_ALL;
  140. void initDamageTypeFlags();
  141. //-------------------------------------------------------------------------------------------------
  142. /** Death types, keep this in sync with TheDeathNames[] */
  143. //-------------------------------------------------------------------------------------------------
  144. enum DeathType
  145. {
  146. // note that these DELIBERATELY have (slightly) different names from the damage names,
  147. // since there isn't necessarily a one-to-one correspondence. e.g., DEATH_BURNED
  148. // can come from DAMAGE_FLAME but also from DAMAGE_PARTICLE_BEAM.
  149. DEATH_NORMAL = 0,
  150. DEATH_NONE = 1, ///< this is a "special case" that can't normally cause death
  151. DEATH_CRUSHED = 2,
  152. DEATH_BURNED = 3,
  153. DEATH_EXPLODED = 4,
  154. DEATH_POISONED = 5,
  155. DEATH_TOPPLED = 6,
  156. DEATH_FLOODED = 7,
  157. DEATH_SUICIDED = 8,
  158. DEATH_LASERED = 9,
  159. DEATH_DETONATED = 10, /**< this is the "death" that occurs when a missile/warhead/etc detonates normally,
  160. as opposed to being shot down, etc */
  161. DEATH_SPLATTED = 11, /**< the death that results from DAMAGE_FALLING */
  162. DEATH_POISONED_BETA = 12,
  163. // these are the "extra" types for yet-to-be-defined stuff. Don't bother renaming or adding
  164. // or removing these; they are reserved for modders :-)
  165. DEATH_EXTRA_2 = 13,
  166. DEATH_EXTRA_3 = 14,
  167. DEATH_EXTRA_4 = 15,
  168. DEATH_EXTRA_5 = 16,
  169. DEATH_EXTRA_6 = 17,
  170. DEATH_EXTRA_7 = 18,
  171. DEATH_EXTRA_8 = 19,
  172. DEATH_POISONED_GAMMA = 20,
  173. DEATH_NUM_TYPES // keep this last
  174. };
  175. #ifdef DEFINE_DEATH_NAMES
  176. static const char *TheDeathNames[] =
  177. {
  178. "NORMAL",
  179. "NONE",
  180. "CRUSHED",
  181. "BURNED",
  182. "EXPLODED",
  183. "POISONED",
  184. "TOPPLED",
  185. "FLOODED",
  186. "SUICIDED",
  187. "LASERED",
  188. "DETONATED",
  189. "SPLATTED",
  190. "POISONED_BETA",
  191. "EXTRA_2",
  192. "EXTRA_3",
  193. "EXTRA_4",
  194. "EXTRA_5",
  195. "EXTRA_6",
  196. "EXTRA_7",
  197. "EXTRA_8",
  198. "POISONED_GAMMA",
  199. NULL
  200. };
  201. #endif // end DEFINE_DEATH_NAMES
  202. //-------------------------------------------------------------------------------------------------
  203. //-------------------------------------------------------------------------------------------------
  204. typedef UnsignedInt DeathTypeFlags;
  205. const DeathTypeFlags DEATH_TYPE_FLAGS_ALL = 0xffffffff;
  206. const DeathTypeFlags DEATH_TYPE_FLAGS_NONE = 0x00000000;
  207. inline Bool getDeathTypeFlag(DeathTypeFlags flags, DeathType dt)
  208. {
  209. return (flags & (1UL << (dt - 1))) != 0;
  210. }
  211. inline DeathTypeFlags setDeathTypeFlag(DeathTypeFlags flags, DeathType dt)
  212. {
  213. return (flags | (1UL << (dt - 1)));
  214. }
  215. inline DeathTypeFlags clearDeathTypeFlag(DeathTypeFlags flags, DeathType dt)
  216. {
  217. return (flags & ~(1UL << (dt - 1)));
  218. }
  219. //-------------------------------------------------------------------------------------------------
  220. /** Damage info inputs */
  221. //-------------------------------------------------------------------------------------------------
  222. class DamageInfoInput : public Snapshot
  223. {
  224. public:
  225. DamageInfoInput( void )
  226. {
  227. m_sourceID = INVALID_ID;
  228. m_sourceTemplate = NULL;
  229. m_sourcePlayerMask = 0;
  230. m_damageType = DAMAGE_EXPLOSION;
  231. m_damageStatusType = OBJECT_STATUS_NONE;
  232. m_damageFXOverride = DAMAGE_UNRESISTABLE;
  233. m_deathType = DEATH_NORMAL;
  234. m_amount = 0;
  235. m_kill = FALSE;
  236. m_shockWaveVector.zero();
  237. m_shockWaveAmount = 0.0f;
  238. m_shockWaveRadius = 0.0f;
  239. m_shockWaveTaperOff = 0.0f;
  240. }
  241. ObjectID m_sourceID; ///< source of the damage
  242. const ThingTemplate *m_sourceTemplate; ///< source of the damage (the template).
  243. PlayerMaskType m_sourcePlayerMask; ///< Player mask of m_sourceID.
  244. DamageType m_damageType; ///< type of damage
  245. ObjectStatusTypes m_damageStatusType; ///< If status damage, what type
  246. DamageType m_damageFXOverride; ///< If not marked as the default of Unresistable, the damage type to use in doDamageFX instead of the real damamge type
  247. DeathType m_deathType; ///< if this kills us, death type to be used
  248. Real m_amount; ///< # value of how much damage to inflict
  249. Bool m_kill; ///< will always cause object to die regardless of damage.
  250. // These are used for damage causing shockwave, forcing units affected to be pushed around
  251. Coord3D m_shockWaveVector; ///< This represents the incoming damage vector
  252. Real m_shockWaveAmount; ///< This represents the amount of shockwave created by the damage. 0 = no shockwave, 1.0 = shockwave equal to damage.
  253. Real m_shockWaveRadius; ///< This represents the effect radius of the shockwave.
  254. Real m_shockWaveTaperOff; ///< This represents the taper off effect of the shockwave at the tip of the radius. 0.0 means shockwave is 0% at the radius edge.
  255. protected:
  256. // snapshot methods
  257. virtual void crc( Xfer *xfer ) { }
  258. virtual void xfer( Xfer *xfer );
  259. virtual void loadPostProcess( void ) { }
  260. };
  261. const Real HUGE_DAMAGE_AMOUNT = 999999.0f;
  262. //-------------------------------------------------------------------------------------------------
  263. /** Damage into outputs */
  264. //-------------------------------------------------------------------------------------------------
  265. class DamageInfoOutput : public Snapshot
  266. {
  267. public:
  268. DamageInfoOutput( void )
  269. {
  270. m_actualDamageDealt = 0;
  271. m_actualDamageClipped = 0;
  272. m_noEffect = false;
  273. }
  274. /**
  275. m_actualDamageDealt is the damage we tried to apply to object (after multipliers and such).
  276. m_actualDamageClipped is the value of m_actualDamageDealt, but clipped to the max health remaining of the obj.
  277. example:
  278. a mammoth tank fires a round at a small tank, attempting 100 damage.
  279. the small tank has a damage multiplier of 50%, meaning that only 50 damage is applied.
  280. furthermore, the small tank has only 30 health remaining.
  281. so: m_actualDamageDealt = 50, m_actualDamageClipped = 30.
  282. this distinction is useful, since visual fx really wants to do the fx for "50 damage",
  283. even though it was more than necessary to kill this object; game logic, on the other hand,
  284. may want to know the "clipped" damage for ai purposes.
  285. */
  286. Real m_actualDamageDealt;
  287. Real m_actualDamageClipped; ///< (see comment for m_actualDamageDealt)
  288. Bool m_noEffect; ///< if true, no damage was done at all (generally due to being InactiveBody)
  289. protected:
  290. // snapshot methods
  291. virtual void crc( Xfer *xfer ) { }
  292. virtual void xfer( Xfer *xfer );
  293. virtual void loadPostProcess( void ) { }
  294. };
  295. //-------------------------------------------------------------------------------------------------
  296. /** DamageInfo is a descriptor of damage we're trying to inflict. The structure
  297. * is divided up into two parts, inputs and outputs.
  298. *
  299. * INPUTS: You must provide valid values for these fields in order for damage
  300. * calculation to correctly take place
  301. * OUTPUT: Upon returning from damage issuing functions, the output fields
  302. * will be filled with the results of the damage occurrence
  303. */
  304. //-------------------------------------------------------------------------------------------------
  305. class DamageInfo : public Snapshot
  306. {
  307. public:
  308. DamageInfoInput in; ///< inputs for the damage info
  309. DamageInfoOutput out; ///< results for the damage occurrence
  310. protected:
  311. virtual void crc( Xfer *xfer ) { }
  312. virtual void xfer( Xfer *xfer );
  313. virtual void loadPostProcess( void ){ }
  314. };
  315. #endif // __DAMAGE_H_