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/bspit.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_video.h"
30 
31 namespace Mohawk {
32 namespace RivenStacks {
33 
BSpit(MohawkEngine_Riven * vm)34 BSpit::BSpit(MohawkEngine_Riven *vm) :
35 		DomeSpit(vm, kStackBspit, "bSliders.190", "bSliderBG.190") {
36 
37 	REGISTER_COMMAND(BSpit, xblabopenbook);
38 	REGISTER_COMMAND(BSpit, xblabbookprevpage);
39 	REGISTER_COMMAND(BSpit, xblabbooknextpage);
40 	REGISTER_COMMAND(BSpit, xsoundplug);
41 	REGISTER_COMMAND(BSpit, xbchangeboiler);
42 	REGISTER_COMMAND(BSpit, xbupdateboiler);
43 	REGISTER_COMMAND(BSpit, xbsettrap);
44 	REGISTER_COMMAND(BSpit, xbcheckcatch);
45 	REGISTER_COMMAND(BSpit, xbait);
46 	REGISTER_COMMAND(BSpit, xbfreeytram);
47 	REGISTER_COMMAND(BSpit, xbaitplate);
48 	REGISTER_COMMAND(BSpit, xbisland190_opencard);
49 	REGISTER_COMMAND(BSpit, xbisland190_resetsliders);
50 	REGISTER_COMMAND(BSpit, xbisland190_slidermd);
51 	REGISTER_COMMAND(BSpit, xbisland190_slidermw);
52 	REGISTER_COMMAND(BSpit, xbscpbtn);
53 	REGISTER_COMMAND(BSpit, xbisland_domecheck);
54 	REGISTER_COMMAND(BSpit, xvalvecontrol);
55 	REGISTER_COMMAND(BSpit, xbchipper);
56 }
57 
xblabopenbook(const ArgumentArray & args)58 void BSpit::xblabopenbook(const ArgumentArray &args) {
59 	// Get the variable
60 	uint32 page = _vm->_vars["blabpage"];
61 
62 	// Draw the image of the page based on the blabbook variable
63 	_vm->getCard()->drawPicture(page);
64 
65 	if (page == 14) {
66 		labBookDrawDomeCombination();
67 	}
68 }
69 
labBookDrawDomeCombination() const70 void BSpit::labBookDrawDomeCombination() const {
71 	// Draw the dome combination
72 	// The images for the numbers are tBMP's 364 through 368
73 	// The start point is at (240, 82)
74 	uint32 domeCombo = _vm->_vars["adomecombo"];
75 	static const uint16 kNumberWidth = 32;
76 	static const uint16 kNumberHeight = 24;
77 	static const uint16 kDstX = 240;
78 	static const uint16 kDstY = 82;
79 	byte numCount = 0;
80 
81 	for (int bitPos = 24; bitPos >= 0; bitPos--) {
82 			if (domeCombo & (1 << bitPos)) {
83 				uint16 offset = (24 - bitPos) * kNumberWidth;
84 				Common::Rect srcRect = Common::Rect(offset, 0, offset + kNumberWidth, kNumberHeight);
85 				Common::Rect dstRect = Common::Rect(numCount * kNumberWidth + kDstX, kDstY, (numCount + 1) * kNumberWidth + kDstX, kDstY + kNumberHeight);
86 				_vm->_gfx->drawImageRect(numCount + 364, srcRect, dstRect);
87 				numCount++;
88 			}
89 		}
90 
91 	assert(numCount == 5); // Sanity check
92 }
93 
xblabbookprevpage(const ArgumentArray & args)94 void BSpit::xblabbookprevpage(const ArgumentArray &args) {
95 	// Get the page variable
96 	uint32 &page = _vm->_vars["blabpage"];
97 
98 	// Keep turning pages while the mouse is pressed
99 	while (keepTurningPages()) {
100 		// Check for the first page
101 		if (page == 1)
102 			return;
103 
104 		// Update the page number
105 		page--;
106 
107 		pageTurn(kRivenTransitionWipeRight);
108 		_vm->getCard()->drawPicture(page);
109 
110 		if (page == 14) {
111 			labBookDrawDomeCombination();
112 		}
113 
114 		_vm->doFrame();
115 
116 		waitForPageTurnSound();
117 	}
118 }
119 
xblabbooknextpage(const ArgumentArray & args)120 void BSpit::xblabbooknextpage(const ArgumentArray &args) {
121 	// Get the page variable
122 	uint32 &page = _vm->_vars["blabpage"];
123 
124 	// Keep turning pages while the mouse is pressed
125 	while (keepTurningPages()) {
126 		// Check for the last page
127 		if (page == 22)
128 			return;
129 
130 		// Update the page number
131 		page++;
132 
133 		pageTurn(kRivenTransitionWipeLeft);
134 		_vm->getCard()->drawPicture(page);
135 
136 		if (page == 14) {
137 			labBookDrawDomeCombination();
138 		}
139 
140 		_vm->doFrame();
141 
142 		waitForPageTurnSound();
143 	}
144 }
145 
xsoundplug(const ArgumentArray & args)146 void BSpit::xsoundplug(const ArgumentArray &args) {
147 	if (_vm->_vars["bcratergg"] == 0) {
148 		if (_vm->_vars["bblrwtr"] == 0) {
149 			_vm->getCard()->overrideSound(0, 2);
150 		} else {
151 			_vm->getCard()->overrideSound(0, 3);
152 		}
153 	} else {
154 		_vm->getCard()->overrideSound(0, 1);
155 	}
156 }
157 
xbchangeboiler(const ArgumentArray & args)158 void BSpit::xbchangeboiler(const ArgumentArray &args) {
159 	uint32 heat = _vm->_vars["bheat"];
160 	uint32 water = _vm->_vars["bblrwtr"];
161 	uint32 platform = _vm->_vars["bblrgrt"];
162 
163 	// Stop any background videos
164 	_vm->_video->closeVideos();
165 
166 	if (args[0] == 1) {
167 		// Water is filling/draining from the boiler
168 		if (water == 0) {
169 			if (platform == 1)
170 				_vm->getCard()->playMovie(12);
171 			else
172 				_vm->getCard()->playMovie(10);
173 		} else if (heat == 1) {
174 			if (platform == 1)
175 				_vm->getCard()->playMovie(22);
176 			else
177 				_vm->getCard()->playMovie(19);
178 		} else {
179 			if (platform == 1)
180 				_vm->getCard()->playMovie(16);
181 			else
182 				_vm->getCard()->playMovie(13);
183 		}
184 	} else if (args[0] == 2 && water != 0) {
185 		if (heat == 1) {
186 			// Turning on the heat
187 			if (platform == 1)
188 				_vm->getCard()->playMovie(23);
189 			else
190 				_vm->getCard()->playMovie(20);
191 		} else {
192 			// Turning off the heat
193 			if (platform == 1)
194 				_vm->getCard()->playMovie(18);
195 			else
196 				_vm->getCard()->playMovie(15);
197 		}
198 	} else if (args[0] == 3) {
199 		if (platform == 1) {
200 			// Lowering the platform
201 			if (water == 1) {
202 				if (heat == 1)
203 					_vm->getCard()->playMovie(24);
204 				else
205 					_vm->getCard()->playMovie(17);
206 			} else {
207 				_vm->getCard()->playMovie(11);
208 			}
209 		} else {
210 			// Raising the platform
211 			if (water == 1) {
212 				if (heat == 1)
213 					_vm->getCard()->playMovie(21);
214 				else
215 					_vm->getCard()->playMovie(14);
216 			} else {
217 				_vm->getCard()->playMovie(9);
218 			}
219 		}
220 	}
221 
222 	if (args.size() > 1)
223 		_vm->getCard()->playSound(args[1]);
224 	else if (args[0] == 2)
225 		_vm->getCard()->playSound(1);
226 
227 	RivenVideo *video = _vm->_video->openSlot(11);
228 	video->playBlocking();
229 }
230 
xbupdateboiler(const ArgumentArray & args)231 void BSpit::xbupdateboiler(const ArgumentArray &args) {
232 	if (_vm->_vars["bheat"] != 0) {
233 		if (_vm->_vars["bblrgrt"] == 0) {
234 			_vm->getCard()->playMovie(8);
235 		} else {
236 			_vm->getCard()->playMovie(7);
237 		}
238 	} else {
239 		RivenVideo *video = _vm->_video->getSlot(7);
240 		if (video) {
241 			video->disable();
242 			video->stop();
243 		}
244 		video = _vm->_video->getSlot(8);
245 		if (video) {
246 			video->disable();
247 			video->stop();
248 		}
249 	}
250 }
251 
ytramTrapTimer()252 void BSpit::ytramTrapTimer() {
253 	// Remove this timer
254 	removeTimer();
255 
256 	// Check if we've caught a Ytram
257 	checkYtramCatch(true);
258 }
259 
xbsettrap(const ArgumentArray & args)260 void BSpit::xbsettrap(const ArgumentArray &args) {
261 	// Set the Ytram trap
262 
263 	// We can catch the Ytram between 10 seconds and 3 minutes from now
264 	uint32 timeUntilCatch = _vm->_rnd->getRandomNumberRng(10, 60 * 3) * 1000;
265 	_vm->_vars["bytramtime"] = timeUntilCatch + _vm->getTotalPlayTime();
266 
267 	// And set the timer too
268 	installTimer(TIMER(BSpit, ytramTrapTimer), timeUntilCatch);
269 }
270 
checkYtramCatch(bool playSound)271 void BSpit::checkYtramCatch(bool playSound) {
272 	// Check if we've caught a Ytram
273 
274 	uint32 &ytramTime = _vm->_vars["bytramtime"];
275 
276 	// The trap has been moved back up.
277 	// You can't catch those sneaky Ytrams that way.
278 	if (ytramTime == 0) {
279 		return;
280 	}
281 
282 	// If the trap still has not gone off, reinstall our timer
283 	// This is in case you set the trap, walked away, and returned
284 	if (_vm->getTotalPlayTime() < ytramTime) {
285 		installTimer(TIMER(BSpit, ytramTrapTimer), ytramTime - _vm->getTotalPlayTime());
286 		return;
287 	}
288 
289 	// Increment the movie per catch (max = 3)
290 	uint32 &ytramMovie = _vm->_vars["bytram"];
291 	ytramMovie++;
292 	if (ytramMovie > 3)
293 		ytramMovie = 3;
294 
295 	// Reset variables
296 	_vm->_vars["bytrapped"] = 1;
297 	_vm->_vars["bbait"] = 0;
298 	_vm->_vars["bytrap"] = 0;
299 	ytramTime = 0;
300 
301 	// Play the capture sound, if requested
302 	if (playSound)
303 		_vm->_sound->playSound(33);
304 }
305 
xbcheckcatch(const ArgumentArray & args)306 void BSpit::xbcheckcatch(const ArgumentArray &args) {
307 	// Just pass our parameter along...
308 	checkYtramCatch(args[0] != 0);
309 }
310 
xbait(const ArgumentArray & args)311 void BSpit::xbait(const ArgumentArray &args) {
312 	// Set the cursor to the pellet
313 	_vm->_cursor->setCursor(kRivenPelletCursor);
314 
315 	// Loop until the player lets go (or quits)
316 	while (mouseIsDown() && !_vm->hasGameEnded()) {
317 		_vm->doFrame();
318 	}
319 
320 	// Set back the cursor
321 	_vm->_cursor->setCursor(kRivenMainCursor);
322 
323 	RivenHotspot *bait = _vm->getCard()->getHotspotByBlstId(9);
324 	RivenHotspot *baitPlate = _vm->getCard()->getHotspotByBlstId(16);
325 
326 	// Set the bait if we put it on the plate
327 	if (baitPlate->containsPoint(getMousePosition())) {
328 		_vm->_vars["bbait"] = 1;
329 		_vm->getCard()->drawPicture(4);
330 
331 		bait->enable(false); // Disable bait hotspot
332 		baitPlate->enable(true); // Enable baitplate hotspot
333 	}
334 }
335 
xbfreeytram(const ArgumentArray & args)336 void BSpit::xbfreeytram(const ArgumentArray &args) {
337 	// Play a random Ytram movie after freeing it
338 	uint16 mlstId;
339 
340 	switch (_vm->_vars["bytram"]) {
341 		case 1:
342 			mlstId = 11;
343 			break;
344 		case 2:
345 			mlstId = 12;
346 			break;
347 		default:
348 			// The original did rand(13, 14)
349 			mlstId = _vm->_rnd->getRandomNumberRng(13, 15);
350 			break;
351 	}
352 
353 	// Play the video
354 	_vm->getCard()->playMovie(mlstId);
355 	RivenVideo *first = _vm->_video->openSlot(11);
356 	first->playBlocking();
357 
358 	// Now play the second movie
359 	_vm->getCard()->playMovie(mlstId + 5);
360 	RivenVideo *second = _vm->_video->openSlot(12);
361 	second->playBlocking();
362 
363 	_vm->getCard()->drawPicture(4);
364 }
365 
xbaitplate(const ArgumentArray & args)366 void BSpit::xbaitplate(const ArgumentArray &args) {
367 	// Remove the pellet from the plate and put it in your hand
368 	_vm->_cursor->setCursor(kRivenPelletCursor);
369 	_vm->getCard()->drawPicture(3);
370 
371 	// Loop until the player lets go (or quits)
372 	while (mouseIsDown() && !_vm->hasGameEnded()) {
373 		_vm->doFrame();
374 	}
375 
376 	// Set back the cursor
377 	_vm->_cursor->setCursor(kRivenMainCursor);
378 
379 	RivenHotspot *bait = _vm->getCard()->getHotspotByBlstId(9);
380 	RivenHotspot *baitPlate = _vm->getCard()->getHotspotByBlstId(16);
381 
382 	// Set the bait if we put it on the plate, remove otherwise
383 	if (baitPlate->containsPoint(getMousePosition())) {
384 		_vm->_vars["bbait"] = 1;
385 		_vm->getCard()->drawPicture(4);
386 		bait->enable(false); // Disable bait hotspot
387 		baitPlate->enable(true); // Enable baitplate hotspot
388 	} else {
389 		_vm->_vars["bbait"] = 0;
390 		bait->enable(true); // Enable bait hotspot
391 		baitPlate->enable(false); // Disable baitplate hotspot
392 	}
393 }
394 
xbisland190_opencard(const ArgumentArray & args)395 void BSpit::xbisland190_opencard(const ArgumentArray &args) {
396 	checkDomeSliders();
397 }
398 
xbisland190_resetsliders(const ArgumentArray & args)399 void BSpit::xbisland190_resetsliders(const ArgumentArray &args) {
400 	resetDomeSliders(9);
401 }
402 
xbisland190_slidermd(const ArgumentArray & args)403 void BSpit::xbisland190_slidermd(const ArgumentArray &args) {
404 	dragDomeSlider(9);
405 }
406 
xbisland190_slidermw(const ArgumentArray & args)407 void BSpit::xbisland190_slidermw(const ArgumentArray &args) {
408 	checkSliderCursorChange(9);
409 }
410 
xbscpbtn(const ArgumentArray & args)411 void BSpit::xbscpbtn(const ArgumentArray &args) {
412 	runDomeButtonMovie();
413 }
414 
xbisland_domecheck(const ArgumentArray & args)415 void BSpit::xbisland_domecheck(const ArgumentArray &args) {
416 	runDomeCheck();
417 }
418 
xvalvecontrol(const ArgumentArray & args)419 void BSpit::xvalvecontrol(const ArgumentArray &args) {
420 	Common::Point startPos = getMouseDragStartPosition();
421 
422 	// Set the cursor to the closed position
423 	_vm->_cursor->setCursor(kRivenClosedHandCursor);
424 
425 	while (mouseIsDown()) {
426 		Common::Point mousePos = getMousePosition();
427 		int changeX = mousePos.x - startPos.x;
428 		int changeY = startPos.y - mousePos.y;
429 
430 		// Get the variable for the valve
431 		uint32 valve = _vm->_vars["bvalve"];
432 
433 		// FIXME: These values for changes in x/y could be tweaked.
434 		if (valve == 0 && changeY <= -10) {
435 			valveChangePosition(1, 2, 2);
436 		} else if (valve == 1) {
437 			if (changeX >= 0 && changeY >= 10) {
438 				valveChangePosition(0, 3, 1);
439 			} else if (changeX <= -10 && changeY <= 10) {
440 				valveChangePosition(2, 1, 3);
441 			}
442 		} else if (valve == 2 && changeX >= 10) {
443 			valveChangePosition(1, 4, 2);
444 		}
445 
446 		_vm->doFrame();
447 	}
448 }
449 
valveChangePosition(uint32 valvePosition,uint16 videoId,uint16 pictureId)450 void BSpit::valveChangePosition(uint32 valvePosition, uint16 videoId, uint16 pictureId) {
451 	RivenVideo *video = _vm->_video->openSlot(videoId);
452 	video->seek(0);
453 	video->playBlocking();
454 
455 	_vm->getCard()->drawPicture(pictureId);
456 
457 	// If we changed state and the new state is that the valve is flowing to
458 	// the boiler, we need to update the boiler state.
459 	if (valvePosition == 1) {
460 		// Check which way the water is going at the boiler
461 		if (_vm->_vars["bidvlv"] == 1) {
462 			if (_vm->_vars["bblrarm"] == 1 && _vm->_vars["bblrwtr"] == 1) {
463 				// If the pipe is open, make sure the water is drained out
464 				_vm->_vars["bheat"] = 0;
465 				_vm->_vars["bblrwtr"] = 0;
466 				_vm->_sound->playCardSound("bBlrFar");
467 			}
468 
469 			if (_vm->_vars["bblrarm"] == 0 && _vm->_vars["bblrwtr"] == 0) {
470 				// If the pipe is closed, fill the boiler again
471 				_vm->_vars["bheat"] = _vm->_vars["bblrvalve"];
472 				_vm->_vars["bblrwtr"] = 1;
473 				_vm->_sound->playCardSound("bBlrFar");
474 			}
475 		} else {
476 			// Have the grating inside the boiler match the switch outside
477 			_vm->_vars["bblrgrt"] = (_vm->_vars["bblrsw"] == 1) ? 0 : 1;
478 		}
479 	}
480 
481 	_vm->_vars["bvalve"] = valvePosition;
482 }
483 
xbchipper(const ArgumentArray & args)484 void BSpit::xbchipper(const ArgumentArray &args) {
485 	Common::Point startPos = getMouseDragStartPosition();
486 
487 	bool pulledLever = false;
488 	while (mouseIsDown() && !_vm->hasGameEnded()) {
489 		Common::Point pos = getMousePosition();
490 		if (pos.y > startPos.y) {
491 			pulledLever = true;
492 			break;
493 		}
494 
495 		_vm->doFrame();
496 	}
497 
498 	if (pulledLever) {
499 		RivenVideo *video = _vm->_video->openSlot(2);
500 		video->seek(0);
501 		video->playBlocking();
502 	}
503 }
504 
505 } // End of namespace RivenStacks
506 } // End of namespace Mohawk
507