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 namespace StarTrek {
26
demon3Tick1()27 void Room::demon3Tick1() {
28 playVoc("DEM3LOOP");
29 loadActorAnim(8, "light", 0xab, 0x03, 0);
30
31 _roomVar.demon.boulder1Shot = true;
32 if (!_awayMission->demon.boulder1Gone) {
33 loadActorAnim(9, "bldr1", 0x26, 0, 0);
34 _roomVar.demon.boulder1Shot = false;
35 }
36 if (!_awayMission->demon.boulder2Gone) {
37 loadActorAnim(10, "bldr2", 0x22, 0, 0);
38 }
39 if (!_awayMission->demon.boulder3Gone) {
40 loadActorAnim(11, "bldr3", 0x22, 0, 0);
41 }
42 if (!_awayMission->demon.boulder4Gone) {
43 loadActorAnim(12, "bldr4", 0x22, 0, 0);
44 }
45
46 if (_awayMission->demon.doorOpened) {
47 loadActorAnim(14, "door2", 0x82, 0x0c, 0);
48 } else {
49 loadMapFile("demon3a");
50 }
51
52 if (!_awayMission->demon.healedMiner && _awayMission->demon.boulder4Gone)
53 loadActorAnim(13, "miner", 0xda, 0x6c, 0);
54 if (_awayMission->redshirtDead && !_awayMission->demon.field45)
55 loadActorAnim(OBJECT_REDSHIRT, "deadre", 0x46, 0xa0, 0);
56
57 if (_awayMission->demon.field41 == 0)
58 _awayMission->demon.field41++;
59
60 if (!_awayMission->demon.field56) {
61 _awayMission->demon.field56 = true;
62 playMidiMusicTracks(0, -1);
63 }
64 }
65
66 // Boulder falling over
demon3Timer0Expired()67 void Room::demon3Timer0Expired() {
68 _roomVar.demon.boulder1Shot = true;
69 loadActorAnim2(9, "drbldr", 0x26, 0, 0);
70 _awayMission->timers[1] = 13;
71 _awayMission->demon.boulder1Gone = true;
72 _awayMission->demon.numBouldersGone++;
73 _awayMission->disableInput = true;
74 playMidiMusicTracks(2, -1);
75 playVoc("BOULDERK");
76 }
77
78 // Redshirt pushing Kirk away
demon3Timer1Expired()79 void Room::demon3Timer1Expired() {
80 _roomVar.demon.kirkPhaserOut = false;
81 loadActorAnim2(OBJECT_REDSHIRT, "redkil", 0x46, 0xa0, 0);
82 loadActorAnim2(OBJECT_KIRK, "redkil", 0x46, 0xa0, 1);
83 }
84
85 // Door just opened
demon3Timer3Expired()86 void Room::demon3Timer3Expired() {
87 if (_awayMission->demon.repairedHand) {
88 showDescription(8, true);
89 loadActorAnim(14, "door", 0x82, 0xc, 0);
90 loadMapFile("demon3");
91 _awayMission->demon.doorOpened = true;
92 _awayMission->demon.missionScore += 2;
93 } else {
94 showDescription(7, true);
95 }
96 }
97
demon3FinishedAnimation1()98 void Room::demon3FinishedAnimation1() {
99 loadActorAnim2(OBJECT_KIRK, "kstnds", 0xee, 0xa6, 0);
100 loadActorAnim2(OBJECT_REDSHIRT, "deadre", 0x46, 0xa0, 0);
101 loadActorStandAnim(OBJECT_SPOCK);
102 walkCrewman(OBJECT_MCCOY, 0x9c, 0xb2, 5);
103 _roomVar.demon.inFiringPosition = false;
104 _awayMission->redshirtDead = true;
105 }
106
107 // Just destroyed boulder 4 (revealing the miner)
demon3FinishedAnimation2()108 void Room::demon3FinishedAnimation2() {
109 loadActorAnim(13, "miner", 0xda, 0x6c, 0);
110 }
111
demon3FinishedWalking5()112 void Room::demon3FinishedWalking5() {
113 loadActorAnim2(OBJECT_MCCOY, "mscanw", -1, -1, 0);
114 playSoundEffectIndex(0x04);
115 showText(TX_SPEAKER_MCCOY, 19, true);
116
117 _awayMission->disableInput = false;
118 }
119
demon3McCoyInFiringPosition()120 void Room::demon3McCoyInFiringPosition() {
121 loadActorAnim2(OBJECT_MCCOY, "mwaitn", 0xd6, 0xb8, 0);
122 _roomVar.demon.mccoyInPosition = true;
123 demon3CrewmanInFiringPosition();
124 }
125
demon3SpockInFiringPosition()126 void Room::demon3SpockInFiringPosition() {
127 loadActorAnim2(OBJECT_SPOCK, "swaitn", 0xae, 0xb4, 0);
128 _roomVar.demon.spockInPosition = true;
129 demon3CrewmanInFiringPosition();
130 }
131
demon3RedShirtInFiringPosition()132 void Room::demon3RedShirtInFiringPosition() {
133 loadActorAnim2(OBJECT_REDSHIRT, "rwaitn", 0x46, 0xa0, 0);
134 _roomVar.demon.redshirtInPosition = true;
135 demon3CrewmanInFiringPosition();
136 }
137
demon3KirkInFiringPosition()138 void Room::demon3KirkInFiringPosition() {
139 loadActorAnim2(OBJECT_KIRK, "kwaitn", 0x79, 0xa0, 0);
140 _roomVar.demon.kirkInPosition = true;
141 demon3CrewmanInFiringPosition();
142 }
143
demon3CrewmanInFiringPosition()144 void Room::demon3CrewmanInFiringPosition() {
145 if (_roomVar.demon.kirkInPosition && _roomVar.demon.spockInPosition && _roomVar.demon.mccoyInPosition && (_awayMission->redshirtDead || _roomVar.demon.redshirtInPosition))
146 demon3PullOutPhaserAndFireAtBoulder();
147 }
148
demon3PullOutPhaserAndFireAtBoulder()149 void Room::demon3PullOutPhaserAndFireAtBoulder() {
150 if (_roomVar.demon.kirkPhaserOut)
151 demon3FireAtBoulder();
152 else {
153 loadActorAnim2(OBJECT_KIRK, "kfiren", -1, -1, 4);
154 _roomVar.demon.kirkPhaserOut = true;
155 }
156 }
157
demon3FireAtBoulder()158 void Room::demon3FireAtBoulder() {
159 _roomVar.demon.kirkInPosition = false;
160 _roomVar.demon.spockInPosition = false;
161 _roomVar.demon.mccoyInPosition = false;
162 _roomVar.demon.redshirtInPosition = false;
163 _roomVar.demon.shootingBoulder = false;
164
165 switch (_roomVar.demon.boulderBeingShot) {
166 case 1: // FIXME: animation overlaps on Kirk, probably due to sprite sorting inaccuracy
167 loadActorAnim2(9, "sbldr1", 0x22, 0, 0);
168 break;
169 case 2:
170 loadActorAnim2(10, "sbldr2", 0x22, 0, 0);
171 break;
172 case 3:
173 loadActorAnim2(11, "sbldr3", 0x22, 0, 0);
174 break;
175 case 4:
176 loadActorAnim2(12, "sbldr4", 0x22, 0, 2);
177 break;
178 default: {
179 // This should never happen (in the original game, this would cause a stack
180 // misalignment?
181 const char *text[] = {
182 "wes",
183 "There is a boulder check error.",
184 ""
185 };
186 showRoomSpecificText(text);
187 break;
188 }
189 }
190
191 loadActorAnim(17, _roomVar.demon.boulderAnim, 0, 0, 0);
192 playSoundEffectIndex(0x06);
193 if (!_roomVar.demon.boulder1Shot)
194 _awayMission->timers[0] = 1;
195 _awayMission->disableInput = false;
196 }
197
demon3UsePhaserOnRedshirt()198 void Room::demon3UsePhaserOnRedshirt() {
199 if (!_awayMission->redshirtDead)
200 return;
201 showText(TX_SPEAKER_MCCOY, 13, true);
202 }
203
demon3UseStunPhaserOnBoulder()204 void Room::demon3UseStunPhaserOnBoulder() {
205 showText(TX_SPEAKER_SPOCK, 7, true);
206 }
207
demon3UsePhaserOnBoulder1()208 void Room::demon3UsePhaserOnBoulder1() {
209 if (_roomVar.demon.shootingBoulder || _awayMission->demon.boulder1Gone)
210 return;
211 _awayMission->demon.boulder1Gone = true;
212 _awayMission->demon.numBouldersGone++;
213 _roomVar.demon.boulderBeingShot = 1;
214 _roomVar.demon.boulder1Shot = true;
215 strcpy(_roomVar.demon.boulderAnim, "s0r3s2");
216 demon3BoulderCommon();
217 }
218
demon3UsePhaserOnBoulder2()219 void Room::demon3UsePhaserOnBoulder2() {
220 if (_roomVar.demon.shootingBoulder || _awayMission->demon.boulder2Gone)
221 return;
222 _awayMission->demon.boulder2Gone = true;
223 _awayMission->demon.numBouldersGone++;
224 _roomVar.demon.boulderBeingShot = 2;
225 strcpy(_roomVar.demon.boulderAnim, "s0r3s3");
226 demon3BoulderCommon();
227 }
228
demon3UsePhaserOnBoulder3()229 void Room::demon3UsePhaserOnBoulder3() {
230 if (_awayMission->demon.boulder1Gone) {
231 if (_roomVar.demon.shootingBoulder || _awayMission->demon.boulder3Gone)
232 return;
233 _awayMission->demon.boulder3Gone = true;
234 _awayMission->demon.numBouldersGone++;
235 _roomVar.demon.boulderBeingShot = 3;
236 strcpy(_roomVar.demon.boulderAnim, "s0r3s1");
237 demon3BoulderCommon();
238 } else {
239 showText(TX_SPEAKER_SPOCK, 6, true);
240 }
241 }
242
demon3UsePhaserOnBoulder4()243 void Room::demon3UsePhaserOnBoulder4() {
244 if (_awayMission->demon.boulder2Gone) {
245 if (_roomVar.demon.shootingBoulder || _awayMission->demon.boulder4Gone)
246 return;
247 _awayMission->demon.boulder4Gone = true;
248 _awayMission->demon.numBouldersGone++;
249 _roomVar.demon.boulderBeingShot = 4;
250 strcpy(_roomVar.demon.boulderAnim, "s0r3s4");
251 _awayMission->demon.foundMiner = true;
252 demon3BoulderCommon();
253 } else {
254 // BUGFIX: In the original, the audio didn't play, despite the file existing (and
255 // despite it being used for the boulder on the left).
256 showText(TX_SPEAKER_SPOCK, 6, true);
257 }
258 }
259
demon3BoulderCommon()260 void Room::demon3BoulderCommon() {
261 _awayMission->disableInput = true;
262 Common::Point pos = getActorPos(OBJECT_KIRK);
263 if (!(pos.x == 0x79 && pos.y == 0xa0)) {
264 _roomVar.demon.inFiringPosition = false;
265 _roomVar.demon.kirkPhaserOut = false;
266 }
267
268 if (_roomVar.demon.inFiringPosition) {
269 demon3PullOutPhaserAndFireAtBoulder();
270 } else {
271 showText(TX_SPEAKER_KIRK, 1, true);
272
273 walkCrewman(OBJECT_KIRK, 0x79, 0xa0, 1);
274 walkCrewman(OBJECT_SPOCK, 0xae, 0xb4, 2);
275 walkCrewman(OBJECT_MCCOY, 0xd6, 0xb8, 3);
276 if (!_awayMission->redshirtDead)
277 walkCrewman(OBJECT_REDSHIRT, 0x46, 0xa0, 4);
278
279 _roomVar.demon.shootingBoulder = true;
280 _roomVar.demon.inFiringPosition = true;
281 }
282 }
283
demon3UseSTricorderOnMiner()284 void Room::demon3UseSTricorderOnMiner() {
285 loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
286 playSoundEffectIndex(0x04);
287 showText(TX_SPEAKER_SPOCK, 8, true);
288 }
289
demon3UseSTricorderOnPanel()290 void Room::demon3UseSTricorderOnPanel() {
291 loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
292 playSoundEffectIndex(0x04);
293 showText(TX_SPEAKER_SPOCK, 9, true);
294 }
295
demon3UseSTricorderOnBoulder()296 void Room::demon3UseSTricorderOnBoulder() {
297 if (_awayMission->demon.foundMiner)
298 return;
299 loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
300 playSoundEffectIndex(0x04);
301 showText(TX_SPEAKER_SPOCK, 10, true);
302 }
303
demon3UseMTricorderOnBoulder()304 void Room::demon3UseMTricorderOnBoulder() {
305 if (_awayMission->demon.foundMiner)
306 return;
307 loadActorAnim2(OBJECT_MCCOY, "mscann", -1, -1, 0);
308 playSoundEffectIndex(0x04);
309 showText(TX_SPEAKER_MCCOY, 20, true);
310 }
311
demon3UseCrewmanOnPanel()312 void Room::demon3UseCrewmanOnPanel() {
313 if (_awayMission->demon.numBouldersGone != 4 || _awayMission->redshirtDead)
314 return;
315 showText(TX_SPEAKER_EVERTS, 31, true);
316 demon3UseRedshirtOnPanel();
317 }
318
demon3UseRedshirtOnPanel()319 void Room::demon3UseRedshirtOnPanel() {
320 if (_awayMission->redshirtDead)
321 return;
322
323 if (_awayMission->demon.numBouldersGone != 4)
324 showText(TX_SPEAKER_EVERTS, 30, true);
325 else
326 walkCrewman(OBJECT_REDSHIRT, 0xd8, 0x70, 8);
327 }
328
demon3RedshirtReachedPanel()329 void Room::demon3RedshirtReachedPanel() {
330 loadActorAnim2(OBJECT_REDSHIRT, "rusehn", -1, -1, 5);
331 }
332
demon3RedshirtUsedPanel()333 void Room::demon3RedshirtUsedPanel() {
334 if (!_awayMission->demon.foundMiner)
335 return;
336
337 _awayMission->demon.field41++;
338 if (_awayMission->demon.field41 == 5) {
339 playVoc("EFX3");
340 showText(TX_SPEAKER_EVERTS, TX_DEM3_A32);
341
342 loadActorAnim2(OBJECT_REDSHIRT, "rkille", -1, -1, 3);
343 playSoundEffectIndex(0x06);
344 _awayMission->redshirtDead = true;
345 _awayMission->demon.field45 = true;
346 } else {
347 const TextRef textTable[] = {
348 5,
349 33,
350 35,
351 34,
352 };
353
354 TextRef text[] = {
355 TX_SPEAKER_EVERTS,
356 TX_NULL,
357 TX_BLANK
358 };
359 text[1] = textTable[_awayMission->demon.field41 - 1];
360 showMultipleTexts(text, true);
361 walkCrewman(OBJECT_REDSHIRT, 0xbe, 0x9b, 0);
362 }
363 }
364
demon3RedshirtElectrocuted()365 void Room::demon3RedshirtElectrocuted() {
366 showText(TX_SPEAKER_MCCOY, 18, true);
367 }
368
demon3UseSTricorderOnDoor()369 void Room::demon3UseSTricorderOnDoor() {
370 loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
371 playSoundEffectIndex(0x04);
372 showText(TX_SPEAKER_SPOCK, 12, true);
373 }
374
demon3UseSTricorderOnAnything()375 void Room::demon3UseSTricorderOnAnything() {
376 loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
377 playSoundEffectIndex(0x04);
378 showText(TX_SPEAKER_SPOCK, 27, true);
379 }
380
demon3UseMTricorderOnDoor()381 void Room::demon3UseMTricorderOnDoor() {
382 loadActorAnim2(OBJECT_SPOCK, "mscann", -1, -1, 0);
383 playSoundEffectIndex(0x04);
384 showText(TX_SPEAKER_MCCOY, 16, true);
385 }
386
demon3UsePhaserOnDoor()387 void Room::demon3UsePhaserOnDoor() {
388 _roomVar.demon.usedPhaserOnDoor++;
389
390 if (_roomVar.demon.usedPhaserOnDoor == 1)
391 showDescription(9, true);
392 else if (_roomVar.demon.usedPhaserOnDoor == 2)
393 showText(TX_SPEAKER_SPOCK, 11, true);
394 }
395
demon3UseHandOnPanel()396 void Room::demon3UseHandOnPanel() {
397 if (_awayMission->demon.numBouldersGone == 4) {
398 if (_awayMission->demon.doorOpened)
399 return;
400 walkCrewman(OBJECT_KIRK, 0xd8, 0x70, 7);
401 } else {
402 showText(TX_SPEAKER_SPOCK, 5, true);
403 }
404 }
405
demon3KirkReachedHandPanel()406 void Room::demon3KirkReachedHandPanel() {
407 loadActorAnim2(OBJECT_KIRK, "kusehn", -1, -1, 6);
408 _awayMission->crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_W;
409 playVoc("MUR4E1");
410 }
411
demon3KirkUsedHandPanel()412 void Room::demon3KirkUsedHandPanel() {
413 loadActorAnim(15, "panel", 0xd6, 0x3d, 0);
414 _awayMission->timers[3] = 10;
415 playVoc("SE0FORCE");
416 }
417
demon3UseMTricorderOnMiner()418 void Room::demon3UseMTricorderOnMiner() {
419 loadActorAnim2(OBJECT_MCCOY, "mscann", -1, -1, 0);
420 playSoundEffectIndex(0x04);
421
422 if (_awayMission->demon.minerDead) {
423 showText(TX_SPEAKER_MCCOY, 22, true);
424 } else {
425 showText(TX_SPEAKER_MCCOY, 23, true);
426 }
427 }
428
demon3UseMedkitOnMiner()429 void Room::demon3UseMedkitOnMiner() {
430 if (_awayMission->demon.healedMiner) {
431 showText(TX_SPEAKER_MCCOY, 15, true);
432 } else {
433 walkCrewman(OBJECT_MCCOY, 0xe6, 0x7b, 6);
434 _roomVar.demon.inFiringPosition = false;
435 _roomVar.demon.kirkPhaserOut = false;
436 }
437 }
438
demon3McCoyReachedMiner()439 void Room::demon3McCoyReachedMiner() {
440 loadActorAnim2(OBJECT_MCCOY, "museln", -1, -1, 7);
441 }
442
demon3McCoyFinishedHealingMiner()443 void Room::demon3McCoyFinishedHealingMiner() {
444 if (_awayMission->demon.minerDead) {
445 showText(TX_SPEAKER_MCCOY, 22, true);
446 } else {
447 showText(TX_SPEAKER_MCCOY, 21, true);
448 _awayMission->demon.healedMiner = true;
449 loadActorAnim2(13, "drmine", 0xda, 0x6c, 0);
450 _awayMission->demon.missionScore += 2;
451 walkCrewman(OBJECT_MCCOY, 0x104, 0x96, 0);
452 }
453 }
454
demon3GetMiner()455 void Room::demon3GetMiner() {
456 showText(TX_SPEAKER_MCCOY, 17, true);
457 }
458
demon3TalkToMiner()459 void Room::demon3TalkToMiner() {
460 if (!_awayMission->demon.healedMiner)
461 return;
462 showText(TX_SPEAKER_KANDREY, TX_DEM3_F21);
463 }
464
demon3TalkToKirk()465 void Room::demon3TalkToKirk() {
466 showText(TX_SPEAKER_KIRK, 2, true);
467 showText(TX_SPEAKER_SPOCK, 29, true);
468 showText(TX_SPEAKER_MCCOY, 26, true);
469 }
470
demon3TalkToSpock()471 void Room::demon3TalkToSpock() {
472 showText(TX_SPEAKER_SPOCK, 28, true);
473 }
474
demon3TalkToMccoy()475 void Room::demon3TalkToMccoy() {
476 if (_awayMission->redshirtDead) {
477 showText(TX_SPEAKER_MCCOY, 14, true);
478 } else {
479 showText(TX_SPEAKER_MCCOY, 25, true);
480 showText(TX_SPEAKER_KIRK, 3, true);
481 showText(TX_SPEAKER_MCCOY, 24, true);
482
483 }
484 }
485
demon3TalkToRedshirt()486 void Room::demon3TalkToRedshirt() {
487 // FIXME: this shouldn't work if he's dead. Should it check higher up whether that's
488 // the case?
489 showText(TX_SPEAKER_EVERTS, 36, true);
490 showText(TX_SPEAKER_KIRK, 4, true);
491 }
492
demon3LookAtKirk()493 void Room::demon3LookAtKirk() {
494 showDescription(4, true);
495 }
496
demon3LookAtSpock()497 void Room::demon3LookAtSpock() {
498 showDescription(1, true);
499 }
500
demon3LookAtMccoy()501 void Room::demon3LookAtMccoy() {
502 showDescription(2, true);
503 }
504
demon3LookAtRedshirt()505 void Room::demon3LookAtRedshirt() {
506 if (_awayMission->redshirtDead) {
507 showDescription(17, true);
508 // NOTE: there's an alternate string that isn't used? (TX_DEM3N018)
509 } else {
510 showDescription(3, true);
511 }
512 }
513
demon3LookAnywhere()514 void Room::demon3LookAnywhere() {
515 showDescription(10, true);
516 }
517
demon3LookAtMiner()518 void Room::demon3LookAtMiner() {
519 if (_awayMission->demon.healedMiner) {
520 showDescription(0, true);
521 } else {
522 showDescription(6, true);
523 }
524 }
525
demon3LookAtBoulder1()526 void Room::demon3LookAtBoulder1() {
527 showDescription(11, true);
528 }
529
demon3LookAtBoulder2()530 void Room::demon3LookAtBoulder2() {
531 showDescription(13, true);
532 }
533
demon3LookAtBoulder3()534 void Room::demon3LookAtBoulder3() {
535 showDescription(13, true);
536 }
537
demon3LookAtBoulder4()538 void Room::demon3LookAtBoulder4() {
539 showDescription(20, true);
540 }
541
demon3LookAtStructure()542 void Room::demon3LookAtStructure() {
543 showDescription(16, true);
544 }
545
demon3LookAtDoor()546 void Room::demon3LookAtDoor() {
547 if (_awayMission->demon.doorOpened) {
548 showDescription(14, true);
549 } else {
550 showDescription(12, true);
551 }
552 }
553
demon3LookAtPanel()554 void Room::demon3LookAtPanel() {
555 showDescription(19, true);
556 }
557
demon3LookAtLight()558 void Room::demon3LookAtLight() {
559 showDescription(15, true);
560 }
561
562 }
563