GameLogic.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. ** Command & Conquer Generals(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: GameLogic.h //////////////////////////////////////////////////////////////////////////////
  24. // GameLogic singleton class - defines interface to GameLogic methods and objects
  25. // Author: Michael S. Booth, October 2000
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #pragma once
  28. #ifndef _GAME_LOGIC_H_
  29. #define _GAME_LOGIC_H_
  30. #include "Common/GameCommon.h" // ensure we get DUMP_PERF_STATS, or not
  31. #include "Common/GameType.h"
  32. #include "Common/Snapshot.h"
  33. #include "Common/STLTypedefs.h"
  34. #include "GameNetwork/NetworkDefs.h"
  35. #include "Common/STLTypedefs.h"
  36. #include "GameLogic/Module/UpdateModule.h" // needed for DIRECT_UPDATEMODULE_ACCESS
  37. /*
  38. At one time, we distinguished between sleepy and nonsleepy
  39. update modules, and kept a separate list for each. however,
  40. now that the bulk of update modules are sleepy, profiling shows
  41. that there is no real advantage to having the separate list,
  42. so to simplify the world, I am removing it. If ALLOW_NONSLEEPY_UPDATES
  43. is still undefined when we ship, please just nuke all the undefed
  44. code. (srj)
  45. */
  46. #define NO_ALLOW_NONSLEEPY_UPDATES
  47. // forward declarations
  48. class AudioEventRTS;
  49. class Object;
  50. class Drawable;
  51. class Player;
  52. class ThingTemplate;
  53. class Team;
  54. class CommandList;
  55. class GameMessage;
  56. class LoadScreen;
  57. class WindowLayout;
  58. class TerrainLogic;
  59. class GhostObjectManager;
  60. class CommandButton;
  61. enum BuildableStatus;
  62. enum ObjectStatusBits;
  63. typedef const CommandButton* ConstCommandButtonPtr;
  64. // What kind of game we're in.
  65. enum
  66. {
  67. #if !defined(_PLAYTEST)
  68. GAME_SINGLE_PLAYER,
  69. GAME_LAN,
  70. GAME_SKIRMISH,
  71. GAME_REPLAY,
  72. #endif
  73. GAME_SHELL,
  74. GAME_INTERNET,
  75. GAME_NONE
  76. };
  77. enum
  78. {
  79. CRC_CACHED,
  80. CRC_RECALC
  81. };
  82. /// Function pointers for use by GameLogic callback functions.
  83. typedef void (*GameLogicFuncPtr)( Object *obj, void *userData );
  84. typedef std::hash_map<ObjectID, Object *, rts::hash<ObjectID>, rts::equal_to<ObjectID> > ObjectPtrHash;
  85. typedef ObjectPtrHash::const_iterator ObjectPtrIter;
  86. // ------------------------------------------------------------------------------------------------
  87. /**
  88. * The implementation of GameLogic
  89. */
  90. class GameLogic : public SubsystemInterface, public Snapshot
  91. {
  92. public:
  93. GameLogic( void );
  94. virtual ~GameLogic();
  95. // subsytem methods
  96. virtual void init( void ); ///< Initialize or re-initialize the instance
  97. virtual void reset( void ); ///< Reset the logic system
  98. virtual void update( void ); ///< update the world
  99. void processCommandList( CommandList *list ); ///< process the command list
  100. void prepareNewGame( Int gameMode, GameDifficulty diff, Int rankPoints ); ///< prepare for new game
  101. void logicMessageDispatcher( GameMessage *msg,
  102. void *userData ); ///< Logic command list processing
  103. void registerObject( Object *obj ); ///< Given an object, register it with the GameLogic and give it a unique ID
  104. void addObjectToLookupTable( Object *obj ); ///< add object ID to hash lookup table
  105. void removeObjectFromLookupTable( Object *obj );///< remove object ID from hash lookup table
  106. /// @todo Change this to refer to a Region3D as an extent of the world
  107. void setWidth( Real width ); ///< Sets the width of the world
  108. Real getWidth( void ); ///< Returns the width of the world
  109. void setHeight( Real height ); ///< Sets the height of the world
  110. Real getHeight( void ); ///< Returns the height of the world
  111. Bool isInGameLogicUpdate( void ) const { return m_isInUpdate; }
  112. UnsignedInt getFrame( void ); ///< Returns the current simulation frame number
  113. UnsignedInt getCRC( Int mode = CRC_CACHED, AsciiString deepCRCFileName = AsciiString::TheEmptyString ); ///< Returns the CRC
  114. void setObjectIDCounter( ObjectID nextObjID ) { m_nextObjID = nextObjID; }
  115. ObjectID getObjectIDCounter( void ) { return m_nextObjID; }
  116. //-----------------------------------------------------------------------------------------------
  117. void setBuildableStatusOverride(const ThingTemplate* tt, BuildableStatus bs);
  118. Bool findBuildableStatusOverride(const ThingTemplate* tt, BuildableStatus& bs) const;
  119. void setControlBarOverride(const AsciiString& commandSetName, Int slot, ConstCommandButtonPtr commandButton);
  120. Bool findControlBarOverride(const AsciiString& commandSetName, Int slot, ConstCommandButtonPtr& commandButton) const;
  121. //-----------------------------------------------------------------------------------------------
  122. /// create an object given the thing template. (Only for use by ThingFactory.)
  123. Object *friend_createObject( const ThingTemplate *thing, ObjectStatusBits statusBits, Team *team );
  124. void destroyObject( Object *obj ); ///< Mark object as destroyed for later deletion
  125. Object *findObjectByID( ObjectID id ); ///< Given an ObjectID, return a pointer to the object.
  126. Object *getFirstObject( void ); ///< Returns the "first" object in the world. When used with the object method "getNextObject()", all objects in the world can be iterated.
  127. ObjectID allocateObjectID( void ); ///< Returns a new unique object id
  128. // super hack
  129. void startNewGame( Bool saveGame );
  130. void loadMapINI( AsciiString mapName );
  131. void updateLoadProgress( Int progress );
  132. void deleteLoadScreen( void );
  133. void setGameLoading( Bool loading );
  134. void setGameMode( Int mode );
  135. Int getGameMode( void );
  136. Bool isInGame( void );
  137. #if !defined(_PLAYTEST)
  138. Bool isInLanGame( void );
  139. Bool isInSinglePlayerGame( void );
  140. Bool isInSkirmishGame( void );
  141. Bool isInReplayGame( void );
  142. #endif
  143. Bool isInInternetGame( void );
  144. Bool isInShellGame( void );
  145. Bool isInMultiplayerGame( void );
  146. Bool isLoadingGame();
  147. void enableScoring(Bool score) { m_isScoringEnabled = score; }
  148. Bool isScoringEnabled() const { return m_isScoringEnabled; }
  149. void setShowBehindBuildingMarkers(Bool b) { m_showBehindBuildingMarkers = b; }
  150. Bool getShowBehindBuildingMarkers() const { return m_showBehindBuildingMarkers; }
  151. void setDrawIconUI(Bool b) { m_drawIconUI = b; }
  152. Bool getDrawIconUI() const { return m_drawIconUI; }
  153. void setShowDynamicLOD(Bool b) { m_showDynamicLOD = b; }
  154. Bool getShowDynamicLOD() const { return m_showDynamicLOD; }
  155. void setHulkMaxLifetimeOverride(Int b) { m_scriptHulkMaxLifetimeOverride = b; }
  156. Int getHulkMaxLifetimeOverride() const { return m_scriptHulkMaxLifetimeOverride; }
  157. Bool isIntroMoviePlaying();
  158. void updateObjectsChangedTriggerAreas(void) {m_frameObjectsChangedTriggerAreas = m_frame;}
  159. UnsignedInt getFrameObjectsChangedTriggerAreas(void) {return m_frameObjectsChangedTriggerAreas;}
  160. void clearGameData(Bool showScoreScreen = TRUE); ///< Clear the game data
  161. void closeWindows( void );
  162. void sendObjectCreated( Object *obj );
  163. void sendObjectDestroyed( Object *obj );
  164. void bindObjectAndDrawable(Object* obj, Drawable* draw);
  165. void setGamePaused( Bool paused, Bool pauseMusic = TRUE );
  166. Bool isGamePaused( void );
  167. Bool getInputEnabledMemory( void ) { return m_inputEnabledMemory; }
  168. void processProgress(Int playerId, Int percentage);
  169. void processProgressComplete(Int playerId);
  170. Bool isProgressComplete( void );
  171. void timeOutGameStart( void );
  172. void initTimeOutValues( void );
  173. UnsignedInt getObjectCount( void );
  174. Int getRankLevelLimit() const { return m_rankLevelLimit; }
  175. void setRankLevelLimit(Int limit)
  176. {
  177. if (limit < 1) limit = 1;
  178. m_rankLevelLimit = limit;
  179. }
  180. // We need to allow access to this, because on a restartGame, we need to restart with the settings we started with
  181. Int getRankPointsToAddAtGameStart() const { return m_rankPointsToAddAtGameStart; }
  182. #ifdef DUMP_PERF_STATS
  183. void getAIMetricsStatistics( UnsignedInt *numAI, UnsignedInt *numMoving, UnsignedInt *numAttacking, UnsignedInt *numWaitingForPath, UnsignedInt *overallFailedPathfinds );
  184. void resetOverallFailedPathfinds() { m_overallFailedPathfinds = 0; }
  185. void incrementOverallFailedPathfinds() { m_overallFailedPathfinds++; }
  186. UnsignedInt getOverallFailedPathfinds() const { return m_overallFailedPathfinds; }
  187. #endif
  188. // NOTE: selectObject and deselectObject should be called *only* by logical things, NEVER by the
  189. // client. These will cause the client to select or deselect the object, if affectClient is true.
  190. // If createToSelection is TRUE, this object causes a new group to be selected.
  191. void selectObject(Object *obj, Bool createNewSelection, PlayerMaskType playerMask, Bool affectClient = FALSE);
  192. void deselectObject(Object *obj, PlayerMaskType playerMask, Bool affectClient = FALSE);
  193. // this should be called only by UpdateModule, thanks.
  194. void friend_awakenUpdateModule(Object* obj, UpdateModulePtr update, UnsignedInt whenToWakeUp);
  195. protected:
  196. // snapshot methods
  197. virtual void crc( Xfer *xfer );
  198. virtual void xfer( Xfer *xfer );
  199. virtual void loadPostProcess( void );
  200. private:
  201. void pushSleepyUpdate(UpdateModulePtr u);
  202. UpdateModulePtr peekSleepyUpdate() const;
  203. void popSleepyUpdate();
  204. void eraseSleepyUpdate(Int i);
  205. void rebalanceSleepyUpdate(Int i);
  206. Int rebalanceParentSleepyUpdate(Int i);
  207. Int rebalanceChildSleepyUpdate(Int i);
  208. void remakeSleepyUpdate();
  209. void validateSleepyUpdate() const;
  210. private:
  211. /**
  212. overrides to thing template buildable status. doesn't really belong here,
  213. but has to go somewhere. (srj)
  214. */
  215. typedef std::hash_map< AsciiString, BuildableStatus, rts::hash<AsciiString>, rts::equal_to<AsciiString> > BuildableMap;
  216. BuildableMap m_thingTemplateBuildableOverrides;
  217. /**
  218. overrides to control bars. doesn't really belong here, but has to go somewhere. (srj)
  219. */
  220. typedef std::hash_map< AsciiString, ConstCommandButtonPtr, rts::hash<AsciiString>, rts::equal_to<AsciiString> > ControlBarOverrideMap;
  221. ControlBarOverrideMap m_controlBarOverrides;
  222. Real m_width, m_height; ///< Dimensions of the world
  223. UnsignedInt m_frame; ///< Simulation frame number
  224. // CRC cache system -----------------------------------------------------------------------------
  225. UnsignedInt m_CRC; ///< Cache of previous CRC value
  226. std::map<Int, UnsignedInt> m_cachedCRCs; ///< CRCs we've seen this frame
  227. Bool m_shouldValidateCRCs; ///< Should we validate CRCs this frame?
  228. //-----------------------------------------------------------------------------------------------
  229. //Added By Sadullah Nader
  230. //Used to for load scene
  231. Bool m_loadingScene;
  232. Bool m_isInUpdate;
  233. Int m_rankPointsToAddAtGameStart;
  234. Bool m_isScoringEnabled;
  235. Bool m_showBehindBuildingMarkers; //used by designers to override the user setting for cinematics
  236. Bool m_drawIconUI;
  237. Bool m_showDynamicLOD; //used by designers to override the user setting for cinematics
  238. Int m_scriptHulkMaxLifetimeOverride; ///< Scripts can change the lifetime of a hulk -- defaults to off (-1) in frames.
  239. /// @todo remove this hack
  240. Bool m_startNewGame;
  241. WindowLayout *m_background;
  242. Object* m_objList; ///< All of the objects in the world.
  243. ObjectPtrHash m_objHash; ///< Used for ObjectID lookups
  244. // this is a vector, but is maintained as a priority queue.
  245. // never modify it directly; please use the proper access methods.
  246. // (for an excellent discussion of priority queues, please see:
  247. // http://dogma.net/markn/articles/pq_stl/priority.htm)
  248. std::vector<UpdateModulePtr> m_sleepyUpdates;
  249. #ifdef ALLOW_NONSLEEPY_UPDATES
  250. // this is a plain old list, not a pq.
  251. std::list<UpdateModulePtr> m_normalUpdates;
  252. #endif
  253. UpdateModulePtr m_curUpdateModule;
  254. ObjectPointerList m_objectsToDestroy; ///< List of things that need to be destroyed at end of frame
  255. ObjectID m_nextObjID; ///< For allocating object id's
  256. void setDefaults( Bool saveGame ); ///< Set default values of class object
  257. void processDestroyList( void ); ///< Destroy all pending objects on the destroy list
  258. void destroyAllObjectsImmediate(); ///< destroy, and process destroy list immediately
  259. /// factory for TheTerrainLogic, called from init()
  260. virtual TerrainLogic *createTerrainLogic( void );
  261. virtual GhostObjectManager *createGhostObjectManager(void);
  262. Int m_gameMode;
  263. Int m_rankLevelLimit;
  264. LoadScreen *getLoadScreen( Bool saveGame );
  265. LoadScreen *m_loadScreen;
  266. Bool m_gamePaused;
  267. Bool m_inputEnabledMemory;// Latches used to remember what to restore to after we unpause
  268. Bool m_mouseVisibleMemory;
  269. Bool m_progressComplete[MAX_SLOTS];
  270. enum { PROGRESS_COMPLETE_TIMEOUT = 60000 }; ///< Timeout we wait for when we've completed our Load
  271. Int m_progressCompleteTimeout[MAX_SLOTS];
  272. void testTimeOut( void );
  273. void lastHeardFrom( Int playerId );
  274. Bool m_forceGameStartByTimeOut; ///< If we timeout someone we're waiting to load, set this flag to start the game
  275. #ifdef DUMP_PERF_STATS
  276. UnsignedInt m_overallFailedPathfinds;
  277. #endif
  278. UnsignedInt m_frameObjectsChangedTriggerAreas; ///< Last frame objects moved into/outof trigger areas, or were created/destroyed. jba.
  279. // ----------------------------------------------------------------------------------------------
  280. struct ObjectTOCEntry
  281. {
  282. AsciiString name;
  283. UnsignedShort id;
  284. };
  285. typedef std::list< ObjectTOCEntry > ObjectTOCList;
  286. typedef ObjectTOCList::iterator ObjectTOCListIterator;
  287. ObjectTOCList m_objectTOC; ///< the object TOC
  288. void addTOCEntry( AsciiString name, UnsignedShort id ); ///< add a new name/id TOC pair
  289. ObjectTOCEntry *findTOCEntryByName( AsciiString name ); ///< find ObjectTOC by name
  290. ObjectTOCEntry *findTOCEntryById( UnsignedShort id ); ///< find ObjectTOC by id
  291. void xferObjectTOC( Xfer *xfer ); ///< save/load object TOC for current state of map
  292. void prepareLogicForObjectLoad( void ); ///< prepare engine for object data from game file
  293. };
  294. // INLINE /////////////////////////////////////////////////////////////////////////////////////////
  295. inline void GameLogic::setWidth( Real width ) { m_width = width; }
  296. inline Real GameLogic::getWidth( void ) { return m_width; }
  297. inline void GameLogic::setHeight( Real height ) { m_height = height; }
  298. inline Real GameLogic::getHeight( void ) { return m_height; }
  299. inline UnsignedInt GameLogic::getFrame( void ) { return m_frame; }
  300. inline Bool GameLogic::isInGame( void ) { return !(m_gameMode == GAME_NONE); }
  301. inline void GameLogic::setGameMode( Int mode ) { m_gameMode = mode; }
  302. inline Int GameLogic::getGameMode( void ) { return m_gameMode; }
  303. #if !defined(_PLAYTEST)
  304. inline Bool GameLogic::isInLanGame( void ) { return (m_gameMode == GAME_LAN); }
  305. inline Bool GameLogic::isInSkirmishGame( void ) { return (m_gameMode == GAME_SKIRMISH); }
  306. inline Bool GameLogic::isInMultiplayerGame( void ) { return ((m_gameMode == GAME_LAN) || (m_gameMode == GAME_INTERNET)) ; }
  307. inline Bool GameLogic::isInReplayGame( void ) { return (m_gameMode == GAME_REPLAY); }
  308. #else
  309. inline Bool GameLogic::isInMultiplayerGame( void ) { return ((m_gameMode == GAME_INTERNET)) ; }
  310. #endif
  311. inline Bool GameLogic::isInInternetGame( void ) { return (m_gameMode == GAME_INTERNET); }
  312. inline Bool GameLogic::isInShellGame( void ) { return (m_gameMode == GAME_SHELL); }
  313. //Check for loading scene
  314. inline Bool GameLogic::isLoadingGame(){ return m_loadingScene;}
  315. inline Object* GameLogic::findObjectByID( ObjectID id )
  316. {
  317. if( id == INVALID_ID )
  318. return NULL;
  319. ObjectPtrHash::iterator it = m_objHash.find(id);
  320. if (it == m_objHash.end())
  321. return NULL;
  322. return (*it).second;
  323. }
  324. // the singleton
  325. extern GameLogic *TheGameLogic;
  326. #endif // _GAME_LOGIC_H_