ProductionUpdate.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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: ProductionUpdate.h ///////////////////////////////////////////////////////////////////////
  24. // Author: Colin Day, March 2002
  25. // Desc: This module allows things to be "constructed" from a building
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #pragma once
  28. #ifndef __PRODUCTIONUPDATE_H_
  29. #define __PRODUCTIONUPDATE_H_
  30. // USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
  31. #include "Common/ModelState.h"
  32. #include "GameLogic/Module/DieModule.h"
  33. #include "GameLogic/Module/UpdateModule.h"
  34. // FORWARD REFERNCES //////////////////////////////////////////////////////////////////////////////
  35. class ProductionEntry;
  36. class ThingTemplate;
  37. class UpgradeTemplate;
  38. ///////////////////////////////////////////////////////////////////////////////////////////////////
  39. enum ProductionID
  40. {
  41. PRODUCTIONID_INVALID = 0
  42. };
  43. enum ProductionType
  44. {
  45. PRODUCTION_INVALID = 0,
  46. PRODUCTION_UNIT,
  47. PRODUCTION_UPGRADE
  48. };
  49. //-------------------------------------------------------------------------------------------------
  50. /** A ProductionEntry is a single entry representing something that we are supposed to
  51. * produce */
  52. //-------------------------------------------------------------------------------------------------
  53. class ProductionEntry : public MemoryPoolObject
  54. {
  55. friend class ProductionUpdate;
  56. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ProductionEntry, "ProductionEntry" )
  57. public:
  58. ProductionEntry( void );
  59. // virtual destructor provided by memory pool object
  60. /// query what kind of thing is being produced by this entry
  61. const ThingTemplate *getProductionObject( void ) const { return m_objectToProduce; }
  62. /// query what kind of upgrade is being produced by this entry
  63. const UpgradeTemplate *getProductionUpgrade( void ) const { return m_upgradeToResearch; }
  64. /// query the production type
  65. ProductionType getProductionType( void ) const { return m_type; }
  66. /// how much progress is done on this entry
  67. Real getPercentComplete( void ) const { return m_percentComplete; }
  68. /// get the unique (to the producer object) production ID
  69. ProductionID getProductionID( void ) const { return m_productionID; }
  70. Int getProductionQuantity() const { return m_productionQuantityTotal; } //How many I try to make
  71. Int getProductionQuantityRemaining() const { return m_productionQuantityTotal - m_productionQuantityProduced; }//How many I have made
  72. void oneProductionSuccessful() { ++m_productionQuantityProduced; m_exitDoor = DOOR_NONE_AVAILABLE; }//increment, and mark door to re-reserve
  73. ExitDoorType getExitDoor() const { return m_exitDoor; }
  74. void setExitDoor(ExitDoorType exitDoor) { m_exitDoor = exitDoor; }
  75. protected:
  76. ProductionType m_type; ///< production type
  77. union
  78. {
  79. const ThingTemplate *m_objectToProduce; ///< what we're going to produce
  80. const UpgradeTemplate *m_upgradeToResearch; ///< what upgrade we're researching
  81. };
  82. ProductionID m_productionID; ///< our very own production ID!
  83. Real m_percentComplete; ///< percent our construction is complete
  84. Int m_framesUnderConstruction; ///< counter for how many frames we've been under construction (incremented once per update)
  85. Int m_productionQuantityTotal; ///< it is now possible to construct multiple units simultaneously.
  86. Int m_productionQuantityProduced; ///< And we need to allow pausing within an entry, so we keep track of number of sub-successes
  87. ExitDoorType m_exitDoor;
  88. ProductionEntry *m_next; ///< next in list
  89. ProductionEntry *m_prev; ///< prev in list
  90. };
  91. //-------------------------------------------------------------------------------------------------
  92. struct QuantityModifier
  93. {
  94. AsciiString m_templateName;
  95. Int m_quantity;
  96. };
  97. //-------------------------------------------------------------------------------------------------
  98. class ProductionUpdateModuleData : public UpdateModuleData
  99. {
  100. public:
  101. Int m_numDoorAnimations; ///< has a door animation(s) upon unit built and exit
  102. UnsignedInt m_doorOpeningTime; ///< in frames, time it takes the door to open
  103. UnsignedInt m_doorWaitOpenTime; ///< in frames, time we should leave the door open
  104. UnsignedInt m_doorClosingTime; ///< in frames, time it takes to close the door
  105. UnsignedInt m_constructionCompleteDuration; ///< in frames, how long we state in "construction complete" condition after making something
  106. std::vector<QuantityModifier> m_quantityModifiers; ///< Quantity modifiers modify the number of specified object to created whenever produced.
  107. Int m_maxQueueEntries; ///< max things that can be queued at once.
  108. DisabledMaskType m_disabledTypesToProcess;
  109. ProductionUpdateModuleData( void );
  110. static void buildFieldParse(MultiIniFieldParse& p);
  111. static void parseAppendQuantityModifier( INI* ini, void *instance, void *store, const void *userData );
  112. };
  113. //-------------------------------------------------------------------------------------------------
  114. enum CanMakeType;
  115. // ------------------------------------------------------------------------------------------------
  116. // ------------------------------------------------------------------------------------------------
  117. class ProductionUpdateInterface
  118. {
  119. public:
  120. virtual CanMakeType canQueueCreateUnit( const ThingTemplate *unitType ) const = 0;
  121. virtual CanMakeType canQueueUpgrade( const UpgradeTemplate *upgrade ) const = 0;
  122. virtual ProductionID requestUniqueUnitID( void ) = 0;
  123. virtual Bool queueUpgrade( const UpgradeTemplate *upgrade ) = 0;
  124. virtual void cancelUpgrade( const UpgradeTemplate *upgrade ) = 0;
  125. virtual Bool isUpgradeInQueue( const UpgradeTemplate *upgrade ) const = 0;
  126. virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const = 0;
  127. virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ) = 0;
  128. virtual void cancelUnitCreate( ProductionID productionID ) = 0;
  129. virtual void cancelAllUnitsOfType( const ThingTemplate *unitType) = 0;
  130. virtual void cancelAndRefundAllProduction( void ) = 0;
  131. virtual UnsignedInt getProductionCount( void ) const = 0;
  132. virtual const ProductionEntry *firstProduction( void ) const = 0;
  133. virtual const ProductionEntry *nextProduction( const ProductionEntry *p ) const = 0;
  134. virtual void setHoldDoorOpen(ExitDoorType exitDoor, Bool holdIt) = 0;
  135. //These functions keep track of the special power construction of a new building via a special power instead of standard production interface.
  136. //This was added for the sneak attack building functionality.
  137. virtual const CommandButton* getSpecialPowerConstructionCommandButton() const = 0;
  138. virtual void setSpecialPowerConstructionCommandButton( const CommandButton *commandButton ) = 0;
  139. };
  140. //-------------------------------------------------------------------------------------------------
  141. /** Production modules do actual unit construction */
  142. //-------------------------------------------------------------------------------------------------
  143. class ProductionUpdate : public UpdateModule, public ProductionUpdateInterface, public DieModuleInterface
  144. {
  145. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ProductionUpdate, "ProductionUpdate" )
  146. MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( ProductionUpdate, ProductionUpdateModuleData )
  147. public:
  148. ProductionUpdate( Thing *thing, const ModuleData* moduleData );
  149. // virtual destructor prototype provided by MemoryPoolObject
  150. static Int getInterfaceMask() { return UpdateModule::getInterfaceMask() | (MODULEINTERFACE_DIE); }
  151. // Disabled conditions to process (AI will still process held status)
  152. virtual DisabledMaskType getDisabledTypesToProcess() const { return getProductionUpdateModuleData()->m_disabledTypesToProcess; }
  153. virtual ProductionUpdateInterface* getProductionUpdateInterface( void ) { return this; }
  154. virtual DieModuleInterface* getDie() { return this; }
  155. static ProductionUpdateInterface *getProductionUpdateInterfaceFromObject( Object *obj );
  156. virtual CanMakeType canQueueCreateUnit( const ThingTemplate *unitType ) const;
  157. virtual CanMakeType canQueueUpgrade( const UpgradeTemplate *upgrade ) const;
  158. /** this method is used to request a unique ID to assign to the production of a single
  159. unit. It is unique to all units that can be created from this source object, but is
  160. not unique amoung multiple source objects */
  161. virtual ProductionID requestUniqueUnitID( void ) { ProductionID tmp = m_uniqueID; m_uniqueID = (ProductionID)(m_uniqueID+1); return tmp; }
  162. virtual Bool queueUpgrade( const UpgradeTemplate *upgrade ); ///< queue upgrade "research"
  163. virtual void cancelUpgrade( const UpgradeTemplate *upgrade ); ///< cancel upgrade "research"
  164. virtual Bool isUpgradeInQueue( const UpgradeTemplate *upgrade ) const; ///< is the upgrade in our production queue already
  165. virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const; ///< count number of units with matching unit type in the production queue
  166. virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ); ///< queue unit to be produced
  167. virtual void cancelUnitCreate( ProductionID productionID ); ///< cancel construction of unit with matching production ID
  168. virtual void cancelAllUnitsOfType( const ThingTemplate *unitType); ///< cancel all production of type unitType
  169. virtual void cancelAndRefundAllProduction( void ); ///< cancel and refund anything in the production queue
  170. virtual UnsignedInt getProductionCount( void ) const { return m_productionCount; } ///< return # of things in the production queue
  171. // walking the production list from outside
  172. virtual const ProductionEntry *firstProduction( void ) const { return m_productionQueue; }
  173. virtual const ProductionEntry *nextProduction( const ProductionEntry *p ) const { return p ? p->m_next : NULL; }
  174. virtual void setHoldDoorOpen(ExitDoorType exitDoor, Bool holdIt);
  175. virtual UpdateSleepTime update( void ); ///< the update
  176. //These functions keep track of the special power construction of a new building via a special power instead of standard production interface.
  177. //This was added for the sneak attack building functionality.
  178. virtual const CommandButton* getSpecialPowerConstructionCommandButton() const { return m_specialPowerConstructionCommandButton; }
  179. virtual void setSpecialPowerConstructionCommandButton( const CommandButton *commandButton ) { m_specialPowerConstructionCommandButton = commandButton; }
  180. // DieModuleInterface
  181. virtual void onDie( const DamageInfo *damageInfo );
  182. protected:
  183. void addToProductionQueue( ProductionEntry *production ); ///< add to *END* of production queue list
  184. void removeFromProductionQueue( ProductionEntry *production ); ///< remove production from the queue list
  185. void updateDoors(); ///< update the door behavior
  186. struct DoorInfo
  187. {
  188. UnsignedInt m_doorOpenedFrame; ///< for producer objects that have a door open/close animation when they make something
  189. UnsignedInt m_doorWaitOpenFrame; ///< frame we entered into wait open state
  190. UnsignedInt m_doorClosedFrame; ///< frame any door was closed on
  191. Bool m_holdOpen; ///< if T, don't allow door to close
  192. };
  193. const CommandButton *m_specialPowerConstructionCommandButton; ///< In a mode to construct a specific building via a special power. (NO NEED TO SAVE DATA ON THIS FIELD)
  194. ProductionEntry* m_productionQueue; ///< queue of things we want to build
  195. ProductionEntry* m_productionQueueTail; ///< tail pointer for m_productionQueue
  196. ProductionID m_uniqueID; ///< unique ID counter for producing units
  197. UnsignedInt m_productionCount; ///< # of things in the production queue
  198. UnsignedInt m_constructionCompleteFrame; ///< frame construction was complete on
  199. DoorInfo m_doors[DOOR_COUNT_MAX];
  200. ModelConditionFlags m_clearFlags; ///< flags to clear from model
  201. ModelConditionFlags m_setFlags; ///< flags to set in model
  202. Bool m_flagsDirty; ///< clearFlags/setFlags needs to be set into the model
  203. };
  204. #endif // end __PRODUCTIONUPDATE_H_