SpawnBehavior.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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: SpawnBehavior.h //////////////////////////////////////////////////////////////////////////
  24. // Author: Graham Smallwood, January 2002
  25. // Colin Day, October 2002
  26. // Desc: Behavior will create and monitor a group of spawned units and replace as needed
  27. ///////////////////////////////////////////////////////////////////////////////////////////////////
  28. #pragma once
  29. #ifndef _SPAWN_BEHAVIOR_H_
  30. #define _SPAWN_BEHAVIOR_H_
  31. const Int SPAWN_UPDATE_RATE = LOGICFRAMES_PER_SECOND/2; ///< This is a low priority module that only needs to be called every this many frames
  32. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  33. #include "Common/INI.h"
  34. #include "GameLogic/Module/BehaviorModule.h"
  35. #include "GameLogic/Module/UpdateModule.h"
  36. #include "GameLogic/Module/DieModule.h"
  37. #include "GameLogic/Module/DamageModule.h"
  38. //-------------------------------------------------------------------------------------------------
  39. class ThingTemplate;
  40. enum CanAttackResult;
  41. //-------------------------------------------------------------------------------------------------
  42. class SpawnBehaviorModuleData : public BehaviorModuleData
  43. {
  44. public:
  45. Int m_spawnNumberData; ///< How many spawn I maintain
  46. Int m_spawnStartNumberData; ///< How many spawn I start with
  47. Int m_spawnReplaceDelayData; ///< After this many frames, I can replace one
  48. Int m_initialBurst; ///< How many should I make immediately, ignoring the delay?
  49. Bool m_isOneShotData; ///< Do I just spawn once and go dormant?
  50. Bool m_canReclaimOrphans; ///< Can I reclaim orphans for purposes of spawning
  51. Bool m_aggregateHealth; ///< should I calc an offset for the healthbox, averaging all my spawn
  52. Bool m_exitByBudding; ///< do I create each new spawn atop an existing one?
  53. Bool m_spawnedRequireSpawner; ///< Spawned objects can only exist while the spawner (us) is alive and present
  54. Bool m_slavesHaveFreeWill; ///< Slaves with free will don't attack when parent attacks.
  55. DamageTypeFlags m_damageTypesToPropagateToSlaves;
  56. std::vector<AsciiString> m_spawnTemplateNameData;
  57. DieMuxData m_dieMuxData;
  58. SpawnBehaviorModuleData()
  59. {
  60. m_spawnNumberData = 0;
  61. m_spawnReplaceDelayData = 0;
  62. //Added By Sadullah Nader
  63. //Initialization(s) inserted
  64. m_spawnStartNumberData = 0;
  65. //
  66. m_initialBurst = 0;
  67. m_isOneShotData = FALSE;
  68. m_canReclaimOrphans = FALSE;
  69. m_aggregateHealth = FALSE;
  70. m_exitByBudding = FALSE;
  71. m_spawnTemplateNameData.clear();
  72. m_spawnedRequireSpawner = FALSE;
  73. m_slavesHaveFreeWill = FALSE;
  74. }
  75. static void buildFieldParse(MultiIniFieldParse& p)
  76. {
  77. BehaviorModuleData::buildFieldParse(p);
  78. static const FieldParse dataFieldParse[] =
  79. {
  80. { "SpawnNumber", INI::parseInt, NULL, offsetof( SpawnBehaviorModuleData, m_spawnNumberData ) },
  81. { "SpawnReplaceDelay", INI::parseDurationUnsignedInt, NULL, offsetof( SpawnBehaviorModuleData, m_spawnReplaceDelayData ) },
  82. { "OneShot", INI::parseBool, NULL, offsetof( SpawnBehaviorModuleData, m_isOneShotData ) },
  83. { "CanReclaimOrphans", INI::parseBool, NULL, offsetof( SpawnBehaviorModuleData, m_canReclaimOrphans ) },
  84. { "AggregateHealth", INI::parseBool, NULL, offsetof( SpawnBehaviorModuleData, m_aggregateHealth ) },
  85. { "ExitByBudding", INI::parseBool, NULL, offsetof( SpawnBehaviorModuleData, m_exitByBudding ) },
  86. { "SpawnTemplateName", INI::parseAsciiStringVectorAppend,NULL, offsetof( SpawnBehaviorModuleData, m_spawnTemplateNameData ) },
  87. { "SpawnedRequireSpawner", INI::parseBool, NULL, offsetof( SpawnBehaviorModuleData, m_spawnedRequireSpawner ) },
  88. { "PropagateDamageTypesToSlavesWhenExisting", INI::parseDamageTypeFlags, NULL, offsetof( SpawnBehaviorModuleData, m_damageTypesToPropagateToSlaves ) },
  89. { "InitialBurst", INI::parseInt, NULL, offsetof( SpawnBehaviorModuleData, m_initialBurst ) },
  90. { "SlavesHaveFreeWill", INI::parseBool, NULL, offsetof( SpawnBehaviorModuleData, m_slavesHaveFreeWill ) },
  91. { 0, 0, 0, 0 }
  92. };
  93. p.add(dataFieldParse);
  94. p.add(DieMuxData::getFieldParse(), offsetof( SpawnBehaviorModuleData, m_dieMuxData ));
  95. }
  96. };
  97. // ------------------------------------------------------------------------------------------------
  98. // ------------------------------------------------------------------------------------------------
  99. class SpawnBehaviorInterface
  100. {
  101. public:
  102. virtual Bool maySpawnSelfTaskAI( Real maxSelfTaskersRatio ) = 0;
  103. virtual void onSpawnDeath( ObjectID deadSpawn, DamageInfo *damageInfo ) = 0;
  104. virtual Object* getClosestSlave( const Coord3D *pos ) = 0;
  105. virtual void orderSlavesToAttackTarget( Object *target, Int maxShotsToFire, CommandSourceType cmdSource ) = 0;
  106. virtual void orderSlavesToAttackPosition( const Coord3D *pos, Int maxShotsToFire, CommandSourceType cmdSource ) = 0;
  107. virtual CanAttackResult getCanAnySlavesAttackSpecificTarget( AbleToAttackType attackType, const Object *target, CommandSourceType cmdSource ) = 0;
  108. virtual CanAttackResult getCanAnySlavesUseWeaponAgainstTarget( AbleToAttackType attackType, const Object *victim, const Coord3D *pos, CommandSourceType cmdSource ) = 0;
  109. virtual Bool canAnySlavesAttack() = 0;
  110. virtual void orderSlavesToGoIdle( CommandSourceType cmdSource ) = 0;
  111. virtual void orderSlavesDisabledUntil( DisabledType type, UnsignedInt frame ) = 0;
  112. virtual void orderSlavesToClearDisabled( DisabledType type ) = 0;
  113. virtual void giveSlavesStealthUpgrade( Bool grantStealth ) = 0;
  114. virtual Bool areAllSlavesStealthed() const = 0;
  115. virtual void revealSlaves() = 0;
  116. virtual Bool doSlavesHaveFreedom() const = 0;
  117. };
  118. // ------------------------------------------------------------------------------------------------
  119. //-------------------------------------------------------------------------------------------------
  120. class SpawnBehavior : public UpdateModule,
  121. public SpawnBehaviorInterface,
  122. public DieModuleInterface,
  123. public DamageModuleInterface
  124. {
  125. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( SpawnBehavior, "SpawnBehavior" )
  126. MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( SpawnBehavior, SpawnBehaviorModuleData )
  127. public:
  128. SpawnBehavior( Thing *thing, const ModuleData* moduleData );
  129. // virtual destructor prototype provided by memory pool declaration
  130. // module methods
  131. static Int getInterfaceMask( void ) { return (MODULEINTERFACE_UPDATE) | (MODULEINTERFACE_DIE) | (MODULEINTERFACE_DAMAGE); }
  132. virtual void onDelete( void );
  133. virtual UpdateModuleInterface *getUpdate() { return this; }
  134. virtual DieModuleInterface *getDie() { return this; }
  135. virtual DamageModuleInterface *getDamage() { return this; }
  136. virtual SpawnBehaviorInterface* getSpawnBehaviorInterface() { return this; }
  137. // update methods
  138. virtual UpdateSleepTime update();
  139. // die methods
  140. virtual void onDie( const DamageInfo *damageInfo );
  141. // damage methods
  142. virtual void onDamage( DamageInfo *damageInfo );
  143. virtual void onHealing( DamageInfo *damageInfo ) { }
  144. virtual void onBodyDamageStateChange( const DamageInfo* damageInfo,
  145. BodyDamageType oldState,
  146. BodyDamageType newState) { }
  147. // SpawnBehaviorInterface methods
  148. virtual Bool maySpawnSelfTaskAI( Real maxSelfTaskersRatio );
  149. virtual void onSpawnDeath( ObjectID deadSpawn, DamageInfo *damageInfo ); ///< Something we spawned and set up to tell us it died just died.
  150. virtual Object* getClosestSlave( const Coord3D *pos );
  151. virtual void orderSlavesToAttackTarget( Object *target, Int maxShotsToFire, CommandSourceType cmdSource );
  152. virtual void orderSlavesToAttackPosition( const Coord3D *pos, Int maxShotsToFire, CommandSourceType cmdSource );
  153. virtual CanAttackResult getCanAnySlavesAttackSpecificTarget( AbleToAttackType attackType, const Object *target, CommandSourceType cmdSource );
  154. virtual CanAttackResult getCanAnySlavesUseWeaponAgainstTarget( AbleToAttackType attackType, const Object *victim, const Coord3D *pos, CommandSourceType cmdSource );
  155. virtual Bool canAnySlavesAttack();
  156. virtual void orderSlavesToGoIdle( CommandSourceType cmdSource );
  157. virtual void orderSlavesDisabledUntil( DisabledType type, UnsignedInt frame );
  158. virtual void orderSlavesToClearDisabled( DisabledType type );
  159. virtual void giveSlavesStealthUpgrade( Bool grantStealth );
  160. virtual Bool areAllSlavesStealthed() const;
  161. virtual void revealSlaves();
  162. virtual Bool doSlavesHaveFreedom() const { return getSpawnBehaviorModuleData()->m_slavesHaveFreeWill; }
  163. // **********************************************************************************************
  164. // our own methods
  165. void stopSpawning(); ///< Whoever owns this module may want to turn it off
  166. void startSpawning(); ///< Whoever owns this module may want to turn it on
  167. void computeAggregateStates(void);
  168. // void notifySelfTasking( Bool isSelfTasking );
  169. private:
  170. Bool shouldTryToSpawn(); ///< For my own use, should I even think of spawning
  171. Bool createSpawn(); ///< Actual work of creating a guy
  172. const ThingTemplate* m_spawnTemplate; ///< What it is I spawn
  173. Int m_oneShotCountdown; ///< and if so, this is what "once" entails
  174. Int m_framesToWait;
  175. Int m_firstBatchCount; ///<how many to start off with on the first Update();
  176. /// @todo Make sure the allocator for std::list<> is a good one. Otherwise override it.
  177. typedef std::list<Int> intList;
  178. typedef std::list<Int>::iterator intListIterator;
  179. typedef std::list<Int>::reverse_iterator intListReverseIterator;
  180. typedef std::list<ObjectID> objectIDList;
  181. typedef std::list<ObjectID>::iterator objectIDListIterator;
  182. typedef std::list<ObjectID>::reverse_iterator objectIDListReverseIterator;
  183. intList m_replacementTimes; ///< A list of frame times that I need to create new spawns
  184. objectIDList m_spawnIDs; ///< My darling little spawns. I need to keep track of them explicitly for the Slave type stuff
  185. Bool m_active; ///< Am I currently turned on
  186. Object *reclaimOrphanSpawn( void ); ///< find existing orphaned spawn object if present
  187. Bool m_aggregateHealth; ///< should I calc an offset for the healthbox, averaging all my spawn
  188. Bool m_initialBurstTimesInited;
  189. Int m_spawnCount; ///< so I can track for zero = kill; (aggregate)
  190. UnsignedInt m_selfTaskingSpawnCount; ///< How many of my spawn have I authorized to do their own thing?
  191. UnsignedInt m_initialBurstCountdown;
  192. std::vector<AsciiString>::const_iterator m_templateNameIterator;
  193. };
  194. #endif