WorkerAIUpdate.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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: WorkerAIUpdate.h //////////////////////////////////////////////////////////////////////////
  24. // Author: Graham Smallwood, June 2002
  25. // Desc: A Worker is a unit that is both a Dozer and a Supply Truck. Holy Fuck.
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #pragma once
  28. #ifndef __WORKER_AI_UPDATE_H_
  29. #define __WORKER_AI_UPDATE_H_
  30. // USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
  31. #include "Common/StateMachine.h"
  32. #include "GameLogic/Module/AIUpdate.h"
  33. #include "GameLogic/Module/DozerAIUpdate.h"
  34. #include "GameLogic/Module/SupplyTruckAIUpdate.h"
  35. // FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
  36. //-------------------------------------------------------------------------------------------------
  37. class WorkerStateMachine : public StateMachine
  38. {
  39. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( WorkerStateMachine, "WorkerStateMachine" );
  40. public:
  41. WorkerStateMachine( Object *owner );
  42. // state transition conditions
  43. static Bool supplyTruckSubMachineWantsToEnter( State *thisState, void* userData );
  44. static Bool supplyTruckSubMachineReadyToLeave( State *thisState, void* userData );
  45. protected:
  46. // snapshot interface
  47. virtual void crc( Xfer *xfer );
  48. virtual void xfer( Xfer *xfer );
  49. virtual void loadPostProcess();
  50. };
  51. // ------------------------------------------------------------------------------------------------
  52. /** NOTE: If you edit module data you must do it in both the Dozer *AND* the Worker */
  53. // ------------------------------------------------------------------------------------------------
  54. class WorkerAIUpdateModuleData : public AIUpdateModuleData
  55. {
  56. public:
  57. // !!!
  58. // !!! NOTE: If you edit module data you must do it in both the Dozer *AND* the Worker !!!
  59. // !!!
  60. Int m_maxBoxesData;
  61. Real m_repairHealthPercentPerSecond; ///< how many health points per second the dozer repairs at
  62. Real m_boredTime; ///< after this many frames, a dozer will try to find something to do on its own
  63. Real m_boredRange; ///< range the dozers try to auto repair when they're bored
  64. UnsignedInt m_centerDelay;
  65. UnsignedInt m_warehouseDelay;
  66. Real m_warehouseScanDistance;
  67. AudioEventRTS m_suppliesDepletedVoice; ///< Sound played when I take the last box.
  68. Int m_upgradedSupplyBoost;
  69. WorkerAIUpdateModuleData()
  70. {
  71. m_maxBoxesData = 0;
  72. m_repairHealthPercentPerSecond = 0.0f;
  73. m_boredTime = 0.0f;
  74. m_boredRange = 0.0f;
  75. m_centerDelay = 0;
  76. m_warehouseDelay = 0;
  77. m_warehouseScanDistance = 100;
  78. m_upgradedSupplyBoost = 0;
  79. }
  80. static void buildFieldParse(MultiIniFieldParse& p)
  81. {
  82. AIUpdateModuleData::buildFieldParse(p);
  83. static const FieldParse dataFieldParse[] =
  84. {
  85. { "MaxBoxes", INI::parseInt, NULL, offsetof( WorkerAIUpdateModuleData, m_maxBoxesData ) },
  86. { "RepairHealthPercentPerSecond", INI::parsePercentToReal, NULL, offsetof( WorkerAIUpdateModuleData, m_repairHealthPercentPerSecond ) },
  87. { "BoredTime", INI::parseDurationReal, NULL, offsetof( WorkerAIUpdateModuleData, m_boredTime ) },
  88. { "BoredRange", INI::parseReal, NULL, offsetof( WorkerAIUpdateModuleData, m_boredRange ) },
  89. { "SupplyCenterActionDelay", INI::parseDurationUnsignedInt, NULL, offsetof( WorkerAIUpdateModuleData, m_centerDelay ) },
  90. { "SupplyWarehouseActionDelay", INI::parseDurationUnsignedInt, NULL, offsetof( WorkerAIUpdateModuleData, m_warehouseDelay ) },
  91. { "SupplyWarehouseScanDistance", INI::parseReal, NULL, offsetof( WorkerAIUpdateModuleData, m_warehouseScanDistance ) },
  92. { "SuppliesDepletedVoice", INI::parseAudioEventRTS, NULL, offsetof( WorkerAIUpdateModuleData, m_suppliesDepletedVoice) },
  93. { "UpgradedSupplyBoost", INI::parseInt, NULL, offsetof( WorkerAIUpdateModuleData, m_upgradedSupplyBoost) },
  94. { 0, 0, 0, 0 }
  95. };
  96. p.add(dataFieldParse);
  97. }
  98. };
  99. class WorkerAIInterface
  100. {
  101. public:
  102. virtual void exitingSupplyTruckState() = 0; ///< This worker is leaving a supply truck task and should go back to Dozer mode.
  103. };
  104. class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public SupplyTruckAIInterface, public WorkerAIInterface
  105. {
  106. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( WorkerAIUpdate, "WorkerAIUpdate" )
  107. MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( WorkerAIUpdate, WorkerAIUpdateModuleData )
  108. public:
  109. WorkerAIUpdate( Thing *thing, const ModuleData* moduleData );
  110. // virtual destructor prototype provided by memory pool declaration
  111. virtual DozerAIInterface* getDozerAIInterface() {return this;}
  112. virtual const DozerAIInterface* getDozerAIInterface() const {return this;}
  113. virtual SupplyTruckAIInterface* getSupplyTruckAIInterface() {return this;}
  114. virtual const SupplyTruckAIInterface* getSupplyTruckAIInterface() const {return this;}
  115. virtual WorkerAIInterface* getWorkerAIInterface() { return this; }
  116. virtual const WorkerAIInterface* getWorkerAIInterface() const { return this; }
  117. // Dozer side
  118. virtual void onDelete( void );
  119. virtual Real getRepairHealthPerSecond( void ) const; ///< get health to repair per second
  120. virtual Real getBoredTime( void ) const; ///< how long till we're bored
  121. virtual Real getBoredRange( void ) const; ///< when we're bored, we look this far away to do things
  122. virtual Object *construct( const ThingTemplate *what,
  123. const Coord3D *pos, Real angle,
  124. Player *owningPlayer,
  125. Bool isRebuild ); ///< construct a building
  126. // get task information
  127. virtual DozerTask getMostRecentCommand( void ); ///< return task that was most recently issued
  128. virtual Bool isTaskPending( DozerTask task ); ///< is there a desire to do the requested task
  129. virtual ObjectID getTaskTarget( DozerTask task ); ///< get target of task
  130. virtual Bool isAnyTaskPending( void ); ///< is there any dozer task pending
  131. virtual DozerTask getCurrentTask( void ) const { return m_currentTask; } ///< return the current task we're doing
  132. virtual void setCurrentTask( DozerTask task ) { m_currentTask = task; } ///< set the current task of the dozer
  133. virtual Bool getIsRebuild( void ) { return m_isRebuild; } ///< get whether or not our task is a rebuild.
  134. // task actions
  135. virtual void newTask( DozerTask task, Object* target ); ///< set a desire to do the requrested task
  136. virtual void cancelTask( DozerTask task ); ///< cancel this task from the queue, if it's the current task the dozer will stop working on it
  137. // internal methods to manage behavior from within the dozer state machine
  138. virtual void internalTaskComplete( DozerTask task ); ///< set a dozer task as successfully completed
  139. virtual void internalCancelTask( DozerTask task ); ///< cancel this task from the dozer
  140. virtual void internalTaskCompleteOrCancelled( DozerTask task ); ///< this is called when tasks are cancelled or completed
  141. /** return a dock point for the action and task (if valid) ... note it can return NULL
  142. if no point has been set for the combination of task and point */
  143. virtual const Coord3D* getDockPoint( DozerTask task, DozerDockPoint point );
  144. virtual void setBuildSubTask( DozerBuildSubTask subTask ) { m_buildSubTask = subTask; };
  145. virtual DozerBuildSubTask getBuildSubTask( void ) { return m_buildSubTask; }
  146. //
  147. // the following methods must be overridden so that if a player issues a command the dozer
  148. // can exit the internal state machine and do whatever the player says
  149. //
  150. virtual void aiDoCommand(const AICommandParms* parms);
  151. // Supply truck stuff
  152. virtual Int getNumberBoxes() const { return m_numberBoxes; }
  153. virtual Bool loseOneBox();
  154. virtual Bool gainOneBox( Int remainingStock );
  155. virtual Bool isAvailableForSupplying() const;
  156. virtual Bool isCurrentlyFerryingSupplies() const;
  157. virtual Real getWarehouseScanDistance() const; ///< How far can I look for a warehouse?
  158. virtual void setForceBusyState(Bool v) { m_forcedBusyPending = v; }
  159. virtual Bool isForcedIntoBusyState() const { return m_forcedBusyPending; }
  160. virtual void setForceWantingState(Bool v){ m_forcePending = v; }
  161. virtual Bool isForcedIntoWantingState() const { return m_forcePending; }
  162. virtual ObjectID getPreferredDockID() const { return m_preferredDock; }
  163. virtual UnsignedInt getActionDelayForDock( Object *dock );
  164. // worker specific
  165. Bool isSupplyTruckBrainActiveAndBusy();
  166. void resetSupplyTruckBrain();
  167. void resetDozerBrain();
  168. virtual void exitingSupplyTruckState(); ///< This worker is leaving a supply truck task and should go back to Dozer mode.
  169. virtual UpdateSleepTime update(); ///< the update entry point
  170. // repairing
  171. virtual Bool canAcceptNewRepair( Object *obj );
  172. virtual void createBridgeScaffolding( Object *bridgeTower );
  173. virtual void removeBridgeScaffolding( Object *bridgeTower );
  174. virtual void startBuildingSound( const AudioEventRTS *sound, ObjectID constructionSiteID );
  175. virtual void finishBuildingSound();
  176. virtual Int getUpgradedSupplyBoost() const;
  177. protected:
  178. // Dozer data
  179. struct DozerTaskInfo
  180. {
  181. ObjectID m_targetObjectID; ///< target object ID of task
  182. UnsignedInt m_taskOrderFrame; ///< logic frame we decided we wanted to do this task
  183. } m_task[ DOZER_NUM_TASKS ]; ///< tasks we want to do indexed by DozerTask
  184. DozerTask m_currentTask; ///< current task the dozer is attending to (if any)
  185. //
  186. // the following info array can be used if we want to have more complicated approaches
  187. // to our target depending on our task
  188. //
  189. struct DozerDockPointInfo
  190. {
  191. Bool valid; ///< this point has been set and is valid
  192. Coord3D location; ///< WORLD location
  193. } m_dockPoint[ DOZER_NUM_TASKS ][ DOZER_NUM_DOCK_POINTS ];
  194. DozerBuildSubTask m_buildSubTask; ///< for building and actually docking for the build
  195. // Supply Truck data
  196. Int m_numberBoxes;
  197. ObjectID m_preferredDock; ///< Instead of searching, try this one first
  198. Bool m_forcePending; // To prevent a function from doing a setState, forceWanting will latch into here until serviced.
  199. Bool m_isRebuild; // is our current construction task a rebuild?
  200. Bool m_forcedBusyPending; // A supply truck can't tell the difference between Idle since
  201. // I'm between docking states, or a Stop command without help.
  202. WorkerStateMachine *m_workerMachine;
  203. // The two state machines are not in Worker's machine because I need to be able to accept
  204. // Dozer like commands while acting as a Supply Truck - that's how I switch.
  205. DozerPrimaryStateMachine *m_dozerMachine; ///< the custom state machine for Dozer behavior
  206. SupplyTruckStateMachine *m_supplyTruckStateMachine;
  207. AudioEventRTS m_buildingSound; ///< sound is pulled from the object we are building!
  208. protected:
  209. virtual void privateRepair( Object *obj, CommandSourceType cmdSource ); ///< repair the target
  210. virtual void privateResumeConstruction( Object *obj, CommandSourceType cmdSource ); ///< resume construction on obj
  211. virtual void privateDock( Object *obj, CommandSourceType cmdSource );
  212. virtual void privateIdle(CommandSourceType cmdSource); ///< Enter idle state.
  213. private:
  214. void createMachines( void ); ///< create our behavior machines we need
  215. AudioEventRTS m_suppliesDepletedVoice; ///< Sound played when I take the last box.
  216. };
  217. #endif // __WORKER_AI_UPDATE_H_