diff options
Diffstat (limited to 'engines/pegasus')
35 files changed, 324 insertions, 75 deletions
diff --git a/engines/pegasus/ai/ai_area.cpp b/engines/pegasus/ai/ai_area.cpp index 5ac8af8812..9cab568d66 100644 --- a/engines/pegasus/ai/ai_area.cpp +++ b/engines/pegasus/ai/ai_area.cpp @@ -234,6 +234,7 @@ void AIArea::playAIAreaSequence(const LowerClientSignature, const LowerAreaSigna vm->_cursor->hide(); while (_middleAreaMovie.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -258,6 +259,7 @@ void AIArea::playAIAreaSequence(const LowerClientSignature, const LowerAreaSigna vm->_cursor->hide(); while (_rightAreaMovie.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); diff --git a/engines/pegasus/configure.engine b/engines/pegasus/configure.engine new file mode 100644 index 0000000000..ed7e295287 --- /dev/null +++ b/engines/pegasus/configure.engine @@ -0,0 +1,3 @@ +# This file is included from the main "configure" script +# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] +add_engine pegasus "The Journeyman Project: Pegasus Prime" yes "" "" "16bit" diff --git a/engines/pegasus/console.cpp b/engines/pegasus/console.cpp index 64bd0ba5f2..e5a0cfec98 100644 --- a/engines/pegasus/console.cpp +++ b/engines/pegasus/console.cpp @@ -28,11 +28,11 @@ namespace Pegasus { PegasusConsole::PegasusConsole(PegasusEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("die", WRAP_METHOD(PegasusConsole, Cmd_Die)); + registerCmd("die", WRAP_METHOD(PegasusConsole, Cmd_Die)); // These functions are non-demo specific if (!_vm->isDemo()) - DCmd_Register("jump", WRAP_METHOD(PegasusConsole, Cmd_Jump)); + registerCmd("jump", WRAP_METHOD(PegasusConsole, Cmd_Jump)); } PegasusConsole::~PegasusConsole() { @@ -40,7 +40,7 @@ PegasusConsole::~PegasusConsole() { bool PegasusConsole::Cmd_Die(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: die <death reason>\n"); + debugPrintf("Usage: die <death reason>\n"); return true; } @@ -54,7 +54,7 @@ bool PegasusConsole::Cmd_Die(int argc, const char **argv) { if (invalidReason) { - DebugPrintf("Invalid death reason %d\n", reason); + debugPrintf("Invalid death reason %d\n", reason); return true; } @@ -65,14 +65,14 @@ bool PegasusConsole::Cmd_Die(int argc, const char **argv) { bool PegasusConsole::Cmd_Jump(int argc, const char **argv) { if (!g_interface) { // TODO - DebugPrintf("Cannot jump without interface set up\n"); + debugPrintf("Cannot jump without interface set up\n"); return true; } // TODO: Default room/direction for each neighborhood if (argc < 4) { - DebugPrintf("Usage: jump <neighborhood> <room> <direction>\n"); + debugPrintf("Usage: jump <neighborhood> <room> <direction>\n"); return true; } @@ -82,14 +82,14 @@ bool PegasusConsole::Cmd_Jump(int argc, const char **argv) { if ((neighborhood < kCaldoriaID || neighborhood > kNoradDeltaID || neighborhood == kFinalTSAID) && neighborhood != kNoradSubChaseID) { - DebugPrintf("Invalid neighborhood %d", neighborhood); + debugPrintf("Invalid neighborhood %d", neighborhood); return true; } // No real way to check room validity at this point if (direction > kWest) { - DebugPrintf("Invalid direction %d", direction); + debugPrintf("Invalid direction %d", direction); return true; } diff --git a/engines/pegasus/cursor.cpp b/engines/pegasus/cursor.cpp index ad0d2c2d7d..602ae88068 100644 --- a/engines/pegasus/cursor.cpp +++ b/engines/pegasus/cursor.cpp @@ -28,7 +28,7 @@ #include "common/system.h" #include "graphics/cursorman.h" #include "graphics/surface.h" -#include "graphics/decoders/pict.h" +#include "image/pict.h" #include "pegasus/cursor.h" #include "pegasus/graphics.h" @@ -148,7 +148,7 @@ void Cursor::loadCursorImage(CursorInfo &cursorInfo) { Common::SeekableReadStream *pictStream = vm->_resFork->getResource(MKTAG('P', 'I', 'C', 'T'), cursorInfo.tag + 1000); if (pictStream) { - Graphics::PICTDecoder pict; + Image::PICTDecoder pict; if (!pict.loadStream(*pictStream)) error("Failed to decode cursor PICT %d", cursorInfo.tag + 1000); @@ -166,7 +166,7 @@ void Cursor::loadCursorImage(CursorInfo &cursorInfo) { error("Failed to find color icon %d", cursorInfo.tag); // PixMap section - Graphics::PICTDecoder::PixMap pixMap = Graphics::PICTDecoder::readPixMap(*cicnStream); + Image::PICTDecoder::PixMap pixMap = Image::PICTDecoder::readPixMap(*cicnStream); // Mask section cicnStream->readUint32BE(); // mask baseAddr diff --git a/engines/pegasus/energymonitor.cpp b/engines/pegasus/energymonitor.cpp index be9d205360..40e54afb89 100644 --- a/engines/pegasus/energymonitor.cpp +++ b/engines/pegasus/energymonitor.cpp @@ -269,6 +269,7 @@ void EnergyMonitor::calibrateEnergyBar() { // Make sure warning light is hidden... _energyLight.hide(); while (getCurrentEnergy() != (int32)kMaxJMPEnergy) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); diff --git a/engines/pegasus/fader.cpp b/engines/pegasus/fader.cpp index a2bbf22944..80ce8ef5dc 100644 --- a/engines/pegasus/fader.cpp +++ b/engines/pegasus/fader.cpp @@ -94,6 +94,7 @@ void Fader::startFaderSync(const FaderMoveSpec &spec) { start(); while (isFading()) { + InputDevice.pumpEvents(); ((PegasusEngine *)g_engine)->checkCallBacks(); useIdleTime(); } diff --git a/engines/pegasus/input.cpp b/engines/pegasus/input.cpp index b74e4a4c45..e1b7e25cd5 100644 --- a/engines/pegasus/input.cpp +++ b/engines/pegasus/input.cpp @@ -57,9 +57,10 @@ InputDeviceManager::InputDeviceManager() { _keyMap[Common::KEYCODE_p] = false; _keyMap[Common::KEYCODE_TILDE] = false; _keyMap[Common::KEYCODE_BACKQUOTE] = false; - _keyMap[Common::KEYCODE_NUMLOCK] = false; + _keyMap[Common::KEYCODE_KP7] = false; _keyMap[Common::KEYCODE_BACKSPACE] = false; _keyMap[Common::KEYCODE_KP_MULTIPLY] = false; + _keyMap[Common::KEYCODE_KP9] = false; _keyMap[Common::KEYCODE_LALT] = false; _keyMap[Common::KEYCODE_RALT] = false; _keyMap[Common::KEYCODE_e] = false; @@ -81,9 +82,7 @@ void InputDeviceManager::getInput(Input &input, const InputBits filter) { // (ie. if one uses enter to access the restore menu, we never receive // the key up event, which leads to bad things) // This is to closely emulate what the GetKeys() function did on Mac OS - Common::Event event; - while (g_system->getEventManager()->pollEvent(event)) - ; + pumpEvents(); // Now create the bitfield InputBits currentBits = 0; @@ -115,10 +114,19 @@ void InputDeviceManager::getInput(Input &input, const InputBits filter) { if (_keyMap[Common::KEYCODE_ESCAPE] || _keyMap[Common::KEYCODE_p]) currentBits |= (kRawButtonDown << kMod3ButtonShift); - if (_keyMap[Common::KEYCODE_TILDE] || _keyMap[Common::KEYCODE_BACKQUOTE] || _keyMap[Common::KEYCODE_NUMLOCK]) + // The original also used clear (aka "num lock" on Mac keyboards) here, but it doesn't + // work right on most systems. Either SDL or the OS treats num lock specially and the + // events don't come as expected. In many cases, the key down event is sent many times + // causing the drawer to open and close constantly until pressed again. It only causes + // more grief than anything else. + + // The original doesn't use KP7 for inventory, but we're using it as an alternative for + // num lock. KP9 is used for the biochip drawer to balance things out. + + if (_keyMap[Common::KEYCODE_TILDE] || _keyMap[Common::KEYCODE_BACKQUOTE] || _keyMap[Common::KEYCODE_KP7]) currentBits |= (kRawButtonDown << kLeftFireButtonShift); - if (_keyMap[Common::KEYCODE_BACKSPACE] || _keyMap[Common::KEYCODE_KP_MULTIPLY]) + if (_keyMap[Common::KEYCODE_BACKSPACE] || _keyMap[Common::KEYCODE_KP_MULTIPLY] || _keyMap[Common::KEYCODE_KP9]) currentBits |= (kRawButtonDown << kRightFireButtonShift); // Update mouse button state @@ -206,6 +214,13 @@ bool InputDeviceManager::notifyEvent(const Common::Event &event) { return false; } +void InputDeviceManager::pumpEvents() { + // Just poll for events. notifyEvent() will pick up on them. + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) + ; +} + int operator==(const Input &arg1, const Input &arg2) { return arg1._inputState == arg2._inputState; } diff --git a/engines/pegasus/input.h b/engines/pegasus/input.h index 3e938fa42a..ba6f11dba0 100644 --- a/engines/pegasus/input.h +++ b/engines/pegasus/input.h @@ -50,6 +50,8 @@ public: void waitInput(const InputBits); + void pumpEvents(); + protected: friend class Common::Singleton<SingletonBaseType>; diff --git a/engines/pegasus/interface.cpp b/engines/pegasus/interface.cpp index f2429bf36a..f8ae6a0752 100644 --- a/engines/pegasus/interface.cpp +++ b/engines/pegasus/interface.cpp @@ -604,6 +604,7 @@ void Interface::raiseInventoryDrawerSync() { raiseInventoryDrawer(false); while (_inventoryLid.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -613,6 +614,7 @@ void Interface::raiseInventoryDrawerSync() { inventoryLidOpen(false); while (_inventoryPush.isFading()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -628,6 +630,7 @@ void Interface::lowerInventoryDrawerSync() { lowerInventoryDrawer(false); while (_inventoryPush.isFading()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -637,6 +640,7 @@ void Interface::lowerInventoryDrawerSync() { inventoryDrawerDown(false); while (_inventoryLid.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -652,6 +656,7 @@ void Interface::raiseBiochipDrawerSync() { raiseBiochipDrawer(false); while (_biochipLid.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -661,6 +666,7 @@ void Interface::raiseBiochipDrawerSync() { biochipLidOpen(false); while (_biochipPush.isFading()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -676,6 +682,7 @@ void Interface::lowerBiochipDrawerSync() { lowerBiochipDrawer(false); while (_biochipPush.isFading()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -685,6 +692,7 @@ void Interface::lowerBiochipDrawerSync() { biochipDrawerDown(false); while (_biochipLid.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); diff --git a/engines/pegasus/items/inventorypicture.cpp b/engines/pegasus/items/inventorypicture.cpp index fc812faae2..bfdc382f5d 100644 --- a/engines/pegasus/items/inventorypicture.cpp +++ b/engines/pegasus/items/inventorypicture.cpp @@ -331,6 +331,7 @@ void InventoryItemsPicture::playEndMessage(DisplayElement *pushElement) { endMessage.start(); while (endMessage.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); diff --git a/engines/pegasus/items/item.cpp b/engines/pegasus/items/item.cpp index 8089f2b93d..830d3f2f34 100644 --- a/engines/pegasus/items/item.cpp +++ b/engines/pegasus/items/item.cpp @@ -39,9 +39,9 @@ namespace Pegasus { Item::Item(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) : IDObject(id) { - _itemNeighborhood = neighborhood; - _itemRoom = room; - _itemDirection = direction; + _originalNeighborhood = _itemNeighborhood = neighborhood; + _originalRoom = _itemRoom = room; + _originalDirection = _itemDirection = direction; _itemWeight = 1; _itemOwnerID = kNoActorID; _itemState = 0; @@ -131,6 +131,14 @@ Item::~Item() { delete[] _itemExtras.entries; } +void Item::reset() { + _itemNeighborhood = _originalNeighborhood; + _itemRoom = _originalRoom; + _itemDirection = _originalDirection; + _itemOwnerID = kNoActorID; + _itemState = 0; +} + void Item::writeToStream(Common::WriteStream *stream) { stream->writeUint16BE(_itemNeighborhood); stream->writeUint16BE(_itemRoom); diff --git a/engines/pegasus/items/item.h b/engines/pegasus/items/item.h index a1451b2a58..26cccf043c 100644 --- a/engines/pegasus/items/item.h +++ b/engines/pegasus/items/item.h @@ -339,6 +339,9 @@ public: void findItemExtra(const uint32 extraID, ItemExtraEntry &entry); + // Reset to its original state at the beginning of the game + void reset(); + protected: NeighborhoodID _itemNeighborhood; RoomID _itemRoom; @@ -347,6 +350,10 @@ protected: WeightType _itemWeight; ItemState _itemState; + NeighborhoodID _originalNeighborhood; + RoomID _originalRoom; + DirectionConstant _originalDirection; + JMPItemInfo _itemInfo; ItemStateInfo _sharedAreaInfo; ItemExtraInfo _itemExtras; diff --git a/engines/pegasus/items/itemlist.cpp b/engines/pegasus/items/itemlist.cpp index ff8cae546b..4b58d9ad78 100644 --- a/engines/pegasus/items/itemlist.cpp +++ b/engines/pegasus/items/itemlist.cpp @@ -64,4 +64,9 @@ Item *ItemList::findItemByID(const ItemID id) { return 0; } +void ItemList::resetAllItems() { + for (ItemIterator it = begin(); it != end(); it++) + (*it)->reset(); +} + } // End of namespace Pegasus diff --git a/engines/pegasus/items/itemlist.h b/engines/pegasus/items/itemlist.h index 9b59206ab3..22bef2c96e 100644 --- a/engines/pegasus/items/itemlist.h +++ b/engines/pegasus/items/itemlist.h @@ -48,6 +48,7 @@ public: virtual void readFromStream(Common::ReadStream *stream); Item *findItemByID(const ItemID id); + void resetAllItems(); }; typedef ItemList::iterator ItemIterator; diff --git a/engines/pegasus/menu.cpp b/engines/pegasus/menu.cpp index e55c006f86..4bbda8fd93 100644 --- a/engines/pegasus/menu.cpp +++ b/engines/pegasus/menu.cpp @@ -227,6 +227,7 @@ MainMenu::MainMenu() : GameMenu(kMainMenuID), _menuBackground(0), _overviewButto _menuLoop.attachFader(&_menuFader); _menuLoop.initFromAIFFFile("Sounds/Main Menu.aiff"); + _menuFader.setMasterVolume(((PegasusEngine *)g_engine)->getAmbienceLevel()); updateDisplay(); } @@ -736,6 +737,7 @@ DeathMenu::DeathMenu(const DeathReason deathReason) : GameMenu(kDeathMenuID), _d _largeSelect.startDisplaying(); } else { _triumphSound.initFromQuickTime("Sounds/Caldoria/Galactic Triumph"); + _triumphSound.setVolume(((PegasusEngine *)g_engine)->getAmbienceLevel()); _triumphSound.playSound(); } diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.cpp b/engines/pegasus/neighborhood/caldoria/caldoria.cpp index 0b3e1ee040..9d2d6723a9 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoria.cpp +++ b/engines/pegasus/neighborhood/caldoria/caldoria.cpp @@ -196,6 +196,8 @@ void Caldoria::start() { if (!pullbackMovie->loadFile("Images/Caldoria/Pullback.movie")) error("Could not load pullback movie"); + pullbackMovie->setVolume(MIN<uint>(_vm->getSoundFXLevel(), 0xFF)); + // Draw the first frame so we can fade to it const Graphics::Surface *frame = pullbackMovie->decodeNextFrame(); assert(frame); @@ -386,54 +388,72 @@ void Caldoria::startSpotOnceOnly(TimeValue startTime, TimeValue stopTime) { if (!_privateFlags.getFlag(kCaldoriaPrivateSeen13CarFlag) && _vm->getRandomBit() == 0) { _privateFlags.setFlag(kCaldoriaPrivateSeen13CarFlag, true); Neighborhood::startSpotOnceOnly(startTime, stopTime); + } else { + showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection())); } break; case MakeRoomView(kCaldoria14, kEast): if (!_privateFlags.getFlag(kCaldoriaPrivateSeen14CarFlag) && _vm->getRandomBit() == 0) { _privateFlags.setFlag(kCaldoriaPrivateSeen14CarFlag, true); Neighborhood::startSpotOnceOnly(startTime, stopTime); + } else { + showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection())); } break; case MakeRoomView(kCaldoria18, kWest): if (!_privateFlags.getFlag(kCaldoriaPrivateSeen18CarFlag) && _vm->getRandomBit() == 0) { _privateFlags.setFlag(kCaldoriaPrivateSeen18CarFlag, true); Neighborhood::startSpotOnceOnly(startTime, stopTime); + } else { + showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection())); } break; case MakeRoomView(kCaldoria23, kSouth): if (!_privateFlags.getFlag(kCaldoriaPrivateSeen23CarFlag) && _vm->getRandomBit() == 0) { _privateFlags.setFlag(kCaldoriaPrivateSeen23CarFlag, true); Neighborhood::startSpotOnceOnly(startTime, stopTime); + } else { + showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection())); } break; case MakeRoomView(kCaldoria33, kSouth): if (!_privateFlags.getFlag(kCaldoriaPrivateSeen33CarFlag) && _vm->getRandomBit() == 0) { _privateFlags.setFlag(kCaldoriaPrivateSeen33CarFlag, true); Neighborhood::startSpotOnceOnly(startTime, stopTime); + } else { + showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection())); } break; case MakeRoomView(kCaldoria36, kNorth): if (!_privateFlags.getFlag(kCaldoriaPrivateSeen36CarFlag) && _vm->getRandomBit() == 0) { _privateFlags.setFlag(kCaldoriaPrivateSeen36CarFlag, true); Neighborhood::startSpotOnceOnly(startTime, stopTime); + } else { + showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection())); } break; case MakeRoomView(kCaldoria41, kNorth): if (!_privateFlags.getFlag(kCaldoriaPrivateSeen41NorthCarFlag) && _vm->getRandomBit() == 0) { _privateFlags.setFlag(kCaldoriaPrivateSeen41NorthCarFlag, true); Neighborhood::startSpotOnceOnly(startTime, stopTime); + } else { + showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection())); } break; case MakeRoomView(kCaldoria41, kEast): if (!_privateFlags.getFlag(kCaldoriaPrivateSeen41EastCarFlag) && _vm->getRandomBit() == 0) { _privateFlags.setFlag(kCaldoriaPrivateSeen41EastCarFlag, true); Neighborhood::startSpotOnceOnly(startTime, stopTime); + } else { + showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection())); } break; case MakeRoomView(kCaldoria41, kWest): if (!_privateFlags.getFlag(kCaldoriaPrivateSeen41WestCarFlag) && _vm->getRandomBit() == 0) { _privateFlags.setFlag(kCaldoriaPrivateSeen41WestCarFlag, true); Neighborhood::startSpotOnceOnly(startTime, stopTime); + } else { + showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection())); } break; default: @@ -889,7 +909,7 @@ void Caldoria::arriveAtCaldoria49() { setCurrentAlternate(kAltCaldoriaNormal); // Need to force the loop to play. - if (GameState.getCurrentDirection() == kNorth) { + if (GameState.getCurrentDirection() == kNorth && !GameState.getCaldoriaSinclairShot()) { GameState.setCaldoriaFuseTimeLimit(kSinclairShootsTimeLimit); startExtraSequence(kCa49NorthVoiceAnalysis, kExtraCompletedFlag, kFilterNoInput); } @@ -1898,10 +1918,13 @@ uint Caldoria::getNumHints() { numHints = 1; } break; +#if 0 + // The hint file is missing case MakeRoomView(kCaldoria49, kEast): case MakeRoomView(kCaldoria54, kEast): numHints = 1; break; +#endif case MakeRoomView(kCaldoria49, kNorth): numHints = 1; break; @@ -1932,9 +1955,12 @@ Common::String Caldoria::getHintMovie(uint hintNum) { } return "Images/AI/Globals/XGLOB1A"; +#if 0 + // The hint file is missing case MakeRoomView(kCaldoria49, kEast): case MakeRoomView(kCaldoria54, kEast): return "Images/AI/Caldoria/X49E"; +#endif case MakeRoomView(kCaldoria49, kNorth): return "Images/AI/Caldoria/X49NB2"; } diff --git a/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp b/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp index abf34d3863..c964e3458b 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp +++ b/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp @@ -1167,6 +1167,18 @@ CaldoriaBomb::~CaldoriaBomb() { delete[] _bombLevel[i]; } +void CaldoriaBomb::setSoundFXLevel(const uint16) { + // The transition sounds between levels are ambience, so overwrite what + // Neighborhood::setSoundFXLevel does and keep using the ambience volume level + if (_timer.isRunning()) + _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getAmbienceLevel()); +} + +void CaldoriaBomb::setAmbienceLevel(const uint16 level) { + if (_timer.isRunning()) + _owner->_navMovie.setVolume(level); +} + void CaldoriaBomb::openInteraction() { _grid.moveElementTo(kCaldoriaBombGridLeft, kCaldoriaBombGridTop); _grid.setDisplayOrder(kCaldoriaBombGridOrder); @@ -1234,6 +1246,7 @@ void CaldoriaBomb::receiveNotification(Notification *notification, const Notific _timer.start(); _currentLevel = 0; _lastVertex = -1; + _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getAmbienceLevel()); startBombAmbient("Sounds/Caldoria/BmbLoop1.22K.AIFF"); break; case kCaldoria56BombStage2: @@ -1258,6 +1271,7 @@ void CaldoriaBomb::receiveNotification(Notification *notification, const Notific _grid.hide(); _timer.stop(); _timer.hide(); + _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel()); _owner->loadLoopSound1(""); _owner->playDeathExtra(kCaldoria56BombExplodes, kDeathNuclearExplosion); } @@ -1411,6 +1425,7 @@ void CaldoriaBomb::handleInput(const Input &input, const Hotspot *hotspot) { _timer.stop(); _grid.hide(); _timer.hide(); + _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel()); _owner->startExtraSequence(kCaldoria56BombStage7, kExtraCompletedFlag, kFilterNoInput); break; } diff --git a/engines/pegasus/neighborhood/caldoria/caldoriabomb.h b/engines/pegasus/neighborhood/caldoria/caldoriabomb.h index 5bb39b4122..ba6d1e8998 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoriabomb.h +++ b/engines/pegasus/neighborhood/caldoria/caldoriabomb.h @@ -122,6 +122,9 @@ public: CaldoriaBomb(Neighborhood *, NotificationManager *); virtual ~CaldoriaBomb(); + void setSoundFXLevel(const uint16); + void setAmbienceLevel(const uint16); + long getNumHints(); Common::String getHintMovie(uint); void doSolve(); diff --git a/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp b/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp index a3ce97d438..2ae990d775 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp +++ b/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp @@ -24,6 +24,7 @@ */ #include "pegasus/gamestate.h" +#include "pegasus/pegasus.h" #include "pegasus/neighborhood/neighborhood.h" #include "pegasus/neighborhood/caldoria/caldoria.h" #include "pegasus/neighborhood/caldoria/caldoriamessages.h" @@ -45,6 +46,10 @@ void CaldoriaMessages::openInteraction() { _messageNumber = 1; } +void CaldoriaMessages::setSoundFXLevel(const uint16 fxLevel) { + _messageMovie.setVolume(fxLevel); +} + void CaldoriaMessages::initInteraction() { GameInteraction::_owner->startExtraSequence(kCaBedroomVidPhone, kExtraCompletedFlag, kFilterNoInput); } @@ -101,6 +106,7 @@ void CaldoriaMessages::play1Message(uint messageNumber) { GameState.setCaldoriaSeenMessages(true); } + _messageMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel()); _messageMovie.moveElementTo(kCaldoriaMessageLeft, kCaldoriaMessageTop); _messageMovie.setDisplayOrder(kCaldoriaMessagesOrder); _messageMovie.startDisplaying(); diff --git a/engines/pegasus/neighborhood/caldoria/caldoriamessages.h b/engines/pegasus/neighborhood/caldoria/caldoriamessages.h index 955fe10ce9..b2fc7c3bf9 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoriamessages.h +++ b/engines/pegasus/neighborhood/caldoria/caldoriamessages.h @@ -41,6 +41,8 @@ public: CaldoriaMessages(Neighborhood *, const NotificationID, NotificationManager *); virtual ~CaldoriaMessages() {} + void setSoundFXLevel(const uint16); + protected: void openInteraction(); void initInteraction(); diff --git a/engines/pegasus/neighborhood/mars/mars.cpp b/engines/pegasus/neighborhood/mars/mars.cpp index 775221589a..df5a75541c 100644 --- a/engines/pegasus/neighborhood/mars/mars.cpp +++ b/engines/pegasus/neighborhood/mars/mars.cpp @@ -535,6 +535,10 @@ void Mars::doorOpened() { } void Mars::setUpReactorEnergyDrain() { + // If there's no energy monitor, there's nothing to do + if (!g_energyMonitor) + return; + switch (GameState.getCurrentRoomAndView()) { case MakeRoomView(kMars51, kEast): if (GameState.isCurrentDoorOpen()) { @@ -2011,7 +2015,7 @@ void Mars::dropItemIntoRoom(Item *item, Hotspot *dropSpot) { void Mars::robotTiredOfWaiting() { if (GameState.getCurrentRoomAndView() == MakeRoomView(kMars48, kEast)) { - if (_attackingItem) { + if (!_attackingItem) { startExtraSequence(kMars48RobotKillsPlayer, kExtraCompletedFlag, kFilterNoInput); loadLoopSound2(""); } else { @@ -2398,6 +2402,8 @@ void Mars::doCanyonChase() { if (!video->loadFile("Images/Mars/M44ESA.movie")) error("Could not load interface->shuttle transition video"); + video->setVolume(MIN<uint>(_vm->getSoundFXLevel(), 0xFF)); + video->start(); while (!_vm->shouldQuit() && !video->endOfVideo()) { @@ -2476,6 +2482,7 @@ void Mars::doCanyonChase() { _shuttleEnergyMeter.initShuttleEnergyMeter(); _shuttleEnergyMeter.powerUpMeter(); while (_shuttleEnergyMeter.isFading()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); g_system->updateScreen(); @@ -2607,6 +2614,7 @@ void Mars::startUpFromFinishedSpaceChase() { kShuttleJunkTop, false); initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false); + _explosions.setVolume(_vm->getSoundFXLevel()); _explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes); _energyBeam.initShuttleWeapon(); @@ -2645,6 +2653,7 @@ void Mars::startUpFromFinishedSpaceChase() { initOneMovie(&_canyonChaseMovie, "Images/Mars/M98EAS.movie", kShuttleTractorBeamMovieOrder, kShuttleWindowLeft, kShuttleWindowTop, true); + _canyonChaseMovie.setVolume(_vm->getSoundFXLevel()); _canyonChaseMovie.setTime(_canyonChaseMovie.getDuration()); _canyonChaseMovie.redrawMovieWorld(); } @@ -2720,6 +2729,7 @@ void Mars::startUpFromSpaceChase() { kShuttleJunkTop, false); initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false); + _explosions.setVolume(_vm->getSoundFXLevel()); _explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes); _energyBeam.initShuttleWeapon(); @@ -2783,6 +2793,10 @@ void Mars::startUpFromSpaceChase() { void Mars::setSoundFXLevel(const uint16 level) { Neighborhood::setSoundFXLevel(level); + if (GameState.getCurrentRoomAndView() == MakeRoomView(kMars48, kEast) && + !GameState.getMarsAvoidedReactorRobot()) + _loop2Fader.setMasterVolume(level); + if (_canyonChaseMovie.isMovieValid()) _canyonChaseMovie.setVolume(level); @@ -2812,6 +2826,7 @@ void Mars::marsTimerExpired(MarsTimerEvent &event) { GameState.setScoringEnteredLaunchTube(); while (_canyonChaseMovie.isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -2836,6 +2851,7 @@ void Mars::marsTimerExpired(MarsTimerEvent &event) { initOneMovie(&_junk, "Images/Mars/Junk.movie", kShuttleJunkOrder, kShuttleJunkLeft, kShuttleJunkTop, false); initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false); + _explosions.setVolume(_vm->getSoundFXLevel()); _explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes); _energyBeam.initShuttleWeapon(); @@ -2945,6 +2961,7 @@ void Mars::marsTimerExpired(MarsTimerEvent &event) { showBigExplosion(r, kShuttleAlienShipOrder); while (_explosions.isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); g_system->delayMillis(10); @@ -3138,6 +3155,7 @@ void Mars::spaceChaseClick(const Input &input, const HotSpotID id) { _shuttleEnergyMeter.drainForTractorBeam(); while (_shuttleEnergyMeter.isFading()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -3167,11 +3185,13 @@ void Mars::spaceChaseClick(const Input &input, const HotSpotID id) { // Shameless reuse of a variable :P initOneMovie(&_canyonChaseMovie, "Images/Mars/M98EAS.movie", kShuttleTractorBeamMovieOrder, kShuttleWindowLeft, kShuttleWindowTop, true); + _canyonChaseMovie.setVolume(_vm->getSoundFXLevel()); _canyonChaseMovie.redrawMovieWorld(); playMovieSegment(&_canyonChaseMovie, 0, _canyonChaseMovie.getDuration()); // wait here until any junk clears... while (_junk.junkFlying()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); diff --git a/engines/pegasus/neighborhood/neighborhood.cpp b/engines/pegasus/neighborhood/neighborhood.cpp index 3116bd7978..c9be349694 100644 --- a/engines/pegasus/neighborhood/neighborhood.cpp +++ b/engines/pegasus/neighborhood/neighborhood.cpp @@ -470,6 +470,7 @@ void Neighborhood::requestSpotSound(const TimeValue in, const TimeValue out, con void Neighborhood::playSpotSoundSync(const TimeValue in, const TimeValue out) { // Let the action queue play out first... while (!actionQueueEmpty()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->checkNotifications(); @@ -480,6 +481,7 @@ void Neighborhood::playSpotSoundSync(const TimeValue in, const TimeValue out) { _spotSounds.playSoundSegment(in, out); while (_spotSounds.isPlaying()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -1105,6 +1107,7 @@ void Neighborhood::startTurnPush(const TurnDirection turnDirection, const TimeVa _turnPush.continueFader(); do { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -1492,7 +1495,15 @@ void Neighborhood::loadLoopSound2(const Common::String &soundName, uint16 volume if (!_loop2SoundString.empty()) { _soundLoop2.initFromAIFFFile(_loop2SoundString); _soundLoop2.loopSound(); - _loop2Fader.setMasterVolume(_vm->getAmbienceLevel()); + // HACK: Some ambient loops are actually sound effects, like Ares waiting at + // the reactor and Poseidon at the launch console. Detect these and use the + // SFX volume instead of ambience. + if (soundName == "Sounds/Mars/Robot Loop.aiff" || + soundName == "Sounds/Norad/Breathing Typing.22K.AIFF" || + soundName == "Sounds/Norad/N54NAS.32K.AIFF") + _loop2Fader.setMasterVolume(_vm->getSoundFXLevel()); + else + _loop2Fader.setMasterVolume(_vm->getAmbienceLevel()); _loop2Fader.setFaderValue(0); faderMove.makeTwoKnotFaderSpec(fadeScale, 0, 0, fadeIn, volume); _loop2Fader.startFaderSync(faderMove); @@ -1577,6 +1588,7 @@ void Neighborhood::closeCroppedMovie() { void Neighborhood::playCroppedMovieOnce(const Common::String &movieName, CoordType left, CoordType top, const InputBits interruptionFilter) { openCroppedMovie(movieName, left, top); + _croppedMovie.setVolume(_vm->getSoundFXLevel()); _croppedMovie.redrawMovieWorld(); _croppedMovie.start(); @@ -1616,6 +1628,7 @@ void Neighborhood::playMovieSegment(Movie *movie, TimeValue startTime, TimeValue movie->start(); while (movie->isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); diff --git a/engines/pegasus/neighborhood/neighborhood.h b/engines/pegasus/neighborhood/neighborhood.h index 3c1c5eac92..f7f2b038c6 100644 --- a/engines/pegasus/neighborhood/neighborhood.h +++ b/engines/pegasus/neighborhood/neighborhood.h @@ -91,6 +91,7 @@ struct QueueRequest { bool operator==(const QueueRequest &arg1, const QueueRequest &arg2); bool operator!=(const QueueRequest &arg1, const QueueRequest &arg2); +class CaldoriaBomb; class GameInteraction; class Item; class Neighborhood; @@ -109,6 +110,7 @@ protected: typedef Common::Queue<QueueRequest> NeighborhoodActionQueue; class Neighborhood : public IDObject, public NotificationReceiver, public InputHandler, public Idler { +friend class CaldoriaBomb; friend class StriderCallBack; public: diff --git a/engines/pegasus/neighborhood/norad/delta/globegame.cpp b/engines/pegasus/neighborhood/norad/delta/globegame.cpp index 0b95e9bc2b..5c321a8e8a 100644 --- a/engines/pegasus/neighborhood/norad/delta/globegame.cpp +++ b/engines/pegasus/neighborhood/norad/delta/globegame.cpp @@ -453,8 +453,13 @@ GlobeGame::GlobeGame(Neighborhood *handler) : GameInteraction(kNoradGlobeGameInt _neighborhoodNotification = handler->getNeighborhoodNotification(); } +void GlobeGame::setSoundFXLevel(const uint16 fxLevel) { + _monitorMovie.setVolume(fxLevel); +} + void GlobeGame::openInteraction() { _monitorMovie.initFromMovieFile("Images/Norad Delta/N79 Left Monitor"); + _monitorMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel()); _monitorMovie.moveElementTo(kGlobeMonitorLeft, kGlobeMonitorTop); _monitorMovie.setDisplayOrder(kGlobeMonitorLayer); _monitorMovie.startDisplaying(); diff --git a/engines/pegasus/neighborhood/norad/delta/globegame.h b/engines/pegasus/neighborhood/norad/delta/globegame.h index 73ed48866f..93235a1784 100644 --- a/engines/pegasus/neighborhood/norad/delta/globegame.h +++ b/engines/pegasus/neighborhood/norad/delta/globegame.h @@ -98,6 +98,8 @@ public: GlobeGame(Neighborhood *); virtual ~GlobeGame() {} + void setSoundFXLevel(const uint16); + void handleInput(const Input &, const Hotspot *); void clickInHotspot(const Input &, const Hotspot *); void activateHotspots(); diff --git a/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp index 1eea2f0156..ee047d72b2 100644 --- a/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp +++ b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp @@ -514,6 +514,17 @@ void NoradDelta::openDoor() { } } +void NoradDelta::cantMoveThatWay(CanOpenDoorReason reason) { + // WORKAROUND: The door outside the launch console room isn't treated as a door, + // so play the correct sound. + if (reason == kCantMoveBlocked && GameState.getCurrentRoomAndView() == MakeRoomView(kNorad67, kNorth)) { + cantOpenDoor(kCantOpenLocked); + return; + } + + Neighborhood::cantMoveThatWay(reason); +} + void NoradDelta::activateHotspots() { Norad::activateHotspots(); @@ -863,6 +874,13 @@ void NoradDelta::doSolve() { } } +void NoradDelta::setSoundFXLevel(const uint16 level) { + Neighborhood::setSoundFXLevel(level); + + if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad54North, kNorth)) + _loop2Fader.setMasterVolume(level); +} + Common::String NoradDelta::getSoundSpotsName() { return "Sounds/Norad/Norad Delta Spots"; } diff --git a/engines/pegasus/neighborhood/norad/delta/noraddelta.h b/engines/pegasus/neighborhood/norad/delta/noraddelta.h index 11065f2c9d..591fd691a2 100644 --- a/engines/pegasus/neighborhood/norad/delta/noraddelta.h +++ b/engines/pegasus/neighborhood/norad/delta/noraddelta.h @@ -68,6 +68,8 @@ public: bool canSolve(); void doSolve(); + void setSoundFXLevel(const uint16); + void doorOpened(); protected: @@ -90,6 +92,7 @@ protected: void arriveAtNorad79West(); TimeValue getViewTime(const RoomID, const DirectionConstant); void openDoor(); + void cantMoveThatWay(CanMoveForwardReason); void activateHotspots(); void clickInHotspot(const Input &, const Hotspot *); void receiveNotification(Notification *, const NotificationFlags); diff --git a/engines/pegasus/neighborhood/prehistoric/prehistoric.cpp b/engines/pegasus/neighborhood/prehistoric/prehistoric.cpp index d62b069e46..190984f8bc 100644 --- a/engines/pegasus/neighborhood/prehistoric/prehistoric.cpp +++ b/engines/pegasus/neighborhood/prehistoric/prehistoric.cpp @@ -124,11 +124,6 @@ void Prehistoric::setUpAIRules() { AIHasItemCondition *hasLogCondition = new AIHasItemCondition(kHistoricalLog); AIRule *rule = new AIRule(hasLogCondition, doneAction); g_AIArea->addAIRule(rule); - } else { - AIPlayMessageAction *messageAction = new AIPlayMessageAction("Images/AI/Prehistoric/XP25W", false); - AIHasItemCondition *hasLogCondition = new AIHasItemCondition(kHistoricalLog); - AIRule *rule = new AIRule(hasLogCondition, messageAction); - g_AIArea->addAIRule(rule); } if (!_vm->isOldDemo()) { @@ -167,6 +162,13 @@ void Prehistoric::setUpAIRules() { rule = new AIRule(timerCondition, messageAction); g_AIArea->addAIRule(rule); } + + if (!_vm->isDemo()) { + AIPlayMessageAction *messageAction = new AIPlayMessageAction("Images/AI/Prehistoric/XP25W", false); + AIHasItemCondition *hasLogCondition = new AIHasItemCondition(kHistoricalLog); + AIRule *rule = new AIRule(hasLogCondition, messageAction); + g_AIArea->addAIRule(rule); + } } } @@ -202,11 +204,11 @@ TimeValue Prehistoric::getViewTime(const RoomID room, const DirectionConstant di void Prehistoric::findSpotEntry(const RoomID room, const DirectionConstant direction, SpotFlags flags, SpotTable::Entry &entry) { Neighborhood::findSpotEntry(room, direction, flags, entry); + // The original strangely disabled the loop for the two volcano spots: + // (kPrehistoric01, kSouth) and (kPrehistoric25, kSouth) + // We don't do that here. + switch (MakeRoomView(room, direction)) { - case MakeRoomView(kPrehistoric01, kSouth): - case MakeRoomView(kPrehistoric25, kSouth): - entry.clear(); - break; case MakeRoomView(kPrehistoric01, kEast): if (GameState.getPrehistoricSeenFlyer1()) entry.clear(); diff --git a/engines/pegasus/neighborhood/tsa/fulltsa.cpp b/engines/pegasus/neighborhood/tsa/fulltsa.cpp index 99efe10272..92b79c038e 100644 --- a/engines/pegasus/neighborhood/tsa/fulltsa.cpp +++ b/engines/pegasus/neighborhood/tsa/fulltsa.cpp @@ -1692,7 +1692,9 @@ void FullTSA::initializeTBPMonitor(const int newMode, const ExtraID highlightExt releaseSprites(); } - _interruptionFilter = kFilterAllInput; + // Only allow input if we're not in the middle of series of queue requests. + if (actionQueueEmpty()) + _interruptionFilter = kFilterAllInput; } void FullTSA::startUpComparisonMonitor() { @@ -2643,6 +2645,7 @@ void FullTSA::receiveNotification(Notification *notification, const Notification GameState.setMarsReadyForShuttleTransport(false); GameState.setMarsFinishedCanyonChase(false); GameState.setMarsThreadedMaze(false); + GameState.setMarsSawRobotLeave(false); break; case kPlayerOnWayToWSC: _vm->jumpToNewEnvironment(kWSCID, kWSC01, kWest); @@ -2691,16 +2694,18 @@ void FullTSA::receiveNotification(Notification *notification, const Notification } break; case kTSA37DownloadToOpMemReview: - switch (GameState.getTSAState()) { - case kPlayerOnWayToNorad: - g_opticalChip->playOpMemMovie(kPoseidonSpotID); - break; - case kPlayerOnWayToMars: - g_opticalChip->playOpMemMovie(kAriesSpotID); - break; - case kPlayerOnWayToWSC: - g_opticalChip->playOpMemMovie(kMercurySpotID); - break; + if (_vm->itemInBiochips(kOpticalBiochip)) { + switch (GameState.getTSAState()) { + case kPlayerOnWayToNorad: + g_opticalChip->playOpMemMovie(kPoseidonSpotID); + break; + case kPlayerOnWayToMars: + g_opticalChip->playOpMemMovie(kAriesSpotID); + break; + case kPlayerOnWayToWSC: + g_opticalChip->playOpMemMovie(kMercurySpotID); + break; + } } if (GameState.allTimeZonesFinished()) { diff --git a/engines/pegasus/neighborhood/tsa/tinytsa.cpp b/engines/pegasus/neighborhood/tsa/tinytsa.cpp index 0d11f5d904..c808325b0f 100644 --- a/engines/pegasus/neighborhood/tsa/tinytsa.cpp +++ b/engines/pegasus/neighborhood/tsa/tinytsa.cpp @@ -327,6 +327,7 @@ void TinyTSA::receiveNotification(Notification *notification, const Notification GameState.setMarsReadyForShuttleTransport(false); GameState.setMarsFinishedCanyonChase(false); GameState.setMarsThreadedMaze(false); + GameState.setMarsSawRobotLeave(false); break; case kPlayerOnWayToWSC: _vm->jumpToNewEnvironment(kWSCID, kWSC01, kWest); @@ -372,16 +373,18 @@ void TinyTSA::receiveNotification(Notification *notification, const Notification } break; case kTinyTSA37DownloadToOpMemReview: - switch (GameState.getTSAState()) { - case kPlayerOnWayToNorad: - g_opticalChip->playOpMemMovie(kPoseidonSpotID); - break; - case kPlayerOnWayToMars: - g_opticalChip->playOpMemMovie(kAriesSpotID); - break; - case kPlayerOnWayToWSC: - g_opticalChip->playOpMemMovie(kMercurySpotID); - break; + if (_vm->itemInBiochips(kOpticalBiochip)) { + switch (GameState.getTSAState()) { + case kPlayerOnWayToNorad: + g_opticalChip->playOpMemMovie(kPoseidonSpotID); + break; + case kPlayerOnWayToMars: + g_opticalChip->playOpMemMovie(kAriesSpotID); + break; + case kPlayerOnWayToWSC: + g_opticalChip->playOpMemMovie(kMercurySpotID); + break; + } } requestExtraSequence(kTinyTSA37OpMemReviewToMainMenu, kExtraCompletedFlag, kFilterNoInput); diff --git a/engines/pegasus/neighborhood/wsc/wsc.cpp b/engines/pegasus/neighborhood/wsc/wsc.cpp index 09e2a48a52..f009b35cdc 100644 --- a/engines/pegasus/neighborhood/wsc/wsc.cpp +++ b/engines/pegasus/neighborhood/wsc/wsc.cpp @@ -2029,6 +2029,7 @@ void WSC::moleculeGameClick(const HotSpotID id) { _moleculesMovie.start(); while (_moleculesMovie.isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -2063,6 +2064,7 @@ void WSC::moleculeGameClick(const HotSpotID id) { _moleculesMovie.start(); while (_moleculesMovie.isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -2076,6 +2078,7 @@ void WSC::moleculeGameClick(const HotSpotID id) { while (_moleculesMovie.isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp index 3bd29ce8dd..0010180d8d 100644 --- a/engines/pegasus/pegasus.cpp +++ b/engines/pegasus/pegasus.cpp @@ -36,6 +36,7 @@ #include "backends/keymapper/keymapper.h" #include "base/plugins.h" #include "base/version.h" +#include "gui/message.h" #include "gui/saveload.h" #include "video/theora_decoder.h" #include "video/qt_decoder.h" @@ -306,6 +307,7 @@ void PegasusEngine::runIntro() { Video::VideoDecoder *video = new Video::QuickTimeDecoder(); if (video->loadFile(_introDirectory + "/BandaiLogo.movie")) { + video->setVolume(MIN<uint>(getAmbienceLevel(), 0xFF)); video->start(); while (!shouldQuit() && !video->endOfVideo() && !skipped) { @@ -337,6 +339,8 @@ void PegasusEngine::runIntro() { if (!video->loadFile(_introDirectory + "/Big Movie.movie")) error("Could not load intro movie"); + video->setVolume(MIN<uint>(getAmbienceLevel(), 0xFF)); + video->seek(Audio::Timestamp(0, 10 * 600, 600)); video->start(); @@ -379,20 +383,21 @@ Common::Error PegasusEngine::showSaveDialog() { int slot = slc.runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName()); - Common::Error result; + if (slot >= 0) + return saveGameState(slot, slc.getResultString()); - if (slot >= 0) { - if (saveGameState(slot, slc.getResultString()).getCode() == Common::kNoError) - result = Common::kNoError; - else - result = Common::kUnknownError; - } else { - result = Common::kUserCanceled; - } + return Common::kUserCanceled; +} - return result; +void PegasusEngine::showSaveFailedDialog(const Common::Error &status) { + Common::String failMessage = Common::String::format(_("Gamestate save failed (%s)! " + "Please consult the README for basic information, and for " + "instructions on how to obtain further assistance."), status.getDesc().c_str()); + GUI::MessageDialog dialog(failMessage); + dialog.runModal(); } + GUI::Debugger *PegasusEngine::getDebugger() { return _console; } @@ -429,8 +434,10 @@ void PegasusEngine::removeTimeBase(TimeBase *timeBase) { _timeBases.remove(timeBase); } -bool PegasusEngine::loadFromStream(Common::ReadStream *stream) { +bool PegasusEngine::loadFromStream(Common::SeekableReadStream *stream) { // Dispose currently running stuff + lowerInventoryDrawerSync(); + lowerBiochipDrawerSync(); useMenu(0); useNeighborhood(0); removeAllItemsFromInventory(); @@ -520,8 +527,36 @@ bool PegasusEngine::loadFromStream(Common::ReadStream *stream) { performJump(GameState.getCurrentNeighborhood()); // AI rules - if (g_AIArea) - g_AIArea->readAIRules(stream); + if (g_AIArea) { + // HACK: clone2727 accidentally changed some Prehistoric code to output some bad saves + // at one point. That's fixed now, but I don't want to leave the other users high + // and dry. + if (GameState.getCurrentNeighborhood() == kPrehistoricID && !isDemo()) { + uint32 pos = stream->pos(); + stream->seek(0x208); + uint32 roomView = stream->readUint32BE(); + stream->seek(pos); + + if (roomView == 0x30019) { + // This is a bad save -> Let's fix the data + // One byte should be put at the end instead + uint32 size = stream->size() - pos; + byte *data = (byte *)malloc(size); + data[0] = stream->readByte(); + data[1] = stream->readByte(); + data[2] = stream->readByte(); + byte wrongData = stream->readByte(); + stream->read(data + 3, size - 4); + data[size - 1] = wrongData; + Common::MemoryReadStream tempStream(data, size, DisposeAfterUse::YES); + g_AIArea->readAIRules(&tempStream); + } else { + g_AIArea->readAIRules(stream); + } + } else { + g_AIArea->readAIRules(stream); + } + } startNeighborhood(); @@ -762,6 +797,8 @@ void PegasusEngine::introTimerExpired() { if (!video->loadFile(_introDirectory + "/LilMovie.movie")) error("Failed to load little movie"); + video->setVolume(MIN<uint>(getAmbienceLevel(), 0xFF)); + bool saveAllowed = swapSaveAllowed(false); bool openAllowed = swapLoadAllowed(false); @@ -804,6 +841,7 @@ void PegasusEngine::delayShell(TimeValue time, TimeScale scale) { uint32 timeInMillis = time * 1000 / scale; while (g_system->getMillis() < startTime + timeInMillis) { + InputDevice.pumpEvents(); checkCallBacks(); _gfx->updateDisplay(); } @@ -908,6 +946,8 @@ void PegasusEngine::doGameMenuCommand(const GameMenuCommand command) { if (!video->loadFile(_introDirectory + "/Closing.movie")) error("Could not load closing movie"); + video->setVolume(MIN<uint>(getSoundFXLevel(), 0xFF)); + uint16 x = (640 - video->getWidth() * 2) / 2; uint16 y = (480 - video->getHeight() * 2) / 2; @@ -939,8 +979,14 @@ void PegasusEngine::doGameMenuCommand(const GameMenuCommand command) { resetIntroTimer(); break; case kMenuCmdPauseSave: - if (showSaveDialog().getCode() != Common::kUserCanceled) + result = showSaveDialog(); + + if (result.getCode() != Common::kUserCanceled) { + if (result.getCode() != Common::kNoError) + showSaveFailedDialog(result); + pauseMenu(false); + } break; case kMenuCmdPauseContinue: pauseMenu(false); @@ -991,7 +1037,12 @@ void PegasusEngine::handleInput(const Input &input, const Hotspot *cursorSpot) { // Can only save during a game and not in the demo if (g_neighborhood && !isDemo()) { pauseEngine(true); - showSaveDialog(); + + Common::Error result = showSaveDialog(); + + if (result.getCode() != Common::kNoError && result.getCode() != Common::kUserCanceled) + showSaveFailedDialog(result); + pauseEngine(false); } } @@ -1432,6 +1483,15 @@ void PegasusEngine::throwAwayEverything() { g_interface = 0; } +InputBits PegasusEngine::getInputFilter() { + InputBits filter = InputHandler::getInputFilter(); + + if (isPaused()) + return filter & ~JMPPPInput::getItemPanelsInputFilter(); + + return filter; +} + void PegasusEngine::processShell() { checkCallBacks(); checkNotifications(); @@ -1630,6 +1690,9 @@ void PegasusEngine::startNewGame() { removeAllItemsFromInventory(); removeAllItemsFromBiochips(); + // Properly reset all items to their original state + g_allItems.resetAllItems(); + BiochipItem *biochip = (BiochipItem *)_allItems.findItemByID(kAIBiochip); addItemToBiochips(biochip); @@ -2120,6 +2183,7 @@ void PegasusEngine::autoDragItemIntoRoom(Item *item, Sprite *draggingSprite) { _autoDragger.autoDrag(draggingSprite, start, stop, time, kDefaultTimeScale); while (_autoDragger.isDragging()) { + InputDevice.pumpEvents(); checkCallBacks(); refreshDisplay(); _system->delayMillis(10); @@ -2153,6 +2217,7 @@ void PegasusEngine::autoDragItemIntoInventory(Item *, Sprite *draggingSprite) { _autoDragger.autoDrag(draggingSprite, start, stop, time, kDefaultTimeScale); while (_autoDragger.isDragging()) { + InputDevice.pumpEvents(); checkCallBacks(); refreshDisplay(); _system->delayMillis(10); @@ -2229,10 +2294,7 @@ void PegasusEngine::doSubChase() { drawScaledFrame(frame, 0, 0); } - Common::Event event; - while (_eventMan->pollEvent(event)) - ; - + InputDevice.pumpEvents(); _system->delayMillis(10); } diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h index 07e6d8f761..d88545a4d1 100644 --- a/engines/pegasus/pegasus.h +++ b/engines/pegasus/pegasus.h @@ -249,7 +249,7 @@ private: Common::List<TimeBase *> _timeBases; // Save/Load - bool loadFromStream(Common::ReadStream *stream); + bool loadFromStream(Common::SeekableReadStream *stream); bool writeToStream(Common::WriteStream *stream, int saveType); void loadFromContinuePoint(); void writeContinueStream(Common::WriteStream *stream); @@ -257,6 +257,7 @@ private: bool _saveAllowed, _loadAllowed; // It's so nice that this was in the original code already :P Common::Error showLoadDialog(); Common::Error showSaveDialog(); + void showSaveFailedDialog(const Common::Error &status); bool _saveRequested, _loadRequested; // Misc. @@ -272,6 +273,7 @@ private: uint getNeighborhoodCD(const NeighborhoodID neighborhood) const; uint _currentCD; void initKeymap(); + InputBits getInputFilter(); // Menu GameMenu *_gameMenu; diff --git a/engines/pegasus/surface.cpp b/engines/pegasus/surface.cpp index cdcb3c6e79..cb1e2e7bcc 100644 --- a/engines/pegasus/surface.cpp +++ b/engines/pegasus/surface.cpp @@ -28,7 +28,7 @@ #include "common/stream.h" #include "common/system.h" #include "graphics/surface.h" -#include "graphics/decoders/pict.h" +#include "image/pict.h" #include "video/video_decoder.h" #include "pegasus/pegasus.h" @@ -101,7 +101,7 @@ void Surface::getImageFromPICTResource(Common::MacResManager *resFork, uint16 id } bool Surface::getImageFromPICTStream(Common::SeekableReadStream *stream) { - Graphics::PICTDecoder pict; + Image::PICTDecoder pict; if (!pict.loadStream(*stream)) return false; diff --git a/engines/pegasus/timers.cpp b/engines/pegasus/timers.cpp index 8463d866e8..5fb2551e7a 100644 --- a/engines/pegasus/timers.cpp +++ b/engines/pegasus/timers.cpp @@ -333,6 +333,7 @@ void TimeBaseCallBack::releaseCallBack() { void TimeBaseCallBack::disposeCallBack() { _timeBase = 0; + _trigger = kTriggerNone; _hasBeenTriggered = false; } |