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/pspit.h"
24 
25 #include "mohawk/cursors.h"
26 #include "mohawk/riven.h"
27 #include "mohawk/riven_card.h"
28 #include "mohawk/riven_sound.h"
29 #include "mohawk/riven_video.h"
30 
31 namespace Mohawk {
32 namespace RivenStacks {
33 
PSpit(MohawkEngine_Riven * vm)34 PSpit::PSpit(MohawkEngine_Riven *vm) :
35 		DomeSpit(vm, kStackPspit, "psliders.25", "psliderbg.25") {
36 
37 	REGISTER_COMMAND(PSpit, xpisland990_elevcombo);
38 	REGISTER_COMMAND(PSpit, xpscpbtn);
39 	REGISTER_COMMAND(PSpit, xpisland290_domecheck);
40 	REGISTER_COMMAND(PSpit, xpisland25_opencard);
41 	REGISTER_COMMAND(PSpit, xpisland25_resetsliders);
42 	REGISTER_COMMAND(PSpit, xpisland25_slidermd);
43 	REGISTER_COMMAND(PSpit, xpisland25_slidermw);
44 }
45 
catherineIdleTimer()46 void PSpit::catherineIdleTimer() {
47 	uint32 &cathCheck = _vm->_vars["pcathcheck"];
48 	uint32 &cathState = _vm->_vars["acathstate"];
49 	uint16 movie;
50 
51 	// Choose a random movie based on where Catherine is
52 	if (cathCheck == 0) {
53 		static const int movieList[] = { 5, 6, 7, 8 };
54 		cathCheck = 1;
55 		movie = movieList[_vm->_rnd->getRandomNumber(3)];
56 	} else if (cathState == 1) {
57 		static const int movieList[] = { 11, 14 };
58 		movie = movieList[_vm->_rnd->getRandomBit()];
59 	} else {
60 		static const int movieList[] = { 9, 10, 12, 13 };
61 		movie = movieList[_vm->_rnd->getRandomNumber(3)];
62 	}
63 
64 	// Update her state if she moves from left/right or right/left, resp.
65 	if (movie == 5 || movie == 7 || movie == 11 || movie == 14)
66 		cathState = 2;
67 	else
68 		cathState = 1;
69 
70 	// Play the movie, blocking
71 	_vm->getCard()->playMovie(movie);
72 	RivenVideo *video = _vm->_video->openSlot(movie);
73 	video->playBlocking();
74 
75 	// Install the next timer for the next video
76 	uint32 timeUntilNextMovie = _vm->_rnd->getRandomNumber(120) * 1000;
77 
78 	_vm->_vars["pcathtime"] = timeUntilNextMovie + _vm->getTotalPlayTime();
79 
80 	installTimer(TIMER(PSpit, catherineIdleTimer), timeUntilNextMovie);
81 }
82 
xpisland990_elevcombo(const ArgumentArray & args)83 void PSpit::xpisland990_elevcombo(const ArgumentArray &args) {
84 	// Play button sound based on args[0]
85 	_vm->_sound->playSound(args[0] + 5);
86 	_vm->_cursor->hideCursor();
87 	_vm->delay(500);
88 	_vm->_cursor->showCursor();
89 
90 	// If the user released the mouse button during the wait time, the mouse up event
91 	// is not forwarded to the game script handler. The button appears to be down
92 	// until the user moves the mouse outside of the button hotspot.
93 	// This happens with the original engine as well.
94 	// To work around this issue we run the mouse up script if the mouse is not
95 	// pressed anymore at this point.
96 	if (!mouseIsDown()) {
97 		Common::String buttonName = Common::String::format("combo%d", args[0]);
98 		RivenHotspot *button = _vm->getCard()->getHotspotByName(buttonName);
99 		RivenScriptPtr mouseUpScript = button->getScript(kMouseUpScript);
100 		_vm->_scriptMan->runScript(mouseUpScript, false);
101 	}
102 
103 	// It is impossible to get here if Gehn is not trapped. However,
104 	// the original also disallows brute forcing the ending if you have
105 	// not yet trapped Gehn.
106 	if (_vm->_vars["agehn"] != 4)
107 		return;
108 
109 	uint32 &correctDigits = _vm->_vars["pelevcombo"];
110 
111 	// pelevcombo keeps count of how many buttons we have pressed in the correct order.
112 	// When pelevcombo is 5, clicking the handle will show the video freeing Catherine.
113 	if (correctDigits < 5 && args[0] == getComboDigit(_vm->_vars["pcorrectorder"], correctDigits))
114 		correctDigits++;
115 	else
116 		correctDigits = 0;
117 }
118 
xpscpbtn(const ArgumentArray & args)119 void PSpit::xpscpbtn(const ArgumentArray &args) {
120 	runDomeButtonMovie();
121 }
122 
xpisland290_domecheck(const ArgumentArray & args)123 void PSpit::xpisland290_domecheck(const ArgumentArray &args) {
124 	runDomeCheck();
125 }
126 
xpisland25_opencard(const ArgumentArray & args)127 void PSpit::xpisland25_opencard(const ArgumentArray &args) {
128 	checkDomeSliders();
129 }
130 
xpisland25_resetsliders(const ArgumentArray & args)131 void PSpit::xpisland25_resetsliders(const ArgumentArray &args) {
132 	resetDomeSliders(14);
133 }
134 
xpisland25_slidermd(const ArgumentArray & args)135 void PSpit::xpisland25_slidermd(const ArgumentArray &args) {
136 	dragDomeSlider(14);
137 }
138 
xpisland25_slidermw(const ArgumentArray & args)139 void PSpit::xpisland25_slidermw(const ArgumentArray &args) {
140 	checkSliderCursorChange(14);
141 }
142 
installCardTimer()143 void PSpit::installCardTimer() {
144 	if (getCurrentCardGlobalId() == 0x3a85) {
145 		// Top of elevator on prison island
146 		// Handle Catherine hardcoded videos
147 		installTimer(TIMER(PSpit, catherineIdleTimer), _vm->_rnd->getRandomNumberRng(1, 33) * 1000);
148 	} else {
149 		RivenStack::installCardTimer();
150 	}
151 }
152 
153 } // End of namespace RivenStacks
154 } // End of namespace Mohawk
155