mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
426 lines
10 KiB
C++
426 lines
10 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/nuvie/nuvie.h"
|
|
#include "ultima/nuvie/metaengine.h"
|
|
#include "ultima/nuvie/core/events.h"
|
|
#include "ultima/nuvie/actors/actor.h"
|
|
#include "ultima/nuvie/core/nuvie_defs.h"
|
|
#include "ultima/nuvie/core/debugger.h"
|
|
#include "ultima/nuvie/conf/configuration.h"
|
|
#include "ultima/nuvie/misc/u6_misc.h"
|
|
#include "ultima/nuvie/files/nuvie_io_file.h"
|
|
#include "ultima/nuvie/screen/screen.h"
|
|
#include "ultima/nuvie/script/script.h"
|
|
#include "ultima/nuvie/core/game.h"
|
|
#include "ultima/nuvie/gui/gui.h"
|
|
#include "ultima/nuvie/gui/widgets/console.h"
|
|
#include "ultima/nuvie/sound/sound_manager.h"
|
|
#include "ultima/nuvie/gui/widgets/map_window.h"
|
|
#include "ultima/nuvie/save/save_game.h"
|
|
#include "ultima/nuvie/gui/widgets/msg_scroll.h"
|
|
#include "common/config-manager.h"
|
|
#include "common/translation.h"
|
|
#include "common/compression/unzip.h"
|
|
|
|
namespace Ultima {
|
|
namespace Nuvie {
|
|
|
|
NuvieEngine *g_engine;
|
|
|
|
NuvieEngine::NuvieEngine(OSystem *syst, const Ultima::UltimaGameDescription *gameDesc) :
|
|
Ultima::Shared::UltimaEngine(syst, gameDesc), _config(nullptr), _savegame(nullptr),
|
|
_screen(nullptr), _script(nullptr), _game(nullptr), _soundManager(nullptr),
|
|
_events(nullptr) {
|
|
g_engine = this;
|
|
}
|
|
|
|
NuvieEngine::~NuvieEngine() {
|
|
delete _config;
|
|
delete _events;
|
|
delete _savegame;
|
|
delete _screen;
|
|
delete _script;
|
|
delete _game;
|
|
|
|
g_engine = nullptr;
|
|
}
|
|
|
|
bool NuvieEngine::isDataRequired(Common::Path &folder, int &majorVersion, int &minorVersion) {
|
|
folder = "ultima6";
|
|
majorVersion = 1;
|
|
minorVersion = 1;
|
|
return true;
|
|
}
|
|
|
|
|
|
bool NuvieEngine::initialize() {
|
|
uint8 gameType;
|
|
bool playEnding = false;
|
|
bool showVirtueMsg = false;
|
|
|
|
if (!Ultima::Shared::UltimaEngine::initialize())
|
|
return false;
|
|
|
|
// Get which game to play
|
|
switch (getGameId()) {
|
|
case GAME_ULTIMA6:
|
|
gameType = NUVIE_GAME_U6;
|
|
break;
|
|
case GAME_MARTIAN_DREAMS:
|
|
gameType = NUVIE_GAME_MD;
|
|
break;
|
|
case GAME_SAVAGE_EMPIRE:
|
|
gameType = NUVIE_GAME_SE;
|
|
break;
|
|
default:
|
|
error("Unknown game");
|
|
break;
|
|
}
|
|
|
|
// Find and load config file
|
|
initConfig();
|
|
|
|
// Setup events
|
|
Events *events = new Ultima::Nuvie::Events(this, _config);
|
|
_events = events;
|
|
|
|
// Setup savegame handler
|
|
_savegame = new SaveGame(_config);
|
|
|
|
// Setup debugger
|
|
setDebugger(new Debugger());
|
|
|
|
// Setup screen
|
|
_screen = new Screen(_config);
|
|
|
|
if (_screen->init() == false)
|
|
error("Error initializing screen!");
|
|
|
|
GUI *gui = new GUI(_config, _screen);
|
|
|
|
ConsoleInit(_config, _screen, gui, _screen->get_width(), _screen->get_height());
|
|
ConsoleAddInfo("ScummVM Nuvie");
|
|
ConsoleAddInfo("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t");
|
|
|
|
if (showVirtueMsg) {
|
|
ConsoleShow();
|
|
ConsoleAddInfo("");
|
|
ConsoleAddInfo("");
|
|
ConsoleAddInfo("\"The path to victory is marked with the laws of");
|
|
ConsoleAddInfo(" Virtue, not the commands of DOS.\"");
|
|
ConsoleAddInfo("");
|
|
ConsoleAddInfo(" -- Lord British");
|
|
return false;
|
|
}
|
|
|
|
// Setup various game related config variables.
|
|
assignGameConfigValues(gameType);
|
|
|
|
// Check for a valid path to the selected game.
|
|
if (checkGameDir(gameType) == false)
|
|
return false;
|
|
|
|
if (checkDataDir() == false)
|
|
return false;
|
|
|
|
_soundManager = new SoundManager(_mixer);
|
|
_soundManager->nuvieStartup(_config);
|
|
|
|
_game = new Game(_config, events, _screen, gui, gameType, _soundManager);
|
|
|
|
_script = new Script(_config, gui, _soundManager, gameType);
|
|
if (_script->init() == false)
|
|
return false;
|
|
|
|
if (playEnding) {
|
|
_script->play_cutscene("/ending.lua");
|
|
return false;
|
|
}
|
|
|
|
if (playIntro() == false) {
|
|
ConsoleDelete();
|
|
return false;
|
|
}
|
|
|
|
if (_game->loadGame(_script) == false) {
|
|
delete _game;
|
|
_game = nullptr;
|
|
return false;
|
|
}
|
|
|
|
ConsoleDelete();
|
|
|
|
return true;
|
|
}
|
|
|
|
Common::Error NuvieEngine::run() {
|
|
if (initialize()) {
|
|
if (_game)
|
|
_game->play();
|
|
}
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
void NuvieEngine::initConfig() {
|
|
_config = new Configuration();
|
|
_config->load(_gameDescription->gameId, isEnhanced());
|
|
}
|
|
|
|
void NuvieEngine::assignGameConfigValues(uint8 gameType) {
|
|
Std::string game_name, game_id;
|
|
|
|
_config->set("config/GameType", gameType);
|
|
|
|
switch (gameType) {
|
|
case NUVIE_GAME_U6 :
|
|
game_name.assign("ultima6");
|
|
game_id.assign("u6");
|
|
break;
|
|
case NUVIE_GAME_MD :
|
|
game_name.assign("martian");
|
|
game_id.assign("md");
|
|
break;
|
|
case NUVIE_GAME_SE :
|
|
game_name.assign("savage");
|
|
game_id.assign("se");
|
|
break;
|
|
}
|
|
|
|
_config->set("config/GameName", game_name);
|
|
_config->set("config/GameID", game_id);
|
|
|
|
return;
|
|
}
|
|
|
|
bool NuvieEngine::checkGameDir(uint8 gameType) {
|
|
Common::Path path;
|
|
|
|
config_get_path(_config, "", path);
|
|
ConsoleAddInfo("gamedir: \"%s\"", path.toString().c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool NuvieEngine::checkDataDir() {
|
|
Std::string path;
|
|
_config->value("config/datadir", path, "");
|
|
ConsoleAddInfo("datadir: \"%s\"", path.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
void NuvieEngine::syncSoundSettings() {
|
|
Ultima::Shared::UltimaEngine::syncSoundSettings();
|
|
if (!_soundManager)
|
|
return;
|
|
|
|
_soundManager->syncSoundSettings();
|
|
}
|
|
|
|
bool NuvieEngine::canLoadGameStateCurrently(bool isAutosave) {
|
|
if (_game == nullptr || !_game->isLoaded())
|
|
return false;
|
|
|
|
// Note that to mimic what Nuvie originally did, any attempt to try and open
|
|
// the save dialog will result in active gumps being closed
|
|
Events *events = static_cast<Events *>(_events);
|
|
MapWindow *mapWindow = _game->get_map_window();
|
|
|
|
if (isAutosave) {
|
|
return events->get_mode() == MOVE_MODE;
|
|
|
|
} else {
|
|
events->close_gumps();
|
|
|
|
switch (events->get_mode()) {
|
|
case EQUIP_MODE:
|
|
events->cancelAction();
|
|
return false;
|
|
case MOVE_MODE:
|
|
mapWindow->set_looking(false);
|
|
mapWindow->set_walking(false);
|
|
return true;
|
|
default:
|
|
// Saving/loading only available in standard move mode in-game
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool NuvieEngine::canSaveGameStateCurrently(bool isAutosave) {
|
|
if (!canLoadGameStateCurrently(isAutosave))
|
|
return false;
|
|
|
|
// Further checks against saving
|
|
Events *events = static_cast<Events *>(_events);
|
|
MsgScroll *scroll = _game->get_scroll();
|
|
|
|
if (_game->is_armageddon()) {
|
|
if (!isAutosave)
|
|
scroll->message("Can't save. You killed everyone!\n\n");
|
|
return false;
|
|
} else if (events->using_control_cheat()) {
|
|
if (!isAutosave)
|
|
scroll->message(" Can't save while using control cheat\n\n");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Common::Error NuvieEngine::loadGameState(int slot) {
|
|
Common::String filename = getSaveStateName(slot);
|
|
|
|
if (slot == ORIGINAL_SAVE_SLOT) {
|
|
// For Nuvie, unless a savegame is already present for the slot,
|
|
// loading it loads in the original game savegame
|
|
Common::InSaveFile *saveFile = _saveFileMan->openForLoading(filename);
|
|
bool isPresent = saveFile != nullptr;
|
|
delete saveFile;
|
|
|
|
if (!isPresent) {
|
|
_savegame->load_original();
|
|
return Common::kNoError;
|
|
}
|
|
}
|
|
|
|
return _savegame->load(filename) ? Common::kNoError : Common::kReadingFailed;
|
|
}
|
|
|
|
Common::Error NuvieEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
|
|
Common::String filename = getSaveStateName(slot);
|
|
if (_savegame->save(filename, desc, isAutosave)) {
|
|
if (!isAutosave) {
|
|
// Store which savegame was most recently saved
|
|
ConfMan.setInt("latest_save", slot);
|
|
ConfMan.flushToDisk();
|
|
|
|
// Display that the game was saved
|
|
MsgScroll *scroll = Game::get_game()->get_scroll();
|
|
scroll->display_string("\nGame Saved\n\n");
|
|
scroll->display_prompt();
|
|
}
|
|
|
|
return Common::kNoError;
|
|
} else {
|
|
return Common::kReadingFailed;
|
|
}
|
|
}
|
|
|
|
bool NuvieEngine::journeyOnwards() {
|
|
// If savegame selected from ScummVM launcher, load it now
|
|
if (ConfMan.hasKey("save_slot")) {
|
|
int saveSlot = ConfMan.getInt("save_slot");
|
|
return loadGameState(saveSlot).getCode() == Common::kNoError;
|
|
}
|
|
|
|
// Check for new game needed
|
|
bool newsave = false;
|
|
_config->value("config/newgame", newsave, false);
|
|
|
|
if (newsave) {
|
|
return _savegame->load_new();
|
|
}
|
|
|
|
// Load the savegame from the last slot which was used for saving
|
|
if (ConfMan.hasKey("latest_save")) {
|
|
int saveSlot = ConfMan.getInt("latest_save");
|
|
return loadGameState(saveSlot).getCode() == Common::kNoError;
|
|
}
|
|
|
|
// Otherwise start a new game
|
|
return _savegame->load_new();
|
|
}
|
|
|
|
bool NuvieEngine::loadLatestSave() {
|
|
if (ConfMan.hasKey("latest_save")) {
|
|
int saveSlot = ConfMan.getInt("latest_save");
|
|
return loadGameState(saveSlot).getCode() == Common::kNoError;
|
|
}
|
|
|
|
return _savegame->load_new();
|
|
}
|
|
|
|
bool NuvieEngine::quickSave(int saveSlot, bool isLoad) {
|
|
if (saveSlot < 0 || saveSlot > 99)
|
|
return false;
|
|
|
|
Std::string text;
|
|
MsgScroll *scroll = _game->get_scroll();
|
|
|
|
if (isLoad) {
|
|
if (!canLoadGameStateCurrently(false))
|
|
return false;
|
|
|
|
text = Common::convertFromU32String(_("loading quick save %d"));
|
|
} else {
|
|
if (!canSaveGameStateCurrently(false))
|
|
return false;
|
|
|
|
text = Common::convertFromU32String(_("saving quick save %d"));
|
|
}
|
|
|
|
text = Std::string::format(text.c_str(), saveSlot);
|
|
scroll->display_string(text);
|
|
|
|
if (isLoad) {
|
|
if (loadGameState(saveSlot).getCode() == Common::kNoError) {
|
|
return true;
|
|
} else {
|
|
scroll->message("\nfailed!\n\n");
|
|
return false;
|
|
}
|
|
} else {
|
|
Common::String saveDesc = Common::String::format("Quicksave %03d", saveSlot);
|
|
return saveGameState(saveSlot, saveDesc, false).getCode() == Common::kNoError;
|
|
}
|
|
}
|
|
|
|
bool NuvieEngine::playIntro() {
|
|
if (ConfMan.hasKey("save_slot") && ConfMan.getInt("save_slot") >= 0)
|
|
// Loading a savegame from the launcher, so skip intro
|
|
return true;
|
|
|
|
bool skip_intro;
|
|
string key = config_get_game_key(_config);
|
|
key.append("/skip_intro");
|
|
_config->value(key, skip_intro, false);
|
|
|
|
if (skip_intro)
|
|
return true;
|
|
|
|
|
|
if (_script->play_cutscene("/intro.lua")) {
|
|
bool should_quit = false;
|
|
_config->value("config/quit", should_quit, false);
|
|
if (!should_quit) {
|
|
ConsoleHide();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
} // End of namespace Nuvie
|
|
} // End of namespace Ultima
|