[Scummvm-git-logs] scummvm master -> c6164fcf4a2063cced828d930df96e8e1dc6cc43
fracturehill
noreply at scummvm.org
Sun May 7 08:52:51 UTC 2023
This automated email contains information about 7 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
bd6023aba0 NANCY: Remove unnecessary forward declaration
932e93d714 NANCY: Implement BombPuzzle
13f61cf882 NANCY: Correct time of day for nancy2 and up
b7637ec92e NANCY: Respect ID offsets for nancy3 flags
ac81086665 NANCY: Correct dependency reading for nancy3
b1749a04e2 NANCY: Fix saving of riddle puzzle state
c6164fcf4a NANCY: Improve puzzle data storage and saving
Commit: bd6023aba00b710ea21f691f281e5e1c2b4113eb
https://github.com/scummvm/scummvm/commit/bd6023aba00b710ea21f691f281e5e1c2b4113eb
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-07T11:46:29+03:00
Commit Message:
NANCY: Remove unnecessary forward declaration
Changed paths:
engines/nancy/action/sliderpuzzle.h
diff --git a/engines/nancy/action/sliderpuzzle.h b/engines/nancy/action/sliderpuzzle.h
index 58115413c9f..0583903637c 100644
--- a/engines/nancy/action/sliderpuzzle.h
+++ b/engines/nancy/action/sliderpuzzle.h
@@ -24,10 +24,6 @@
#include "engines/nancy/action/actionrecord.h"
-namespace Common {
-class Serializer;
-}
-
namespace Nancy {
struct SPUZ;
Commit: 932e93d7141fbea2a57a0c4013f63c11a5d5c287
https://github.com/scummvm/scummvm/commit/932e93d7141fbea2a57a0c4013f63c11a5d5c287
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-07T11:46:32+03:00
Commit Message:
NANCY: Implement BombPuzzle
Changed paths:
A engines/nancy/action/bombpuzzle.cpp
A engines/nancy/action/bombpuzzle.h
engines/nancy/action/arfactory.cpp
engines/nancy/module.mk
engines/nancy/state/scene.h
diff --git a/engines/nancy/action/arfactory.cpp b/engines/nancy/action/arfactory.cpp
index da76380e44d..0af8f4beb8f 100644
--- a/engines/nancy/action/arfactory.cpp
+++ b/engines/nancy/action/arfactory.cpp
@@ -34,6 +34,7 @@
#include "engines/nancy/action/towerpuzzle.h"
#include "engines/nancy/action/riddlepuzzle.h"
#include "engines/nancy/action/overridelockpuzzle.h"
+#include "engines/nancy/action/bombpuzzle.h"
#include "engines/nancy/state/scene.h"
@@ -149,6 +150,8 @@ ActionRecord *ActionManager::createActionRecord(uint16 type) {
return new HintSystem();
case 201:
return new TowerPuzzle();
+ case 202:
+ return new BombPuzzle();
case 203:
return new RippedLetterPuzzle();
case 204:
diff --git a/engines/nancy/action/bombpuzzle.cpp b/engines/nancy/action/bombpuzzle.cpp
new file mode 100644
index 00000000000..7f27504ed0f
--- /dev/null
+++ b/engines/nancy/action/bombpuzzle.cpp
@@ -0,0 +1,275 @@
+/* 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 "engines/nancy/nancy.h"
+#include "engines/nancy/graphics.h"
+#include "engines/nancy/resource.h"
+#include "engines/nancy/sound.h"
+#include "engines/nancy/input.h"
+#include "engines/nancy/util.h"
+
+#include "engines/nancy/state/scene.h"
+
+#include "engines/nancy/action/bombpuzzle.h"
+
+namespace Nancy {
+namespace Action {
+
+void BombPuzzle::init() {
+ _screenPosition = _displayBounds;
+ for (Common::Rect &r : _wireDests) {
+ _screenPosition.extend(r);
+ }
+
+ _drawSurface.create(_screenPosition.width(), _screenPosition.height(), g_nancy->_graphicsManager->getInputPixelFormat());
+ _drawSurface.clear(g_nancy->_graphicsManager->getTransColor());
+
+ setTransparent(true);
+
+ g_nancy->_resource->loadImage(_imageName, _image);
+ RenderActionRecord::init();
+}
+
+void BombPuzzle::readData(Common::SeekableReadStream &stream) {
+ readFilename(stream, _imageName);
+
+ readRectArray(stream, _wireSrcs, 4);
+ readRectArray(stream, _wireDests, 4);
+ readRectArray(stream, _digitSrcs, 10);
+ readRectArray(stream, _digitDests, 4);
+ readRect(stream, _colonSrc);
+ readRect(stream, _colonDest);
+ readRect(stream, _displayBounds);
+
+ _solveOrder.resize(4);
+ for (uint i = 0; i < 4; ++i) {
+ _solveOrder[i] = stream.readByte();
+ }
+
+ _snipSound.readData(stream, SoundDescription::kNormal);
+ _noToolSound.readData(stream, SoundDescription::kNormal);
+ _toolID = stream.readUint16LE();
+
+ _solveSceneChange.readData(stream);
+ stream.skip(2);
+ _solveSound.readData(stream, SoundDescription::kNormal);
+
+ _failSceneChange.readData(stream);
+ stream.skip(2);
+ _failSound.readData(stream, SoundDescription::kNormal);
+
+ switch (NancySceneState.getDifficulty()) {
+ case 0:
+ _timerTotalTime = 30 * 1000;
+ break;
+ case 1:
+ _timerTotalTime = 25 * 1000;
+ break;
+ case 2:
+ _timerTotalTime = 20 * 1000;
+ break;
+ }
+
+ _nextBlinkTime = _timerTotalTime;
+ _timerBlinkTime = 10 * 1000; // 10 seconds for all difficulties
+}
+
+void BombPuzzle::updateGraphics() {
+ if (_state != kRun) {
+ return;
+ }
+
+ Time timeRemaining = NancySceneState.getTimerTime();
+
+ if (timeRemaining == 0) {
+ return;
+ }
+
+ if (timeRemaining > _timerTotalTime) {
+ timeRemaining = 0;
+ } else {
+ timeRemaining = _timerTotalTime - timeRemaining;
+ }
+
+ bool toggleBlink = false;
+
+ if (timeRemaining < _nextBlinkTime) {
+ _nextBlinkTime = timeRemaining - 300; // hardcoded to 300 ms
+ toggleBlink = timeRemaining < _timerBlinkTime;
+ }
+
+ if (_lastDrawnTime == timeRemaining.getSeconds() && !toggleBlink) {
+ // State is the same as last call, do not redraw
+ return;
+ }
+
+ Common::Rect t = _displayBounds;
+ t.translate(-_screenPosition.left, -_screenPosition.top);
+
+ _lastDrawnTime = timeRemaining.getSeconds();
+
+ // Clear the display
+ _drawSurface.fillRect(t, _drawSurface.getTransparentColor());
+
+ if (toggleBlink) {
+ if (!_isBlinking) {
+ // Only clear the display
+ _isBlinking = true;
+ _needsRedraw = true;
+ return;
+ } else {
+ // Redraw the display
+ _isBlinking = false;
+ }
+ } else {
+ if (_isBlinking) {
+ // Only clear the display
+ _needsRedraw = true;
+ return;
+ }
+ }
+
+ // Add 1 second to timer so it starts at 30/25/20 seconds
+ timeRemaining += 1000;
+
+ // Draw 10s of minutes
+ t = _digitDests[0];
+ t.translate(-_screenPosition.left, -_screenPosition.top);
+ _drawSurface.blitFrom(_image, _digitSrcs[timeRemaining.getMinutes() / 10], t);
+
+ // Draw 1s of minutes
+ t = _digitDests[1];
+ t.translate(-_screenPosition.left, -_screenPosition.top);
+ _drawSurface.blitFrom(_image, _digitSrcs[timeRemaining.getMinutes() % 10], t);
+
+ // Draw 10s of seconds
+ t = _digitDests[2];
+ t.translate(-_screenPosition.left, -_screenPosition.top);
+ _drawSurface.blitFrom(_image, _digitSrcs[timeRemaining.getSeconds() / 10], t);
+
+ // Draw 1s of seconds
+ t = _digitDests[3];
+ t.translate(-_screenPosition.left, -_screenPosition.top);
+ _drawSurface.blitFrom(_image, _digitSrcs[timeRemaining.getSeconds() % 10], t);
+
+ // Draw colon
+ t = _colonDest;
+ t.translate(-_screenPosition.left, -_screenPosition.top);
+ _drawSurface.blitFrom(_image, _colonSrc, t);
+
+ _needsRedraw = true;
+}
+
+void BombPuzzle::execute() {
+ switch (_state) {
+ case kBegin:
+ init();
+ registerGraphics();
+
+ g_nancy->_sound->loadSound(_snipSound);
+ g_nancy->_sound->loadSound(_noToolSound);
+
+ _state = kRun;
+ break;
+ case kRun: {
+ bool fail = false;
+
+ for (uint i = 0; i < _playerOrder.size(); ++i) {
+ if (_playerOrder[i] != _solveOrder[i]) {
+ fail = true;
+ break;
+ }
+ }
+
+ if (fail) {
+ _failed = true;
+ _state = kActionTrigger;
+ g_nancy->_sound->loadSound(_failSound);
+ g_nancy->_sound->playSound(_failSound);
+
+ return;
+ }
+
+ if (_playerOrder.size() == _solveOrder.size()) {
+ _failed = false;
+ _state = kActionTrigger;
+ g_nancy->_sound->loadSound(_solveSound);
+ g_nancy->_sound->playSound(_solveSound);
+ }
+
+ break;
+ }
+ case kActionTrigger:
+ if (_failed) {
+ if (g_nancy->_sound->isSoundPlaying(_failSound)) {
+ return;
+ }
+
+ g_nancy->_sound->stopSound(_failSound);
+ _failSceneChange.execute();
+ } else {
+ if (g_nancy->_sound->isSoundPlaying(_solveSound)) {
+ return;
+ }
+
+ g_nancy->_sound->stopSound(_solveSound);
+ _solveSceneChange.execute();
+ }
+
+ g_nancy->_sound->stopSound(_snipSound);
+ g_nancy->_sound->stopSound(_noToolSound);
+
+ finishExecution();
+ }
+}
+
+void BombPuzzle::handleInput(NancyInput &input) {
+ for (uint i = 0 ; i < _wireDests.size(); ++i) {
+ if (NancySceneState.getViewport().convertViewportToScreen(_wireDests[i]).contains(input.mousePos)) {
+ for (byte j : _playerOrder) {
+ if (i == j) {
+ // Wire already snipped, do nothing
+ return;
+ }
+ }
+
+ g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
+
+ if (input.input & NancyInput::kLeftMouseButtonUp) {
+ if (NancySceneState.getHeldItem() == _toolID) {
+ _playerOrder.push_back(i);
+ g_nancy->_sound->playSound(_snipSound);
+ Common::Rect dest = _wireDests[i];
+ dest.translate(-_screenPosition.left, -_screenPosition.top);
+ _drawSurface.blitFrom(_image, _wireSrcs[i], dest);
+ _needsRedraw = true;
+ } else {
+ g_nancy->_sound->playSound(_noToolSound);
+ }
+ }
+
+ break;
+ }
+ }
+}
+
+} // End of namespace Action
+} // End of namespace Nancy
diff --git a/engines/nancy/action/bombpuzzle.h b/engines/nancy/action/bombpuzzle.h
new file mode 100644
index 00000000000..a0b2a6d52a9
--- /dev/null
+++ b/engines/nancy/action/bombpuzzle.h
@@ -0,0 +1,78 @@
+/* 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/>.
+ *
+ */
+
+#ifndef NANCY_ACTION_BOMBPUZZLE_H
+#define NANCY_ACTION_BOMBPUZZLE_H
+
+#include "engines/nancy/action/actionrecord.h"
+
+namespace Nancy {
+namespace Action {
+
+class BombPuzzle : public RenderActionRecord {
+public:
+ BombPuzzle() : RenderActionRecord(7) {}
+ virtual ~BombPuzzle() {}
+
+ void init() override;
+ void updateGraphics() override;
+
+ void readData(Common::SeekableReadStream &stream) override;
+ void execute() override;
+ void handleInput(NancyInput &input) override;
+
+protected:
+ Common::String getRecordTypeName() const override { return "BombPuzzle"; }
+ bool isViewportRelative() const override { return true; }
+
+ Common::String _imageName;
+ Common::Array<Common::Rect> _wireSrcs;
+ Common::Array<Common::Rect> _wireDests;
+ Common::Array<Common::Rect> _digitSrcs;
+ Common::Array<Common::Rect> _digitDests;
+ Common::Rect _colonSrc;
+ Common::Rect _colonDest;
+ Common::Rect _displayBounds;
+ Common::Array<byte> _solveOrder;
+ SoundDescription _snipSound;
+ SoundDescription _noToolSound;
+ uint16 _toolID;
+ SceneChangeWithFlag _solveSceneChange;
+ SoundDescription _solveSound;
+ SceneChangeWithFlag _failSceneChange;
+ SoundDescription _failSound;
+
+ Graphics::ManagedSurface _image;
+ Common::Array<byte> _playerOrder;
+
+ Time _timerTotalTime;
+ Time _timerBlinkTime;
+ Time _nextBlinkTime;
+ bool _isBlinking = false;
+ uint _lastDrawnTime = 0;
+
+ bool _failed = false;
+};
+
+} // End of namespace Action
+} // End of namespace Nancy
+
+#endif // NANCY_ACTION_BOMBPUZZLE_H
diff --git a/engines/nancy/module.mk b/engines/nancy/module.mk
index 18bde304e50..dec6e74a51a 100644
--- a/engines/nancy/module.mk
+++ b/engines/nancy/module.mk
@@ -4,6 +4,7 @@ MODULE_OBJS = \
action/actionmanager.o \
action/actionrecord.o \
action/arfactory.o \
+ action/bombpuzzle.o \
action/conversation.o \
action/leverpuzzle.o \
action/orderingpuzzle.o \
diff --git a/engines/nancy/state/scene.h b/engines/nancy/state/scene.h
index 171675414ee..d6d1926b2e8 100644
--- a/engines/nancy/state/scene.h
+++ b/engines/nancy/state/scene.h
@@ -132,6 +132,7 @@ public:
void setPlayerTime(Time time, byte relative);
Time getPlayerTime() const { return _timers.playerTime; }
+ Time getTimerTime() const { return _timers.timerIsActive ? _timers.timerTime : 0; }
byte getPlayerTOD() const;
void addItemToInventory(uint16 id);
Commit: 13f61cf8823901d15af4f4925b519ee9ffe35185
https://github.com/scummvm/scummvm/commit/13f61cf8823901d15af4f4925b519ee9ffe35185
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-07T11:46:33+03:00
Commit Message:
NANCY: Correct time of day for nancy2 and up
Changed paths:
engines/nancy/state/scene.cpp
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index a4b18b2e806..fab951ccb41 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -280,12 +280,21 @@ void Scene::setPlayerTime(Time time, byte relative) {
}
byte Scene::getPlayerTOD() const {
- if (_timers.playerTime.getHours() >= 7 && _timers.playerTime.getHours() < 18) {
- return kPlayerDay;
- } else if (_timers.playerTime.getHours() >= 19 || _timers.playerTime.getHours() < 6) {
- return kPlayerNight;
+ if (g_nancy->getGameType() <= kGameTypeNancy1) {
+ if (_timers.playerTime.getHours() >= 7 && _timers.playerTime.getHours() < 18) {
+ return kPlayerDay;
+ } else if (_timers.playerTime.getHours() >= 19 || _timers.playerTime.getHours() < 6) {
+ return kPlayerNight;
+ } else {
+ return kPlayerDuskDawn;
+ }
} else {
- return kPlayerDuskDawn;
+ // nancy2 and up removed dusk/dawn
+ if (_timers.playerTime.getHours() >= 6 && _timers.playerTime.getHours() < 18) {
+ return kPlayerDay;
+ } else {
+ return kPlayerNight;
+ }
}
}
Commit: b7637ec92ec2178ef94f9a5768f4f979292090eb
https://github.com/scummvm/scummvm/commit/b7637ec92ec2178ef94f9a5768f4f979292090eb
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-07T11:46:33+03:00
Commit Message:
NANCY: Respect ID offsets for nancy3 flags
Changed paths:
engines/nancy/state/scene.cpp
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index fab951ccb41..0dc1d22ad2f 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -322,6 +322,11 @@ void Scene::setHeldItem(int16 id) {
}
void Scene::setEventFlag(int16 label, byte flag) {
+ if (label > 1000) {
+ // In nancy3 and onwards flags begin from 1000
+ label -= 1000;
+ }
+
if (label > kEvNoEvent && (uint)label < g_nancy->getStaticData().numEventFlags) {
_flags.eventFlags[label] = flag;
}
@@ -332,6 +337,11 @@ void Scene::setEventFlag(FlagDescription eventFlag) {
}
bool Scene::getEventFlag(int16 label, byte flag) const {
+ if (label > 1000) {
+ // In nancy3 and onwards flags begin from 1000
+ label -= 1000;
+ }
+
if (label > kEvNoEvent && (uint)label < g_nancy->getStaticData().numEventFlags) {
return _flags.eventFlags[label] == flag;
} else {
@@ -345,6 +355,10 @@ bool Scene::getEventFlag(FlagDescription eventFlag) const {
void Scene::setLogicCondition(int16 label, byte flag) {
if (label > kEvNoEvent) {
+ if (label > 2000) {
+ // In nancy3 and onwards logic conditions begin from 2000
+ label -= 2000;
+ }
_flags.logicConditions[label].flag = flag;
_flags.logicConditions[label].timestamp = g_nancy->getTotalPlayTime();
}
Commit: ac81086665766f14e67e93e2d3615c5ca6a3c819
https://github.com/scummvm/scummvm/commit/ac81086665766f14e67e93e2d3615c5ca6a3c819
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-07T11:46:34+03:00
Commit Message:
NANCY: Correct dependency reading for nancy3
Changed paths:
engines/nancy/action/actionmanager.cpp
engines/nancy/action/actionrecord.h
diff --git a/engines/nancy/action/actionmanager.cpp b/engines/nancy/action/actionmanager.cpp
index 2551cc13484..84abe63d7b2 100644
--- a/engines/nancy/action/actionmanager.cpp
+++ b/engines/nancy/action/actionmanager.cpp
@@ -119,10 +119,11 @@ bool ActionManager::addNewActionRecord(Common::SeekableReadStream &inputData) {
// If the localChunkSize is less than the total data, there must be dependencies at the end of the chunk
uint16 depsDataSize = (uint16)inputData.size() - localChunkSize;
if (depsDataSize > 0) {
- // Each dependency is 0x0C bytes long (in v1)
- uint numDependencies = depsDataSize / 0xC;
- if (depsDataSize % 0xC) {
- error("Action record type %s has incorrect read size", newRecord->getRecordTypeName().c_str());;
+ // Each dependency is 12 (up to nancy2) or 16 (nancy3 and up) bytes long
+ uint singleDepSize = g_nancy->getGameType() <= kGameTypeNancy2 ? 12 : 16;
+ uint numDependencies = depsDataSize / singleDepSize;
+ if (depsDataSize % singleDepSize) {
+ error("Action record type %s has incorrect read size", newRecord->getRecordTypeName().c_str());
}
// Initialize the dependencies data
@@ -132,10 +133,18 @@ bool ActionManager::addNewActionRecord(Common::SeekableReadStream &inputData) {
newRecord->_dependencies.push_back(DependencyRecord());
DependencyRecord &dep = newRecord->_dependencies.back();
- dep.type = (DependencyType)inputData.readByte();
- dep.label = inputData.readByte();
- dep.condition = inputData.readByte();
- dep.orFlag = inputData.readByte();
+ if (singleDepSize == 12) {
+ dep.type = (DependencyType)inputData.readByte();
+ dep.label = inputData.readByte();
+ dep.condition = inputData.readByte();
+ dep.orFlag = inputData.readByte();
+ } else if (singleDepSize == 16) {
+ dep.type = (DependencyType)inputData.readUint16LE();
+ dep.label = inputData.readUint16LE();
+ dep.condition = inputData.readUint16LE();
+ dep.orFlag = inputData.readUint16LE();
+ }
+
dep.hours = inputData.readSint16LE();
dep.minutes = inputData.readSint16LE();
dep.seconds = inputData.readSint16LE();
diff --git a/engines/nancy/action/actionrecord.h b/engines/nancy/action/actionrecord.h
index 2029a777a20..c548bee75f1 100644
--- a/engines/nancy/action/actionrecord.h
+++ b/engines/nancy/action/actionrecord.h
@@ -39,7 +39,7 @@ struct NancyInput;
namespace Action {
-enum struct DependencyType : byte {
+enum struct DependencyType : int16 {
kNone = 0,
kInventory = 1,
kEvent = 2,
@@ -66,8 +66,8 @@ enum struct DependencyType : byte {
// action record can be executed
struct DependencyRecord {
DependencyType type; // 0x00
- byte label; // 0x01
- byte condition; // 0x02
+ int16 label; // 0x01
+ int16 condition; // 0x02
bool orFlag; // 0x03
int16 hours; // 0x04
int16 minutes; // 0x06
Commit: b1749a04e2bb7a996c6b0ce2429329726c13a8b9
https://github.com/scummvm/scummvm/commit/b1749a04e2bb7a996c6b0ce2429329726c13a8b9
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-07T11:46:34+03:00
Commit Message:
NANCY: Fix saving of riddle puzzle state
Changed paths:
engines/nancy/state/scene.cpp
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 0dc1d22ad2f..1964545a7ec 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -560,7 +560,7 @@ void Scene::synchronize(Common::Serializer &ser) {
ser.syncArray(_towerPuzzleState->order[i].data(), 6, Common::Serializer::Byte);
}
- byte numRiddles;
+ byte numRiddles = _riddlePuzzleState->solvedRiddleIDs.size();
ser.syncAsByte(numRiddles);
if (ser.isLoading()) {
Commit: c6164fcf4a2063cced828d930df96e8e1dc6cc43
https://github.com/scummvm/scummvm/commit/c6164fcf4a2063cced828d930df96e8e1dc6cc43
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-07T11:46:35+03:00
Commit Message:
NANCY: Improve puzzle data storage and saving
Changed the way game-specific puzzle data is stored and
saved. Scene now holds a HashMap of lazily initialized
PuzzleData objects, each of which stores data for a specific
puzzle type. This helps avoid long switch statements in
the initialization and save/load code, and helps avoid
breaking savefiles every time a new puzzle type
is implemented.
Changed paths:
A engines/nancy/puzzledata.cpp
A engines/nancy/puzzledata.h
engines/nancy/action/riddlepuzzle.cpp
engines/nancy/action/riddlepuzzle.h
engines/nancy/action/rippedletterpuzzle.cpp
engines/nancy/action/rippedletterpuzzle.h
engines/nancy/action/sliderpuzzle.cpp
engines/nancy/action/sliderpuzzle.h
engines/nancy/action/towerpuzzle.cpp
engines/nancy/action/towerpuzzle.h
engines/nancy/commontypes.h
engines/nancy/module.mk
engines/nancy/nancy.h
engines/nancy/state/scene.cpp
engines/nancy/state/scene.h
diff --git a/engines/nancy/action/riddlepuzzle.cpp b/engines/nancy/action/riddlepuzzle.cpp
index 0c291facf6e..064f48b0db5 100644
--- a/engines/nancy/action/riddlepuzzle.cpp
+++ b/engines/nancy/action/riddlepuzzle.cpp
@@ -25,6 +25,7 @@
#include "engines/nancy/util.h"
#include "engines/nancy/input.h"
#include "engines/nancy/graphics.h"
+#include "engines/nancy/puzzledata.h"
#include "engines/nancy/state/scene.h"
#include "engines/nancy/action/riddlepuzzle.h"
@@ -45,7 +46,7 @@ void RiddlePuzzle::init() {
}
void RiddlePuzzle::readData(Common::SeekableReadStream &stream) {
- _puzzleState = NancySceneState._riddlePuzzleState;
+ _puzzleState = (RiddlePuzzleData *)NancySceneState.getPuzzleData(RiddlePuzzleData::getTag());
assert(_puzzleState);
_viewportTextFontID = stream.readUint16LE();
diff --git a/engines/nancy/action/riddlepuzzle.h b/engines/nancy/action/riddlepuzzle.h
index 88b92a5c1f5..f347a3e16c7 100644
--- a/engines/nancy/action/riddlepuzzle.h
+++ b/engines/nancy/action/riddlepuzzle.h
@@ -25,6 +25,9 @@
#include "engines/nancy/action/actionrecord.h"
namespace Nancy {
+
+struct RiddlePuzzleData;
+
namespace Action {
class RiddlePuzzle : public RenderActionRecord {
@@ -73,7 +76,7 @@ protected:
bool _playerHasHitReturn = false;
Common::String _playerInput;
uint _riddleID = 0;
- RiddlePuzzleState *_puzzleState = nullptr;
+ RiddlePuzzleData *_puzzleState = nullptr;
};
} // End of namespace Action
diff --git a/engines/nancy/action/rippedletterpuzzle.cpp b/engines/nancy/action/rippedletterpuzzle.cpp
index 655951bacca..640d6345ce8 100644
--- a/engines/nancy/action/rippedletterpuzzle.cpp
+++ b/engines/nancy/action/rippedletterpuzzle.cpp
@@ -26,6 +26,7 @@
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
#include "engines/nancy/cursor.h"
+#include "engines/nancy/puzzledata.h"
#include "engines/nancy/state/scene.h"
#include "engines/nancy/action/rippedletterpuzzle.h"
@@ -55,7 +56,7 @@ void RippedLetterPuzzle::registerGraphics() {
}
void RippedLetterPuzzle::readData(Common::SeekableReadStream &stream) {
- _puzzleState = NancySceneState._rippedLetterPuzzleState;
+ _puzzleState = (RippedLetterPuzzleData *)NancySceneState.getPuzzleData(RippedLetterPuzzleData::getTag());
assert(_puzzleState);
readFilename(stream, _imageName);
diff --git a/engines/nancy/action/rippedletterpuzzle.h b/engines/nancy/action/rippedletterpuzzle.h
index 3b6152019c6..8d9036a0824 100644
--- a/engines/nancy/action/rippedletterpuzzle.h
+++ b/engines/nancy/action/rippedletterpuzzle.h
@@ -25,6 +25,9 @@
#include "engines/nancy/action/actionrecord.h"
namespace Nancy {
+
+struct RippedLetterPuzzleData;
+
namespace Action {
class RippedLetterPuzzle : public RenderActionRecord {
@@ -63,7 +66,7 @@ public:
Graphics::ManagedSurface _image;
SolveState _solveState = kNotSolved;
- RippedLetterPuzzleState *_puzzleState = nullptr;
+ RippedLetterPuzzleData *_puzzleState = nullptr;
protected:
Common::String getRecordTypeName() const override { return "RippedLetterPuzzle"; }
diff --git a/engines/nancy/action/sliderpuzzle.cpp b/engines/nancy/action/sliderpuzzle.cpp
index 6f84b14ad27..4715ae965ca 100644
--- a/engines/nancy/action/sliderpuzzle.cpp
+++ b/engines/nancy/action/sliderpuzzle.cpp
@@ -25,6 +25,7 @@
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
#include "engines/nancy/util.h"
+#include "engines/nancy/puzzledata.h"
#include "engines/nancy/action/sliderpuzzle.h"
@@ -46,7 +47,7 @@ void SliderPuzzle::readData(Common::SeekableReadStream &stream) {
_spuzData = g_nancy->_sliderPuzzleData;
assert(_spuzData);
- _puzzleState = NancySceneState._sliderPuzzleState;
+ _puzzleState = (SliderPuzzleData *)NancySceneState.getPuzzleData(SliderPuzzleData::getTag());
assert(_puzzleState);
readFilename(stream, _imageName);
diff --git a/engines/nancy/action/sliderpuzzle.h b/engines/nancy/action/sliderpuzzle.h
index 0583903637c..c71242b0910 100644
--- a/engines/nancy/action/sliderpuzzle.h
+++ b/engines/nancy/action/sliderpuzzle.h
@@ -27,6 +27,7 @@
namespace Nancy {
struct SPUZ;
+struct SliderPuzzleData;
namespace Action {
@@ -43,7 +44,7 @@ public:
void handleInput(NancyInput &input) override;
SPUZ *_spuzData = nullptr;
- SliderPuzzleState *_puzzleState = nullptr;
+ SliderPuzzleData *_puzzleState = nullptr;
Common::String _imageName;
uint16 _width = 0;
diff --git a/engines/nancy/action/towerpuzzle.cpp b/engines/nancy/action/towerpuzzle.cpp
index 03d21a6757b..145cd289f69 100644
--- a/engines/nancy/action/towerpuzzle.cpp
+++ b/engines/nancy/action/towerpuzzle.cpp
@@ -25,6 +25,7 @@
#include "engines/nancy/resource.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
+#include "engines/nancy/puzzledata.h"
#include "engines/nancy/state/scene.h"
#include "engines/nancy/action/towerpuzzle.h"
@@ -50,7 +51,7 @@ void TowerPuzzle::registerGraphics() {
}
void TowerPuzzle::readData(Common::SeekableReadStream &stream) {
- _puzzleState = NancySceneState._towerPuzzleState;
+ _puzzleState = (TowerPuzzleData *)NancySceneState.getPuzzleData(TowerPuzzleData::getTag());
assert(_puzzleState);
readFilename(stream, _imageName);
diff --git a/engines/nancy/action/towerpuzzle.h b/engines/nancy/action/towerpuzzle.h
index b698b4f00c8..1cdd51872dc 100644
--- a/engines/nancy/action/towerpuzzle.h
+++ b/engines/nancy/action/towerpuzzle.h
@@ -25,6 +25,9 @@
#include "engines/nancy/action/actionrecord.h"
namespace Nancy {
+
+struct TowerPuzzleData;
+
namespace Action {
class TowerPuzzle : public RenderActionRecord {
@@ -68,7 +71,7 @@ protected:
int8 _heldRingID = -1;
int8 _heldRingPoleID = -1;
SolveState _solveState = kNotSolved;
- TowerPuzzleState *_puzzleState;
+ TowerPuzzleData *_puzzleState = nullptr;
uint _numRings = 0;
};
diff --git a/engines/nancy/commontypes.h b/engines/nancy/commontypes.h
index 78710d725cd..c1f1c0db5b3 100644
--- a/engines/nancy/commontypes.h
+++ b/engines/nancy/commontypes.h
@@ -249,28 +249,6 @@ struct StaticData {
void readData(Common::SeekableReadStream &stream, Common::Language language);
};
-// Structs for game-specific puzzle data that needs to be saved/loaded
-struct SliderPuzzleState {
- Common::Array<Common::Array<int16>> playerTileOrder;
- bool playerHasTriedPuzzle;
-};
-
-struct RippedLetterPuzzleState {
- Common::Array<int8> order;
- Common::Array<byte> rotations;
- bool playerHasTriedPuzzle;
-};
-
-struct TowerPuzzleState {
- Common::Array<Common::Array<int8>> order;
- bool playerHasTriedPuzzle;
-};
-
-struct RiddlePuzzleState {
- Common::Array<byte> solvedRiddleIDs;
- int8 incorrectRiddleID;
-};
-
} // End of namespace Nancy
#endif // NANCY_COMMONYPES_H
diff --git a/engines/nancy/module.mk b/engines/nancy/module.mk
index dec6e74a51a..075bfd37c4b 100644
--- a/engines/nancy/module.mk
+++ b/engines/nancy/module.mk
@@ -48,6 +48,7 @@ MODULE_OBJS = \
input.o \
metaengine.o \
nancy.o \
+ puzzledata.o \
renderobject.o \
resource.o \
sound.o \
diff --git a/engines/nancy/nancy.h b/engines/nancy/nancy.h
index 35c6ca20671..4e6856f587e 100644
--- a/engines/nancy/nancy.h
+++ b/engines/nancy/nancy.h
@@ -52,7 +52,7 @@ class Serializer;
*/
namespace Nancy {
-static const int kSavegameVersion = 2;
+static const int kSavegameVersion = 3;
struct NancyGameDescription;
diff --git a/engines/nancy/puzzledata.cpp b/engines/nancy/puzzledata.cpp
new file mode 100644
index 00000000000..5515e88f5da
--- /dev/null
+++ b/engines/nancy/puzzledata.cpp
@@ -0,0 +1,114 @@
+/* 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 "engines/nancy/puzzledata.h"
+
+namespace Nancy {
+
+SliderPuzzleData::SliderPuzzleData() : playerHasTriedPuzzle(false) {}
+
+void SliderPuzzleData::synchronize(Common::Serializer &ser) {
+ ser.syncAsByte(playerHasTriedPuzzle);
+
+ byte x = 0, y = 0;
+
+ if (ser.isSaving()) {
+ y = playerTileOrder.size();
+ if (y) {
+ x = playerTileOrder.back().size();
+ } else {
+ x = 0;
+ }
+ }
+
+ ser.syncAsByte(x);
+ ser.syncAsByte(y);
+
+ playerTileOrder.resize(y);
+
+ for (int i = 0; i < y; ++i) {
+ playerTileOrder[i].resize(x);
+ ser.syncArray(playerTileOrder[i].data(), x, Common::Serializer::Sint16LE);
+ }
+}
+
+RippedLetterPuzzleData::RippedLetterPuzzleData() :
+ order(24, 0),
+ rotations(24, 0),
+ playerHasTriedPuzzle(false) {}
+
+void RippedLetterPuzzleData::synchronize(Common::Serializer &ser) {
+ if (ser.isLoading()) {
+ order.resize(24);
+ rotations.resize(24);
+ }
+
+ ser.syncArray(order.data(), 24, Common::Serializer::Byte);
+ ser.syncArray(rotations.data(), 24, Common::Serializer::Byte);
+}
+
+TowerPuzzleData::TowerPuzzleData() {
+ order.resize(3, Common::Array<int8>(6, -1));
+ playerHasTriedPuzzle = false;
+}
+
+void TowerPuzzleData::synchronize(Common::Serializer &ser) {
+ ser.syncAsByte(playerHasTriedPuzzle);
+
+ if (ser.isLoading()) {
+ order.resize(3, Common::Array<int8>(6, -1));
+ }
+
+ for (uint i = 0; i < 3; ++i) {
+ ser.syncArray(order[i].data(), 6, Common::Serializer::Byte);
+ }
+}
+
+RiddlePuzzleData::RiddlePuzzleData() :
+ incorrectRiddleID(-1) {}
+
+void RiddlePuzzleData::synchronize(Common::Serializer &ser) {
+ byte numRiddles = solvedRiddleIDs.size();
+ ser.syncAsByte(numRiddles);
+
+ if (ser.isLoading()) {
+ solvedRiddleIDs.resize(numRiddles);
+ }
+
+ ser.syncArray(solvedRiddleIDs.data(), numRiddles, Common::Serializer::Byte);
+}
+
+PuzzleData *makePuzzleData(const uint32 tag) {
+ switch(tag) {
+ case SliderPuzzleData::getTag():
+ return new SliderPuzzleData();
+ case RippedLetterPuzzleData::getTag():
+ return new RippedLetterPuzzleData();
+ case TowerPuzzleData::getTag():
+ return new TowerPuzzleData();
+ case RiddlePuzzleData::getTag():
+ return new RiddlePuzzleData();
+ default:
+ return nullptr;
+ }
+}
+
+} // End of namespace Nancy
diff --git a/engines/nancy/puzzledata.h b/engines/nancy/puzzledata.h
new file mode 100644
index 00000000000..bf9c90f4a07
--- /dev/null
+++ b/engines/nancy/puzzledata.h
@@ -0,0 +1,85 @@
+/* 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 "common/serializer.h"
+#include "common/array.h"
+
+#ifndef NANCY_PUZZLEDATA_H
+#define NANCY_PUZZLEDATA_H
+
+namespace Nancy {
+
+// The following structs contain persistent data for specific
+// puzzle types, which is to be stored in savefiles
+
+struct PuzzleData {
+ PuzzleData() {}
+ virtual ~PuzzleData() {}
+
+ virtual void synchronize(Common::Serializer &ser) = 0;
+};
+
+struct SliderPuzzleData : public PuzzleData {
+ SliderPuzzleData();
+
+ static constexpr uint32 getTag() { return MKTAG('S', 'L', 'I', 'D'); }
+ virtual void synchronize(Common::Serializer &ser);
+
+ Common::Array<Common::Array<int16>> playerTileOrder;
+ bool playerHasTriedPuzzle;
+};
+
+struct RippedLetterPuzzleData : public PuzzleData {
+ RippedLetterPuzzleData();
+
+ static constexpr uint32 getTag() { return MKTAG('R', 'I', 'P', 'L'); }
+ virtual void synchronize(Common::Serializer &ser);
+
+ Common::Array<int8> order;
+ Common::Array<byte> rotations;
+ bool playerHasTriedPuzzle;
+};
+
+struct TowerPuzzleData : public PuzzleData {
+ TowerPuzzleData();
+
+ static constexpr uint32 getTag() { return MKTAG('T', 'O', 'W', 'R'); }
+ virtual void synchronize(Common::Serializer &ser);
+
+ Common::Array<Common::Array<int8>> order;
+ bool playerHasTriedPuzzle;
+};
+
+struct RiddlePuzzleData : public PuzzleData {
+ RiddlePuzzleData();
+
+ static constexpr uint32 getTag() { return MKTAG('R', 'I', 'D', 'L'); }
+ virtual void synchronize(Common::Serializer &ser);
+
+ Common::Array<byte> solvedRiddleIDs;
+ int8 incorrectRiddleID;
+};
+
+PuzzleData *makePuzzleData(const uint32 tag);
+
+} // End of namespace Nancy
+
+#endif // NANCY_PUZZLEDATA_H
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 1964545a7ec..f1ef5a129e7 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -115,11 +115,7 @@ Scene::Scene() :
_difficulty(0),
_activeConversation(nullptr),
_lightning(nullptr),
- _specialEffect(nullptr),
- _sliderPuzzleState(nullptr),
- _rippedLetterPuzzleState(nullptr),
- _towerPuzzleState(nullptr),
- _riddlePuzzleState(nullptr) {}
+ _specialEffect(nullptr) {}
Scene::~Scene() {
delete _helpButton;
@@ -130,10 +126,8 @@ Scene::~Scene() {
delete _clock;
delete _lightning;
delete _specialEffect;
- delete _sliderPuzzleState;
- delete _rippedLetterPuzzleState;
- delete _towerPuzzleState;
- delete _riddlePuzzleState;
+
+ clearPuzzleData();
}
void Scene::process() {
@@ -486,7 +480,7 @@ void Scene::synchronize(Common::Serializer &ser) {
ser.syncAsUint32LE((uint32 &)_timers.pushedPlayTime);
ser.syncAsUint32LE((uint32 &)_timers.timerTime);
ser.syncAsByte(_timers.timerIsActive);
- ser.skip(1); // timeOfDay; To be removed on next savefile version bump
+ ser.skip(1, 0, 2);
g_nancy->setTotalPlayTime((uint32)_timers.lastTotalTime);
@@ -500,79 +494,38 @@ void Scene::synchronize(Common::Serializer &ser) {
ser.syncAsSint16LE(_lastHintCharacter);
ser.syncAsSint16LE(_lastHintID);
- switch (g_nancy->getGameType()) {
- case kGameTypeVampire:
- // Fall through to avoid having to bump the savegame version
- // fall through
- case kGameTypeNancy1: {
- // Synchronize SliderPuzzle static data
- if (!_sliderPuzzleState) {
- return;
- }
-
- ser.syncAsByte(_sliderPuzzleState->playerHasTriedPuzzle);
-
- byte x = 0, y = 0;
-
- if (ser.isSaving()) {
- y = _sliderPuzzleState->playerTileOrder.size();
- if (y) {
- x = _sliderPuzzleState->playerTileOrder.back().size();
- } else {
- x = 0;
- }
- }
-
- ser.syncAsByte(x);
- ser.syncAsByte(y);
+ // Sync game-specific puzzle data
- _sliderPuzzleState->playerTileOrder.resize(y);
-
- for (int i = 0; i < y; ++i) {
- _sliderPuzzleState->playerTileOrder[i].resize(x);
- ser.syncArray(_sliderPuzzleState->playerTileOrder[i].data(), x, Common::Serializer::Sint16LE);
+ // Support for older savefiles
+ if (ser.getVersion() < 3 && g_nancy->getGameType() <= kGameTypeNancy1) {
+ PuzzleData *pd = getPuzzleData(SliderPuzzleData::getTag());
+ if (pd) {
+ pd->synchronize(ser);
}
- break;
+ return;
}
- case kGameTypeNancy2 : {
- if (!_rippedLetterPuzzleState || !_towerPuzzleState || !_riddlePuzzleState) {
- break;
- }
-
- ser.syncAsByte(_rippedLetterPuzzleState->playerHasTriedPuzzle);
-
- if (ser.isLoading()) {
- _rippedLetterPuzzleState->order.resize(24);
- _rippedLetterPuzzleState->rotations.resize(24);
- }
-
- ser.syncArray(_rippedLetterPuzzleState->order.data(), 24, Common::Serializer::Byte);
- ser.syncArray(_rippedLetterPuzzleState->rotations.data(), 24, Common::Serializer::Byte);
- ser.syncAsByte(_towerPuzzleState->playerHasTriedPuzzle);
+ byte numPuzzleData = _puzzleData.size();
+ ser.syncAsByte(numPuzzleData);
- if (ser.isLoading()) {
- _towerPuzzleState->order.resize(3, Common::Array<int8>(6, -1));
- }
-
- for (uint i = 0; i < 3; ++i) {
- ser.syncArray(_towerPuzzleState->order[i].data(), 6, Common::Serializer::Byte);
+ if (ser.isSaving()) {
+ for (auto pd : _puzzleData) {
+ uint32 tag = pd._key;
+ ser.syncAsUint32LE(tag);
+ pd._value->synchronize(ser);
}
-
- byte numRiddles = _riddlePuzzleState->solvedRiddleIDs.size();
- ser.syncAsByte(numRiddles);
-
- if (ser.isLoading()) {
- _riddlePuzzleState->solvedRiddleIDs.resize(numRiddles);
+ } else {
+ clearPuzzleData();
+
+ uint32 tag;
+ for (uint i = 0; i < numPuzzleData; ++i) {
+ ser.syncAsUint32LE(tag);
+ PuzzleData *pd = getPuzzleData(tag);
+ if (pd) {
+ pd->synchronize(ser);
+ }
}
-
- ser.syncArray(_riddlePuzzleState->solvedRiddleIDs.data(), numRiddles, Common::Serializer::Byte);
-
- break;
- }
- default:
- break;
}
}
@@ -604,38 +557,6 @@ void Scene::init() {
_lastHintCharacter = _lastHintID = -1;
}
- // Initialize game-specific data
- switch (g_nancy->getGameType()) {
- case kGameTypeVampire:
- // Fall through to avoid having to bump the savefile version
- // fall through
- case kGameTypeNancy1:
- delete _sliderPuzzleState;
- _sliderPuzzleState = new SliderPuzzleState();
- _sliderPuzzleState->playerHasTriedPuzzle = false;
-
- break;
- case kGameTypeNancy2:
- delete _rippedLetterPuzzleState;
- _rippedLetterPuzzleState = new RippedLetterPuzzleState();
- _rippedLetterPuzzleState->playerHasTriedPuzzle = false;
- _rippedLetterPuzzleState->order.resize(24, 0);
- _rippedLetterPuzzleState->rotations.resize(24, 0);
-
- delete _towerPuzzleState;
- _towerPuzzleState = new TowerPuzzleState();
- _towerPuzzleState->playerHasTriedPuzzle = false;
- _towerPuzzleState->order.resize(3, Common::Array<int8>(6, -1));
-
- delete _riddlePuzzleState;
- _riddlePuzzleState = new RiddlePuzzleState();
- _riddlePuzzleState->incorrectRiddleID = -1;
-
- break;
- default:
- break;
- }
-
initStaticData();
if (ConfMan.hasKey("save_slot")) {
@@ -680,6 +601,22 @@ void Scene::specialEffect(byte type, uint16 fadeToBlackTime, uint16 frameTime) {
_specialEffect->init();
}
+PuzzleData *Scene::getPuzzleData(const uint32 tag) {
+ // Lazy initialization ensures both init() and synchronize() will not need
+ // to care about which puzzles a specific game has
+
+ if (_puzzleData.contains(tag)) {
+ return _puzzleData[tag];
+ } else {
+ PuzzleData *newData = makePuzzleData(tag);
+ if (newData) {
+ _puzzleData.setVal(tag, newData);
+ }
+
+ return newData;
+ }
+}
+
void Scene::load() {
clearSceneData();
@@ -950,5 +887,11 @@ void Scene::clearSceneData() {
}
}
+void Scene::clearPuzzleData() {
+ for (auto &pd : _puzzleData) {
+ delete pd._value;
+ }
+}
+
} // End of namespace State
} // End of namespace Nancy
diff --git a/engines/nancy/state/scene.h b/engines/nancy/state/scene.h
index d6d1926b2e8..da17783563b 100644
--- a/engines/nancy/state/scene.h
+++ b/engines/nancy/state/scene.h
@@ -25,6 +25,7 @@
#include "common/singleton.h"
#include "engines/nancy/commontypes.h"
+#include "engines/nancy/puzzledata.h"
#include "engines/nancy/action/actionmanager.h"
@@ -190,11 +191,8 @@ public:
// Used from nancy2 onwards
void specialEffect(byte type, uint16 fadeToBlackTime, uint16 frameTime);
- // Game-specific data that needs to be saved/loaded
- SliderPuzzleState *_sliderPuzzleState;
- RippedLetterPuzzleState *_rippedLetterPuzzleState;
- TowerPuzzleState *_towerPuzzleState;
- RiddlePuzzleState *_riddlePuzzleState;
+ // Get the persistent data for a given puzzle type
+ PuzzleData *getPuzzleData(const uint32 tag);
private:
void init();
@@ -205,6 +203,7 @@ private:
void initStaticData();
void clearSceneData();
+ void clearPuzzleData();
enum State {
kInit,
@@ -262,6 +261,8 @@ private:
UI::InventoryBoxOrnaments *_inventoryBoxOrnaments;
UI::Clock *_clock;
+ Common::Rect _mapHotspot;
+
// General data
SceneState _sceneState;
PlayFlags _flags;
@@ -275,7 +276,7 @@ private:
Misc::Lightning *_lightning;
Misc::SpecialEffect *_specialEffect;
- Common::Rect _mapHotspot;
+ Common::HashMap<uint32, PuzzleData *> _puzzleData;
Action::ActionManager _actionManager;
Action::ConversationSound *_activeConversation;
More information about the Scummvm-git-logs
mailing list