[Scummvm-git-logs] scummvm master -> a5b1143fc663b2e4fb9a903e82d5829d20b8c7ee

fracturehill noreply at scummvm.org
Thu Aug 24 09:51:06 UTC 2023


This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
4c5d0d2299 NANCY: Silence warnings
0ec7f97605 NANCY: Add getters for sound rate and volume
452e259281 NANCY: Implement kRandom dependency type
bc12fbf01c NANCY: Implement PianoPuzzle
a5b1143fc6 NANCY: Add workaround for broken video


Commit: 4c5d0d2299f4488c05847d6c1e9432954da75370
    https://github.com/scummvm/scummvm/commit/4c5d0d2299f4488c05847d6c1e9432954da75370
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-24T12:47:50+03:00

Commit Message:
NANCY: Silence warnings

Fixed several small issues that caused compiler and/or
Coverity warnings.

Changed paths:
    engines/nancy/action/bombpuzzle.h
    engines/nancy/action/overlay.cpp
    engines/nancy/action/raycastpuzzle.h
    engines/nancy/action/riddlepuzzle.h
    engines/nancy/action/secondarymovie.cpp
    engines/nancy/action/secondaryvideo.cpp
    engines/nancy/action/setplayerclock.h
    engines/nancy/action/soundequalizerpuzzle.h
    engines/nancy/enginedata.cpp
    engines/nancy/graphics.cpp
    engines/nancy/state/scene.cpp


diff --git a/engines/nancy/action/bombpuzzle.h b/engines/nancy/action/bombpuzzle.h
index a0b2a6d52a9..3d40ffd2ebe 100644
--- a/engines/nancy/action/bombpuzzle.h
+++ b/engines/nancy/action/bombpuzzle.h
@@ -54,7 +54,7 @@ protected:
 	Common::Array<byte> _solveOrder;
 	SoundDescription _snipSound;
 	SoundDescription _noToolSound;
-	uint16 _toolID;
+	uint16 _toolID = 0;
 	SceneChangeWithFlag _solveSceneChange;
 	SoundDescription _solveSound;
 	SceneChangeWithFlag _failSceneChange;
diff --git a/engines/nancy/action/overlay.cpp b/engines/nancy/action/overlay.cpp
index bfd530670b8..169eca49305 100644
--- a/engines/nancy/action/overlay.cpp
+++ b/engines/nancy/action/overlay.cpp
@@ -45,7 +45,7 @@ void Overlay::readData(Common::SeekableReadStream &stream) {
 	Common::Serializer ser(&stream, nullptr);
 	ser.setVersion(g_nancy->getGameType());
 
-	uint16 numSrcRects;
+	uint16 numSrcRects = 0;
 
 	readFilename(ser, _imageName);
 	ser.skip(2, kGameTypeVampire, kGameTypeNancy2);
diff --git a/engines/nancy/action/raycastpuzzle.h b/engines/nancy/action/raycastpuzzle.h
index e843392eb0d..a8e35733f30 100644
--- a/engines/nancy/action/raycastpuzzle.h
+++ b/engines/nancy/action/raycastpuzzle.h
@@ -103,13 +103,13 @@ protected:
 
 	int32 _playerX = -1;				// Player position with precision 1/128th of cell width/height
 	int32 _playerY = -1;
-	int32 _playerRotation; 				// Rotation of player (0 - 4096)
+	int32 _playerRotation = 0; 			// Rotation of player (0 - 4096)
 	uint32 _playerAltitude = 88;		// Z position of "camera"; only modified in god mode
 
 	float _rotationSingleStep = 4096.0 / (_pi * 2);
-	float _maxWorldDistance;
+	float _maxWorldDistance = 0.0;
 
-	uint32 _lastMovementTime;
+	uint32 _lastMovementTime = 0;
 	int _lastMouseX = -1;
 
 	uint32 _nextSlowdownMovementTime = 0;
diff --git a/engines/nancy/action/riddlepuzzle.h b/engines/nancy/action/riddlepuzzle.h
index f347a3e16c7..a56ceae54c5 100644
--- a/engines/nancy/action/riddlepuzzle.h
+++ b/engines/nancy/action/riddlepuzzle.h
@@ -58,8 +58,8 @@ protected:
 
 	void drawText();
 
-	uint16 _viewportTextFontID;
-	uint16 _textboxTextFontID;
+	uint16 _viewportTextFontID = 0;
+	uint16 _textboxTextFontID = 0;
 	Time _cursorBlinkTime;
 	SoundDescription _typeSound;
 	SoundDescription _eraseSound;
diff --git a/engines/nancy/action/secondarymovie.cpp b/engines/nancy/action/secondarymovie.cpp
index 934f09c0b0b..4f914855bea 100644
--- a/engines/nancy/action/secondarymovie.cpp
+++ b/engines/nancy/action/secondarymovie.cpp
@@ -77,7 +77,7 @@ void PlaySecondaryMovie::readData(Common::SeekableReadStream &stream) {
 	_sound.readNormal(stream);
 	_sceneChange.readData(stream, ser.getVersion() == kGameTypeVampire);
 
-	uint16 numVideoDescs;
+	uint16 numVideoDescs = 0;
 	ser.syncAsUint16LE(numVideoDescs);
 	_videoDescs.resize(numVideoDescs);
 	for (uint i = 0; i < numVideoDescs; ++i) {
diff --git a/engines/nancy/action/secondaryvideo.cpp b/engines/nancy/action/secondaryvideo.cpp
index 953bc3ceadc..0f4b372ca2e 100644
--- a/engines/nancy/action/secondaryvideo.cpp
+++ b/engines/nancy/action/secondaryvideo.cpp
@@ -178,7 +178,7 @@ void PlaySecondaryVideo::readData(Common::SeekableReadStream &stream) {
 	_sceneChange.readData(stream, ser.getVersion() == kGameTypeVampire);
 	ser.skip(1, kGameTypeNancy1);
 
-	uint16 numVideoDescs;
+	uint16 numVideoDescs = 0;
 	ser.syncAsUint16LE(numVideoDescs);
 	_videoDescs.resize(numVideoDescs);
 	for (uint i = 0; i < numVideoDescs; ++i) {
diff --git a/engines/nancy/action/setplayerclock.h b/engines/nancy/action/setplayerclock.h
index d0eb9ae2fb8..b5afa712119 100644
--- a/engines/nancy/action/setplayerclock.h
+++ b/engines/nancy/action/setplayerclock.h
@@ -74,7 +74,7 @@ protected:
 
 	SoundDescription _buttonSound;
 	SceneChangeWithFlag _alarmSetScene;
-	uint16 _alarmSoundDelay;
+	uint16 _alarmSoundDelay = 0;
 	SoundDescription _alarmRingSound; // NO SOUND in MHM
 	SceneChangeWithFlag _exitScene;
 
diff --git a/engines/nancy/action/soundequalizerpuzzle.h b/engines/nancy/action/soundequalizerpuzzle.h
index 25df8896d10..2f28eb9e4de 100644
--- a/engines/nancy/action/soundequalizerpuzzle.h
+++ b/engines/nancy/action/soundequalizerpuzzle.h
@@ -70,11 +70,11 @@ public:
 	Common::Array<uint16> _minRate;
 	Common::Array<uint16> _maxRate;
 
-	uint16 _solveChannelID;
-	uint16 _solveMinVolume;
-	uint16 _solveMaxVolume;
-	uint16 _solveMinRate;
-	uint16 _solveMaxRate;
+	uint16 _solveChannelID = 0;
+	uint16 _solveMinVolume = 0;
+	uint16 _solveMaxVolume = 0;
+	uint16 _solveMinRate = 0;
+	uint16 _solveMaxRate = 0;
 
 	SceneChangeDescription _exitScene;
 	SoundDescription _exitSound;
diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index 975287e107a..31645cbaed3 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -358,8 +358,9 @@ HINT::HINT(Common::SeekableReadStream *chunkStream) {
 	assert(chunkStream);
 
 	chunkStream->seek(0);
-	numHints.resize(chunkStream->size());
-	for (uint i = 0; i < numHints.size(); ++i) {
+	uint size = chunkStream->size();
+	numHints.resize(size);
+	for (uint i = 0; i < size; ++i) {
 		numHints[i] = chunkStream->readByte();
 	}
 
diff --git a/engines/nancy/graphics.cpp b/engines/nancy/graphics.cpp
index 591d726c1a8..f9b58605ced 100644
--- a/engines/nancy/graphics.cpp
+++ b/engines/nancy/graphics.cpp
@@ -271,7 +271,7 @@ void GraphicsManager::copyToManaged(void *src, Graphics::ManagedSurface &dst, ui
 void GraphicsManager::rotateBlit(const Graphics::ManagedSurface &src, Graphics::ManagedSurface &dest, byte rotation) {
 	assert(!src.empty() && !dest.empty());
 	assert(src.w == src.h && src.h == dest.w && dest.w == dest.h);
-	assert(rotation >= 0 && rotation <= 3);
+	assert(rotation <= 3);
 	assert(src.format.bytesPerPixel == 2 && dest.format.bytesPerPixel == 2);
 
 	uint size = src.w;
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 68c2d73fae3..6f755a712bb 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -343,8 +343,11 @@ void Scene::setLogicCondition(int16 label, byte flag) {
 			// In nancy3 and onwards logic conditions begin from 2000
 			label -= 2000;
 		}
-		_flags.logicConditions[label].flag = flag;
-		_flags.logicConditions[label].timestamp = g_nancy->getTotalPlayTime();
+
+		if (label > kEvNoEvent && (uint)label < 30) {
+			_flags.logicConditions[label].flag = flag;
+			_flags.logicConditions[label].timestamp = g_nancy->getTotalPlayTime();
+		}
 	}
 }
 
@@ -496,7 +499,8 @@ void Scene::synchronize(Common::Serializer &ser) {
 			ser.syncAsUint16LE(entry._value);
 		}
 	} else {
-		uint16 key, val;
+		uint16 key = 0;
+		uint16 val = 0;
 		for (uint i = 0; i < numSceneCounts; ++i) {
 			ser.syncAsUint16LE(key);
 			ser.syncAsUint16LE(val);
@@ -526,7 +530,7 @@ void Scene::synchronize(Common::Serializer &ser) {
 	ser.syncAsByte(numPuzzleData);
 
 	if (ser.isSaving()) {
-		for (auto pd : _puzzleData) {
+		for (auto &pd : _puzzleData) {
 			uint32 tag = pd._key;
 			ser.syncAsUint32LE(tag);
 			pd._value->synchronize(ser);
@@ -534,7 +538,7 @@ void Scene::synchronize(Common::Serializer &ser) {
 	} else {
 		clearPuzzleData();
 
-		uint32 tag;
+		uint32 tag = 0;
 		for (uint i = 0; i < numPuzzleData; ++i) {
 			ser.syncAsUint32LE(tag);
 			PuzzleData *pd = getPuzzleData(tag);


Commit: 0ec7f976054cb7bea5ca97e48b94d0ed1a8df1bf
    https://github.com/scummvm/scummvm/commit/0ec7f976054cb7bea5ca97e48b94d0ed1a8df1bf
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-24T12:47:50+03:00

Commit Message:
NANCY: Add getters for sound rate and volume

Changed paths:
    engines/nancy/sound.cpp
    engines/nancy/sound.h


diff --git a/engines/nancy/sound.cpp b/engines/nancy/sound.cpp
index 1d59397b554..d6a8d826bf9 100644
--- a/engines/nancy/sound.cpp
+++ b/engines/nancy/sound.cpp
@@ -461,29 +461,96 @@ void SoundManager::stopSound(const Common::String &chunkName) {
 }
 
 void SoundManager::stopAllSounds() {
-	for (uint i = 0; i < 31; ++i) {
+	for (uint i = 0; i < _channels.size(); ++i) {
 		stopSound(i);
 	}
 }
 
+byte SoundManager::getVolume(uint16 channelID) {
+	if (channelID >= _channels.size())
+		return 0;
+
+	return _mixer->getChannelVolume(_channels[channelID].handle);
+}
+
+byte SoundManager::getVolume(const SoundDescription &description) {
+	if (description.name != "NO SOUND") {
+		return getVolume(description.channelID);
+	}
+	
+	return 0;
+}
+
+byte SoundManager::getVolume(const Common::String &chunkName) {
+	return getVolume(_commonSounds[chunkName]);
+}
+
 void SoundManager::setVolume(uint16 channelID, uint16 volume) {
+	if (channelID >= _channels.size())
+		return;
+
 	_mixer->setChannelVolume(_channels[channelID].handle, volume);
 }
 
 void SoundManager::setVolume(const SoundDescription &description, uint16 volume) {
-	setVolume(description.channelID, volume);
+	if (description.name != "NO SOUND") {
+		setVolume(description.channelID, volume);
+	}
 }
 
 void SoundManager::setVolume(const Common::String &chunkName, uint16 volume) {
 	setVolume(_commonSounds[chunkName], volume);
 }
 
+uint32 SoundManager::getRate(uint16 channelID) {
+	if (channelID >= _channels.size())
+		return 0;
+	
+	return _mixer->getChannelRate(_channels[channelID].handle);
+}
+
+uint32 SoundManager::getRate(const SoundDescription &description) {
+	if (description.name != "NO SOUND") {
+		return getRate(description.channelID);
+	}
+
+	return 0;
+}
+
+uint32 SoundManager::getRate(const Common::String &chunkName) {
+	return getRate(_commonSounds[chunkName]);
+}
+
+uint32 SoundManager::getBaseRate(uint16 channelID) {
+	if (channelID >= _channels.size() || !_channels[channelID].stream)
+		return 0;
+	
+	return _channels[channelID].stream->getRate();
+}
+
+uint32 SoundManager::getBaseRate(const SoundDescription &description) {
+	if (description.name != "NO SOUND") {
+		return getBaseRate(description.channelID);
+	}
+
+	return 0;
+}
+
+uint32 SoundManager::getBaseRate(const Common::String &chunkName) {
+	return getBaseRate(_commonSounds[chunkName]);
+}
+
 void SoundManager::setRate(uint16 channelID, uint32 rate) {
+	if (channelID >= _channels.size())
+		return;
+
 	_mixer->setChannelRate(_channels[channelID].handle, rate);
 }
 
 void SoundManager::setRate(const SoundDescription &description, uint32 rate) {
-	setRate(description.channelID, rate);
+	if (description.name != "NO SOUND") {
+		setRate(description.channelID, rate);
+	}
 }
 
 void SoundManager::setRate(const Common::String &chunkName, uint32 rate) {
diff --git a/engines/nancy/sound.h b/engines/nancy/sound.h
index d4c87e0e285..9a05398a486 100644
--- a/engines/nancy/sound.h
+++ b/engines/nancy/sound.h
@@ -93,10 +93,22 @@ public:
 	void stopSound(const Common::String &chunkName);
 	void stopAllSounds();
 
+	byte getVolume(uint16 channelID);
+	byte getVolume(const SoundDescription &description);
+	byte getVolume(const Common::String &chunkName);
+
 	void setVolume(uint16 channelID, uint16 volume);
 	void setVolume(const SoundDescription &description, uint16 volume);
 	void setVolume(const Common::String &chunkName, uint16 volume);
 
+	uint32 getRate(uint16 channelID);
+	uint32 getRate(const SoundDescription &description);
+	uint32 getRate(const Common::String &chunkName);
+
+	uint32 getBaseRate(uint16 channelID);
+	uint32 getBaseRate(const SoundDescription &description);
+	uint32 getBaseRate(const Common::String &chunkName);
+
 	void setRate(uint16 channelID, uint32 rate);
 	void setRate(const SoundDescription &description, uint32 rate);
 	void setRate(const Common::String &chunkName, uint32 rate);


Commit: 452e25928141babfce93c3ecc6c379dc7e3a8d41
    https://github.com/scummvm/scummvm/commit/452e25928141babfce93c3ecc6c379dc7e3a8d41
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-24T12:47:50+03:00

Commit Message:
NANCY: Implement kRandom dependency type

Implemented the random dependency type, which evaluates
to true or false based on random chance.

Changed paths:
    engines/nancy/action/actionmanager.cpp
    engines/nancy/action/actionrecord.h
    engines/nancy/console.cpp


diff --git a/engines/nancy/action/actionmanager.cpp b/engines/nancy/action/actionmanager.cpp
index d09732141a1..8111e6e5acf 100644
--- a/engines/nancy/action/actionmanager.cpp
+++ b/engines/nancy/action/actionmanager.cpp
@@ -22,6 +22,7 @@
 #include "common/serializer.h"
 #include "common/stack.h"
 #include "common/config-manager.h"
+#include "common/random.h"
 
 #include "engines/nancy/nancy.h"
 #include "engines/nancy/input.h"
@@ -464,6 +465,18 @@ void ActionManager::processDependency(DependencyRecord &dep, ActionRecord &recor
 				dep.satisfied = dep.condition == 0;
 			}
 
+			break;
+		case DependencyType::kRandom:
+			// Pick a random number and compare it with the value in condition
+			// This is only executed once
+			if (!dep.stopEvaluating) {
+				if ((int)g_nancy->_randomSource->getRandomNumber(99) < dep.condition) {
+					dep.satisfied = true;
+				}
+
+				dep.stopEvaluating = true;
+			}
+
 			break;
 		default:
 			warning("Unimplemented Dependency type %i", (int)dep.type);
diff --git a/engines/nancy/action/actionrecord.h b/engines/nancy/action/actionrecord.h
index 70020605386..9ed7c21c653 100644
--- a/engines/nancy/action/actionrecord.h
+++ b/engines/nancy/action/actionrecord.h
@@ -59,7 +59,8 @@ enum struct DependencyType : int16 {
 	kClosedCaptioning				= 16,
 	kSound							= 17,
 	kOpenParenthesis				= 18,
-	kCloseParenthesis				= 19
+	kCloseParenthesis				= 19,
+	kRandom							= 20
 };
 
 // Describes a condition that needs to be fulfilled before the
@@ -77,6 +78,9 @@ struct DependencyRecord {
 	bool satisfied		= false;
 	Time timeData;
 
+	// Only used for kRandom
+	bool stopEvaluating = false;
+
 	// Used to support the dependency tree structure in nancy3 and up
 	// The only valid field in dependencies with children is the orFlag
 	Common::Array<DependencyRecord> children;
diff --git a/engines/nancy/console.cpp b/engines/nancy/console.cpp
index a291f6effdb..0c8c3aa9293 100644
--- a/engines/nancy/console.cpp
+++ b/engines/nancy/console.cpp
@@ -519,6 +519,9 @@ void NancyConsole::recurseDependencies(const Nancy::Action::DependencyRecord &re
 			recurseDependencies(dep);
 			debugPrintf("\n))))))))");
 			break;
+		case DependencyType::kRandom :
+			debugPrintf("kRandom, chance %i", dep.condition);
+			break;
 		default:
 			debugPrintf("unknown type %u", (uint)dep.type);
 			break;


Commit: bc12fbf01ce57dcc791241127ee1195aaa22957d
    https://github.com/scummvm/scummvm/commit/bc12fbf01ce57dcc791241127ee1195aaa22957d
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-24T12:47:50+03:00

Commit Message:
NANCY: Implement PianoPuzzle

Implemented nancy3's PianoPuzzle action record. Since the
record is extremely similar to OrderingPuzzle, the latter's
implementation was extended to cover both record types.

Changed paths:
    engines/nancy/action/arfactory.cpp
    engines/nancy/action/orderingpuzzle.cpp
    engines/nancy/action/orderingpuzzle.h


diff --git a/engines/nancy/action/arfactory.cpp b/engines/nancy/action/arfactory.cpp
index f0f6fbf867e..27dd6ca6f86 100644
--- a/engines/nancy/action/arfactory.cpp
+++ b/engines/nancy/action/arfactory.cpp
@@ -136,7 +136,7 @@ ActionRecord *ActionManager::createActionRecord(uint16 type) {
 	case 107:
 		return new EventFlags();
 	case 108:
-		return new OrderingPuzzle();
+		return new OrderingPuzzle(OrderingPuzzle::kOrdering);
 	case 109:
 		return new LoseGame();
 	case 110:
@@ -193,6 +193,8 @@ ActionRecord *ActionManager::createActionRecord(uint16 type) {
 		return new RiddlePuzzle();
 	case 206:
 		return new RaycastPuzzle();
+	case 208:
+		return new OrderingPuzzle(OrderingPuzzle::PuzzleType::kPiano);
 	default:
 		error("Action Record type %i is invalid!", type);
 		return nullptr;
diff --git a/engines/nancy/action/orderingpuzzle.cpp b/engines/nancy/action/orderingpuzzle.cpp
index 624807d86be..99954ad4590 100644
--- a/engines/nancy/action/orderingpuzzle.cpp
+++ b/engines/nancy/action/orderingpuzzle.cpp
@@ -54,6 +54,7 @@ void OrderingPuzzle::init() {
 }
 
 void OrderingPuzzle::readData(Common::SeekableReadStream &stream) {
+	bool isPiano = _puzzleType == kPiano;
 	readFilename(stream, _imageName);
 	Common::Serializer ser(&stream, nullptr);
 	ser.setVersion(g_nancy->getGameType());
@@ -66,18 +67,24 @@ void OrderingPuzzle::readData(Common::SeekableReadStream &stream) {
 		ser.syncAsUint16LE(numElements);
 	}
 
-	_srcRects.resize(numElements);
-	for (uint i = 0; i < numElements; ++i) {
-		readRect(stream, _srcRects[i]);
-	}
+	readRectArray(stream, _srcRects, numElements);
+
+	ser.skip(16 * (15 - numElements), kGameTypeNancy1);
+
+	readRectArray(stream, _destRects, numElements);
 
 	ser.skip(16 * (15 - numElements), kGameTypeNancy1);
 
-	_destRects.resize(numElements);
+	_hotspots.resize(numElements);
+	if (isPiano) {
+		readRectArray(stream, _hotspots, numElements);
+		ser.skip(16 * (15 - numElements));
+	} else {
+		_hotspots = _destRects;
+	}
+
 	_drawnElements.resize(numElements, false);
 	for (uint i = 0; i < numElements; ++i) {
-		readRect(stream, _destRects[i]);
-
 		if (i == 0) {
 			_screenPosition = _destRects[i];
 		} else {
@@ -85,8 +92,6 @@ void OrderingPuzzle::readData(Common::SeekableReadStream &stream) {
 		}
 	}
 
-	ser.skip(16 * (15 - numElements), kGameTypeNancy1);
-
 	if (ser.getVersion() == kGameTypeVampire) {
 		_sequenceLength = 5;
 	} else {
@@ -95,10 +100,14 @@ void OrderingPuzzle::readData(Common::SeekableReadStream &stream) {
 
 	_correctSequence.resize(_sequenceLength);
 	for (uint i = 0; i < _sequenceLength; ++i) {
-		ser.syncAsByte(_correctSequence[i]);
+		if (isPiano) {
+			ser.syncAsUint16LE(_correctSequence[i]);
+		} else {
+			ser.syncAsByte(_correctSequence[i]);
+		}
 	}
 
-	ser.skip(15 - _sequenceLength, kGameTypeNancy1);
+	ser.skip((15 - _sequenceLength) * (isPiano ? 2 : 1), kGameTypeNancy1);
 
 	if (ser.getVersion() != kGameTypeVampire) {
 		_clickSound.readNormal(stream);
@@ -125,19 +134,45 @@ void OrderingPuzzle::execute() {
 	case kRun:
 		switch (_solveState) {
 		case kNotSolved:
-			if (_clickedSequence.size() <  _sequenceLength) {
-				return;
-			}
+			if (_puzzleType == kOrdering) {
+				if (_clickedSequence.size() <  _sequenceLength) {
+					return;
+				}
 
-			for (uint i = 0; i < _sequenceLength; ++i) {
+				for (uint i = 0; i < _sequenceLength; ++i) {
+					if (_clickedSequence[i] != (int16)_correctSequence[i]) {
+						if (_clickedSequence.size() > (g_nancy->getGameType() == kGameTypeVampire ? 4 : (uint)_sequenceLength + 1)) {
+							clearAllElements();
+						}
 
-				if (_clickedSequence[i] != (int16)_correctSequence[i]) {
-					if (_clickedSequence.size() > (g_nancy->getGameType() == kGameTypeVampire ? 4 : (uint)_sequenceLength + 1)) {
-						clearAllElements();
+						return;
 					}
+				}
+			} else {
+				if (g_nancy->_sound->isSoundPlaying(_clickSound)) {
+					return;
+				}
 
+				for (uint i = 0; i < _drawnElements.size(); ++i) {
+					if (_drawnElements[i]) {
+						undrawElement(i);
+					}
+				}
+				
+				if (_clickedSequence.size() <  _sequenceLength) {
 					return;
 				}
+
+				// Arbitrary number
+				if (_clickedSequence.size() > 30) {
+					_clickedSequence.erase(&_clickedSequence[0], &_clickedSequence[_clickedSequence.size() - 6]);
+				}
+
+				for (uint i = 0; i < _sequenceLength; ++i) {
+					if (_clickedSequence[_clickedSequence.size() - _sequenceLength + i] != (int16)_correctSequence[i]) {
+						return;
+					}
+				}
 			}
 
 			NancySceneState.setEventFlag(_solveExitScene._flag);
@@ -184,40 +219,57 @@ void OrderingPuzzle::handleInput(NancyInput &input) {
 		return;
 	}
 
+	bool canClick = true;
+	if (_puzzleType == kPiano && g_nancy->_sound->isSoundPlaying(_clickSound)) {
+		canClick = false;
+	}
+
 	if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
 		g_nancy->_cursorManager->setCursorType(CursorManager::kExit);
 
-		if (input.input & NancyInput::kLeftMouseButtonUp) {
+		if (canClick && input.input & NancyInput::kLeftMouseButtonUp) {
 			_state = kActionTrigger;
 		}
 		return;
 	}
 
-	for (int i = 0; i < (int)_destRects.size(); ++i) {
-		if (NancySceneState.getViewport().convertViewportToScreen(_destRects[i]).contains(input.mousePos)) {
+	for (int i = 0; i < (int)_hotspots.size(); ++i) {
+		if (NancySceneState.getViewport().convertViewportToScreen(_hotspots[i]).contains(input.mousePos)) {
 			g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
 
-			if (input.input & NancyInput::kLeftMouseButtonUp) {
+			if (canClick && input.input & NancyInput::kLeftMouseButtonUp) {
 				if (g_nancy->getGameType() == kGameTypeVampire) {
 					g_nancy->_sound->playSound("BUOK");
 				} else {
+					if (_puzzleType == kPiano) {
+						if (Common::isDigit(_clickSound.name.lastChar())) {
+							_clickSound.name.deleteLastChar();
+						}
+
+						_clickSound.name.insertChar('0' + i, _clickSound.name.size());
+						g_nancy->_sound->loadSound(_clickSound);
+					}
+
 					g_nancy->_sound->playSound(_clickSound);
 				}
 
-				for (uint j = 0; j < _clickedSequence.size(); ++j) {
-					if (_clickedSequence[j] == i && _drawnElements[i] == true) {
-						undrawElement(i);
-						if (_clickedSequence.back() == i) {
-							_clickedSequence.pop_back();
-						}
+				if (_puzzleType == kOrdering) {
+					for (uint j = 0; j < _clickedSequence.size(); ++j) {
+						if (_clickedSequence[j] == i && _drawnElements[i] == true) {
+							undrawElement(i);
+							if (_clickedSequence.back() == i) {
+								_clickedSequence.pop_back();
+							}
 
-						return;
+							return;
+						}
 					}
 				}
 
 				_clickedSequence.push_back(i);
 				drawElement(i);
 			}
+
 			return;
 		}
 	}
diff --git a/engines/nancy/action/orderingpuzzle.h b/engines/nancy/action/orderingpuzzle.h
index 9c9a6034c02..58991ef5467 100644
--- a/engines/nancy/action/orderingpuzzle.h
+++ b/engines/nancy/action/orderingpuzzle.h
@@ -30,7 +30,8 @@ namespace Action {
 class OrderingPuzzle : public RenderActionRecord {
 public:
 	enum SolveState { kNotSolved, kPlaySound, kWaitForSound };
-	OrderingPuzzle() : RenderActionRecord(7) {}
+	enum PuzzleType { kOrdering, kPiano };
+	OrderingPuzzle(PuzzleType type) : RenderActionRecord(7), _puzzleType(type) {}
 	virtual ~OrderingPuzzle() {}
 
 	void init() override;
@@ -39,9 +40,18 @@ public:
 	void execute() override;
 	void handleInput(NancyInput &input) override;
 
+protected:
+	Common::String getRecordTypeName() const override { return _puzzleType == kOrdering ? "OrderingPuzzle" : "PianoPuzzle"; }
+	bool isViewportRelative() const override { return true; }
+
+	void drawElement(uint id);
+	void undrawElement(uint id);
+	void clearAllElements();
+
 	Common::String _imageName;
 	Common::Array<Common::Rect> _srcRects;
 	Common::Array<Common::Rect> _destRects;
+	Common::Array<Common::Rect> _hotspots;
 	uint16 _sequenceLength = 0;
 	Common::Array<byte> _correctSequence;
 	Nancy::SoundDescription _clickSound;
@@ -57,13 +67,7 @@ public:
 	Common::Array<bool> _drawnElements;
 	Time _solveSoundPlayTime;
 
-protected:
-	Common::String getRecordTypeName() const override { return "OrderingPuzzle"; }
-	bool isViewportRelative() const override { return true; }
-
-	void drawElement(uint id);
-	void undrawElement(uint id);
-	void clearAllElements();
+	PuzzleType _puzzleType;
 };
 
 } // End of namespace Action


Commit: a5b1143fc663b2e4fb9a903e82d5829d20b8c7ee
    https://github.com/scummvm/scummvm/commit/a5b1143fc663b2e4fb9a903e82d5829d20b8c7ee
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-24T12:47:51+03:00

Commit Message:
NANCY: Add workaround for broken video

Added a workaround for a broken nancy3 video file which
would otherwise crash the engine.

Changed paths:
    engines/nancy/decompress.cpp


diff --git a/engines/nancy/decompress.cpp b/engines/nancy/decompress.cpp
index 4413f3f7214..1291fbd5eb0 100644
--- a/engines/nancy/decompress.cpp
+++ b/engines/nancy/decompress.cpp
@@ -92,6 +92,11 @@ bool Decompressor::decompress(Common::ReadStream &input, Common::MemoryWriteStre
 	}
 
 	if (output.err() || output.pos() != output.size()) {
+		// Workaround for nancy3 file "SLN RollPanOpn.avf", which outputs 2 bytes less than it should
+		if (output.size() - output.pos() <= 2) {
+			return true;
+		}
+
 		warning("Failed to decompress resource");
 		return false;
 	}




More information about the Scummvm-git-logs mailing list