mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-13 15:40:57 +00:00
NANCY: Implement rotating lock puzzle
Implemented the RotatingLockPuzzle action record.
This commit is contained in:
parent
725ff2f95d
commit
c7e1c95803
@ -27,6 +27,7 @@
|
||||
#include "engines/nancy/action/secondaryvideo.h"
|
||||
#include "engines/nancy/action/staticbitmapanim.h"
|
||||
#include "engines/nancy/action/orderingpuzzle.h"
|
||||
#include "engines/nancy/action/rotatinglockpuzzle.h"
|
||||
|
||||
#include "engines/nancy/state/scene.h"
|
||||
|
||||
@ -114,7 +115,7 @@ ActionRecord *ActionManager::createActionRecord(uint16 type) {
|
||||
case 0x67:
|
||||
return new DifficultyLevel();
|
||||
case 0x68:
|
||||
return new RotatingLockPuzzle();
|
||||
return new RotatingLockPuzzle(_engine->scene->getViewport());
|
||||
case 0x69:
|
||||
return new LeverPuzzle();
|
||||
case 0x6A:
|
||||
|
@ -233,4 +233,4 @@ void OrderingPuzzle::clearAllElements() {
|
||||
}
|
||||
|
||||
} // End of namespace Action
|
||||
} // End of namespace Nancy
|
||||
} // End of namespace Nancy
|
||||
|
@ -41,7 +41,7 @@ class OrderingPuzzle : public ActionRecord, public RenderObject {
|
||||
public:
|
||||
enum SolveState { kNotSolved, kPlaySound, kWaitForSound };
|
||||
OrderingPuzzle(RenderObject &redrawFrom) : RenderObject(redrawFrom) {}
|
||||
~OrderingPuzzle() {}
|
||||
virtual ~OrderingPuzzle() {}
|
||||
|
||||
virtual void init() override;
|
||||
|
||||
@ -60,7 +60,6 @@ public:
|
||||
uint16 solveSoundDelay; // 0x22C
|
||||
Nancy::SoundManager::SoundDescription solveSound; // 0x22E
|
||||
SceneChangeDesc exitScene; // 0x250
|
||||
//
|
||||
FlagDesc flagOnExit; // 0x25A
|
||||
Common::Rect exitHotspot; // 0x25D
|
||||
|
||||
@ -83,4 +82,4 @@ protected:
|
||||
} // End of namespace Action
|
||||
} // End of namespace Nancy
|
||||
|
||||
#endif // NANCY_ACTION_ORDERINGPUZZLE_H
|
||||
#endif // NANCY_ACTION_ORDERINGPUZZLE_H
|
||||
|
@ -424,10 +424,6 @@ void DifficultyLevel::execute(NancyEngine *engine) {
|
||||
isDone = true;
|
||||
}
|
||||
|
||||
uint16 RotatingLockPuzzle::readData(Common::SeekableReadStream &stream) {
|
||||
return readRaw(stream, 0x2A4); // TODO
|
||||
}
|
||||
|
||||
void ShowInventoryItem::init() {
|
||||
Graphics::Surface srcSurf;
|
||||
_engine->_res->loadImage("ciftree", imageName, srcSurf);
|
||||
|
@ -312,11 +312,6 @@ public:
|
||||
FlagDesc flag;
|
||||
};
|
||||
|
||||
class RotatingLockPuzzle : public ActionRecord {
|
||||
public:
|
||||
virtual uint16 readData(Common::SeekableReadStream &stream) override;
|
||||
};
|
||||
|
||||
class ShowInventoryItem : public ActionRecord, public RenderObject {
|
||||
public:
|
||||
virtual uint16 readData(Common::SeekableReadStream &stream) override;
|
||||
|
224
engines/nancy/action/rotatinglockpuzzle.cpp
Normal file
224
engines/nancy/action/rotatinglockpuzzle.cpp
Normal file
@ -0,0 +1,224 @@
|
||||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "engines/nancy/action/rotatinglockpuzzle.h"
|
||||
|
||||
#include "engines/nancy/util.h"
|
||||
#include "engines/nancy/nancy.h"
|
||||
#include "engines/nancy/resource.h"
|
||||
#include "engines/nancy/graphics.h"
|
||||
#include "engines/nancy/state/scene.h"
|
||||
|
||||
#include "common/random.h"
|
||||
|
||||
namespace Nancy {
|
||||
namespace Action {
|
||||
|
||||
void RotatingLockPuzzle::init() {
|
||||
_drawSurface.create(_screenPosition.width(), _screenPosition.height(), GraphicsManager::pixelFormat);
|
||||
_drawSurface.clear(GraphicsManager::transColor);
|
||||
|
||||
Graphics::Surface surf;
|
||||
_engine->_res->loadImage("ciftree", imageName, surf);
|
||||
image.create(surf.w, surf.h, surf.format);
|
||||
image.blitFrom(surf);
|
||||
surf.free();
|
||||
}
|
||||
|
||||
uint16 RotatingLockPuzzle::readData(Common::SeekableReadStream &stream) {
|
||||
char buf[10];
|
||||
stream.read(buf, 10);
|
||||
imageName = buf;
|
||||
|
||||
uint numDials = stream.readUint16LE();
|
||||
|
||||
for (uint i = 0; i < 10; ++i) {
|
||||
srcRects.push_back(Common::Rect());
|
||||
readRect(stream, srcRects.back());
|
||||
}
|
||||
|
||||
for (uint i = 0; i < numDials; ++i) {
|
||||
destRects.push_back(Common::Rect());
|
||||
readRect(stream, destRects.back());
|
||||
|
||||
if (i == 0) {
|
||||
_screenPosition = destRects.back();
|
||||
} else {
|
||||
_screenPosition.extend(destRects.back());
|
||||
}
|
||||
}
|
||||
|
||||
stream.skip((8 - numDials) * 16);
|
||||
|
||||
for (uint i = 0; i < numDials; ++i) {
|
||||
upHotspots.push_back(Common::Rect());
|
||||
readRect(stream, upHotspots.back());
|
||||
}
|
||||
|
||||
stream.skip((8 - numDials) * 16);
|
||||
|
||||
for (uint i = 0; i < numDials; ++i) {
|
||||
downHotspots.push_back(Common::Rect());
|
||||
readRect(stream, downHotspots.back());
|
||||
}
|
||||
|
||||
stream.skip((8 - numDials) * 16);
|
||||
|
||||
for (uint i = 0; i < numDials; ++i) {
|
||||
correctSequence.push_back(stream.readByte());
|
||||
}
|
||||
|
||||
stream.skip(8 - numDials);
|
||||
|
||||
clickSound.read(stream, SoundManager::SoundDescription::kNormal);
|
||||
solveExitScene.readData(stream);
|
||||
stream.skip(2); // shouldStopRendering, useless
|
||||
flagOnSolve.label = stream.readUint16LE();
|
||||
flagOnSolve.flag = (NancyFlag)stream.readByte();
|
||||
solveSoundDelay = stream.readUint16LE();
|
||||
solveSound.read(stream, SoundManager::SoundDescription::kNormal);
|
||||
exitScene.readData(stream);
|
||||
stream.skip(2); // shouldStopRendering, useless
|
||||
flagOnExit.label = stream.readUint16LE();
|
||||
flagOnExit.flag = (NancyFlag)stream.readByte();
|
||||
readRect(stream, exitHotspot);
|
||||
|
||||
return 0x2A4;
|
||||
}
|
||||
|
||||
void RotatingLockPuzzle::execute(Nancy::NancyEngine *engine) {
|
||||
switch (state) {
|
||||
case kBegin:
|
||||
init();
|
||||
registerGraphics();
|
||||
|
||||
for (uint i = 0; i < correctSequence.size(); ++i) {
|
||||
currentSequence.push_back(_engine->_rnd->getRandomNumber(9));
|
||||
drawDial(i);
|
||||
}
|
||||
|
||||
_engine->sound->loadSound(clickSound);
|
||||
_engine->sound->loadSound(solveSound);
|
||||
state = kRun;
|
||||
// fall through
|
||||
case kRun:
|
||||
switch (solveState) {
|
||||
case kNotSolved:
|
||||
for (uint i = 0; i < correctSequence.size(); ++i) {
|
||||
if (currentSequence[i] != (int16)correctSequence[i]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_engine->scene->setEventFlag(flagOnSolve.label, flagOnSolve.flag);
|
||||
solveSoundPlayTime = _engine->getTotalPlayTime() + solveSoundDelay * 1000;
|
||||
solveState = kPlaySound;
|
||||
// fall through
|
||||
case kPlaySound:
|
||||
if (_engine->getTotalPlayTime() <= solveSoundPlayTime) {
|
||||
break;
|
||||
}
|
||||
|
||||
_engine->sound->playSound(solveSound.channelID);
|
||||
solveState = kWaitForSound;
|
||||
break;
|
||||
case kWaitForSound:
|
||||
if (!_engine->sound->isSoundPlaying(solveSound.channelID)) {
|
||||
state = kActionTrigger;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case kActionTrigger:
|
||||
_engine->sound->stopSound(clickSound.channelID);
|
||||
_engine->sound->stopSound(solveSound.channelID);
|
||||
|
||||
if (solveState == kNotSolved) {
|
||||
if (exitScene.sceneID != 9999) {
|
||||
_engine->scene->changeScene(exitScene.sceneID, exitScene.frameID, exitScene.verticalOffset, exitScene.doNotStartSound);
|
||||
_engine->scene->setEventFlag(flagOnExit.label, flagOnExit.flag);
|
||||
}
|
||||
} else {
|
||||
if (solveExitScene.sceneID != 9999) {
|
||||
_engine->scene->changeScene(solveExitScene.sceneID, solveExitScene.frameID, solveExitScene.verticalOffset, solveExitScene.doNotStartSound);
|
||||
}
|
||||
}
|
||||
|
||||
isDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RotatingLockPuzzle::handleInput(NancyInput &input) {
|
||||
if (solveState != kNotSolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_engine->scene->getViewport().convertViewportToScreen(exitHotspot).contains(input.mousePos)) {
|
||||
_engine->cursorManager->setCursorType(CursorManager::kExitArrow);
|
||||
|
||||
if (input.input & NancyInput::kLeftMouseButtonUp) {
|
||||
state = kActionTrigger;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < upHotspots.size(); ++i) {
|
||||
if (_engine->scene->getViewport().convertViewportToScreen(upHotspots[i]).contains(input.mousePos)) {
|
||||
_engine->cursorManager->setCursorType(CursorManager::kHotspot);
|
||||
|
||||
if (input.input & NancyInput::kLeftMouseButtonUp) {
|
||||
_engine->sound->playSound(clickSound.channelID);
|
||||
|
||||
currentSequence[i] = ++currentSequence[i] > 9 ? 0 : currentSequence[i];
|
||||
drawDial(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; i < downHotspots.size(); ++i) {
|
||||
if (_engine->scene->getViewport().convertViewportToScreen(downHotspots[i]).contains(input.mousePos)) {
|
||||
_engine->cursorManager->setCursorType(CursorManager::kHotspot);
|
||||
|
||||
if (input.input & NancyInput::kLeftMouseButtonUp) {
|
||||
_engine->sound->playSound(clickSound.channelID);
|
||||
|
||||
int8 n = currentSequence[i];
|
||||
n = --n < 0 ? 9 : n;
|
||||
currentSequence[i] = n;
|
||||
drawDial(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RotatingLockPuzzle::drawDial(uint id) {
|
||||
Common::Point destPoint(destRects[id].left - _screenPosition.left, destRects[id].top - _screenPosition.top);
|
||||
_drawSurface.blitFrom(image, srcRects[currentSequence[id]], destPoint);
|
||||
|
||||
_needsRedraw = true;
|
||||
}
|
||||
|
||||
} // End of namespace Action
|
||||
} // End of namespace Nancy
|
84
engines/nancy/action/rotatinglockpuzzle.h
Normal file
84
engines/nancy/action/rotatinglockpuzzle.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NANCY_ACTION_ROTATINGLOCKPUZZLE_H
|
||||
#define NANCY_ACTION_ROTATINGLOCKPUZZLE_H
|
||||
|
||||
#include "engines/nancy/action/recordtypes.h"
|
||||
#include "engines/nancy/renderobject.h"
|
||||
|
||||
#include "engines/nancy/sound.h"
|
||||
#include "engines/nancy/time.h"
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Nancy {
|
||||
namespace Action {
|
||||
|
||||
class RotatingLockPuzzle : public ActionRecord, public RenderObject {
|
||||
public:
|
||||
enum SolveState { kNotSolved, kPlaySound, kWaitForSound };
|
||||
RotatingLockPuzzle(RenderObject &redrawFrom) : RenderObject(redrawFrom) {}
|
||||
virtual ~RotatingLockPuzzle() {}
|
||||
|
||||
virtual void init() override;
|
||||
|
||||
virtual uint16 readData(Common::SeekableReadStream &stream) override;
|
||||
virtual void execute(Nancy::NancyEngine *engine) override;
|
||||
virtual void handleInput(NancyInput &input) override;
|
||||
|
||||
Common::String imageName; // 0x00
|
||||
// 0xA numDials
|
||||
Common::Array<Common::Rect> srcRects; // 0xC, 10
|
||||
Common::Array<Common::Rect> destRects; // 0xAC, 8
|
||||
Common::Array<Common::Rect> upHotspots; // 0x12C, 8
|
||||
Common::Array<Common::Rect> downHotspots; // 0x1AC, 8
|
||||
Common::Array<byte> correctSequence; // 0x22C
|
||||
Nancy::SoundManager::SoundDescription clickSound; // 0x234, kNormal
|
||||
SceneChangeDesc solveExitScene; // 0x256
|
||||
FlagDesc flagOnSolve; // 0x260
|
||||
uint16 solveSoundDelay; // 0x263
|
||||
Nancy::SoundManager::SoundDescription solveSound; // 0x265
|
||||
SceneChangeDesc exitScene; // 0x287
|
||||
FlagDesc flagOnExit; // 0x291
|
||||
Common::Rect exitHotspot; // 0x294
|
||||
|
||||
SolveState solveState = kNotSolved;
|
||||
Graphics::ManagedSurface image;
|
||||
Common::Array<byte> currentSequence;
|
||||
Time solveSoundPlayTime;
|
||||
|
||||
|
||||
protected:
|
||||
virtual uint16 getZOrder() const override { return 7; }
|
||||
virtual BlitType getBlitType() const override { return kTrans; }
|
||||
virtual bool isViewportRelative() const override { return true; }
|
||||
|
||||
void drawDial(uint id);
|
||||
};
|
||||
|
||||
} // End of namespace Action
|
||||
} // End of namespace Nancy
|
||||
|
||||
#endif // NANCY_ACTION_ROTATINGLOCKPUZZLE_H
|
@ -6,6 +6,7 @@ MODULE_OBJS = \
|
||||
action/orderingpuzzle.o \
|
||||
action/primaryvideo.o \
|
||||
action/recordtypes.o \
|
||||
action/rotatinglockpuzzle.o \
|
||||
action/secondaryvideo.o \
|
||||
action/staticbitmapanim.o \
|
||||
ui/frame.o \
|
||||
|
Loading…
x
Reference in New Issue
Block a user