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