aboutsummaryrefslogtreecommitdiff
path: root/engines/titanic
diff options
context:
space:
mode:
Diffstat (limited to 'engines/titanic')
-rw-r--r--engines/titanic/carry/mouth.cpp5
-rw-r--r--engines/titanic/game/bridge_view.cpp5
-rw-r--r--engines/titanic/game/chicken_dispensor.cpp9
-rw-r--r--engines/titanic/game/fan_control.cpp2
-rw-r--r--engines/titanic/game_manager.cpp2
-rw-r--r--engines/titanic/main_game_window.cpp6
-rw-r--r--engines/titanic/npcs/titania.cpp13
-rw-r--r--engines/titanic/sound/qmixer.cpp22
-rw-r--r--engines/titanic/sound/sound_manager.cpp2
-rw-r--r--engines/titanic/sound/wave_file.cpp9
-rw-r--r--engines/titanic/sound/wave_file.h6
-rw-r--r--engines/titanic/support/credit_text.cpp2
-rw-r--r--engines/titanic/titanic.cpp62
-rw-r--r--engines/titanic/titanic.h10
14 files changed, 119 insertions, 36 deletions
diff --git a/engines/titanic/carry/mouth.cpp b/engines/titanic/carry/mouth.cpp
index d750fc969e..1b2830b99e 100644
--- a/engines/titanic/carry/mouth.cpp
+++ b/engines/titanic/carry/mouth.cpp
@@ -74,6 +74,11 @@ bool CMouth::PETGainedObjectMsg(CPETGainedObjectMsg *msg) {
_field13C = true;
}
+ // WORKAROUND: If Mouth is removed from Titania after inserting,
+ // message the Titania control so it can be flagged as removed
+ CTakeHeadPieceMsg headpieceMsg(getName());
+ headpieceMsg.execute("TitaniaControl");
+
return true;
}
diff --git a/engines/titanic/game/bridge_view.cpp b/engines/titanic/game/bridge_view.cpp
index e8d70c8c43..14361b4e8c 100644
--- a/engines/titanic/game/bridge_view.cpp
+++ b/engines/titanic/game/bridge_view.cpp
@@ -55,6 +55,7 @@ bool CBridgeView::ActMsg(CActMsg *msg) {
} else if (msg->_action == "Go") {
_action = BA_GO;
setVisible(true);
+ hideMouse();
volumeMsg._volume = 100;
volumeMsg.execute("EngineSounds");
onMsg.execute("EngineSounds");
@@ -67,10 +68,13 @@ bool CBridgeView::ActMsg(CActMsg *msg) {
if (msg->_action == "Cruise") {
_action = BA_CRUISE;
setVisible(true);
+ hideMouse();
playMovie(MOVIE_NOTIFY_OBJECT);
} else if (msg->_action == "GoEnd") {
_action = BA_ENDING1;
setVisible(true);
+ hideMouse();
+
CChangeMusicMsg musicMsg;
musicMsg._flags = 1;
musicMsg.execute("BridgeAutoMusicPlayer");
@@ -90,6 +94,7 @@ bool CBridgeView::MovieEndMsg(CMovieEndMsg *msg) {
case BA_GO:
case BA_CRUISE:
setVisible(false);
+ showMouse();
decTransitions();
break;
diff --git a/engines/titanic/game/chicken_dispensor.cpp b/engines/titanic/game/chicken_dispensor.cpp
index 89873dcc4d..d44bc7157b 100644
--- a/engines/titanic/game/chicken_dispensor.cpp
+++ b/engines/titanic/game/chicken_dispensor.cpp
@@ -104,7 +104,7 @@ bool CChickenDispensor::StatusChangeMsg(CStatusChangeMsg *msg) {
}
bool CChickenDispensor::MovieEndMsg(CMovieEndMsg *msg) {
- int movieFrame = getMovieFrame();
+ int movieFrame = msg->_endFrame;
if (movieFrame == 16) {
// Dispensed a chicken
@@ -113,12 +113,7 @@ bool CChickenDispensor::MovieEndMsg(CMovieEndMsg *msg) {
CActMsg actMsg("Dispense Chicken");
actMsg.execute("Chicken");
- if (_dispenseMode == DISPENSE_HOT) {
- // A properly hot chicken is dispensed, no further ones will be
- // until the current one is used up, and the fuse in Titania's
- // fusebox is removed and replaced
- _dispenseMode = DISPENSE_NONE;
- } else {
+ if (_dispenseMode != DISPENSE_HOT) {
// WORKAROUND: If the fuse for the dispensor is removed in Titania's fusebox,
// make the dispensed chicken already cold
CChicken::_temperature = 0;
diff --git a/engines/titanic/game/fan_control.cpp b/engines/titanic/game/fan_control.cpp
index 7ed22fd560..fc99bd8b36 100644
--- a/engines/titanic/game/fan_control.cpp
+++ b/engines/titanic/game/fan_control.cpp
@@ -107,7 +107,7 @@ bool CFanControl::StatusChangeMsg(CStatusChangeMsg *msg) {
case 2:
// Fan Speed button
if (_fanOn) {
- _state = (_state + 1) % 4;
+ _state = (_state + 1) % 3;
switch (_state) {
case 0:
playMovie(18, 24, 0);
diff --git a/engines/titanic/game_manager.cpp b/engines/titanic/game_manager.cpp
index 13fe1d2872..65a2a278c8 100644
--- a/engines/titanic/game_manager.cpp
+++ b/engines/titanic/game_manager.cpp
@@ -81,8 +81,8 @@ void CGameManager::preLoad() {
_timers.destroyContents();
_soundMaker = nullptr;
- _trueTalkManager.preLoad();
_sound.preLoad();
+ _trueTalkManager.preLoad();
}
void CGameManager::postLoad(CProjectItem *project) {
diff --git a/engines/titanic/main_game_window.cpp b/engines/titanic/main_game_window.cpp
index 053712d412..cfea98cdf1 100644
--- a/engines/titanic/main_game_window.cpp
+++ b/engines/titanic/main_game_window.cpp
@@ -341,6 +341,12 @@ void CMainGameWindow::keyDown(Common::KeyState keyState) {
_gameManager->_gameState.changeView(newView, nullptr);
}
+ } else if (keyState.keycode == Common::KEYCODE_F5) {
+ // Show the GMM save dialog
+ g_vm->showScummVMSaveDialog();
+ } else if (keyState.keycode == Common::KEYCODE_F7) {
+ // Show the GMM load dialog
+ g_vm->showScummVMRestoreDialog();
} else if (_inputAllowed) {
_gameManager->_inputTranslator.keyDown(keyState);
}
diff --git a/engines/titanic/npcs/titania.cpp b/engines/titanic/npcs/titania.cpp
index 70ca4bace6..d3e3395fc8 100644
--- a/engines/titanic/npcs/titania.cpp
+++ b/engines/titanic/npcs/titania.cpp
@@ -149,9 +149,10 @@ bool CTitania::ActMsg(CActMsg *msg) {
playSound("z#47.wav", 100);
changeView("Titania.Node 7.S", "");
+ // Re-enable control, and reset bomb's volume back to normal 60%
petShow();
enableMouse();
- CSetFrameMsg frameMsg;
+ CSetFrameMsg frameMsg(60);
frameMsg.execute("Bomb");
} else if (msg->_action == "CheckHead") {
@@ -173,8 +174,9 @@ bool CTitania::ActMsg(CActMsg *msg) {
workingMsg3._value = _speechCentre ? "Working" : "Random";
}
- if (_centralCore && _eye1 && _eye2 && _ear1 && _ear2 && _nose && _mouth
- && _speechCentre && _olfactoryCentre && _auditoryCentre) {
+ if (_centralCore && _eye1 && _eye2 && _ear1 && _ear2 && _nose
+ && _mouth && _visionCentre && _speechCentre
+ && _olfactoryCentre && _auditoryCentre) {
CProximity prox(Audio::Mixer::kSpeechSoundType);
playSound("z#47.wav", prox);
@@ -203,11 +205,14 @@ bool CTitania::EnterViewMsg(CEnterViewMsg *msg) {
disableMouse();
petHide();
+ // The Bomb uses the CSetFrameMsg as a hack for setting the volume.
+ // In case it's currently active, set it to a quieter 25% so that
+ // it won't obscure Titania's speech.
CSetFrameMsg frameMsg;
frameMsg._frameNumber = 25;
frameMsg.execute("Bomb");
- playCutscene(0, 52);
+ playCutscene(0, 52);
setVisible(false);
CActMsg actMsg("TitaniaSpeech");
actMsg.execute("TitaniaSpeech");
diff --git a/engines/titanic/sound/qmixer.cpp b/engines/titanic/sound/qmixer.cpp
index 5c511c3cae..beb1502ab4 100644
--- a/engines/titanic/sound/qmixer.cpp
+++ b/engines/titanic/sound/qmixer.cpp
@@ -208,18 +208,13 @@ void QMixer::qsWaveMixPump() {
if (!channel._sounds.empty()) {
SoundEntry &sound = channel._sounds.front();
if (sound._started && !_mixer->isSoundHandleActive(sound._soundHandle)) {
- if (sound._loops == -1 || sound._loops-- > 0) {
- // Need to loop (replay) the sound again
- sound._soundHandle = sound._waveFile->play(channel.getRawVolume());
- } else {
- // Sound is finished
- if (sound._callback)
- // Call the callback to signal end
- sound._callback(iChannel, sound._waveFile, sound._userData);
-
- // Remove sound record from channel
- channel._sounds.erase(channel._sounds.begin());
- }
+ // Sound is finished
+ if (sound._callback)
+ // Call the callback to signal end
+ sound._callback(iChannel, sound._waveFile, sound._userData);
+
+ // Remove sound record from channel
+ channel._sounds.erase(channel._sounds.begin());
}
}
@@ -232,7 +227,8 @@ void QMixer::qsWaveMixPump() {
channel._distance = 0.0;
// Play the wave
- sound._soundHandle = sound._waveFile->play(channel.getRawVolume());
+ sound._soundHandle = sound._waveFile->play(
+ sound._loops, channel.getRawVolume());
sound._started = true;
}
}
diff --git a/engines/titanic/sound/sound_manager.cpp b/engines/titanic/sound/sound_manager.cpp
index 514618783b..4b5887b1e7 100644
--- a/engines/titanic/sound/sound_manager.cpp
+++ b/engines/titanic/sound/sound_manager.cpp
@@ -288,7 +288,7 @@ void QSoundManager::setVolume(int handle, uint volume, uint seconds) {
_channelsVolume[slot._channel] = volume;
updateVolume(slot._channel, seconds * 1000);
- if (volume) {
+ if (!volume) {
uint ticks = g_vm->_events->getTicksCount() + seconds * 1000;
if (!slot._ticks || ticks >= slot._ticks)
slot._ticks = ticks;
diff --git a/engines/titanic/sound/wave_file.cpp b/engines/titanic/sound/wave_file.cpp
index 8a4755ac97..c1aab42a7f 100644
--- a/engines/titanic/sound/wave_file.cpp
+++ b/engines/titanic/sound/wave_file.cpp
@@ -204,10 +204,15 @@ void CWaveFile::unlock(const int16 *ptr) {
// No implementation needed in ScummVM
}
-Audio::SoundHandle CWaveFile::play(byte volume) {
- Audio::SeekableAudioStream *stream = createAudioStream();
+Audio::SoundHandle CWaveFile::play(int numLoops, byte volume) {
+ Audio::SeekableAudioStream *audioStream = createAudioStream();
Audio::SoundHandle handle;
+ Audio::AudioStream *stream = audioStream;
+ if (numLoops != 0)
+ stream = new Audio::LoopingAudioStream(audioStream,
+ (numLoops == -1) ? 0 : numLoops);
+
_mixer->playStream(_soundType, &handle, stream, -1,
volume, 0, DisposeAfterUse::NO);
return handle;
diff --git a/engines/titanic/sound/wave_file.h b/engines/titanic/sound/wave_file.h
index 17c7b62f4b..c14891e2e4 100644
--- a/engines/titanic/sound/wave_file.h
+++ b/engines/titanic/sound/wave_file.h
@@ -126,8 +126,12 @@ public:
/**
* Plays the wave file
+ * @param numLoops Number of times to loop. 0 for none,
+ * -1 for infinite, and >0 for specified number of times
+ * @param volume Volume to play at
+ * @returns Audio handle for started sound
*/
- Audio::SoundHandle play(byte volume);
+ Audio::SoundHandle play(int numLoops, byte volume);
};
} // End of namespace Titanic
diff --git a/engines/titanic/support/credit_text.cpp b/engines/titanic/support/credit_text.cpp
index 98c3d9bf1d..6ee17a2b95 100644
--- a/engines/titanic/support/credit_text.cpp
+++ b/engines/titanic/support/credit_text.cpp
@@ -96,7 +96,7 @@ void CCreditText::setup() {
_screenManagerP->setFontNumber(oldFontNumber);
_groupIt = _groups.begin();
_lineIt = (*_groupIt)->_lines.begin();
- _yOffset = _objectP->getBounds().height() + _fontHeight * 2;
+ _yOffset = _objectP->_bounds.height() + _fontHeight * 2;
}
CString CCreditText::readLine(Common::SeekableReadStream *stream) {
diff --git a/engines/titanic/titanic.cpp b/engines/titanic/titanic.cpp
index 8a1b00c0fc..b6ee868877 100644
--- a/engines/titanic/titanic.cpp
+++ b/engines/titanic/titanic.cpp
@@ -25,9 +25,11 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/events.h"
+#include "common/translation.h"
#include "engines/util.h"
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
+#include "gui/saveload.h"
#include "titanic/titanic.h"
#include "titanic/debugger.h"
#include "titanic/carry/hose.h"
@@ -179,23 +181,30 @@ bool TitanicEngine::canLoadGameStateCurrently() {
CGameManager *gameManager = _window->_gameManager;
CScreenManager *screenMan = CScreenManager::_screenManagerPtr;
- if (!_window->_inputAllowed || !gameManager->_gameState._petActive)
+ if (!_window->_inputAllowed)
return false;
if (screenMan && screenMan->_inputHandler->isLocked())
return false;
CProjectItem *project = gameManager->_project;
if (project) {
- CPetControl *pet = project->getPetControl();
- if (pet && !pet->isAreaUnlocked())
- return false;
+ if (gameManager->_gameState._petActive) {
+ CPetControl *pet = project->getPetControl();
+ if (pet && !pet->isAreaUnlocked())
+ return false;
+ }
+ } else {
+ return false;
}
return true;
}
bool TitanicEngine::canSaveGameStateCurrently() {
- return canLoadGameStateCurrently();
+ CGameManager *gameManager = _window->_gameManager;
+
+ return gameManager->_gameState._petActive &&
+ canLoadGameStateCurrently();
}
Common::Error TitanicEngine::loadGameState(int slot) {
@@ -251,4 +260,47 @@ void TitanicEngine::GUIError(const char *msg, ...) {
GUIErrorMessage(buffer);
}
+
+void TitanicEngine::showScummVMSaveDialog() {
+ if (!canSaveGameStateCurrently())
+ return;
+
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+
+ pauseEngine(true);
+ int slot = dialog->runModalWithCurrentTarget();
+ pauseEngine(false);
+
+ if (slot >= 0) {
+ Common::String desc = dialog->getResultString();
+
+ if (desc.empty()) {
+ // create our own description for the saved game, the user didn't enter it
+ desc = dialog->createDefaultSaveDescription(slot);
+ }
+
+ // Save the game
+ saveGameState(slot, desc);
+ }
+
+ delete dialog;
+}
+
+void TitanicEngine::showScummVMRestoreDialog() {
+ if (!canLoadGameStateCurrently())
+ return;
+
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
+
+ pauseEngine(true);
+ int slot = dialog->runModalWithCurrentTarget();
+ pauseEngine(false);
+
+ if (slot >= 0) {
+ loadGameState(slot);
+ }
+
+ delete dialog;
+}
+
} // End of namespace Titanic
diff --git a/engines/titanic/titanic.h b/engines/titanic/titanic.h
index dc7fd156b8..0c15cf3e72 100644
--- a/engines/titanic/titanic.h
+++ b/engines/titanic/titanic.h
@@ -191,6 +191,16 @@ public:
* Displays an error message in a GUI dialog
*/
void GUIError(const char *msg, ...) GCC_PRINTF(2, 3);
+
+ /**
+ * Shows the ScummVM GMM save dialog
+ */
+ void showScummVMSaveDialog();
+
+ /**
+ * Shows the ScummVM GMM load dialog
+ */
+ void showScummVMRestoreDialog();
};
extern TitanicEngine *g_vm;