[Scummvm-cvs-logs] SF.net SVN: scummvm:[52482] scummvm/trunk/engines/mohawk

mthreepwood at users.sourceforge.net mthreepwood at users.sourceforge.net
Wed Sep 1 15:28:13 CEST 2010


Revision: 52482
          http://scummvm.svn.sourceforge.net/scummvm/?rev=52482&view=rev
Author:   mthreepwood
Date:     2010-09-01 13:28:12 +0000 (Wed, 01 Sep 2010)

Log Message:
-----------
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).

Modified Paths:
--------------
    scummvm/trunk/engines/mohawk/riven_external.cpp
    scummvm/trunk/engines/mohawk/riven_external.h
    scummvm/trunk/engines/mohawk/riven_scripts.cpp
    scummvm/trunk/engines/mohawk/riven_scripts.h
    scummvm/trunk/engines/mohawk/video.cpp
    scummvm/trunk/engines/mohawk/video.h

Modified: scummvm/trunk/engines/mohawk/riven_external.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/riven_external.cpp	2010-09-01 12:56:34 UTC (rev 52481)
+++ scummvm/trunk/engines/mohawk/riven_external.cpp	2010-09-01 13:28:12 UTC (rev 52482)
@@ -211,9 +211,26 @@
 
 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::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) {

Modified: scummvm/trunk/engines/mohawk/riven_external.h
===================================================================
--- scummvm/trunk/engines/mohawk/riven_external.h	2010-09-01 12:56:34 UTC (rev 52481)
+++ scummvm/trunk/engines/mohawk/riven_external.h	2010-09-01 13:28:12 UTC (rev 52482)
@@ -61,6 +61,7 @@
 	int jspitElevatorLoop();
 	void runDemoBoundaryDialog();
 	void runEndGame(uint16 video);
+	void runCredits(uint16 video);
 	void runDomeCheck();
 	void runDomeButtonMovie();
 	void resetDomeSliders(uint16 bitmapId, uint16 soundId, uint16 startHotspot);

Modified: scummvm/trunk/engines/mohawk/riven_scripts.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/riven_scripts.cpp	2010-09-01 12:56:34 UTC (rev 52481)
+++ scummvm/trunk/engines/mohawk/riven_scripts.cpp	2010-09-01 13:28:12 UTC (rev 52482)
@@ -38,7 +38,7 @@
 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::runScript() {
-	_isRunning = true;
+	_isRunning = _continueRunning = true;
 
 	if (_stream->pos() != 0)
 		_stream->seek(0);
@@ -242,7 +242,7 @@
 
 	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 @@
 	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++) {

Modified: scummvm/trunk/engines/mohawk/riven_scripts.h
===================================================================
--- scummvm/trunk/engines/mohawk/riven_scripts.h	2010-09-01 12:56:34 UTC (rev 52481)
+++ scummvm/trunk/engines/mohawk/riven_scripts.h	2010-09-01 13:28:12 UTC (rev 52482)
@@ -62,6 +62,7 @@
 	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 @@
 
 	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 @@
 	~RivenScriptManager();
 
 	RivenScriptList readScripts(Common::SeekableReadStream *stream, bool garbageCollect = true);
+	void stopAllScripts();
 
 private:
 	void unloadUnusedScripts();

Modified: scummvm/trunk/engines/mohawk/video.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/video.cpp	2010-09-01 12:56:34 UTC (rev 52481)
+++ scummvm/trunk/engines/mohawk/video.cpp	2010-09-01 13:28:12 UTC (rev 52482)
@@ -412,4 +412,14 @@
 	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

Modified: scummvm/trunk/engines/mohawk/video.h
===================================================================
--- scummvm/trunk/engines/mohawk/video.h	2010-09-01 12:56:34 UTC (rev 52481)
+++ scummvm/trunk/engines/mohawk/video.h	2010-09-01 13:28:12 UTC (rev 52482)
@@ -94,6 +94,8 @@
 	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;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list