diff options
author | Matthew Hoops | 2010-09-01 13:28:12 +0000 |
---|---|---|
committer | Matthew Hoops | 2010-09-01 13:28:12 +0000 |
commit | 649e275ca622b0e6b84181cb23dfc714270346d3 (patch) | |
tree | fc6a91f6bd3e430b0b802b802b0687540385645b /engines | |
parent | 43bbfa5ca8d384f601ef91f69d7d6bd6f3bba5cd (diff) | |
download | scummvm-rg350-649e275ca622b0e6b84181cb23dfc714270346d3.tar.gz scummvm-rg350-649e275ca622b0e6b84181cb23dfc714270346d3.tar.bz2 scummvm-rg350-649e275ca622b0e6b84181cb23dfc714270346d3.zip |
MOHAWK: Implement xbookclick
It is now possible to trap Gehn in the trap book. Side note: Riven is now completable from the beginning provided you know the D'ni number system already (and the marble puzzle is just hacked to always work).
svn-id: r52482
Diffstat (limited to 'engines')
-rw-r--r-- | engines/mohawk/riven_external.cpp | 140 | ||||
-rw-r--r-- | engines/mohawk/riven_external.h | 1 | ||||
-rw-r--r-- | engines/mohawk/riven_scripts.cpp | 11 | ||||
-rw-r--r-- | engines/mohawk/riven_scripts.h | 6 | ||||
-rw-r--r-- | engines/mohawk/video.cpp | 10 | ||||
-rw-r--r-- | engines/mohawk/video.h | 2 |
6 files changed, 159 insertions, 11 deletions
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 24cd23d1d4..2a2a6f4630 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -211,9 +211,26 @@ void RivenExternal::runDemoBoundaryDialog() { void RivenExternal::runEndGame(uint16 video) { _vm->_sound->stopAllSLST(); - _vm->_video->playMovieBlocking(video); + _vm->_video->playMovie(video); + runCredits(video); +} +void RivenExternal::runCredits(uint16 video) { // TODO: Play until the last frame and then run the credits + + VideoHandle videoHandle = _vm->_video->findVideoHandle(video); + + while (!_vm->_video->endOfVideo(videoHandle) && !_vm->shouldQuit()) { + if (_vm->_video->updateBackgroundMovies()) + _vm->_system->updateScreen(); + + Common::Event event; + while (_vm->_system->getEventManager()->pollEvent(event)) + ; + + _vm->_system->delayMillis(10); + } + _vm->setGameOver(); } @@ -1433,11 +1450,122 @@ void RivenExternal::xorollcredittime(uint16 argc, uint16 *argv) { } void RivenExternal::xbookclick(uint16 argc, uint16 *argv) { - // TODO: This fun external command is probably one of the most complex, - // up there with the marble puzzle ones. It involves so much... Basically, - // it's playing when Gehn holds the trap book up to you and you have to - // click on the book (hence the name of the function). Yeah, not fun. - // Lots of timing stuff needs to be done for a couple videos. + // Hide the cursor + _vm->_gfx->changeCursor(kRivenHideCursor); + + // Let's hook onto our video + VideoHandle video = _vm->_video->findVideoHandle(argv[0]); + + // Convert from the standard QuickTime base time to milliseconds + // The values are in terms of 1/600 of a second. + // Have I said how much I just *love* QuickTime? </sarcasm> + uint32 startTime = argv[1] * 1000 / 600; + uint32 endTime = argv[2] * 1000 / 600; + + // Track down our hotspot + // Of course, they're not in any sane order... + static const uint16 hotspotMap[] = { 1, 3, 2, 0 }; + Common::Rect hotspotRect = _vm->_hotspots[hotspotMap[argv[3] - 1]].rect; + + debug(0, "xbookclick:"); + debug(0, "\tVideo Code = %d", argv[0]); + debug(0, "\tStart Time = %dms", startTime); + debug(0, "\tEnd Time = %dms", endTime); + debug(0, "\tHotspot = %d -> %d", argv[3], hotspotMap[argv[3] - 1]); + + // Just let the video play while we wait until Gehn opens the trap book for us + while (_vm->_video->getElapsedTime(video) < startTime && !_vm->shouldQuit()) { + if (_vm->_video->updateBackgroundMovies()) + _vm->_system->updateScreen(); + + Common::Event event; + while (_vm->_system->getEventManager()->pollEvent(event)) + ; + + _vm->_system->delayMillis(10); + } + + // Break out if we're quitting + if (_vm->shouldQuit()) + return; + + // Update our hotspot stuff + if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos())) + _vm->_gfx->changeCursor(kRivenOpenHandCursor); + else + _vm->_gfx->changeCursor(kRivenMainCursor); + + // OK, Gehn has opened the trap book and has asked us to go in. Let's watch + // and see what the player will do... + while (_vm->_video->getElapsedTime(video) < endTime && !_vm->shouldQuit()) { + bool updateScreen = _vm->_video->updateBackgroundMovies(); + + Common::Event event; + while (_vm->_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_MOUSEMOVE: + if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos())) + _vm->_gfx->changeCursor(kRivenOpenHandCursor); + else + _vm->_gfx->changeCursor(kRivenMainCursor); + updateScreen = false; // Don't update twice, changing the cursor already updates the screen + break; + case Common::EVENT_LBUTTONUP: + if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos())) { + // OK, we've used the trap book! We go for ride lady! + _vm->_scriptMan->stopAllScripts(); // Stop all running scripts (so we don't remain in the cage) + _vm->_video->stopVideos(); // Stop all videos + _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor + _vm->_gfx->drawPLST(3); // Black out the screen + _vm->_gfx->updateScreen(); // Update the screen + _vm->_sound->playSound(0, false); // Play the link sound + _vm->_video->activateMLST(7, _vm->getCurCard()); // Activate Gehn Link Video + _vm->_video->playMovieBlocking(1); // Play Gehn Link Video + *_vm->matchVarToString("agehn") = 4; // Set Gehn to the trapped state + *_vm->matchVarToString("atrapbook") = 1; // We've got the trap book again + _vm->_sound->playSound(0, false); // Play the link sound again + _vm->changeToCard(_vm->matchRMAPToCard(0x2885)); // Link out! (TODO: Shouldn't this card change?) + return; + } + break; + default: + break; + } + } + + if (updateScreen && !_vm->shouldQuit()) + _vm->_system->updateScreen(); + + _vm->_system->delayMillis(10); + } + + // Break out if we're quitting + if (_vm->shouldQuit()) + return; + + // Hide the cursor again + _vm->_gfx->changeCursor(kRivenHideCursor); + + // If there was no click and this is the third time Gehn asks us to + // use the trap book, he will shoot the player. Dead on arrival. + // Run the credits from here. + if (*_vm->matchVarToString("agehn") == 3) { + _vm->_scriptMan->stopAllScripts(); + runCredits(argv[0]); + return; + } + + // There was no click, so just play the rest of the video. + while (!_vm->_video->endOfVideo(video) && !_vm->shouldQuit()) { + if (_vm->_video->updateBackgroundMovies()) + _vm->_system->updateScreen(); + + Common::Event event; + while (_vm->_system->getEventManager()->pollEvent(event)) + ; + + _vm->_system->delayMillis(10); + } } void RivenExternal::xooffice30_closebook(uint16 argc, uint16 *argv) { diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h index 701b16f77a..887520416e 100644 --- a/engines/mohawk/riven_external.h +++ b/engines/mohawk/riven_external.h @@ -61,6 +61,7 @@ private: int jspitElevatorLoop(); void runDemoBoundaryDialog(); void runEndGame(uint16 video); + void runCredits(uint16 video); void runDomeCheck(); void runDomeButtonMovie(); void resetDomeSliders(uint16 bitmapId, uint16 soundId, uint16 startHotspot); diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index 1fcaba8ac0..17ff0716c5 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -38,7 +38,7 @@ namespace Mohawk { RivenScript::RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard) : _vm(vm), _stream(stream), _scriptType(scriptType), _parentStack(parentStack), _parentCard(parentCard) { setupOpcodes(); - _isRunning = false; + _isRunning = _continueRunning = false; } RivenScript::~RivenScript() { @@ -227,7 +227,7 @@ void RivenScript::dumpCommands(Common::StringArray varNames, Common::StringArray } void RivenScript::runScript() { - _isRunning = true; + _isRunning = _continueRunning = true; if (_stream->pos() != 0) _stream->seek(0); @@ -242,7 +242,7 @@ void RivenScript::processCommands(bool runCommands) { uint16 commandCount = _stream->readUint16BE(); - for (uint16 j = 0; j < commandCount && !_vm->shouldQuit() && _stream->pos() < _stream->size(); j++) { + for (uint16 j = 0; j < commandCount && !_vm->shouldQuit() && _stream->pos() < _stream->size() && _continueRunning; j++) { uint16 command = _stream->readUint16BE(); if (command == 8) { @@ -632,6 +632,11 @@ RivenScriptList RivenScriptManager::readScripts(Common::SeekableReadStream *stre return scriptList; } +void RivenScriptManager::stopAllScripts() { + for (uint32 i = 0; i < _currentScripts.size(); i++) + _currentScripts[i]->stopRunning(); +} + void RivenScriptManager::unloadUnusedScripts() { // Free any scripts that aren't part of the current card and aren't running for (uint32 i = 0; i < _currentScripts.size(); i++) { diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h index 5187bbde08..a85cde1702 100644 --- a/engines/mohawk/riven_scripts.h +++ b/engines/mohawk/riven_scripts.h @@ -62,6 +62,7 @@ public: uint16 getParentStack() { return _parentStack; } uint16 getParentCard() { return _parentCard; } bool isRunning() { return _isRunning; } + void stopRunning() { _continueRunning = false; } static uint32 calculateScriptSize(Common::SeekableReadStream *script); @@ -76,8 +77,8 @@ private: MohawkEngine_Riven *_vm; Common::SeekableReadStream *_stream; - uint16 _scriptType, _parentStack, _parentCard, _parentHotspot; - bool _isRunning; + uint16 _scriptType, _parentStack, _parentCard; + bool _isRunning, _continueRunning; void dumpCommands(Common::StringArray varNames, Common::StringArray xNames, byte tabs); void processCommands(bool runCommands); @@ -131,6 +132,7 @@ public: ~RivenScriptManager(); RivenScriptList readScripts(Common::SeekableReadStream *stream, bool garbageCollect = true); + void stopAllScripts(); private: void unloadUnusedScripts(); diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp index 17456b8ec3..a266ebf518 100644 --- a/engines/mohawk/video.cpp +++ b/engines/mohawk/video.cpp @@ -412,4 +412,14 @@ uint32 VideoManager::getFrameCount(const VideoHandle &handle) { return _videoStreams[handle]->getFrameCount(); } +uint32 VideoManager::getElapsedTime(const VideoHandle &handle) { + assert(handle != NULL_VID_HANDLE); + return _videoStreams[handle]->getElapsedTime(); +} + +bool VideoManager::endOfVideo(const VideoHandle &handle) { + assert(handle != NULL_VID_HANDLE); + return _videoStreams[handle]->endOfVideo(); +} + } // End of namespace Mohawk diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h index 6aa553e26b..4c6ed05cef 100644 --- a/engines/mohawk/video.h +++ b/engines/mohawk/video.h @@ -94,6 +94,8 @@ public: VideoHandle findVideoHandle(uint16 id); int32 getCurFrame(const VideoHandle &handle); uint32 getFrameCount(const VideoHandle &handle); + uint32 getElapsedTime(const VideoHandle &handle); + bool endOfVideo(const VideoHandle &handle); private: MohawkEngine *_vm; |