[Scummvm-git-logs] scummvm master -> 6a07442d53efd0e3622cdc592db815688cf2d3d0
fracturehill
76959842+fracturehill at users.noreply.github.com
Thu Apr 8 18:54:13 UTC 2021
This automated email contains information about 7 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
36118700b9 NANCY: Fix state changing
a8a7f0ee57 NANCY: Fix MapCallHot1Fr action record
9bb543a69e NANCY: Common sound handling changes
9f35d133ca NANCY: Implement sound options, add options dialog
68e54edd50 NANCY: Initial main menu implementation
f98da95b1f NANCY: Fix doubled input between states
6a07442d53 NANCY: Cheat dialogs fixes
Commit: 36118700b97edff3a3ccb00126054be51af8980d
https://github.com/scummvm/scummvm/commit/36118700b97edff3a3ccb00126054be51af8980d
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-08T21:42:51+03:00
Commit Message:
NANCY: Fix state changing
Fixed the state system so it supports changing between two states that both get destroyed after exiting.
Changed paths:
engines/nancy/console.cpp
engines/nancy/input.cpp
engines/nancy/input.h
engines/nancy/nancy.cpp
engines/nancy/nancy.h
engines/nancy/state/credits.cpp
engines/nancy/state/credits.h
engines/nancy/state/help.cpp
engines/nancy/state/help.h
engines/nancy/state/logo.cpp
engines/nancy/state/logo.h
engines/nancy/state/map.cpp
engines/nancy/state/map.h
engines/nancy/state/scene.cpp
engines/nancy/state/scene.h
engines/nancy/state/state.h
diff --git a/engines/nancy/console.cpp b/engines/nancy/console.cpp
index 68d82c3903..8b8cffd593 100644
--- a/engines/nancy/console.cpp
+++ b/engines/nancy/console.cpp
@@ -315,7 +315,7 @@ bool NancyConsole::Cmd_loadScene(int argc, const char **argv) {
return true;
}
- if (g_nancy->_gameFlow.previousState != &NancySceneState) {
+ if (g_nancy->_gameFlow.curState != NancyState::kScene) {
debugPrintf("Not in the kScene state\n");
return true;
}
@@ -333,7 +333,7 @@ bool NancyConsole::Cmd_loadScene(int argc, const char **argv) {
}
bool NancyConsole::Cmd_sceneID(int argc, const char **argv) {
- if (g_nancy->_gameFlow.previousState != &NancySceneState) {
+ if (g_nancy->_gameFlow.curState != NancyState::kScene) {
debugPrintf("Not in the kScene state\n");
return true;
}
diff --git a/engines/nancy/input.cpp b/engines/nancy/input.cpp
index f103c9e455..bad1c93b56 100644
--- a/engines/nancy/input.cpp
+++ b/engines/nancy/input.cpp
@@ -50,7 +50,7 @@ void InputManager::processEvents() {
}
break;
case EVENT_CUSTOM_ENGINE_ACTION_START:
- if (_inputBeginState == nullptr) {
+ if (_inputBeginState == NancyState::kNone) {
_inputBeginState = g_nancy->getState();
}
@@ -125,7 +125,7 @@ void InputManager::processEvents() {
}
if (_inputs == 0 && _otherKbdInput.size() == 0) {
- _inputBeginState = nullptr;
+ _inputBeginState = NancyState::kNone;
}
}
diff --git a/engines/nancy/input.h b/engines/nancy/input.h
index 29b96cc75d..22305f9531 100644
--- a/engines/nancy/input.h
+++ b/engines/nancy/input.h
@@ -91,7 +91,7 @@ public:
InputManager() :
_inputs(0),
_mouseEnabled(true),
- _inputBeginState(nullptr) {}
+ _inputBeginState(NancyState::kNone) {}
void processEvents();
@@ -105,7 +105,7 @@ private:
uint16 _inputs;
Common::Array<Common::KeyState> _otherKbdInput;
bool _mouseEnabled;
- State::State *_inputBeginState;
+ NancyState::NancyState _inputBeginState;
};
} // End of namespace Nancy
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index 3368519651..81b1ee72c4 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -148,11 +148,10 @@ void NancyEngine::setState(NancyState::NancyState state, NancyState::NancyState
bootGameEngine();
setState(NancyState::kLogo);
return;
- case NancyState::kMainMenu:
- if (_gameFlow.currentState) {
- if (_gameFlow.currentState->onStateExit()) {
- _gameFlow.currentState = nullptr;
- }
+ case NancyState::kMainMenu: {
+ State::State *s = getStateObject(_gameFlow.curState);
+ if (s) {
+ s->onStateExit();
}
// TODO until the game's own menus are implemented we simply open the GMM
@@ -162,11 +161,13 @@ void NancyEngine::setState(NancyState::NancyState state, NancyState::NancyState
return;
}
- if (_gameFlow.currentState) {
- _gameFlow.currentState->onStateEnter();
+ s = getStateObject(_gameFlow.curState);
+ if (s) {
+ s->onStateEnter();
}
return;
+ }
case NancyState::kCheat:
if (_cheatTypeIsEventFlag) {
EventFlagDialog *dialog = new EventFlagDialog();
@@ -185,32 +186,37 @@ void NancyEngine::setState(NancyState::NancyState state, NancyState::NancyState
_graphicsManager->clearObjects();
- _gameFlow.previousState = _gameFlow.currentState;
- _gameFlow.currentState = getStateObject(state);
-
- if (_gameFlow.previousState) {
- _gameFlow.previousState->onStateExit();
+ State::State *s = getStateObject(_gameFlow.curState);
+ if (s) {
+ s->onStateExit();
}
-
- if (_gameFlow.currentState) {
- _gameFlow.currentState->onStateEnter();
+
+ s = getStateObject(state);
+ if (s) {
+ s->onStateEnter();
}
if (overridePrevious != NancyState::kNone) {
- _gameFlow.previousState = getStateObject(state);
+ _gameFlow.prevState = overridePrevious;
+ } else {
+ _gameFlow.prevState = _gameFlow.curState;
}
+
+ _gameFlow.curState = state;
}
-void NancyEngine::setPreviousState() {
- if (_gameFlow.currentState) {
- _gameFlow.currentState->onStateExit();
+void NancyEngine::setToPreviousState() {
+ State::State *s = getStateObject(_gameFlow.curState);
+ if (s) {
+ s->onStateExit();
}
- if (_gameFlow.previousState) {
- _gameFlow.previousState->onStateEnter();
+ s = getStateObject(_gameFlow.prevState);
+ if (s) {
+ s->onStateEnter();
}
- SWAP<Nancy::State::State *>(_gameFlow.currentState, _gameFlow.previousState);
+ SWAP<NancyState::NancyState>(_gameFlow.curState, _gameFlow.prevState);
}
void NancyEngine::setMouseEnabled(bool enabled) {
@@ -241,9 +247,10 @@ Common::Error NancyEngine::run() {
while (!shouldQuit()) {
_cursorManager->setCursorType(CursorManager::kNormalArrow);
_input->processEvents();
-
- if (_gameFlow.currentState) {
- _gameFlow.currentState->process();
+
+ State::State *s = getStateObject(_gameFlow.curState);
+ if (s) {
+ s->process();
}
_graphicsManager->draw();
@@ -252,7 +259,9 @@ Common::Error NancyEngine::run() {
_system->delayMillis(16);
}
- NancySceneState.destroy();
+ if (State::Scene::hasInstance()) {
+ NancySceneState.destroy();
+ }
return Common::kNoError;
}
diff --git a/engines/nancy/nancy.h b/engines/nancy/nancy.h
index 1579d6e169..bca65a7a98 100644
--- a/engines/nancy/nancy.h
+++ b/engines/nancy/nancy.h
@@ -74,11 +74,6 @@ class NancyConsole;
namespace State {
class State;
-class Logo;
-class Scene;
-class Map;
-class Help;
-class Credits;
}
class NancyEngine : public Engine {
@@ -104,8 +99,8 @@ public:
Common::Platform getPlatform() const;
void setState(NancyState::NancyState state, NancyState::NancyState overridePrevious = NancyState::kNone);
- State::State *getState() { return _gameFlow.currentState; }
- void setPreviousState();
+ NancyState::NancyState getState() { return _gameFlow.curState; }
+ void setToPreviousState();
// Chunks found in BOOT get extracted and cached at startup, this function lets other classes access them
Common::SeekableReadStream *getBootChunkStream(const Common::String &name) const;
@@ -133,8 +128,8 @@ public:
private:
struct GameFlow {
- State::State *currentState = nullptr;
- State::State *previousState = nullptr;
+ NancyState::NancyState curState = NancyState::kNone;
+ NancyState::NancyState prevState = NancyState::kNone;
};
virtual Common::Error run() override;
diff --git a/engines/nancy/state/credits.cpp b/engines/nancy/state/credits.cpp
index 2d8b41abf1..d174622a9e 100644
--- a/engines/nancy/state/credits.cpp
+++ b/engines/nancy/state/credits.cpp
@@ -90,9 +90,10 @@ void Credits::run() {
if (input.input & NancyInput::kLeftMouseButtonDown) {
_state = kInit;
g_nancy->_sound->stopSound(_sound);
- g_nancy->setState(NancyState::kMainMenu);
g_nancy->_cursorManager->showCursor(true);
_fullTextSurface.free();
+ g_nancy->setState(NancyState::kMainMenu);
+ return;
}
Time currentTime = g_nancy->getTotalPlayTime();
diff --git a/engines/nancy/state/credits.h b/engines/nancy/state/credits.h
index 057930916a..e1bb065e2a 100644
--- a/engines/nancy/state/credits.h
+++ b/engines/nancy/state/credits.h
@@ -43,7 +43,7 @@ public:
// State API
virtual void process() override;
- virtual bool onStateExit() override { destroy(); return true; };
+ virtual void onStateExit() override { destroy(); };
protected:
void init();
diff --git a/engines/nancy/state/help.cpp b/engines/nancy/state/help.cpp
index ba8c03bb2a..72b80b9077 100644
--- a/engines/nancy/state/help.cpp
+++ b/engines/nancy/state/help.cpp
@@ -97,7 +97,7 @@ void Help::run() {
void Help::waitForSound() {
if (!g_nancy->_sound->isSoundPlaying(18)) {
g_nancy->_sound->stopSound(_sound);
- g_nancy->setPreviousState();
+ g_nancy->setToPreviousState();
}
}
diff --git a/engines/nancy/state/help.h b/engines/nancy/state/help.h
index bb76b8cb15..01439a5ed9 100644
--- a/engines/nancy/state/help.h
+++ b/engines/nancy/state/help.h
@@ -42,7 +42,7 @@ public:
// State API
virtual void process() override;
- virtual bool onStateExit() override { destroy(); return true; };
+ virtual void onStateExit() override { destroy(); };
private:
void init();
diff --git a/engines/nancy/state/logo.cpp b/engines/nancy/state/logo.cpp
index 56d80e627d..bd60fbe477 100644
--- a/engines/nancy/state/logo.cpp
+++ b/engines/nancy/state/logo.cpp
@@ -49,10 +49,9 @@ void Logo::process() {
}
}
-bool Logo::onStateExit() {
+void Logo::onStateExit() {
g_nancy->_sound->stopSound(_msnd);
destroy();
- return true;
}
void Logo::init() {
diff --git a/engines/nancy/state/logo.h b/engines/nancy/state/logo.h
index b780beacd3..6002f018df 100644
--- a/engines/nancy/state/logo.h
+++ b/engines/nancy/state/logo.h
@@ -41,7 +41,7 @@ public:
// State API
virtual void process() override;
- virtual bool onStateExit() override;
+ virtual void onStateExit() override;
private:
void init();
diff --git a/engines/nancy/state/map.cpp b/engines/nancy/state/map.cpp
index b2f387562f..466fe8f5be 100644
--- a/engines/nancy/state/map.cpp
+++ b/engines/nancy/state/map.cpp
@@ -158,15 +158,13 @@ void Map::run() {
}
}
-bool Map::onStateExit() {
+void Map::onStateExit() {
Common::SeekableReadStream *chunk = g_nancy->getBootChunkStream("MAP");
SoundDescription sound;
chunk->seek(0x18 + _mapID * 0x20, SEEK_SET);
sound.read(*chunk, SoundDescription::kMenu);
g_nancy->_sound->stopSound(sound);
- g_nancy->setState(NancyState::kScene);
-
if (_pickedLocationID != -1) {
auto &loc = _locations[_pickedLocationID];
NancySceneState.changeScene(loc.scenes[_mapID].sceneID, loc.scenes[_mapID].frameID, loc.scenes[_mapID].verticalOffset, false);
@@ -181,7 +179,6 @@ bool Map::onStateExit() {
_mapButtonClicked = false;
destroy();
- return true;
}
void Map::registerGraphics() {
diff --git a/engines/nancy/state/map.h b/engines/nancy/state/map.h
index 8e807ca9f8..c433961c08 100644
--- a/engines/nancy/state/map.h
+++ b/engines/nancy/state/map.h
@@ -45,7 +45,7 @@ public:
// State API
virtual void process() override;
- virtual bool onStateExit() override;
+ virtual void onStateExit() override;
private:
struct Location {
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index b7e10879dc..ac7bb8e93f 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -124,13 +124,11 @@ void Scene::onStateEnter() {
}
}
-bool Scene::onStateExit() {
+void Scene::onStateExit() {
_timers.pushedPlayTime = g_nancy->getTotalPlayTime();
_actionManager.onPause(true);
pauseSceneSpecificSounds();
_gameStateRequested = NancyState::kNone;
-
- return false;
}
void Scene::changeScene(uint16 id, uint16 frame, uint16 verticalOffset, bool noSound) {
diff --git a/engines/nancy/state/scene.h b/engines/nancy/state/scene.h
index 9ab6724e9b..dfd8d36068 100644
--- a/engines/nancy/state/scene.h
+++ b/engines/nancy/state/scene.h
@@ -116,7 +116,7 @@ public:
// State API
virtual void process() override;
virtual void onStateEnter() override;
- virtual bool onStateExit() override;
+ virtual void onStateExit() override;
void changeScene(uint16 id, uint16 frame, uint16 verticalOffset, bool noSound);
void changeScene(const SceneChangeDescription &sceneDescription);
diff --git a/engines/nancy/state/state.h b/engines/nancy/state/state.h
index 489e2c1a49..0720191909 100644
--- a/engines/nancy/state/state.h
+++ b/engines/nancy/state/state.h
@@ -34,7 +34,7 @@ public:
virtual void process() = 0;
virtual void onStateEnter() {}
- virtual bool onStateExit() { return true; } // Returns whether the object destroyed itself after exit
+ virtual void onStateExit() {}
};
} // End of namespace State
Commit: a8a7f0ee57abc995ed67a5634e9f8be3af38c08c
https://github.com/scummvm/scummvm/commit/a8a7f0ee57abc995ed67a5634e9f8be3af38c08c
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-08T21:42:52+03:00
Commit Message:
NANCY: Fix MapCallHot1Fr action record
Fixed the MapCallHot1Fr action record, which accidentally got broken during a previous refactoring.
Changed paths:
engines/nancy/action/recordtypes.cpp
diff --git a/engines/nancy/action/recordtypes.cpp b/engines/nancy/action/recordtypes.cpp
index 4794a1e502..d635a492b0 100644
--- a/engines/nancy/action/recordtypes.cpp
+++ b/engines/nancy/action/recordtypes.cpp
@@ -124,7 +124,7 @@ void MapCall::execute() {
}
void MapCallHot1Fr::readData(Common::SeekableReadStream &stream) {
- stream.skip(0x12);
+ _hotspotDesc.readData(stream);
}
void MapCallHot1Fr::execute() {
Commit: 9bb543a69edb25d58058c42496428ae35b1aac80
https://github.com/scummvm/scummvm/commit/9bb543a69edb25d58058c42496428ae35b1aac80
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-08T21:42:52+03:00
Commit Message:
NANCY: Common sound handling changes
SoundManager is now responsible for loading and storing all common sounds (sounds with their own BOOT chunk). All playSound() calls with a hardcoded channel ID now use the chunk name instead. Also fixed some sound inaccuracies when switching between states.
Changed paths:
engines/nancy/action/actionmanager.cpp
engines/nancy/action/recordtypes.cpp
engines/nancy/nancy.cpp
engines/nancy/sound.cpp
engines/nancy/sound.h
engines/nancy/state/credits.cpp
engines/nancy/state/help.cpp
engines/nancy/state/help.h
engines/nancy/state/logo.cpp
engines/nancy/state/map.cpp
engines/nancy/state/map.h
engines/nancy/state/scene.cpp
engines/nancy/ui/button.cpp
engines/nancy/ui/inventorybox.cpp
diff --git a/engines/nancy/action/actionmanager.cpp b/engines/nancy/action/actionmanager.cpp
index 3fcd82214f..30b07b7dc2 100644
--- a/engines/nancy/action/actionmanager.cpp
+++ b/engines/nancy/action/actionmanager.cpp
@@ -64,7 +64,7 @@ void ActionManager::handleInput(NancyInput &input) {
}
if (!shouldTrigger) {
- g_nancy->_sound->playSound(17); // Hardcoded by original engine
+ g_nancy->_sound->playSound("CANT");
}
} else {
shouldTrigger = true;
diff --git a/engines/nancy/action/recordtypes.cpp b/engines/nancy/action/recordtypes.cpp
index d635a492b0..59582aa0c5 100644
--- a/engines/nancy/action/recordtypes.cpp
+++ b/engines/nancy/action/recordtypes.cpp
@@ -398,7 +398,7 @@ void ShowInventoryItem::execute() {
break;
}
case kActionTrigger:
- g_nancy->_sound->playSound(24); // Hardcoded by original engine
+ g_nancy->_sound->playSound("BUOK");
NancySceneState.addItemToInventory(_objectID);
setVisible(false);
_hasHotspot = false;
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index 81b1ee72c4..2a7f82d2de 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -317,25 +317,11 @@ void NancyEngine::bootGameEngine() {
"CLOK", "SPEC"
};
- Common::String persistentSounds[] = {
- "BUOK", "BUDE", "BULS", "GLOB", "CURT",
- "CANT"
- };
-
- SoundDescription desc;
-
for (auto const &n : names) {
addBootChunk(n, boot->getChunkStream(n));
}
- // Persistent sounds that are used across the engine. These originally get loaded inside Logo
- for (auto const &s : persistentSounds) {
- Common::SeekableReadStream *str = g_nancy->getBootChunkStream(s);
- if (str) {
- desc.read(*str, SoundDescription::kNormal);
- g_nancy->_sound->loadSound(desc);
- }
- }
+ _sound->loadCommonSounds();
delete boot;
diff --git a/engines/nancy/sound.cpp b/engines/nancy/sound.cpp
index 78f956e88a..1f1f9e8b59 100644
--- a/engines/nancy/sound.cpp
+++ b/engines/nancy/sound.cpp
@@ -215,6 +215,36 @@ SoundManager::SoundManager() {
initSoundChannels();
}
+void SoundManager::loadCommonSounds() {
+ // Persistent sounds that are used across the engine. These originally get loaded inside Logo
+ Common::String chunkNames[] = {
+ "CANT", // channel 17
+ "CURT", // channel 18
+ "GLOB", // channel 20
+ "BULS", // channel 22
+ "BUDE", // channel 23
+ "BUOK", // channel 24
+ };
+
+ Common::SeekableReadStream *chunk = nullptr;
+ for (auto const &s : chunkNames) {
+ chunk = g_nancy->getBootChunkStream(s);
+ if (chunk) {
+ SoundDescription &desc = _commonSounds.getOrCreateVal(s);
+ desc.read(*chunk, SoundDescription::kNormal);
+ g_nancy->_sound->loadSound(desc);
+ }
+ }
+
+ // Menu sound is special since it's stored differently and can be
+ // unloaded and loaded again
+ chunk = g_nancy->getBootChunkStream("MSND"); // channel 28
+ if (chunk) {
+ SoundDescription &desc = _commonSounds.getOrCreateVal("MSND");
+ desc.read(*chunk, SoundDescription::kMenu);
+ }
+}
+
SoundManager::~SoundManager() {
stopAllSounds();
}
@@ -262,6 +292,16 @@ void SoundManager::playSound(const SoundDescription &description) {
}
}
+void SoundManager::playSound(const Common::String &chunkName) {
+ const SoundDescription &desc = _commonSounds[chunkName];
+
+ if (!isSoundPlaying(desc)) {
+ loadSound(desc);
+ }
+
+ playSound(desc);
+}
+
void SoundManager::pauseSound(uint16 channelID, bool pause) {
if (channelID > 31)
return;
@@ -277,6 +317,10 @@ void SoundManager::pauseSound(const SoundDescription &description, bool pause) {
}
}
+void SoundManager::pauseSound(const Common::String &chunkName, bool pause) {
+ pauseSound(_commonSounds[chunkName], pause);
+}
+
bool SoundManager::isSoundPlaying(uint16 channelID) const {
if (channelID > 31)
return false;
@@ -292,6 +336,10 @@ bool SoundManager::isSoundPlaying(const SoundDescription &description) const {
}
}
+bool SoundManager::isSoundPlaying(const Common::String &chunkName) const {
+ return isSoundPlaying(_commonSounds[chunkName]);
+}
+
void SoundManager::stopSound(uint16 channelID) {
if (channelID > 31)
return;
@@ -310,6 +358,10 @@ void SoundManager::stopSound(const SoundDescription &description) {
}
}
+void SoundManager::stopSound(const Common::String &chunkName) {
+ stopSound(_commonSounds[chunkName]);
+}
+
// Returns whether the exception was skipped
void SoundManager::stopAllSounds() {
for (uint i = 0; i < 31; ++i) {
@@ -323,6 +375,8 @@ void SoundManager::stopAndUnloadSpecificSounds() {
for (uint i = 0; i < 10; ++i) {
stopSound(i);
}
+
+ stopSound(_commonSounds["MSND"]);
}
void SoundManager::initSoundChannels() {
diff --git a/engines/nancy/sound.h b/engines/nancy/sound.h
index 9b3e5c273f..21c34d4f47 100644
--- a/engines/nancy/sound.h
+++ b/engines/nancy/sound.h
@@ -23,6 +23,8 @@
#ifndef NANCY_SOUND_H
#define NANCY_SOUND_H
+#include "engines/nancy/commontypes.h"
+
#include "audio/mixer.h"
namespace Common {
@@ -36,27 +38,32 @@ class SeekableAudioStream;
namespace Nancy {
class NancyEngine;
-struct SoundDescription;
class SoundManager {
public:
SoundManager();
~SoundManager();
+ void loadCommonSounds();
+
// Load a sound into a channel without starting it
void loadSound(const SoundDescription &description);
void playSound(uint16 channelID);
void playSound(const SoundDescription &description);
+ void playSound(const Common::String &chunkName);
void pauseSound(uint16 channelID, bool pause);
void pauseSound(const SoundDescription &description, bool pause);
+ void pauseSound(const Common::String &chunkName, bool pause);
bool isSoundPlaying(uint16 channelID) const;
bool isSoundPlaying(const SoundDescription &description) const;
+ bool isSoundPlaying(const Common::String &chunkName) const;
void stopSound(uint16 channelID);
void stopSound(const SoundDescription &description);
+ void stopSound(const Common::String &chunkName);
void stopAllSounds();
// Used when changing scenes
@@ -78,6 +85,7 @@ protected:
Audio::Mixer *_mixer;
Channel _channels[32];
+ Common::HashMap<Common::String, SoundDescription> _commonSounds;
};
} // End of namespace Nancy
diff --git a/engines/nancy/state/credits.cpp b/engines/nancy/state/credits.cpp
index d174622a9e..110d1a20fd 100644
--- a/engines/nancy/state/credits.cpp
+++ b/engines/nancy/state/credits.cpp
@@ -73,6 +73,8 @@ void Credits::init() {
_text._drawSurface.create(_fullTextSurface, src);
_text.init();
+ g_nancy->_sound->stopSound("MSND");
+
g_nancy->_sound->loadSound(_sound);
g_nancy->_sound->playSound(_sound);
diff --git a/engines/nancy/state/help.cpp b/engines/nancy/state/help.cpp
index 72b80b9077..c96fa79af3 100644
--- a/engines/nancy/state/help.cpp
+++ b/engines/nancy/state/help.cpp
@@ -66,16 +66,13 @@ void Help::init() {
_hotspot.right = chunk->readUint16LE();
_hotspot.bottom = chunk->readUint16LE();
- chunk = g_nancy->getBootChunkStream("MSND");
- chunk->seek(0);
- _sound.read(*chunk, SoundDescription::kMenu);
-
_state = kBegin;
}
void Help::begin() {
- g_nancy->_sound->loadSound(_sound);
- g_nancy->_sound->playSound(_sound);
+ if (!g_nancy->_sound->isSoundPlaying("MSND")) {
+ g_nancy->_sound->playSound("MSND");
+ }
_image.registerGraphics();
_image.setVisible(true);
@@ -89,14 +86,14 @@ void Help::run() {
NancyInput input = g_nancy->_input->getInput();
if (_hotspot.contains(input.mousePos) && input.input & NancyInput::kLeftMouseButtonUp) {
- g_nancy->_sound->playSound(0x18); // Hardcoded by original engine
+ g_nancy->_sound->playSound("BUOK");
_state = kWaitForSound;
}
}
void Help::waitForSound() {
- if (!g_nancy->_sound->isSoundPlaying(18)) {
- g_nancy->_sound->stopSound(_sound);
+ if (!g_nancy->_sound->isSoundPlaying("BUOK")) {
+ g_nancy->_sound->stopSound("BUOK");
g_nancy->setToPreviousState();
}
}
diff --git a/engines/nancy/state/help.h b/engines/nancy/state/help.h
index 01439a5ed9..0b798fffd7 100644
--- a/engines/nancy/state/help.h
+++ b/engines/nancy/state/help.h
@@ -53,7 +53,6 @@ private:
State _state;
UI::FullScreenImage _image;
Common::Rect _hotspot; // Can be an array, but isn't in nancy1
- SoundDescription _sound;
};
#define NancyHelpState Nancy::State::Help::instance()
diff --git a/engines/nancy/state/logo.cpp b/engines/nancy/state/logo.cpp
index bd60fbe477..5fba350a7e 100644
--- a/engines/nancy/state/logo.cpp
+++ b/engines/nancy/state/logo.cpp
@@ -50,7 +50,6 @@ void Logo::process() {
}
void Logo::onStateExit() {
- g_nancy->_sound->stopSound(_msnd);
destroy();
}
@@ -65,9 +64,7 @@ void Logo::init() {
}
void Logo::startSound() {
- _msnd.read(*g_nancy->getBootChunkStream("MSND"), SoundDescription::kMenu);
- g_nancy->_sound->loadSound(_msnd);
- g_nancy->_sound->playSound(_msnd);
+ g_nancy->_sound->playSound("MSND");
_startTicks = g_nancy->getTotalPlayTime();
_state = kRun;
@@ -83,9 +80,6 @@ void Logo::stop() {
// The original engine checks for N+D and N+C key combos here.
// For the N+C key combo it looks for some kind of cheat file
// to initialize the game state with.
-
- g_nancy->_sound->stopSound(_msnd);
-
g_nancy->setState(NancyState::kScene);
}
diff --git a/engines/nancy/state/map.cpp b/engines/nancy/state/map.cpp
index 466fe8f5be..e1b3271711 100644
--- a/engines/nancy/state/map.cpp
+++ b/engines/nancy/state/map.cpp
@@ -80,10 +80,9 @@ void Map::init() {
// Load the audio
chunk->seek(0x18 + _mapID * 0x20, SEEK_SET);
- SoundDescription sound;
- sound.read(*chunk, SoundDescription::kMenu);
- g_nancy->_sound->loadSound(sound);
- g_nancy->_sound->playSound(0x14);
+ _sound.read(*chunk, SoundDescription::kMenu);
+ g_nancy->_sound->loadSound(_sound);
+ g_nancy->_sound->playSound("GLOB");
_locations.clear();
@@ -126,8 +125,8 @@ void Map::init() {
}
void Map::run() {
- if (!g_nancy->_sound->isSoundPlaying(0x14) && !g_nancy->_sound->isSoundPlaying(0x13)) {
- g_nancy->_sound->playSound(0x13);
+ if (!g_nancy->_sound->isSoundPlaying("GLOB") && !g_nancy->_sound->isSoundPlaying(_sound)) {
+ g_nancy->_sound->playSound(_sound);
}
NancyInput input = g_nancy->_input->getInput();
@@ -159,22 +158,18 @@ void Map::run() {
}
void Map::onStateExit() {
- Common::SeekableReadStream *chunk = g_nancy->getBootChunkStream("MAP");
- SoundDescription sound;
- chunk->seek(0x18 + _mapID * 0x20, SEEK_SET);
- sound.read(*chunk, SoundDescription::kMenu);
- g_nancy->_sound->stopSound(sound);
+ g_nancy->_sound->stopSound(_sound);
if (_pickedLocationID != -1) {
auto &loc = _locations[_pickedLocationID];
NancySceneState.changeScene(loc.scenes[_mapID].sceneID, loc.scenes[_mapID].frameID, loc.scenes[_mapID].verticalOffset, false);
_pickedLocationID = -1;
- g_nancy->_sound->playSound(0x18);
+ g_nancy->_sound->playSound("BUOK");
}
// The two sounds play at the same time if a location was picked
- g_nancy->_sound->playSound(0x14);
+ g_nancy->_sound->playSound("GLOB");
_mapButtonClicked = false;
diff --git a/engines/nancy/state/map.h b/engines/nancy/state/map.h
index c433961c08..147712b816 100644
--- a/engines/nancy/state/map.h
+++ b/engines/nancy/state/map.h
@@ -100,6 +100,7 @@ private:
Nancy::UI::Viewport _viewport;
MapLabel _label;
MapButton _button;
+ SoundDescription _sound;
State _state;
uint16 _mapID;
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index ac7bb8e93f..f98cd6d3a6 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -121,6 +121,7 @@ void Scene::onStateEnter() {
g_nancy->setTotalPlayTime((uint32)_timers.pushedPlayTime);
unpauseSceneSpecificSounds();
+ g_nancy->_sound->stopSound("MSND");
}
}
diff --git a/engines/nancy/ui/button.cpp b/engines/nancy/ui/button.cpp
index 4dd6d94dff..b7b77dcb0c 100644
--- a/engines/nancy/ui/button.cpp
+++ b/engines/nancy/ui/button.cpp
@@ -60,7 +60,7 @@ void MenuButton::init() {
void MenuButton::onClick() {
NancySceneState.requestStateChange(NancyState::kMainMenu);
- g_nancy->_sound->playSound(0x18);
+ g_nancy->_sound->playSound("GLOB");
setVisible(true);
}
@@ -80,7 +80,7 @@ void HelpButton::init() {
void HelpButton::onClick() {
NancySceneState.requestStateChange(NancyState::kHelp);
- g_nancy->_sound->playSound(0x18);
+ g_nancy->_sound->playSound("GLOB");
setVisible(true);
}
diff --git a/engines/nancy/ui/inventorybox.cpp b/engines/nancy/ui/inventorybox.cpp
index 200202c4b8..d158fee72a 100644
--- a/engines/nancy/ui/inventorybox.cpp
+++ b/engines/nancy/ui/inventorybox.cpp
@@ -118,13 +118,13 @@ void InventoryBox::handleInput(NancyInput &input) {
g_nancy->_cursorManager->setCursorType(CursorManager::kHotspotArrow);
if (input.input & NancyInput::kLeftMouseButtonUp) {
NancySceneState.addItemToInventory(NancySceneState.getHeldItem());
- g_nancy->_sound->playSound(0x16);
+ g_nancy->_sound->playSound("BULS");
}
} else if (_itemHotspots[i].itemID != -1) {
g_nancy->_cursorManager->setCursorType(CursorManager::kHotspotArrow);
if (input.input & NancyInput::kLeftMouseButtonUp) {
NancySceneState.removeItemFromInventory(_itemHotspots[i].itemID);
- g_nancy->_sound->playSound(0x18);
+ g_nancy->_sound->playSound("GLOB");
}
}
break;
@@ -242,7 +242,7 @@ void InventoryBox::Shades::updateGraphics() {
if (!_soundTriggered) {
_soundTriggered = true;
- g_nancy->_sound->playSound(0x12);
+ g_nancy->_sound->playSound("CURT");
}
}
} else {
@@ -252,7 +252,7 @@ void InventoryBox::Shades::updateGraphics() {
if (!_soundTriggered) {
_soundTriggered = true;
- g_nancy->_sound->playSound(0x12);
+ g_nancy->_sound->playSound("CURT");
}
}
}
Commit: 9f35d133cadd9b647ed9338cd9b2fd7d0628bec7
https://github.com/scummvm/scummvm/commit/9f35d133cadd9b647ed9338cd9b2fd7d0628bec7
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-08T21:42:53+03:00
Commit Message:
NANCY: Implement sound options, add options dialog
Hooked the engine into ScummVM's speech/subtitle settings, and added two extra options for player and character speech. Added a custom settings dialog which gets shown both inside the Edit Game window and the in-game Settings.
Changed paths:
A engines/nancy/dialogs.cpp
A engines/nancy/dialogs.h
engines/nancy/POTFILES
engines/nancy/action/primaryvideo.cpp
engines/nancy/detection.cpp
engines/nancy/metaengine.cpp
engines/nancy/module.mk
engines/nancy/nancy.cpp
diff --git a/engines/nancy/POTFILES b/engines/nancy/POTFILES
index 5870c5a4dd..ccf152b44c 100644
--- a/engines/nancy/POTFILES
+++ b/engines/nancy/POTFILES
@@ -1,2 +1,3 @@
engines/nancy/cheat.cpp
engines/nancy/input.cpp
+engines/nancy/dialogs.cpp
diff --git a/engines/nancy/action/primaryvideo.cpp b/engines/nancy/action/primaryvideo.cpp
index 0f106fe0a0..d77164780c 100644
--- a/engines/nancy/action/primaryvideo.cpp
+++ b/engines/nancy/action/primaryvideo.cpp
@@ -21,6 +21,7 @@
*/
#include "common/random.h"
+#include "common/config-manager.h"
#include "engines/nancy/nancy.h"
#include "engines/nancy/sound.h"
@@ -226,7 +227,11 @@ void PlayPrimaryVideoChan0::execute() {
init();
registerGraphics();
g_nancy->_sound->loadSound(_sound);
- g_nancy->_sound->playSound(_sound);
+
+ if (!ConfMan.getBool("speech_mute") && ConfMan.getBool("character_speech")) {
+ g_nancy->_sound->playSound(_sound);
+ }
+
_state = kRun;
_activePrimaryVideo = this;
// fall through
@@ -234,7 +239,10 @@ void PlayPrimaryVideoChan0::execute() {
if (!_hasDrawnTextbox) {
_hasDrawnTextbox = true;
NancySceneState.getTextbox().clear();
- NancySceneState.getTextbox().addTextLine(_text);
+
+ if (ConfMan.getBool("subtitles")) {
+ NancySceneState.getTextbox().addTextLine(_text);
+ }
// Add responses when conditions have been satisfied
if (_conditionalResponseCharacterID != 10) {
@@ -270,11 +278,14 @@ void PlayPrimaryVideoChan0::execute() {
}
if (_pickedResponse != -1) {
- // Player has picked response, play sound file and change _state
+ // Player has picked response, play sound file and change state
_responseGenericSound.name = _responses[_pickedResponse].soundName;
- // TODO this is probably not correct
g_nancy->_sound->loadSound(_responseGenericSound);
- g_nancy->_sound->playSound(_responseGenericSound);
+
+ if (!ConfMan.getBool("speech_mute") && ConfMan.getBool("player_speech")) {
+ g_nancy->_sound->playSound(_responseGenericSound);
+ }
+
_state = kActionTrigger;
}
}
diff --git a/engines/nancy/detection.cpp b/engines/nancy/detection.cpp
index 55e64dbd18..b9c97608df 100644
--- a/engines/nancy/detection.cpp
+++ b/engines/nancy/detection.cpp
@@ -21,6 +21,7 @@
*/
#include "engines/nancy/detection.h"
+#include "engines/nancy/dialogs.h"
const char *const directoryGlobs[] = {
"game",
@@ -193,18 +194,31 @@ public:
_directoryGlobs = directoryGlobs;
}
- const char *getEngineId() const override {
+ virtual const char *getEngineId() const override {
return "nancy";
}
- const char *getName() const override {
+ virtual const char *getName() const override {
return "Nancy Drew";
}
- const char *getOriginalCopyright() const override {
+ virtual const char *getOriginalCopyright() const override {
return "Nancy Drew Engine copyright Her Interactive, 1995-2012";
}
+ virtual void registerDefaultSettings(const Common::String &target) const override;
+ virtual GUI::OptionsContainerWidget *buildEngineOptionsWidgetStatic(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const override;
};
+void NancyMetaEngineDetection::registerDefaultSettings(const Common::String &target) const {
+ ConfMan.setInt("music_volume", 54 * 255 / 100, target);
+ ConfMan.setInt("speech_volume", 54 * 255 / 100, target);
+ ConfMan.setInt("sfx_volume", 51 * 255 / 100, target);
+ ConfMan.setBool("subtitles", true, target);
+}
+
+GUI::OptionsContainerWidget *NancyMetaEngineDetection::buildEngineOptionsWidgetStatic(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const {
+ return new Nancy::NancyOptionsWidget(boss, name, target);
+}
+
REGISTER_PLUGIN_STATIC(NANCY_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, NancyMetaEngineDetection);
diff --git a/engines/nancy/dialogs.cpp b/engines/nancy/dialogs.cpp
new file mode 100644
index 0000000000..51e8776cae
--- /dev/null
+++ b/engines/nancy/dialogs.cpp
@@ -0,0 +1,67 @@
+/* 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 "common/translation.h"
+
+#include "gui/ThemeEval.h"
+
+#include "engines/nancy/dialogs.h"
+
+namespace Nancy {
+
+NancyOptionsWidget::NancyOptionsWidget(GuiObject *boss, const Common::String &name, const Common::String &domain) :
+ OptionsContainerWidget(boss, name, "NancyOptionsDialog", false, domain) {
+ _playerSpeechCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "NancyOptionsDialog.PlayerSpeech", _("Player Speech"), _("Enable player speech. Only works if speech is enabled in the Audio settings."));
+ _characterSpeechCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "NancyOptionsDialog.CharacterSpeech", _("Character Speech"), _("Enable NPC speech. Only works if speech is enabled in the Audio settings."));
+
+ new GUI::StaticTextWidget(widgetsBoss(), "NancyOptionsDialog.SpeechSettingsLabel", _("Speech Options"));
+}
+
+void NancyOptionsWidget::load() {
+ _playerSpeechCheckbox->setState(ConfMan.getBool("player_speech", _domain));
+ _characterSpeechCheckbox->setState(ConfMan.getBool("character_speech", _domain));
+}
+
+bool NancyOptionsWidget::save() {
+ ConfMan.setBool("player_speech", _playerSpeechCheckbox->getState(), _domain);
+ ConfMan.setBool("character_speech", _characterSpeechCheckbox->getState(), _domain);
+
+ return true;
+}
+
+void NancyOptionsWidget::defineLayout(GUI::ThemeEval &layouts, const Common::String &layoutName, const Common::String &overlayedLayout) const {
+ layouts.addDialog(layoutName, overlayedLayout)
+ .addLayout(GUI::ThemeLayout::kLayoutVertical)
+ .addPadding(16, 16, 16, 16)
+ .addWidget("SpeechSettingsLabel", "OptionsLabel")
+ .addWidget("PlayerSpeech", "Checkbox")
+ .addWidget("CharacterSpeech", "Checkbox")
+ .closeLayout()
+ .closeDialog();
+}
+
+bool NancyOptionsWidget::isInGame() const {
+ return _domain.equals(ConfMan.getActiveDomainName());
+}
+
+
+} // End of namespace Nancy
diff --git a/engines/nancy/dialogs.h b/engines/nancy/dialogs.h
new file mode 100644
index 0000000000..861d81fcc7
--- /dev/null
+++ b/engines/nancy/dialogs.h
@@ -0,0 +1,49 @@
+/* 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/dialogs.h"
+
+#ifndef NANCY_DIALOGS_H
+#define NANCY_DIALOGS_H
+
+namespace Nancy {
+
+class NancyOptionsWidget : public GUI::OptionsContainerWidget {
+public:
+ NancyOptionsWidget(GuiObject *boss, const Common::String &name, const Common::String &domain);
+ virtual ~NancyOptionsWidget() override {};
+
+ void load() override;
+ bool save() override;
+
+private:
+ void defineLayout(GUI::ThemeEval &layouts, const Common::String &layoutName, const Common::String &overlayedLayout) const override;
+
+ bool isInGame() const;
+
+ GUI::CheckboxWidget *_playerSpeechCheckbox;
+ GUI::CheckboxWidget *_characterSpeechCheckbox;
+};
+
+} // End of namespace Nancy
+
+#endif // NANCY_DIALOGS_H
diff --git a/engines/nancy/metaengine.cpp b/engines/nancy/metaengine.cpp
index e41c62fde2..d355590805 100644
--- a/engines/nancy/metaengine.cpp
+++ b/engines/nancy/metaengine.cpp
@@ -24,19 +24,22 @@
#include "engines/nancy/nancy.h"
#include "engines/nancy/input.h"
+#include "engines/nancy/dialogs.h"
class NancyMetaEngine : public AdvancedMetaEngine {
public:
- const char *getName() const override {
+ virtual const char *getName() const override {
return "nancy";
}
- bool hasFeature(MetaEngineFeature f) const override;
- Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
+ virtual bool hasFeature(MetaEngineFeature f) const override;
+ virtual Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
- int getMaximumSaveSlot() const override;
+ virtual int getMaximumSaveSlot() const override;
- Common::KeymapArray initKeymaps(const char *target) const override;
+ virtual Common::KeymapArray initKeymaps(const char *target) const override;
+
+ virtual GUI::OptionsContainerWidget *buildEngineOptionsWidgetDynamic(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const override;
};
Common::KeymapArray NancyMetaEngine::initKeymaps(const char *target) const {
@@ -71,6 +74,10 @@ Common::Error NancyMetaEngine::createInstance(OSystem *syst, Engine **engine, co
int NancyMetaEngine::getMaximumSaveSlot() const { return 8; }
+GUI::OptionsContainerWidget *NancyMetaEngine::buildEngineOptionsWidgetDynamic(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const {
+ return new Nancy::NancyOptionsWidget(boss, name, target);
+}
+
#if PLUGIN_ENABLED_DYNAMIC(NANCY)
REGISTER_PLUGIN_DYNAMIC(NANCY, PLUGIN_TYPE_ENGINE, NancyMetaEngine);
#else
diff --git a/engines/nancy/module.mk b/engines/nancy/module.mk
index 9ff66844c7..81ee9d0f86 100644
--- a/engines/nancy/module.mk
+++ b/engines/nancy/module.mk
@@ -31,6 +31,7 @@ MODULE_OBJS = \
console.o \
cursor.o \
decompress.o \
+ dialogs.o \
font.o \
graphics.o \
iff.o \
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index 2a7f82d2de..3194d60bf8 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -118,7 +118,11 @@ bool NancyEngine::canSaveGameStateCurrently() {
}
bool NancyEngine::hasFeature(EngineFeature f) const {
- return (f == kSupportsReturnToLauncher) || (f == kSupportsLoadingDuringRuntime) || (f == kSupportsSavingDuringRuntime);
+ return (f == kSupportsReturnToLauncher) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime) ||
+ (f == kSupportsChangingOptionsDuringRuntime) ||
+ (f == kSupportsSubtitleOptions);
}
const char *NancyEngine::getCopyrightString() const {
@@ -279,6 +283,10 @@ void NancyEngine::bootGameEngine() {
SearchMan.addSubDirectoryMatching(gameDataDir, "art");
SearchMan.addSubDirectoryMatching(gameDataDir, "font");
+ // Register default settings
+ ConfMan.registerDefault("player_speech", true);
+ ConfMan.registerDefault("character_speech", true);
+
// Load archive
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember("data1.cab");
if (stream) {
Commit: 68e54edd50c7b0f7b090949f5f8abb79a645c989
https://github.com/scummvm/scummvm/commit/68e54edd50c7b0f7b090949f5f8abb79a645c989
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-08T21:42:54+03:00
Commit Message:
NANCY: Initial main menu implementation
Implemented the original engine's main menu and added an option to enable it from the custom options dialog. Several buttons in the main menu don't work yet since they require implementing additional game states.
Changed paths:
A engines/nancy/state/mainmenu.cpp
A engines/nancy/state/mainmenu.h
engines/nancy/dialogs.cpp
engines/nancy/dialogs.h
engines/nancy/module.mk
engines/nancy/nancy.cpp
engines/nancy/renderobject.h
engines/nancy/state/logo.cpp
diff --git a/engines/nancy/dialogs.cpp b/engines/nancy/dialogs.cpp
index 51e8776cae..c899262a44 100644
--- a/engines/nancy/dialogs.cpp
+++ b/engines/nancy/dialogs.cpp
@@ -32,18 +32,22 @@ NancyOptionsWidget::NancyOptionsWidget(GuiObject *boss, const Common::String &na
OptionsContainerWidget(boss, name, "NancyOptionsDialog", false, domain) {
_playerSpeechCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "NancyOptionsDialog.PlayerSpeech", _("Player Speech"), _("Enable player speech. Only works if speech is enabled in the Audio settings."));
_characterSpeechCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "NancyOptionsDialog.CharacterSpeech", _("Character Speech"), _("Enable NPC speech. Only works if speech is enabled in the Audio settings."));
+ _originalMenusCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "NancyOptionsDialog.OriginalMenus", _("Use original menus"), _("Use the original engine's main, save/load, and setup menus. ScummVM's Global Main Menu can still be accessed through its keymap."));
new GUI::StaticTextWidget(widgetsBoss(), "NancyOptionsDialog.SpeechSettingsLabel", _("Speech Options"));
+ new GUI::StaticTextWidget(widgetsBoss(), "NancyOptionsDialog.EngineSettingsLabel", _("Engine Options"));
}
void NancyOptionsWidget::load() {
_playerSpeechCheckbox->setState(ConfMan.getBool("player_speech", _domain));
_characterSpeechCheckbox->setState(ConfMan.getBool("character_speech", _domain));
+ _originalMenusCheckbox->setState(ConfMan.getBool("original_menus", _domain));
}
bool NancyOptionsWidget::save() {
ConfMan.setBool("player_speech", _playerSpeechCheckbox->getState(), _domain);
ConfMan.setBool("character_speech", _characterSpeechCheckbox->getState(), _domain);
+ ConfMan.setBool("original_menus", _characterSpeechCheckbox->getState(), _domain);
return true;
}
@@ -55,6 +59,9 @@ void NancyOptionsWidget::defineLayout(GUI::ThemeEval &layouts, const Common::Str
.addWidget("SpeechSettingsLabel", "OptionsLabel")
.addWidget("PlayerSpeech", "Checkbox")
.addWidget("CharacterSpeech", "Checkbox")
+ .addSpace(16)
+ .addWidget("EngineSettingsLabel", "OptionsLabel")
+ .addWidget("OriginalMenus", "Checkbox")
.closeLayout()
.closeDialog();
}
diff --git a/engines/nancy/dialogs.h b/engines/nancy/dialogs.h
index 861d81fcc7..6cb167f4f4 100644
--- a/engines/nancy/dialogs.h
+++ b/engines/nancy/dialogs.h
@@ -42,6 +42,7 @@ private:
GUI::CheckboxWidget *_playerSpeechCheckbox;
GUI::CheckboxWidget *_characterSpeechCheckbox;
+ GUI::CheckboxWidget *_originalMenusCheckbox;
};
} // End of namespace Nancy
diff --git a/engines/nancy/module.mk b/engines/nancy/module.mk
index 81ee9d0f86..6f8c5733f9 100644
--- a/engines/nancy/module.mk
+++ b/engines/nancy/module.mk
@@ -24,6 +24,7 @@ MODULE_OBJS = \
state/credits.o \
state/logo.o \
state/help.o \
+ state/mainmenu.o \
state/map.o \
state/scene.o \
cheat.o \
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index 3194d60bf8..5cc5b3a124 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -44,6 +44,7 @@
#include "engines/nancy/state/help.h"
#include "engines/nancy/state/map.h"
#include "engines/nancy/state/credits.h"
+#include "engines/nancy/state/mainmenu.h"
namespace Nancy {
@@ -153,6 +154,11 @@ void NancyEngine::setState(NancyState::NancyState state, NancyState::NancyState
setState(NancyState::kLogo);
return;
case NancyState::kMainMenu: {
+ if (ConfMan.getBool("original_menus")) {
+ break;
+ }
+
+ // Do not use the original engine's menus, call the GMM instead
State::State *s = getStateObject(_gameFlow.curState);
if (s) {
s->onStateExit();
@@ -286,6 +292,7 @@ void NancyEngine::bootGameEngine() {
// Register default settings
ConfMan.registerDefault("player_speech", true);
ConfMan.registerDefault("character_speech", true);
+ ConfMan.registerDefault("original_menus", false);
// Load archive
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember("data1.cab");
@@ -349,6 +356,8 @@ State::State *NancyEngine::getStateObject(NancyState::NancyState state) const {
return &State::Help::instance();
case NancyState::kScene:
return &State::Scene::instance();
+ case NancyState::kMainMenu:
+ return &State::MainMenu::instance();
default:
return nullptr;
}
diff --git a/engines/nancy/renderobject.h b/engines/nancy/renderobject.h
index 1a7ec22640..d22a9a4101 100644
--- a/engines/nancy/renderobject.h
+++ b/engines/nancy/renderobject.h
@@ -67,6 +67,7 @@ public:
Common::Rect convertToScreen(const Common::Rect &rect) const;
Common::Rect getBounds() const { return Common::Rect(_drawSurface.w, _drawSurface.h); }
+ Graphics::ManagedSurface &getDrawSurface() { return _drawSurface; }
protected:
// Z order and blit type are extracted directly from the corresponding
diff --git a/engines/nancy/state/logo.cpp b/engines/nancy/state/logo.cpp
index 5fba350a7e..87338aabe7 100644
--- a/engines/nancy/state/logo.cpp
+++ b/engines/nancy/state/logo.cpp
@@ -20,6 +20,8 @@
*
*/
+#include "common/config-manager.h"
+
#include "engines/nancy/nancy.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
@@ -80,7 +82,12 @@ void Logo::stop() {
// The original engine checks for N+D and N+C key combos here.
// For the N+C key combo it looks for some kind of cheat file
// to initialize the game state with.
- g_nancy->setState(NancyState::kScene);
+
+ if (ConfMan.getBool("original_menus")) {
+ g_nancy->setState(NancyState::kMainMenu);
+ } else {
+ g_nancy->setState(NancyState::kScene);
+ }
}
} // End of namespace State
diff --git a/engines/nancy/state/mainmenu.cpp b/engines/nancy/state/mainmenu.cpp
new file mode 100644
index 0000000000..69abb3b8f0
--- /dev/null
+++ b/engines/nancy/state/mainmenu.cpp
@@ -0,0 +1,178 @@
+/* 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/nancy.h"
+#include "engines/nancy/cursor.h"
+#include "engines/nancy/sound.h"
+#include "engines/nancy/input.h"
+#include "engines/nancy/util.h"
+
+#include "engines/nancy/state/mainmenu.h"
+#include "engines/nancy/state/scene.h"
+
+namespace Common {
+DECLARE_SINGLETON(Nancy::State::MainMenu);
+}
+
+namespace Nancy {
+namespace State {
+
+void MainMenu::process() {
+ switch (_state) {
+ case kInit:
+ init();
+ // fall through
+ case kRun:
+ run();
+ break;
+ case kStop:
+ stop();
+ break;
+ }
+}
+
+void MainMenu::onStateExit() {
+ destroy();
+}
+
+void MainMenu::init() {
+ Common::SeekableReadStream *chunk = g_nancy->getBootChunkStream("MENU");
+ chunk->seek(0);
+
+ Common::String imageName;
+ readFilename(*chunk, imageName);
+
+ _background.init(imageName);
+ _background.registerGraphics();
+
+ g_nancy->_cursorManager->setCursorType(CursorManager::kNormalArrow);
+ g_nancy->_cursorManager->showCursor(true);
+
+ if (!g_nancy->_sound->isSoundPlaying("MSND")) {
+ g_nancy->_sound->playSound("MSND");
+ }
+
+ chunk->seek(0x20);
+
+ // Unlike every other rect in the engine, these use int16 instead of int32
+ for (uint i = 0; i < 8; ++i) {
+ _destRects.push_back(Common::Rect());
+ Common::Rect &rect = _destRects.back();
+ rect.left = chunk->readSint16LE();
+ rect.top = chunk->readSint16LE();
+ rect.right = chunk->readSint16LE();
+ rect.bottom = chunk->readSint16LE();
+ }
+
+ for (uint i = 0; i < 8; ++i) {
+ _srcRects.push_back(Common::Rect());
+ Common::Rect &rect = _srcRects.back();
+ rect.left = chunk->readSint16LE();
+ rect.top = chunk->readSint16LE();
+ rect.right = chunk->readSint16LE();
+ rect.bottom = chunk->readSint16LE();
+ }
+
+ _buttonDown.registerGraphics();
+ _buttonDown._redrawFrom = &_background;
+
+ _state = kRun;
+}
+
+void MainMenu::run() {
+ NancyInput input = g_nancy->_input->getInput();
+
+ _buttonDown.setVisible(false);
+
+ if (input.input & NancyInput::kLeftMouseButtonUp) {
+ for (uint i = 0; i < 8; ++i) {
+ if (_destRects[i].contains(input.mousePos)) {
+ if (i == 3 && !Scene::hasInstance()) {
+ g_nancy->_sound->playSound("BUDE");
+ _playedOKSound = false;
+ } else {
+ g_nancy->_sound->playSound("BUOK");
+ _playedOKSound = true;
+ }
+
+ _selected = i;
+ _state = kStop;
+
+ _buttonDown._drawSurface.create(_background.getDrawSurface(), _srcRects[i]);
+ _buttonDown._screenPosition = _destRects[i];
+ _buttonDown.setVisible(true);
+
+ return;
+ }
+ }
+ }
+}
+
+void MainMenu::stop() {
+ if (!g_nancy->_sound->isSoundPlaying(_playedOKSound ? "BUOK" : "BUDE")) {
+ switch (_selected) {
+ case 0:
+ // Credits
+ g_nancy->setState(NancyState::kCredits);
+ break;
+ case 1:
+ // New Game
+ if (Scene::hasInstance()) {
+ NancySceneState.destroy(); // Simply destroy the existing Scene and create a new one
+ }
+
+ g_nancy->setState(NancyState::kScene);
+ break;
+ case 2:
+ // Load and Save Game, TODO
+ _state = kRun;
+ break;
+ case 3:
+ // Continue
+ if (Scene::hasInstance()) {
+ g_nancy->setState(NancyState::kScene);
+ } else {
+ _state = kRun;
+ }
+ break;
+ case 4:
+ // Second Chance, TODO
+ _state = kRun;
+ break;
+ case 5:
+ // Game Setup, TODO
+ _state = kRun;
+ break;
+ case 6:
+ // Exit Game
+ g_nancy->quitGame(); // Consider returning to launcher instead?
+ break;
+ case 7:
+ // Help
+ g_nancy->setState(NancyState::kHelp);
+ break;
+ }
+ }
+}
+
+} // End of namespace State
+} // End of namespace Nancy
diff --git a/engines/nancy/state/mainmenu.h b/engines/nancy/state/mainmenu.h
new file mode 100644
index 0000000000..eef90e7e46
--- /dev/null
+++ b/engines/nancy/state/mainmenu.h
@@ -0,0 +1,75 @@
+/* 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_STATE_MAINMENU_H
+#define NANCY_STATE_MAINMENU_H
+
+#include "common/singleton.h"
+
+#include "engines/nancy/state/state.h"
+
+#include "engines/nancy/ui/fullscreenimage.h"
+
+namespace Nancy {
+namespace State {
+
+class MainMenu : public State, public Common::Singleton<MainMenu> {
+ friend class MainMenuButton;
+public:
+ MainMenu() : _state(kInit), _selected(-1), _playedOKSound(false) {}
+
+ // State API
+ virtual void process() override;
+ virtual void onStateExit() override;
+
+private:
+ // This is not a UI::Button subclass since the cursor doesn't change on hover
+ class ButtonDownLabel : public RenderObject {
+ friend class MainMenu;
+ public:
+ ButtonDownLabel() {}
+ virtual ~ButtonDownLabel() override {}
+
+ protected:
+ virtual uint16 getZOrder() const override { return 5; }
+ };
+
+ void init();
+ void run();
+ void stop();
+
+ enum State { kInit, kRun, kStop };
+
+ UI::FullScreenImage _background;
+ ButtonDownLabel _buttonDown;
+ State _state;
+ int16 _selected;
+ bool _playedOKSound;
+
+ Common::Array<Common::Rect> _destRects;
+ Common::Array<Common::Rect> _srcRects;
+};
+
+} // End of namespace State
+} // End of namespace Nancy
+
+#endif // NANCY_STATE_MAINMENU_H
Commit: f98da95b1fec0fd5cb6eff13ffa7a18d87c339eb
https://github.com/scummvm/scummvm/commit/f98da95b1fec0fd5cb6eff13ffa7a18d87c339eb
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-08T21:42:54+03:00
Commit Message:
NANCY: Fix doubled input between states
Fixed an issue where input would get doubled when changing states.
Changed paths:
engines/nancy/nancy.cpp
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index 5cc5b3a124..a5a32fc6b8 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -196,16 +196,6 @@ void NancyEngine::setState(NancyState::NancyState state, NancyState::NancyState
_graphicsManager->clearObjects();
- State::State *s = getStateObject(_gameFlow.curState);
- if (s) {
- s->onStateExit();
- }
-
- s = getStateObject(state);
- if (s) {
- s->onStateEnter();
- }
-
if (overridePrevious != NancyState::kNone) {
_gameFlow.prevState = overridePrevious;
} else {
@@ -213,6 +203,16 @@ void NancyEngine::setState(NancyState::NancyState state, NancyState::NancyState
}
_gameFlow.curState = state;
+
+ State::State *s = getStateObject(_gameFlow.prevState);
+ if (s) {
+ s->onStateExit();
+ }
+
+ s = getStateObject(_gameFlow.curState);
+ if (s) {
+ s->onStateEnter();
+ }
}
void NancyEngine::setToPreviousState() {
Commit: 6a07442d53efd0e3622cdc592db815688cf2d3d0
https://github.com/scummvm/scummvm/commit/6a07442d53efd0e3622cdc592db815688cf2d3d0
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-08T21:47:15+03:00
Commit Message:
NANCY: Cheat dialogs fixes
Moved CheatDialog and EventFlagDialog to dialogs.h and removed cheat.h. Fixed a crash on closing the event flags dialog. Fixed the timer data in CheatDialog being incorrectly written to the player time. Removed a couple of incorrectly marked translation strings.
Changed paths:
R engines/nancy/cheat.cpp
R engines/nancy/cheat.h
engines/nancy/POTFILES
engines/nancy/dialogs.cpp
engines/nancy/dialogs.h
engines/nancy/module.mk
engines/nancy/nancy.cpp
engines/nancy/state/scene.cpp
diff --git a/engines/nancy/POTFILES b/engines/nancy/POTFILES
index ccf152b44c..65da832d68 100644
--- a/engines/nancy/POTFILES
+++ b/engines/nancy/POTFILES
@@ -1,3 +1,2 @@
-engines/nancy/cheat.cpp
engines/nancy/input.cpp
engines/nancy/dialogs.cpp
diff --git a/engines/nancy/cheat.cpp b/engines/nancy/cheat.cpp
deleted file mode 100644
index b89432b9d4..0000000000
--- a/engines/nancy/cheat.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
-/* 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 "common/winexe.h"
-#include "common/translation.h"
-#include "common/stream.h"
-
-#include "gui/widgets/tab.h"
-#include "gui/widgets/edittext.h"
-
-#include "engines/nancy/iff.h"
-#include "engines/nancy/cheat.h"
-
-#include "engines/nancy/state/scene.h"
-
-namespace Nancy {
-
-CheatDialog::CheatDialog() : GUI::Dialog(20, 20, 600, 440) {
- _backgroundType = GUI::ThemeEngine::kDialogBackgroundSpecial;
- Common::WinResources *res = Common::WinResources::createFromEXE("game.exe");
- Common::Array<Common::WinResourceID> dialogIDs = res->getIDList(Common::kWinDialog);
- State::SceneInfo scene = NancySceneState.getSceneInfo();
- Time playerTime = NancySceneState._timers.playerTime;
- Time timerTime = NancySceneState._timers.timerTime;
- bool timerIsActive = NancySceneState._timers.timerIsActive;
- if (!timerIsActive) {
- timerTime = 0;
- }
-
- GUI::TabWidget *_tabs = new GUI::TabWidget(this, 0, 0, 600, 370);
- new GUI::ButtonWidget(this, 420, 410, 60, 20, _("Cancel"), Common::U32String(), GUI::kCloseCmd);
- new GUI::ButtonWidget(this, 520, 410, 60, 20, _("Ok"), Common::U32String(), GUI::kOKCmd);
-
- _tabs->addTab(_("General"), "Cheat.General");
-
- new GUI::StaticTextWidget(_tabs, 30, 20, 150, 20, _("Scene Data"), Graphics::kTextAlignLeft);
- _restartScene = new GUI::CheckboxWidget(_tabs, 35, 50, 150, 20, _("Restart the Scene"));
- _scene = new GUI::EditTextWidget(_tabs, 35, 75, 45, 20, Common::U32String::format("%u", scene.sceneID), Common::U32String(), kInputSceneNr, kInputSceneNr);
- new GUI::StaticTextWidget(_tabs, 85, 75, 150, 20, _("Scene Number"), Graphics::kTextAlignLeft);
- _frame = new GUI::EditTextWidget(_tabs, 35, 100, 45, 20, Common::U32String::format("%u", scene.frameID), Common::U32String(), kInputFrameNr, kInputFrameNr);
- new GUI::StaticTextWidget(_tabs, 85, 100, 150, 20, _("Frame Number"), Graphics::kTextAlignLeft);
- _offset = new GUI::EditTextWidget(_tabs, 35, 125, 45, 20, Common::U32String::format("%u", scene.verticalOffset), Common::U32String(), kInputScroll, kInputScroll);
-
- // I18N: The Y position (a.k.a vertical scroll) of the background
- new GUI::StaticTextWidget(_tabs, 85, 125, 150, 20, _("Background Top (Y)"), Graphics::kTextAlignLeft);
-
- new GUI::StaticTextWidget(_tabs, 30, 160, 150, 20, _("Hints Remaining"), Graphics::kTextAlignLeft);
- new GUI::StaticTextWidget(_tabs, 35, 185, 45, 20, _("Easy"), Graphics::kTextAlignLeft);
- _hintsRemainingEasy = new GUI::EditTextWidget(_tabs, 35, 205, 45, 20, Common::U32String::format("%u", NancySceneState._hintsRemaining[0]), Common::U32String(), kInputHintsEasy, kInputHintsEasy);
- new GUI::StaticTextWidget(_tabs, 85, 185, 45, 20, _("Medium"), Graphics::kTextAlignLeft);
- _hintsRemainingMedium = new GUI::EditTextWidget(_tabs, 85, 205, 45, 20, Common::U32String::format("%u", NancySceneState._hintsRemaining[1]), Common::U32String(), kInputHintsMedium, kInputHintsMedium);
- new GUI::StaticTextWidget(_tabs, 135, 185, 45, 20, _("Hard"), Graphics::kTextAlignLeft);
- _hintsRemainingHard = new GUI::EditTextWidget(_tabs, 135, 205, 45, 20, Common::U32String::format("%u", NancySceneState._hintsRemaining[2]), Common::U32String(), kInputHintsHard, kInputHintsHard);
-
- new GUI::StaticTextWidget(_tabs, 250, 20, 150, 20, _("Player Data"), Graphics::kTextAlignLeft);
- new GUI::StaticTextWidget(_tabs, 255, 50, 150, 20, _("Player Time:"), Graphics::kTextAlignLeft);
- _playerTimeDays = new GUI::EditTextWidget(_tabs, 255, 75, 35, 20, Common::U32String::format("%u", playerTime.getDays()), Common::U32String(), kInputPlayerTime, kInputPlayerTime);
- new GUI::StaticTextWidget(_tabs, 295, 75, 40, 20, _("Days"), Graphics::kTextAlignLeft);
- _playerTimeHours = new GUI::EditTextWidget(_tabs, 335, 75, 35, 20, Common::U32String::format("%u", playerTime.getHours()), Common::U32String(), kInputPlayerTime, kInputPlayerTime);
- new GUI::StaticTextWidget(_tabs, 375, 75, 40, 20, _("Hours"), Graphics::kTextAlignLeft);
- _playerTimeMinutes = new GUI::EditTextWidget(_tabs, 415, 75, 35, 20, Common::U32String::format("%u", playerTime.getMinutes()), Common::U32String(), kInputPlayerTime, kInputPlayerTime);
- new GUI::StaticTextWidget(_tabs, 455, 75, 50, 20, _("Minutes"), Graphics::kTextAlignLeft);
- _difficulty = new GUI::EditTextWidget(_tabs, 255, 105, 35, 20, Common::U32String::format("%u", NancySceneState._difficulty), Common::U32String(), kInputDifficulty, kInputDifficulty);
- new GUI::StaticTextWidget(_tabs, 295, 105, 150, 20, _("Player Difficulty Level"), Graphics::kTextAlignLeft);
-
- new GUI::StaticTextWidget(_tabs, 250, 140, 150, 20, _("Player Data"), Graphics::kTextAlignLeft);
- _timerOn = new GUI::CheckboxWidget(_tabs, 255, 170, 150, 20, _("Timer On"));
- _timerOn->setState(timerIsActive);
- _timerHours = new GUI::EditTextWidget(_tabs, 255, 195, 35, 20, Common::U32String::format("%u", timerTime.getTotalHours()), Common::U32String(), kInputTimer, kInputTimer);
- new GUI::StaticTextWidget(_tabs, 295, 195, 40, 20, _("Hours"), Graphics::kTextAlignLeft);
- _timerMinutes = new GUI::EditTextWidget(_tabs, 335, 195, 35, 20, Common::U32String::format("%u", timerTime.getMinutes()), Common::U32String(), kInputTimer, kInputTimer);
- new GUI::StaticTextWidget(_tabs, 375, 195, 50, 20, _("Minutes"), Graphics::kTextAlignLeft);
- _timerSeconds = new GUI::EditTextWidget(_tabs, 425, 195, 35, 20, Common::U32String::format("%u", timerTime.getSeconds()), Common::U32String(), kInputTimer, kInputTimer);
- new GUI::StaticTextWidget(_tabs, 465, 195, 50, 20, _("Seconds"), Graphics::kTextAlignLeft);
-
- _tabs->addTab(_("Inventory"), "Cheat.Inventory");
-
- for (uint i = 0; i < dialogIDs.size(); ++i) {
- Common::SeekableReadStream *resStream = res->getResource(Common::kWinDialog, dialogIDs[i].getID());
-
- Common::String idString;
- resStream->skip(0x16);
- while (true) {
- char add = resStream->readByte();
- if (add != 0) {
- idString += add;
- resStream->skip(1);
- } else {
- resStream->skip(1);
- break;
- }
- }
-
- if (!idString.hasPrefix("Inventory")) {
- continue;
- }
-
- idString.trim();
- uint numItems = 0;
-
- while (resStream->pos() < resStream->size()) {
- if (resStream->readUint16LE() == 0xFFFF && resStream->readSint16LE() == 0x80) {
- // Found a resource, read its string id
- Common::String itemLabel;
-
- while (true) {
- char add = resStream->readByte();
- if (add != 0) {
- itemLabel += add;
- resStream->skip(1);
- } else {
- resStream->skip(1);
- break;
- }
- }
- GUI::CheckboxWidget *box = new GUI::CheckboxWidget(_tabs, 250 * (numItems / 10) + 20, (350 / 10) * (numItems % 10) + 15, 250, 250/10, _(itemLabel));
- box->setState(NancySceneState.hasItem(numItems) == kTrue);
- _inventory.push_back(box);
-
- ++numItems;
- }
- }
-
- break;
- }
-
- _tabs->setActiveTab(0);
-}
-
-void CheatDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
- switch (cmd) {
- case GUI::kOKCmd: {
- if (_restartScene->getState()) {
- uint sceneID = atoi(Common::String(_scene->getEditString()).c_str());
- IFF iff(Common::String::format("S%u", sceneID));
- if (iff.load()) {
- NancySceneState.changeScene(
- atoi(Common::String(_scene->getEditString()).c_str()),
- atoi(Common::String(_frame->getEditString()).c_str()),
- atoi(Common::String(_offset->getEditString()).c_str()),
- true);
- } else {
- new GUI::StaticTextWidget(this, 20, 410, 150, 20, _("Invalid Scene ID!"), Graphics::kTextAlignLeft);
- return;
- }
- }
-
- if (_timerOn->getState()) {
- NancySceneState._timers.timerIsActive = true;
- Time &timer = NancySceneState._timers.timerTime;
- timer = 0;
- timer += 1000 * atoi(Common::String(_timerSeconds->getEditString()).c_str());
- timer += 60000 * atoi(Common::String(_timerMinutes->getEditString()).c_str());
- timer += 3600000 * atoi(Common::String(_timerHours->getEditString()).c_str());
- } else {
- NancySceneState.stopTimer();
- }
-
- Time &playerTime = NancySceneState._timers.timerTime;
- playerTime = 0;
- playerTime += 60000 * atoi(Common::String(_playerTimeMinutes->getEditString()).c_str());
- playerTime += 3600000 * atoi(Common::String(_playerTimeHours->getEditString()).c_str());
- playerTime += 86400000 * atoi(Common::String(_playerTimeMinutes->getEditString()).c_str());
-
- NancySceneState._difficulty = atoi(Common::String(_difficulty->getEditString()).c_str());
- NancySceneState._hintsRemaining[0] = atoi(Common::String(_hintsRemainingEasy->getEditString()).c_str());
- NancySceneState._hintsRemaining[1] = atoi(Common::String(_hintsRemainingMedium->getEditString()).c_str());
- NancySceneState._hintsRemaining[2] = atoi(Common::String(_hintsRemainingHard->getEditString()).c_str());
-
- for (uint i = 0; i < _inventory.size(); ++i) {
- if (NancySceneState.hasItem(i) == kTrue && !_inventory[i]->getState()) {
- NancySceneState.removeItemFromInventory(i, false);
- } else if (NancySceneState.hasItem(i) == kFalse && _inventory[i]->getState()) {
- NancySceneState.addItemToInventory(i);
- }
- }
- cmd = GUI::kCloseCmd;
-
- break;
- }
- case kInputSceneNr:
- sanitizeInput(_scene);
- break;
- case kInputFrameNr:
- sanitizeInput(_frame);
- break;
- case kInputScroll:
- sanitizeInput(_offset);
- break;
- case kInputDifficulty:
- sanitizeInput(_scene, 2);
- break;
- case kInputHintsEasy:
- sanitizeInput(_hintsRemainingEasy);
- break;
- case kInputHintsMedium:
- sanitizeInput(_hintsRemainingMedium);
- break;
- case kInputHintsHard:
- sanitizeInput(_hintsRemainingHard);
- break;
- case kInputPlayerTime:
- sanitizeInput(_playerTimeMinutes, 59);
- sanitizeInput(_playerTimeHours, 23);
- sanitizeInput(_playerTimeDays);
- break;
- case kInputTimer:
- sanitizeInput(_timerSeconds, 59);
- sanitizeInput(_timerMinutes, 59);
- sanitizeInput(_timerHours, 23);
- break;
- default:
- break;
- }
-
- Dialog::handleCommand(sender, cmd, data);
-}
-
-void CheatDialog::sanitizeInput(GUI::EditTextWidget *textWidget, int maxValue) {
- const Common::U32String &str = textWidget->getEditString();
- for (uint i = 0; i < str.size(); ++i) {
- if (!Common::isDigit(str[i])) {
- textWidget->setEditString(str.substr(0, i));
- break;
- }
- }
-
- if (maxValue > -1) {
- int number = atoi(Common::String(str).c_str());
- if (number > maxValue) {
- textWidget->setEditString(Common::U32String::format("%d", maxValue));
- }
- }
-
- textWidget->setCaretPos(str.size());
-}
-
-EventFlagDialog::EventFlagDialog() : GUI::Dialog(20, 20, 600, 440) {
- _backgroundType = GUI::ThemeEngine::kDialogBackgroundSpecial;
- Common::WinResources *res = Common::WinResources::createFromEXE("game.exe");
- Common::Array<Common::WinResourceID> dialogIDs = res->getIDList(Common::kWinDialog);
-
- GUI::TabWidget *_tabs = new GUI::TabWidget(this, 0, 0, 600, 370);
- new GUI::ButtonWidget(this, 520, 410, 60, 20, _("Close"), Common::U32String(), GUI::kCloseCmd);
-
- for (uint i = 0; i < dialogIDs.size(); ++i) {
- Common::SeekableReadStream *resStream = res->getResource(Common::kWinDialog, dialogIDs[i].getID());
-
- Common::String idString;
- resStream->skip(0x16);
- while (true) {
- char add = resStream->readByte();
- if (add != 0) {
- idString += add;
- resStream->skip(1);
- } else {
- resStream->skip(1);
- break;
- }
- }
-
- if (!idString.hasPrefix("Event")) {
- continue;
- }
-
- idString.trim();
- _tabs->addTab(idString, Common::String("tab " + idString));
- uint numFlags = 0;
-
- while (resStream->pos() < resStream->size()) {
- if (resStream->readUint16LE() == 0xFFFF && resStream->readSint16LE() == 0x80) {
- // Found a resource, read its string id
- Common::String flagLabel;
-
- while (true) {
- char add = resStream->readByte();
- if (add != 0) {
- flagLabel += add;
- resStream->skip(1);
- } else {
- resStream->skip(1);
- break;
- }
- }
-
- // String begins with number so we assume it's an event flag radio button
- if (Common::isDigit(flagLabel.firstChar())) {
- Common::String num;
- uint j = 0;
- while (true) {
- if (Common::isDigit(flagLabel[j])) {
- num += flagLabel[j];
- } else {
- break;
- }
- ++j;
- }
-
- uint32 command = atoi(num.c_str()) << 16 | 'ev';
-
- GUI::CheckboxWidget *box = new GUI::CheckboxWidget(_tabs, 300 * (numFlags / 12) + 20, (350 / 12) * (numFlags % 12) + 15, 300, 350/12, _(flagLabel), Common::U32String(), command);
- box->setState(NancySceneState.getEventFlag(command >> 16));
-
- ++numFlags;
- }
- }
- }
- }
-
- _tabs->setActiveTab(0);
-}
-
-void EventFlagDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
- Dialog::handleCommand(sender, cmd, data);
- if (cmd & 'ev') {
- cmd >>= 16;
- NancySceneState.setEventFlag(cmd, data == 0 ? kFalse : kTrue);
- }
-}
-
-} // End of namespace Nancy
diff --git a/engines/nancy/cheat.h b/engines/nancy/cheat.h
deleted file mode 100644
index 9f7321c622..0000000000
--- a/engines/nancy/cheat.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* 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_CHEAT_H
-#define NANCY_CHEAT_H
-
-#include "gui/dialog.h"
-
-namespace GUI {
-class EditTextWidget;
-class CheckboxWidget;
-}
-
-namespace Nancy {
-
-class NancyEngine;
-
-class CheatDialog : public GUI::Dialog {
-public:
- CheatDialog();
-
-protected:
- enum Commands {
- kInputSceneNr = 'isnr',
- kInputFrameNr = 'ifnr',
- kInputScroll = 'iscr',
- kInputHintsEasy = 'ihea',
- kInputHintsMedium = 'ihme',
- kInputHintsHard = 'ihha',
- kInputPlayerTime = 'plti',
- kInputDifficulty = 'diff',
- kInputTimer = 'time'
- };
-
- void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
- static void sanitizeInput(GUI::EditTextWidget *textWidget, int maxValue = -1);
-
- GUI::CheckboxWidget *_restartScene;
- GUI::EditTextWidget *_scene;
- GUI::EditTextWidget *_frame;
- GUI::EditTextWidget *_offset;
-
- GUI::EditTextWidget *_hintsRemainingEasy;
- GUI::EditTextWidget *_hintsRemainingMedium;
- GUI::EditTextWidget *_hintsRemainingHard;
-
- GUI::EditTextWidget *_playerTimeDays;
- GUI::EditTextWidget *_playerTimeHours;
- GUI::EditTextWidget *_playerTimeMinutes;
- GUI::EditTextWidget *_difficulty;
-
- GUI::CheckboxWidget *_timerOn;
- GUI::EditTextWidget *_timerHours;
- GUI::EditTextWidget *_timerMinutes;
- GUI::EditTextWidget *_timerSeconds;
-
- Common::Array<GUI::CheckboxWidget *> _inventory;
-};
-
-class EventFlagDialog : public GUI::Dialog {
-public:
- EventFlagDialog();
-
-protected:
- void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
-};
-
-} // End of namespace Nancy
-
-#endif // NANCY_CHEAT_H
diff --git a/engines/nancy/dialogs.cpp b/engines/nancy/dialogs.cpp
index c899262a44..3c3ebf4232 100644
--- a/engines/nancy/dialogs.cpp
+++ b/engines/nancy/dialogs.cpp
@@ -20,11 +20,19 @@
*
*/
+#include "common/winexe.h"
#include "common/translation.h"
+#include "common/stream.h"
+
+#include "gui/widgets/tab.h"
+#include "gui/widgets/edittext.h"
#include "gui/ThemeEval.h"
#include "engines/nancy/dialogs.h"
+#include "engines/nancy/iff.h"
+
+#include "engines/nancy/state/scene.h"
namespace Nancy {
@@ -47,7 +55,7 @@ void NancyOptionsWidget::load() {
bool NancyOptionsWidget::save() {
ConfMan.setBool("player_speech", _playerSpeechCheckbox->getState(), _domain);
ConfMan.setBool("character_speech", _characterSpeechCheckbox->getState(), _domain);
- ConfMan.setBool("original_menus", _characterSpeechCheckbox->getState(), _domain);
+ ConfMan.setBool("original_menus", _originalMenusCheckbox->getState(), _domain);
return true;
}
@@ -70,5 +78,308 @@ bool NancyOptionsWidget::isInGame() const {
return _domain.equals(ConfMan.getActiveDomainName());
}
+// TODO rewrite this class so its layout is not hardcoded
+CheatDialog::CheatDialog() : GUI::Dialog(20, 20, 600, 440) {
+ _backgroundType = GUI::ThemeEngine::kDialogBackgroundSpecial;
+ Common::WinResources *res = Common::WinResources::createFromEXE("game.exe");
+ Common::Array<Common::WinResourceID> dialogIDs = res->getIDList(Common::kWinDialog);
+ State::SceneInfo scene = NancySceneState.getSceneInfo();
+ Time playerTime = NancySceneState._timers.playerTime;
+ Time timerTime = NancySceneState._timers.timerTime;
+ bool timerIsActive = NancySceneState._timers.timerIsActive;
+ if (!timerIsActive) {
+ timerTime = 0;
+ }
+
+ GUI::TabWidget *_tabs = new GUI::TabWidget(this, 0, 0, 600, 370);
+ new GUI::ButtonWidget(this, 420, 410, 60, 20, _("Cancel"), Common::U32String(), GUI::kCloseCmd);
+ new GUI::ButtonWidget(this, 520, 410, 60, 20, _("Ok"), Common::U32String(), GUI::kOKCmd);
+
+ _tabs->addTab(_("General"), "Cheat.General");
+
+ new GUI::StaticTextWidget(_tabs, 30, 20, 150, 20, _("Scene Data"), Graphics::kTextAlignLeft);
+ _restartScene = new GUI::CheckboxWidget(_tabs, 35, 50, 150, 20, _("Restart the Scene"));
+ _scene = new GUI::EditTextWidget(_tabs, 35, 75, 45, 20, Common::U32String::format("%u", scene.sceneID), Common::U32String(), kInputSceneNr, kInputSceneNr);
+ new GUI::StaticTextWidget(_tabs, 85, 75, 150, 20, _("Scene Number"), Graphics::kTextAlignLeft);
+ _frame = new GUI::EditTextWidget(_tabs, 35, 100, 45, 20, Common::U32String::format("%u", scene.frameID), Common::U32String(), kInputFrameNr, kInputFrameNr);
+ new GUI::StaticTextWidget(_tabs, 85, 100, 150, 20, _("Frame Number"), Graphics::kTextAlignLeft);
+ _offset = new GUI::EditTextWidget(_tabs, 35, 125, 45, 20, Common::U32String::format("%u", scene.verticalOffset), Common::U32String(), kInputScroll, kInputScroll);
+
+ // I18N: The Y position (a.k.a vertical scroll) of the background
+ new GUI::StaticTextWidget(_tabs, 85, 125, 150, 20, _("Background Top (Y)"), Graphics::kTextAlignLeft);
+
+ new GUI::StaticTextWidget(_tabs, 30, 160, 150, 20, _("Hints Remaining"), Graphics::kTextAlignLeft);
+ new GUI::StaticTextWidget(_tabs, 35, 185, 45, 20, _("Easy"), Graphics::kTextAlignLeft);
+ _hintsRemainingEasy = new GUI::EditTextWidget(_tabs, 35, 205, 45, 20, Common::U32String::format("%u", NancySceneState._hintsRemaining[0]), Common::U32String(), kInputHintsEasy, kInputHintsEasy);
+ new GUI::StaticTextWidget(_tabs, 85, 185, 45, 20, _("Medium"), Graphics::kTextAlignLeft);
+ _hintsRemainingMedium = new GUI::EditTextWidget(_tabs, 85, 205, 45, 20, Common::U32String::format("%u", NancySceneState._hintsRemaining[1]), Common::U32String(), kInputHintsMedium, kInputHintsMedium);
+ new GUI::StaticTextWidget(_tabs, 135, 185, 45, 20, _("Hard"), Graphics::kTextAlignLeft);
+ _hintsRemainingHard = new GUI::EditTextWidget(_tabs, 135, 205, 45, 20, Common::U32String::format("%u", NancySceneState._hintsRemaining[2]), Common::U32String(), kInputHintsHard, kInputHintsHard);
+
+ new GUI::StaticTextWidget(_tabs, 250, 20, 150, 20, _("Player Data"), Graphics::kTextAlignLeft);
+ new GUI::StaticTextWidget(_tabs, 255, 50, 150, 20, _("Player Time:"), Graphics::kTextAlignLeft);
+ _playerTimeDays = new GUI::EditTextWidget(_tabs, 255, 75, 35, 20, Common::U32String::format("%u", playerTime.getDays()), Common::U32String(), kInputPlayerTime, kInputPlayerTime);
+ new GUI::StaticTextWidget(_tabs, 295, 75, 40, 20, _("Days"), Graphics::kTextAlignLeft);
+ _playerTimeHours = new GUI::EditTextWidget(_tabs, 335, 75, 35, 20, Common::U32String::format("%u", playerTime.getHours()), Common::U32String(), kInputPlayerTime, kInputPlayerTime);
+ new GUI::StaticTextWidget(_tabs, 375, 75, 40, 20, _("Hours"), Graphics::kTextAlignLeft);
+ _playerTimeMinutes = new GUI::EditTextWidget(_tabs, 415, 75, 35, 20, Common::U32String::format("%u", playerTime.getMinutes()), Common::U32String(), kInputPlayerTime, kInputPlayerTime);
+ new GUI::StaticTextWidget(_tabs, 455, 75, 50, 20, _("Minutes"), Graphics::kTextAlignLeft);
+ _difficulty = new GUI::EditTextWidget(_tabs, 255, 105, 35, 20, Common::U32String::format("%u", NancySceneState._difficulty), Common::U32String(), kInputDifficulty, kInputDifficulty);
+ new GUI::StaticTextWidget(_tabs, 295, 105, 150, 20, _("Player Difficulty Level"), Graphics::kTextAlignLeft);
+
+ new GUI::StaticTextWidget(_tabs, 250, 140, 150, 20, _("Software Timer"), Graphics::kTextAlignLeft);
+ _timerOn = new GUI::CheckboxWidget(_tabs, 255, 170, 150, 20, _("Timer On"));
+ _timerOn->setState(timerIsActive);
+ _timerHours = new GUI::EditTextWidget(_tabs, 255, 195, 35, 20, Common::U32String::format("%u", timerTime.getTotalHours()), Common::U32String(), kInputTimer, kInputTimer);
+ new GUI::StaticTextWidget(_tabs, 295, 195, 40, 20, _("Hours"), Graphics::kTextAlignLeft);
+ _timerMinutes = new GUI::EditTextWidget(_tabs, 335, 195, 35, 20, Common::U32String::format("%u", timerTime.getMinutes()), Common::U32String(), kInputTimer, kInputTimer);
+ new GUI::StaticTextWidget(_tabs, 375, 195, 50, 20, _("Minutes"), Graphics::kTextAlignLeft);
+ _timerSeconds = new GUI::EditTextWidget(_tabs, 425, 195, 35, 20, Common::U32String::format("%u", timerTime.getSeconds()), Common::U32String(), kInputTimer, kInputTimer);
+ new GUI::StaticTextWidget(_tabs, 465, 195, 50, 20, _("Seconds"), Graphics::kTextAlignLeft);
+
+ _tabs->addTab(_("Inventory"), "Cheat.Inventory");
+
+ for (uint i = 0; i < dialogIDs.size(); ++i) {
+ Common::SeekableReadStream *resStream = res->getResource(Common::kWinDialog, dialogIDs[i].getID());
+
+ Common::String idString;
+ resStream->skip(0x16);
+ while (true) {
+ char add = resStream->readByte();
+ if (add != 0) {
+ idString += add;
+ resStream->skip(1);
+ } else {
+ resStream->skip(1);
+ break;
+ }
+ }
+
+ if (!idString.hasPrefix("Inventory")) {
+ continue;
+ }
+
+ idString.trim();
+ uint numItems = 0;
+
+ while (resStream->pos() < resStream->size()) {
+ if (resStream->readUint16LE() == 0xFFFF && resStream->readSint16LE() == 0x80) {
+ // Found a resource, read its string id
+ Common::String itemLabel;
+
+ while (true) {
+ char add = resStream->readByte();
+ if (add != 0) {
+ itemLabel += add;
+ resStream->skip(1);
+ } else {
+ resStream->skip(1);
+ break;
+ }
+ }
+ GUI::CheckboxWidget *box = new GUI::CheckboxWidget(_tabs, 250 * (numItems / 10) + 20, (350 / 10) * (numItems % 10) + 15, 250, 250/10, Common::U32String(itemLabel));
+ box->setState(NancySceneState.hasItem(numItems) == kTrue);
+ _inventory.push_back(box);
+
+ ++numItems;
+ }
+ }
+
+ break;
+ }
+
+ _tabs->setActiveTab(0);
+}
+
+void CheatDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
+ switch (cmd) {
+ case GUI::kOKCmd: {
+ if (_restartScene->getState()) {
+ uint sceneID = atoi(Common::String(_scene->getEditString()).c_str());
+ IFF iff(Common::String::format("S%u", sceneID));
+ if (iff.load()) {
+ NancySceneState.changeScene(
+ atoi(Common::String(_scene->getEditString()).c_str()),
+ atoi(Common::String(_frame->getEditString()).c_str()),
+ atoi(Common::String(_offset->getEditString()).c_str()),
+ true);
+ } else {
+ new GUI::StaticTextWidget(this, 20, 410, 150, 20, _("Invalid Scene ID!"), Graphics::kTextAlignLeft);
+ return;
+ }
+ }
+
+ if (_timerOn->getState()) {
+ NancySceneState._timers.timerIsActive = true;
+ Time &timer = NancySceneState._timers.timerTime;
+ timer = 0;
+ timer += 1000 * atoi(Common::String(_timerSeconds->getEditString()).c_str());
+ timer += 60000 * atoi(Common::String(_timerMinutes->getEditString()).c_str());
+ timer += 3600000 * atoi(Common::String(_timerHours->getEditString()).c_str());
+ } else {
+ NancySceneState.stopTimer();
+ }
+
+ Time &playerTime = NancySceneState._timers.timerTime;
+ playerTime = 0;
+ playerTime += 60000 * atoi(Common::String(_playerTimeMinutes->getEditString()).c_str());
+ playerTime += 3600000 * atoi(Common::String(_playerTimeHours->getEditString()).c_str());
+ playerTime += 86400000 * atoi(Common::String(_playerTimeMinutes->getEditString()).c_str());
+
+ NancySceneState._difficulty = atoi(Common::String(_difficulty->getEditString()).c_str());
+ NancySceneState._hintsRemaining[0] = atoi(Common::String(_hintsRemainingEasy->getEditString()).c_str());
+ NancySceneState._hintsRemaining[1] = atoi(Common::String(_hintsRemainingMedium->getEditString()).c_str());
+ NancySceneState._hintsRemaining[2] = atoi(Common::String(_hintsRemainingHard->getEditString()).c_str());
+
+ for (uint i = 0; i < _inventory.size(); ++i) {
+ if (NancySceneState.hasItem(i) == kTrue && !_inventory[i]->getState()) {
+ NancySceneState.removeItemFromInventory(i, false);
+ } else if (NancySceneState.hasItem(i) == kFalse && _inventory[i]->getState()) {
+ NancySceneState.addItemToInventory(i);
+ }
+ }
+ cmd = GUI::kCloseCmd;
+
+ break;
+ }
+ case kInputSceneNr:
+ sanitizeInput(_scene);
+ break;
+ case kInputFrameNr:
+ sanitizeInput(_frame);
+ break;
+ case kInputScroll:
+ sanitizeInput(_offset);
+ break;
+ case kInputDifficulty:
+ sanitizeInput(_scene, 2);
+ break;
+ case kInputHintsEasy:
+ sanitizeInput(_hintsRemainingEasy);
+ break;
+ case kInputHintsMedium:
+ sanitizeInput(_hintsRemainingMedium);
+ break;
+ case kInputHintsHard:
+ sanitizeInput(_hintsRemainingHard);
+ break;
+ case kInputPlayerTime:
+ sanitizeInput(_playerTimeMinutes, 59);
+ sanitizeInput(_playerTimeHours, 23);
+ sanitizeInput(_playerTimeDays);
+ break;
+ case kInputTimer:
+ sanitizeInput(_timerSeconds, 59);
+ sanitizeInput(_timerMinutes, 59);
+ sanitizeInput(_timerHours, 23);
+ break;
+ default:
+ break;
+ }
+
+ Dialog::handleCommand(sender, cmd, data);
+}
+
+void CheatDialog::sanitizeInput(GUI::EditTextWidget *textWidget, int maxValue) {
+ const Common::U32String &str = textWidget->getEditString();
+ for (uint i = 0; i < str.size(); ++i) {
+ if (!Common::isDigit(str[i])) {
+ textWidget->setEditString(str.substr(0, i));
+ break;
+ }
+ }
+
+ if (maxValue > -1) {
+ int number = atoi(Common::String(str).c_str());
+ if (number > maxValue) {
+ textWidget->setEditString(Common::U32String::format("%d", maxValue));
+ }
+ }
+
+ textWidget->setCaretPos(str.size());
+}
+
+EventFlagDialog::EventFlagDialog() : GUI::Dialog(20, 20, 600, 440) {
+ _backgroundType = GUI::ThemeEngine::kDialogBackgroundSpecial;
+ Common::WinResources *res = Common::WinResources::createFromEXE("game.exe");
+ Common::Array<Common::WinResourceID> dialogIDs = res->getIDList(Common::kWinDialog);
+
+ GUI::TabWidget *_tabs = new GUI::TabWidget(this, 0, 0, 600, 370);
+ new GUI::ButtonWidget(this, 520, 410, 60, 20, _("Close"), Common::U32String(), GUI::kCloseCmd);
+
+ for (uint i = 0; i < dialogIDs.size(); ++i) {
+ Common::SeekableReadStream *resStream = res->getResource(Common::kWinDialog, dialogIDs[i].getID());
+
+ Common::String idString;
+ resStream->skip(0x16);
+ while (true) {
+ char add = resStream->readByte();
+ if (add != 0) {
+ idString += add;
+ resStream->skip(1);
+ } else {
+ resStream->skip(1);
+ break;
+ }
+ }
+
+ if (!idString.hasPrefix("Event")) {
+ continue;
+ }
+
+ idString.trim();
+ _tabs->addTab(idString, Common::String("tab " + idString));
+ uint numFlags = 0;
+
+ while (resStream->pos() < resStream->size()) {
+ if (resStream->readUint16LE() == 0xFFFF && resStream->readSint16LE() == 0x80) {
+ // Found a resource, read its string id
+ Common::String flagLabel;
+
+ while (true) {
+ char add = resStream->readByte();
+ if (add != 0) {
+ flagLabel += add;
+ resStream->skip(1);
+ } else {
+ resStream->skip(1);
+ break;
+ }
+ }
+
+ // String begins with number so we assume it's an event flag radio button
+ if (Common::isDigit(flagLabel.firstChar())) {
+ Common::String num;
+ uint j = 0;
+ while (true) {
+ if (Common::isDigit(flagLabel[j])) {
+ num += flagLabel[j];
+ } else {
+ break;
+ }
+ ++j;
+ }
+
+ uint32 command = atoi(num.c_str()) << 16 | 'ev';
+
+ GUI::CheckboxWidget *box = new GUI::CheckboxWidget(_tabs, 300 * (numFlags / 12) + 20, (350 / 12) * (numFlags % 12) + 15, 300, 350/12, Common::U32String(flagLabel), Common::U32String(), command);
+ box->setState(NancySceneState.getEventFlag(command >> 16));
+
+ ++numFlags;
+ }
+ }
+ }
+ }
+
+ _tabs->setActiveTab(0);
+}
+
+void EventFlagDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
+ Dialog::handleCommand(sender, cmd, data);
+ if (cmd & 'ev') {
+ cmd >>= 16;
+ NancySceneState.setEventFlag(cmd, data == 0 ? kFalse : kTrue);
+ }
+}
} // End of namespace Nancy
diff --git a/engines/nancy/dialogs.h b/engines/nancy/dialogs.h
index 6cb167f4f4..53da8ff657 100644
--- a/engines/nancy/dialogs.h
+++ b/engines/nancy/dialogs.h
@@ -45,6 +45,56 @@ private:
GUI::CheckboxWidget *_originalMenusCheckbox;
};
+class CheatDialog : public GUI::Dialog {
+public:
+ CheatDialog();
+
+protected:
+ enum Commands {
+ kInputSceneNr = 'isnr',
+ kInputFrameNr = 'ifnr',
+ kInputScroll = 'iscr',
+ kInputHintsEasy = 'ihea',
+ kInputHintsMedium = 'ihme',
+ kInputHintsHard = 'ihha',
+ kInputPlayerTime = 'plti',
+ kInputDifficulty = 'diff',
+ kInputTimer = 'time'
+ };
+
+ void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
+ static void sanitizeInput(GUI::EditTextWidget *textWidget, int maxValue = -1);
+
+ GUI::CheckboxWidget *_restartScene;
+ GUI::EditTextWidget *_scene;
+ GUI::EditTextWidget *_frame;
+ GUI::EditTextWidget *_offset;
+
+ GUI::EditTextWidget *_hintsRemainingEasy;
+ GUI::EditTextWidget *_hintsRemainingMedium;
+ GUI::EditTextWidget *_hintsRemainingHard;
+
+ GUI::EditTextWidget *_playerTimeDays;
+ GUI::EditTextWidget *_playerTimeHours;
+ GUI::EditTextWidget *_playerTimeMinutes;
+ GUI::EditTextWidget *_difficulty;
+
+ GUI::CheckboxWidget *_timerOn;
+ GUI::EditTextWidget *_timerHours;
+ GUI::EditTextWidget *_timerMinutes;
+ GUI::EditTextWidget *_timerSeconds;
+
+ Common::Array<GUI::CheckboxWidget *> _inventory;
+};
+
+class EventFlagDialog : public GUI::Dialog {
+public:
+ EventFlagDialog();
+
+protected:
+ void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
+};
+
} // End of namespace Nancy
#endif // NANCY_DIALOGS_H
diff --git a/engines/nancy/module.mk b/engines/nancy/module.mk
index 6f8c5733f9..1f71a8c133 100644
--- a/engines/nancy/module.mk
+++ b/engines/nancy/module.mk
@@ -27,7 +27,6 @@ MODULE_OBJS = \
state/mainmenu.o \
state/map.o \
state/scene.o \
- cheat.o \
commontypes.o \
console.o \
cursor.o \
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index a5a32fc6b8..b3a0d0fe7d 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -34,7 +34,7 @@
#include "engines/nancy/input.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/graphics.h"
-#include "engines/nancy/cheat.h"
+#include "engines/nancy/dialogs.h"
#include "engines/nancy/console.h"
#include "engines/nancy/action/primaryvideo.h"
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index f98cd6d3a6..67e5464f89 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -196,7 +196,7 @@ void Scene::setHeldItem(int16 id) {
}
void Scene::setEventFlag(int16 label, NancyFlag flag) {
- if (label > -1) {
+ if (label > -1 && label < 168) {
_flags.eventFlags[label] = flag;
}
}
More information about the Scummvm-git-logs
mailing list