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 "startrek/room.h"
24 
25 #define OBJECT_MUDD 8
26 #define OBJECT_9 9
27 #define OBJECT_ALIEN_IMAGE 10
28 #define OBJECT_ALIENDV 11
29 #define OBJECT_NORTH_DOOR 12
30 #define OBJECT_REPAIR_TOOL 13
31 
32 #define HOTSPOT_SCREEN 0x20
33 #define HOTSPOT_SPHERE 0x21
34 #define HOTSPOT_NORTH_DOOR 0x22
35 #define HOTSPOT_EAST_DOOR 0x23
36 
37 namespace StarTrek {
38 
39 // BUG-ish: trying to scan the sphere while someone is behind it causes it to scan that
40 // object instead.
41 
mudd3Tick1()42 void Room::mudd3Tick1() {
43 	playVoc("MUD3LOOP");
44 
45 	_awayMission->crewDirectionsAfterWalk[OBJECT_REDSHIRT] = DIR_W;
46 
47 	if (_awayMission->mudd.databaseDestroyed) {
48 		loadActorAnim(OBJECT_9, "s4lbpb", 0xa2, 0x9f);
49 
50 		// FIXME: is this supposed to be in this if statement?
51 		if (!_awayMission->mudd.tookRepairTool)
52 			loadActorAnim(OBJECT_REPAIR_TOOL, "s4lbdv", 0xb7, 0xa8);
53 	}
54 
55 	_awayMission->mudd.muddInDatabaseRoom = false;
56 
57 	if (!_awayMission->mudd.muddVisitedDatabaseRoom && _awayMission->mudd.translatedAlienLanguage && !_awayMission->mudd.muddUnavailable) {
58 		_awayMission->mudd.muddVisitedDatabaseRoom = true;
59 		loadActorAnim(OBJECT_MUDD, "s4lbhs", 0xa2, 0x9f);
60 		playMidiMusicTracks(3);
61 		_awayMission->mudd.muddInDatabaseRoom = true;
62 		_awayMission->timers[2] = 10;
63 	}
64 }
65 
mudd3UseCommunicator()66 void Room::mudd3UseCommunicator() {
67 	showText(TX_SPEAKER_KIRK,  TX_MUD3_003);
68 	showText(TX_SPEAKER_UHURA, TX_STATICU1);
69 }
70 
mudd3LookAtScreen()71 void Room::mudd3LookAtScreen() {
72 	// BUGFIX: the condition was flipped in the original; the more "vague" description
73 	// should be shown before the alien language is understood.
74 	if (_awayMission->mudd.translatedAlienLanguage)
75 		showText(TX_SPEAKER_SPOCK, TX_MUD3_038);
76 	else
77 		showDescription(TX_MUD3N017);
78 }
79 
mudd3UseSTricorderOnScreen()80 void Room::mudd3UseSTricorderOnScreen() {
81 	if (_roomVar.mudd.tricordersUnavailable)
82 		showText(TX_SPEAKER_SPOCK, TX_MUD3_039);
83 	else
84 		spockScan(DIR_S, TX_MUD3_017, false);
85 }
86 
87 // BUGFIX: Event was actually "use screen on kirk", which makes no sense.
mudd3UseKirkOnScreen()88 void Room::mudd3UseKirkOnScreen() {
89 	if (!_awayMission->mudd.translatedAlienLanguage) {
90 		showDescription(TX_MUD3N011);
91 		showText(TX_SPEAKER_SPOCK, TX_MUD3_037);
92 	}
93 }
94 
mudd3UseSpockOnSphere()95 void Room::mudd3UseSpockOnSphere() {
96 	_awayMission->crewDirectionsAfterWalk[OBJECT_SPOCK] = DIR_S;
97 	loadActorStandAnim(OBJECT_SPOCK);
98 
99 	if (_awayMission->mudd.computerDataErasedOrDestroyed) {
100 		if (!_awayMission->mudd.databaseDestroyed) {
101 			showDescription(TX_MUD3N000);
102 			showText(TX_SPEAKER_SPOCK, TX_MUD3_052);
103 			showText(TX_SPEAKER_KIRK,  TX_MUD3_012);
104 			showText(TX_SPEAKER_MCCOY, TX_MUD3_024);
105 		}
106 		showText(TX_SPEAKER_KIRK,  TX_MUD3_006);
107 		showText(TX_SPEAKER_SPOCK, TX_MUD3_048);
108 		showText(TX_SPEAKER_KIRK,  TX_MUD3_008);
109 		showText(TX_SPEAKER_SPOCK, TX_MUD3_051);
110 	} else if (_awayMission->mudd.translatedAlienLanguage) {
111 		if (_awayMission->mudd.accessedAlienDatabase)
112 			showText(TX_SPEAKER_SPOCK, TX_MUD3_035);
113 		else {
114 			_awayMission->mudd.accessedAlienDatabase = true;
115 
116 			showText(TX_SPEAKER_SPOCK, TX_MUD3_054);
117 			showText(TX_SPEAKER_MCCOY, TX_MUD3_032);
118 			showText(TX_SPEAKER_SPOCK, TX_MUD3_050);
119 			showText(TX_SPEAKER_SPOCK, TX_MUD3_049);
120 			showText(TX_SPEAKER_SPOCK, TX_MUD3_046);
121 			showText(TX_SPEAKER_KIRK,  TX_MUD3_007);
122 
123 			_awayMission->mudd.missionScore++;
124 			playVoc("LSHAIANS");
125 			loadActorAnim(OBJECT_ALIEN_IMAGE, "s4lbap", 0x32, 0x64);
126 
127 			_awayMission->crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_W;
128 			_awayMission->crewDirectionsAfterWalk[OBJECT_SPOCK] = DIR_W;
129 			_awayMission->crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_W;
130 			_awayMission->crewDirectionsAfterWalk[OBJECT_REDSHIRT] = DIR_W;
131 			loadActorStandAnim(OBJECT_KIRK);
132 			loadActorStandAnim(OBJECT_SPOCK);
133 			loadActorStandAnim(OBJECT_MCCOY);
134 			loadActorStandAnim(OBJECT_REDSHIRT);
135 
136 			_awayMission->disableInput = true;
137 			_awayMission->timers[3] = 40;
138 		}
139 	} else if (_awayMission->mudd.discoveredBase3System) {
140 		showText(TX_SPEAKER_SPOCK, TX_MUD3_043);
141 		showText(TX_SPEAKER_MCCOY, TX_MUD3_022);
142 		showText(TX_SPEAKER_SPOCK, TX_MUD3_056);
143 		showText(TX_SPEAKER_KIRK,  TX_MUD3_015);
144 		showText(TX_SPEAKER_SPOCK, TX_MUD3_047);
145 		_roomVar.mudd.suggestedUsingTricorders = true;
146 	} else {
147 		showText(TX_SPEAKER_SPOCK, TX_MUD3_044);
148 		_awayMission->crewDirectionsAfterWalk[OBJECT_SPOCK] = DIR_W;
149 		walkCrewman(OBJECT_SPOCK, 0xcd, 0x87);
150 	}
151 }
152 
153 // Finished looking at alien image
mudd3Timer3Expired()154 void Room::mudd3Timer3Expired() {
155 	_awayMission->disableInput = false;
156 
157 	showText(TX_SPEAKER_MCCOY, TX_MUD3_027);
158 	showText(TX_SPEAKER_SPOCK, TX_MUD3_053);
159 	showText(TX_SPEAKER_MCCOY, TX_MUD3_028);
160 	showText(TX_SPEAKER_MCCOY, TX_MUD3_026);
161 }
162 
mudd3UseMccoyOnSphere()163 void Room::mudd3UseMccoyOnSphere() {
164 	// ENHANCEMENT: Turn to face south
165 	_awayMission->crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_S;
166 	loadActorStandAnim(OBJECT_MCCOY);
167 
168 	showText(TX_SPEAKER_MCCOY, TX_MUD3_021);
169 	_awayMission->crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_W;
170 	walkCrewman(OBJECT_MCCOY, 0xec, 0x84);
171 }
172 
mudd3UseRedshirtOnSphere()173 void Room::mudd3UseRedshirtOnSphere() {
174 	// ENHANCEMENT: Turn to face south
175 	_awayMission->crewDirectionsAfterWalk[OBJECT_REDSHIRT] = DIR_S;
176 	loadActorStandAnim(OBJECT_REDSHIRT);
177 
178 	showText(TX_SPEAKER_BUCHERT, TX_MUD3_068); // BUGFIX: original played McCoy's audio by mistake
179 	_awayMission->crewDirectionsAfterWalk[OBJECT_REDSHIRT] = DIR_W;
180 	walkCrewman(OBJECT_REDSHIRT, 0xec, 0x84);
181 }
182 
mudd3UseMTricorderOnSphere()183 void Room::mudd3UseMTricorderOnSphere() {
184 	if (_roomVar.mudd.tricordersUnavailable)
185 		showText(TX_SPEAKER_SPOCK, TX_MUD3_039); // BUGFIX: speaker is Spock
186 	else {
187 		_awayMission->crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_S;
188 		loadActorStandAnim(OBJECT_MCCOY);
189 		if (!_awayMission->mudd.translatedAlienLanguage && _roomVar.mudd.suggestedUsingTricorders && _awayMission->mudd.discoveredBase3System) {
190 			_awayMission->disableInput = true;
191 
192 			_awayMission->crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_S;
193 			walkCrewman(OBJECT_MCCOY, 0xac, 0x88);
194 			_awayMission->crewDirectionsAfterWalk[OBJECT_SPOCK] = DIR_S;
195 			walkCrewmanC(OBJECT_SPOCK, 0xa5, 0x8c, &Room::mudd3ReadyToHookUpTricorders);
196 		} else {
197 			showText(TX_SPEAKER_MCCOY, TX_MUD3_021);
198 			_awayMission->crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_W;
199 			walkCrewman(OBJECT_MCCOY, 0xec, 0x84);
200 		}
201 	}
202 }
203 
mudd3UseSTricorderOnSphere()204 void Room::mudd3UseSTricorderOnSphere() {
205 	_awayMission->crewDirectionsAfterWalk[OBJECT_SPOCK] = DIR_S;
206 	loadActorStandAnim(OBJECT_SPOCK);
207 
208 	if (_roomVar.mudd.tricordersUnavailable)
209 		showText(TX_SPEAKER_SPOCK, TX_MUD3_039); // BUGFIX: speaker is Spock
210 	else if (_awayMission->mudd.translatedAlienLanguage || (_awayMission->mudd.discoveredBase3System && !_roomVar.mudd.suggestedUsingTricorders)) {
211 		showText(TX_SPEAKER_SPOCK, TX_MUD3_041);
212 		_awayMission->crewDirectionsAfterWalk[OBJECT_SPOCK] = DIR_W;
213 		walkCrewman(OBJECT_SPOCK, 0xcd, 0x87);
214 	} else if (_awayMission->mudd.discoveredBase3System && _roomVar.mudd.suggestedUsingTricorders) { // Hooking up tricorders
215 		_awayMission->disableInput = true;
216 		_awayMission->crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_S;
217 		walkCrewmanC(OBJECT_MCCOY, 0xca, 0x88, &Room::mudd3ReadyToHookUpTricorders);
218 	} else { // No idea how to access it
219 		showText(TX_SPEAKER_SPOCK, TX_MUD3_042);
220 		walkCrewman(OBJECT_SPOCK, 0xcd, 0x87);
221 	}
222 }
223 
mudd3ReadyToHookUpTricorders()224 void Room::mudd3ReadyToHookUpTricorders() {
225 	showText(TX_SPEAKER_SPOCK, TX_MUD3_018);
226 
227 	_roomVar.mudd.tricordersUnavailable = true;
228 	_awayMission->timers[1] = 50;
229 
230 	loadActorAnim2(OBJECT_SPOCK, "sscans");
231 	playSoundEffectIndex(SND_TRICORDER);
232 }
233 
mudd3Timer1Expired()234 void Room::mudd3Timer1Expired() { // Tricorders ready for use again
235 	showText(TX_SPEAKER_SPOCK, TX_MUD3_040);
236 	showText(TX_SPEAKER_SPOCK, TX_MUD3_034);
237 
238 	_awayMission->disableInput = false;
239 	_roomVar.mudd.tricordersUnavailable = false;
240 	_roomVar.mudd.suggestedUsingTricorders = false;
241 	_awayMission->mudd.translatedAlienLanguage = true;
242 	_awayMission->mudd.missionScore++;
243 
244 	_awayMission->crewDirectionsAfterWalk[OBJECT_SPOCK] = DIR_W;
245 	_awayMission->crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_W;
246 	walkCrewman(OBJECT_SPOCK, 0xcd, 0x87);
247 	walkCrewman(OBJECT_MCCOY, 0xec, 0x84);
248 }
249 
250 // Harry Mudd stumbled into the room
mudd3Timer2Expired()251 void Room::mudd3Timer2Expired() {
252 	const TextRef choices[] = {
253 		TX_SPEAKER_KIRK,
254 		TX_MUD3_010,
255 		TX_MUD3_009,
256 		TX_BLANK
257 	};
258 
259 	_awayMission->mudd.computerDataErasedOrDestroyed = true;
260 
261 	showText(TX_SPEAKER_MUDD, TX_MUD3_065);
262 	int choice = showMultipleTexts(choices);
263 
264 	if (choice == 0) { // Allow him to access the database (he ends up erasing it)
265 		showText(TX_SPEAKER_MUDD, TX_MUD3_066);
266 		_awayMission->mudd.muddErasedDatabase = true;
267 
268 		// ENHANCEMENT: Add a few lines to make it clear that Mudd erased the databanks.
269 		// Otherwise, the end of the mission when you confront Mudd doesn't make sense
270 		// unless the player happened to try accessing the database again. Also, if you
271 		// talk to the crew, they berate him for no apparent reason if this isn't clear.
272 		showDescription(TX_MUD3N000);
273 		showText(TX_SPEAKER_MCCOY, TX_MUD3_031);
274 
275 	} else { // Don't allow it (he destroys it by accident)
276 		showText(TX_SPEAKER_MUDD, TX_MUD3_064);
277 		_awayMission->timers[4] = 98;
278 		_awayMission->disableInput = 2;
279 		playMidiMusicTracks(26);
280 		loadActorAnim(OBJECT_MUDD, "s4lbhb", 0xa2, 0x9f);
281 	}
282 }
283 
mudd3Timer4Expired()284 void Room::mudd3Timer4Expired() {
285 	_awayMission->mudd.databaseDestroyed = true;
286 
287 	showText(TX_SPEAKER_MUDD, TX_MUD3_063);
288 	showText(TX_SPEAKER_MCCOY, TX_MUD3_031);
289 
290 	_awayMission->disableInput = false;
291 }
292 
mudd3UseMemoryDiskOnSphere()293 void Room::mudd3UseMemoryDiskOnSphere() {
294 	// ENHANCEMENT: Turn to face south
295 	_awayMission->crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_S;
296 	loadActorStandAnim(OBJECT_KIRK);
297 
298 	if (_awayMission->mudd.databaseDestroyed)
299 		showDescription(TX_MUD3N014);
300 	else if (_awayMission->mudd.translatedAlienLanguage && !_awayMission->mudd.muddErasedDatabase) {
301 		showDescription(TX_MUD3N020);
302 		if (!_awayMission->mudd.gotPointsForDownloadingData) {
303 			_awayMission->mudd.missionScore += 3;
304 			_awayMission->mudd.gotPointsForDownloadingData = true;
305 		}
306 	} else
307 		showDescription(TX_MUD3N019);
308 }
309 
310 
mudd3GetRepairTool()311 void Room::mudd3GetRepairTool() {
312 	if (_awayMission->mudd.tookRepairTool)
313 		showDescription(TX_MUD3N018); // NOTE: unused, since the object disappears, can't be selected again
314 	else {
315 		_awayMission->disableInput = true;
316 		_awayMission->crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_N;
317 		walkCrewmanC(OBJECT_KIRK, 0xba, 0xc1, &Room::mudd3ReachedRepairTool);
318 	}
319 }
320 
mudd3ReachedRepairTool()321 void Room::mudd3ReachedRepairTool() {
322 	_awayMission->crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_N;
323 	loadActorAnimC(OBJECT_KIRK, "kusemn", -1, -1, &Room::mudd3PickedUpRepairTool);
324 }
325 
mudd3PickedUpRepairTool()326 void Room::mudd3PickedUpRepairTool() {
327 	_awayMission->disableInput = false;
328 	loadActorStandAnim(OBJECT_REPAIR_TOOL);
329 	_awayMission->mudd.tookRepairTool = true;
330 	_awayMission->mudd.missionScore++;
331 	giveItem(OBJECT_IDOOVER);
332 }
333 
mudd3LookAtSphere()334 void Room::mudd3LookAtSphere() {
335 	// ENHANCEMENT: Turn to face south
336 	_awayMission->crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_S;
337 	loadActorStandAnim(OBJECT_KIRK);
338 
339 	showDescription(TX_MUD3N015);
340 }
341 
mudd3WalkToNorthDoor()342 void Room::mudd3WalkToNorthDoor() {
343 	_roomVar.mudd.walkingToDoor = true;
344 	_awayMission->disableInput = true;
345 	walkCrewman(OBJECT_KIRK, 0xb8, 0x70);
346 }
347 
mudd3TouchedHotspot0()348 void Room::mudd3TouchedHotspot0() { // Triggers north door
349 	if (_roomVar.mudd.walkingToDoor) {
350 		playVoc("SMADOOR3");
351 		loadActorAnim(OBJECT_NORTH_DOOR, "s4lbdo", 0xba, 0x6f);
352 	}
353 }
354 
mudd3WalkToEastDoor()355 void Room::mudd3WalkToEastDoor() {
356 	_roomVar.mudd.walkingToDoor = true;
357 	_awayMission->disableInput = true;
358 	walkCrewman(OBJECT_KIRK, 0x121, 0x81);
359 }
360 
mudd3TouchedHotspot1()361 void Room::mudd3TouchedHotspot1() {
362 	if (_roomVar.mudd.walkingToDoor) {
363 		playVoc("SMADOOR3");
364 	}
365 }
366 
mudd3LookAtKirk()367 void Room::mudd3LookAtKirk() {
368 	if (!_awayMission->mudd.muddInDatabaseRoom)
369 		showDescription(TX_MUD3N005);
370 	else
371 		showDescription(TX_MUD3N004);
372 }
373 
mudd3LookAtSpock()374 void Room::mudd3LookAtSpock() {
375 	if (!_awayMission->mudd.muddInDatabaseRoom)
376 		showDescription(TX_MUD3N012);
377 	else
378 		showDescription(TX_MUD3N002);
379 }
380 
mudd3LookAtMccoy()381 void Room::mudd3LookAtMccoy() {
382 	if (!_awayMission->mudd.muddInDatabaseRoom)
383 		showDescription(TX_MUD3N010);
384 	else
385 		showDescription(TX_MUD3N009);
386 }
387 
mudd3LookAtRedshirt()388 void Room::mudd3LookAtRedshirt() {
389 	if (!_awayMission->mudd.muddInDatabaseRoom)
390 		showDescription(TX_MUD3N007);
391 	else
392 		showDescription(TX_MUD3N006);
393 }
394 
mudd3LookAtMudd()395 void Room::mudd3LookAtMudd() {
396 	showDescription(TX_MUD3N003);
397 }
398 
mudd3TalkToKirk()399 void Room::mudd3TalkToKirk() {
400 	if (!_awayMission->mudd.muddInDatabaseRoom) {
401 		showText(TX_SPEAKER_KIRK,  TX_MUD3_014);
402 		showText(TX_SPEAKER_SPOCK, TX_MUD3_057);
403 		showText(TX_SPEAKER_MCCOY, TX_MUD3_025);
404 	} else
405 		showText(TX_SPEAKER_KIRK, TX_MUD3_002);
406 }
407 
mudd3TalkToSpock()408 void Room::mudd3TalkToSpock() {
409 	if (!_awayMission->mudd.muddInDatabaseRoom) {
410 		showText(TX_SPEAKER_SPOCK, TX_MUD3_055);
411 		showText(TX_SPEAKER_MCCOY, TX_MUD3_033);
412 		showText(TX_SPEAKER_KIRK,  TX_MUD3_011);
413 	} else
414 		showText(TX_SPEAKER_SPOCK, TX_MUD3_019);
415 }
416 
mudd3TalkToMccoy()417 void Room::mudd3TalkToMccoy() {
418 	if (!_awayMission->mudd.muddInDatabaseRoom)
419 		showText(TX_SPEAKER_MCCOY, TX_MUD3_023);
420 	else {
421 		showText(TX_SPEAKER_MCCOY, TX_MUD3_030);
422 		showText(TX_SPEAKER_MUDD,  TX_MUD3_062);
423 	}
424 }
425 
mudd3TalkToRedshirt()426 void Room::mudd3TalkToRedshirt() {
427 	if (!_awayMission->mudd.muddInDatabaseRoom) {
428 		showText(TX_SPEAKER_BUCHERT, TX_MUD3_070);
429 		showText(TX_SPEAKER_KIRK,    TX_MUD3_016);
430 		showText(TX_SPEAKER_BUCHERT, TX_MUD3_071);
431 	} else
432 		showText(TX_SPEAKER_BUCHERT, TX_MUD3_067);
433 }
434 
mudd3TalkToMudd()435 void Room::mudd3TalkToMudd() {
436 	// ENHANCEMENT: the 2nd part of the if condition is new; whether he physically
437 	// destroys the database or does through software, he should give this reaction.
438 	if (_awayMission->mudd.databaseDestroyed || _awayMission->mudd.muddErasedDatabase) {
439 		showText(TX_SPEAKER_MUDD,    TX_MUD3_060);
440 		showText(TX_SPEAKER_MCCOY,   TX_MUD3_029);
441 		showText(TX_SPEAKER_MUDD,    TX_MUD3_061);
442 		showText(TX_SPEAKER_KIRK,    TX_MUD3_013);
443 		showText(TX_SPEAKER_MUDD,    TX_MUD3_058);
444 		showText(TX_SPEAKER_SPOCK,   TX_MUD3C001);
445 		showText(TX_SPEAKER_BUCHERT, TX_MUD3_069);
446 		showText(TX_SPEAKER_MUDD,    TX_MUD3_059);
447 		showText(TX_SPEAKER_KIRK,    TX_MUD3_005);
448 	}
449 }
450 
mudd3UseMedkit()451 void Room::mudd3UseMedkit() {
452 	showText(TX_SPEAKER_MCCOY, TX_MUD3_020);
453 }
454 
455 }
456