[Scummvm-git-logs] scummvm master -> 22bdbbfd50c50696945b8480c3b8d875b5722430
fracturehill
noreply at scummvm.org
Fri Dec 29 22:16:39 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:
7ad2367d8b NANCY: Implement forced reloading of sounds
0df1785eb3 NANCY: Implement HamRadioPuzzle
6939fddaa7 NANCY: Show/hide virtual keyboard when saving
8710768d77 NANCY: Show general keymaps in GMM
22bdbbfd50 NANCY: Split maze map key into separate Keymap
Commit: 7ad2367d8bf80027e22a7ea23be743c0d6a535bb
https://github.com/scummvm/scummvm/commit/7ad2367d8bf80027e22a7ea23be743c0d6a535bb
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-12-30T00:16:14+02:00
Commit Message:
NANCY: Implement forced reloading of sounds
In cases where a sound needs to be rapidly replayed
without the need to wait for it to end, loadSound() now
has a parameter for forcing a reload.
Changed paths:
engines/nancy/sound.cpp
engines/nancy/sound.h
diff --git a/engines/nancy/sound.cpp b/engines/nancy/sound.cpp
index a896c7b4387..bdbac095a46 100644
--- a/engines/nancy/sound.cpp
+++ b/engines/nancy/sound.cpp
@@ -259,13 +259,13 @@ SoundManager::~SoundManager() {
stopAllSounds();
}
-void SoundManager::loadSound(const SoundDescription &description, SoundEffectDescription **effectData) {
+void SoundManager::loadSound(const SoundDescription &description, SoundEffectDescription **effectData, bool forceReload) {
if (description.name == "NO SOUND") {
return;
}
Channel &existing = _channels[description.channelID];
- if (existing.stream != nullptr) {
+ if (!forceReload && existing.stream != nullptr) {
// There's a channel already loaded. Check if we're trying to reload the exact same sound
if ( description.name == existing.name &&
description.numLoops == existing.numLoops &&
diff --git a/engines/nancy/sound.h b/engines/nancy/sound.h
index f51d7084a03..a7e10da3ec3 100644
--- a/engines/nancy/sound.h
+++ b/engines/nancy/sound.h
@@ -67,7 +67,7 @@ public:
void initSoundChannels();
// Load a sound into a channel without starting it
- void loadSound(const SoundDescription &description, SoundEffectDescription **effectData = nullptr);
+ void loadSound(const SoundDescription &description, SoundEffectDescription **effectData = nullptr, bool forceReload = false);
void playSound(uint16 channelID);
void playSound(const SoundDescription &description);
Commit: 0df1785eb327080109182d27453c2b6d473c842a
https://github.com/scummvm/scummvm/commit/0df1785eb327080109182d27453c2b6d473c842a
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-12-30T00:16:14+02:00
Commit Message:
NANCY: Implement HamRadioPuzzle
Implemented the action record type responsible for nancy6's
ham radio puzzle sequence.
Changed paths:
A engines/nancy/action/puzzle/hamradiopuzzle.cpp
A engines/nancy/action/puzzle/hamradiopuzzle.h
engines/nancy/action/arfactory.cpp
engines/nancy/module.mk
diff --git a/engines/nancy/action/arfactory.cpp b/engines/nancy/action/arfactory.cpp
index 7f50f3fb289..0887dbd5f91 100644
--- a/engines/nancy/action/arfactory.cpp
+++ b/engines/nancy/action/arfactory.cpp
@@ -36,6 +36,7 @@
#include "engines/nancy/action/puzzle/bombpuzzle.h"
#include "engines/nancy/action/puzzle/collisionpuzzle.h"
#include "engines/nancy/action/puzzle/cubepuzzle.h"
+#include "engines/nancy/action/puzzle/hamradiopuzzle.h"
#include "engines/nancy/action/puzzle/leverpuzzle.h"
#include "engines/nancy/action/puzzle/mazechasepuzzle.h"
#include "engines/nancy/action/puzzle/mouselightpuzzle.h"
@@ -319,6 +320,8 @@ ActionRecord *ActionManager::createActionRecord(uint16 type, Common::SeekableRea
return new BBallPuzzle();
case 220:
return new TwoDialPuzzle();
+ case 221:
+ return new HamRadioPuzzle();
case 222:
return new AssemblyPuzzle();
case 223:
diff --git a/engines/nancy/action/puzzle/hamradiopuzzle.cpp b/engines/nancy/action/puzzle/hamradiopuzzle.cpp
new file mode 100644
index 00000000000..4e7cab73d75
--- /dev/null
+++ b/engines/nancy/action/puzzle/hamradiopuzzle.cpp
@@ -0,0 +1,473 @@
+/* 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 "common/random.h"
+#include "common/config-manager.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/util.h"
+
+#include "engines/nancy/state/scene.h"
+
+#include "engines/nancy/action/puzzle/hamradiopuzzle.h"
+
+namespace Nancy {
+namespace Action {
+
+static const char *morseCodeTable[] = {
+ ".-", "-...", "-.-.", "-..", // a, b, c, d
+ ".", "..-.", "--.", "....", // e, f, g, h
+ "..", ".---", "-.-", ".-..", // i, j, k, l
+ "--", "-.", "---", ".--.", // m, n, o, p
+ "--.-", ".-.", "...", "-", // q, r, s, t
+ "..-", "...-", ".--", "-..-", // u, v, w, x
+ "-.--", "--.." // y, z
+};
+
+void HamRadioPuzzle::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 HamRadioPuzzle::updateGraphics() {
+ if (_digitsRolling) {
+ uint32 curTime = g_nancy->getTotalPlayTime();
+ bool allDigitsCorrect = true;
+
+ for (uint i = 0; i < _numDigits; ++i) {
+ if (curTime > _nextDigitFrameTimes[i]) {
+ uint targetFrame = (_curDigits[i] == 0 ? (10 - 1) * 3 : (_curDigits[i] - 1) * 3);
+
+ if (_displayedDigitFrames[i] == targetFrame) {
+ continue;
+ }
+
+ if (++_displayedDigitFrames[i] >= 10 * 3) {
+ _displayedDigitFrames[i] = 0;
+ }
+
+ // Have we arrived at the correct digit?
+ if (_displayedDigitFrames[i] != targetFrame) {
+ // If not, set the next frame time depending on how far away the next digit is
+ // This way, the animation slows down as we approach the correct digit
+ int frameDifference = targetFrame - _displayedDigitFrames[i];
+ if (frameDifference < 0) {
+ frameDifference += 10 * 3;
+ }
+
+ if (_nextDigitFrameTimes[i] == 0) {
+ _nextDigitFrameTimes[i] = curTime;
+ }
+
+ switch (frameDifference) {
+ case 1:
+ _nextDigitFrameTimes[i] += 300; break;
+ case 2:
+ // fall through
+ case 3:
+ _nextDigitFrameTimes[i] += 200; break;
+ case 4:
+ // fall through
+ case 5:
+ _nextDigitFrameTimes[i] += 100; break;
+ default:
+ _nextDigitFrameTimes[i] += 50; break;
+ }
+
+ // Mark digits as incorrect
+ allDigitsCorrect = false;
+ }
+
+ // Play the rolling sound
+ g_nancy->_sound->loadSound(_digitRollSound, nullptr, true);
+ g_nancy->_sound->playSound(_digitRollSound);
+
+ // Finally, change the digit graphic
+ _drawSurface.blitFrom(_image, _digitSrcs[_displayedDigitFrames[i]], _digitDests[i]);
+ _needsRedraw = true;
+ } else {
+ // Still animating a digit, so we can't be at the correct one yet
+ allDigitsCorrect = false;
+ }
+ }
+
+ if (allDigitsCorrect) {
+ // We've arrived at the correct digits, end the animation state
+ _digitsRolling = false;
+ Common::fill(_nextDigitFrameTimes.begin(), _nextDigitFrameTimes.end(), 0);
+ }
+ }
+}
+
+void HamRadioPuzzle::setFrequency(const Common::Array<uint16> &freq) {
+ _isOnCorrectFrequency = false;
+ _curMorseString.clear();
+ _curCharString.clear();
+
+ if (freq == _startFreq.frequency) {
+ // Check start frequency
+ _startFreq.sound.loadAndPlay();
+ NancySceneState.setEventFlag(_startFreq.flag);
+ } else if (freq == _correctFreq.frequency) {
+ // Check correct transmission frequency
+ _correctFreq.sound.loadAndPlay();
+ NancySceneState.setEventFlag(_correctFreq.flag);
+ _isOnCorrectFrequency = true;
+ } else {
+ // Check other frequencies
+ for (auto &otherFreq : _otherFrequencies) {
+ if (freq == otherFreq.frequency) {
+ otherFreq.sound.loadAndPlay();
+ NancySceneState.setEventFlag(otherFreq.flag);
+ return;
+ }
+ }
+
+ // No frequency found, pick random "bad" sound
+ // This is re-rolled every time a bad frequency is connected to, even if the player
+ // hasn't inputted any new digits
+ _badFrequencySounds[g_nancy->_randomSource->getRandomNumber(_badFrequencySounds.size() - 1)].loadAndPlay();
+ }
+}
+
+void HamRadioPuzzle::CCSound::readData(Common::SeekableReadStream &stream) {
+ char buf[100];
+ stream.read(buf, 100);
+ assembleTextLine(buf, text, 100);
+ sound.readNormal(stream);
+}
+
+void HamRadioPuzzle::CCSound::loadAndPlay() {
+ g_nancy->_sound->loadSound(sound);
+ g_nancy->_sound->playSound(sound);
+
+ if (text.size() && ConfMan.getBool("subtitles")) {
+ NancySceneState.getTextbox().clear();
+ NancySceneState.getTextbox().addTextLine(text);
+ NancySceneState.getTextbox().drawTextbox();
+ }
+}
+
+void HamRadioPuzzle::Frequency::readData(Common::SeekableReadStream &stream, uint16 numDigits) {
+ frequency.resize(numDigits);
+ for (uint i = 0; i < numDigits; ++i) {
+ frequency[i] = stream.readUint16LE();
+ }
+ stream.skip((8 - numDigits) * 2);
+
+ sound.readData(stream);
+ flag.label = stream.readUint16LE();
+ flag.flag = stream.readByte();
+}
+
+void HamRadioPuzzle::readData(Common::SeekableReadStream &stream) {
+ readFilename(stream, _imageName);
+
+ _numDigits = stream.readUint16LE();
+
+ _startFreq.readData(stream, _numDigits);
+ _correctFreq.readData(stream, _numDigits);
+
+ _passwordMaxSize = stream.readUint16LE();
+ readFilename(stream, _password); // not a filename
+ _passwordFlag.label = stream.readUint16LE();
+ _passwordFlag.flag = stream.readByte();
+ readFilename(stream, _codeWord); // not a filename
+
+ stream.skip(2);
+
+ readRectArray(stream, _digitDests, _numDigits, 8);
+ readRectArray(stream, _buttonDests, 10 + 6);
+
+ readRectArray(stream, _digitSrcs, 10 * 3); // digits 0-9, plus 2 inbetweens per digit
+ readRectArray(stream, _buttonSrcs, 10 + 6);
+
+ _digitRollSound.readNormal(stream);
+ _frequencyButtonSound.readData(stream);
+ _connectButtonSound.readData(stream);
+ _dotButtonSound.readData(stream);
+ _dashButtonSound.readData(stream);
+ _sendButtonSound.readData(stream);
+ _deleteButtonSound.readData(stream);
+ _resetButtonSound.readData(stream);
+ _badLetterSound.readData(stream);
+ _longMorseOtherSound.readData(stream);
+ _goodPasswordSound.readData(stream);
+ _longMorseSound.readData(stream);
+
+ _badFrequencySounds.resize(3);
+ for (uint i = 0; i < 3; ++i) {
+ _badFrequencySounds[i].readData(stream);
+ }
+
+ _solveScene.readData(stream);
+ _solveSoundDelay = stream.readUint16LE();
+ _solveSound.readData(stream);
+
+ readRect(stream, _exitButtonDest);
+ readRect(stream, _exitButtonSrc);
+
+ _exitScene.readData(stream);
+ _exitSoundDelay = stream.readUint16LE();
+ _exitSound.readNormal(stream);
+
+ uint16 numOtherFreqs = stream.readUint16LE();
+ _otherFrequencies.resize(numOtherFreqs);
+ for (uint i = 0; i < numOtherFreqs; ++i) {
+ _otherFrequencies[i].readData(stream, _numDigits);
+ }
+
+ _curDigits.resize(_numDigits, 0);
+ _displayedDigitFrames.resize(_numDigits, 0);
+ _nextDigitFrameTimes.resize(_numDigits, 0);
+}
+
+void HamRadioPuzzle::execute() {
+ switch (_state) {
+ case kBegin :
+ init();
+ registerGraphics();
+
+ g_nancy->_sound->loadSound(_digitRollSound);
+ setFrequency(_startFreq.frequency);
+ _curDigits = _startFreq.frequency;
+ _state = kRun;
+ // fall through
+ case kRun :
+ if (_pressedButton != kNone && g_nancy->getTotalPlayTime() > _buttonEndTime) {
+ bool isDot = false;
+
+ // Check for button presses
+ switch (_pressedButton) {
+ case kConnect:
+ setFrequency(_curDigits);
+ break;
+ case kDot:
+ isDot = true;
+ // fall through
+ case kDash:
+ _curMorseString += isDot ? '.' : '-'; // Original engine uses the captions inside the dot and dash sounds
+
+ if (_curMorseString.size() > 4) {
+ _curMorseString.clear();
+ _badLetterSound.loadAndPlay();
+ } else {
+ if (ConfMan.getBool("subtitles")) {
+ NancySceneState.getTextbox().clear();
+ NancySceneState.getTextbox().addTextLine(_curMorseString);
+ NancySceneState.getTextbox().setOverrideFont(3); // Original engine pushes <f3> tag instead
+ NancySceneState.getTextbox().drawTextbox();
+ }
+ }
+
+ break;
+ case kSend: {
+ bool foundCorrect = false;
+
+ if (_curMorseString.size()) {
+ for (uint i = 0; i < ARRAYSIZE(morseCodeTable); ++i) {
+ if (_curMorseString == morseCodeTable[i]) {
+ foundCorrect = true;
+ _curCharString += ('a' + i);
+ break;
+ }
+ }
+ }
+
+ // Check if above maximum length string
+ if (_curMorseString.size() > 10) {
+ _longMorseSound.loadAndPlay();
+ _curCharString.clear();
+ _curMorseString.clear();
+ break;
+ }
+
+ // Morse code is incorrect
+ if (!foundCorrect) {
+ _badLetterSound.loadAndPlay();
+ }
+ }
+
+ // fall through
+ case kDelete:
+ _curMorseString.clear();
+
+ if (_curCharString.size() > 10) {
+ // Password is above max size, clear
+ _curCharString.clear();
+ NancySceneState.getTextbox().clear();
+ _longMorseSound.loadAndPlay();
+ } else if (_solvedPassword && _curCharString.size() > _passwordMaxSize) {
+ // Password is above max size, clear
+ _curCharString.clear();
+ NancySceneState.getTextbox().clear();
+ _longMorseOtherSound.loadAndPlay();
+ }
+
+ if (ConfMan.getBool("subtitles")) {
+ NancySceneState.getTextbox().clear();
+ NancySceneState.getTextbox().addTextLine(_curCharString);
+ NancySceneState.getTextbox().drawTextbox();
+ }
+
+ if (_isOnCorrectFrequency) {
+ // When transmitting on right frequency, check password/code word
+ if (!_solvedPassword) {
+ // Password not solved, check against it
+ if (_curCharString == _password) {
+ _solvedPassword = true;
+ NancySceneState.setEventFlag(_passwordFlag);
+ _curCharString.clear();
+ _goodPasswordSound.loadAndPlay();
+ }
+ } else {
+ // Password solved, check against codeword
+ if (_curCharString == _codeWord) {
+ _solvedCodeword = true;
+ _curCharString.clear();
+
+ _solveSound.loadAndPlay(); // Sound delay is ignored
+ }
+ }
+ }
+
+ break;
+ case kReset:
+ _curCharString.clear();
+ _curMorseString.clear();
+ NancySceneState.getTextbox().clear();
+
+ break;
+ default:
+ // Number digit
+ for (int i = 0; i < _numDigits - 1; ++i) {
+ _curDigits[i] = _curDigits[i + 1];
+ }
+
+ _curDigits.back() = (_pressedButton == 9 ? 0 : _pressedButton + 1);
+ _digitsRolling = true;
+
+ break;
+ }
+
+ _drawSurface.fillRect(_buttonDests[_pressedButton], _drawSurface.getTransparentColor());
+ _needsRedraw = true;
+
+ _pressedButton = kNone;
+ }
+
+ break;
+ case kActionTrigger:
+ if (_digitsRolling) {
+ return;
+ }
+
+ if (_solvedCodeword) {
+ _solveScene.execute();
+ } else {
+ // Fail sound is ignored
+ _exitScene.execute();
+ }
+
+ finishExecution();
+ break;
+ }
+}
+
+void HamRadioPuzzle::handleInput(NancyInput &input) {
+ if (_digitsRolling || _state != kRun || _pressedButton != kNone) {
+ return;
+ }
+
+ // Handle exit button
+ if (NancySceneState.getViewport().convertViewportToScreen(_exitButtonDest).contains(input.mousePos)) {
+ g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
+
+ if (input.input & NancyInput::kLeftMouseButtonUp) {
+ _state = kActionTrigger;
+ for (uint i = 0; i < _curDigits.size(); ++i) {
+ _curDigits[i] = 0;
+ }
+ _digitsRolling = true;
+ _drawSurface.blitFrom(_image, _exitButtonSrc, _exitButtonDest);
+ _needsRedraw = true;
+ }
+ return;
+ }
+
+ // Handle other buttons
+ for (uint i = 0; i < _buttonDests.size(); ++i) {
+ if (NancySceneState.getViewport().convertViewportToScreen(_buttonDests[i]).contains(input.mousePos)) {
+ if (i >= 10 || _pressedButton == kNone) {
+ g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
+
+ if (input.input & NancyInput::kLeftMouseButtonUp) {
+ _pressedButton = i;
+ _drawSurface.blitFrom(_image, _buttonSrcs[i], _buttonDests[i]);
+ _needsRedraw = true;
+
+ CCSound *soundToPlay = nullptr;
+
+ switch (i) {
+ case kConnect:
+ soundToPlay = &_connectButtonSound; break;
+ case kDot:
+ soundToPlay = &_dotButtonSound; break;
+ case kDash:
+ soundToPlay = &_dashButtonSound; break;
+ case kSend:
+ soundToPlay = &_sendButtonSound; break;
+ case kDelete:
+ soundToPlay = &_deleteButtonSound; break;
+ case kReset:
+ soundToPlay = &_resetButtonSound; break;
+ default:
+ soundToPlay = &_frequencyButtonSound; break;
+ }
+
+ // Do NOT use the loadAndPlaySound() function, since the dot/dash sounds have ./- captions
+ g_nancy->_sound->loadSound(soundToPlay->sound, nullptr, true);
+ g_nancy->_sound->playSound(soundToPlay->sound);
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (_pressedButton != kNone) {
+ _buttonEndTime = g_nancy->getTotalPlayTime() + 250;
+ }
+}
+
+} // End of namespace Action
+} // End of namespace Nancy
diff --git a/engines/nancy/action/puzzle/hamradiopuzzle.h b/engines/nancy/action/puzzle/hamradiopuzzle.h
new file mode 100644
index 00000000000..47f11f4125e
--- /dev/null
+++ b/engines/nancy/action/puzzle/hamradiopuzzle.h
@@ -0,0 +1,137 @@
+/* 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_HAMRADIOPUZZLE_H
+#define NANCY_ACTION_HAMRADIOPUZZLE_H
+
+#include "engines/nancy/action/actionrecord.h"
+
+namespace Nancy {
+namespace Action {
+
+// A puzzle that has the player input radio frequencies, and
+// send morse code data via ham radio. Used in nancy6.
+class HamRadioPuzzle : public RenderActionRecord {
+public:
+ HamRadioPuzzle() : RenderActionRecord(7) {}
+ virtual ~HamRadioPuzzle() {}
+
+ void init() override;
+ void updateGraphics() override;
+
+ void readData(Common::SeekableReadStream &stream) override;
+ void execute() override;
+ void handleInput(NancyInput &input) override;
+
+protected:
+ Common::String getRecordTypeName() const override { return "HamRadioPuzzle"; }
+ bool isViewportRelative() const override { return true; }
+
+ void setFrequency(const Common::Array<uint16> &freq);
+
+ // 0-10 are the digit buttons
+ enum ButtonPress { kNone = -1, kConnect = 10, kDot = 11, kDash = 12, kSend = 13, kDelete = 14, kReset = 15 };
+
+ struct CCSound {
+ Common::String text;
+ SoundDescription sound;
+
+ void readData(Common::SeekableReadStream &stream);
+ void loadAndPlay();
+ };
+
+ struct Frequency {
+ Common::Array<uint16> frequency;
+ CCSound sound;
+ FlagDescription flag;
+
+ void readData(Common::SeekableReadStream &stream, uint16 numDigits);
+ };
+
+ Common::Path _imageName;
+
+ uint16 _numDigits = 0;
+
+ Frequency _startFreq;
+ Frequency _correctFreq;
+
+ uint16 _passwordMaxSize = 0;
+ Common::String _password;
+ FlagDescription _passwordFlag;
+ Common::String _codeWord;
+
+ Common::Array<Common::Rect> _digitDests;
+ Common::Array<Common::Rect> _buttonDests;
+
+ Common::Array<Common::Rect> _digitSrcs;
+ Common::Array<Common::Rect> _buttonSrcs;
+
+ SoundDescription _digitRollSound;
+ CCSound _frequencyButtonSound;
+ CCSound _connectButtonSound;
+ CCSound _dotButtonSound;
+ CCSound _dashButtonSound;
+ CCSound _sendButtonSound;
+ CCSound _deleteButtonSound;
+ CCSound _resetButtonSound;
+ CCSound _badLetterSound;
+ CCSound _longMorseOtherSound;
+ CCSound _goodPasswordSound;
+ CCSound _longMorseSound;
+ Common::Array<CCSound> _badFrequencySounds;
+
+ SceneChangeWithFlag _solveScene;
+ uint16 _solveSoundDelay = 0; // not used
+ CCSound _solveSound;
+
+ Common::Rect _exitButtonDest;
+ Common::Rect _exitButtonSrc;
+
+ SceneChangeWithFlag _exitScene;
+ uint16 _exitSoundDelay = 0; // not used
+ SoundDescription _exitSound; // not used
+
+ Common::Array<Frequency> _otherFrequencies;
+
+ Graphics::ManagedSurface _image;
+
+ // Frequency display data
+ bool _digitsRolling = true;
+ Common::Array<uint16> _curDigits;
+ Common::Array<uint16> _displayedDigitFrames;
+ Common::Array<uint32> _nextDigitFrameTimes;
+
+ // Sent morse code
+ Common::String _curMorseString;
+ Common::String _curCharString;
+
+ int _pressedButton = kNone;
+ uint32 _buttonEndTime = 0;
+
+ bool _isOnCorrectFrequency = false;
+ bool _solvedPassword = false;
+ bool _solvedCodeword = false;
+};
+
+} // End of namespace Action
+} // End of namespace Nancy
+
+#endif // NANCY_ACTION_HAMRADIOPUZZLE_H
diff --git a/engines/nancy/module.mk b/engines/nancy/module.mk
index 7d12ec1bf97..74cecf79072 100644
--- a/engines/nancy/module.mk
+++ b/engines/nancy/module.mk
@@ -19,6 +19,7 @@ MODULE_OBJS = \
action/puzzle/bombpuzzle.o \
action/puzzle/collisionpuzzle.o \
action/puzzle/cubepuzzle.o \
+ action/puzzle/hamradiopuzzle.o \
action/puzzle/leverpuzzle.o \
action/puzzle/mazechasepuzzle.o \
action/puzzle/mouselightpuzzle.o \
Commit: 6939fddaa7c7b16a1c4876564b0fe2f797aaa347
https://github.com/scummvm/scummvm/commit/6939fddaa7c7b16a1c4876564b0fe2f797aaa347
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-12-30T00:16:14+02:00
Commit Message:
NANCY: Show/hide virtual keyboard when saving
Changed paths:
engines/nancy/state/loadsave.cpp
diff --git a/engines/nancy/state/loadsave.cpp b/engines/nancy/state/loadsave.cpp
index 06bbff6eeda..4ec9f4b3a2e 100644
--- a/engines/nancy/state/loadsave.cpp
+++ b/engines/nancy/state/loadsave.cpp
@@ -399,6 +399,7 @@ void LoadSaveMenu::enterFilename() {
_blinkingCursorOverlay.setVisible(true);
_nextBlink = g_nancy->getTotalPlayTime() + _loadSaveData->_blinkingTimeDelay;
_enteringNewState = false;
+ g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
}
// Perform cursor blinking
@@ -436,6 +437,7 @@ void LoadSaveMenu::enterFilename() {
_state = kRun;
_enteringNewState = true;
g_nancy->_sound->playSound("BULS");
+ g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
return;
}
@@ -444,6 +446,7 @@ void LoadSaveMenu::enterFilename() {
_state = kSave;
_enteringNewState = true;
g_nancy->_sound->playSound("BULS");
+ g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
return;
}
}
Commit: 8710768d77176a687069a60e8eacc00074ed804e
https://github.com/scummvm/scummvm/commit/8710768d77176a687069a60e8eacc00074ed804e
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-12-30T00:16:14+02:00
Commit Message:
NANCY: Show general keymaps in GMM
Fixed an issue in the nancy MetaEngine which caused
the general keymaps to not be shown alongside the
engine-specific ones.
Changed paths:
engines/nancy/metaengine.cpp
diff --git a/engines/nancy/metaengine.cpp b/engines/nancy/metaengine.cpp
index 0f6b9a1b5b6..0d1f5cd5609 100644
--- a/engines/nancy/metaengine.cpp
+++ b/engines/nancy/metaengine.cpp
@@ -123,7 +123,7 @@ public:
};
Common::KeymapArray NancyMetaEngine::initKeymaps(const char *target) const {
- Common::KeymapArray keymaps;
+ Common::KeymapArray keymaps = MetaEngine::initKeymaps(target);
Nancy::InputManager::initKeymaps(keymaps, target);
return keymaps;
}
Commit: 22bdbbfd50c50696945b8480c3b8d875b5722430
https://github.com/scummvm/scummvm/commit/22bdbbfd50c50696945b8480c3b8d875b5722430
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-12-30T00:16:14+02:00
Commit Message:
NANCY: Split maze map key into separate Keymap
The "Open map" action used in nancy3/nancy6's
RaycastPuzzle interfered with general keyboard input,
causing whichever key was bound to it to not fire.
Effectively, this meant that inputting the letter 'm' was
impossible. This commit makes sure the binding is
deactivated whenever text input is needed.
Changed paths:
engines/nancy/action/puzzle/passwordpuzzle.cpp
engines/nancy/action/puzzle/riddlepuzzle.cpp
engines/nancy/input.cpp
engines/nancy/input.h
engines/nancy/state/loadsave.cpp
diff --git a/engines/nancy/action/puzzle/passwordpuzzle.cpp b/engines/nancy/action/puzzle/passwordpuzzle.cpp
index d538731ac3d..b77360cd971 100644
--- a/engines/nancy/action/puzzle/passwordpuzzle.cpp
+++ b/engines/nancy/action/puzzle/passwordpuzzle.cpp
@@ -92,6 +92,7 @@ void PasswordPuzzle::execute() {
init();
registerGraphics();
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
+ g_nancy->_input->enableSecondaryKeymaps(false);
_nextBlinkTime = g_nancy->getTotalPlayTime() + _cursorBlinkTime;
_state = kRun;
// fall through
@@ -180,6 +181,7 @@ void PasswordPuzzle::execute() {
}
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
+ g_nancy->_input->enableSecondaryKeymaps(true);
finishExecution();
}
}
diff --git a/engines/nancy/action/puzzle/riddlepuzzle.cpp b/engines/nancy/action/puzzle/riddlepuzzle.cpp
index 25441773bef..09238414efd 100644
--- a/engines/nancy/action/puzzle/riddlepuzzle.cpp
+++ b/engines/nancy/action/puzzle/riddlepuzzle.cpp
@@ -145,6 +145,7 @@ void RiddlePuzzle::execute() {
if (!g_nancy->_sound->isSoundPlaying(_riddles[_riddleID].sound)) {
_solveState = kNotSolved;
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
+ g_nancy->_input->enableSecondaryKeymaps(false);
}
@@ -257,6 +258,7 @@ void RiddlePuzzle::execute() {
sceneChange->execute();
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
+ g_nancy->_input->enableSecondaryKeymaps(true);
finishExecution();
}
}
diff --git a/engines/nancy/input.cpp b/engines/nancy/input.cpp
index b589ddfe375..8338a0e1c7d 100644
--- a/engines/nancy/input.cpp
+++ b/engines/nancy/input.cpp
@@ -23,6 +23,7 @@
#include "backends/keymapper/action.h"
#include "backends/keymapper/keymap.h"
+#include "backends/keymapper/keymapper.h"
#include "backends/keymapper/standard-actions.h"
#include "engines/nancy/nancy.h"
@@ -30,6 +31,8 @@
namespace Nancy {
+static const char *mazeKeymapID = "nancy-maze";
+
void InputManager::processEvents() {
using namespace Common;
Common::Event event;
@@ -155,10 +158,18 @@ void InputManager::forceCleanInput() {
_otherKbdInput.clear();
}
+void InputManager::enableSecondaryKeymaps(bool enabled) {
+ Common::Keymapper *keymapper = g_nancy->getEventManager()->getKeymapper();
+ Common::Keymap *mazeKeymap = keymapper->getKeymap(mazeKeymapID);
+ if (mazeKeymap)
+ mazeKeymap->setEnabled(enabled);
+}
+
void InputManager::initKeymaps(Common::KeymapArray &keymaps, const char *target) {
using namespace Common;
using namespace Nancy;
+ Common::String gameId = ConfMan.get("gameid", target);
Keymap *mainKeymap = new Keymap(Keymap::kKeymapTypeGame, "nancy-main", "Nancy Drew");
Action *act;
@@ -211,17 +222,20 @@ void InputManager::initKeymaps(Common::KeymapArray &keymaps, const char *target)
act->addDefaultInputMapping("ESCAPE");
act->addDefaultInputMapping("JOY_START");
mainKeymap->addAction(act);
+
+ keymaps.push_back(mainKeymap);
- Common::String t(target);
- if (t.hasPrefix("nancy3") || t.hasPrefix("nancy6")) {
+ if (gameId == "nancy3" || gameId == "nancy6") {
+ Keymap *mazeKeymap = new Keymap(Keymap::kKeymapTypeGame, mazeKeymapID, "Nancy Drew - Maze");
+
act = new Action("RAYCM", _("Show/hide maze map"));
act->setCustomEngineActionEvent(kNancyActionShowRaycastMap);
act->addDefaultInputMapping("m");
act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
- mainKeymap->addAction(act);
- }
+ mazeKeymap->addAction(act);
- keymaps.push_back(mainKeymap);
+ keymaps.push_back(mazeKeymap);
+ }
}
} // End of namespace Nancy
diff --git a/engines/nancy/input.h b/engines/nancy/input.h
index de816b4a597..b09b32c8904 100644
--- a/engines/nancy/input.h
+++ b/engines/nancy/input.h
@@ -93,6 +93,7 @@ public:
NancyInput getInput() const;
void forceCleanInput();
void setMouseInputEnabled(bool enabled) { _mouseEnabled = enabled; }
+ void enableSecondaryKeymaps(bool enabled);
static void initKeymaps(Common::KeymapArray &keymaps, const char *target);
diff --git a/engines/nancy/state/loadsave.cpp b/engines/nancy/state/loadsave.cpp
index 4ec9f4b3a2e..e09f3896918 100644
--- a/engines/nancy/state/loadsave.cpp
+++ b/engines/nancy/state/loadsave.cpp
@@ -69,6 +69,7 @@ void LoadSaveMenu::process() {
switch (_state) {
case kInit:
init();
+ g_nancy->_input->enableSecondaryKeymaps(false);
// fall through
case kRun:
run();
@@ -92,6 +93,7 @@ void LoadSaveMenu::process() {
// Make sure stop runs on the same frame
if (_state == kStop) {
stop();
+ g_nancy->_input->enableSecondaryKeymaps(true);
}
g_nancy->_cursorManager->setCursorType(CursorManager::kNormalArrow);
More information about the Scummvm-git-logs
mailing list