| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: GameLogic.h //////////////////////////////////////////////////////////////////////////////
- // GameLogic singleton class - defines interface to GameLogic methods and objects
- // Author: Michael S. Booth, October 2000
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- #pragma once
- #ifndef _GAME_LOGIC_H_
- #define _GAME_LOGIC_H_
- #include "Common/GameCommon.h" // ensure we get DUMP_PERF_STATS, or not
- #include "Common/GameType.h"
- #include "Common/Snapshot.h"
- #include "Common/STLTypedefs.h"
- #include "GameNetwork/NetworkDefs.h"
- #include "Common/STLTypedefs.h"
- #include "GameLogic/Module/UpdateModule.h" // needed for DIRECT_UPDATEMODULE_ACCESS
- /*
- At one time, we distinguished between sleepy and nonsleepy
- update modules, and kept a separate list for each. however,
- now that the bulk of update modules are sleepy, profiling shows
- that there is no real advantage to having the separate list,
- so to simplify the world, I am removing it. If ALLOW_NONSLEEPY_UPDATES
- is still undefined when we ship, please just nuke all the undefed
- code. (srj)
- */
- #define NO_ALLOW_NONSLEEPY_UPDATES
- // forward declarations
- class AudioEventRTS;
- class Object;
- class Drawable;
- class Player;
- class ThingTemplate;
- class Team;
- class CommandList;
- class GameMessage;
- class LoadScreen;
- class WindowLayout;
- class TerrainLogic;
- class GhostObjectManager;
- class CommandButton;
- enum BuildableStatus;
- enum ObjectStatusBits;
- typedef const CommandButton* ConstCommandButtonPtr;
- // What kind of game we're in.
- enum
- {
- #if !defined(_PLAYTEST)
- GAME_SINGLE_PLAYER,
- GAME_LAN,
- GAME_SKIRMISH,
- GAME_REPLAY,
- #endif
- GAME_SHELL,
- GAME_INTERNET,
- GAME_NONE
- };
- enum
- {
- CRC_CACHED,
- CRC_RECALC
- };
- /// Function pointers for use by GameLogic callback functions.
- typedef void (*GameLogicFuncPtr)( Object *obj, void *userData );
- typedef std::hash_map<ObjectID, Object *, rts::hash<ObjectID>, rts::equal_to<ObjectID> > ObjectPtrHash;
- typedef ObjectPtrHash::const_iterator ObjectPtrIter;
- // ------------------------------------------------------------------------------------------------
- /**
- * The implementation of GameLogic
- */
- class GameLogic : public SubsystemInterface, public Snapshot
- {
- public:
- GameLogic( void );
- virtual ~GameLogic();
- // subsytem methods
- virtual void init( void ); ///< Initialize or re-initialize the instance
- virtual void reset( void ); ///< Reset the logic system
- virtual void update( void ); ///< update the world
- void processCommandList( CommandList *list ); ///< process the command list
- void prepareNewGame( Int gameMode, GameDifficulty diff, Int rankPoints ); ///< prepare for new game
- void logicMessageDispatcher( GameMessage *msg,
- void *userData ); ///< Logic command list processing
- void registerObject( Object *obj ); ///< Given an object, register it with the GameLogic and give it a unique ID
- void addObjectToLookupTable( Object *obj ); ///< add object ID to hash lookup table
- void removeObjectFromLookupTable( Object *obj );///< remove object ID from hash lookup table
- /// @todo Change this to refer to a Region3D as an extent of the world
- void setWidth( Real width ); ///< Sets the width of the world
- Real getWidth( void ); ///< Returns the width of the world
- void setHeight( Real height ); ///< Sets the height of the world
- Real getHeight( void ); ///< Returns the height of the world
- Bool isInGameLogicUpdate( void ) const { return m_isInUpdate; }
- UnsignedInt getFrame( void ); ///< Returns the current simulation frame number
- UnsignedInt getCRC( Int mode = CRC_CACHED, AsciiString deepCRCFileName = AsciiString::TheEmptyString ); ///< Returns the CRC
- void setObjectIDCounter( ObjectID nextObjID ) { m_nextObjID = nextObjID; }
- ObjectID getObjectIDCounter( void ) { return m_nextObjID; }
- //-----------------------------------------------------------------------------------------------
- void setBuildableStatusOverride(const ThingTemplate* tt, BuildableStatus bs);
- Bool findBuildableStatusOverride(const ThingTemplate* tt, BuildableStatus& bs) const;
- void setControlBarOverride(const AsciiString& commandSetName, Int slot, ConstCommandButtonPtr commandButton);
- Bool findControlBarOverride(const AsciiString& commandSetName, Int slot, ConstCommandButtonPtr& commandButton) const;
- //-----------------------------------------------------------------------------------------------
- /// create an object given the thing template. (Only for use by ThingFactory.)
- Object *friend_createObject( const ThingTemplate *thing, ObjectStatusBits statusBits, Team *team );
- void destroyObject( Object *obj ); ///< Mark object as destroyed for later deletion
- Object *findObjectByID( ObjectID id ); ///< Given an ObjectID, return a pointer to the object.
- 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.
- ObjectID allocateObjectID( void ); ///< Returns a new unique object id
- // super hack
- void startNewGame( Bool saveGame );
- void loadMapINI( AsciiString mapName );
- void updateLoadProgress( Int progress );
- void deleteLoadScreen( void );
-
- void setGameLoading( Bool loading );
- void setGameMode( Int mode );
- Int getGameMode( void );
- Bool isInGame( void );
- #if !defined(_PLAYTEST)
- Bool isInLanGame( void );
- Bool isInSinglePlayerGame( void );
- Bool isInSkirmishGame( void );
- Bool isInReplayGame( void );
- #endif
- Bool isInInternetGame( void );
- Bool isInShellGame( void );
- Bool isInMultiplayerGame( void );
- Bool isLoadingGame();
- void enableScoring(Bool score) { m_isScoringEnabled = score; }
- Bool isScoringEnabled() const { return m_isScoringEnabled; }
- void setShowBehindBuildingMarkers(Bool b) { m_showBehindBuildingMarkers = b; }
- Bool getShowBehindBuildingMarkers() const { return m_showBehindBuildingMarkers; }
- void setDrawIconUI(Bool b) { m_drawIconUI = b; }
- Bool getDrawIconUI() const { return m_drawIconUI; }
- void setShowDynamicLOD(Bool b) { m_showDynamicLOD = b; }
- Bool getShowDynamicLOD() const { return m_showDynamicLOD; }
- void setHulkMaxLifetimeOverride(Int b) { m_scriptHulkMaxLifetimeOverride = b; }
- Int getHulkMaxLifetimeOverride() const { return m_scriptHulkMaxLifetimeOverride; }
- Bool isIntroMoviePlaying();
- void updateObjectsChangedTriggerAreas(void) {m_frameObjectsChangedTriggerAreas = m_frame;}
- UnsignedInt getFrameObjectsChangedTriggerAreas(void) {return m_frameObjectsChangedTriggerAreas;}
- void clearGameData(Bool showScoreScreen = TRUE); ///< Clear the game data
- void closeWindows( void );
- void sendObjectCreated( Object *obj );
- void sendObjectDestroyed( Object *obj );
- void bindObjectAndDrawable(Object* obj, Drawable* draw);
- void setGamePaused( Bool paused, Bool pauseMusic = TRUE );
- Bool isGamePaused( void );
- Bool getInputEnabledMemory( void ) { return m_inputEnabledMemory; }
- void processProgress(Int playerId, Int percentage);
- void processProgressComplete(Int playerId);
- Bool isProgressComplete( void );
- void timeOutGameStart( void );
- void initTimeOutValues( void );
- UnsignedInt getObjectCount( void );
- Int getRankLevelLimit() const { return m_rankLevelLimit; }
- void setRankLevelLimit(Int limit)
- {
- if (limit < 1) limit = 1;
- m_rankLevelLimit = limit;
- }
-
- // We need to allow access to this, because on a restartGame, we need to restart with the settings we started with
- Int getRankPointsToAddAtGameStart() const { return m_rankPointsToAddAtGameStart; }
- #ifdef DUMP_PERF_STATS
- void getAIMetricsStatistics( UnsignedInt *numAI, UnsignedInt *numMoving, UnsignedInt *numAttacking, UnsignedInt *numWaitingForPath, UnsignedInt *overallFailedPathfinds );
- void resetOverallFailedPathfinds() { m_overallFailedPathfinds = 0; }
- void incrementOverallFailedPathfinds() { m_overallFailedPathfinds++; }
- UnsignedInt getOverallFailedPathfinds() const { return m_overallFailedPathfinds; }
- #endif
-
- // NOTE: selectObject and deselectObject should be called *only* by logical things, NEVER by the
- // client. These will cause the client to select or deselect the object, if affectClient is true.
- // If createToSelection is TRUE, this object causes a new group to be selected.
- void selectObject(Object *obj, Bool createNewSelection, PlayerMaskType playerMask, Bool affectClient = FALSE);
- void deselectObject(Object *obj, PlayerMaskType playerMask, Bool affectClient = FALSE);
- // this should be called only by UpdateModule, thanks.
- void friend_awakenUpdateModule(Object* obj, UpdateModulePtr update, UnsignedInt whenToWakeUp);
- protected:
- // snapshot methods
- virtual void crc( Xfer *xfer );
- virtual void xfer( Xfer *xfer );
- virtual void loadPostProcess( void );
- private:
- void pushSleepyUpdate(UpdateModulePtr u);
- UpdateModulePtr peekSleepyUpdate() const;
- void popSleepyUpdate();
- void eraseSleepyUpdate(Int i);
- void rebalanceSleepyUpdate(Int i);
- Int rebalanceParentSleepyUpdate(Int i);
- Int rebalanceChildSleepyUpdate(Int i);
- void remakeSleepyUpdate();
- void validateSleepyUpdate() const;
- private:
- /**
- overrides to thing template buildable status. doesn't really belong here,
- but has to go somewhere. (srj)
- */
- typedef std::hash_map< AsciiString, BuildableStatus, rts::hash<AsciiString>, rts::equal_to<AsciiString> > BuildableMap;
- BuildableMap m_thingTemplateBuildableOverrides;
- /**
- overrides to control bars. doesn't really belong here, but has to go somewhere. (srj)
- */
- typedef std::hash_map< AsciiString, ConstCommandButtonPtr, rts::hash<AsciiString>, rts::equal_to<AsciiString> > ControlBarOverrideMap;
- ControlBarOverrideMap m_controlBarOverrides;
- Real m_width, m_height; ///< Dimensions of the world
- UnsignedInt m_frame; ///< Simulation frame number
-
- // CRC cache system -----------------------------------------------------------------------------
- UnsignedInt m_CRC; ///< Cache of previous CRC value
- std::map<Int, UnsignedInt> m_cachedCRCs; ///< CRCs we've seen this frame
- Bool m_shouldValidateCRCs; ///< Should we validate CRCs this frame?
- //-----------------------------------------------------------------------------------------------
- //Added By Sadullah Nader
- //Used to for load scene
- Bool m_loadingScene;
- Bool m_isInUpdate;
- Int m_rankPointsToAddAtGameStart;
- Bool m_isScoringEnabled;
- Bool m_showBehindBuildingMarkers; //used by designers to override the user setting for cinematics
- Bool m_drawIconUI;
- Bool m_showDynamicLOD; //used by designers to override the user setting for cinematics
- Int m_scriptHulkMaxLifetimeOverride; ///< Scripts can change the lifetime of a hulk -- defaults to off (-1) in frames.
- /// @todo remove this hack
- Bool m_startNewGame;
- WindowLayout *m_background;
- Object* m_objList; ///< All of the objects in the world.
- ObjectPtrHash m_objHash; ///< Used for ObjectID lookups
- // this is a vector, but is maintained as a priority queue.
- // never modify it directly; please use the proper access methods.
- // (for an excellent discussion of priority queues, please see:
- // http://dogma.net/markn/articles/pq_stl/priority.htm)
- std::vector<UpdateModulePtr> m_sleepyUpdates;
-
- #ifdef ALLOW_NONSLEEPY_UPDATES
- // this is a plain old list, not a pq.
- std::list<UpdateModulePtr> m_normalUpdates;
- #endif
- UpdateModulePtr m_curUpdateModule;
- ObjectPointerList m_objectsToDestroy; ///< List of things that need to be destroyed at end of frame
- ObjectID m_nextObjID; ///< For allocating object id's
- void setDefaults( Bool saveGame ); ///< Set default values of class object
- void processDestroyList( void ); ///< Destroy all pending objects on the destroy list
- void destroyAllObjectsImmediate(); ///< destroy, and process destroy list immediately
- /// factory for TheTerrainLogic, called from init()
- virtual TerrainLogic *createTerrainLogic( void );
- virtual GhostObjectManager *createGhostObjectManager(void);
- Int m_gameMode;
- Int m_rankLevelLimit;
- LoadScreen *getLoadScreen( Bool saveGame );
- LoadScreen *m_loadScreen;
- Bool m_gamePaused;
- Bool m_inputEnabledMemory;// Latches used to remember what to restore to after we unpause
- Bool m_mouseVisibleMemory;
- Bool m_progressComplete[MAX_SLOTS];
- enum { PROGRESS_COMPLETE_TIMEOUT = 60000 }; ///< Timeout we wait for when we've completed our Load
- Int m_progressCompleteTimeout[MAX_SLOTS];
- void testTimeOut( void );
- void lastHeardFrom( Int playerId );
- Bool m_forceGameStartByTimeOut; ///< If we timeout someone we're waiting to load, set this flag to start the game
- #ifdef DUMP_PERF_STATS
- UnsignedInt m_overallFailedPathfinds;
- #endif
- UnsignedInt m_frameObjectsChangedTriggerAreas; ///< Last frame objects moved into/outof trigger areas, or were created/destroyed. jba.
- // ----------------------------------------------------------------------------------------------
- struct ObjectTOCEntry
- {
- AsciiString name;
- UnsignedShort id;
- };
- typedef std::list< ObjectTOCEntry > ObjectTOCList;
- typedef ObjectTOCList::iterator ObjectTOCListIterator;
- ObjectTOCList m_objectTOC; ///< the object TOC
- void addTOCEntry( AsciiString name, UnsignedShort id ); ///< add a new name/id TOC pair
- ObjectTOCEntry *findTOCEntryByName( AsciiString name ); ///< find ObjectTOC by name
- ObjectTOCEntry *findTOCEntryById( UnsignedShort id ); ///< find ObjectTOC by id
- void xferObjectTOC( Xfer *xfer ); ///< save/load object TOC for current state of map
- void prepareLogicForObjectLoad( void ); ///< prepare engine for object data from game file
-
- };
- // INLINE /////////////////////////////////////////////////////////////////////////////////////////
- inline void GameLogic::setWidth( Real width ) { m_width = width; }
- inline Real GameLogic::getWidth( void ) { return m_width; }
- inline void GameLogic::setHeight( Real height ) { m_height = height; }
- inline Real GameLogic::getHeight( void ) { return m_height; }
- inline UnsignedInt GameLogic::getFrame( void ) { return m_frame; }
- inline Bool GameLogic::isInGame( void ) { return !(m_gameMode == GAME_NONE); }
- inline void GameLogic::setGameMode( Int mode ) { m_gameMode = mode; }
- inline Int GameLogic::getGameMode( void ) { return m_gameMode; }
- #if !defined(_PLAYTEST)
- inline Bool GameLogic::isInLanGame( void ) { return (m_gameMode == GAME_LAN); }
- inline Bool GameLogic::isInSkirmishGame( void ) { return (m_gameMode == GAME_SKIRMISH); }
- inline Bool GameLogic::isInMultiplayerGame( void ) { return ((m_gameMode == GAME_LAN) || (m_gameMode == GAME_INTERNET)) ; }
- inline Bool GameLogic::isInReplayGame( void ) { return (m_gameMode == GAME_REPLAY); }
- #else
- inline Bool GameLogic::isInMultiplayerGame( void ) { return ((m_gameMode == GAME_INTERNET)) ; }
- #endif
- inline Bool GameLogic::isInInternetGame( void ) { return (m_gameMode == GAME_INTERNET); }
- inline Bool GameLogic::isInShellGame( void ) { return (m_gameMode == GAME_SHELL); }
- //Check for loading scene
- inline Bool GameLogic::isLoadingGame(){ return m_loadingScene;}
- inline Object* GameLogic::findObjectByID( ObjectID id )
- {
- if( id == INVALID_ID )
- return NULL;
- ObjectPtrHash::iterator it = m_objHash.find(id);
- if (it == m_objHash.end())
- return NULL;
-
- return (*it).second;
- }
- // the singleton
- extern GameLogic *TheGameLogic;
- #endif // _GAME_LOGIC_H_
|