BodyModule.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  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: BodyModule.h /////////////////////////////////////////////////////////////////////////////////
  24. // Author: Colin Day, September 2001
  25. // Desc:
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #pragma once
  28. #ifndef __BODYMODULE_H_
  29. #define __BODYMODULE_H_
  30. #include "Common/Module.h"
  31. #include "GameLogic/Damage.h"
  32. #include "GameLogic/ArmorSet.h"
  33. #include "GameLogic/Module/BehaviorModule.h"
  34. //-------------------------------------------------------------------------------------------------
  35. /** OBJECT BODY MODULE base class */
  36. //-------------------------------------------------------------------------------------------------
  37. class WeaponTemplate;
  38. //-------------------------------------------------------------------------------------------------
  39. /** Damage states for structures
  40. *
  41. * NOTE: the macros below for IS_CONDITION_WORSE and IS_CONDITION_BETTER depend on this
  42. * enumeration being in sequential order
  43. */
  44. //-------------------------------------------------------------------------------------------------
  45. enum BodyDamageType
  46. {
  47. BODY_PRISTINE, ///< unit should appear in pristine condition
  48. BODY_DAMAGED, ///< unit has been damaged
  49. BODY_REALLYDAMAGED, ///< unit is extremely damaged / nearly destroyed
  50. BODY_RUBBLE, ///< unit has been reduced to rubble/corpse/exploded-hulk, etc
  51. BODYDAMAGETYPE_COUNT
  52. };
  53. #ifdef DEFINE_BODYDAMAGETYPE_NAMES
  54. static const char* TheBodyDamageTypeNames[] =
  55. {
  56. "PRISTINE",
  57. "DAMAGED",
  58. "REALLYDAMAGED",
  59. "RUBBLE",
  60. NULL
  61. };
  62. #endif
  63. enum MaxHealthChangeType
  64. {
  65. SAME_CURRENTHEALTH,
  66. PRESERVE_RATIO,
  67. ADD_CURRENT_HEALTH_TOO,
  68. FULLY_HEAL,
  69. };
  70. #ifdef DEFINE_MAXHEALTHCHANGETYPE_NAMES
  71. static const char* TheMaxHealthChangeTypeNames[] =
  72. {
  73. "SAME_CURRENTHEALTH",
  74. "PRESERVE_RATIO",
  75. "ADD_CURRENT_HEALTH_TOO",
  76. };
  77. #endif
  78. //
  79. // is condition A worse than condition B ... NOTE: this assumes the conditions
  80. // in BodyDamageType are in sequential order
  81. //
  82. // is a worse than b
  83. #define IS_CONDITION_WORSE( a, b ) ( a > b )
  84. // is a better than b
  85. #define IS_CONDITION_BETTER( a, b ) ( a < b )
  86. //-------------------------------------------------------------------------------------------------
  87. //-------------------------------------------------------------------------------------------------
  88. class BodyModuleData : public BehaviorModuleData
  89. {
  90. public:
  91. BodyModuleData()
  92. {
  93. }
  94. static void buildFieldParse(MultiIniFieldParse& p)
  95. {
  96. BehaviorModuleData::buildFieldParse(p);
  97. }
  98. };
  99. //-------------------------------------------------------------------------------------------------
  100. class BodyModuleInterface
  101. {
  102. public:
  103. /**
  104. Try to damage this Object. The module's Armor
  105. will be taken into account, so the actual damage done may vary
  106. considerably from what you requested. Also note that (if damage is done)
  107. the DamageFX will be invoked to provide a/v fx as appropriate.
  108. */
  109. virtual void attemptDamage( DamageInfo *damageInfo ) = 0;
  110. /**
  111. Instead of having negative damage count as healing, or allowing access to the private
  112. changeHealth Method, we will use this parallel to attemptDamage to do healing without hack.
  113. */
  114. virtual void attemptHealing( DamageInfo *healingInfo ) = 0;
  115. /**
  116. Estimate the (unclipped) damage that would be done to this object
  117. by the given damage (taking bonuses, armor, etc into account),
  118. but DO NOT alter the body in any way. (This is used by the AI system
  119. to choose weapons.)
  120. */
  121. virtual Real estimateDamage( DamageInfoInput& damageInfo ) const = 0;
  122. virtual Real getHealth() const = 0; ///< get current health
  123. virtual Real getMaxHealth() const = 0;
  124. virtual Real getInitialHealth() const = 0;
  125. virtual Real getPreviousHealth() const = 0;
  126. virtual UnsignedInt getSubdualDamageHealRate() const = 0;
  127. virtual Real getSubdualDamageHealAmount() const = 0;
  128. virtual Bool hasAnySubdualDamage() const = 0;
  129. virtual Real getCurrentSubdualDamageAmount() const = 0;
  130. virtual BodyDamageType getDamageState() const = 0;
  131. virtual void setDamageState( BodyDamageType newState ) = 0; ///< control damage state directly. Will adjust hitpoints.
  132. virtual void setAflame( Bool setting ) = 0;///< This is a major change like a damage state.
  133. virtual void onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback ) = 0; ///< I just achieved this level right this moment
  134. virtual void setArmorSetFlag(ArmorSetType ast) = 0;
  135. virtual void clearArmorSetFlag(ArmorSetType ast) = 0;
  136. virtual Bool testArmorSetFlag(ArmorSetType ast) = 0;
  137. virtual const DamageInfo *getLastDamageInfo() const = 0;
  138. virtual UnsignedInt getLastDamageTimestamp() const = 0;
  139. virtual UnsignedInt getLastHealingTimestamp() const = 0;
  140. virtual ObjectID getClearableLastAttacker() const = 0;
  141. virtual void clearLastAttacker() = 0;
  142. virtual Bool getFrontCrushed() const = 0;
  143. virtual Bool getBackCrushed() const = 0;
  144. virtual void setInitialHealth(Int initialPercent) = 0;
  145. virtual void setMaxHealth( Real maxHealth, MaxHealthChangeType healthChangeType = SAME_CURRENTHEALTH ) = 0;
  146. virtual void setFrontCrushed(Bool v) = 0;
  147. virtual void setBackCrushed(Bool v) = 0;
  148. virtual void applyDamageScalar( Real scalar ) = 0;
  149. virtual Real getDamageScalar() const = 0;
  150. /**
  151. Change the module's health by the given delta. Note that
  152. the module's DamageFX and Armor are NOT taken into
  153. account, so you should think about what you're bypassing when you
  154. call this directly (especially when when decreasing health, since
  155. you probably want "attemptDamage" or "attemptHealing")
  156. */
  157. virtual void internalChangeHealth( Real delta ) = 0;
  158. virtual void setIndestructible( Bool indestructible ) = 0;
  159. virtual Bool isIndestructible( void ) const = 0;
  160. virtual void evaluateVisualCondition() = 0;
  161. virtual void updateBodyParticleSystems() = 0; // made public for topple and building collapse updates -ML
  162. };
  163. //-------------------------------------------------------------------------------------------------
  164. class BodyModule : public BehaviorModule, public BodyModuleInterface
  165. {
  166. MEMORY_POOL_GLUE_ABC( BodyModule )
  167. public:
  168. BodyModule( Thing *thing, const ModuleData* moduleData );
  169. // virtual destructor prototype defined by MemoryPoolObject
  170. static Int getInterfaceMask() { return MODULEINTERFACE_BODY; }
  171. // BehaviorModule
  172. virtual BodyModuleInterface* getBody() { return this; }
  173. /**
  174. Try to damage this Object. The module's Armor
  175. will be taken into account, so the actual damage done may vary
  176. considerably from what you requested. Also note that (if damage is done)
  177. the DamageFX will be invoked to provide a/v fx as appropriate.
  178. */
  179. virtual void attemptDamage( DamageInfo *damageInfo ) = 0;
  180. /**
  181. Instead of having negative damage count as healing, or allowing access to the private
  182. changeHealth Method, we will use this parallel to attemptDamage to do healing without hack.
  183. */
  184. virtual void attemptHealing( DamageInfo *healingInfo ) = 0;
  185. /**
  186. Estimate the (unclipped) damage that would be done to this object
  187. by the given damage (taking bonuses, armor, etc into account),
  188. but DO NOT alter the body in any way. (This is used by the AI system
  189. to choose weapons.)
  190. */
  191. virtual Real estimateDamage( DamageInfoInput& damageInfo ) const = 0;
  192. virtual Real getHealth() const = 0; ///< get current health
  193. virtual Real getMaxHealth() const {return 0.0f;} ///< return max health
  194. virtual Real getPreviousHealth() const { return 0.0f; } ///< return previous health
  195. virtual UnsignedInt getSubdualDamageHealRate() const {return 0;}
  196. virtual Real getSubdualDamageHealAmount() const {return 0.0f;}
  197. virtual Bool hasAnySubdualDamage() const{return FALSE;}
  198. virtual Real getCurrentSubdualDamageAmount() const { return 0.0f; }
  199. virtual Real getInitialHealth() const {return 0.0f;} // return initial health
  200. virtual BodyDamageType getDamageState() const = 0;
  201. virtual void setDamageState( BodyDamageType newState ) = 0; ///< control damage state directly. Will adjust hitpoints.
  202. virtual void setAflame( Bool setting ) = 0;///< This is a major change like a damage state.
  203. virtual void onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback = FALSE ) = 0; ///< I just achieved this level right this moment
  204. virtual void setArmorSetFlag(ArmorSetType ast) = 0;
  205. virtual void clearArmorSetFlag(ArmorSetType ast) = 0;
  206. virtual Bool testArmorSetFlag(ArmorSetType ast) = 0;
  207. virtual const DamageInfo *getLastDamageInfo() const { return NULL; } ///< return info on last damage dealt to this object
  208. virtual UnsignedInt getLastDamageTimestamp() const { return 0; } ///< return frame of last damage dealt
  209. virtual UnsignedInt getLastHealingTimestamp() const { return 0; } ///< return frame of last healing dealt
  210. virtual ObjectID getClearableLastAttacker() const { return INVALID_ID; }
  211. virtual void clearLastAttacker() { }
  212. virtual Bool getFrontCrushed() const { return false; }
  213. virtual Bool getBackCrushed() const { return false; }
  214. virtual void setInitialHealth(Int initialPercent) { } ///< Sets the inital load health %.
  215. virtual void setMaxHealth(Real maxHealth, MaxHealthChangeType healthChangeType = SAME_CURRENTHEALTH ) { } ///< Sets the max health.
  216. virtual void setFrontCrushed(Bool v) { DEBUG_CRASH(("you should never call this for generic Bodys")); }
  217. virtual void setBackCrushed(Bool v) { DEBUG_CRASH(("you should never call this for generic Bodys")); }
  218. virtual void setIndestructible( Bool indestructible ) { }
  219. virtual Bool isIndestructible( void ) const { return TRUE; }
  220. //Allows outside systems to apply defensive bonuses or penalties (they all stack as a multiplier!)
  221. virtual void applyDamageScalar( Real scalar ) { m_damageScalar *= scalar; }
  222. virtual Real getDamageScalar() const { return m_damageScalar; }
  223. /**
  224. Change the module's health by the given delta. Note that
  225. the module's DamageFX and Armor are NOT taken into
  226. account, so you should think about what you're bypassing when you
  227. call this directly (especially when when decreasing health, since
  228. you probably want "attemptDamage" or "attemptHealing")
  229. */
  230. virtual void internalChangeHealth( Real delta ) = 0;
  231. virtual void evaluateVisualCondition() { }
  232. virtual void updateBodyParticleSystems() { };// made public for topple anf building collapse updates -ML
  233. protected:
  234. // snapshot methods
  235. virtual void crc( Xfer *xfer );
  236. virtual void xfer( Xfer *xfer );
  237. virtual void loadPostProcess( void );
  238. Real m_damageScalar;
  239. };
  240. inline BodyModule::BodyModule( Thing *thing, const ModuleData* moduleData ) : BehaviorModule( thing, moduleData ), m_damageScalar(1.0f) { }
  241. inline BodyModule::~BodyModule() { }
  242. #endif