From a06f291280e0897beed18e63e269938dfa45ccef Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Sat, 16 Jul 2016 19:57:36 +0200 Subject: MACVENTURE: Add basic game save/load feature --- engines/macventure/dialog.cpp | 11 ++++---- engines/macventure/dialog.h | 3 ++- engines/macventure/gui.cpp | 38 ++++++++++++++++++--------- engines/macventure/gui.h | 4 +++ engines/macventure/image.cpp | 4 +-- engines/macventure/macventure.cpp | 52 ++++++++++++++++++++++++++++++++++-- engines/macventure/macventure.h | 13 +++++++++ engines/macventure/world.cpp | 55 +++++++++++++++++++++++++-------------- engines/macventure/world.h | 12 +++++---- 9 files changed, 144 insertions(+), 48 deletions(-) (limited to 'engines/macventure') diff --git a/engines/macventure/dialog.cpp b/engines/macventure/dialog.cpp index 3a09feffd5..ba489d4bad 100644 --- a/engines/macventure/dialog.cpp +++ b/engines/macventure/dialog.cpp @@ -43,7 +43,7 @@ PrebuiltDialog prebuiltDialogs[kPrebuiltDialogCount] = { {/* kSaveAsDialog */ Common::Rect(0, 146, 456, 254), { - {kDEButton, "YES", kDANone, Common::Point(24, 68), 120, 22}, + {kDEButton, "YES", kDASaveAs, Common::Point(24, 68), 120, 22}, {kDEButton, "NO", kDACloseDialog, Common::Point(168, 68), 120, 22}, {kDEButton, "CANCEL", kDACloseDialog, Common::Point(312, 68), 120, 22}, {kDEPlainText, "Save As...", kDANone, Common::Point(100, 10), 340, 38}, @@ -92,6 +92,10 @@ void Dialog::handleDialogAction(DialogElement *trigger, DialogAction action) { _gui->setTextInput(_userInput); _gui->closeDialog(); break; + case kDASaveAs: + _gui->saveInto(0); + _gui->closeDialog(); + break; } } @@ -169,11 +173,6 @@ DialogElement::DialogElement(Dialog *dialog, Common::String title, DialogAction } bool DialogElement::processEvent(MacVenture::Dialog *dialog, Common::Event event) { - // HACK for test, please delete me - Common::Point mouse = event.mouse; - dialog->localize(mouse); - if (_bounds.contains(mouse)) debug(1, "Hovering over: %s", _text.c_str()); - return doProcessEvent(dialog, event); } diff --git a/engines/macventure/dialog.h b/engines/macventure/dialog.h index 1dbebf77f2..e773956b09 100644 --- a/engines/macventure/dialog.h +++ b/engines/macventure/dialog.h @@ -38,7 +38,8 @@ class DialogElement; enum DialogAction { kDANone, kDACloseDialog, - kDASubmit + kDASubmit, + kDASaveAs }; enum PrebuiltDialogs { diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp index d8deb4b568..6c9ccf6a2f 100644 --- a/engines/macventure/gui.cpp +++ b/engines/macventure/gui.cpp @@ -335,8 +335,8 @@ WindowReference Gui::createInventoryWindow(ObjID objRef) { newWindow->setDimensions(newData.bounds); newWindow->setCallback(inventoryWindowCallback, this); - //loadBorder(newWindow, "border_no_scroll_inac.bmp", false); - //loadBorder(newWindow, "border_no_scroll_act.bmp", true); + loadBorder(newWindow, "border_no_scroll_inac.bmp", false); + loadBorder(newWindow, "border_no_scroll_act.bmp", true); _inventoryWindows.push_back(newWindow); debug("Create new inventory window. Reference: %d", newData.refcon); @@ -686,13 +686,12 @@ void Gui::drawWindowTitle(WindowReference target, Graphics::ManagedSurface * sur } void Gui::drawDraggedObject() { - if (_draggedObj.id != 0) { + if (_draggedObj.id != 0 && + _engine->isObjVisible(_draggedObj.id)) { ensureAssetLoaded(_draggedObj.id); ImageAsset *asset = _assets[_draggedObj.id]; _draggedSurface.create(asset->getWidth(), asset->getHeight(), _screen.format); - _screen.copyRectToSurface(_draggedSurface, _draggedObj.pos.x, _draggedObj.pos.y, - Common::Rect(asset->getWidth() - 1, asset->getHeight() - 1)); asset->blitInto(&_draggedSurface, 0, 0, kBlitBIC); @@ -820,6 +819,14 @@ void Gui::getTextFromUser() { _engine->clickToContinue(); } +void Gui::loadGame(int slot) { + _engine->loadGameState(slot); +} + +void Gui::saveInto(int slot) { + _engine->saveGameState(slot, "desc"); + _engine->preparedToRun(); +} void Gui::moveDraggedObject(Common::Point target) { Common::Point newPos = target + _draggedObj.mouseOffset; @@ -857,9 +864,11 @@ WindowReference Gui::findWindowAtPoint(Common::Point point) { Graphics::MacWindow *win; for (it = _windowData->begin(); it != _windowData->end(); it++) { win = findWindow(it->refcon); - if (win && win->getDimensions().contains(point) && it->refcon != kDiplomaWindow) { //HACK, diploma should be cosnidered - if (win->isActive()) - return it->refcon; + if (win && it->refcon != kDiplomaWindow) { //HACK, diploma should be cosnidered + if (win->getDimensions().contains(point)) { + if (win->isActive()) + return it->refcon; + } } } return kNoWindow; @@ -869,6 +878,7 @@ Common::Point Gui::getWindowSurfacePos(WindowReference reference) { const WindowData &data = getWindowData(reference); BorderBounds border = borderBounds(data.type); Graphics::MacWindow *win = findWindow(reference); + if (!win) return Common::Point(0, 0); return Common::Point(win->getDimensions().left + border.leftOffset, win->getDimensions().top + border.topOffset); } @@ -976,9 +986,9 @@ void Gui::selectDraggable(ObjID child, WindowReference origin, Common::Point cli } void Gui::handleDragRelease(Common::Point pos, bool shiftPressed, bool isDoubleClick) { - WindowReference destinationWindow = findWindowAtPoint(pos); - if (destinationWindow == kNoWindow) return; if (_draggedObj.id != 0) { + WindowReference destinationWindow = findWindowAtPoint(pos); + if (destinationWindow == kNoWindow) return; if (_draggedObj.hasMoved) { ObjID destObject = getWindowData(destinationWindow).objRef; pos -= (_draggedObj.startPos - _draggedObj.mouseOffset); @@ -1027,9 +1037,11 @@ void Gui::handleMenuAction(MenuAction action) { break; case MacVenture::kMenuActionOpen: debug("MacVenture Menu Action: Open"); + loadGame(0); break; case MacVenture::kMenuActionSave: debug("MacVenture Menu Action: Save"); + saveInto(0); break; case MacVenture::kMenuActionSaveAs: debug("MacVenture Menu Action: Save As"); @@ -1139,8 +1151,8 @@ bool Gui::tryCloseWindow(WindowReference winID) { Common::Point Gui::getObjMeasures(ObjID obj) { ensureAssetLoaded(obj); - int w = MAX(0, (int)_assets[obj]->getWidth()); - int h = MAX(0, (int)_assets[obj]->getHeight()); + int w = _assets[obj]->getWidth(); + int h = _assets[obj]->getHeight(); return Common::Point(w, h); } @@ -1296,7 +1308,7 @@ void Gui::processCursorTick() { void Gui::handleSingleClick(Common::Point pos) { debug("Single Click"); - // HACK + // HACK THERE HAS TO BE A MORE ELEGANT WAY if (_dialog) return; handleDragRelease(pos, false, false); } diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h index f800aeb835..b03ca2afe9 100644 --- a/engines/macventure/gui.h +++ b/engines/macventure/gui.h @@ -247,10 +247,14 @@ public: void printText(const Common::String &text); + //Dialog interactions void getTextFromUser(); void setTextInput(Common::String str); void closeDialog(); + void loadGame(int slot); + void saveInto(int slot); + // Ugly switches BorderBounds borderBounds(MVWindowType type); diff --git a/engines/macventure/image.cpp b/engines/macventure/image.cpp index cbe3cc910d..fa281eb19a 100644 --- a/engines/macventure/image.cpp +++ b/engines/macventure/image.cpp @@ -387,11 +387,11 @@ bool ImageAsset::isRectInside(Common::Rect rect) { } uint ImageAsset::getWidth() { - return _bitWidth; + return MAX(0, (int)_bitWidth); } uint ImageAsset::getHeight() { - return _bitHeight; + return MAX(0, (int)_bitHeight); } void ImageAsset::blitDirect(Graphics::ManagedSurface * target, uint32 ox, uint32 oy, const Common::Array& data) { diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp index 1fca4288e8..9b764d9856 100644 --- a/engines/macventure/macventure.cpp +++ b/engines/macventure/macventure.cpp @@ -82,7 +82,6 @@ Common::Error MacVentureEngine::run() { // Additional setup. debug("MacVentureEngine::init"); - _resourceManager = new Common::MacResManager(); if (!_resourceManager->open(getGameFileName())) error("Could not open %s as a resource fork", getGameFileName()); @@ -113,7 +112,6 @@ Common::Error MacVentureEngine::run() { _destObject = 0; _prepared = true; - //if !savegame _cmdReady = true; _selectedControl = kStartOrResume; ObjID playerParent = _world->getObjAttr(1, kAttrParentObject); @@ -162,6 +160,42 @@ Common::Error MacVentureEngine::run() { return Common::kNoError; } +Common::Error MacVentureEngine::loadGameState(int slot) { + Common::InSaveFile *file = getSaveFileManager()->openForLoading("Shadowgate.1"); + _world->loadGameFrom(file); + reset(); + return Common::kNoError; +} + +Common::Error MacVentureEngine::saveGameState(int slot, const Common::String &desc) { + Common::SaveFileManager *manager = getSaveFileManager(); + // HACK Get a real name! + Common::OutSaveFile *file = manager->openForSaving("Shadowgate.1"); + _world->saveGameInto(file); + delete file; +} + +void MacVentureEngine::reset() { + resetInternals(); + resetGui(); +} + +void MacVentureEngine::resetInternals() { + _scriptEngine->reset(); + _currentSelection.clear(); + _selectedObjs.clear(); + _objQueue.clear(); + _textQueue.clear(); +} + +void MacVentureEngine::resetGui() { + _gui->updateWindowInfo(kMainGameWindow, getParent(1), _world->getChildren(getParent(1), true)); + // HACK! should update all inventories + _gui->updateWindowInfo(kInventoryStart, 1, _world->getChildren(1, true)); + _gui->updateWindowInfo(kExitsWindow, getParent(1), _world->getChildren(getParent(1), true)); +} + + void MacVentureEngine::requestQuit() { // TODO: Display save game dialog and such _gameState = kGameStateQuitting; @@ -391,6 +425,20 @@ Common::String MacVentureEngine::getUserInput() { return _userInput; } + +Common::String MacVentureEngine::getStartGameFileName() { + Common::SeekableReadStream *res; + res = _resourceManager->getResource(MKTAG('S', 'T', 'R', ' '), kStartGameFilenameID); + if (!res) + return ""; + + byte length = res->readByte(); + char *fileName = new char[length + 1]; + res->read(fileName, length); + fileName[length] = '\0'; + return Common::String(fileName, length); +} + const GlobalSettings& MacVentureEngine::getGlobalSettings() const { return _globalSettings; } diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h index f6a3ea66af..167abcc351 100644 --- a/engines/macventure/macventure.h +++ b/engines/macventure/macventure.h @@ -24,10 +24,13 @@ #define MACVENTURE_H #include "engines/engine.h" +#include "common/scummsys.h" +#include "common/system.h" #include "common/debug.h" #include "common/random.h" #include "common/macresman.h" #include "common/huffman.h" +#include "common/savefile.h" #include "gui/debugger.h" @@ -41,6 +44,8 @@ struct ADGameDescription; namespace MacVenture { +class SaveFileManager; + class Console; class World; class ScriptEngine; @@ -158,6 +163,12 @@ public: ~MacVentureEngine(); virtual Common::Error run(); + virtual Common::Error loadGameState(int slot); + virtual Common::Error saveGameState(int slot, const Common::String &desc); + + void reset(); + void resetInternals(); + void resetGui(); void requestQuit(); void requestUnpause(); @@ -189,7 +200,9 @@ public: void setTextInput(Common::String content); Common::String getUserInput(); + // Data retrieval + Common::String getStartGameFileName(); bool isPaused(); bool needsClickToContinue(); Common::String getCommandsPausedString() const; diff --git a/engines/macventure/world.cpp b/engines/macventure/world.cpp index e247404eb6..cf13b78e48 100644 --- a/engines/macventure/world.cpp +++ b/engines/macventure/world.cpp @@ -9,7 +9,7 @@ World::World(MacVentureEngine *engine, Common::MacResManager *resMan) { _resourceManager = resMan; _engine = engine; - if (!loadStartGameFileName()) + if ((_startGameFileName = _engine->getStartGameFileName()) == "") error("Could not load initial game configuration"); Common::File saveGameFile; @@ -150,9 +150,11 @@ void World::updateObj(ObjID objID) { } void World::captureChildren(ObjID objID) { + warning("Capture children unimplemented!"); } void World::releaseChildren(ObjID objID) { + warning("Release children unimplemented!"); } Common::String World::getText(ObjID objID, ObjID source, ObjID target) { @@ -175,23 +177,8 @@ bool World::intersects(ObjID objID, Common::Rect rect) { return _engine->getObjBounds(objID).intersects(rect); } -bool World::loadStartGameFileName() { - Common::SeekableReadStream *res; - - res = _resourceManager->getResource(MKTAG('S', 'T', 'R', ' '), kStartGameFilenameID); - if (!res) - return false; - - byte length = res->readByte(); - char *fileName = new char[length + 1]; - res->read(fileName, length); - fileName[length] = '\0'; - _startGameFileName = Common::String(fileName, length); - - return true; -} - void World::calculateObjectRelations() { + _relations.clear(); ObjID val, next; uint32 numObjs = _engine->getGlobalSettings().numObjects; const AttributeGroup &parents = *_saveGame->getGroup(0); @@ -228,6 +215,16 @@ void World::setParent(ObjID child, ObjID newParent) { _relations[oldNdx] = child; } +void World::loadGameFrom(Common::InSaveFile *file) { + if (_saveGame) delete _saveGame; + _saveGame = new SaveGame(_engine, file); + calculateObjectRelations(); +} + +void World::saveGameInto(Common::OutSaveFile *file) { + _saveGame->saveInto(file); +} + // SaveGame SaveGame::SaveGame(MacVentureEngine *engine, Common::SeekableReadStream *res) { _groups = Common::Array(); @@ -263,14 +260,34 @@ void SaveGame::setGlobal(uint32 attrID, Attribute value) { _globals[attrID] = value; } -const Common::Array& MacVenture::SaveGame::getGlobals() { +const Common::Array& SaveGame::getGlobals() { return _globals; } -const Common::String & MacVenture::SaveGame::getText() { +const Common::String & SaveGame::getText() { return _text; } +void SaveGame::saveInto(Common::OutSaveFile *file) { + warning("Saving the game not yet tested!"); + // Save attibutes + Common::Array::const_iterator itg; + for(itg = _groups.begin(); itg != _groups.end(); itg++) { + Common::Array::const_iterator ita; + for (ita = itg->begin(); ita != itg->end(); ita++) { + file->writeUint16BE((*ita)); + } + } + // Save globals + Common::Array::const_iterator global; + for (global = _globals.begin(); global != _globals.end(); global++) { + file->writeUint16BE((*global)); + } + // Save text + _text = "Hello"; + file->write(_text.c_str(), _text.size()); +} + void SaveGame::loadGroups(MacVentureEngine *engine, Common::SeekableReadStream * res) { GlobalSettings settings = engine->getGlobalSettings(); for (int i = 0; i < settings.numGroups; ++i) { diff --git a/engines/macventure/world.h b/engines/macventure/world.h index c023c70ec6..f3933c5f7e 100644 --- a/engines/macventure/world.h +++ b/engines/macventure/world.h @@ -74,6 +74,8 @@ public: const AttributeGroup *getGroup(uint32 groupID); const Common::String &getText(); + void saveInto(Common::OutSaveFile *file); + private: void loadGroups(MacVentureEngine *engine, Common::SeekableReadStream *res); void loadGlobals(MacVentureEngine *engine, Common::SeekableReadStream *res); @@ -90,7 +92,6 @@ public: World(MacVentureEngine *engine, Common::MacResManager *resMan); ~World(); - void setObjAttr(ObjID objID, uint32 attrID, Attribute value); void setGlobal(uint32 attrID, Attribute value); void updateObj(ObjID objID); @@ -105,13 +106,15 @@ public: ObjID getAncestor(ObjID objID); Common::Array getFamily(ObjID objID, bool recursive); - Common::Array getChildren(ObjID objID, bool recursive); + Common::Array getChildren(ObjID objID, bool recursive); + + void loadGameFrom(Common::InSaveFile *file); + void saveGameInto(Common::OutSaveFile *file); private: bool isObjDraggable(ObjID objID); bool intersects(ObjID objID, Common::Rect rect); - bool loadStartGameFileName(); void calculateObjectRelations(); void setParent(ObjID child, ObjID newParent); @@ -119,7 +122,7 @@ private: MacVentureEngine *_engine; Common::MacResManager *_resourceManager; - Common::String _startGameFileName; + Common::String _startGameFileName; SaveGame *_saveGame; @@ -132,4 +135,3 @@ private: } // End of namespace MacVenture #endif - -- cgit v1.2.3