2019-10-30 01:42:47 +02:00

556 lines
14 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "startrek/room.h"
namespace StarTrek {
// BUG: under certain circumstances, the klingons just stop firing?
void Room::demon1Tick1() {
playVoc("DEM1LOOP");
if (!_awayMission->demon.beatKlingons)
playMidiMusicTracks(1, -1);
if (_awayMission->demon.enteredFrom == 1) { // Entered from south
_awayMission->crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_N;
_awayMission->crewDirectionsAfterWalk[OBJECT_SPOCK] = DIR_N;
_awayMission->crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_N;
_awayMission->crewDirectionsAfterWalk[OBJECT_REDSHIRT] = DIR_N;
} else if (_awayMission->demon.enteredFrom == 2) { // Entered from north?
_awayMission->crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_S;
_awayMission->crewDirectionsAfterWalk[OBJECT_SPOCK] = DIR_S;
_awayMission->crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_S;
_awayMission->crewDirectionsAfterWalk[OBJECT_REDSHIRT] = DIR_S;
}
if (!_awayMission->demon.beatKlingons) {
_awayMission->disableWalking = true;
_awayMission->timers[2] = 50;
} else {
loadActorAnim(8, "klg1d2", 0x120, 0x82, 0);
if (!_awayMission->demon.tookKlingonHand)
loadActorAnim(13, "klghnd", 0x10b, 0x8e, 0);
loadActorAnim(9, "klg2d2", 0xaa, 0x7c, 0);
loadActorAnim(10, "klg3d2", 0, 0, 0);
_roomVar.demon.klingonShot[0] = true;
_roomVar.demon.klingonShot[1] = true;
_roomVar.demon.klingonShot[2] = true;
_roomVar.demon.numKlingonsKilled = 3;
}
}
void Room::demon1WalkToCave() {
if (_roomVar.demon.numKlingonsKilled != 3)
return;
walkCrewman(OBJECT_KIRK, 0xa3, 0x56, 2);
}
void Room::demon1TouchedTopWarp() {
if (_awayMission->demon.warpsDisabled)
return;
loadRoomIndex(2, 1);
}
void Room::demon1TouchedBottomWarp() {
if (_awayMission->demon.warpsDisabled)
return;
loadRoomIndex(0, 0);
}
void Room::demon1Timer2Expired() {
if (_awayMission->demon.beatKlingons)
return;
_awayMission->demon.field37 = 1;
_awayMission->demon.beatKlingons = true;
_awayMission->demon.warpsDisabled = true;
_awayMission->timers[0] = 5;
_awayMission->timers[3] = 2;
_awayMission->timers[1] = 100;
loadActorAnim(8, "klg1u", 0x120, 0x82, 0);
}
void Room::demon1Timer0Expired() {
loadActorAnim(9, "klg2u", 0xaa, 0x7c, 0);
}
void Room::demon1Timer3Expired() {
loadActorAnim(10, "klg3u", 0xdb, 0x6d, 0);
}
void Room::demon1Timer1Expired() {
int shooter;
Common::String anim;
if (!_roomVar.demon.klingonShot[0]) {
anim = "klg1f";
shooter = 8;
switch (_roomVar.demon.attackIndex) {
case 0:
strcpy(_roomVar.demon.d6, "klg1fr");
break;
case 1:
strcpy(_roomVar.demon.d6, "klg1fm");
break;
case 2:
strcpy(_roomVar.demon.d6, "klg1fs");
break;
case 3:
strcpy(_roomVar.demon.d6, "klg1fk");
break;
default:
// TODO
return;
}
} else if (!_roomVar.demon.klingonShot[1]) {
anim = "klg2f";
shooter = 9;
switch (_roomVar.demon.attackIndex) {
case 0:
strcpy(_roomVar.demon.d6, "klg2fr");
break;
case 1:
strcpy(_roomVar.demon.d6, "klg2fm");
break;
case 2:
strcpy(_roomVar.demon.d6, "klg2fs");
break;
case 3:
strcpy(_roomVar.demon.d6, "klg2fk");
break;
default:
// TODO
return;
}
} else {
anim = "klg3f";
shooter = 10;
switch (_roomVar.demon.attackIndex) {
case 0:
strcpy(_roomVar.demon.d6, "klg3fr");
break;
case 1:
strcpy(_roomVar.demon.d6, "klg3fm");
break;
case 2:
strcpy(_roomVar.demon.d6, "klg3fs");
break;
case 3:
strcpy(_roomVar.demon.d6, "klg3fk");
break;
default:
// TODO
return;
}
}
loadActorAnim2(shooter, anim, -1, -1, 2);
}
void Room::demon1KlingonFinishedAimingWeapon() {
loadActorAnim(11, _roomVar.demon.d6, 0, 0, 0);
playSoundEffectIndex(0x06);
_roomVar.demon.attackIndex++;
int crewman = OBJECT_REDSHIRT;
if (_roomVar.demon.attackIndex == 1) {
loadActorAnim2(OBJECT_REDSHIRT, "rstunn", -1, -1, 0);
crewman = OBJECT_REDSHIRT;
} else if (_roomVar.demon.attackIndex == 2) {
loadActorAnim2(OBJECT_SPOCK, "sstunn", -1, -1, 0);
crewman = OBJECT_SPOCK;
} else if (_roomVar.demon.attackIndex == 3) {
loadActorAnim2(OBJECT_MCCOY, "mstune", -1, -1, 0);
crewman = OBJECT_MCCOY;
} else if (_roomVar.demon.attackIndex == 4) {
loadActorAnim2(OBJECT_KIRK, "kstunn", -1, -1, 1);
crewman = OBJECT_KIRK;
}
_awayMission->crewDirectionsAfterWalk[crewman] = DIR_N;
_awayMission->crewGetupTimers[crewman] = 650;
_awayMission->crewDownBitset |= (1 << crewman);
_awayMission->timers[1] = 100;
}
void Room::demon1KirkShot() {
showDescription(0, true);
showGameOverMenu();
}
void Room::demon1UsePhaserOnAnything() {
if (_roomVar.demon.numKlingonsKilled == 3)
showText(TX_SPEAKER_MCCOY, 11, true);
}
void Room::demon1UsePhaserOnKlingon1() {
if (_roomVar.demon.klingonShot[0])
return;
_awayMission->disableInput = 1;
_roomVar.demon.klingonShot[0] = true;
if (_roomVar.demon.kirkShooting) {
demon1ShootKlingon1();
} else {
loadActorAnim2(OBJECT_KIRK, "kfiren", -1, -1, 3);
_roomVar.demon.kirkShooting = true;
}
}
void Room::demon1ShootKlingon1() {
_roomVar.demon.numKlingonsKilled++;
if (_roomVar.demon.numKlingonsKilled == 3) {
_awayMission->timers[1] = 0;
_awayMission->timers[5] = 180;
_awayMission->timers[6] = 1;
_awayMission->demon.warpsDisabled = false;
_awayMission->disableWalking = false;
}
loadActorAnim(12, "s0ks1", 0, 0, 0);
playSoundEffectIndex(0x06);
playVoc("EFX19");
loadActorAnim2(8, "klg1d", 0x120, 0x84, 7);
}
void Room::demon1KlingonDropsHand() {
loadActorAnim(13, "klghnd", 0x10b, 0x8e, 0);
_awayMission->disableInput = 0;
_awayMission->timers[1] = 0;
showDescription(20, true);
if (_awayMission->crewDownBitset & (1 << OBJECT_REDSHIRT))
return;
showText(TX_SPEAKER_EVERTS, 25, true);
if (_roomVar.demon.numKlingonsKilled == 3)
return;
showText(TX_SPEAKER_KLINGON, 23 + FOLLOWUP_MESSAGE_OFFSET, true);
_awayMission->timers[1] = 1;
}
void Room::demon1UsePhaserOnKlingon2() {
if (_roomVar.demon.klingonShot[1])
return;
_awayMission->disableInput = 1;
_roomVar.demon.klingonShot[1] = true;
if (_roomVar.demon.kirkShooting) {
demon1ShootKlingon2();
} else {
loadActorAnim2(OBJECT_KIRK, "kfiren", -1, -1, 4);
_roomVar.demon.kirkShooting = true;
}
}
void Room::demon1ShootKlingon2() {
_roomVar.demon.numKlingonsKilled++;
if (_roomVar.demon.numKlingonsKilled == 3) {
_awayMission->timers[1] = 0;
_awayMission->timers[5] = 180;
_awayMission->timers[6] = 1;
_awayMission->demon.warpsDisabled = false;
_awayMission->disableWalking = false;
}
loadActorAnim(12, "s0ks2", 0, 0, 0);
playSoundEffectIndex(0x06);
loadActorAnim2(9, "klg2d", 0xaa, 0x7c, 0);
_awayMission->disableInput = 0;
}
void Room::demon1UsePhaserOnKlingon3() {
if (_roomVar.demon.klingonShot[2])
return;
_awayMission->disableInput = 1;
_roomVar.demon.klingonShot[2] = true;
if (_roomVar.demon.kirkShooting) {
demon1ShootKlingon3();
} else {
loadActorAnim2(OBJECT_KIRK, "kfiren", -1, -1, 5);
_roomVar.demon.kirkShooting = true;
}
}
void Room::demon1ShootKlingon3() {
_roomVar.demon.numKlingonsKilled++;
if (_roomVar.demon.numKlingonsKilled == 3) {
_awayMission->timers[1] = 0;
_awayMission->timers[5] = 180;
_awayMission->timers[6] = 1;
_awayMission->demon.warpsDisabled = false;
_awayMission->disableWalking = false;
}
loadActorAnim(12, "s0ks3", 0, 0, 0);
playSoundEffectIndex(0x06);
loadActorAnim2(10, "klg3d", 0, 0, 0);
_awayMission->disableInput = 0;
}
// Timer 6 expired
void Room::demon1AllKlingonsDead() {
_awayMission->crewGetupTimers[OBJECT_KIRK] = 45;
_awayMission->crewGetupTimers[OBJECT_SPOCK] = 45;
_awayMission->crewGetupTimers[OBJECT_MCCOY] = 45;
_awayMission->crewGetupTimers[OBJECT_REDSHIRT] = 45;
}
void Room::demon1Timer5Expired() {
if (_awayMission->crewDownBitset != 0)
return;
showText(TX_SPEAKER_UHURA, 77, true);
showText(TX_SPEAKER_KIRK, 3, true);
showText(TX_SPEAKER_UHURA, 78, true);
showText(TX_SPEAKER_KIRK, 2, true);
showText(TX_SPEAKER_SPOCK, 20, true);
showText(TX_SPEAKER_KIRK, 4, true);
showText(TX_SPEAKER_SPOCK, 21, true);
}
void Room::demon1UseMTricorderOnKlingon() {
loadActorAnim2(OBJECT_MCCOY, "mscann", -1, -1, 0);
playSoundEffectIndex(0x04);
showText(TX_SPEAKER_MCCOY, 12, true);
}
void Room::demon1UseSTricorderOnTulips() {
loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
playSoundEffectIndex(0x04);
showText(TX_SPEAKER_SPOCK, 7, true);
}
void Room::demon1UseSTricorderOnPods() {
loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
playSoundEffectIndex(0x04);
showText(TX_SPEAKER_SPOCK, 8, true);
}
void Room::demon1UseSTricorderOnCattails() {
loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
playSoundEffectIndex(0x04);
showText(TX_SPEAKER_SPOCK, 5, true);
}
void Room::demon1UseSTricorderOnFerns() {
loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
playSoundEffectIndex(0x04);
showText(TX_SPEAKER_SPOCK, 6, true);
}
void Room::demon1UseSTricorderOnHand() {
loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
playSoundEffectIndex(0x04);
showText(TX_SPEAKER_SPOCK, 17, true);
}
void Room::demon1UseSTricorderOnKlingon1() {
// BUGFIX: Original game sets up the stack for this function call, but doesn't
// actually call the function...
loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
playSoundEffectIndex(0x04);
if (_roomVar.demon.numKlingonsKilled == 3 && !_awayMission->demon.tookKlingonHand && _rdfData[0xcf] != 1) {
showText(TX_SPEAKER_SPOCK, 18, true);
_rdfData[0xcf] = 1;
} else {
showText(TX_SPEAKER_SPOCK, 19, true);
}
}
void Room::demon1UseSTricorderOnKlingon2Or3() {
loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
playSoundEffectIndex(0x04);
showText(TX_SPEAKER_SPOCK, 19, true);
}
void Room::demon1UseMTricorderOnKirk() {
if (_awayMission->crewDownBitset & (1 << OBJECT_KIRK))
demon1UseMTricorderOnCrewman();
}
void Room::demon1UseMTricorderOnSpock() {
if (_awayMission->crewDownBitset & (1 << OBJECT_SPOCK))
demon1UseMTricorderOnCrewman();
}
void Room::demon1UseMTricorderOnRedshirt() {
if (_awayMission->crewDownBitset & (1 << OBJECT_REDSHIRT))
demon1UseMTricorderOnCrewman();
}
void Room::demon1UseMTricorderOnCrewman() {
loadActorAnim2(OBJECT_MCCOY, "mscann", -1, -1, 0);
playSoundEffectIndex(0x04);
showText(TX_SPEAKER_MCCOY, 9, true);
}
void Room::demon1GetHand() {
if (_roomVar.demon.numKlingonsKilled != 3)
return;
walkCrewman(OBJECT_KIRK, 0x104, 0x8e, 1);
}
void Room::demon1ReachedHand() {
loadActorAnim2(OBJECT_KIRK, "s5r1kg", -1, -1, 6);
}
void Room::demon1PickedUpHand() {
loadActorStandAnim(13);
_awayMission->demon.missionScore += 3;
loadActorStandAnim(OBJECT_KIRK);
_awayMission->timers[4] = 2;
}
// Timer 4 expired
void Room::demon1FinishedGettingHand() {
if (_awayMission->demon.tookKlingonHand)
showDescription(5, true);
else {
_awayMission->demon.tookKlingonHand = true;
giveItem(OBJECT_IHAND);
showDescription(7, true);
}
}
void Room::demon1LookAtKlingon() {
showDescription(4, true);
}
void Room::demon1LookAtCattails() {
showDescription(18, true);
}
void Room::demon1LookAtTulips() {
showDescription(10, true);
}
void Room::demon1LookAtPods() {
showDescription(19, true);
}
void Room::demon1LookAtFerns() {
showDescription(9, true);
}
void Room::demon1LookAtStream() {
showDescription(11, true);
}
void Room::demon1LookAtMine() {
showDescription(21, true);
}
void Room::demon1LookAtMountain() {
showDescription(16, true);
}
void Room::demon1LookAtHand() {
showDescription(23, true);
}
void Room::demon1LookAnywhere() {
showDescription(17, true);
}
void Room::demon1LookAtKirk() {
if (_awayMission->crewDownBitset & (1 << OBJECT_KIRK))
showDescription(12, true);
else
showDescription(3, true);
}
void Room::demon1LookAtSpock() {
if (_awayMission->crewDownBitset & (1 << OBJECT_SPOCK))
showDescription(15, true);
else
showDescription(8, true);
}
void Room::demon1LookAtMcCoy() {
if (_awayMission->crewDownBitset & (1 << OBJECT_MCCOY))
showDescription(13, true);
else
showDescription(1, true);
}
void Room::demon1LookAtRedshirt() {
if (_awayMission->crewDownBitset & (1 << OBJECT_REDSHIRT))
showDescription(14, true);
else
showDescription(2, true);
}
void Room::demon1TalkToKirk() {
if (_awayMission->crewDownBitset & (1 << OBJECT_KIRK))
demon1TalkToUnconsciousCrewman();
else if (_roomVar.demon.numKlingonsKilled == 3)
showText(TX_SPEAKER_KIRK, 1, true);
}
void Room::demon1TalkToSpock() {
if (_awayMission->crewDownBitset & (1 << OBJECT_SPOCK))
demon1TalkToUnconsciousCrewman();
else {
showText(TX_SPEAKER_SPOCK, 22, true);
showText(TX_SPEAKER_MCCOY, 13, true);
showText(TX_SPEAKER_SPOCK, 24, true);
showText(TX_SPEAKER_MCCOY, 14, true);
}
}
void Room::demon1TalkToMcCoy() {
if (_awayMission->crewDownBitset & (1 << OBJECT_MCCOY))
demon1TalkToUnconsciousCrewman();
else {
showText(TX_SPEAKER_MCCOY, 15, true);
showText(TX_SPEAKER_SPOCK, 23, true);
}
}
void Room::demon1TalkToRedshirt() {
if (_awayMission->crewDownBitset & (1 << OBJECT_REDSHIRT))
demon1TalkToUnconsciousCrewman();
else
showText(TX_SPEAKER_EVERTS, 26, true);
}
// FIXME: this doesn't happen in actual game? (does the event get blocked from higher up?)
void Room::demon1TalkToUnconsciousCrewman() {
const char *text[] = {
nullptr,
"Zzzzz....",
""
};
showRoomSpecificText(text);
}
}