NANCY: Handle consecutive SpecialEffects

Handled an edge case where two consecutive scenes have
SpecialEffect fades, but only the latter one would get played.
This commit is contained in:
Kaloyan Chehlarski 2023-05-11 14:14:39 +03:00
parent 899f435cfd
commit 4cddb2e61c
4 changed files with 28 additions and 33 deletions

View File

@ -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;
}

View File

@ -65,7 +65,7 @@ protected:
uint16 _fadeToBlackTime = 0;
uint16 _frameTime = 0;
uint _currentFrame = 0;
int _currentFrame = 0;
uint _numFrames = 0;
SPEC *_specialEffectData = nullptr;
};

View File

@ -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();
}
return;
}
Time currentPlayTime = g_nancy->getTotalPlayTime();
if (_specialEffects.size()) {
if (_specialEffects.front().isInitialized()) {
if (_specialEffects.front().isDone()) {
_specialEffects.pop();
g_nancy->_graphicsManager->redrawAll();
}
} else {
_specialEffects.front().afterSceneChange();
}
}
Time deltaTime = currentPlayTime - _timers.lastTotalTime;
_timers.lastTotalTime = currentPlayTime;

View File

@ -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;