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

fracturehill noreply at scummvm.org
Thu May 11 11:29:30 UTC 2023


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

Summary:
2fc98c4542 NANCY: Correctly handle nancy3 cursors
218bbfe71d NANCY: Show all text in TextboxWrite action record
09e5cefea3 NANCY: Rewrite textbox drawing code
899f435cfd NANCY: Allow first event flag to be set
4cddb2e61c NANCY: Handle consecutive SpecialEffects
c74c52097f NANCY: Properly clear puzzle data


Commit: 2fc98c4542c373b38b0ac21c73484a2c0c1d9681
    https://github.com/scummvm/scummvm/commit/2fc98c4542c373b38b0ac21c73484a2c0c1d9681
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-11T14:28:54+03:00

Commit Message:
NANCY: Correctly handle nancy3 cursors

Nancy3 added several new cursor types, which are now
loaded correctly.

Changed paths:
    engines/nancy/action/rippedletterpuzzle.cpp
    engines/nancy/cursor.cpp
    engines/nancy/cursor.h


diff --git a/engines/nancy/action/rippedletterpuzzle.cpp b/engines/nancy/action/rippedletterpuzzle.cpp
index 726df97e2ca..2d553c1b4c9 100644
--- a/engines/nancy/action/rippedletterpuzzle.cpp
+++ b/engines/nancy/action/rippedletterpuzzle.cpp
@@ -178,7 +178,7 @@ void RippedLetterPuzzle::handleInput(NancyInput &input) {
 				insideRect.translate(screenHotspot.left, screenHotspot.top);
 
 				if (insideRect.contains(input.mousePos)) {
-					g_nancy->_cursorManager->setCursorType(CursorManager::kRotate);
+					g_nancy->_cursorManager->setCursorType(CursorManager::kRotateCW);
 
 					if (input.input & NancyInput::kLeftMouseButtonUp) {
 						// Player has clicked, rotate the piece
diff --git a/engines/nancy/cursor.cpp b/engines/nancy/cursor.cpp
index f7ce0eec1b9..b641911ec98 100644
--- a/engines/nancy/cursor.cpp
+++ b/engines/nancy/cursor.cpp
@@ -33,8 +33,21 @@ void CursorManager::init(Common::SeekableReadStream *chunkStream) {
 	assert(chunkStream);
 
 	chunkStream->seek(0);
-	uint numCursorTypes = g_nancy->getGameType() <= kGameTypeNancy1 ? 4 : 5;
-	uint numCursors = g_nancy->getStaticData().numNonItemCursors + g_nancy->getStaticData().numItems * numCursorTypes;
+
+	switch(g_nancy->getGameType()) {
+	case kGameTypeVampire:
+		// fall thorugh
+	case kGameTypeNancy1:
+		_numCursorTypes = 4;
+		break;
+	case kGameTypeNancy2:	
+		_numCursorTypes = 5;
+		break;
+	default:
+		_numCursorTypes = 9;
+	}
+
+	uint numCursors = g_nancy->getStaticData().numNonItemCursors + g_nancy->getStaticData().numItems * _numCursorTypes;
 	_cursors.resize(numCursors);
 
 	for (uint i = 0; i < numCursors; ++i) {
@@ -80,16 +93,20 @@ void CursorManager::setCursor(CursorType type, int16 itemID) {
 	case kNormalArrow:
 		if (gameType <= kGameTypeNancy1) {
 			_curCursorID = 4;
-		} else {
+		} else if (gameType == kGameTypeNancy2) {
 			_curCursorID = 5;
+		} else {
+			_curCursorID = 8;
 		}
 		
 		break;
 	case kHotspotArrow:
 		if (gameType <= kGameTypeNancy1) {
 			_curCursorID = 5;
-		} else {
+		} else if (gameType == kGameTypeNancy2) {
 			_curCursorID = 6;
+		} else {
+			_curCursorID = 9;
 		}
 
 		break;
@@ -110,7 +127,7 @@ void CursorManager::setCursor(CursorType type, int16 itemID) {
 			_hasItem = true;
 		}
 
-		_curCursorID = itemID * (gameType <= kGameTypeNancy1? 4 : 5) + itemsOffset + type;
+		_curCursorID = (itemID * _numCursorTypes) + itemsOffset + type;
 	}
 	}
 }
diff --git a/engines/nancy/cursor.h b/engines/nancy/cursor.h
index 88a7f026e45..114cc1d5258 100644
--- a/engines/nancy/cursor.h
+++ b/engines/nancy/cursor.h
@@ -34,14 +34,15 @@ class CursorManager {
 	friend class NancyEngine;
 
 public:
-	enum CursorType { kNormal = 0, kHotspot = 1, kMove = 2, kExit = 3, kRotate = 4, kNormalArrow, kHotspotArrow };
+	enum CursorType { kNormal = 0, kHotspot = 1, kMove = 2, kExit = 3, kRotateCW = 4, kRotateCCW = 5, kTurnLeft = 6, kTurnRight = 7, kNormalArrow, kHotspotArrow };
 
 	CursorManager() :
 		_isInitialized(false),
 		_curItemID(-1),
 		_curCursorType(kNormal),
 		_curCursorID(0),
-		_hasItem(false) {}
+		_hasItem(false),
+		_numCursorTypes(0) {}
 
 	void init(Common::SeekableReadStream *chunkStream);
 
@@ -78,6 +79,7 @@ private:
 	uint _curCursorID;
 	bool _hasItem;
 	bool _isInitialized;
+	int _numCursorTypes;
 };
 
 } // End of namespace Nancy


Commit: 218bbfe71db065430dbf5b90146a483a7536b3e7
    https://github.com/scummvm/scummvm/commit/218bbfe71db065430dbf5b90146a483a7536b3e7
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-11T14:28:55+03:00

Commit Message:
NANCY: Show all text in TextboxWrite action record

Fixed nancy3's tutorial text only showing the first line. Also
made sure to use the correct, non-dialogue font.

Changed paths:
    engines/nancy/action/recordtypes.cpp


diff --git a/engines/nancy/action/recordtypes.cpp b/engines/nancy/action/recordtypes.cpp
index 158b4b6e4b2..e6584eec5ab 100644
--- a/engines/nancy/action/recordtypes.cpp
+++ b/engines/nancy/action/recordtypes.cpp
@@ -292,7 +292,8 @@ void TextBoxWrite::readData(Common::SeekableReadStream &stream) {
 	char *buf = new char[size];
 	stream.read(buf, size);
 	buf[size - 1] = '\0';
-	_text = buf;
+
+	UI::Textbox::assembleTextLine(buf, _text, size);
 
 	delete[] buf;
 }
@@ -305,6 +306,7 @@ TextBoxWrite::~TextBoxWrite() {
 void TextBoxWrite::execute() {
 	auto &tb = NancySceneState.getTextbox();
 	tb.clear();
+	tb.overrideFontID(g_nancy->_textboxData->defaultFontID);
 	tb.addTextLine(_text);
 	tb.setVisible(true);
 	NancySceneState.setShouldClearTextbox(false);


Commit: 09e5cefea371c036e6a199fb5da9df642774415c
    https://github.com/scummvm/scummvm/commit/09e5cefea371c036e6a199fb5da9df642774415c
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-11T14:28:55+03:00

Commit Message:
NANCY: Rewrite textbox drawing code

Rewrote drawTextbox() to be much cleaner and to support
some edge cases in nancy3 which would previously crash
the engine.

Changed paths:
    engines/nancy/ui/textbox.cpp


diff --git a/engines/nancy/ui/textbox.cpp b/engines/nancy/ui/textbox.cpp
index d954e948292..7df090ad9ad 100644
--- a/engines/nancy/ui/textbox.cpp
+++ b/engines/nancy/ui/textbox.cpp
@@ -153,8 +153,6 @@ void Textbox::drawTextbox() {
 
 	for (uint lineID = 0; lineID < _textLines.size(); ++lineID) {
 		Common::String currentLine = _textLines[lineID];
-
-		uint horizontalOffset = 0;
 		bool hasHotspot = false;
 		Rect hotspot;
 
@@ -173,6 +171,11 @@ void Textbox::drawTextbox() {
 			currentLine.replace(newLinePos, ARRAYSIZE(_newLineToken) - 1, "\n");
 		}
 
+		// Replace tab token with four spaces
+		while (newLinePos = currentLine.find(_tabToken), newLinePos != String::npos) {
+			currentLine.replace(newLinePos, ARRAYSIZE(_tabToken) - 1, "    ");
+		}
+
 		// Simply remove telephone end token
 		if (currentLine.hasSuffix(_telephoneEndToken)) {
 			currentLine = currentLine.substr(0, currentLine.size() - ARRAYSIZE(_telephoneEndToken) + 1);
@@ -195,86 +198,93 @@ void Textbox::drawTextbox() {
 			lastHotspotPos = hotspotPos;
 		}
 
-		// Subdivide current line into sublines for proper handling of the tab and color tokens
-		// Assumes the tab token is on a new line
-		while (!currentLine.empty()) {
-			if (currentLine.hasPrefix(_tabToken)) {
-				horizontalOffset += font->getStringWidth("    "); // Replace tab with 4 spaces
-				currentLine = currentLine.substr(ARRAYSIZE(_tabToken) - 1);
-			}
+		// Scan for color begin and end tokens and keep their positions
+		// in a queue. We do this last so the positions are accurate
+		Common::Queue<uint> colorTokens;
+		while (newLinePos = currentLine.find(_colorBeginToken), newLinePos != String::npos) {
+			currentLine.erase(newLinePos, ARRAYSIZE(_colorBeginToken) - 1);
+			colorTokens.push(newLinePos);
 
-			String currentSubstring;
-			_lastResponseisMultiline = false;
+			newLinePos = currentLine.find(_colorEndToken);
+			currentLine.erase(newLinePos, ARRAYSIZE(_colorEndToken) - 1);
+			colorTokens.push(newLinePos);
+		}
 
-			uint32 nextTabPos = currentLine.find(_tabToken);
-			if (nextTabPos != String::npos) {
-				currentSubstring = currentLine.substr(0, nextTabPos);
-				currentLine = currentLine.substr(nextTabPos);
-			} else {
-				currentSubstring = currentLine;
-				currentLine.clear();
-			}
-			
-			Array<Common::String> wrappedLines;
-			uint numColorLines = 0;
-			uint colorLinesWidth = 0;
-
-			// Color token denotes a highlighted section of the dialogue
-			// The russian variant of nancy1 makes all player text colored, so we need to do font wrapping here
-			if (currentSubstring.hasPrefix(_colorBeginToken)) {
-				// Found color string, look for end token
-				uint32 colorEndPos = currentSubstring.find(_colorEndToken);
-
-				Common::String colorSubstring = currentSubstring.substr(ARRAYSIZE(_colorBeginToken) - 1, colorEndPos - ARRAYSIZE(_colorBeginToken) + 1);
-				currentSubstring = currentSubstring.substr(ARRAYSIZE(_colorBeginToken) + ARRAYSIZE(_colorEndToken) + colorSubstring.size() - 2);
-
-				font->wordWrap(colorSubstring, maxWidth, wrappedLines, 0);
-
-				// Draw the color lines
-				for (uint i = 0; i < wrappedLines.size(); ++i) {
-					font->drawString(&_fullSurface, wrappedLines[i], tbox->borderWidth + horizontalOffset, tbox->firstLineOffset - font->getFontHeight() + _numLines * lineDist, maxWidth, 1);
-					colorLinesWidth = MAX<int16>(colorLinesWidth, font->getStringWidth(wrappedLines[i]));
-					if (i != wrappedLines.size() - 1) {
-						++_numLines;
-						++numColorLines;
-					}
-				}
-				
-				horizontalOffset += font->getStringWidth(wrappedLines.back());
-				wrappedLines.clear();
-			}
+		// Do word wrapping on the text, sans tokens
+		Array<Common::String> wrappedLines;
+		font->wordWrap(currentLine, maxWidth, wrappedLines, 0);
+
+		// Setup most of the hotspot
+		if (hasHotspot) {
+			hotspot.left = tbox->borderWidth;
+			hotspot.top = tbox->firstLineOffset - tbox->lineHeight + (_numLines * lineDist) - 1;
+			hotspot.setHeight((wrappedLines.size() * lineDist) - (lineDist - tbox->lineHeight));
+			hotspot.setWidth(0);
+		}
 
-			// Do word wrapping on the rest of the text
-			font->wordWrap(currentSubstring, maxWidth, wrappedLines, horizontalOffset);
+		// Go through the wrapped lines and draw them, making sure to
+		// respect color tokens
+		uint totalCharsDrawn = 0;
+		bool isColor = false;
+		for (Common::String &line : wrappedLines) {
+			uint horizontalOffset = 0;
 
+			// Set the width of the hotspot
 			if (hasHotspot) {
-				hotspot.left = tbox->borderWidth;
-				hotspot.top = tbox->firstLineOffset - tbox->lineHeight + (_numLines - numColorLines) * lineDist - 1;
-				hotspot.setHeight((wrappedLines.size() + MAX<int16>((numColorLines - 1), 0)) * lineDist - (lineDist - tbox->lineHeight));
-				hotspot.setWidth(0);
+				hotspot.setWidth(MAX<int16>(hotspot.width(), font->getStringWidth(line)));
 			}
 
-			// Draw the wrapped lines
-			for (uint i = 0; i < wrappedLines.size(); ++i) {
-				font->drawString(&_fullSurface, wrappedLines[i], tbox->borderWidth + (i == 0 ? horizontalOffset : 0), tbox->firstLineOffset - font->getFontHeight() + _numLines * lineDist, maxWidth, 0);
-				if (hasHotspot) {
-					highlightFont->drawString(&_textHighlightSurface, wrappedLines[i], tbox->borderWidth + (i == 0 ? horizontalOffset : 0), tbox->firstLineOffset - highlightFont->getFontHeight() + _numLines * lineDist, maxWidth, 0);
-					hotspot.setWidth(MAX<int16>(hotspot.width(), font->getStringWidth(wrappedLines[i]) + (i == 0 ? horizontalOffset : 0)));
+			while (!line.empty()) {
+				Common::String subLine;
+
+				if (colorTokens.size()) {
+					// Text contains color part
+
+					if (totalCharsDrawn == colorTokens.front()) {
+						// Token is at begginning of (what's left of) the current line
+						isColor = !isColor;
+						colorTokens.pop();
+					}
+
+					if (totalCharsDrawn < colorTokens.front() && colorTokens.front() < (totalCharsDrawn + line.size())) {
+						// There's a token inside the current line, so split off the part before it
+						subLine = line.substr(0, colorTokens.front() - totalCharsDrawn);
+						line = line.substr(subLine.size());
+					}
 				}
-				++_numLines;
-			}
 
-			// Make sure to adjust the hotspot width if we had a multi-line color string
-			hotspot.setWidth(MAX<int16>(hotspot.width(), colorLinesWidth));
+				// Choose whether to draw the subLine, or the full line
+				Common::String &stringToDraw = subLine.size() ? subLine : line;
 
-			// Simulate a bug in the original engine where player text longer than
-			// a single line gets a double newline afterwards
-			if ((wrappedLines.size() + numColorLines) > 1 && hasHotspot) {
-				++_numLines;
-				_lastResponseisMultiline = true;
+				// Draw the normal text
+				font->drawString(				&_fullSurface,
+												stringToDraw,
+												tbox->borderWidth + horizontalOffset,
+												tbox->firstLineOffset - font->getFontHeight() + _numLines * lineDist,
+												maxWidth,
+												isColor);
+				
+				// Then, draw the highlight
+				if (hasHotspot) {
+					highlightFont->drawString(	&_textHighlightSurface,
+												stringToDraw,
+												tbox->borderWidth + horizontalOffset,
+												tbox->firstLineOffset - font->getFontHeight() + _numLines * lineDist,
+												maxWidth,
+												isColor);
+				}
+
+				if (subLine.size()) {
+					horizontalOffset += font->getStringWidth(subLine);
+					totalCharsDrawn += subLine.size();
+				} else {
+					totalCharsDrawn += line.size();
+					break;
+				}
 			}
 
-			horizontalOffset = 0;
+			++totalCharsDrawn; // Account for newlines, which are removed from the string when doing word wrap
+			++_numLines;
 		}
 
 		// Add the hotspot to the list
@@ -282,7 +292,17 @@ void Textbox::drawTextbox() {
 			_hotspots.push_back(hotspot);
 		}
 
-		// Add a new line after every text line
+		// Simulate a bug in the original engine where player text longer than
+		// a single line gets a double newline afterwards
+		if (wrappedLines.size() > 1 && hasHotspot) {
+			++_numLines;
+
+			if (lineID == _textLines.size() - 1) {
+				_lastResponseisMultiline = true;
+			}
+		}
+
+		// Add a newline after every full piece of text
 		++_numLines;
 	}
 


Commit: 899f435cfd97484b7be03f779927301e5e5e1f10
    https://github.com/scummvm/scummvm/commit/899f435cfd97484b7be03f779927301e5e5e1f10
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-11T14:28:55+03:00

Commit Message:
NANCY: Allow first event flag to be set

Fixed an issue in nancy3 where the first event flag wouldn't
be set, blocking the player from choosing easy difficulty.

Changed paths:
    engines/nancy/state/scene.cpp


diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 1f306a413da..ac9c7704162 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -308,7 +308,7 @@ void Scene::setHeldItem(int16 id)  {
 }
 
 void Scene::setEventFlag(int16 label, byte flag) {
-	if (label > 1000) {
+	if (label >= 1000) {
 		// In nancy3 and onwards flags begin from 1000
 		label -= 1000;
 	}


Commit: 4cddb2e61c3539d61ea5b418a7d055a6bcfbf6e2
    https://github.com/scummvm/scummvm/commit/4cddb2e61c3539d61ea5b418a7d055a6bcfbf6e2
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-11T14:28:56+03:00

Commit Message:
NANCY: Handle consecutive SpecialEffects

Handled an edge case where two consecutive scenes have
SpecialEffect fades, but only the latter one would get played.

Changed paths:
    engines/nancy/misc/specialeffect.cpp
    engines/nancy/misc/specialeffect.h
    engines/nancy/state/scene.cpp
    engines/nancy/state/scene.h


diff --git a/engines/nancy/misc/specialeffect.cpp b/engines/nancy/misc/specialeffect.cpp
index b2d9e6deb70..a964a986cf3 100644
--- a/engines/nancy/misc/specialeffect.cpp
+++ b/engines/nancy/misc/specialeffect.cpp
@@ -42,7 +42,7 @@ void SpecialEffect::init() {
 }
 
 void SpecialEffect::updateGraphics() {
-	if (g_nancy->getTotalPlayTime() > _nextFrameTime && _currentFrame < _numFrames) {
+	if (g_nancy->getTotalPlayTime() > _nextFrameTime && _currentFrame < (int)_numFrames && isInitialized()) {
 		++_currentFrame;
 		_nextFrameTime += _frameTime;
 
@@ -57,6 +57,10 @@ void SpecialEffect::onSceneChange() {
 }
 
 void SpecialEffect::afterSceneChange() {
+	if (_fadeFrom.empty()) {
+		return;
+	}
+
 	if (_type == kSceneChangeFadeCrossDissolve) {
 		g_nancy->_graphicsManager->screenshotViewport(_fadeTo);
 	} else {
@@ -66,7 +70,7 @@ void SpecialEffect::afterSceneChange() {
 
 	// Workaround for the way ManagedSurface handles transparency. Both pure black
 	// and pure white appear in scenes with SpecialEffects, and those happen to be
-	// the two default values transBlitFrom uses for transColor. By doing this
+	// the two default values transBlitFrom uses for transColor. By doing this,
 	// transColor gets set to the one color guaranteed to not appear in any scene,
 	// and transparency works correctly
 	_fadeTo.setTransparentColor(g_nancy->_graphicsManager->getTransColor());
@@ -79,7 +83,7 @@ void SpecialEffect::afterSceneChange() {
 
 bool SpecialEffect::isDone() const {
 	if (_type == kSceneChangeFadeCrossDissolve) {
-		return _currentFrame >= _numFrames;
+		return _currentFrame >= (int)_numFrames;
 	} else {
 		return g_nancy->getTotalPlayTime() > _fadeToBlackEndTime;
 	}
diff --git a/engines/nancy/misc/specialeffect.h b/engines/nancy/misc/specialeffect.h
index 33b03340bc7..d66b2080105 100644
--- a/engines/nancy/misc/specialeffect.h
+++ b/engines/nancy/misc/specialeffect.h
@@ -65,7 +65,7 @@ protected:
 	uint16 _fadeToBlackTime = 0;
 	uint16 _frameTime = 0;
 
-	uint _currentFrame = 0;
+	int _currentFrame = 0;
 	uint _numFrames = 0;
 	SPEC *_specialEffectData = nullptr;
 };
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index ac9c7704162..4f6c7246f38 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -106,8 +106,7 @@ Scene::Scene() :
 		_actionManager(),
 		_difficulty(0),
 		_activeConversation(nullptr),
-		_lightning(nullptr),
-		_specialEffect(nullptr) {}
+		_lightning(nullptr) {}
 
 Scene::~Scene()  {
 	delete _helpButton;
@@ -117,7 +116,6 @@ Scene::~Scene()  {
 	delete _inventoryBoxOrnaments;
 	delete _clock;
 	delete _lightning;
-	delete _specialEffect;
 
 	clearPuzzleData();
 }
@@ -142,7 +140,6 @@ void Scene::process() {
 			g_nancy->_sound->loadSound(_sceneState.summary.sound);
 			g_nancy->_sound->playSound(_sceneState.summary.sound);
 		}
-		run(); // Extra run() call to fix the single frame with a wrong palette in TVD
 		// fall through
 	case kRun:
 		run();
@@ -202,10 +199,6 @@ void Scene::changeScene(uint16 id, uint16 frame, uint16 verticalOffset, byte con
 		_sceneState.nextScene.paletteID = paletteID;
 	}
 
-	if (_specialEffect) {
-		_specialEffect->onSceneChange();
-	}
-
 	_state = kLoad;
 }
 
@@ -602,12 +595,8 @@ void Scene::beginLightning(int16 distance, uint16 pulseTime, int16 rgbPercent) {
 }
 
 void Scene::specialEffect(byte type, uint16 fadeToBlackTime, uint16 frameTime) {
-	if (_specialEffect) {
-		delete _specialEffect;
-	}
-
-	_specialEffect = new Misc::SpecialEffect(type, fadeToBlackTime, frameTime);
-	_specialEffect->init();
+	_specialEffects.push(Misc::SpecialEffect(type, fadeToBlackTime, frameTime));
+	_specialEffects.back().init();
 }
 
 PuzzleData *Scene::getPuzzleData(const uint32 tag) {
@@ -627,6 +616,10 @@ PuzzleData *Scene::getPuzzleData(const uint32 tag) {
 }
 
 void Scene::load() {
+	if (_specialEffects.size()) {
+		_specialEffects.front().onSceneChange();
+	}
+
 	clearSceneData();
 
 	// Scene IDs are prefixed with S inside the cif tree; e.g 100 -> S100
@@ -700,10 +693,6 @@ void Scene::load() {
 
 	_flags.sceneCounts.getOrCreateVal(_sceneState.currentScene.sceneID)++;
 
-	if (_specialEffect) {
-		_specialEffect->afterSceneChange();
-	}
-
 	_state = kStartSound;
 }
 
@@ -714,18 +703,19 @@ void Scene::run() {
 		return;
 	}
 
-	if (_specialEffect && _specialEffect->isInitialized()) {
-		if (_specialEffect->isDone()) {
-			delete _specialEffect;
-			_specialEffect = nullptr;
-			g_nancy->_graphicsManager->redrawAll();
-		}
+	Time currentPlayTime = g_nancy->getTotalPlayTime();
 
-		return;
+	if (_specialEffects.size()) {
+		if (_specialEffects.front().isInitialized()) {
+			if (_specialEffects.front().isDone()) {
+				_specialEffects.pop();
+				g_nancy->_graphicsManager->redrawAll();
+			}
+		} else {
+			_specialEffects.front().afterSceneChange();
+		}
 	}
 
-	Time currentPlayTime = g_nancy->getTotalPlayTime();
-
 	Time deltaTime = currentPlayTime - _timers.lastTotalTime;
 	_timers.lastTotalTime = currentPlayTime;
 
diff --git a/engines/nancy/state/scene.h b/engines/nancy/state/scene.h
index 8255c876a3b..506b0044a57 100644
--- a/engines/nancy/state/scene.h
+++ b/engines/nancy/state/scene.h
@@ -23,6 +23,7 @@
 #define NANCY_STATE_SCENE_H
 
 #include "common/singleton.h"
+#include "common/queue.h"
 
 #include "engines/nancy/commontypes.h"
 #include "engines/nancy/puzzledata.h"
@@ -275,7 +276,7 @@ private:
 	NancyState::NancyState _gameStateRequested;
 
 	Misc::Lightning *_lightning;
-	Misc::SpecialEffect *_specialEffect;
+	Common::Queue<Misc::SpecialEffect> _specialEffects;
 
 	Common::HashMap<uint32, PuzzleData *> _puzzleData;
 


Commit: c74c52097fca75bbc0d43d2560deb063e6811c66
    https://github.com/scummvm/scummvm/commit/c74c52097fca75bbc0d43d2560deb063e6811c66
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-05-11T14:28:56+03:00

Commit Message:
NANCY: Properly clear puzzle data

Fixed an issue where in-game loading would segfault
because the _puzzleData HashMap wasn't getting properly
cleared.

Changed paths:
    engines/nancy/state/scene.cpp


diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 4f6c7246f38..2141521da3f 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -892,6 +892,8 @@ void Scene::clearPuzzleData() {
 	for (auto &pd : _puzzleData) {
 		delete pd._value;
 	}
+
+	_puzzleData.clear();
 }
 
 Scene::PlayFlags::LogicCondition::LogicCondition() : flag(g_nancy->_false) {}




More information about the Scummvm-git-logs mailing list