[Scummvm-git-logs] scummvm master -> 6ba8e586a33bfb03e395d4e86a26d2f95f4d28ce
fracturehill
noreply at scummvm.org
Mon Apr 17 17:29:48 UTC 2023
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
197c2bbd26 NANCY: Implement TowerPuzzle
0faeb96c20 NANCY: Disable RippedLetterPuzzle input after completion
5844495076 NANCY: Clock fixes
6ba8e586a3 NANCY: Fix ShowInventoryItem
Commit: 197c2bbd267981ed820e1b30e19a1c80bfdcd5fc
https://github.com/scummvm/scummvm/commit/197c2bbd267981ed820e1b30e19a1c80bfdcd5fc
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-17T20:27:26+03:00
Commit Message:
NANCY: Implement TowerPuzzle
Implemented the TowerPuzzle action record, which
handles the hanoi tower minigame in nancy2.
Changed paths:
A engines/nancy/action/towerpuzzle.cpp
A engines/nancy/action/towerpuzzle.h
engines/nancy/action/arfactory.cpp
engines/nancy/commontypes.h
engines/nancy/module.mk
engines/nancy/state/scene.cpp
engines/nancy/state/scene.h
diff --git a/engines/nancy/action/arfactory.cpp b/engines/nancy/action/arfactory.cpp
index 74f8f6a8398..ea22ece48f7 100644
--- a/engines/nancy/action/arfactory.cpp
+++ b/engines/nancy/action/arfactory.cpp
@@ -31,6 +31,7 @@
#include "engines/nancy/action/passwordpuzzle.h"
#include "engines/nancy/action/leverpuzzle.h"
#include "engines/nancy/action/rippedletterpuzzle.h"
+#include "engines/nancy/action/towerpuzzle.h"
#include "engines/nancy/state/scene.h"
@@ -144,6 +145,8 @@ ActionRecord *ActionManager::createActionRecord(uint16 type) {
return new PlaySoundMultiHS();
case 160:
return new HintSystem();
+ case 201:
+ return new TowerPuzzle();
case 203:
return new RippedLetterPuzzle();
default:
diff --git a/engines/nancy/action/towerpuzzle.cpp b/engines/nancy/action/towerpuzzle.cpp
new file mode 100644
index 00000000000..06f169b4b69
--- /dev/null
+++ b/engines/nancy/action/towerpuzzle.cpp
@@ -0,0 +1,329 @@
+/* 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/util.h"
+#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/state/scene.h"
+
+#include "engines/nancy/action/towerpuzzle.h"
+
+namespace Nancy {
+namespace Action {
+
+void TowerPuzzle::init() {
+ Common::Rect screenBounds = NancySceneState.getViewport().getBounds();
+ _drawSurface.create(screenBounds.width(), screenBounds.height(), g_nancy->_graphicsManager->getInputPixelFormat());
+ _drawSurface.clear(g_nancy->_graphicsManager->getTransColor());
+ setTransparent(true);
+ setVisible(true);
+ moveTo(screenBounds);
+
+ g_nancy->_resource->loadImage(_imageName, _image);
+ _image.setTransparentColor(_drawSurface.getTransparentColor());
+}
+
+void TowerPuzzle::registerGraphics() {
+ _heldRing.registerGraphics();
+ RenderObject::registerGraphics();
+}
+
+void TowerPuzzle::readData(Common::SeekableReadStream &stream) {
+ _puzzleState = NancySceneState._towerPuzzleState;
+ assert(_puzzleState);
+
+ readFilename(stream, _imageName);
+
+ _numRingsByDifficulty.resize(3);
+ for (uint i = 0; i < 3; ++i) {
+ _numRingsByDifficulty[i] = stream.readUint16LE();
+ }
+
+ stream.skip(2);
+
+ readRectArray(stream, _droppedRingSrcs, 6);
+ readRectArray(stream, _heldRingSrcs, 6);
+
+ readRectArray(stream, _hotspots, 3);
+
+ _destRects.resize(6);
+ for (uint ringID = 0; ringID < 6; ++ringID) {
+ _destRects[ringID].resize(3);
+ for (uint poleID = 0; poleID < 3; ++poleID) {
+ // Biggest ring can only be in bottom position,
+ // so it only has one rect per pole; second-biggest can
+ // be in bottom-most and one position above it, so it has
+ // two rects per pole, etc. Skipped data is array of 0xFF.
+ readRectArray(stream, _destRects[ringID][poleID], ringID + 1);
+ stream.skip((6 - ringID - 1) * 16);
+ }
+ }
+
+ _takeSound.read(stream, SoundDescription::kNormal);
+ _dropSound.read(stream, SoundDescription::kNormal);
+
+ _solveExitScene.readData(stream);
+ stream.skip(2);
+ _solveSound.read(stream, SoundDescription::kNormal);
+ _flagOnSolve.label = stream.readSint16LE();
+ _flagOnSolve.flag = stream.readByte();
+
+ _exitScene.readData(stream);
+ stream.skip(2);
+ _flagOnExit.label = stream.readSint16LE();
+ _flagOnExit.flag = stream.readByte();
+ readRect(stream, _exitHotspot);
+}
+
+void TowerPuzzle::execute() {
+ switch (_state) {
+ case kBegin:
+ init();
+ registerGraphics();
+ _numRings = _numRingsByDifficulty[NancySceneState.getDifficulty()];
+
+ if (!_puzzleState->playerHasTriedPuzzle) {
+ for (uint i = 0; i < _numRings; ++i) {
+ _puzzleState->order[0][i] = i;
+ }
+ _puzzleState->playerHasTriedPuzzle = true;
+ }
+
+ for (uint poleID = 0; poleID < 3; ++poleID) {
+ for (uint pos = 0; pos < _numRings; ++pos) {
+ if (_puzzleState->order[poleID][pos] == -1) {
+ continue;
+ }
+
+ drawRing(poleID, pos, _puzzleState->order[poleID][pos]);
+ }
+ }
+
+ g_nancy->_sound->loadSound(_takeSound);
+ g_nancy->_sound->loadSound(_dropSound);
+
+ _state = kRun;
+ // fall through
+ case kRun:
+ switch (_solveState) {
+ case kNotSolved :
+ for (uint i = 0; i < _numRings; ++i) {
+ // Win condition is valid for both middle and right pole
+ if (_puzzleState->order[1][i] != (int8)i && _puzzleState->order[2][i] != (int8)i) {
+ return;
+ }
+ }
+
+ g_nancy->_sound->loadSound(_solveSound);
+ g_nancy->_sound->playSound(_solveSound);
+ _solveState = kWaitForSound;
+ break;
+ case kWaitForSound :
+ if (!g_nancy->_sound->isSoundPlaying(_solveSound)) {
+ g_nancy->_sound->stopSound(_solveSound);
+ _state = kActionTrigger;
+ }
+
+ break;
+ }
+
+ break;
+ case kActionTrigger :
+ switch (_solveState) {
+ case kNotSolved:
+ NancySceneState.changeScene(_exitScene);
+ NancySceneState.setEventFlag(_flagOnExit);
+ break;
+ case kWaitForSound:
+ NancySceneState.changeScene(_solveExitScene);
+ NancySceneState.setEventFlag(_flagOnSolve);
+ _puzzleState->playerHasTriedPuzzle = false;
+ break;
+ }
+
+ g_nancy->_sound->stopSound(_takeSound);
+ g_nancy->_sound->stopSound(_dropSound);
+ g_nancy->_sound->stopSound(_solveSound);
+ finishExecution();
+ }
+}
+
+void TowerPuzzle::handleInput(NancyInput &input) {
+ if (_state != kRun && _solveState != kNotSolved) {
+ return;
+ }
+
+ // Note: this is a click-and-drag puzzle
+
+ // Check if mouse is above a pole hotspot
+ // and change the cursor if needed
+ int hoveredPoleID = -1;
+ for (uint poleID = 0; poleID < 3; ++poleID) {
+ if (NancySceneState.getViewport().convertViewportToScreen(_hotspots[poleID]).contains(input.mousePos)) {
+ g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
+ hoveredPoleID = poleID;
+ break;
+ }
+ }
+
+ if (_heldRingID == -1) {
+ // Not holding a ring
+
+ // First, check the exit hotspot
+ if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
+ g_nancy->_cursorManager->setCursorType(CursorManager::kExit);
+
+ if (input.input & NancyInput::kLeftMouseButtonUp) {
+ // Player has clicked, exit
+ _state = kActionTrigger;
+ }
+
+ return;
+ }
+
+ // Check if we need to pick up a ring
+ // Behavior is the same as original engine, where clicking outside a hotspot
+ // and dragging the mouse inside while holding the click still triggers
+ if (hoveredPoleID != -1 && (input.input & NancyInput::kLeftMouseButtonHeld)) {
+ // Find the position of the topmost ring
+ int ringPos;
+ for (ringPos = 5; ringPos > -1; --ringPos) {
+ if (_puzzleState->order[hoveredPoleID][ringPos] != -1) {
+ break;
+ }
+ }
+
+ if (ringPos == -1) {
+ // Pole contains no rings, do nothing
+ return;
+ }
+
+ // Redraw so the ring isn't visible anymore
+ drawRing(hoveredPoleID, ringPos, _puzzleState->order[hoveredPoleID][ringPos], true);
+
+ if (ringPos > 0) {
+ drawRing(hoveredPoleID, ringPos - 1, _puzzleState->order[hoveredPoleID][ringPos - 1]);
+ }
+
+ // Change the data
+ SWAP<int8>(_heldRingID, _puzzleState->order[hoveredPoleID][ringPos]);
+ _heldRingPoleID = hoveredPoleID;
+
+ // Show the held ring
+ _heldRing._drawSurface.create(_image, _heldRingSrcs[_heldRingID]);
+ _heldRing.setVisible(true);
+ _heldRing.setTransparent(true);
+
+ g_nancy->_sound->playSound(_takeSound);
+ }
+ }
+
+ if (_heldRingID != -1) {
+ // Holding a ring, check if it has just been dropped
+ if ((input.input & NancyInput::kLeftMouseButtonUp) || !(input.input & NancyInput::kLeftMouseButtonHeld)) {
+ // Check if dropped over a pole hotspot
+ // If not, return to old pole; if yes, move to new one
+ uint returnToPole = hoveredPoleID == -1 ? _heldRingPoleID : hoveredPoleID;
+
+ // Find the new position of the ring
+ uint newPos;
+ for (newPos = 0; newPos < 6; ++newPos) {
+ if (_puzzleState->order[returnToPole][newPos] == -1) {
+ break;
+ }
+ }
+
+ // Make sure the player can't place a larger ring on top of a smaller one
+ if (newPos > 0 && _puzzleState->order[returnToPole][newPos - 1] > _heldRingID) {
+ returnToPole = _heldRingPoleID;
+
+ for (newPos = 0; newPos < 6; ++newPos) {
+ if (_puzzleState->order[returnToPole][newPos] == -1) {
+ break;
+ }
+ }
+ }
+
+ // Draw the new ring in its place
+ drawRing(returnToPole, newPos, _heldRingID);
+
+ // Change the data
+ SWAP<int8>(_heldRingID, _puzzleState->order[returnToPole][newPos]);
+ _heldRingPoleID = -1;
+
+ g_nancy->_sound->playSound(_dropSound);
+
+ // Hide the held ring
+ _heldRing.setVisible(false);
+ } else {
+ // Still holding the ring, move under mouse
+
+ Common::Rect viewport = NancySceneState.getViewport().getScreenPosition();
+
+ // Do not move ring if mouse is outside viewport
+ if (!viewport.contains(input.mousePos)) {
+ return;
+ }
+
+ Common::Rect newScreenPos = _heldRingSrcs[_heldRingID];
+ newScreenPos.moveTo(input.mousePos);
+ newScreenPos.translate(-newScreenPos.width() / 2, -newScreenPos.height() / 2);
+
+ // Center of ring is at top left of cursor
+ const Common::Point &cursorHotspot = g_nancy->_cursorManager->getCurrentCursorHotspot();
+ newScreenPos.translate(-cursorHotspot.x, -cursorHotspot.y);
+
+ // Clip movement so the ring stays entirely inside the viewport
+ if (newScreenPos.left < viewport.left) {
+ newScreenPos.translate(viewport.left - newScreenPos.left, 0);
+ } else if (newScreenPos.right > viewport.right) {
+ newScreenPos.translate(viewport.right - newScreenPos.right, 0);
+ }
+
+ if (newScreenPos.top < viewport.top) {
+ newScreenPos.translate(0, viewport.top - newScreenPos.top);
+ } else if (newScreenPos.bottom > viewport.bottom) {
+ newScreenPos.translate(0, viewport.bottom - newScreenPos.bottom);
+ }
+
+ _heldRing.moveTo(newScreenPos);
+ }
+ }
+}
+
+void TowerPuzzle::drawRing(uint poleID, uint position, uint ringID, bool clear) {
+ _needsRedraw = true;
+
+ if (clear) {
+ // Just clear the ring, leaving a hole in the surface
+ // that needs to be filled by redrawing the ring below
+ _drawSurface.fillRect(_destRects[ringID][poleID][position], _drawSurface.getTransparentColor());
+ return;
+ }
+
+ _drawSurface.blitFrom(_image, _droppedRingSrcs[ringID], _destRects[ringID][poleID][position]);
+}
+
+} // End of namespace Action
+} // End of namespace Nancy
diff --git a/engines/nancy/action/towerpuzzle.h b/engines/nancy/action/towerpuzzle.h
new file mode 100644
index 00000000000..653d0c4a661
--- /dev/null
+++ b/engines/nancy/action/towerpuzzle.h
@@ -0,0 +1,82 @@
+/* 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_TOWERIPPEDLETTERPUZZLE_H
+#define NANCY_ACTION_TOWERIPPEDLETTERPUZZLE_H
+
+#include "engines/nancy/renderobject.h"
+#include "engines/nancy/action/actionrecord.h"
+
+namespace Nancy {
+namespace Action {
+
+class TowerPuzzle : public ActionRecord, public RenderObject {
+public:
+ enum SolveState { kNotSolved, kWaitForSound };
+ TowerPuzzle() : RenderObject(7), _heldRing(8) {}
+ virtual ~TowerPuzzle() {}
+
+ void init() override;
+ void registerGraphics() override;
+ void readData(Common::SeekableReadStream &stream) override;
+ void execute() override;
+ void handleInput(NancyInput &input) override;
+
+protected:
+ Common::String getRecordTypeName() const override { return "TowerPuzzle"; }
+ bool isViewportRelative() const override { return true; }
+
+ void drawRing(uint poleID, uint position, uint ringID, bool clear = false);
+
+ Common::String _imageName;
+ Common::Array<uint16> _numRingsByDifficulty;
+ // 2 unknown
+ Common::Array<Common::Rect> _droppedRingSrcs; // 6
+ Common::Array<Common::Rect> _heldRingSrcs; // 6
+
+ Common::Array<Common::Rect> _hotspots; // 3
+
+ Common::Array<Common::Array<Common::Array<Common::Rect>>> _destRects; // [ringID][poleID][position]
+
+ SoundDescription _takeSound;
+ SoundDescription _dropSound;
+
+ SceneChangeDescription _solveExitScene;
+ SoundDescription _solveSound;
+ FlagDescription _flagOnSolve;
+
+ SceneChangeDescription _exitScene;
+ FlagDescription _flagOnExit;
+ Common::Rect _exitHotspot;
+
+ Graphics::ManagedSurface _image;
+ RenderObject _heldRing;
+ int8 _heldRingID = -1;
+ int8 _heldRingPoleID = -1;
+ SolveState _solveState = kNotSolved;
+ TowerPuzzleState *_puzzleState;
+ uint _numRings = 0;
+};
+
+} // End of namespace Action
+} // End of namespace Nancy
+
+#endif // NANCY_ACTION_TOWERIPPEDLETTERPUZZLE_H
diff --git a/engines/nancy/commontypes.h b/engines/nancy/commontypes.h
index b8b46865fbe..8254ebc92ff 100644
--- a/engines/nancy/commontypes.h
+++ b/engines/nancy/commontypes.h
@@ -252,6 +252,11 @@ struct RippedLetterPuzzleState {
bool playerHasTriedPuzzle;
};
+struct TowerPuzzleState {
+ Common::Array<Common::Array<int8>> order;
+ bool playerHasTriedPuzzle;
+};
+
} // End of namespace Nancy
#endif // NANCY_COMMONYPES_H
diff --git a/engines/nancy/module.mk b/engines/nancy/module.mk
index fb96c90b751..44c6f1a2f2b 100644
--- a/engines/nancy/module.mk
+++ b/engines/nancy/module.mk
@@ -14,6 +14,7 @@ MODULE_OBJS = \
action/secondarymovie.o \
action/secondaryvideo.o \
action/sliderpuzzle.o \
+ action/towerpuzzle.o \
action/overlay.o \
action/telephone.o \
ui/fullscreenimage.o \
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 4c2e9fc2069..10ef1e63b06 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -115,7 +115,8 @@ Scene::Scene() :
_activeConversation(nullptr),
_lightning(nullptr),
_sliderPuzzleState(nullptr),
- _rippedLetterPuzzleState(nullptr) {}
+ _rippedLetterPuzzleState(nullptr),
+ _towerPuzzleState(nullptr) {}
Scene::~Scene() {
delete _helpButton;
@@ -502,7 +503,7 @@ void Scene::synchronize(Common::Serializer &ser) {
break;
}
case kGameTypeNancy2 :
- if (!_rippedLetterPuzzleState) {
+ if (!_rippedLetterPuzzleState || !_towerPuzzleState) {
break;
}
@@ -516,6 +517,16 @@ void Scene::synchronize(Common::Serializer &ser) {
ser.syncArray(_rippedLetterPuzzleState->order.data(), 24, Common::Serializer::Byte);
ser.syncArray(_rippedLetterPuzzleState->rotations.data(), 24, Common::Serializer::Byte);
+ ser.syncAsByte(_towerPuzzleState->playerHasTriedPuzzle);
+
+ 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);
+ }
+
break;
default:
break;
@@ -566,6 +577,12 @@ void Scene::init() {
_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));
+ break;
default:
break;
}
diff --git a/engines/nancy/state/scene.h b/engines/nancy/state/scene.h
index 0394a63f7f9..9a2a4e3c4d0 100644
--- a/engines/nancy/state/scene.h
+++ b/engines/nancy/state/scene.h
@@ -47,7 +47,6 @@ class NancyConsole;
struct SceneChangeDescription;
namespace Action {
-class SliderPuzzle;
class ConversationSound;
}
@@ -189,6 +188,7 @@ public:
// Game-specific data that needs to be saved/loaded
SliderPuzzleState *_sliderPuzzleState;
RippedLetterPuzzleState *_rippedLetterPuzzleState;
+ TowerPuzzleState *_towerPuzzleState;
private:
void init();
Commit: 0faeb96c206300d71f1a3649fe8a0ee60a16d421
https://github.com/scummvm/scummvm/commit/0faeb96c206300d71f1a3649fe8a0ee60a16d421
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-17T20:27:26+03:00
Commit Message:
NANCY: Disable RippedLetterPuzzle input after completion
Changed paths:
engines/nancy/action/rippedletterpuzzle.cpp
diff --git a/engines/nancy/action/rippedletterpuzzle.cpp b/engines/nancy/action/rippedletterpuzzle.cpp
index bc0f273a84f..efd4ae0f186 100644
--- a/engines/nancy/action/rippedletterpuzzle.cpp
+++ b/engines/nancy/action/rippedletterpuzzle.cpp
@@ -173,6 +173,10 @@ void RippedLetterPuzzle::execute() {
}
void RippedLetterPuzzle::handleInput(NancyInput &input) {
+ if (_state != kRun && _solveState != kNotSolved) {
+ return;
+ }
+
for (uint i = 0; i < 24; ++i) {
Common::Rect screenHotspot = NancySceneState.getViewport().convertViewportToScreen(_destRects[i]);
if (screenHotspot.contains(input.mousePos)) {
Commit: 5844495076fd967b0d4d78ae526b0a544b8ad671
https://github.com/scummvm/scummvm/commit/5844495076fd967b0d4d78ae526b0a544b8ad671
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-17T20:27:27+03:00
Commit Message:
NANCY: Clock fixes
Added highlight and fixed input issues.
Changed paths:
engines/nancy/enginedata.cpp
engines/nancy/enginedata.h
engines/nancy/state/scene.cpp
engines/nancy/ui/animatedbutton.cpp
engines/nancy/ui/animatedbutton.h
engines/nancy/ui/clock.cpp
diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index 70000e708e6..7afb3ca34fa 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -51,9 +51,10 @@ BSUM::BSUM(Common::SeekableReadStream *chunkStream) {
s.skip(4, kGameTypeNancy3);
s.skip(8, kGameTypeVampire, kGameTypeVampire);
- readRect(s, mapButtonHotspot, kGameTypeVampire, kGameTypeVampire);
- readRect(s, clockHotspot, kGameTypeNancy2);
- s.skip(0x10);
+ readRect(s, extraButtonHotspot, kGameTypeVampire, kGameTypeVampire);
+ readRect(s, extraButtonHotspot, kGameTypeNancy2);
+ readRect(s, extraButtonHighlightDest, kGameTypeNancy1);
+ s.skip(0x10, kGameTypeVampire, kGameTypeVampire);
readRect(s, textboxScreenPosition);
readRect(s, inventoryBoxScreenPosition);
readRect(s, menuButtonSrc);
diff --git a/engines/nancy/enginedata.h b/engines/nancy/enginedata.h
index c1bfb1c4fbc..1394ee1836c 100644
--- a/engines/nancy/enginedata.h
+++ b/engines/nancy/enginedata.h
@@ -39,8 +39,8 @@ struct BSUM {
uint16 startTimeMinutes;
// UI
- Common::Rect mapButtonHotspot;
- Common::Rect clockHotspot;
+ Common::Rect extraButtonHotspot; // Extra button is map in tvd, clock in nancy2 and up
+ Common::Rect extraButtonHighlightDest;
Common::Rect textboxScreenPosition;
Common::Rect inventoryBoxScreenPosition;
Common::Rect menuButtonSrc;
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 10ef1e63b06..18d09a7729d 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -832,7 +832,7 @@ void Scene::initStaticData() {
assert(bsum);
if (g_nancy->getGameType() == kGameTypeVampire) {
- _mapHotspot = bsum->mapButtonHotspot;
+ _mapHotspot = bsum->extraButtonHotspot;
} else if (g_nancy->_mapData) {
_mapHotspot = g_nancy->_mapData->buttonDest;
}
diff --git a/engines/nancy/ui/animatedbutton.cpp b/engines/nancy/ui/animatedbutton.cpp
index b8f1453012e..2b395e14b96 100644
--- a/engines/nancy/ui/animatedbutton.cpp
+++ b/engines/nancy/ui/animatedbutton.cpp
@@ -72,9 +72,14 @@ void AnimatedButton::handleInput(NancyInput &input) {
g_nancy->_cursorManager->setCursorType(g_nancy->getGameType() == kGameTypeVampire ? CursorManager::kHotspot : CursorManager::kHotspotArrow);
}
+ if (isPlaying()) {
+ return;
+ }
+
if (!_highlightSrcRect.isEmpty() && !isVisible()) {
_drawSurface.create(g_nancy->_graphicsManager->_object0, _highlightSrcRect);
- moveTo(_hotspot);
+ moveTo(_highlightDestRect);
+ setVisible(true);
}
if (input.input & NancyInput::kLeftMouseButtonUp) {
@@ -87,7 +92,12 @@ void AnimatedButton::handleInput(NancyInput &input) {
}
}
- input.eatMouseInput();
+ // This breaks TowerPuzzle in nancy2, so we only enable it for TVD
+ if (g_nancy->getGameType() == kGameTypeVampire) {
+ input.eatMouseInput();
+ }
+ } else if (!_highlightSrcRect.isEmpty() && isVisible() && !(isPlaying() || _isOpen)) {
+ setVisible(false);
}
}
diff --git a/engines/nancy/ui/animatedbutton.h b/engines/nancy/ui/animatedbutton.h
index b5c7f7eb8a4..21b467072d2 100644
--- a/engines/nancy/ui/animatedbutton.h
+++ b/engines/nancy/ui/animatedbutton.h
@@ -50,6 +50,7 @@ protected:
Common::Array<Common::Rect> _srcRects;
Common::Array<Common::Rect> _destRects;
Common::Rect _highlightSrcRect;
+ Common::Rect _highlightDestRect;
uint32 _frameTime;
bool _alwaysHighlightCursor;
diff --git a/engines/nancy/ui/clock.cpp b/engines/nancy/ui/clock.cpp
index c44c8aee51d..71487abc59a 100644
--- a/engines/nancy/ui/clock.cpp
+++ b/engines/nancy/ui/clock.cpp
@@ -66,6 +66,7 @@ void Clock::init() {
_staticImage.setTransparent(g_nancy->getGameType() == kGameTypeVampire);
_animation.setTransparent(true);
+ _animation.setVisible(false);
if (g_nancy->getGameType() == kGameTypeVampire) {
GraphicsManager::loadSurfacePalette(_drawSurface, "OBJECT0");
}
@@ -98,9 +99,7 @@ void Clock::updateGraphics() {
}
void Clock::handleInput(NancyInput &input) {
- if (!_animation.isPlaying()) {
- _animation.handleInput(input);
- }
+ _animation.handleInput(input);
}
void Clock::drawClockHands() {
@@ -125,9 +124,11 @@ void Clock::drawClockHands() {
void Clock::ClockAnim::init() {
_srcRects = _owner->_clockData->animSrcs;
_destRects = _owner->_clockData->animDests;
+ _highlightSrcRect = g_nancy->_bootSummary->clockHighlightSrc;
+ _highlightDestRect = g_nancy->_bootSummary->extraButtonHighlightDest;
if (_destRects.size()) {
- moveTo(g_nancy->_bootSummary->clockHotspot);
+ moveTo(g_nancy->_bootSummary->extraButtonHotspot);
} else {
moveTo(_owner->_clockData->screenPosition);
}
Commit: 6ba8e586a33bfb03e395d4e86a26d2f95f4d28ce
https://github.com/scummvm/scummvm/commit/6ba8e586a33bfb03e395d4e86a26d2f95f4d28ce
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-17T20:27:28+03:00
Commit Message:
NANCY: Fix ShowInventoryItem
Fixed a data reading error in ShowInventoryItem that
would crash nancy2.
Changed paths:
engines/nancy/action/overlay.cpp
engines/nancy/action/recordtypes.cpp
engines/nancy/commontypes.cpp
engines/nancy/commontypes.h
diff --git a/engines/nancy/action/overlay.cpp b/engines/nancy/action/overlay.cpp
index 52d5714a175..64397d52a68 100644
--- a/engines/nancy/action/overlay.cpp
+++ b/engines/nancy/action/overlay.cpp
@@ -96,7 +96,7 @@ void Overlay::readData(Common::SeekableReadStream &stream) {
_bitmaps.resize(numViewportFrames);
for (auto &bm : _bitmaps) {
- bm.readData(stream);
+ bm.readData(stream, ser.getVersion() >= kGameTypeNancy2);
}
}
diff --git a/engines/nancy/action/recordtypes.cpp b/engines/nancy/action/recordtypes.cpp
index 40824c4da96..e62854877e9 100644
--- a/engines/nancy/action/recordtypes.cpp
+++ b/engines/nancy/action/recordtypes.cpp
@@ -496,9 +496,8 @@ void ShowInventoryItem::readData(Common::SeekableReadStream &stream) {
uint16 numFrames = stream.readUint16LE();
- _bitmaps.reserve(numFrames);
+ _bitmaps.resize(numFrames);
for (uint i = 0; i < numFrames; ++i) {
- _bitmaps.push_back(BitmapDescription());
_bitmaps[i].readData(stream);
}
}
diff --git a/engines/nancy/commontypes.cpp b/engines/nancy/commontypes.cpp
index 9d492d2b77d..7893e4e313c 100644
--- a/engines/nancy/commontypes.cpp
+++ b/engines/nancy/commontypes.cpp
@@ -43,8 +43,8 @@ void HotspotDescription::readData(Common::SeekableReadStream &stream) {
readRect(stream, coords);
}
-void BitmapDescription::readData(Common::SeekableReadStream &stream) {
- if (g_nancy->getGameType() <= kGameTypeNancy1) {
+void BitmapDescription::readData(Common::SeekableReadStream &stream, bool frameIsLong) {
+ if (!frameIsLong) {
frameID = stream.readUint16LE();
} else {
frameID = stream.readUint32LE();
diff --git a/engines/nancy/commontypes.h b/engines/nancy/commontypes.h
index 8254ebc92ff..5aca4bb77ff 100644
--- a/engines/nancy/commontypes.h
+++ b/engines/nancy/commontypes.h
@@ -142,7 +142,7 @@ struct BitmapDescription {
Common::Rect src;
Common::Rect dest;
- void readData(Common::SeekableReadStream &stream);
+ void readData(Common::SeekableReadStream &stream, bool frameIsLong = false);
};
// Describes 10 event flag changes to be executed when an action is triggered
More information about the Scummvm-git-logs
mailing list