1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "mohawk/riven_stacks/ospit.h"
24 
25 #include "mohawk/cursors.h"
26 #include "mohawk/riven.h"
27 #include "mohawk/riven_card.h"
28 #include "mohawk/riven_graphics.h"
29 #include "mohawk/riven_inventory.h"
30 #include "mohawk/riven_video.h"
31 
32 namespace Mohawk {
33 namespace RivenStacks {
34 
OSpit(MohawkEngine_Riven * vm)35 OSpit::OSpit(MohawkEngine_Riven *vm) :
36 		RivenStack(vm, kStackOspit) {
37 
38 	REGISTER_COMMAND(OSpit, xorollcredittime);
39 	REGISTER_COMMAND(OSpit, xbookclick);
40 	REGISTER_COMMAND(OSpit, xooffice30_closebook);
41 	REGISTER_COMMAND(OSpit, xobedroom5_closedrawer);
42 	REGISTER_COMMAND(OSpit, xogehnopenbook);
43 	REGISTER_COMMAND(OSpit, xogehnbookprevpage);
44 	REGISTER_COMMAND(OSpit, xogehnbooknextpage);
45 	REGISTER_COMMAND(OSpit, xgwatch);
46 }
47 
xorollcredittime(const ArgumentArray & args)48 void OSpit::xorollcredittime(const ArgumentArray &args) {
49 	// WORKAROUND: The special change stuff only handles one destination and it would
50 	// be messy to modify the way that currently works. If we use the trap book on Tay,
51 	// we should be using the Tay end game sequences.
52 	if (_vm->_vars["returnstackid"] == kStackRspit) {
53 		RivenScriptPtr script = _vm->_scriptMan->createScriptWithCommand(
54 				new RivenStackChangeCommand(_vm, kStackRspit, 0x3338, true, false));
55 		_vm->_scriptMan->runScript(script, false);
56 		return;
57 	}
58 
59 	// You used the trap book... why? What were you thinking?
60 	uint32 gehnState = _vm->_vars["agehn"];
61 
62 	if (gehnState == 0)         // Gehn who?
63 		runEndGame(1, 9500, 1225);
64 	else if (gehnState == 4)    // You freed him? Are you kidding me?
65 		runEndGame(2, 12000, 558);
66 	else                        // You already spoke with Gehn. What were you thinking?
67 		runEndGame(3, 8000, 857);
68 }
69 
xbookclick(const ArgumentArray & args)70 void OSpit::xbookclick(const ArgumentArray &args) {
71 	// Let's hook onto our video
72 	RivenVideo *video = _vm->_video->getSlot(args[0]);
73 
74 	// Convert from the standard QuickTime base time to milliseconds
75 	// The values are in terms of 1/600 of a second.
76 	// Have I said how much I just *love* QuickTime? </sarcasm>
77 	uint32 startTime = args[1] * 1000 / 600;
78 	uint32 endTime = args[2] * 1000 / 600;
79 
80 	// Track down our hotspot
81 	Common::String hotspotName = Common::String::format("touchBook%d", args[3]);
82 	RivenHotspot *hotspot = _vm->getCard()->getHotspotByName(hotspotName);
83 	Common::Rect hotspotRect = hotspot->getRect();
84 
85 	debug(0, "xbookclick:");
86 	debug(0, "\tVideo Code = %d", args[0]);
87 	debug(0, "\tStart Time = %dms", startTime);
88 	debug(0, "\tEnd Time   = %dms", endTime);
89 	debug(0, "\tHotspot    = %d -> %s", args[3], hotspotName.c_str());
90 
91 	// Just let the video play while we wait until Gehn opens the trap book for us
92 	while (video->getTime() < startTime && !_vm->hasGameEnded()) {
93 		_vm->doFrame();
94 	}
95 
96 	// Break out if we're quitting
97 	if (_vm->hasGameEnded())
98 		return;
99 
100 	// OK, Gehn has opened the trap book and has asked us to go in. Let's watch
101 	// and see what the player will do...
102 	while (video->getTime() < endTime && !_vm->hasGameEnded()) {
103 		if (hotspotRect.contains(getMousePosition()))
104 			_vm->_cursor->setCursor(kRivenOpenHandCursor);
105 		else
106 			_vm->_cursor->setCursor(kRivenMainCursor);
107 
108 		if (mouseIsDown()) {
109 			if (hotspotRect.contains(getMousePosition())) {
110 				// OK, we've used the trap book! We go for ride lady!
111 				_vm->_video->closeVideos();                          // Stop all videos
112 				_vm->_cursor->setCursor(kRivenHideCursor);          // Hide the cursor
113 				_vm->_gfx->scheduleTransition(kRivenTransitionBlend);
114 				_vm->getCard()->drawPicture(3);                  // Black out the screen
115 				_vm->_sound->playSound(0);                          // Play the link sound
116 				_vm->delay(12000);
117 				_vm->getCard()->playMovie(7);    // Activate Gehn Link Video
118 				RivenVideo *linkVideo = _vm->_video->openSlot(1);             // Play Gehn Link Video
119 				linkVideo->playBlocking();
120 				_vm->_vars["ocage"] = 1;
121 				_vm->_vars["agehn"] = 4;                            // Set Gehn to the trapped state
122 				_vm->_vars["atrapbook"] = 1;                        // We've got the trap book again
123 				_vm->_sound->playSound(0);                          // Play the link sound again
124 				_vm->_gfx->scheduleTransition(kRivenTransitionBlend);
125 				_vm->changeToCard(_vm->getStack()->getCardStackId(0x2885));    // Link out!
126 				_vm->_inventory->forceVisible(true);
127 				_vm->delay(2000);
128 				_vm->_inventory->forceVisible(false);
129 				_vm->_scriptMan->stopAllScripts();                  // Stop all running scripts (so we don't remain in the cage)
130 				return;
131 			}
132 		}
133 
134 		_vm->doFrame();
135 	}
136 
137 	// Break out if we're quitting
138 	if (_vm->hasGameEnded())
139 		return;
140 
141 	// If there was no click and this is the third time Gehn asks us to
142 	// use the trap book, he will shoot the player. Dead on arrival.
143 	// Run the credits from here.
144 	if (_vm->_vars["agehn"] == 3) {
145 		runCredits(args[0], 5000, 995);
146 		return;
147 	}
148 
149 	// There was no click, so just play the rest of the video.
150 	video->playBlocking();
151 }
152 
xooffice30_closebook(const ArgumentArray & args)153 void OSpit::xooffice30_closebook(const ArgumentArray &args) {
154 	// Close the blank linking book if it's open
155 	uint32 &book = _vm->_vars["odeskbook"];
156 	if (book != 1)
157 		return;
158 
159 	// Set the variable to be "closed"
160 	book = 0;
161 
162 	// Play the movie
163 	RivenVideo *video = _vm->_video->openSlot(1);
164 	video->seek(0);
165 	video->playBlocking();
166 
167 	// Set the hotspots into their correct states
168 	RivenHotspot *closeBook = _vm->getCard()->getHotspotByName("closeBook");
169 	RivenHotspot *nullHotspot = _vm->getCard()->getHotspotByName("null");
170 	RivenHotspot *openBook = _vm->getCard()->getHotspotByName("openBook");
171 
172 	closeBook->enable(false);
173 	nullHotspot->enable(false);
174 	openBook->enable(true);
175 
176 	_vm->getCard()->drawPicture(1);
177 }
178 
xobedroom5_closedrawer(const ArgumentArray & args)179 void OSpit::xobedroom5_closedrawer(const ArgumentArray &args) {
180 	// Close the drawer if open when clicking on the journal.
181 	RivenVideo *video = _vm->_video->openSlot(2);
182 	video->playBlocking();
183 	_vm->_vars["ostanddrawer"] = 0;
184 }
185 
xogehnopenbook(const ArgumentArray & args)186 void OSpit::xogehnopenbook(const ArgumentArray &args) {
187 	_vm->getCard()->drawPicture(_vm->_vars["ogehnpage"]);
188 }
189 
xogehnbookprevpage(const ArgumentArray & args)190 void OSpit::xogehnbookprevpage(const ArgumentArray &args) {
191 	// Get the page variable
192 	uint32 &page = _vm->_vars["ogehnpage"];
193 
194 	// Keep turning pages while the mouse is pressed
195 	while (keepTurningPages()) {
196 		// Check for the first page
197 		if (page == 1)
198 			return;
199 
200 		// Update the page number
201 		page--;
202 
203 		pageTurn(kRivenTransitionWipeRight);
204 		_vm->getCard()->drawPicture(page);
205 		_vm->doFrame();
206 
207 		waitForPageTurnSound();
208 	}
209 }
210 
xogehnbooknextpage(const ArgumentArray & args)211 void OSpit::xogehnbooknextpage(const ArgumentArray &args) {
212 	// Get the page variable
213 	uint32 &page = _vm->_vars["ogehnpage"];
214 
215 	// Keep turning pages while the mouse is pressed
216 	while (keepTurningPages()) {
217 		// Check for the last page
218 		if (page == 13)
219 			return;
220 
221 		// Update the page number
222 		page++;
223 
224 		pageTurn(kRivenTransitionWipeLeft);
225 		_vm->getCard()->drawPicture(page);
226 		_vm->doFrame();
227 
228 		waitForPageTurnSound();
229 	}
230 }
231 
xgwatch(const ArgumentArray & args)232 void OSpit::xgwatch(const ArgumentArray &args) {
233 	// Hide the cursor
234 	_vm->_cursor->setCursor(kRivenHideCursor);
235 
236 	uint32 prisonCombo = _vm->_vars["pcorrectorder"];
237 
238 	byte curSound = 0;
239 	while (curSound < 5 && !_vm->hasGameEnded()) {
240 		// Play a sound every half second
241 		_vm->_sound->playSound(getComboDigit(prisonCombo, curSound) + 13);
242 		_vm->delay(500);
243 
244 		curSound++;
245 	}
246 
247 	// Now play the video for the watch
248 	_vm->getCard()->playMovie(1);
249 	RivenVideo *watchVideo = _vm->_video->openSlot(1);
250 	watchVideo->playBlocking();
251 }
252 
253 } // End of namespace RivenStacks
254 } // End of namespace Mohawk
255