From cfb46da90cb045e029153848652bbd166a5c95b6 Mon Sep 17 00:00:00 2001 From: Peter Kohaut Date: Sun, 25 Nov 2018 21:47:00 +0100 Subject: BLADERUNNER: Add in-game loading screen It is also possible to start new game from it. --- engines/bladerunner/bladerunner.cpp | 71 +++++++----- engines/bladerunner/bladerunner.h | 7 +- engines/bladerunner/debugger.cpp | 6 +- engines/bladerunner/detection.cpp | 42 +------ engines/bladerunner/module.mk | 1 + engines/bladerunner/savefile.cpp | 49 ++++++++- engines/bladerunner/savefile.h | 9 +- engines/bladerunner/script/ai/steele.cpp | 2 +- engines/bladerunner/ui/kia.cpp | 35 +++--- engines/bladerunner/ui/kia.h | 31 +++--- engines/bladerunner/ui/kia_section_load.cpp | 163 ++++++++++++++++++++++++++++ engines/bladerunner/ui/kia_section_load.h | 38 ++++++- engines/bladerunner/ui/ui_container.cpp | 8 +- 13 files changed, 346 insertions(+), 116 deletions(-) create mode 100644 engines/bladerunner/ui/kia_section_load.cpp (limited to 'engines/bladerunner') diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp index 41299fc7d1..3d9ba34cb1 100644 --- a/engines/bladerunner/bladerunner.cpp +++ b/engines/bladerunner/bladerunner.cpp @@ -230,7 +230,7 @@ Common::Error BladeRunnerEngine::loadGameState(int slot) { } BladeRunner::SaveFileHeader header; - if (!BladeRunner::SaveFile::readHeader(*saveFile, header)) { + if (!BladeRunner::SaveFileManager::readHeader(*saveFile, header)) { error("Invalid savegame"); } @@ -261,18 +261,18 @@ Common::Error BladeRunnerEngine::saveGameState(int slot, const Common::String &d return Common::kReadingFailed; } - byte *thumbnail = new byte[SaveFile::kThumbnailSize]; - generateThumbnail(thumbnail); + Graphics::Surface thumbnail = generateThumbnail(); BladeRunner::SaveFileHeader header; header._name = desc; - BladeRunner::SaveFile::writeHeader(*saveFile, header); + + BladeRunner::SaveFileManager::writeHeader(*saveFile, header); saveGame(*saveFile, thumbnail); saveFile->finalize(); - delete[] thumbnail; + thumbnail.free(); delete saveFile; @@ -285,19 +285,29 @@ Common::Error BladeRunnerEngine::run() { _system->showMouse(true); - if (!startup()) { + bool hasSavegames = !SaveFileManager::list(_targetName).empty(); + + if (!startup(hasSavegames)) { shutdown(); return Common::Error(Common::kUnknownError, "Failed to initialize resources"); } + + #if BLADERUNNER_DEBUG_GAME { #else if (warnUserAboutUnsupportedGame()) { #endif - init2(); + if (hasSavegames) { + _kia->_forceOpen = true; + _kia->open(kKIASectionLoad); + } + // TODO: why is game starting new game here when everything is done in startup? + // else { + // newGame(1); + // } - /* TODO: Check for save games and enter KIA */ gameLoop(); _mouse->disable(); @@ -361,7 +371,6 @@ bool BladeRunnerEngine::startup(bool hasSavegames) { return false; } - _combat = new Combat(this); // TODO: Create datetime - not used @@ -377,13 +386,11 @@ bool BladeRunnerEngine::startup(bool hasSavegames) { _waypoints = new Waypoints(this, _gameInfo->getWaypointCount()); - // TODO: Cover waypoints - - // TODO: Flee waypoints + _combat = new Combat(this); _gameVars = new int[_gameInfo->getGlobalVarCount()](); - // TODO: Actor AI DLL init + // TODO: Init Actor AI Update counter // Seed rand @@ -789,10 +796,6 @@ bool BladeRunnerEngine::loadSplash() { return true; } -bool BladeRunnerEngine::init2() { - return true; -} - Common::Point BladeRunnerEngine::getMousePos() const { Common::Point p = _eventMan->getMousePos(); p.x = CLIP(p.x, int16(0), int16(639)); @@ -816,8 +819,7 @@ void BladeRunnerEngine::gameTick() { handleEvents(); if (_gameIsRunning && _windowIsActive) { - // TODO: Only run if not in Kia, script, nor AI - if (!_sceneScript->isInsideScript() && !_aiScripts->isInsideScript()) { + if (!_kia->isOpen() && !_sceneScript->isInsideScript() && !_aiScripts->isInsideScript()) { _settings->openNewScene(); } @@ -1713,7 +1715,7 @@ void BladeRunnerEngine::playerGainsControl() { } } -bool BladeRunnerEngine::saveGame(Common::WriteStream &stream, const void *thumbnail) { +bool BladeRunnerEngine::saveGame(Common::WriteStream &stream, const Graphics::Surface &thumbnail) { if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) { return false; } @@ -1721,7 +1723,7 @@ bool BladeRunnerEngine::saveGame(Common::WriteStream &stream, const void *thumbn Common::MemoryWriteStreamDynamic memoryStream(DisposeAfterUse::YES); SaveFileWriteStream s(memoryStream); - s.write(thumbnail, SaveFile::kThumbnailSize); + s.write(thumbnail.getPixels(), SaveFileManager::kThumbnailSize); s.writeFloat(1.0f); _settings->save(s); _scene->save(s); @@ -1793,7 +1795,7 @@ bool BladeRunnerEngine::loadGame(Common::SeekableReadStream &stream) { _gameIsLoading = true; _settings->setLoadingGame(); - s.skip(SaveFile::kThumbnailSize); // skip the thumbnail + s.skip(SaveFileManager::kThumbnailSize); // skip the thumbnail s.skip(4);// always float 1.0, but never used _settings->load(s); _scene->load(s); @@ -1870,6 +1872,10 @@ void BladeRunnerEngine::newGame(int difficulty) { _settings->setDifficulty(difficulty); } + InitScript initScript(this); + initScript.SCRIPT_Initialize_Game(); + initChapterAndScene(); + _settings->setStartingGame(); } @@ -1882,21 +1888,30 @@ void BladeRunnerEngine::blitToScreen(const Graphics::Surface &src) const { _system->updateScreen(); } -void BladeRunnerEngine::generateThumbnail(void *thumbnail) const { - uint16 *dstPixels = (uint16*)thumbnail; +Graphics::Surface BladeRunnerEngine::generateThumbnail() const { + Graphics::Surface thumbnail; + thumbnail.create(640 / 8, 480 / 8, createRGB555()); + + for (int y = 0; y < thumbnail.h; ++y) { + for (int x = 0; x < thumbnail.w; ++x) { + uint16 *dstPixel = (uint16 *)thumbnail.getBasePtr(x, y); + const uint16 *srcPixel = (const uint16 *)_surfaceFront.getBasePtr(x * 8, y * 8); - for (int y = 0; y < 480; y += 8) { - for (int x = 0; x < 640; x += 8) { - *dstPixels = *(const uint16 *)_surfaceFront.getBasePtr(x, y); - ++dstPixels; + *dstPixel = *srcPixel; } } + + return thumbnail; } GUI::Debugger *BladeRunnerEngine::getDebugger() { return _debugger; } +Common::String BladeRunnerEngine::getTargetName() const { + return _targetName; +} + void blit(const Graphics::Surface &src, Graphics::Surface &dst) { dst.copyRectToSurface(src.getPixels(), src.pitch, 0, 0, src.w, src.h); } diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h index 29015a36c4..a377b89aa9 100644 --- a/engines/bladerunner/bladerunner.h +++ b/engines/bladerunner/bladerunner.h @@ -24,7 +24,6 @@ #define BLADERUNNER_BLADERUNNER_H #include "bladerunner/archive.h" -#include "bladerunner/savefile.h" #include "common/array.h" #include "common/cosinetables.h" @@ -238,7 +237,6 @@ public: void shutdown(); bool loadSplash(); - bool init2(); Common::Point getMousePos() const; bool isMouseButtonDown() const; @@ -276,7 +274,7 @@ public: void playerLosesControl(); void playerGainsControl(); - bool saveGame(Common::WriteStream &stream, const void *thumbnail); + bool saveGame(Common::WriteStream &stream, const Graphics::Surface &thumbnail); bool loadGame(Common::SeekableReadStream &stream); void newGame(int difficulty); void autoSaveGame(); @@ -284,9 +282,10 @@ public: void ISez(const Common::String &str); void blitToScreen(const Graphics::Surface &src) const; - void generateThumbnail(void *thumbnail) const; + Graphics::Surface generateThumbnail() const; GUI::Debugger *getDebugger(); + Common::String getTargetName() const; }; static inline const Graphics::PixelFormat createRGB555() { diff --git a/engines/bladerunner/debugger.cpp b/engines/bladerunner/debugger.cpp index 6f7e5d14a2..f0137c4376 100644 --- a/engines/bladerunner/debugger.cpp +++ b/engines/bladerunner/debugger.cpp @@ -33,6 +33,7 @@ #include "bladerunner/light.h" #include "bladerunner/lights.h" #include "bladerunner/regions.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene.h" #include "bladerunner/scene_objects.h" #include "bladerunner/settings.h" @@ -399,14 +400,13 @@ bool Debugger::cmdSave(int argc, const char **argv) { Common::WriteStream *saveFile = fs.createWriteStream(); - uint16 *thumbnail = new uint16[SaveFile::kThumbnailSize]; - _vm->generateThumbnail(thumbnail); + Graphics::Surface thumbnail = _vm->generateThumbnail(); _vm->saveGame(*saveFile, thumbnail); saveFile->finalize(); - delete[] thumbnail; + thumbnail.free(); delete saveFile; diff --git a/engines/bladerunner/detection.cpp b/engines/bladerunner/detection.cpp index 8cd4288a0d..46285e57bc 100644 --- a/engines/bladerunner/detection.cpp +++ b/engines/bladerunner/detection.cpp @@ -87,27 +87,7 @@ bool BladeRunnerMetaEngine::hasFeature(MetaEngineFeature f) const { } SaveStateList BladeRunnerMetaEngine::listSaves(const char *target) const { - Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); - Common::StringArray files = saveFileMan->listSavefiles(Common::String::format("%s.###", target)); - - SaveStateList saveList; - for (Common::StringArray::const_iterator fileName = files.begin(); fileName != files.end(); ++fileName) { - Common::InSaveFile *saveFile = saveFileMan->openForLoading(*fileName); - if (saveFile == nullptr || saveFile->err()) { - warning("Cannot open save file '%s'", fileName->c_str()); - continue; - } - - BladeRunner::SaveFileHeader header; - BladeRunner::SaveFile::readHeader(*saveFile, header); - - int slotNum = atoi(fileName->c_str() + fileName->size() - 3); - saveList.push_back(SaveStateDescriptor(slotNum, header._name)); - } - - // Sort saves based on slot number. - Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator()); - return saveList; + return BladeRunner::SaveFileManager::list(target); } int BladeRunnerMetaEngine::getMaximumSaveSlot() const { @@ -120,25 +100,7 @@ void BladeRunnerMetaEngine::removeSaveState(const char *target, int slot) const } SaveStateDescriptor BladeRunnerMetaEngine::querySaveMetaInfos(const char *target, int slot) const { - Common::String filename = Common::String::format("%s.%03d", target, slot); - Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(filename); - - if (saveFile == nullptr || saveFile->err()) { - return SaveStateDescriptor(); - } - - BladeRunner::SaveFileHeader header; - if (!BladeRunner::SaveFile::readHeader(*saveFile, header, false)) { - delete saveFile; - return SaveStateDescriptor(); - } - delete saveFile; - - SaveStateDescriptor desc(slot, header._name); - desc.setThumbnail(header._thumbnail); - desc.setSaveDate(header._year, header._month, header._day); - desc.setSaveTime(header._hour, header._minute); - return desc; + return BladeRunner::SaveFileManager::queryMetaInfos(target, slot); } #if PLUGIN_ENABLED_DYNAMIC(BLADERUNNER) diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk index b0bae4f7bd..29b6fd2c3a 100644 --- a/engines/bladerunner/module.mk +++ b/engines/bladerunner/module.mk @@ -257,6 +257,7 @@ MODULE_OBJS = \ ui/kia_section_crimes.o \ ui/kia_section_diagnostic.o \ ui/kia_section_help.o \ + ui/kia_section_load.o \ ui/kia_section_pogo.o \ ui/kia_section_settings.o \ ui/kia_section_suspects.o \ diff --git a/engines/bladerunner/savefile.cpp b/engines/bladerunner/savefile.cpp index 143d947646..fc0073c3ee 100644 --- a/engines/bladerunner/savefile.cpp +++ b/engines/bladerunner/savefile.cpp @@ -33,7 +33,52 @@ namespace BladeRunner { -bool SaveFile::readHeader(Common::SeekableReadStream &in, SaveFileHeader &header, bool skipThumbnail) { +SaveStateList SaveFileManager::list(const Common::String &target) { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray files = saveFileMan->listSavefiles(target + ".###"); + + SaveStateList saveList; + for (Common::StringArray::const_iterator fileName = files.begin(); fileName != files.end(); ++fileName) { + Common::InSaveFile *saveFile = saveFileMan->openForLoading(*fileName); + if (saveFile == nullptr || saveFile->err()) { + continue; + } + + BladeRunner::SaveFileHeader header; + readHeader(*saveFile, header); + + int slotNum = atoi(fileName->c_str() + fileName->size() - 3); + saveList.push_back(SaveStateDescriptor(slotNum, header._name)); + } + + Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator()); + + return saveList; +} + +SaveStateDescriptor SaveFileManager::queryMetaInfos(const Common::String &target, int slot) { + Common::String filename = Common::String::format("%s.%03d", target.c_str(), slot); + Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(filename); + + if (saveFile == nullptr || saveFile->err()) { + return SaveStateDescriptor(); + } + + BladeRunner::SaveFileHeader header; + if (!BladeRunner::SaveFileManager::readHeader(*saveFile, header, false)) { + delete saveFile; + return SaveStateDescriptor(); + } + delete saveFile; + + SaveStateDescriptor desc(slot, header._name); + desc.setThumbnail(header._thumbnail); + desc.setSaveDate(header._year, header._month, header._day); + desc.setSaveTime(header._hour, header._minute); + return desc; +} + +bool SaveFileManager::readHeader(Common::SeekableReadStream &in, SaveFileHeader &header, bool skipThumbnail) { SaveFileReadStream s(in); if (s.readUint32BE() != kTag) { @@ -76,7 +121,7 @@ bool SaveFile::readHeader(Common::SeekableReadStream &in, SaveFileHeader &header return true; } -bool SaveFile::writeHeader(Common::WriteStream &out, SaveFileHeader &header) { +bool SaveFileManager::writeHeader(Common::WriteStream &out, SaveFileHeader &header) { SaveFileWriteStream s(out); s.writeUint32BE(kTag); diff --git a/engines/bladerunner/savefile.h b/engines/bladerunner/savefile.h index bcd1619496..64fb0b4999 100644 --- a/engines/bladerunner/savefile.h +++ b/engines/bladerunner/savefile.h @@ -23,11 +23,14 @@ #ifndef BLADERUNNER_SAVEFILE_H #define BLADERUNNER_SAVEFILE_H +#include "common/array.h" #include "common/memstream.h" #include "common/types.h" #include "graphics/surface.h" +#include "engines/savestate.h" + namespace Common { class OutSaveFile; class String; @@ -40,6 +43,7 @@ class Vector2; class Vector3; class BoundingBox; + struct SaveFileHeader { uint8 _version; Common::String _name; @@ -51,7 +55,7 @@ struct SaveFileHeader { Graphics::Surface *_thumbnail; }; -class SaveFile { +class SaveFileManager { private: static const uint32 kTag = MKTAG('B', 'R', 'S', 'V'); static const uint32 kVersion = 1; @@ -60,6 +64,9 @@ private: public: static const uint32 kThumbnailSize = 9600; // 80x60x16bpp + static SaveStateList list(const Common::String &target); + static SaveStateDescriptor queryMetaInfos(const Common::String &target, int slot); + static bool readHeader(Common::SeekableReadStream &in, SaveFileHeader &header, bool skipThumbnail = true); static bool writeHeader(Common::WriteStream &out, SaveFileHeader &header); }; diff --git a/engines/bladerunner/script/ai/steele.cpp b/engines/bladerunner/script/ai/steele.cpp index ff2afa1ec3..830a9aaa73 100644 --- a/engines/bladerunner/script/ai/steele.cpp +++ b/engines/bladerunner/script/ai/steele.cpp @@ -43,7 +43,7 @@ void AIScriptSteele::Initialize() { Actor_Put_In_Set(kActorSteele, kSetFreeSlotG); Actor_Set_At_Waypoint(kActorSteele, 39, 0); Actor_Set_Goal_Number(kActorSteele, 0); - Actor_Clue_Acquire(kActorSteele, 178, 1, -1); + Actor_Clue_Acquire(kActorSteele, kClueCrimeSceneNotes, 1, -1); } bool AIScriptSteele::Update() { diff --git a/engines/bladerunner/ui/kia.cpp b/engines/bladerunner/ui/kia.cpp index 4b95607541..6bea198b7c 100644 --- a/engines/bladerunner/ui/kia.cpp +++ b/engines/bladerunner/ui/kia.cpp @@ -31,6 +31,7 @@ #include "bladerunner/game_flags.h" #include "bladerunner/game_info.h" #include "bladerunner/mouse.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene.h" #include "bladerunner/shape.h" #include "bladerunner/script/kia_script.h" @@ -66,7 +67,7 @@ KIA::KIA(BladeRunnerEngine *vm) { _log = new KIALog(_vm); _shapes = new KIAShapes(_vm); - _forceOpen = 0; + _forceOpen = false; _currentSectionId = kKIASectionNone; _lastSectionIdKIA = kKIASectionCrimes; _lastSectionIdOptions = kKIASectionSettings; @@ -88,8 +89,6 @@ KIA::KIA(BladeRunnerEngine *vm) { _pogoPos = 0; - _thumbnail = nullptr; - _buttons = new UIImagePicker(_vm, 22); _crimesSection = new KIASectionCrimes(_vm, _vm->_playerActor->_clues); @@ -109,6 +108,7 @@ KIA::KIA(BladeRunnerEngine *vm) { } KIA::~KIA() { + _thumbnail.free(); delete _crimesSection; delete _suspectsSection; delete _cluesSection; @@ -118,7 +118,7 @@ KIA::~KIA() { delete _loadSection; delete _diagnosticSection; delete _pogoSection; - + _playerImage.free(); delete _playerPhotograph; delete _buttons; delete _shapes; @@ -129,6 +129,7 @@ KIA::~KIA() { void KIA::reset() { _lastSectionIdKIA = kKIASectionCrimes; _lastSectionIdOptions = kKIASectionSettings; + _playerImage.free(); _playerVqaFrame = 0; _playerVisualizerState = 0; _playerSliceModelAngle = 0.0f; @@ -226,7 +227,7 @@ void KIA::tick() { if (_playerActorDialogueQueueSize == _playerActorDialogueQueuePosition) { _playerActorDialogueState = 0; } else if (_playerActorDialogueState == 0) { - if (_playerSliceModelId == -1 && _playerPhotographId == -1) { //&& !this->_playerImage + if (_playerSliceModelId == -1 && _playerPhotographId == -1 && _playerImage.getPixels() == nullptr) { _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(495), 70, 0, 0, 50, 0); } _playerActorDialogueState = 1; @@ -251,18 +252,17 @@ void KIA::tick() { int timeDiffDiv48 = (timeNow - _playerVqaTimeLast) / 48; if (timeDiffDiv48 > 0) { _playerVqaTimeLast = timeNow; - if (_playerActorDialogueQueueSize == _playerActorDialogueQueuePosition || _playerSliceModelId != -1 || _playerPhotographId != -1) { // || this->_viewerImage + if (_playerActorDialogueQueueSize == _playerActorDialogueQueuePosition || _playerSliceModelId != -1 || _playerPhotographId != -1 || _playerImage.getPixels() != nullptr) { if (_playerVisualizerState > 0) { _playerVisualizerState = MAX(_playerVisualizerState - timeDiffDiv48, 0); } } else { if (_playerVisualizerState < 2) { _playerVisualizerState = MIN(_playerVisualizerState + timeDiffDiv48, 2); - } } - if ( _playerSliceModelId != -1 || _playerPhotographId != -1 ) { // || _playerImage + if ( _playerSliceModelId != -1 || _playerPhotographId != -1 || _playerImage.getPixels() != nullptr) { if (_playerVqaFrame < 8) { int newVqaFrame = MIN(timeDiffDiv48 + _playerVqaFrame, 8); if (_playerVqaFrame <= 0 && newVqaFrame > 0) { @@ -325,10 +325,10 @@ void KIA::tick() { int width = _playerPhotograph->getWidth(); int height = _playerPhotograph->getHeight(); _playerPhotograph->draw(_vm->_surfaceFront, 590 - width / 2, 80 - height / 2); + } else if (_playerImage.getPixels() != nullptr) { + _vm->_surfaceFront.fillRect(Common::Rect(549, 49, 631, 111), 0x7FFF); + _vm->_surfaceFront.copyRectToSurface(_playerImage.getPixels(), _playerImage.pitch, 550, 50, _playerImage.w, _playerImage.h); } - // else if (_playerImage) { - // ... - // } } if (_playerVisualizerState == 1) { @@ -530,8 +530,7 @@ void KIA::playerReset() { _playerPhotograph = nullptr; } _playerPhotographId = -1; - // delete _playerImage; - // _playerImage = nullptr; + _playerImage.free(); _playerActorDialogueState = 0; } @@ -564,6 +563,10 @@ void KIA::playPhotograph(int photographId) { _playerPhotograph->open("photos.shp", photographId); } +void KIA::playImage(const Graphics::Surface &image) { + _playerImage.copyFrom(image); +} + void KIA::mouseDownCallback(int buttonId, void *callbackData) { KIA *self = (KIA *)callbackData; switch (buttonId) { @@ -635,8 +638,7 @@ void KIA::loopEnded(void *callbackData, int frame, int loopId) { } void KIA::init() { - _thumbnail = new byte[SaveFile::kThumbnailSize]; - _vm->generateThumbnail(_thumbnail); + _thumbnail = _vm->generateThumbnail(); if (!_vm->openArchive("MODE.MIX")) { return; @@ -667,8 +669,7 @@ void KIA::init() { } void KIA::unload() { - delete[] _thumbnail; - _thumbnail = nullptr; + _thumbnail.free(); if (!isOpen()) { return; diff --git a/engines/bladerunner/ui/kia.h b/engines/bladerunner/ui/kia.h index 0612234db1..b5be9a7e08 100644 --- a/engines/bladerunner/ui/kia.h +++ b/engines/bladerunner/ui/kia.h @@ -25,14 +25,12 @@ #include "common/str.h" +#include "graphics/surface.h" + namespace Common { struct KeyState; } -namespace Graphics { -struct Surface; -} - namespace BladeRunner { class BladeRunnerEngine; @@ -78,18 +76,18 @@ class KIA { BladeRunnerEngine *_vm; - int _forceOpen; int _transitionId; - int _playerVqaTimeLast; - VQAPlayer *_playerVqaPlayer; - int _playerVqaFrame; - int _playerVisualizerState; - int _playerPhotographId; - Shape *_playerPhotograph; - int _playerSliceModelId; - float _playerSliceModelAngle; - int _timeLast; + int _playerVqaTimeLast; + VQAPlayer *_playerVqaPlayer; + int _playerVqaFrame; + int _playerVisualizerState; + int _playerPhotographId; + Shape *_playerPhotograph; + int _playerSliceModelId; + float _playerSliceModelAngle; + Graphics::Surface _playerImage; + int _timeLast; ActorDialogueQueueEntry _playerActorDialogueQueue[kPlayerActorDialogueQueueCapacity]; int _playerActorDialogueQueuePosition; @@ -117,9 +115,11 @@ class KIA { int _pogoPos; - byte *_thumbnail; + Graphics::Surface _thumbnail; public: + bool _forceOpen; + KIALog *_log; KIAScript *_script; KIAShapes *_shapes; @@ -147,6 +147,7 @@ public: void playActorDialogue(int actorId, int sentenceId); void playSliceModel(int sliceModelId); void playPhotograph(int photographId); + void playImage(const Graphics::Surface &image); private: static void mouseDownCallback(int buttonId, void *callbackData); diff --git a/engines/bladerunner/ui/kia_section_load.cpp b/engines/bladerunner/ui/kia_section_load.cpp new file mode 100644 index 0000000000..ba746cab3b --- /dev/null +++ b/engines/bladerunner/ui/kia_section_load.cpp @@ -0,0 +1,163 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "bladerunner/ui/kia_section_load.h" + +#include "bladerunner/audio_player.h" +#include "bladerunner/bladerunner.h" +#include "bladerunner/game_info.h" +#include "bladerunner/savefile.h" +#include "bladerunner/text_resource.h" +#include "bladerunner/ui/kia.h" +#include "bladerunner/ui/kia_shapes.h" +#include "bladerunner/ui/ui_container.h" +#include "bladerunner/ui/ui_scroll_box.h" + +#include "common/error.h" +#include "common/system.h" + +#include "engines/savestate.h" + +namespace BladeRunner { + +KIASectionLoad::KIASectionLoad(BladeRunnerEngine *vm) : KIASectionBase(vm) { + _uiContainer = new UIContainer(_vm); + _scrollBox = new UIScrollBox(_vm, scrollBoxCallback, this, 1025, 0, true, Common::Rect(155, 158, 461, 346), Common::Rect(506, 160, 506, 350)); + _uiContainer->add(_scrollBox); +} + +KIASectionLoad::~KIASectionLoad() { + _uiContainer->clear(); + delete _scrollBox; + delete _uiContainer; +} + +void KIASectionLoad::open() { + _scheduledSwitch = false; + _scrollBox->show(); + _scrollBox->clearLines(); + + SaveStateList saveList = SaveFileManager::list(_vm->getTargetName()); + + _saveSlotMax = -1; + + if (!saveList.empty()) { + _scrollBox->addLine(_vm->_textOptions->getText(36), -1, 4); // Load game: + for (Common::Array::iterator save = saveList.begin(); save != saveList.end(); save++) { + _scrollBox->addLine(save->getDescription(), save->getSaveSlot(), 0); + _saveSlotMax = MAX(_saveSlotMax, save->getSaveSlot()); + } + _scrollBox->addLine("", -1, 4); + } + + + _scrollBox->addLine(_vm->_textOptions->getText(37), -1, 4); // New game: + _scrollBox->addLine(_vm->_textOptions->getText(20), _saveSlotMax + 1, 0); // Easy + _scrollBox->addLine(_vm->_textOptions->getText(28), _saveSlotMax + 2, 0); // Medium + _scrollBox->addLine(_vm->_textOptions->getText(29), _saveSlotMax + 3, 0); // Hard + + _hoveredSaveSlot = -1; + _timeLast = _vm->getTotalPlayTime(); + _timeLeft = 800; +} + +void KIASectionLoad::close() { + _scrollBox->hide(); + + _vm->_kia->playerReset(); +} + +void KIASectionLoad::draw(Graphics::Surface &surface){ + _vm->_kia->_shapes->get(69)->draw(surface, 501, 123); + + _uiContainer->draw(surface); + + int selectedSaveSlot = _scrollBox->getSelectedLineData(); + + if (_hoveredSaveSlot != selectedSaveSlot) { + if (selectedSaveSlot >= 0) { + if (_timeLeft == 0) { + SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getTargetName(), selectedSaveSlot); + const Graphics::Surface *thumbnail = desc.getThumbnail(); + if (thumbnail != nullptr) { + _vm->_kia->playImage(*thumbnail); + } + } + } else { + _vm->_kia->playerReset(); + _timeLeft = 800; + } + _hoveredSaveSlot = selectedSaveSlot; + } + + uint32 now = _vm->getTotalPlayTime(); + if (selectedSaveSlot >= 0) { + if (_timeLeft) { + uint32 timeDiff = now - _timeLast; + if (timeDiff >= _timeLeft) { + SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getTargetName(), selectedSaveSlot); + const Graphics::Surface *thumbnail = desc.getThumbnail(); + if (thumbnail != nullptr) { + _vm->_kia->playImage(*thumbnail); + } + } else { + _timeLeft -= timeDiff; + } + } + } + + _timeLast = now; +} + +void KIASectionLoad::handleMouseMove(int mouseX, int mouseY) { + _uiContainer->handleMouseMove(mouseX, mouseY); +} + +void KIASectionLoad::handleMouseDown(bool mainButton) { + _uiContainer->handleMouseDown(!mainButton); +} + +void KIASectionLoad::handleMouseUp(bool mainButton) { + _uiContainer->handleMouseUp(!mainButton); +} + +void KIASectionLoad::scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton) { + KIASectionLoad *self = (KIASectionLoad *)callbackData; + + if (mouseButton == 0 && source == self->_scrollBox && lineData >= 0) { + if (lineData == self->_saveSlotMax + 1) { + self->_vm->newGame(0); + } else if (lineData == self->_saveSlotMax + 2) { + self->_vm->newGame(1); + } else if (lineData == self->_saveSlotMax + 3) { + self->_vm->newGame(2); + } else { + self->_vm->loadGameState(lineData); + } + + self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(513), 90, 0, 0, 50, 0); + self->_vm->_kia->resume(); + self->_scheduledSwitch = true; + } +} + +} // End of namespace BladeRunner diff --git a/engines/bladerunner/ui/kia_section_load.h b/engines/bladerunner/ui/kia_section_load.h index 4cff04d2c4..040fc090cc 100644 --- a/engines/bladerunner/ui/kia_section_load.h +++ b/engines/bladerunner/ui/kia_section_load.h @@ -25,13 +25,49 @@ #include "bladerunner/ui/kia_section_base.h" +#include "common/scummsys.h" +#include "common/str.h" + +namespace Graphics { +struct Surface; +} + namespace BladeRunner { +class UIContainer; +class UIScrollBox; + class KIASectionLoad : public KIASectionBase { + struct Save { + Common::String name; + int slotNum; + }; + + UIContainer *_uiContainer; + UIScrollBox *_scrollBox; + + uint32 _timeLast; + uint32 _timeLeft; + + int _hoveredSaveSlot; + int _saveSlotMax; + public: - KIASectionLoad(BladeRunnerEngine *vm): KIASectionBase(vm){} + KIASectionLoad(BladeRunnerEngine *vm); + ~KIASectionLoad(); + + void open(); + void close(); + + void draw(Graphics::Surface &surface); + + void handleMouseMove(int mouseX, int mouseY); + void handleMouseDown(bool mainButton); + void handleMouseUp(bool mainButton); +private: + static void scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/ui/ui_container.cpp b/engines/bladerunner/ui/ui_container.cpp index 78097a9d3d..e84809d379 100644 --- a/engines/bladerunner/ui/ui_container.cpp +++ b/engines/bladerunner/ui/ui_container.cpp @@ -27,7 +27,7 @@ namespace BladeRunner { void UIContainer::draw(Graphics::Surface &surface) { -for (Common::Array::iterator component = _components.begin(); component != _components.end(); component++) { + for (Common::Array::iterator component = _components.begin(); component != _components.end(); component++) { (*component)->draw(surface); } } @@ -39,19 +39,19 @@ void UIContainer::handleMouseMove(int mouseX, int mouseY) { } void UIContainer::handleMouseDown(bool alternateButton) { -for (Common::Array::iterator component = _components.begin(); component != _components.end(); component++) { + for (Common::Array::iterator component = _components.begin(); component != _components.end(); component++) { (*component)->handleMouseDown(alternateButton); } } void UIContainer::handleMouseUp(bool alternateButton) { -for (Common::Array::iterator component = _components.begin(); component != _components.end(); component++) { + for (Common::Array::iterator component = _components.begin(); component != _components.end(); component++) { (*component)->handleMouseUp(alternateButton); } } void UIContainer::handleKeyUp(const Common::KeyState &kbd) { -for (Common::Array::iterator component = _components.begin(); component != _components.end(); component++) { + for (Common::Array::iterator component = _components.begin(); component != _components.end(); component++) { (*component)->handleKeyUp(kbd); } } -- cgit v1.2.3