diff options
author | Matthew Stewart | 2018-06-14 02:19:14 -0400 |
---|---|---|
committer | Eugene Sandulenko | 2018-08-09 08:37:30 +0200 |
commit | 6e322ebfc5279ee16076b07b82a1dc2c44122b26 (patch) | |
tree | 2203059dba594b0871082f063730c0fc1b87db69 /engines/startrek | |
parent | 3d27a9a92cc7bcf88f58aa8f4b2639573bb5e697 (diff) | |
download | scummvm-rg350-6e322ebfc5279ee16076b07b82a1dc2c44122b26.tar.gz scummvm-rg350-6e322ebfc5279ee16076b07b82a1dc2c44122b26.tar.bz2 scummvm-rg350-6e322ebfc5279ee16076b07b82a1dc2c44122b26.zip |
STARTREK: TUG3 (mission 2 finished)
Diffstat (limited to 'engines/startrek')
-rw-r--r-- | engines/startrek/awaymission.h | 20 | ||||
-rw-r--r-- | engines/startrek/module.mk | 1 | ||||
-rw-r--r-- | engines/startrek/room.cpp | 4 | ||||
-rw-r--r-- | engines/startrek/room.h | 40 | ||||
-rw-r--r-- | engines/startrek/rooms/function_map.h | 39 | ||||
-rw-r--r-- | engines/startrek/rooms/tug0.cpp | 21 | ||||
-rw-r--r-- | engines/startrek/rooms/tug2.cpp | 30 | ||||
-rw-r--r-- | engines/startrek/rooms/tug3.cpp | 504 | ||||
-rw-r--r-- | engines/startrek/text.h | 82 |
9 files changed, 711 insertions, 30 deletions
diff --git a/engines/startrek/awaymission.h b/engines/startrek/awaymission.h index aa581d8dd6..b649477b96 100644 --- a/engines/startrek/awaymission.h +++ b/engines/startrek/awaymission.h @@ -99,10 +99,13 @@ struct AwayMission { struct { int16 missionScore; // 0x29 int16 field2b; // 0x2b - int16 field2d; // 0x2d; + int16 field2d; // 0x2d bool engineerConscious; // 0x30 byte field35; // 0x35 bool gotWires; // 0x37 + byte orbitalDecayCounter; // 0x3b + bool bridgeElasiDrewPhasers; // 0x3d + bool talkedToCereth; // 0x3e bool gotJunkPile; // 0x3f bool gotTransmogrifier; // 0x43 bool transporterRepaired; // 0x44 @@ -111,16 +114,27 @@ struct AwayMission { bool bridgeForceFieldDown; // 0x47 bool savedPrisoners; // 0x48 bool haveBomb; // 0x49 - bool field4a; // 0x4a + bool brigElasiPhasersOnKill; // 0x4a byte field4b; // 0x4b byte guard1Status; // 0x4c byte guard2Status; // 0x4d byte field4e; // 0x4e - bool crewmanKilled[4]; // 0x4f + byte crewmanKilled[4]; // 0x4f + byte bridgeElasi1Status; // 0x53 + byte bridgeElasi2Status; // 0x54 + byte bridgeElasi3Status; // 0x55 + byte bridgeElasi4Status; // 0x56 bool brigForceFieldDown; // 0x58 byte field59; // 0x59 byte field5b; // 0x5b + bool elasiSurrendered; // 0x5c byte kirkPhaserDrawn; // 0x5d + + // 1: Decided to shoot them + // 2: Talked, and they surrendered immediately + // 3: They deorbited the ship (and perhps surrendered after) + byte bridgeWinMethod; // 0x5e + bool talkedToBrigCrewman; // 0x5f } tug; }; diff --git a/engines/startrek/module.mk b/engines/startrek/module.mk index b3fed14cca..acf696fbbb 100644 --- a/engines/startrek/module.mk +++ b/engines/startrek/module.mk @@ -29,6 +29,7 @@ MODULE_OBJS = \ rooms/tug0.o \ rooms/tug1.o \ rooms/tug2.o \ + rooms/tug3.o \ diff --git a/engines/startrek/room.cpp b/engines/startrek/room.cpp index cc07488747..844b8c3c7e 100644 --- a/engines/startrek/room.cpp +++ b/engines/startrek/room.cpp @@ -77,6 +77,10 @@ Room::Room(StarTrekEngine *vm, const Common::String &name) : _vm(vm) { _roomActionList = tug2ActionList; _numRoomActions = sizeof(tug2ActionList) / sizeof(RoomAction); } + else if (name == "TUG3") { + _roomActionList = tug3ActionList; + _numRoomActions = sizeof(tug3ActionList) / sizeof(RoomAction); + } else { warning("Room \"%s\" unimplemented", name.c_str()); _numRoomActions = 0; diff --git a/engines/startrek/room.h b/engines/startrek/room.h index 1523f3313b..1127de8cd5 100644 --- a/engines/startrek/room.h +++ b/engines/startrek/room.h @@ -672,6 +672,44 @@ public: void tug2UseMTricorderOnOpenBrig(); void tug2UsePhaserAnywhere(); + // TUG3 + void tug3Tick1(); + void tug3Tick40(); + void tug3LookAnywhere(); + void tug3ElasiSurrendered(); + void tug3UsePhaserAnywhere(); + void tug3ElasiDrawPhasers(); + void tug3UseStunPhaserOnElasi1(); + void tug3UseStunPhaserOnElasi2(); + void tug3UseStunPhaserOnElasi3(); + void tug3UseStunPhaserOnElasi4(); + void tug3UseKillPhaserOnElasi1(); + void tug3UseKillPhaserOnElasi2(); + void tug3UseKillPhaserOnElasi3(); + void tug3UseKillPhaserOnElasi4(); + void tug3ElasiStunnedOrKilled(); + void tug3TalkToElasi1(); + void tug3Elasi1DrewPhaser(); + void tug3Elasi1ShotConsole(); + void tug3Elasi1DrewPhaser2(); + void tug3Elasi1ShotConsoleAndSurrenders(); + void tug3LookAtMccoy(); + void tug3LookAtSpock(); + void tug3LookAtRedshirt(); + void tug3LookAtElasi1(); + void tug3LookAtElasi2(); + void tug3LookAtElasi3(); + void tug3LookAtElasi4(); + void tug3TalkToMccoy(); + void tug3TalkToSpock(); + void tug3TalkToRedshirt(); + void tug3UseCommunicator(); + void tug3Timer0Expired(); + void tug3AllCrewmenDead(); + void tug3Timer1Expired(); + void tug3EndMission(); + void tug3SecurityTeamBeamedIn(); + private: // Room-specific variables. This is memset'ed to 0 when the room is initialized. union { @@ -732,7 +770,7 @@ private: byte shootingObject; // 0x1ec1 byte shootingTarget; bool elasiPhaserOnKill; - byte _1ec4; // 0x1ec4 + byte shootKirkOverride; // 0x1ec4 } tug2; } _roomVar; diff --git a/engines/startrek/rooms/function_map.h b/engines/startrek/rooms/function_map.h index a88214cdfa..0eb8d97afa 100644 --- a/engines/startrek/rooms/function_map.h +++ b/engines/startrek/rooms/function_map.h @@ -650,7 +650,6 @@ RoomAction tug1ActionList[] = { { Action(ACTION_USE, OBJECT_IMEDKIT, 0x20, 0), &Room::tug1UseMedkitOnBridgeDoor }, { Action(ACTION_USE, OBJECT_IMEDKIT, 0x21, 0), &Room::tug1UseMedkitOnBridgeDoor }, { Action(ACTION_USE, OBJECT_IMEDKIT, 0x22, 0), &Room::tug1UseMedkitOnBridgeDoor }, - }; @@ -745,6 +744,44 @@ RoomAction tug2ActionList[] = { { Action(ACTION_USE, OBJECT_IPHASERK, -1, 0), &Room::tug2UsePhaserAnywhere }, }; + +RoomAction tug3ActionList[] = { + { Action(ACTION_TICK, 1, 0, 0), &Room::tug3Tick1 }, + { Action(ACTION_TICK, 40, 0, 0), &Room::tug3Tick40 }, + { Action(ACTION_LOOK, -1, 0, 0), &Room::tug3LookAnywhere }, + { Action(ACTION_USE, OBJECT_IPHASERS, -1, 0), &Room::tug3UsePhaserAnywhere }, + { Action(ACTION_USE, OBJECT_IPHASERK, -1, 0), &Room::tug3UsePhaserAnywhere }, + { Action(ACTION_USE, OBJECT_IPHASERS, 8, 0), &Room::tug3UseStunPhaserOnElasi1 }, + { Action(ACTION_USE, OBJECT_IPHASERS, 9, 0), &Room::tug3UseStunPhaserOnElasi2 }, + { Action(ACTION_USE, OBJECT_IPHASERS, 10, 0), &Room::tug3UseStunPhaserOnElasi3 }, + { Action(ACTION_USE, OBJECT_IPHASERS, 11, 0), &Room::tug3UseStunPhaserOnElasi4 }, + { Action(ACTION_USE, OBJECT_IPHASERK, 8, 0), &Room::tug3UseKillPhaserOnElasi1 }, + { Action(ACTION_USE, OBJECT_IPHASERK, 9, 0), &Room::tug3UseKillPhaserOnElasi2 }, + { Action(ACTION_USE, OBJECT_IPHASERK, 10, 0), &Room::tug3UseKillPhaserOnElasi3 }, + { Action(ACTION_USE, OBJECT_IPHASERK, 11, 0), &Room::tug3UseKillPhaserOnElasi4 }, + { Action(ACTION_FINISHED_ANIMATION, 12, 0, 0), &Room::tug3ElasiStunnedOrKilled }, + { Action(ACTION_TALK, 8, 0, 0), &Room::tug3TalkToElasi1 }, + { Action(ACTION_FINISHED_ANIMATION, 3, 0, 0), &Room::tug3Elasi1DrewPhaser }, + { Action(ACTION_FINISHED_ANIMATION, 4, 0, 0), &Room::tug3Elasi1ShotConsole }, + { Action(ACTION_FINISHED_ANIMATION, 5, 0, 0), &Room::tug3Elasi1DrewPhaser2 }, + { Action(ACTION_FINISHED_ANIMATION, 6, 0, 0), &Room::tug3Elasi1ShotConsoleAndSurrenders }, + { Action(ACTION_LOOK, OBJECT_MCCOY, 0, 0), &Room::tug3LookAtMccoy }, + { Action(ACTION_LOOK, OBJECT_SPOCK, 0, 0), &Room::tug3LookAtSpock }, + { Action(ACTION_LOOK, OBJECT_REDSHIRT, 0, 0), &Room::tug3LookAtRedshirt }, + { Action(ACTION_LOOK, 8, 0, 0), &Room::tug3LookAtElasi1 }, + { Action(ACTION_LOOK, 9, 0, 0), &Room::tug3LookAtElasi2 }, + { Action(ACTION_LOOK, 10, 0, 0), &Room::tug3LookAtElasi3 }, + { Action(ACTION_LOOK, 11, 0, 0), &Room::tug3LookAtElasi4 }, + { Action(ACTION_TALK, OBJECT_MCCOY, 0, 0), &Room::tug3TalkToMccoy }, + { Action(ACTION_TALK, OBJECT_SPOCK, 0, 0), &Room::tug3TalkToSpock }, + { Action(ACTION_TALK, OBJECT_REDSHIRT, 0, 0), &Room::tug3TalkToRedshirt }, + { Action(ACTION_USE, OBJECT_ICOMM, -1, 0), &Room::tug3UseCommunicator }, + { Action(ACTION_TIMER_EXPIRED, 0, 0, 0), &Room::tug3Timer0Expired }, + { Action(ACTION_FINISHED_ANIMATION, 13, 0, 0), &Room::tug3AllCrewmenDead }, + { Action(ACTION_TIMER_EXPIRED, 1, 0, 0), &Room::tug3Timer1Expired }, + { Action(ACTION_FINISHED_ANIMATION, 7, 0, 0), &Room::tug3SecurityTeamBeamedIn }, +}; + } #endif diff --git a/engines/startrek/rooms/tug0.cpp b/engines/startrek/rooms/tug0.cpp index e90544d57e..4461b226d5 100644 --- a/engines/startrek/rooms/tug0.cpp +++ b/engines/startrek/rooms/tug0.cpp @@ -142,14 +142,19 @@ void Room::tug0SpockFinishedUsingWire() { showText(TX_SPEAKER_KIRK, TX_TUG0_010); showText(TX_SPEAKER_MCCOY, TX_TUG0_022); - showText(TX_SPEAKER_KIRK, TX_TUG0_002); - showText(TX_SPEAKER_CHRISTENSEN, TX_TUG0L009); - showText(TX_SPEAKER_CHRISTENSEN, TX_TUG0L008); - - if (_vm->_awayMission.tug.haveBomb) { - showText(TX_SPEAKER_CHRISTENSEN, TX_TUG0L010); - showText(TX_SPEAKER_MCCOY, TX_TUG0_021); - showText(TX_SPEAKER_SPOCK, TX_TUG0_041); + + // BUGFIX: check if the redshirt is dead. + if (!_vm->_awayMission.redshirtDead) { + showText(TX_SPEAKER_KIRK, TX_TUG0_002); + + showText(TX_SPEAKER_CHRISTENSEN, TX_TUG0L009); + showText(TX_SPEAKER_CHRISTENSEN, TX_TUG0L008); + + if (_vm->_awayMission.tug.haveBomb) { + showText(TX_SPEAKER_CHRISTENSEN, TX_TUG0L010); + showText(TX_SPEAKER_MCCOY, TX_TUG0_021); + showText(TX_SPEAKER_SPOCK, TX_TUG0_041); + } } } diff --git a/engines/startrek/rooms/tug2.cpp b/engines/startrek/rooms/tug2.cpp index e89aff79fd..3c6aad2ed5 100644 --- a/engines/startrek/rooms/tug2.cpp +++ b/engines/startrek/rooms/tug2.cpp @@ -481,7 +481,7 @@ void Room::tug2UseKillPhaserOnGuard1() { else { loadActorAnim2(OBJECT_KIRK, "kdrawe", -1, -1, 24); _vm->_awayMission.tug.kirkPhaserDrawn = true; - _vm->_awayMission.tug.field4a = true; + _vm->_awayMission.tug.brigElasiPhasersOnKill = true; } } } @@ -509,7 +509,7 @@ void Room::tug2UseKillPhaserOnGuard2() { else { loadActorAnim2(OBJECT_KIRK, "kdrawe", -1, -1, 25); _vm->_awayMission.tug.kirkPhaserDrawn = true; - _vm->_awayMission.tug.field4a = true; + _vm->_awayMission.tug.brigElasiPhasersOnKill = true; } } } @@ -624,7 +624,7 @@ void Room::tug2Timer0Expired() { return; _roomVar.tug2.elasiPhaserOnKill = 0; - if (_vm->_awayMission.tug.field4a) + if (_vm->_awayMission.tug.brigElasiPhasersOnKill) _roomVar.tug2.elasiPhaserOnKill = 1; switch (_vm->_awayMission.tug.field4b) { @@ -659,14 +659,14 @@ void Room::tug2Timer0Expired() { case 2: // Guard shoots spock (or kirk) _vm->_awayMission.tug.field4b++; - _roomVar.tug2._1ec4 = 0; - if (_vm->_awayMission.tug.field4a) - _roomVar.tug2._1ec4 = 1; + _roomVar.tug2.shootKirkOverride = false; + if (_vm->_awayMission.tug.brigElasiPhasersOnKill) + _roomVar.tug2.shootKirkOverride = true; tug2DetermineElasiShooter(); - if (_roomVar.tug2._1ec4 == 0) - _roomVar.tug2.shootingTarget = OBJECT_SPOCK; - else + if (_roomVar.tug2.shootKirkOverride) _roomVar.tug2.shootingTarget = OBJECT_KIRK; + else + _roomVar.tug2.shootingTarget = OBJECT_SPOCK; _vm->_awayMission.timers[0] = 60; tug2GuardShootsCrewman(); break; @@ -683,16 +683,16 @@ void Room::tug2Timer0Expired() { case 4: _vm->_awayMission.tug.field4b++; - if (_roomVar.tug2._1ec4 == 0) { + if (_roomVar.tug2.shootKirkOverride) { tug2DetermineElasiShooter(); - _roomVar.tug2.shootingTarget = OBJECT_KIRK; - _vm->_awayMission.timers[2] = 40; // TODO + _roomVar.tug2.shootingTarget = OBJECT_SPOCK; + _vm->_awayMission.timers[2] = 40; tug2GuardShootsCrewman(); } - else if (_roomVar.tug2._1ec4 == 1) { + else if (_roomVar.tug2.shootKirkOverride) { tug2DetermineElasiShooter(); - _roomVar.tug2.shootingTarget = OBJECT_SPOCK; - _vm->_awayMission.timers[2] = 40; + _roomVar.tug2.shootingTarget = OBJECT_KIRK; + _vm->_awayMission.timers[2] = 40; // TODO tug2GuardShootsCrewman(); } break; diff --git a/engines/startrek/rooms/tug3.cpp b/engines/startrek/rooms/tug3.cpp new file mode 100644 index 0000000000..6c1b67409d --- /dev/null +++ b/engines/startrek/rooms/tug3.cpp @@ -0,0 +1,504 @@ +/* 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 { + +#define OBJECT_ELASI_1 8 +#define OBJECT_ELASI_2 9 +#define OBJECT_ELASI_3 10 +#define OBJECT_ELASI_4 11 +#define OBJECT_12 12 +#define OBJECT_13 13 +#define OBJECT_14 14 +#define OBJECT_15 15 + +#define GUARDSTAT_UP 0 +#define GUARDSTAT_STUNNED 1 +#define GUARDSTAT_DEAD 2 +#define GUARDSTAT_SURRENDERED 4 +#define GUARDSTAT_TIED 8 + +void Room::tug3Tick1() { + playVoc("TUG3LOOP"); + + _vm->_awayMission.disableWalking = true; + loadActorAnim2(OBJECT_ELASI_1, "p1turn", 0xa4, 0x98, 0); + loadActorAnim2(OBJECT_ELASI_2, "p2turn", 0xd1, 0x88, 0); + loadActorAnim2(OBJECT_ELASI_3, "p3turn", 0xfb, 0xc4, 0); + loadActorAnim2(OBJECT_ELASI_4, "p4turn", 0x5a, 0x9e, 0); +} + +void Room::tug3Tick40() { + loadActorAnim2(OBJECT_KIRK, "kdraws", -1, -1, 0); // Draw phaser +} + +void Room::tug3LookAnywhere() { + showText(TX_TUG3N007); +} + +void Room::tug3ElasiSurrendered() { + // BUGFIX: the original game had the condition below. However, this would cause + // problems if you start shooting, then get them to surrender; if timed correctly, + // they could shoot Kirk as he's beaming out and the mission is "successful". To + // prevent that, the below condition is removed in ScummVM. + /* + if (_vm->_awayMission.tug.bridgeElasiDrewPhasers) + return; + */ + + // Also part of the bugfix (stop shooting) + _vm->_awayMission.timers[0] = 0; + + _vm->_awayMission.tug.elasiSurrendered = true; + loadActorAnim2(OBJECT_ELASI_1, "p1surr", -1, -1, 0); + _vm->_awayMission.tug.bridgeElasi1Status = GUARDSTAT_SURRENDERED; + + if (_vm->_awayMission.tug.bridgeElasi2Status == GUARDSTAT_UP) { + loadActorAnim2(OBJECT_ELASI_2, "p2surr", -1, -1, 0); + _vm->_awayMission.tug.bridgeElasi2Status = GUARDSTAT_SURRENDERED; + } + if (_vm->_awayMission.tug.bridgeElasi3Status == GUARDSTAT_UP) { + loadActorAnim2(OBJECT_ELASI_3, "p3surr", -1, -1, 0); + _vm->_awayMission.tug.bridgeElasi3Status = GUARDSTAT_SURRENDERED; + } + if (_vm->_awayMission.tug.bridgeElasi4Status == GUARDSTAT_UP) { + loadActorAnim2(OBJECT_ELASI_4, "p4surr", -1, -1, 0); + _vm->_awayMission.tug.bridgeElasi4Status = GUARDSTAT_SURRENDERED; + } + + _vm->_awayMission.tug.missionScore += 4; +} + +void Room::tug3UsePhaserAnywhere() { + // Stub function to suppress "you can't do that" messages +} + +void Room::tug3ElasiDrawPhasers() { + if (_vm->_awayMission.tug.bridgeElasiDrewPhasers) + return; + + _vm->_awayMission.tug.bridgeElasiDrewPhasers = true; + + // If brig guards are alive & untied, kill the hostages + if (_vm->_awayMission.tug.guard1Status == 0 || _vm->_awayMission.tug.guard2Status == 0) { + showText(TX_SPEAKER_ELASI_CLANSMAN, TX_TUG3L081); + _vm->_awayMission.tug.missionScore = 0; + } + + if (_vm->_awayMission.timers[0] == 0) + _vm->_awayMission.timers[0] = 10; + + // Make all elasi draw their phasers + if (_vm->_awayMission.tug.bridgeElasi1Status == 0) + loadActorAnim2(OBJECT_ELASI_1, "p1draw", -1, -1, 0); + if (_vm->_awayMission.tug.bridgeElasi2Status == 0) + loadActorAnim2(OBJECT_ELASI_2, "p2draw", -1, -1, 0); + if (_vm->_awayMission.tug.bridgeElasi3Status == 0) + loadActorAnim2(OBJECT_ELASI_3, "p3draw", -1, -1, 0); + if (_vm->_awayMission.tug.bridgeElasi4Status == 0) + loadActorAnim2(OBJECT_ELASI_4, "p4draw", -1, -1, 0); +} + +void Room::tug3UseStunPhaserOnElasi1() { + if (_vm->_awayMission.tug.crewmanKilled[OBJECT_KIRK] || _vm->_awayMission.tug.bridgeElasi1Status != GUARDSTAT_UP) + return; + loadActorAnim2(OBJECT_ELASI_1, "p1stun", -1, -1, 12); + playSoundEffectIndex(SND_PHASSHOT); + showBitmapFor5Ticks("t3beem05", 5); + _vm->_awayMission.tug.bridgeElasi1Status = GUARDSTAT_STUNNED; + tug3ElasiDrawPhasers(); +} + +void Room::tug3UseStunPhaserOnElasi2() { + if (_vm->_awayMission.tug.crewmanKilled[OBJECT_KIRK] || _vm->_awayMission.tug.bridgeElasi2Status != GUARDSTAT_UP) + return; + loadActorAnim2(OBJECT_ELASI_2, "p2stun", -1, -1, 12); + playSoundEffectIndex(SND_PHASSHOT); + showBitmapFor5Ticks("t3beem06", 5); + _vm->_awayMission.tug.bridgeElasi2Status = GUARDSTAT_STUNNED; + tug3ElasiDrawPhasers(); +} + +void Room::tug3UseStunPhaserOnElasi3() { + if (_vm->_awayMission.tug.crewmanKilled[OBJECT_KIRK] || _vm->_awayMission.tug.bridgeElasi3Status != GUARDSTAT_UP) + return; + loadActorAnim2(OBJECT_ELASI_3, "p3stun", -1, -1, 12); + playSoundEffectIndex(SND_PHASSHOT); + showBitmapFor5Ticks("t3beem07", 5); + _vm->_awayMission.tug.bridgeElasi3Status = GUARDSTAT_STUNNED; + tug3ElasiDrawPhasers(); +} + +void Room::tug3UseStunPhaserOnElasi4() { + if (_vm->_awayMission.tug.crewmanKilled[OBJECT_KIRK] || _vm->_awayMission.tug.bridgeElasi4Status != GUARDSTAT_UP) + return; + loadActorAnim2(OBJECT_ELASI_4, "p4stun", -1, -1, 12); + playSoundEffectIndex(SND_PHASSHOT); + showBitmapFor5Ticks("t3beem04", 5); + _vm->_awayMission.tug.bridgeElasi4Status = GUARDSTAT_STUNNED; + tug3ElasiDrawPhasers(); +} + +void Room::tug3UseKillPhaserOnElasi1() { + if (_vm->_awayMission.tug.crewmanKilled[OBJECT_KIRK] || _vm->_awayMission.tug.bridgeElasi1Status != GUARDSTAT_UP) + return; + loadActorAnim2(OBJECT_ELASI_1, "p1Kill", -1, -1, 12); + playSoundEffectIndex(SND_PHASSHOT); + showBitmapFor5Ticks("t3beem25", 5); + _vm->_awayMission.tug.bridgeElasi1Status = GUARDSTAT_DEAD; + _vm->_awayMission.tug.missionScore -= 2; + tug3ElasiDrawPhasers(); +} + +void Room::tug3UseKillPhaserOnElasi2() { + if (_vm->_awayMission.tug.crewmanKilled[OBJECT_KIRK] || _vm->_awayMission.tug.bridgeElasi2Status != GUARDSTAT_UP) + return; + loadActorAnim2(OBJECT_ELASI_2, "p2Kill", -1, -1, 12); + playSoundEffectIndex(SND_PHASSHOT); + showBitmapFor5Ticks("t3beem27", 5); + _vm->_awayMission.tug.bridgeElasi2Status = GUARDSTAT_DEAD; + _vm->_awayMission.tug.missionScore -= 2; + tug3ElasiDrawPhasers(); +} + +void Room::tug3UseKillPhaserOnElasi3() { + if (_vm->_awayMission.tug.crewmanKilled[OBJECT_KIRK] || _vm->_awayMission.tug.bridgeElasi3Status != GUARDSTAT_UP) + return; + loadActorAnim2(OBJECT_ELASI_3, "p3Kill", -1, -1, 12); + playSoundEffectIndex(SND_PHASSHOT); + showBitmapFor5Ticks("t3beem26", 5); + _vm->_awayMission.tug.bridgeElasi3Status = GUARDSTAT_DEAD; + _vm->_awayMission.tug.missionScore -= 2; + tug3ElasiDrawPhasers(); +} + +void Room::tug3UseKillPhaserOnElasi4() { + if (_vm->_awayMission.tug.crewmanKilled[OBJECT_KIRK] || _vm->_awayMission.tug.bridgeElasi4Status != GUARDSTAT_UP) + return; + loadActorAnim2(OBJECT_ELASI_4, "p4Kill", -1, -1, 12); + playSoundEffectIndex(SND_PHASSHOT); + showBitmapFor5Ticks("t3beem24", 5); + _vm->_awayMission.tug.bridgeElasi4Status = GUARDSTAT_DEAD; + _vm->_awayMission.tug.missionScore -= 2; + tug3ElasiDrawPhasers(); +} + +void Room::tug3ElasiStunnedOrKilled() { + if (_vm->_awayMission.tug.bridgeWinMethod == 1) + return; + if (_vm->_awayMission.tug.bridgeElasi1Status == GUARDSTAT_UP || _vm->_awayMission.tug.bridgeElasi2Status == GUARDSTAT_UP + || _vm->_awayMission.tug.bridgeElasi3Status == GUARDSTAT_UP || _vm->_awayMission.tug.bridgeElasi4Status == GUARDSTAT_UP) + return; + + // BUGFIX: if the ship is deorbiting, the mission isn't won yet. + if (_vm->_awayMission.tug.orbitalDecayCounter != 0) + return; + + _vm->_awayMission.tug.bridgeWinMethod = 1; + tug3EndMission(); +} + +void Room::tug3TalkToElasi1() { + if (_vm->_awayMission.tug.bridgeElasi1Status != GUARDSTAT_UP || _vm->_awayMission.tug.talkedToCereth) + return; + _vm->_awayMission.tug.talkedToCereth = true; + + const int choices[] = { + TX_SPEAKER_KIRK, + TX_TUG3_004, + TX_TUG3_003, + TX_TUG3_002, + TX_BLANK + }; + int choice = showText(choices); + + switch (choice) { + case 0: // They surrender + showText(TX_SPEAKER_ELASI_CERETH, TX_TUG3L084); + _vm->_awayMission.tug.bridgeElasi1Status = GUARDSTAT_SURRENDERED; + loadActorAnim2(OBJECT_ELASI_1, "p1surr", -1, -1, 0); + tug3ElasiSurrendered(); + _vm->_awayMission.tug.bridgeWinMethod = 2; + _vm->_awayMission.tug.missionScore += 8; + tug3EndMission(); + break; + + case 1: // Cereth shoots console, doesn't surrender + _vm->_awayMission.disableInput = true; + showText(TX_SPEAKER_ELASI_CERETH, TX_TUG3_F27); + loadActorAnim2(OBJECT_ELASI_1, "p1draw", -1, -1, 3); + break; + + case 2: // Cereth shoots console and surrenders + _vm->_awayMission.disableInput = true; + showText(TX_SPEAKER_ELASI_CERETH, TX_TUG3L083); + loadActorAnim2(OBJECT_ELASI_1, "p1draw", -1, -1, 5); + + // BUGFIX: they're going to surrender, so stop the firefight. + _vm->_awayMission.timers[0] = 0; + break; + } +} + +void Room::tug3Elasi1DrewPhaser() { + playSoundEffectIndex(SND_PHASSHOT); + showBitmapFor5Ticks("t3beem41", 13); + playSoundEffectIndex(SND_BLANK_16); + loadActorAnim2(OBJECT_12, "sparks", 0xa0, 0xad, 4); +} + +void Room::tug3Elasi1ShotConsole() { + tug3ElasiDrawPhasers(); + _vm->_awayMission.disableInput = false; + _vm->_awayMission.tug.bridgeWinMethod = 3; + _vm->_awayMission.timers[1] = 10; +} + +void Room::tug3Elasi1DrewPhaser2() { + playSoundEffectIndex(SND_PHASSHOT); + showBitmapFor5Ticks("t3beem41", 13); + loadActorAnim2(OBJECT_12, "sparks", 0xa0, 0xad, 6); +} + +void Room::tug3Elasi1ShotConsoleAndSurrenders() { + showText(TX_SPEAKER_ELASI_CERETH, TX_TUG3L080); + tug3ElasiSurrendered(); + _vm->_awayMission.disableInput = false; + _vm->_awayMission.tug.bridgeWinMethod = 3; + _vm->_awayMission.timers[1] = 10; +} + +void Room::tug3LookAtMccoy() { + showText(TX_TUG3N000); +} + +void Room::tug3LookAtSpock() { + showText(TX_TUG3N002); +} + +void Room::tug3LookAtRedshirt() { + showText(TX_TUG3N001); +} + +void Room::tug3LookAtElasi1() { + // BUGFIX: there were two implementations of this function; the first was the same as + // the other 3 elasi, the second was specific to the captain. The second was never + // called in the original game, but it's used here instead for more variety. + // The function itself is changed by checking both if he's stunned or if he's dead, + // instead of just checking if he's stunned. + + if (_vm->_awayMission.tug.bridgeElasi1Status == GUARDSTAT_STUNNED || _vm->_awayMission.tug.bridgeElasi1Status == GUARDSTAT_DEAD) + showText(TX_TUG3N003); + else + showText(TX_TUG3N008); +} + +void Room::tug3LookAtElasi2() { + // BUGFIX: also check if stunned. They can't "glare at the crewmembers" if they're + // unconscious. (applies to below functions too.) + if (_vm->_awayMission.tug.bridgeElasi2Status == GUARDSTAT_DEAD || _vm->_awayMission.tug.bridgeElasi2Status == GUARDSTAT_STUNNED) + showText(TX_TUG3N004); + else + showText(TX_TUG3N005); +} + +void Room::tug3LookAtElasi3() { + if (_vm->_awayMission.tug.bridgeElasi3Status == GUARDSTAT_DEAD || _vm->_awayMission.tug.bridgeElasi2Status == GUARDSTAT_STUNNED) + showText(TX_TUG3N004); + else + showText(TX_TUG3N005); +} + +void Room::tug3LookAtElasi4() { + if (_vm->_awayMission.tug.bridgeElasi4Status == GUARDSTAT_DEAD || _vm->_awayMission.tug.bridgeElasi2Status == GUARDSTAT_STUNNED) + showText(TX_TUG3N004); + else + showText(TX_TUG3N005); +} + +void Room::tug3TalkToMccoy() { + if (_vm->_awayMission.tug.orbitalDecayCounter != 0 || _vm->_awayMission.tug.bridgeElasi1Status != GUARDSTAT_UP) { + if (_vm->_awayMission.tug.orbitalDecayCounter >= 10) { + if (_vm->_awayMission.tug.orbitalDecayCounter < 16) + showText(TX_SPEAKER_MCCOY, TX_TUG3_011); + } + else if (_vm->_awayMission.tug.orbitalDecayCounter != 0) { + // BUGFIX: original game displays a blank textbox. An appropriate audio file + // exists, but the corresponding text was written from scratch for ScummVM. + // TODO: check if original floppy version has text for this. + showText(TX_SPEAKER_MCCOY, TX_TUG3_012); + } + } + else + showText(TX_SPEAKER_MCCOY, TX_TUG3_013); +} + +void Room::tug3TalkToSpock() { + if (_vm->_awayMission.tug.orbitalDecayCounter != 0) { + if (_vm->_awayMission.tug.orbitalDecayCounter >= 10) { + if (_vm->_awayMission.tug.orbitalDecayCounter < 16) + showText(TX_SPEAKER_SPOCK, TX_TUG3_008); + } + else + showText(TX_SPEAKER_SPOCK, TX_TUG3_009); + } +} + +void Room::tug3TalkToRedshirt() { + showText(TX_SPEAKER_CHRISTENSEN, TX_TUG3L003); +} + +void Room::tug3UseCommunicator() { + if (_vm->_awayMission.tug.orbitalDecayCounter == 0) + return; + + if (_vm->_awayMission.tug.orbitalDecayCounter < 10) { + showText(TX_SPEAKER_KIRK, TX_TUG3_007); + showText(TX_SPEAKER_SULU, TX_TUG3_015); + showText(TX_SPEAKER_SHIPS_COMPUTER, TX_COMPA180); + _vm->_awayMission.timers[1] = 0; + + // BUGFIX: if still fighting the elasi, the mission isn't done yet. + _vm->_awayMission.tug.orbitalDecayCounter = 0; + if (!_vm->_awayMission.tug.elasiSurrendered && + (_vm->_awayMission.tug.bridgeElasi1Status == GUARDSTAT_UP + || _vm->_awayMission.tug.bridgeElasi2Status == GUARDSTAT_UP + || _vm->_awayMission.tug.bridgeElasi3Status == GUARDSTAT_UP + || _vm->_awayMission.tug.bridgeElasi4Status == GUARDSTAT_UP)) + return; + + tug3EndMission(); + } + else { + if (_vm->_awayMission.tug.orbitalDecayCounter < 16) { + showText(TX_SPEAKER_KIRK, TX_TUG3_006); + showText(TX_SPEAKER_SCOTT, TX_TUG3_S07); + + playMidiMusicTracks(-1, -1); + + _vm->_awayMission.disableInput = true; + if (_vm->_awayMission.tug.missionScore < 0) + _vm->_awayMission.tug.missionScore = 0; + endMission(_vm->_awayMission.tug.missionScore, _vm->_awayMission.tug.field2b, _vm->_awayMission.tug.field2d); + } + } +} + +// One of the elasi shoots one of the crewmen +void Room::tug3Timer0Expired() { + const char *beamAnims[][4] = { + { "t3beem33", "t3beem35", "t3beem34", "t3beem32" }, + { "t3beem37", "t3beem39", "t3beem38", "t3beem36" }, + { "t3beem29", "t3beem31", "t3beem30", "t3beem28" }, + }; + + int elasiShooter, elasiTarget; + + if (_vm->_awayMission.tug.bridgeElasi2Status == GUARDSTAT_UP) + elasiShooter = 0; + else if (_vm->_awayMission.tug.bridgeElasi3Status == GUARDSTAT_UP) + elasiShooter = 1; + else if (_vm->_awayMission.tug.bridgeElasi4Status == GUARDSTAT_UP) + elasiShooter = 2; + else + return; + + if (!_vm->_awayMission.tug.crewmanKilled[OBJECT_REDSHIRT]) { + _vm->_awayMission.tug.crewmanKilled[OBJECT_REDSHIRT] = 2; + _vm->_awayMission.redshirtDead = true; + loadActorAnim2(OBJECT_REDSHIRT, "rkills", -1, -1, 0); + elasiTarget = OBJECT_REDSHIRT; + } + else if (!_vm->_awayMission.tug.crewmanKilled[OBJECT_KIRK]) { + _vm->_awayMission.tug.crewmanKilled[OBJECT_KIRK] = 2; + _vm->_awayMission.disableInput = true; + loadActorAnim2(OBJECT_KIRK, "kkills", -1, -1, 0); + elasiTarget = OBJECT_KIRK; + } + else if (!_vm->_awayMission.tug.crewmanKilled[OBJECT_SPOCK]) { + _vm->_awayMission.tug.crewmanKilled[OBJECT_SPOCK] = 2; + loadActorAnim2(OBJECT_SPOCK, "skills", -1, -1, 0); + elasiTarget = OBJECT_SPOCK; + } + else if (!_vm->_awayMission.tug.crewmanKilled[OBJECT_MCCOY]) { + _vm->_awayMission.tug.crewmanKilled[OBJECT_MCCOY] = 2; + loadActorAnim2(OBJECT_MCCOY, "mkills", -1, -1, 13); + elasiTarget = OBJECT_MCCOY; + } + else + return; + + playSoundEffectIndex(SND_PHASSHOT); + showBitmapFor5Ticks(beamAnims[elasiShooter][elasiTarget], 5); + _vm->_awayMission.timers[0] = 50; +} + +void Room::tug3AllCrewmenDead() { + playMidiMusicTracks(2, -1); + showGameOverMenu(); +} + +// "Orbital decay" countdown timer +void Room::tug3Timer1Expired() { + if (_vm->_awayMission.tug.orbitalDecayCounter < 10) { // Decay still preventable + showText(TX_SPEAKER_SHIPS_COMPUTER, TX_COMPU182); + _vm->_awayMission.timers[1] = 100; + _vm->_awayMission.tug.orbitalDecayCounter++; + } + else if (_vm->_awayMission.tug.orbitalDecayCounter < 16) { // Decay now unavoidable + showText(TX_SPEAKER_SHIPS_COMPUTER, TX_COMPU181); + _vm->_awayMission.timers[1] = 100; + _vm->_awayMission.tug.orbitalDecayCounter++; + } + else { // Game over + showText(TX_TUG3N006); + showGameOverMenu(); + } +} + +void Room::tug3EndMission() { + playMidiMusicTracks(28, -1); + showText(TX_SPEAKER_KIRK, TX_TUG3_001); + playSoundEffectIndex(SND_TRANSMAT); + loadActorAnim2(OBJECT_13, "rteleb", 0x14, 0xa0, 7); + loadActorAnim2(OBJECT_14, "rteleb", 0x118, 0xa0, 0); + loadActorAnim2(OBJECT_15, "rteleb", 0x96, 0xbe, 0); +} + +void Room::tug3SecurityTeamBeamedIn() { + loadActorAnim2(OBJECT_13, "rdrawe", -1, -1, 8); + loadActorAnim2(OBJECT_14, "rdraws", -1, -1, 9); + loadActorAnim2(OBJECT_15, "rfiren", -1, -1, 10); + + showText(TX_SPEAKER_KIRK, TX_TUG3_005); + showText(TX_SPEAKER_SCOTT, TX_TUG3_S08); + + playMidiMusicTracks(-1, -1); + _vm->_awayMission.disableInput = true; + if (_vm->_awayMission.tug.missionScore < 0) + _vm->_awayMission.tug.missionScore = 0; + endMission(_vm->_awayMission.tug.missionScore, _vm->_awayMission.tug.field2b, _vm->_awayMission.tug.field2d); +} + +} diff --git a/engines/startrek/text.h b/engines/startrek/text.h index b56a20a547..1a9e18280e 100644 --- a/engines/startrek/text.h +++ b/engines/startrek/text.h @@ -66,6 +66,8 @@ enum GameStringIDs { TX_SPEAKER_MCCOY, TX_SPEAKER_UHURA, TX_SPEAKER_SCOTT, + TX_SPEAKER_SULU, + TX_SPEAKER_SHIPS_COMPUTER, TX_SPEAKER_EVERTS, TX_SPEAKER_ANGIVEN, @@ -81,6 +83,8 @@ enum GameStringIDs { TX_SPEAKER_CHRISTENSEN, TX_SPEAKER_SIMPSON, TX_SPEAKER_ELASI_GUARD, + TX_SPEAKER_ELASI_CLANSMAN, + TX_SPEAKER_ELASI_CERETH, TX_SPEAKER_MASADA_CREWMAN, TX_DEM0_001, @@ -674,6 +678,41 @@ enum GameStringIDs { TX_TUG2C001, // Custom + TX_COMPA180, + TX_COMPU181, + TX_COMPU182, + TX_TUG3_001, + TX_TUG3_002, + TX_TUG3_003, + TX_TUG3_004, + TX_TUG3_005, + TX_TUG3_006, + TX_TUG3_007, + TX_TUG3_008, + TX_TUG3_009, + TX_TUG3_011, + TX_TUG3_012, + TX_TUG3_013, + TX_TUG3_015, + TX_TUG3_F27, + TX_TUG3_S07, + TX_TUG3_S08, + TX_TUG3L003, + TX_TUG3L080, + TX_TUG3L081, + TX_TUG3L083, + TX_TUG3L084, + TX_TUG3N000, + TX_TUG3N001, + TX_TUG3N002, + TX_TUG3N003, + TX_TUG3N004, + TX_TUG3N005, + TX_TUG3N006, + TX_TUG3N007, + TX_TUG3N008, + + TX_END }; @@ -687,6 +726,8 @@ const char * const g_gameStrings[] = { "Dr. McCoy", "Lt. Uhura", "Mr. Scott", + "Mr. Sulu", + "Ship's Computer", "Ensign Everts", "Prel. Angiven", @@ -702,6 +743,8 @@ const char * const g_gameStrings[] = { "Lt. Christensen", "Crewman Simpson", "Elasi Guard", + "Elasi Clansman", + "Elasi Cereth", "Masada Crewman", "#DEM0\\DEM0_001#Doctor, you need to investigate the possibility of disease, mental or physical, among these people, before we go chasing up the mountains. Prelate Angiven, may we see those who have encountered the demons?", @@ -1138,7 +1181,7 @@ const char * const g_gameStrings[] = { "#TUG0\\TUG0_017#He will be all right, but we shouldn't move him.", "#TUG0\\TUG0_018#He's not hurt badly. I can revive him.", "#TUG0\\TUG0_019#I don't think he should be moved, Jim.", - "#TUG0\\TUG0_020#Well, at least I'm not picking up residue of any biologicalweapons. The Elasi used some restraint if you can call it that.", + "#TUG0\\TUG0_020#Well, at least I'm not picking up residue of any biological weapons. The Elasi used some restraint if you can call it that.", "#TUG0\\TUG0_021#And any hostages on the bridge will be killed when the bomb goes off! No, Jim, that's inhuman!", "#TUG0\\TUG0_022#I wouldn't go that far, Jim. But I do have to congratulate you, Mr. Spock. Now we can really risk shooting our atoms around the universe. Is this really necessary, Jim?", "#TUG0\\TUG0_023#My God Jim, what have you done! You killed them all. You probably blew up the whole damn bridge.", @@ -1194,7 +1237,7 @@ const char * const g_gameStrings[] = { "#TUG1\\TUG1_004#Jim, I can only perform medical miracles not engineering ones.", "#TUG1\\TUG1_005#Jim, I'm picking up 11 life forms in the brig. That accounts for over half the crew. I don't like what that indicates.", "#TUG1\\TUG1_006#Nothing unusual is detected.", - "#TUG1\\TUG1_007#The force field is interfering too much to get an accurate reading, Jim", + "#TUG1\\TUG1_007#The force field is interfering too much to get an accurate reading, Jim.", // TYPO "#TUG1\\TUG1_008#My daddy would have sent me to bed without supper if I'd done something like this.", "#TUG1\\TUG1_009#Five phasers without power packs, a drained phaser welder, insulation and bits of wire, and droplets of cooled molten metal.", "#TUG1\\TUG1_010#I don't think we can bring down that forcefield, Captain. If we could, though, it might be less risky than trying to transport onto the bridge.", @@ -1293,6 +1336,41 @@ const char * const g_gameStrings[] = { "#TUG2\\TUG2N037#He doesn't look to friendly.", "#TUG2\\TUG2N106#Only the red beret of the elasi guard remains.", "Snip...snip...snip.", + + + "#COMP\\COMPA180#Orbit Stabilized. Warning Cancelled.", // FIXME + "#COMP\\COMPU181#Warning. Orbital Decay is now irreversible. Abandon Ship. Abandon Ship.", + "#COMP\\COMPU182#Warning. Orbital decay detected. Warning.", + "#TUG3\\TUG3_001#Scotty, beam down a security team to the bridge. We have regained control.", + "#TUG3\\TUG3_002#Check and mate, Elasi. Don't do anything foolish.", + "#TUG3\\TUG3_003#Freeze, don't even think about it.", + "#TUG3\\TUG3_004#It's over, Cereth. Surrender and I'll guarantee the lives of you and your crew.", + "#TUG3\\TUG3_005#Mr. Scott, beam us out of here.", + "#TUG3\\TUG3_006#Mr. Scott, get us out of here.", + "#TUG3\\TUG3_007#Mr. Sulu, we need some help over here.", + "#TUG3\\TUG3_008#Captain, I highly recommend returning to the Enterprise within the next 57.32 seconds.", + "#TUG3\\TUG3_009#Captain, I recommend that Mr. Sulu stabilize the Masada's orbit from the Enterprise.", + "#TUG3\\TUG3_011#I think we should return to the Enterprise before we burn up, Jim.", + "#TUG3\\TUG3_012#I'm a doctor, not a space jockey! Talk to Mr. Sulu about fixing our orbit!", + "#TUG3\\TUG3_013#Jim, that man is mad.", + "#TUG3\\TUG3_015#Aye, Captain, using prefix code override to stabilize Masada's orbit. Sulu out.", + "#TUG3\\TUG3_F27#Foolhardy words, Kirk. You have underestimated me at every turn.", + "#TUG3\\TUG3_S07#Aye, Captain.", + "#TUG3\\TUG3_S08#Aye, Captain.", + "#TUG3\\TUG3L003#I'm just a security officer, sir.", + "#TUG3\\TUG3L080#A blow struck for freedom, Captain. Now I surrender.", + "#TUG3\\TUG3L081#Bridge to brig, kill the hostages!", + "#TUG3\\TUG3L083#I still have a gambit or two left, my friend.", + "#TUG3\\TUG3L084#You are an honorable and worthy opponent, Kirk. I accept your offer.", + "#TUG3\\TUG3N000#Dr. McCoy appears a bit restless.", + "#TUG3\\TUG3N001#Lt. Christensen is carefully observing Elasi.", + "#TUG3\\TUG3N002#Spock is analyzing the surroundings.", + "#TUG3\\TUG3N003#The body of Elasi Cereth lies on the ground.", + "#TUG3\\TUG3N004#The body of the Elasi clanmember lies on the ground here.", + "#TUG3\\TUG3N005#The Elasi clanmember glares at the party.", + "#TUG3\\TUG3N006#The Masada goes down in a fireball over Beta Myamid, with you on it. Better luck next season.", + "#TUG3\\TUG3N007#This is a standard Starfleet bridge, perhaps not as impressive as the one on the Enterprise. There are quite a few pirates here.", + "#TUG3\\TUG3N008#You carefully eye the chief lieutenant of the Elasi Clan, Elasi Cereth.", }; } |