1010 lines
41 KiB
C++
1010 lines
41 KiB
C++
![]() |
/*
|
||
|
** Command & Conquer Generals Zero Hour(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. //
|
||
|
// //
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// GameEngine.cpp /////////////////////////////////////////////////////////////////////////////////
|
||
|
// Implementation of the Game Engine singleton
|
||
|
// Author: Michael S. Booth, April 2001
|
||
|
|
||
|
#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
|
||
|
|
||
|
#include "Common/ActionManager.h"
|
||
|
#include "Common/AudioAffect.h"
|
||
|
#include "Common/BuildAssistant.h"
|
||
|
#include "Common/CRCDebug.h"
|
||
|
#include "Common/Radar.h"
|
||
|
#include "Common/PlayerTemplate.h"
|
||
|
#include "Common/Team.h"
|
||
|
#include "Common/PlayerList.h"
|
||
|
#include "Common/GameAudio.h"
|
||
|
#include "Common/GameEngine.h"
|
||
|
#include "Common/INI.h"
|
||
|
#include "Common/INIException.h"
|
||
|
#include "Common/MessageStream.h"
|
||
|
#include "Common/ThingFactory.h"
|
||
|
#include "Common/File.h"
|
||
|
#include "Common/FileSystem.h"
|
||
|
#include "Common/ArchiveFileSystem.h"
|
||
|
#include "Common/LocalFileSystem.h"
|
||
|
#include "Common/CDManager.h"
|
||
|
#include "Common/GlobalData.h"
|
||
|
#include "Common/PerfTimer.h"
|
||
|
#include "Common/RandomValue.h"
|
||
|
#include "Common/NameKeyGenerator.h"
|
||
|
#include "Common/ModuleFactory.h"
|
||
|
#include "Common/Debug.h"
|
||
|
#include "Common/GameState.h"
|
||
|
#include "Common/GameStateMap.h"
|
||
|
#include "Common/Science.h"
|
||
|
#include "Common/FunctionLexicon.h"
|
||
|
#include "Common/CommandLine.h"
|
||
|
#include "Common/DamageFX.h"
|
||
|
#include "Common/MultiplayerSettings.h"
|
||
|
#include "Common/Recorder.h"
|
||
|
#include "Common/SpecialPower.h"
|
||
|
#include "Common/TerrainTypes.h"
|
||
|
#include "Common/Upgrade.h"
|
||
|
#include "Common/UserPreferences.h"
|
||
|
#include "Common/Xfer.h"
|
||
|
#include "Common/XferCRC.h"
|
||
|
#include "Common/GameLOD.h"
|
||
|
#include "Common/Registry.h"
|
||
|
#include "Common/GameCommon.h" // FOR THE ALLOW_DEBUG_CHEATS_IN_RELEASE #define
|
||
|
|
||
|
#include "GameLogic/Armor.h"
|
||
|
#include "GameLogic/AI.h"
|
||
|
#include "GameLogic/CaveSystem.h"
|
||
|
#include "GameLogic/CrateSystem.h"
|
||
|
#include "GameLogic/Damage.h"
|
||
|
#include "GameLogic/VictoryConditions.h"
|
||
|
#include "GameLogic/ObjectCreationList.h"
|
||
|
#include "GameLogic/Weapon.h"
|
||
|
#include "GameLogic/GameLogic.h"
|
||
|
#include "GameLogic/Locomotor.h"
|
||
|
#include "GameLogic/RankInfo.h"
|
||
|
#include "GameLogic/ScriptEngine.h"
|
||
|
#include "GameLogic/SidesList.h"
|
||
|
|
||
|
#include "GameClient/Display.h"
|
||
|
#include "GameClient/FXList.h"
|
||
|
#include "GameClient/GameClient.h"
|
||
|
#include "GameClient/Keyboard.h"
|
||
|
#include "GameClient/Shell.h"
|
||
|
#include "GameClient/GameText.h"
|
||
|
#include "GameClient/ParticleSys.h"
|
||
|
#include "GameClient/Water.h"
|
||
|
#include "GameClient/TerrainRoads.h"
|
||
|
#include "GameClient/MetaEvent.h"
|
||
|
#include "GameClient/MapUtil.h"
|
||
|
#include "GameClient/GameWindowManager.h"
|
||
|
#include "GameClient/GlobalLanguage.h"
|
||
|
#include "GameClient/Drawable.h"
|
||
|
#include "GameClient/GUICallbacks.h"
|
||
|
|
||
|
#include "GameNetwork/NetworkInterface.h"
|
||
|
#include "GameNetwork/WOLBrowser/WebBrowser.h"
|
||
|
#include "GameNetwork/LANAPI.h"
|
||
|
#include "GameNetwork/GameSpy/GameResultsThread.h"
|
||
|
|
||
|
#include "Common/Version.h"
|
||
|
|
||
|
#ifdef _INTERNAL
|
||
|
// for occasional debugging...
|
||
|
//#pragma optimize("", off)
|
||
|
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||
|
#endif
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
|
||
|
#ifdef DEBUG_CRC
|
||
|
class DeepCRCSanityCheck : public SubsystemInterface
|
||
|
{
|
||
|
public:
|
||
|
DeepCRCSanityCheck() {}
|
||
|
virtual ~DeepCRCSanityCheck() {}
|
||
|
|
||
|
virtual void init(void) {}
|
||
|
virtual void reset(void);
|
||
|
virtual void update(void) {}
|
||
|
|
||
|
protected:
|
||
|
};
|
||
|
|
||
|
DeepCRCSanityCheck *TheDeepCRCSanityCheck = NULL;
|
||
|
|
||
|
void DeepCRCSanityCheck::reset(void)
|
||
|
{
|
||
|
static Int timesThrough = 0;
|
||
|
static UnsignedInt lastCRC = 0;
|
||
|
|
||
|
AsciiString fname;
|
||
|
fname.format("%sCRCAfter%dMaps.dat", TheGlobalData->getPath_UserData().str(), timesThrough);
|
||
|
UnsignedInt thisCRC = TheGameLogic->getCRC( CRC_RECALC, fname );
|
||
|
|
||
|
DEBUG_LOG(("DeepCRCSanityCheck: CRC is %X\n", thisCRC));
|
||
|
DEBUG_ASSERTCRASH(timesThrough == 0 || thisCRC == lastCRC,
|
||
|
("CRC after reset did not match beginning CRC!\nNetwork games won't work after this.\nOld: 0x%8.8X, New: 0x%8.8X",
|
||
|
lastCRC, thisCRC));
|
||
|
lastCRC = thisCRC;
|
||
|
|
||
|
timesThrough++;
|
||
|
}
|
||
|
#endif // DEBUG_CRC
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
/// The GameEngine singleton instance
|
||
|
GameEngine *TheGameEngine = NULL;
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
SubsystemInterfaceList* TheSubsystemList = NULL;
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
template<class SUBSYSTEM>
|
||
|
void initSubsystem(SUBSYSTEM*& sysref, AsciiString name, SUBSYSTEM* sys, Xfer *pXfer, const char* path1 = NULL,
|
||
|
const char* path2 = NULL, const char* dirpath = NULL)
|
||
|
{
|
||
|
sysref = sys;
|
||
|
TheSubsystemList->initSubsystem(sys, path1, path2, dirpath, pXfer, name);
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
extern HINSTANCE ApplicationHInstance; ///< our application instance
|
||
|
extern CComModule _Module;
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
static void updateTGAtoDDS();
|
||
|
|
||
|
Int GameEngine::getFramesPerSecondLimit( void )
|
||
|
{
|
||
|
return m_maxFPS;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
GameEngine::GameEngine( void )
|
||
|
{
|
||
|
// Set the time slice size to 1 ms.
|
||
|
timeBeginPeriod(1);
|
||
|
|
||
|
// initialize to non garbage values
|
||
|
m_maxFPS = 0;
|
||
|
m_quitting = FALSE;
|
||
|
m_isActive = FALSE;
|
||
|
|
||
|
_Module.Init(NULL, ApplicationHInstance);
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
GameEngine::~GameEngine()
|
||
|
{
|
||
|
//extern std::vector<std::string> preloadTextureNamesGlobalHack;
|
||
|
//preloadTextureNamesGlobalHack.clear();
|
||
|
|
||
|
delete TheMapCache;
|
||
|
TheMapCache = NULL;
|
||
|
|
||
|
// delete TheShell;
|
||
|
// TheShell = NULL;
|
||
|
|
||
|
TheGameResultsQueue->endThreads();
|
||
|
|
||
|
TheSubsystemList->shutdownAll();
|
||
|
delete TheSubsystemList;
|
||
|
TheSubsystemList = NULL;
|
||
|
|
||
|
delete TheNetwork;
|
||
|
TheNetwork = NULL;
|
||
|
|
||
|
delete TheCommandList;
|
||
|
TheCommandList = NULL;
|
||
|
|
||
|
delete TheNameKeyGenerator;
|
||
|
TheNameKeyGenerator = NULL;
|
||
|
|
||
|
delete TheFileSystem;
|
||
|
TheFileSystem = NULL;
|
||
|
|
||
|
if (TheGameLODManager)
|
||
|
delete TheGameLODManager;
|
||
|
|
||
|
Drawable::killStaticImages();
|
||
|
|
||
|
_Module.Term();
|
||
|
|
||
|
#ifdef PERF_TIMERS
|
||
|
PerfGather::termPerfDump();
|
||
|
#endif
|
||
|
|
||
|
// Restore the previous time slice for Windows.
|
||
|
timeEndPeriod(1);
|
||
|
}
|
||
|
|
||
|
void GameEngine::setFramesPerSecondLimit( Int fps )
|
||
|
{
|
||
|
DEBUG_LOG(("GameEngine::setFramesPerSecondLimit() - setting max fps to %d (TheGlobalData->m_useFpsLimit == %d)\n", fps, TheGlobalData->m_useFpsLimit));
|
||
|
m_maxFPS = fps;
|
||
|
}
|
||
|
|
||
|
/** -----------------------------------------------------------------------------------------------
|
||
|
* Initialize the game engine by initializing the GameLogic and GameClient.
|
||
|
*/
|
||
|
void GameEngine::init( void ) {} /// @todo: I changed this to take argc & argv so we can parse those after the GDF is loaded. We need to rethink this immediately as it is a nasty hack
|
||
|
void GameEngine::init( int argc, char *argv[] )
|
||
|
{
|
||
|
try {
|
||
|
//create an INI object to use for loading stuff
|
||
|
INI ini;
|
||
|
|
||
|
#ifdef DEBUG_LOGGING
|
||
|
if (TheVersion)
|
||
|
{
|
||
|
DEBUG_LOG(("================================================================================\n"));
|
||
|
#if defined _DEBUG
|
||
|
const char *buildType = "Debug";
|
||
|
#elif defined _INTERNAL
|
||
|
const char *buildType = "Internal";
|
||
|
#else
|
||
|
const char *buildType = "Release";
|
||
|
#endif
|
||
|
DEBUG_LOG(("Generals version %s (%s)\n", TheVersion->getAsciiVersion().str(), buildType));
|
||
|
DEBUG_LOG(("Build date: %s\n", TheVersion->getAsciiBuildTime().str()));
|
||
|
DEBUG_LOG(("Build location: %s\n", TheVersion->getAsciiBuildLocation().str()));
|
||
|
DEBUG_LOG(("Built by: %s\n", TheVersion->getAsciiBuildUser().str()));
|
||
|
DEBUG_LOG(("================================================================================\n"));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if defined(PERF_TIMERS) || defined(DUMP_PERF_STATS)
|
||
|
DEBUG_LOG(("Calculating CPU frequency for performance timers.\n"));
|
||
|
InitPrecisionTimer();
|
||
|
#endif
|
||
|
#ifdef PERF_TIMERS
|
||
|
PerfGather::initPerfDump("AAAPerfStats", PerfGather::PERF_NETTIME);
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS////////////////////////////////////////////////////////////
|
||
|
__int64 startTime64;//////////////////////////////////////////////////////////////
|
||
|
__int64 endTime64,freq64;///////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimerTicksPerSec(&freq64);///////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&startTime64);////////////////////////////////////////////////////
|
||
|
char Buf[256];//////////////////////////////////////////////////////////////////////
|
||
|
#endif//////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
m_maxFPS = DEFAULT_MAX_FPS;
|
||
|
|
||
|
TheSubsystemList = MSGNEW("GameEngineSubsystem") SubsystemInterfaceList;
|
||
|
|
||
|
TheSubsystemList->addSubsystem(this);
|
||
|
|
||
|
// initialize the random number system
|
||
|
InitRandom();
|
||
|
|
||
|
// Create the low-level file system interface
|
||
|
TheFileSystem = createFileSystem();
|
||
|
|
||
|
//Kris: Patch 1.01 - November 17, 2003
|
||
|
//I was unable to resolve the RTPatch method of deleting a shipped file. English, Chinese, and Korean
|
||
|
//SKU's shipped with two INIZH.big files. One properly in the Run directory and the other in Run\INI\Data.
|
||
|
//We need to toast the latter in order for the game to patch properly.
|
||
|
DeleteFile( "Data\\INI\\INIZH.big" );
|
||
|
|
||
|
// not part of the subsystem list, because it should normally never be reset!
|
||
|
TheNameKeyGenerator = MSGNEW("GameEngineSubsystem") NameKeyGenerator;
|
||
|
TheNameKeyGenerator->init();
|
||
|
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheNameKeyGenerator = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
// not part of the subsystem list, because it should normally never be reset!
|
||
|
TheCommandList = MSGNEW("GameEngineSubsystem") CommandList;
|
||
|
TheCommandList->init();
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheCommandList = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
XferCRC xferCRC;
|
||
|
xferCRC.open("lightCRC");
|
||
|
|
||
|
|
||
|
initSubsystem(TheLocalFileSystem, "TheLocalFileSystem", createLocalFileSystem(), NULL);
|
||
|
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheLocalFileSystem = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
initSubsystem(TheArchiveFileSystem, "TheArchiveFileSystem", createArchiveFileSystem(), NULL); // this MUST come after TheLocalFileSystem creation
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheArchiveFileSystem = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
initSubsystem(TheWritableGlobalData, "TheWritableGlobalData", MSGNEW("GameEngineSubsystem") GlobalData(), &xferCRC, "Data\\INI\\Default\\GameData.ini", "Data\\INI\\GameData.ini");
|
||
|
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheWritableGlobalData = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
|
||
|
#if defined(_DEBUG) || defined(_INTERNAL)
|
||
|
// If we're in Debug or Internal, load the Debug info as well.
|
||
|
ini.load( AsciiString( "Data\\INI\\GameDataDebug.ini" ), INI_LOAD_OVERWRITE, NULL );
|
||
|
#endif
|
||
|
|
||
|
// special-case: parse command-line parameters after loading global data
|
||
|
parseCommandLine(argc, argv);
|
||
|
|
||
|
// doesn't require resets so just create a single instance here.
|
||
|
TheGameLODManager = MSGNEW("GameEngineSubsystem") GameLODManager;
|
||
|
TheGameLODManager->init();
|
||
|
|
||
|
// after parsing the command line, we may want to perform dds stuff. Do that here.
|
||
|
if (TheGlobalData->m_shouldUpdateTGAToDDS) {
|
||
|
// update any out of date targas here.
|
||
|
updateTGAtoDDS();
|
||
|
}
|
||
|
|
||
|
// read the water settings from INI (must do prior to initing GameClient, apparently)
|
||
|
ini.load( AsciiString( "Data\\INI\\Default\\Water.ini" ), INI_LOAD_OVERWRITE, &xferCRC );
|
||
|
ini.load( AsciiString( "Data\\INI\\Water.ini" ), INI_LOAD_OVERWRITE, &xferCRC );
|
||
|
ini.load( AsciiString( "Data\\INI\\Default\\Weather.ini" ), INI_LOAD_OVERWRITE, &xferCRC );
|
||
|
ini.load( AsciiString( "Data\\INI\\Weather.ini" ), INI_LOAD_OVERWRITE, &xferCRC );
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After water INI's = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
#ifdef DEBUG_CRC
|
||
|
initSubsystem(TheDeepCRCSanityCheck, "TheDeepCRCSanityCheck", MSGNEW("GameEngineSubystem") DeepCRCSanityCheck, NULL, NULL, NULL, NULL);
|
||
|
#endif // DEBUG_CRC
|
||
|
initSubsystem(TheGameText, "TheGameText", CreateGameTextInterface(), NULL);
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheGameText = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
initSubsystem(TheScienceStore,"TheScienceStore", MSGNEW("GameEngineSubsystem") ScienceStore(), &xferCRC, "Data\\INI\\Default\\Science.ini", "Data\\INI\\Science.ini");
|
||
|
initSubsystem(TheMultiplayerSettings,"TheMultiplayerSettings", MSGNEW("GameEngineSubsystem") MultiplayerSettings(), &xferCRC, "Data\\INI\\Default\\Multiplayer.ini", "Data\\INI\\Multiplayer.ini");
|
||
|
initSubsystem(TheTerrainTypes,"TheTerrainTypes", MSGNEW("GameEngineSubsystem") TerrainTypeCollection(), &xferCRC, "Data\\INI\\Default\\Terrain.ini", "Data\\INI\\Terrain.ini");
|
||
|
initSubsystem(TheTerrainRoads,"TheTerrainRoads", MSGNEW("GameEngineSubsystem") TerrainRoadCollection(), &xferCRC, "Data\\INI\\Default\\Roads.ini", "Data\\INI\\Roads.ini");
|
||
|
initSubsystem(TheGlobalLanguageData,"TheGlobalLanguageData",MSGNEW("GameEngineSubsystem") GlobalLanguage, NULL); // must be before the game text
|
||
|
initSubsystem(TheCDManager,"TheCDManager", CreateCDManager(), NULL);
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheCDManager = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
initSubsystem(TheAudio,"TheAudio", createAudioManager(), NULL);
|
||
|
if (!TheAudio->isMusicAlreadyLoaded())
|
||
|
setQuitting(TRUE);
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheAudio = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
initSubsystem(TheFunctionLexicon,"TheFunctionLexicon", createFunctionLexicon(), NULL);
|
||
|
initSubsystem(TheModuleFactory,"TheModuleFactory", createModuleFactory(), NULL);
|
||
|
initSubsystem(TheMessageStream,"TheMessageStream", createMessageStream(), NULL);
|
||
|
initSubsystem(TheSidesList,"TheSidesList", MSGNEW("GameEngineSubsystem") SidesList(), NULL);
|
||
|
initSubsystem(TheCaveSystem,"TheCaveSystem", MSGNEW("GameEngineSubsystem") CaveSystem(), NULL);
|
||
|
initSubsystem(TheRankInfoStore,"TheRankInfoStore", MSGNEW("GameEngineSubsystem") RankInfoStore(), &xferCRC, NULL, "Data\\INI\\Rank.ini");
|
||
|
initSubsystem(ThePlayerTemplateStore,"ThePlayerTemplateStore", MSGNEW("GameEngineSubsystem") PlayerTemplateStore(), &xferCRC, "Data\\INI\\Default\\PlayerTemplate.ini", "Data\\INI\\PlayerTemplate.ini");
|
||
|
initSubsystem(TheParticleSystemManager,"TheParticleSystemManager", createParticleSystemManager(), NULL);
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheParticleSystemManager = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
initSubsystem(TheFXListStore,"TheFXListStore", MSGNEW("GameEngineSubsystem") FXListStore(), &xferCRC, "Data\\INI\\Default\\FXList.ini", "Data\\INI\\FXList.ini");
|
||
|
initSubsystem(TheWeaponStore,"TheWeaponStore", MSGNEW("GameEngineSubsystem") WeaponStore(), &xferCRC, NULL, "Data\\INI\\Weapon.ini");
|
||
|
initSubsystem(TheObjectCreationListStore,"TheObjectCreationListStore", MSGNEW("GameEngineSubsystem") ObjectCreationListStore(), &xferCRC, "Data\\INI\\Default\\ObjectCreationList.ini", "Data\\INI\\ObjectCreationList.ini");
|
||
|
initSubsystem(TheLocomotorStore,"TheLocomotorStore", MSGNEW("GameEngineSubsystem") LocomotorStore(), &xferCRC, NULL, "Data\\INI\\Locomotor.ini");
|
||
|
initSubsystem(TheSpecialPowerStore,"TheSpecialPowerStore", MSGNEW("GameEngineSubsystem") SpecialPowerStore(), &xferCRC, "Data\\INI\\Default\\SpecialPower.ini", "Data\\INI\\SpecialPower.ini");
|
||
|
initSubsystem(TheDamageFXStore,"TheDamageFXStore", MSGNEW("GameEngineSubsystem") DamageFXStore(), &xferCRC, NULL, "Data\\INI\\DamageFX.ini");
|
||
|
initSubsystem(TheArmorStore,"TheArmorStore", MSGNEW("GameEngineSubsystem") ArmorStore(), &xferCRC, NULL, "Data\\INI\\Armor.ini");
|
||
|
initSubsystem(TheBuildAssistant,"TheBuildAssistant", MSGNEW("GameEngineSubsystem") BuildAssistant, NULL);
|
||
|
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheBuildAssistant = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
|
||
|
initSubsystem(TheThingFactory,"TheThingFactory", createThingFactory(), &xferCRC, "Data\\INI\\Default\\Object.ini", NULL, "Data\\INI\\Object");
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheThingFactory = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
initSubsystem(TheUpgradeCenter,"TheUpgradeCenter", MSGNEW("GameEngineSubsystem") UpgradeCenter, &xferCRC, "Data\\INI\\Default\\Upgrade.ini", "Data\\INI\\Upgrade.ini");
|
||
|
initSubsystem(TheGameClient,"TheGameClient", createGameClient(), NULL);
|
||
|
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheGameClient = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
initSubsystem(TheAI,"TheAI", MSGNEW("GameEngineSubsystem") AI(), &xferCRC, "Data\\INI\\Default\\AIData.ini", "Data\\INI\\AIData.ini");
|
||
|
initSubsystem(TheGameLogic,"TheGameLogic", createGameLogic(), NULL);
|
||
|
initSubsystem(TheTeamFactory,"TheTeamFactory", MSGNEW("GameEngineSubsystem") TeamFactory(), NULL);
|
||
|
initSubsystem(TheCrateSystem,"TheCrateSystem", MSGNEW("GameEngineSubsystem") CrateSystem(), &xferCRC, "Data\\INI\\Default\\Crate.ini", "Data\\INI\\Crate.ini");
|
||
|
initSubsystem(ThePlayerList,"ThePlayerList", MSGNEW("GameEngineSubsystem") PlayerList(), NULL);
|
||
|
initSubsystem(TheRecorder,"TheRecorder", createRecorder(), NULL);
|
||
|
initSubsystem(TheRadar,"TheRadar", createRadar(), NULL);
|
||
|
initSubsystem(TheVictoryConditions,"TheVictoryConditions", createVictoryConditions(), NULL);
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheVictoryConditions = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
AsciiString fname;
|
||
|
fname.format("Data\\%s\\CommandMap.ini", GetRegistryLanguage().str());
|
||
|
initSubsystem(TheMetaMap,"TheMetaMap", MSGNEW("GameEngineSubsystem") MetaMap(), NULL, fname.str(), "Data\\INI\\CommandMap.ini");
|
||
|
|
||
|
#if defined(_DEBUG) || defined(_INTERNAL)
|
||
|
ini.load("Data\\INI\\CommandMapDebug.ini", INI_LOAD_MULTIFILE, NULL);
|
||
|
#endif
|
||
|
|
||
|
#if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)
|
||
|
ini.load("Data\\INI\\CommandMapDemo.ini", INI_LOAD_MULTIFILE, NULL);
|
||
|
#endif
|
||
|
|
||
|
|
||
|
initSubsystem(TheActionManager,"TheActionManager", MSGNEW("GameEngineSubsystem") ActionManager(), NULL);
|
||
|
//initSubsystem((CComObject<WebBrowser> *)TheWebBrowser,"(CComObject<WebBrowser> *)TheWebBrowser", (CComObject<WebBrowser> *)createWebBrowser(), NULL);
|
||
|
initSubsystem(TheGameStateMap,"TheGameStateMap", MSGNEW("GameEngineSubsystem") GameStateMap, NULL, NULL, NULL );
|
||
|
initSubsystem(TheGameState,"TheGameState", MSGNEW("GameEngineSubsystem") GameState, NULL, NULL, NULL );
|
||
|
|
||
|
// Create the interface for sending game results
|
||
|
initSubsystem(TheGameResultsQueue,"TheGameResultsQueue", GameResultsInterface::createNewGameResultsInterface(), NULL, NULL, NULL, NULL);
|
||
|
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheGameResultsQueue = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
xferCRC.close();
|
||
|
TheWritableGlobalData->m_iniCRC = xferCRC.getCRC();
|
||
|
DEBUG_LOG(("INI CRC is 0x%8.8X\n", TheGlobalData->m_iniCRC));
|
||
|
|
||
|
TheSubsystemList->postProcessLoadAll();
|
||
|
|
||
|
setFramesPerSecondLimit(TheGlobalData->m_framesPerSecondLimit);
|
||
|
|
||
|
TheAudio->setOn(TheGlobalData->m_audioOn && TheGlobalData->m_musicOn, AudioAffect_Music);
|
||
|
TheAudio->setOn(TheGlobalData->m_audioOn && TheGlobalData->m_soundsOn, AudioAffect_Sound);
|
||
|
TheAudio->setOn(TheGlobalData->m_audioOn && TheGlobalData->m_sounds3DOn, AudioAffect_Sound3D);
|
||
|
TheAudio->setOn(TheGlobalData->m_audioOn && TheGlobalData->m_speechOn, AudioAffect_Speech);
|
||
|
|
||
|
// We're not in a network game yet, so set the network singleton to NULL.
|
||
|
TheNetwork = NULL;
|
||
|
|
||
|
//Create a default ini file for options if it doesn't already exist.
|
||
|
//OptionPreferences prefs( TRUE );
|
||
|
|
||
|
// If we turn m_quitting to FALSE here, then we throw away any requests to quit that
|
||
|
// took place during loading. :-\ - jkmcd
|
||
|
// If this really needs to take place, please make sure that pressing cancel on the audio
|
||
|
// load music dialog will still cause the game to quit.
|
||
|
// m_quitting = FALSE;
|
||
|
|
||
|
// for fingerprinting, we need to ensure the presence of these files
|
||
|
|
||
|
|
||
|
#if !defined(_INTERNAL) && !defined(_DEBUG)
|
||
|
AsciiString dirName;
|
||
|
dirName = TheArchiveFileSystem->getArchiveFilenameForFile("generalsbzh.sec");
|
||
|
|
||
|
if (dirName.compareNoCase("genseczh.big") != 0)
|
||
|
{
|
||
|
DEBUG_LOG(("generalsbzh.sec was not found in genseczh.big - it was in '%s'\n", dirName.str()));
|
||
|
m_quitting = TRUE;
|
||
|
}
|
||
|
|
||
|
dirName = TheArchiveFileSystem->getArchiveFilenameForFile("generalsazh.sec");
|
||
|
const char *noPath = dirName.reverseFind('\\');
|
||
|
if (noPath) {
|
||
|
dirName = noPath + 1;
|
||
|
}
|
||
|
|
||
|
if (dirName.compareNoCase("musiczh.big") != 0)
|
||
|
{
|
||
|
DEBUG_LOG(("generalsazh.sec was not found in musiczh.big - it was in '%s'\n", dirName.str()));
|
||
|
m_quitting = TRUE;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
// initialize the MapCache
|
||
|
TheMapCache = MSGNEW("GameEngineSubsystem") MapCache;
|
||
|
TheMapCache->updateCache();
|
||
|
|
||
|
|
||
|
#ifdef DUMP_PERF_STATS///////////////////////////////////////////////////////////////////////////
|
||
|
GetPrecisionTimer(&endTime64);//////////////////////////////////////////////////////////////////
|
||
|
sprintf(Buf,"----------------------------------------------------------------------------After TheMapCache->updateCache = %f seconds \n",((double)(endTime64-startTime64)/(double)(freq64)));
|
||
|
startTime64 = endTime64;//Reset the clock ////////////////////////////////////////////////////////
|
||
|
DEBUG_LOG(("%s", Buf));////////////////////////////////////////////////////////////////////////////
|
||
|
#endif/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
if (TheGlobalData->m_buildMapCache)
|
||
|
{
|
||
|
// just quit, since the map cache has already updated
|
||
|
//populateMapListbox(NULL, true, true);
|
||
|
m_quitting = TRUE;
|
||
|
}
|
||
|
|
||
|
// load the initial shell screen
|
||
|
//TheShell->push( AsciiString("Menus/MainMenu.wnd") );
|
||
|
|
||
|
// This allows us to run a map/reply from the command line
|
||
|
if (TheGlobalData->m_initialFile.isEmpty() == FALSE)
|
||
|
{
|
||
|
AsciiString fname = TheGlobalData->m_initialFile;
|
||
|
fname.toLower();
|
||
|
|
||
|
if (fname.endsWithNoCase(".map"))
|
||
|
{
|
||
|
TheWritableGlobalData->m_shellMapOn = FALSE;
|
||
|
TheWritableGlobalData->m_playIntro = FALSE;
|
||
|
TheWritableGlobalData->m_pendingFile = TheGlobalData->m_initialFile;
|
||
|
|
||
|
// shutdown the top, but do not pop it off the stack
|
||
|
// TheShell->hideShell();
|
||
|
|
||
|
// send a message to the logic for a new game
|
||
|
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
|
||
|
msg->appendIntegerArgument(GAME_SINGLE_PLAYER);
|
||
|
msg->appendIntegerArgument(DIFFICULTY_NORMAL);
|
||
|
msg->appendIntegerArgument(0);
|
||
|
InitRandom(0);
|
||
|
}
|
||
|
else if (fname.endsWithNoCase(".rep"))
|
||
|
{
|
||
|
TheRecorder->playbackFile(fname);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
if (TheMapCache && TheGlobalData->m_shellMapOn)
|
||
|
{
|
||
|
AsciiString lowerName = TheGlobalData->m_shellMapName;
|
||
|
lowerName.toLower();
|
||
|
|
||
|
MapCache::const_iterator it = TheMapCache->find(lowerName);
|
||
|
if (it == TheMapCache->end())
|
||
|
{
|
||
|
TheWritableGlobalData->m_shellMapOn = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(!TheGlobalData->m_playIntro)
|
||
|
TheWritableGlobalData->m_afterIntro = TRUE;
|
||
|
|
||
|
//initDisabledMasks();
|
||
|
|
||
|
}
|
||
|
catch (ErrorCode ec)
|
||
|
{
|
||
|
if (ec == ERROR_INVALID_D3D)
|
||
|
{
|
||
|
RELEASE_CRASHLOCALIZED("ERROR:D3DFailurePrompt", "ERROR:D3DFailureMessage");
|
||
|
}
|
||
|
}
|
||
|
catch (INIException e)
|
||
|
{
|
||
|
if (e.mFailureMessage)
|
||
|
RELEASE_CRASH((e.mFailureMessage));
|
||
|
else
|
||
|
RELEASE_CRASH(("Uncaught Exception during initialization."));
|
||
|
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
RELEASE_CRASH(("Uncaught Exception during initialization."));
|
||
|
}
|
||
|
|
||
|
if(!TheGlobalData->m_playIntro)
|
||
|
TheWritableGlobalData->m_afterIntro = TRUE;
|
||
|
|
||
|
initKindOfMasks();
|
||
|
initDisabledMasks();
|
||
|
initDamageTypeFlags();
|
||
|
|
||
|
TheSubsystemList->resetAll();
|
||
|
HideControlBar();
|
||
|
} // end init
|
||
|
|
||
|
/** -----------------------------------------------------------------------------------------------
|
||
|
* Reset all necessary parts of the game engine to be ready to accept new game data
|
||
|
*/
|
||
|
void GameEngine::reset( void )
|
||
|
{
|
||
|
|
||
|
WindowLayout *background = TheWindowManager->winCreateLayout("Menus/BlankWindow.wnd");
|
||
|
DEBUG_ASSERTCRASH(background,("We Couldn't Load Menus/BlankWindow.wnd"));
|
||
|
background->hide(FALSE);
|
||
|
background->bringForward();
|
||
|
background->getFirstWindow()->winClearStatus(WIN_STATUS_IMAGE);
|
||
|
Bool deleteNetwork = false;
|
||
|
if (TheGameLogic->isInMultiplayerGame())
|
||
|
deleteNetwork = true;
|
||
|
|
||
|
TheSubsystemList->resetAll();
|
||
|
|
||
|
if (deleteNetwork)
|
||
|
{
|
||
|
DEBUG_ASSERTCRASH(TheNetwork, ("Deleting NULL TheNetwork!"));
|
||
|
if (TheNetwork)
|
||
|
delete TheNetwork;
|
||
|
TheNetwork = NULL;
|
||
|
}
|
||
|
if(background)
|
||
|
{
|
||
|
background->destroyWindows();
|
||
|
background->deleteInstance();
|
||
|
background = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// -----------------------------------------------------------------------------------------------
|
||
|
DECLARE_PERF_TIMER(GameEngine_update)
|
||
|
|
||
|
/** -----------------------------------------------------------------------------------------------
|
||
|
* Update the game engine by updating the GameClient and GameLogic singletons.
|
||
|
* @todo Allow the client to run as fast as possible, but limit the execution
|
||
|
* of TheNetwork and TheGameLogic to a fixed framerate.
|
||
|
*/
|
||
|
void GameEngine::update( void )
|
||
|
{
|
||
|
USE_PERF_TIMER(GameEngine_update)
|
||
|
{
|
||
|
|
||
|
{
|
||
|
|
||
|
// VERIFY CRC needs to be in this code block. Please to not pull TheGameLogic->update() inside this block.
|
||
|
VERIFY_CRC
|
||
|
|
||
|
TheRadar->UPDATE();
|
||
|
|
||
|
/// @todo Move audio init, update, etc, into GameClient update
|
||
|
|
||
|
TheAudio->UPDATE();
|
||
|
TheGameClient->UPDATE();
|
||
|
TheMessageStream->propagateMessages();
|
||
|
|
||
|
if (TheNetwork != NULL)
|
||
|
{
|
||
|
TheNetwork->UPDATE();
|
||
|
}
|
||
|
|
||
|
TheCDManager->UPDATE();
|
||
|
}
|
||
|
|
||
|
|
||
|
if ((TheNetwork == NULL && !TheGameLogic->isGamePaused()) || (TheNetwork && TheNetwork->isFrameDataReady()))
|
||
|
{
|
||
|
TheGameLogic->UPDATE();
|
||
|
}
|
||
|
|
||
|
} // end perfGather
|
||
|
|
||
|
}
|
||
|
|
||
|
// Horrible reference, but we really, really need to know if we are windowed.
|
||
|
extern bool DX8Wrapper_IsWindowed;
|
||
|
extern HWND ApplicationHWnd;
|
||
|
|
||
|
/** -----------------------------------------------------------------------------------------------
|
||
|
* The "main loop" of the game engine. It will not return until the game exits.
|
||
|
*/
|
||
|
void GameEngine::execute( void )
|
||
|
{
|
||
|
|
||
|
DWORD prevTime = timeGetTime();
|
||
|
#if defined(_DEBUG) || defined(_INTERNAL)
|
||
|
DWORD startTime = timeGetTime() / 1000;
|
||
|
#endif
|
||
|
|
||
|
// pretty basic for now
|
||
|
while( !m_quitting )
|
||
|
{
|
||
|
|
||
|
//if (TheGlobalData->m_vTune)
|
||
|
{
|
||
|
#ifdef PERF_TIMERS
|
||
|
PerfGather::resetAll();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
{
|
||
|
|
||
|
#if defined(_DEBUG) || defined(_INTERNAL)
|
||
|
{
|
||
|
// enter only if in benchmark mode
|
||
|
if (TheGlobalData->m_benchmarkTimer > 0)
|
||
|
{
|
||
|
DWORD currentTime = timeGetTime() / 1000;
|
||
|
if (TheGlobalData->m_benchmarkTimer < currentTime - startTime)
|
||
|
{
|
||
|
if (TheGameLogic->isInGame())
|
||
|
{
|
||
|
if (TheRecorder->getMode() == RECORDERMODETYPE_RECORD)
|
||
|
{
|
||
|
TheRecorder->stopRecording();
|
||
|
}
|
||
|
TheGameLogic->clearGameData();
|
||
|
}
|
||
|
TheGameEngine->setQuitting(TRUE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
// compute a frame
|
||
|
update();
|
||
|
}
|
||
|
catch (INIException e)
|
||
|
{
|
||
|
// Release CRASH doesn't return, so don't worry about executing additional code.
|
||
|
if (e.mFailureMessage)
|
||
|
RELEASE_CRASH((e.mFailureMessage));
|
||
|
else
|
||
|
RELEASE_CRASH(("Uncaught Exception in GameEngine::update"));
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
// try to save info off
|
||
|
try
|
||
|
{
|
||
|
if (TheRecorder && TheRecorder->getMode() == RECORDERMODETYPE_RECORD && TheRecorder->isMultiplayer())
|
||
|
TheRecorder->cleanUpReplayFile();
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
}
|
||
|
RELEASE_CRASH(("Uncaught Exception in GameEngine::update"));
|
||
|
} // catch
|
||
|
} // perf
|
||
|
|
||
|
{
|
||
|
|
||
|
if (TheTacticalView->getTimeMultiplier()<=1 && !TheScriptEngine->isTimeFast())
|
||
|
{
|
||
|
|
||
|
// I'm disabling this in internal because many people need alt-tab capability. If you happen to be
|
||
|
// doing performance tuning, please just change this on your local system. -MDC
|
||
|
#if defined(_DEBUG) || defined(_INTERNAL)
|
||
|
::Sleep(1); // give everyone else a tiny time slice.
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)
|
||
|
if ( ! TheGlobalData->m_TiVOFastMode )
|
||
|
#else //always allow this cheatkey if we're in a replaygame.
|
||
|
if ( ! (TheGlobalData->m_TiVOFastMode && TheGameLogic->isInReplayGame()))
|
||
|
#endif
|
||
|
{
|
||
|
// limit the framerate
|
||
|
DWORD now = timeGetTime();
|
||
|
DWORD limit = (1000.0f/m_maxFPS)-1;
|
||
|
while (TheGlobalData->m_useFpsLimit && (now - prevTime) < limit)
|
||
|
{
|
||
|
::Sleep(0);
|
||
|
now = timeGetTime();
|
||
|
}
|
||
|
//Int slept = now - prevTime;
|
||
|
//DEBUG_LOG(("delayed %d\n",slept));
|
||
|
|
||
|
prevTime = now;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // perfgather for execute_loop
|
||
|
|
||
|
#ifdef PERF_TIMERS
|
||
|
if (!m_quitting && TheGameLogic->isInGame() && !TheGameLogic->isInShellGame() && !TheGameLogic->isGamePaused())
|
||
|
{
|
||
|
PerfGather::dumpAll(TheGameLogic->getFrame());
|
||
|
PerfGather::displayGraph(TheGameLogic->getFrame());
|
||
|
PerfGather::resetAll();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/** -----------------------------------------------------------------------------------------------
|
||
|
* Factory for the message stream
|
||
|
*/
|
||
|
MessageStream *GameEngine::createMessageStream( void )
|
||
|
{
|
||
|
// if you change this update the tools that use the engine systems
|
||
|
// like GUIEdit, it creates a message stream to run in "test" mode
|
||
|
return MSGNEW("GameEngineSubsystem") MessageStream;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
FileSystem *GameEngine::createFileSystem( void )
|
||
|
{
|
||
|
return MSGNEW("GameEngineSubsystem") FileSystem;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
Bool GameEngine::isMultiplayerSession( void )
|
||
|
{
|
||
|
return TheRecorder->isMultiplayer();
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
#define CONVERT_EXEC1 "..\\Build\\nvdxt -list buildDDS.txt -dxt5 -full -outdir Art\\Textures > buildDDS.out"
|
||
|
|
||
|
void updateTGAtoDDS()
|
||
|
{
|
||
|
// Here's the scoop. We're going to traverse through all of the files in the Art\Textures folder
|
||
|
// and determine if there are any .tga files that are newer than associated .dds files. If there
|
||
|
// are, then we will re-run the compression tool on them.
|
||
|
|
||
|
File *fp = TheLocalFileSystem->openFile("buildDDS.txt", File::WRITE | File::CREATE | File::TRUNCATE | File::TEXT);
|
||
|
if (!fp) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
FilenameList files;
|
||
|
TheLocalFileSystem->getFileListInDirectory("Art\\Textures\\", "", "*.tga", files, TRUE);
|
||
|
FilenameList::iterator it;
|
||
|
for (it = files.begin(); it != files.end(); ++it) {
|
||
|
AsciiString filenameTGA = *it;
|
||
|
AsciiString filenameDDS = *it;
|
||
|
FileInfo infoTGA;
|
||
|
TheLocalFileSystem->getFileInfo(filenameTGA, &infoTGA);
|
||
|
|
||
|
// skip the water textures, since they need to be NOT compressed
|
||
|
filenameTGA.toLower();
|
||
|
if (strstr(filenameTGA.str(), "caust"))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
// and the recolored stuff.
|
||
|
if (strstr(filenameTGA.str(), "zhca"))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// replace tga with dds
|
||
|
filenameDDS.removeLastChar(); // a
|
||
|
filenameDDS.removeLastChar(); // g
|
||
|
filenameDDS.removeLastChar(); // t
|
||
|
filenameDDS.concat("dds");
|
||
|
|
||
|
Bool needsToBeUpdated = FALSE;
|
||
|
FileInfo infoDDS;
|
||
|
if (TheFileSystem->doesFileExist(filenameDDS.str())) {
|
||
|
TheFileSystem->getFileInfo(filenameDDS, &infoDDS);
|
||
|
if (infoTGA.timestampHigh > infoDDS.timestampHigh ||
|
||
|
(infoTGA.timestampHigh == infoDDS.timestampHigh &&
|
||
|
infoTGA.timestampLow > infoDDS.timestampLow)) {
|
||
|
needsToBeUpdated = TRUE;
|
||
|
}
|
||
|
} else {
|
||
|
needsToBeUpdated = TRUE;
|
||
|
}
|
||
|
|
||
|
if (!needsToBeUpdated) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
filenameTGA.concat("\n");
|
||
|
fp->write(filenameTGA.str(), filenameTGA.getLength());
|
||
|
}
|
||
|
|
||
|
fp->close();
|
||
|
|
||
|
system(CONVERT_EXEC1);
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
// System things
|
||
|
|
||
|
// If we're using the Wide character version of MessageBox, then there's no additional
|
||
|
// processing necessary. Please note that this is a sleazy way to get this information,
|
||
|
// but pending a better one, this'll have to do.
|
||
|
extern const Bool TheSystemIsUnicode = (((void*) (::MessageBox)) == ((void*) (::MessageBoxW)));
|