Files
2026-02-02 04:50:13 +01:00

268 lines
7.6 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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/>.
*
*/
#include "ultima/ultima4/ultima4.h"
#include "ultima/ultima4/controllers/intro_controller.h"
#include "ultima/ultima4/conversation/conversation.h"
#include "ultima/ultima4/conversation/dialogueloader.h"
#include "ultima/ultima4/core/config.h"
#include "ultima/ultima4/core/debugger.h"
#include "ultima/ultima4/core/settings.h"
#include "ultima/ultima4/core/utils.h"
#include "ultima/ultima4/events/event_handler.h"
#include "ultima/ultima4/filesys/savegame.h"
#include "ultima/ultima4/game/armor.h"
#include "ultima/ultima4/game/codex.h"
#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/game/death.h"
#include "ultima/ultima4/game/game.h"
#include "ultima/ultima4/game/item.h"
#include "ultima/ultima4/game/moongate.h"
#include "ultima/ultima4/game/person.h"
#include "ultima/ultima4/game/weapon.h"
#include "ultima/ultima4/gfx/screen.h"
#include "ultima/ultima4/gfx/imagemgr.h"
#include "ultima/ultima4/map/maploader.h"
#include "ultima/ultima4/map/shrine.h"
#include "ultima/ultima4/map/tilemap.h"
#include "ultima/ultima4/map/tileset.h"
#include "ultima/ultima4/sound/music.h"
#include "ultima/ultima4/sound/sound.h"
#include "ultima/shared/engine/data_archive.h"
#include "common/debug.h"
#include "common/system.h"
namespace Ultima {
namespace Ultima4 {
Ultima4Engine *g_ultima;
Ultima4Engine::Ultima4Engine(OSystem *syst, const Ultima::UltimaGameDescription *gameDesc) :
Engine(syst), _gameDescription(gameDesc), _randomSource("Ultima4"), _saveSlotToLoad(-1), _armors(nullptr),
_codex(nullptr), _config(nullptr), _context(nullptr), _death(nullptr),
_dialogueLoaders(nullptr), _game(nullptr), _items(nullptr), _music(nullptr),
_mapLoaders(nullptr), _moongates(nullptr),
_responseParts(nullptr), _saveGame(nullptr), _screen(nullptr), _shrines(nullptr),
_soundManager(nullptr), _spells(nullptr), _tileMaps(nullptr), _tileRules(nullptr),
_tileSets(nullptr), _weapons(nullptr) {
g_ultima = this;
g_armors = nullptr;
g_codex = nullptr;
g_context = nullptr;
g_death = nullptr;
g_game = nullptr;
g_items = nullptr;
g_mapLoaders = nullptr;
g_moongates = nullptr;
g_music = nullptr;
g_responseParts = nullptr;
g_screen = nullptr;
g_shrines = nullptr;
g_sound = nullptr;
g_spells = nullptr;
g_tileMaps = nullptr;
g_tileRules = nullptr;
g_tileSets = nullptr;
g_weapons = nullptr;
}
Ultima4Engine::~Ultima4Engine() {
delete _armors;
delete _codex;
delete _config;
delete _context;
delete _death;
delete _dialogueLoaders;
delete _game;
delete _items;
delete _mapLoaders;
delete _moongates;
delete _music;
delete _responseParts;
delete _saveGame;
delete _screen;
delete _shrines;
delete _soundManager;
delete _spells;
delete _tileMaps;
delete _tileRules;
delete _tileSets;
delete _weapons;
ImageMgr::destroy();
//delete g_music;
}
bool Ultima4Engine::initialize() {
Common::Path folder;
int reqMajorVersion, reqMinorVersion;
// Call syncSoundSettings to get default volumes set
syncSoundSettings();
// Check if the game uses data from te ultima.dat archive
if (!isDataRequired(folder, reqMajorVersion, reqMinorVersion))
return true;
// Try and set up the data archive
Common::U32String errorMsg;
if (!Shared::UltimaDataArchive::load(folder, reqMajorVersion, reqMinorVersion, errorMsg)) {
GUIErrorMessage(errorMsg);
return false;
}
// Initialize the sub-systems
_config = new Config();
_armors = new Armors();
_codex = new Codex();
_context = new Context();
_death = new Death();
_dialogueLoaders = new DialogueLoaders();
_items = new Items();
_mapLoaders = new MapLoaders();
_moongates = new Moongates();
_music = new Music(_mixer);
_soundManager = new SoundManager(_mixer);
_responseParts = new ResponseParts();
_screen = new Screen();
_screen->init();
_shrines = new Shrines();
_spells = new Spells();
_tileRules = new TileRules();
_tileSets = new TileSets();
_tileMaps = new TileMaps();
_game = new GameController();
_saveGame = new SaveGame();
_weapons = new Weapons();
setDebugger(new Debugger());
creatureMgr->getInstance();
_saveSlotToLoad = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
return true;
}
void Ultima4Engine::startup() {
bool skipInfo = _saveSlotToLoad != -1;
if (!skipInfo) {
// do the intro
g_intro = new IntroController();
g_intro->init();
g_intro->preloadMap();
eventHandler->pushController(g_intro);
eventHandler->run();
eventHandler->popController();
g_intro->deleteIntro();
}
}
Common::Error Ultima4Engine::run() {
if (initialize()) {
startup();
if (!shouldQuit()) {
g_game->init();
if (_saveSlotToLoad != -1) {
if (loadGameState(_saveSlotToLoad).getCode() != Common::kNoError)
error("Error loading save");
} else {
_saveGame->newGame();
}
eventHandler->setControllerDone(false);
eventHandler->pushController(g_game);
eventHandler->run();
eventHandler->popController();
}
}
return Common::kNoError;
}
bool Ultima4Engine::isDataRequired(Common::Path &folder, int &majorVersion, int &minorVersion) {
folder = "ultima4";
majorVersion = 1;
minorVersion = 0;
return true;
}
void Ultima4Engine::setToJourneyOnwards() {
_saveSlotToLoad = ConfMan.hasKey("last_save") ? ConfMan.getInt("last_save") : -1;
assert(_saveSlotToLoad);
}
bool Ultima4Engine::canLoadGameStateCurrently(Common::U32String *msg) {
return g_game != nullptr && g_context != nullptr && eventHandler->getController() == g_game;
}
bool Ultima4Engine::canSaveGameStateCurrently(Common::U32String *msg) {
return g_game != nullptr && g_context != nullptr && eventHandler->getController() == g_game
&& (g_context->_location->_context & CTX_CAN_SAVE_GAME);
}
Common::Error Ultima4Engine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
Common::Error result = Engine::saveGameState(slot, desc, isAutosave);
if (!isAutosave && result.getCode() == Common::kNoError) {
ConfMan.setInt("last_save", slot);
ConfMan.flushToDisk();
}
return result;
}
bool Ultima4Engine::hasFeature(EngineFeature f) const {
return
(f == kSupportsReturnToLauncher) ||
(f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsChangingOptionsDuringRuntime) ||
(f == kSupportsSavingDuringRuntime);
}
bool Ultima4Engine::isEnhanced() const {
return _gameDescription->features & GF_VGA_ENHANCED;
}
Common::Error Ultima4Engine::loadGameStream(Common::SeekableReadStream *stream) {
g_ultima->_saveGame->load(stream);
g_screen->screenUpdate(&g_game->_mapArea, true, false);
return Common::kNoError;
}
Common::Error Ultima4Engine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
g_ultima->_saveGame->save(stream);
return Common::kNoError;
}
void Ultima4Engine::quitGame() {
Engine::quitGame();
// Do an event poll to all the quit message to be processed
Common::Event e;
(void)g_system->getEventManager()->pollEvent(e);
}
} // End of namespace Ultima4
} // End of namespace Ultima