scummvm/engines/startrek/bridge.cpp
2021-12-26 18:48:43 +01:00

1382 lines
48 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "startrek/bridge.h"
#include "startrek/iwfile.h"
#include "startrek/resource.h"
#include "startrek/room.h"
#include "startrek/startrek.h"
namespace StarTrek {
#define ACTOR_STANDING_SPOCK "xstndsp"
#define ACTOR_STANDING_MCCOY "xstndmc"
#define ACTOR_SITTING_SPOCK "bstndsp"
struct BridgeActorAndMenu {
int id;
const char *anim;
const char *menu;
int16 x;
int16 y;
};
BridgeActorAndMenu bridgeActorsAndMenus[] = {
{ 0, "bstndki", "command", 60, 100 }, // Kirk
{ 1, "bstndsp", "comp", 200, 30 }, // Spock
{ 4, "bstndsu", "helm", 60, 70 }, // Sulu
{ 5, "bstndch", "nav", 60, 70 }, // Chekov
{ 6, "bstnduh", "comm", 30, 30 }, // Uhura
{ 7, "bstndsc", "eng", 30, 30 }, // Scotty
};
void StarTrekEngine::initBridge(bool b) {
_gfx->loadPalette("bridge");
_sound->loadMusicFile("bridge");
initStarfieldPosition();
// TODO: starfield
loadBridge();
}
void StarTrekEngine::loadBridge() {
// TODO: Check why the +1 is needed here
initStarfield(72 + 1, 30, 247 + 1, 102, 0);
_gfx->setBackgroundImage("bridge");
_gfx->loadPri("bridge");
_gfx->copyBackgroundScreen();
_system->updateScreen();
loadBridgeActors();
//sub_1312C(); // TODO
// TODO
//initStarfieldSprite();
//initStarfieldSprite();
//initStarfieldSprite();
//initStarfieldSprite();
//initStarfieldSprite();
}
void StarTrekEngine::loadBridgeActors() {
for (int i = 0; i < ARRAYSIZE(bridgeActorsAndMenus); ++i) {
BridgeActorAndMenu a = bridgeActorsAndMenus[i];
loadActorAnim(a.id, a.anim, 0, 0, 1.0);
}
}
// TODO: 2 params, change Enterprise state
void StarTrekEngine::setBridgeMouseCursor() {
_gfx->setMouseBitmap("pushbtn" /*_mouseControllingShip ? "entcur" : "cursor"*/);
}
void StarTrekEngine::showTextboxBridge(int talker, int textId) {
showTextboxBridge(talker, _resource->getLoadedText(textId));
}
void StarTrekEngine::showTextboxBridge(int talker, Common::String text) {
switch (talker) {
case kBridgeTalkerKirk:
showTextbox("Captain Kirk", text, 160, 130, 176, 0);
break;
case kBridgeTalkerSpock:
showTextbox("Mr. Spock", text, 294, 106, 44, 0);
break;
case kBridgeTalkerSulu:
showTextbox("Mr. Sulu", text, 122, 116, 176, 0);
break;
case kBridgeTalkerChekov:
showTextbox("Mr. Chekov", text, 196, 116, 176, 0);
break;
case kBridgeTalkerUhura:
showTextbox("Lieutenant Uhura", text, 298, 150, 161, 0);
break;
case kBridgeTalkerScotty:
showTextbox("Mr. Scott", text, 64, 100, 161, 0);
break;
case kBridgeTalkerMcCoy:
showTextbox("Dr. McCoy", text, 160, 100, 44, 0);
break;
case kBridgeTalkerCaptainsLog:
showTextbox("Captain's Log", text, 160, 130, 176, 0);
break;
case kBridgeTalkerElasiCaptain:
showTextbox("Elasi Captain", text, 160, 190, 44, 0);
break;
case kBridgeTalkerElasiCereth:
showTextbox("Elasi Cereth", text, 160, 190, 44, 0);
break;
case kBridgeTalkerAutobeacon:
showTextbox("Autobeacon", text, 160, 130, 161, 0);
break;
case kBridgeTalkerHarryMuddsVoice:
showTextbox("Voice", text, 160, 130, 44, 0);
break;
case kBridgeTalkerHarryMudd:
showTextbox("Harry Mudd", text, 160, 190, 44, 0);
break;
case kBridgeTalkerTaraz:
showTextbox("Taraz", text, 160, 190, 44, 0);
break;
case kBridgeTalkerAdmiralKenka:
showTextbox("Admiral Kenka", text, 160, 190, 44, 0);
break;
case kBridgeTalkerKallarax:
showTextbox("Kallarax", text, 160, 190, 44, 0);
break;
}
}
void StarTrekEngine::playBridgeSequence(int sequenceId) {
const char *lowerShieldsText = "#BRID\\B_336#Lowering shields and disarming weapons.";
switch (sequenceId) {
case kSeqStartMissionDemon: // Chapter 1: Demon world (demon)
_targetPlanet = kPlanetPollux; // We set it earlier for uniformity
_missionName = _missionToLoad = "DEMON";
_resource->setTxtFileName(_missionName);
_sound->loadMusicFile("bridgew");
showMissionStartEnterpriseFlyby("DEM0\\FLYBY", "demon");
showTextboxBridge(kBridgeTalkerCaptainsLog, 0);
showTextboxBridge(kBridgeTalkerUhura, 1);
showTextboxBridge(kBridgeTalkerSpock, 2);
// TODO: sub_2FF19("enterpri") // random number generation
// TODO: changeBridgeMode 1
_sound->playMidiMusicTracks(2, -1);
_sound->playSoundEffectIndex(kSfxRedAlert);
// HACK: Play the end of the mock battle sequence, until the 3D code is implemented
_bridgeSequenceToLoad = kSeqEndMockBattle;
break;
case kSeqEndMockBattle:
if (true) { // TODO: Check for Enterprise damage
// Mock battle won
_sound->playMidiMusicTracks(3, -1);
showTextboxBridge(kBridgeTalkerSpock, 4);
showTextboxBridge(kBridgeTalkerUhura, 5);
// TODO: sub_2f4c3()
// TODO: sub_321f9()
showTextboxBridge(kBridgeTalkerSulu, lowerShieldsText);
// TODO: Check variable
} else {
// Mock battle lost
// TODO
}
_bridgeSequenceToLoad = kSeqShowDebriefDemon;
break;
case kSeqShowDebriefDemon:
setBridgeMouseCursor(); // 0, 0
// TODO: Delete 3D object
showBridgeScreenTalkerWithMessage(12, "Admiral", "woman");
break;
case kSeqArrivedAtPolluxV:
showTextboxBridge(kBridgeTalkerSpock, 15); // We have arrived at Pollux V
_hailedTarget = false;
// In the original, this is actually a handler for Spock, Uhura and Chekov.
// We moved their actions in separate functions instead.
break;
case kSeqEndMissionDemon:
_resource->setTxtFileName("DEMON");
loadActorAnim(1, ACTOR_STANDING_SPOCK, 0, 0, 1.0);
loadActorAnim(2, ACTOR_STANDING_MCCOY, 0, 0, 1.0);
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 23); // Message from Starfleet
showTextboxBridge(kBridgeTalkerKirk, 24);
showMissionPerformance(_awayMission.demon.missionScore * 100 / 32, 29, 0);
showTextboxBridge(kBridgeTalkerMcCoy, 25);
showTextboxBridge(kBridgeTalkerKirk, 26);
showTextboxBridge(kBridgeTalkerSpock, 27);
showTextboxBridge(kBridgeTalkerMcCoy, 28);
loadActorAnim(1, ACTOR_SITTING_SPOCK, 0, 0, 1.0);
removeActorFromScreen(2);
_bridgeSequenceToLoad = kSeqStartMissionTug;
break;
case kSeqStartMissionTug: // Chapter 2: Hijacked (tug)
_targetPlanet = kPlanetBetaMyamid;
_missionName = _missionToLoad = "TUG";
_resource->setTxtFileName(_missionName);
_sound->loadMusicFile("bridge");
showMissionStartEnterpriseFlyby("TUG0\\FLYBY", "hijacked");
_sound->playMidiMusicTracks(0, -1);
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 0);
showTextboxBridge(kBridgeTalkerKirk, 1);
showBridgeScreenTalkerWithMessage(2, "Admiral", "woman");
showTextboxBridge(kBridgeTalkerChekov, 3);
break;
case kSeqStartElasiPirateBattle:
showTextboxBridge(kBridgeTalkerSpock, 6);
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 7);
showTextboxBridge(kBridgeTalkerKirk, 8);
showBridgeScreenTalkerWithMessage(9, "Elasi Captain", "pira", false);
showTextboxBridge(kBridgeTalkerKirk, 10);
showTextboxBridge(kBridgeTalkerElasiCaptain, 11);
removeActorFromScreen(_currentScreenTalker);
initStarfieldSprite(&_starfieldSprite, new StubBitmap(0, 0), _starfieldRect);
_sound->playSoundEffectIndex(kSfxRedAlert);
_enterpriseState.underAttack = true;
_sound->playMidiMusicTracks(2, -1);
startBattle("orion"); // Elasi Pirate battle
_enterpriseState.underAttack = false;
_sound->playMidiMusicTracks(3, -1);
showTextboxBridge(kBridgeTalkerChekov, 14); // Captain they are fleeing!
showTextboxBridge(kBridgeTalkerSpock, 15); // The enemy ship's initial intercept course...
_bridgeSequenceToLoad = kSeqArrivedAtBetaMyamid;
break;
case kSeqArrivedAtBetaMyamid:
// In the original, this is actually a handler for Spock, Uhura and Chekov.
// We moved their actions in separate functions instead.
break;
case kSeqApproachedTheMasada:
// TODO: approach the Masada 3D animation
showTextboxBridge(kBridgeTalkerSpock, 20); // There she is, Captain. She does not appear to be seriously damaged
_hailedTarget = false;
_beamDownAllowed = false;
break;
case kSeqEndMissionTug:
_resource->setTxtFileName("TUG");
loadActorAnim(1, ACTOR_STANDING_SPOCK, 0, 0, 1.0); // Standing Spock
loadActorAnim(2, ACTOR_STANDING_MCCOY, 0, 0, 1.0); // Standing McCoy
if (_missionEndFlag == 0) {
// Good ending
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 29);
showTextboxBridge(kBridgeTalkerKirk, 30);
showMissionPerformance(_awayMission.tug.missionScore * 100 / 32, 31, 1);
showTextboxBridge(kBridgeTalkerMcCoy, 32); // Trying to hold a Federation starship captive. Can you believe it?
showTextboxBridge(kBridgeTalkerSpock, 33); // Since we just witnessed that very event, Doctor, I'm surprised you ask.
showTextboxBridge(kBridgeTalkerMcCoy, 34);
showTextboxBridge(kBridgeTalkerKirk, 35);
showTextboxBridge(kBridgeTalkerSpock, 36);
showTextboxBridge(kBridgeTalkerKirk, 37);
} else if (_missionEndFlag == 1) {
// Bad ending 1 (0 score): the Masada got destroyed, everyone died
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 39);
showTextboxBridge(kBridgeTalkerKirk, 40);
showMissionPerformance(0, 41, 1);
} else if (_missionEndFlag == 2) {
// Bad ending 2 (0 score): bad handling of the situation, some prisoners died
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 42);
showMissionPerformance(0, 43, 1);
}
loadActorAnim(1, ACTOR_SITTING_SPOCK, 0, 0, 1.0);
removeActorFromScreen(2);
_bridgeSequenceToLoad = kSeqStartMissionLove;
break;
case kSeqStartMissionLove: // Chapter 3: Love's Labor Jeopardized (love)
_targetPlanet = kPlanetArk7; // We set it earlier for uniformity
_missionName = _missionToLoad = "LOVE";
_resource->setTxtFileName(_missionName);
_sound->loadMusicFile("bridge");
showMissionStartEnterpriseFlyby("LOV0\\FLYBY", "tlove");
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 0);
showTextboxBridge(kBridgeTalkerKirk, 1);
showBridgeScreenTalkerWithMessage(2, "Admiral", "woman");
_mouseControllingShip = true;
break;
case kSeqAfterLoveDebrief:
// In the original, this is actually a handler for Spock, Uhura and Chekov.
// We moved their actions in separate functions instead.
break;
case kSeqStartRomulanBattle:
showTextboxBridge(kBridgeTalkerSpock, "#BRID\\B_160#Romulan ship decloaking, Captain.");
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 6); // Message from the Romulan ship, Sir
showBridgeScreenTalkerWithMessage(9, "Romulan Captain", "romula");
showTextboxBridge(kBridgeTalkerSpock, 10);
_sound->playMidiMusicTracks(2, -1);
_enterpriseState.underAttack = true;
// HACK: Play the end of the Romulan battle sequence, until the 3D code is implemented
_bridgeSequenceToLoad = kSeqAfterRomulanBattle;
break;
case kSeqAfterRomulanBattle:
_enterpriseState.underAttack = false;
showTextboxBridge(kBridgeTalkerSpock, 11); // They activated a self-destruct device...
showTextboxBridge(kBridgeTalkerSulu, 12); // Resuming course to ARK7, Captain
orbitPlanetSequence(4);
_bridgeSequenceToLoad = kSeqArrivedAtArk7;
break;
case kSeqArrivedAtArk7:
_hailedTarget = false;
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 17);
showTextboxBridge(kBridgeTalkerAutobeacon, 16);
break;
case kSeqEndMissionLove:
_resource->setTxtFileName("LOVE");
loadActorAnim(1, ACTOR_STANDING_SPOCK, 0, 0, 1.0); // Standing Spock
loadActorAnim(2, ACTOR_STANDING_MCCOY, 0, 0, 1.0); // Standing McCoy
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 18);
showTextboxBridge(kBridgeTalkerKirk, 19);
showMissionPerformance(_awayMission.love.missionScore * 100 / 32, 26, 2);
showTextboxBridge(kBridgeTalkerKirk, 20);
showTextboxBridge(kBridgeTalkerMcCoy, 21);
showTextboxBridge(kBridgeTalkerKirk, 22);
showTextboxBridge(kBridgeTalkerMcCoy, 23);
showTextboxBridge(kBridgeTalkerScotty, 24);
showTextboxBridge(kBridgeTalkerKirk, 25);
loadActorAnim(1, ACTOR_SITTING_SPOCK, 0, 0, 1.0);
removeActorFromScreen(2);
_bridgeSequenceToLoad = kSeqStartMissionMudd;
break;
case kSeqStartMissionMudd: // Chapter 4: Another Fine Mess (mudd)
_targetPlanet = kPlanetHarlequin; // We set it earlier for uniformity
_missionName = _missionToLoad = "MUDD";
_resource->setTxtFileName(_missionName);
_sound->loadMusicFile("bridge");
// TODO: sub_321F9()
showMissionStartEnterpriseFlyby("MUD0\\FLYBY", "another");
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 0);
showTextboxBridge(kBridgeTalkerKirk, 1);
showBridgeScreenTalkerWithMessage(2, "Admiral", "woman");
// TODO: changeBridgeMode 1
// Spock's planet arrival quote has been moved to kSeqFightElasiShipsAndContactMudd
break;
case kSeqFightElasiShipsAndContactMudd:
showTextboxBridge(kBridgeTalkerSpock, 5); // We have arrived at Harlequin
//_beamDownAllowed = false; // TODO: unused, since the player jumps straight into a battle?
showTextboxBridge(kBridgeTalkerSpock, 6);
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 7);
showBridgeScreenTalkerWithMessage(14, "Elasi Pirate", "pira");
_enterpriseState.underAttack = true;
_sound->playMidiMusicTracks(2, -1);
startBattle("orion"); // Pirate Ship 1
startBattle("orion"); // Pirate Ship 2
_enterpriseState.underAttack = false;
showTextboxBridge(kBridgeTalkerSpock, 8); // The ion trail of the scout ship leads to the Harrapan system, Captain
showTextboxBridge(kBridgeTalkerUhura, 9);
showTextboxBridge(kBridgeTalkerKirk, 10);
showTextboxBridge(kBridgeTalkerHarryMuddsVoice, 11);
showTextboxBridge(kBridgeTalkerKirk, 12);
showTextboxBridge(kBridgeTalkerUhura, 13);
showBridgeScreenTalkerWithMessage(15, "Harry Mudd", "mudd", false);
showTextboxBridge(kBridgeTalkerKirk, 16);
showTextboxBridge(kBridgeTalkerHarryMudd, 17);
removeActorFromScreen(_currentScreenTalker);
initStarfieldSprite(&_starfieldSprite, new StubBitmap(0, 0), _starfieldRect);
showTextboxBridge(kBridgeTalkerSpock, 18);
break;
case kSeqEndMissionMudd:
_resource->setTxtFileName("MUDD");
loadActorAnim(1, ACTOR_STANDING_SPOCK, 0, 0, 1.0); // Standing Spock
loadActorAnim(2, ACTOR_STANDING_MCCOY, 0, 0, 1.0); // Standing McCoy
showMissionPerformance(_awayMission.mudd.missionScore * 100 / 32, 35, 3);
if (_missionEndFlag != 0) {
// Obtained alien contraption
showTextboxBridge(kBridgeTalkerScotty, 36);
showTextboxBridge(kBridgeTalkerKirk, 37);
} else {
// Did not obtain alien contraption
showTextboxBridge(kBridgeTalkerKirk, 38);
}
showTextboxBridge(kBridgeTalkerUhura, 41);
showTextboxBridge(kBridgeTalkerKirk, 42);
showTextboxBridge(kBridgeTalkerUhura, 43);
showTextboxBridge(kBridgeTalkerKirk, 44);
loadActorAnim(1, ACTOR_SITTING_SPOCK, 0, 0, 1.0);
removeActorFromScreen(2);
_bridgeSequenceToLoad = kSeqStartMissionFeather;
break;
case kSeqStartMissionFeather:
_targetPlanet = kPlanetDigifal; // We set it earlier for uniformity
_missionName = _missionToLoad = "FEATHER";
_resource->setTxtFileName(_missionName);
_sound->loadMusicFile("bridgeb");
// TODO: sub_321F9()
showMissionStartEnterpriseFlyby("FEA0\\FLYBY", "feather");
showTextboxBridge(kBridgeTalkerKirk, 5); // Captain's log, Stardate 5097.3. Starfleet reports major military activity...
// TODO
break;
case kSeqUnk20:
// TODO
break;
case kSeqEndMissionFeather:
_resource->setTxtFileName("FEATHER");
_enterpriseState.underAttack = false;
orbitPlanet(); // 1,1
_gfx->fadeinScreen();
// orbitPlanet(); // 0,0
showTextboxBridge(kBridgeTalkerUhura, 21);
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 22);
//addAction
showBridgeScreenTalkerWithMessage(23, "Admiral Kenka", "klg2", false);
// TODO: Show dialog options
showTextboxBridge(kBridgeTalkerAdmiralKenka, 24);
showTextboxBridge(kBridgeTalkerKirk, 25);
showTextboxBridge(kBridgeTalkerAdmiralKenka, 26);
// TODO: Show dialog options
showTextboxBridge(kBridgeTalkerAdmiralKenka, 27);
showTextboxBridge(kBridgeTalkerUhura, 28);
showTextboxBridge(kBridgeTalkerKirk, 29);
showTextboxBridge(kBridgeTalkerAdmiralKenka, 30);
showBridgeScreenTalkerWithMessage(31, "Admiral", "woman");
showTextboxBridge(kBridgeTalkerScotty, 32);
showTextboxBridge(kBridgeTalkerKirk, 33);
//showFullScreenStarMap
//mouseControllingShip = false
//sub_346C6()
_currentPlanet = _targetPlanet = kPlanetHrakkour;
_bridgeSequenceToLoad = kSeqStartMissionTrial;
// TODO: Battle with the K'lrta
break;
case kSeqStartMissionTrial:
_currentPlanet = _targetPlanet = kPlanetHrakkour;
_missionName = _missionToLoad = "TRIAL";
_resource->setTxtFileName(_missionName);
orbitPlanet();
showTextboxBridge(kBridgeTalkerKirk, 0); // Captain's Log. We have come to the ruined Klingon planet of Hrakkour...
// TODO
break;
case kSeqEndMissionTrial:
// In the original, this was in the same function as the start. It's a separate function in our implementation
_resource->setTxtFileName("TRIAL");
orbitPlanet(); // 0,0
// TODO: Also handle bad ending with inflammatory remarks
switch (_awayMission.trial.missionEndMethod) {
case 0:
// Bad ending, returned to enterprise in the middle of the trial
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 1);
showBridgeScreenTalkerWithMessage(2, "Admiral Kenka", "klg2");
showTextboxBridge(kBridgeTalkerUhura, 3);
showTextboxBridge(kBridgeTalkerKirk, 4);
break;
case 1:
case 2:
// Bad ending, Queztecoatl died
showTextboxBridge(kBridgeTalkerKirk, 5);
showTextboxBridge(kBridgeTalkerSpock, 6);
showTextboxBridge(kBridgeTalkerKirk, 7);
showTextboxBridge(kBridgeTalkerSpock, 8);
showTextboxBridge(kBridgeTalkerKirk, 9);
break;
case 3:
// Bad ending, people died
showTextboxBridge(kBridgeTalkerSulu, 10);
showTextboxBridge(kBridgeTalkerKirk, 11);
showTextboxBridge(kBridgeTalkerSpock, 12);
showTextboxBridge(kBridgeTalkerKirk, 13);
break;
case 4:
// Good ending
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 17);
showBridgeScreenTalkerWithMessage(18, "Kallarax", "klg1", false);
// TODO: dialog options
showTextboxBridge(kBridgeTalkerKallarax, 19);
removeActorFromScreen(_currentScreenTalker);
initStarfieldSprite(&_starfieldSprite, new StubBitmap(0, 0), _starfieldRect);
showTextboxBridge(kBridgeTalkerUhura, 20); // Quetzecoatl is safely aboard, Captain, and wishes to return to his home world
showTextboxBridge(kBridgeTalkerKirk, 21);
break;
}
//showFullScreenStarfield();
//mouseControllingShip = false;
showMissionPerformance(_awayMission.trial.missionScore * 100 / 32, 26, 4);
_bridgeSequenceToLoad = kSeqStartMissionSins;
break;
case kSeqStartMissionSins:
_targetPlanet = kPlanetAlphaProxima; // We set it earlier for uniformity
_missionName = _missionToLoad = "SINS";
_resource->setTxtFileName(_missionName);
_sound->loadMusicFile("bridge");
showMissionStartEnterpriseFlyby("SIN0\\FLYBY", "devilmon");
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 0);
showTextboxBridge(kBridgeTalkerKirk, 1);
showBridgeScreenTalkerWithMessage(2, "Admiral", "woman");
showTextboxBridge(kBridgeTalkerSpock, 3);
showTextboxBridge(kBridgeTalkerKirk, 4);
showTextboxBridge(kBridgeTalkerSpock, 5);
showTextboxBridge(kBridgeTalkerChekov, 6);
showTextboxBridge(kBridgeTalkerSpock, 7);
showTextboxBridge(kBridgeTalkerKirk, 8);
showTextboxBridge(kBridgeTalkerSpock, 9);
// TODO
break;
case kSeqEndMissionSins:
// TODO: The rest before the sequence - check for crew actions etc
updateStarfieldAndShips(0);
_resource->setTxtFileName("SINS");
loadActorAnim(1, ACTOR_STANDING_SPOCK, 0, 0, 1.0); // Standing Spock
loadActorAnim(2, ACTOR_STANDING_MCCOY, 0, 0, 1.0); // Standing McCoy
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 22);
showTextboxBridge(kBridgeTalkerKirk, 23);
showMissionPerformance(_awayMission.sins.missionScore * 100 / 32, 24, 5);
showTextboxBridge(kBridgeTalkerMcCoy, 25);
showTextboxBridge(kBridgeTalkerSpock, 26);
showTextboxBridge(kBridgeTalkerMcCoy, 27);
showTextboxBridge(kBridgeTalkerKirk, 28);
showTextboxBridge(kBridgeTalkerKirk, 29);
showTextboxBridge(kBridgeTalkerMcCoy, 30);
showTextboxBridge(kBridgeTalkerKirk, 31);
loadActorAnim(1, ACTOR_SITTING_SPOCK, 0, 0, 1.0);
removeActorFromScreen(2);
_bridgeSequenceToLoad = kSeqStartMissionVeng;
break;
case kSeqStartMissionVeng:
_missionName = _missionToLoad = "VENG";
_resource->setTxtFileName(_missionName);
_sound->loadMusicFile("bridgew");
showMissionStartEnterpriseFlyby("VEN0\\FLYBY", "vengence"); // a typo in the original
showTextboxBridge(kBridgeTalkerKirk, 10);
showTextboxBridge(kBridgeTalkerSpock, 11);
showTextboxBridge(kBridgeTalkerKirk, 12);
showTextboxBridge(kBridgeTalkerUhura, 13);
// TODO
break;
case kSeqEndMissionVengAndGame:
_resource->setTxtFileName("VENG");
if (_enterpriseState.underAttack) {
_sound->playSoundEffectIndex(kSfxRedAlert);
showTextboxBridge(kBridgeTalkerSpock, 34);
startBattle("3PIRATE");
startBattle("orion");
} else {
showTextboxBridge(kBridgeTalkerSpock, 37);
showTextboxBridge(kBridgeTalkerKirk, 38);
showTextboxBridge(kBridgeTalkerScotty, 39);
showTextboxBridge(kBridgeTalkerChekov, 40);
showTextboxBridge(kBridgeTalkerKirk, 41);
showTextboxBridge(kBridgeTalkerUhura, 42);
showTextboxBridge(kBridgeTalkerKirk, 43);
showMissionPerformance(_awayMission.veng.missionScore * 100 / 32, 44, 6);
// TODO: The rest
}
break;
default:
break;
}
}
struct CrewTextsForChapter {
int targetPlanet;
int talker;
int underAttackTextId;
int notReachedPlanetTextId;
int notInOrbitTextId;
int inOrbitTextId;
};
CrewTextsForChapter crewTexts[] = {
// -- Chapter 1 ----
{ kPlanetPollux, kBridgeTalkerSpock, 10, 20, 21, 22 },
{ kPlanetPollux, kBridgeTalkerUhura, 9, 16, 19, 19 },
// -- Chapter 2 ----
{ kPlanetBetaMyamid, kBridgeTalkerSpock, 13, 5, 17, 27 },
{ kPlanetBetaMyamid, kBridgeTalkerUhura, 12, 4, 16, -1 },
// -- Chapter 3 ----
{ kPlanetArk7, kBridgeTalkerSpock, 8, 4, -1, 13 },
{ kPlanetArk7, kBridgeTalkerUhura, 7, 5, -1, -1 },
// -- Chapter 4 ----
{ kPlanetHarlequin, kBridgeTalkerSpock, 21, 4, 22, -1 },
{ kPlanetHarlequin, kBridgeTalkerUhura, 19, 3, 20, -1 },
// -- Chapter 6 ----
{ kPlanetAlphaProxima, kBridgeTalkerSpock, -1, 11, -1, -1 },
{ kPlanetAlphaProxima, kBridgeTalkerUhura, -1, 10, -1, -1 },
// TODO: The rest
{ kPlanetNone, kBridgeTalkerNone, 0, 0, 0, 0 }
};
void StarTrekEngine::bridgeCrewAction(int crewId) {
CrewTextsForChapter *curCrewTexts = crewTexts;
int textId = -1;
const char *underAttackText = "#BRID\\B_348#Unable to comply, Captain. We're under attack.";
const char *missionNotOverText = "#BRID\\B_338#May I respectfully remind the Captain that we haven't accomplished our mission, Sir.";
const char *leaveOrbitText = "#BRID\\B_349#We must first leave orbit, Sir.";
const char *nothingToReportText = "#BRID\\B_155 #Nothing to report, Captain.";
const char *hailingFrequenciesOpenText = "#BRID\\BRIDU016#Hailing frequencies open.";
const char *shieldsUpText = "#BRID\\B_332#Captain, the shields are up.";
const char *notInOrbitText = "#BRID\\B_350#We're not in orbit, Captain.";
const char *wrongDestinationText = "#BRID\\B_346#This isn't our destination.";
const char *transporterText = "#BRID\\C_060#Spock, come with me. Mr Scott, you have the conn.";
const char *transporterTextFeather = "#BRID\\C_006#Assemble a landing party. Unless we find this so-called criminal, we're going to war.";
switch (crewId) {
case kBridgeTalkerSpock:
case kBridgeTalkerUhura:
while (curCrewTexts->targetPlanet != kPlanetNone) {
if (_targetPlanet == curCrewTexts->targetPlanet && curCrewTexts->talker == crewId) {
if (_enterpriseState.underAttack) {
textId = curCrewTexts->underAttackTextId;
} else if (_currentPlanet != _targetPlanet) {
textId = curCrewTexts->notReachedPlanetTextId;
} else if (!_enterpriseState.inOrbit) {
textId = curCrewTexts->notInOrbitTextId;
} else {
textId = curCrewTexts->inOrbitTextId;
}
break;
}
curCrewTexts++;
}
// Uhura's hailing sequences
if (crewId == kBridgeTalkerUhura && _currentPlanet == _targetPlanet) {
if (!_hailedTarget) {
contactTargetAction();
_hailedTarget = true;
return;
} else if (_currentPlanet == kPlanetBetaMyamid && _hailedTarget) {
hailTheMasada();
return;
}
}
break;
case kBridgeTalkerChekov:
if (_enterpriseState.underAttack) {
showTextboxBridge(kBridgeTalkerSulu, underAttackText);
} else if (_currentPlanet == _targetPlanet) {
showTextboxBridge(kBridgeTalkerSulu, missionNotOverText);
} else if (_enterpriseState.inOrbit) {
showTextboxBridge(kBridgeTalkerSulu, leaveOrbitText);
} else {
showStarMap();
if (_currentPlanet != _targetPlanet) {
wrongDestinationRandomEncounter();
// TODO: Redraw sprites
}
}
break;
case kBridgeTalkerSulu:
if (_enterpriseState.underAttack) {
showTextboxBridge(kBridgeTalkerSulu, underAttackText);
} else if (_currentPlanet == _targetPlanet && _enterpriseState.inOrbit) {
showTextboxBridge(kBridgeTalkerSulu, missionNotOverText);
} else {
if (_targetPlanet == kPlanetBetaMyamid) {
orbitPlanetSequence(6);
_bridgeSequenceToLoad = kSeqApproachedTheMasada;
} else if (_targetPlanet == kPlanetHarlequin) {
orbitPlanetSequence(5);
}
orbitPlanet();
}
break;
case kBridgeTalkerKirk:
if (_enterpriseState.shields) {
showTextboxBridge(kBridgeTalkerSulu, shieldsUpText);
} else if (!_enterpriseState.inOrbit) {
showTextboxBridge(kBridgeTalkerSulu, notInOrbitText);
} else if (_currentPlanet != _targetPlanet) {
showTextboxBridge(kBridgeTalkerSulu, wrongDestinationText);
} else {
if (_targetPlanet == kPlanetBetaMyamid && !_beamDownAllowed) {
// Chapter 2, disallow beaming down until the correct code is set
showTextboxBridge(kBridgeTalkerSulu, 28); // Captain, the Masada's shields are still up
} else {
if (_missionToLoad != "FEATHER")
showTextboxBridge(kBridgeTalkerKirk, transporterText);
else
showTextboxBridge(kBridgeTalkerKirk, transporterTextFeather);
_gameMode = GAMEMODE_BEAMDOWN;
}
}
break;
}
if (textId >= 0) {
showTextboxBridge(crewId, textId);
} else if (crewId == kBridgeTalkerSpock) {
showTextboxBridge(crewId, nothingToReportText);
} else if (crewId == kBridgeTalkerUhura) {
showTextboxBridge(crewId, hailingFrequenciesOpenText);
}
}
void StarTrekEngine::contactTargetAction() {
switch (_targetPlanet) {
case kPlanetPollux: // Chapter 1: Demon world (demon)
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 17);
showBridgeScreenTalkerWithMessage(18, "Priest", "prst");
break;
case kPlanetBetaMyamid: // Chapter 2: Hijacked (tug)
if (!_hailedTarget) {
showTextboxBridge(kBridgeTalkerUhura, 21);
showBridgeScreenTalkerWithMessage(65, "Elasi Captain", "pira", false);
negotiateWithElasiCereth();
removeActorFromScreen(_currentScreenTalker);
initStarfieldSprite(&_starfieldSprite, new StubBitmap(0, 0), _starfieldRect);
} else {
hailTheMasada();
}
break;
case kPlanetArk7: // Chapter 3: Love's Labor Jeopardized (love)
_sound->playSoundEffectIndex(kSfxHailing);
showTextboxBridge(kBridgeTalkerUhura, 14);
showBridgeScreenTalkerWithMessage(15, "Centurion Preax", "romula");
break;
// TODO: The rest
}
}
void StarTrekEngine::negotiateWithElasiCereth() {
// TODO: Read these from tug.txt
const char *options1[] = {
"Captain Kirk",
"#BRID\\C_074#This is Captain James T. Kirk of the U.S.S. Enterprise. You are illegally in possession of Starfleet property.",
"#BRID\\C_072#This is Captain James T. Kirk of the U.S.S. Enterprise. Listen, Elasi, hand over the ship and hostages now or things are going to get very nasty.",
"#BRID\\C_073#This is Captain James T. Kirk of the U.S.S. Enterprise. Mr. Elasi, it appears that you have found something that Starfleet lost.",
""
};
const char *options2[] = {
"Captain Kirk",
"#BRID\\C_026#Freeing the prisoners you requested will take time. We have to track down their current locations, and Starfleet will have to grant permission to move them here. I will get that started - you should tender a show of good faith on your part. Will you beam over so we can discuss negotiations face to face?",
"#BRID\\C_091#We can work together on this, Elasi. How about beaming some of the hostages over as a show of good faith?",
""
};
const char *options3[] = {
"Captain Kirk",
"#BRID\\C_077#Very well, we'll do it your way. I will put together the data packet. Kirk out.",
"#BRID\\C_102#Your fellow Elasi have been tried in Federation courts of law, and found guilty of their crimes. We'll listen to your complaints if you discuss them reasonably.",
"#BRID\\C_014#Forget it. Elasi Cereth, you'll be the next one languishing on a Federation penal planet unless you drop your shields and surrender to me immediately.",
""
};
int choice = showText(&StarTrekEngine::readTextFromArrayWithChoices, (uintptr)options1, 160, 130, 176, true, false, false);
if (choice == 0) {
showTextboxBridge(kBridgeTalkerElasiCereth, 44); // Ah, the infamous captain Kirk...
showTextboxBridge(kBridgeTalkerUhura, 45);
} else if (choice == 1) {
showTextboxBridge(kBridgeTalkerElasiCereth, 46); // Well, Kirk, someone is about to pay the price for your insolence
showTextboxBridge(kBridgeTalkerSpock, 60);
_deadMasadaPrisoners++;
} else if (choice == 2) {
showTextboxBridge(kBridgeTalkerElasiCereth, 47);
showTextboxBridge(kBridgeTalkerElasiCereth, 44); // Ah, the infamous captain Kirk...
showTextboxBridge(kBridgeTalkerUhura, 45);
}
showText(&StarTrekEngine::readTextFromArrayWithChoices, (uintptr)options2, 160, 130, 176, true, false, false);
// The choice here makes no difference
showTextboxBridge(kBridgeTalkerElasiCereth, 51);
showTextboxBridge(kBridgeTalkerScotty, 52);
showTextboxBridge(kBridgeTalkerSulu, 53);
showTextboxBridge(kBridgeTalkerElasiCereth, 54);
choice = showText(&StarTrekEngine::readTextFromArrayWithChoices, (uintptr)options3, 160, 130, 176, true, false, false);
if (choice == 0) {
// End of dialog
} else if (choice == 1) {
showTextboxBridge(kBridgeTalkerElasiCereth, 69);
} else if (choice == 2) {
showTextboxBridge(kBridgeTalkerElasiCereth, 70);
showTextboxBridge(kBridgeTalkerSpock, 60);
_deadMasadaPrisoners++;
showTextboxBridge(kBridgeTalkerElasiCereth, 71);
// The original checks for 4 dead prisoners here, but that is impossible at this point
}
// There are some more checks for dialog choices here, but all seem to be dead code
}
void StarTrekEngine::hailTheMasada() {
// TODO: Read these from tug.txt
const char *options[] = {
"Captain Kirk",
"Hail the Masada.",
"Send prefix code.",
""
};
int choice = showText(&StarTrekEngine::readTextFromArrayWithChoices, (uintptr)options, 160, 130, 176, true, false, false);
if (choice == 0) {
showTextboxBridge(kBridgeTalkerUhura, 21);
showBridgeScreenTalkerWithMessage(22, "Elasi Cereth", "pira", false);
showTextboxBridge(kBridgeTalkerKirk, 23);
removeActorFromScreen(_currentScreenTalker);
initStarfieldSprite(&_starfieldSprite, new StubBitmap(0, 0), _starfieldRect);
showTextboxBridge(kBridgeTalkerSpock, 60);
_deadMasadaPrisoners++;
if (_deadMasadaPrisoners > 4) {
_missionEndFlag = 2;
_bridgeSequenceToLoad = kSeqEndMissionTug;
}
} else {
Common::String code = showCodeInputBox();
if (code == "293391-197736-3829") {
showTextboxBridge(kBridgeTalkerUhura, 25);
_beamDownAllowed = true;
} else {
showTextboxBridge(kBridgeTalkerUhura, 26);
}
}
}
Common::String StarTrekEngine::getSpeechSampleForNumber(int number) {
const char *speechTemplate = ",BRID\\B_%03d";
Common::String result;
if (number <= 19) {
// Speech samples 228 ("zero") - 247 ("nineteen")
result = Common::String::format(speechTemplate, number + 228);
} else if (number >= 20 && number <= 99) {
// Speech samples 248 ("twenty") - 255 ("ninety")
result = Common::String::format(speechTemplate, number / 10 - 2 + 248);
if (number % 10 > 0)
result += Common::String::format(speechTemplate, number % 10 + 228);
} else if (number == 100) {
result = Common::String::format(speechTemplate, 256);
}
return result;
}
// TODO: one more parameter
void StarTrekEngine::showMissionPerformance(int score, int missionScoreTextId, int missionId) {
Common::String performanceDescription;
int midiTrack = 0;
int commendationPoints = 0;
if (score >= 0 && score <= 50) {
performanceDescription = "#BRID\\B_199#I'll be frank, Kirk. Starfleet expects more of you than that. Try to do better on your next assignment.";
commendationPoints = 0;
midiTrack = 13;
} else if (score >= 60 && score <= 70) {
performanceDescription = "#BRID\\B_197#A satisfactory performance, Captain, but there's still room for improvement.";
commendationPoints = 1;
midiTrack = 13;
} else if (score >= 71 && score <= 85) {
performanceDescription = "#BRID\\B_214#Well done, Captain. Keep up the good work.";
commendationPoints = 2;
midiTrack = 11;
} else if (score >= 86 && score <= 99) {
performanceDescription = "#BRID\\B_414#The top brass at Starfleet are impressed. Outstanding work, Jim.";
commendationPoints = 3;
midiTrack = 12;
} else if (score == 100) {
performanceDescription = "#BRID\\B_195#A perfect mission, Jim! You are a model for all Starfleet!";
commendationPoints = 4;
midiTrack = 14;
}
_sound->playMidiMusicTracks(midiTrack, -1);
Common::String speechIdPerformance = getSpeechSampleForNumber(score);
Common::String speechIdCommendationPoints = getSpeechSampleForNumber(commendationPoints);
Common::String missionPerformanceText = Common::String::format(
_resource->getLoadedText(missionScoreTextId).c_str(),
speechIdPerformance.c_str(),
speechIdCommendationPoints.c_str(),
score,
commendationPoints
);
Common::String texts[] = {
missionPerformanceText,
performanceDescription,
""
};
showBridgeScreenTalkerWithMessages(texts, "Admiral", "woman");
_lastMissionId = missionId;
_missionPoints[missionId] = commendationPoints;
}
void StarTrekEngine::showBridgeScreenTalkerWithMessage(int textId, Common::String talkerHeader, Common::String talkerId, bool removeTalker) {
Common::String text = _resource->getLoadedText(textId);
Common::String texts[] = {
text,
""
};
showBridgeScreenTalkerWithMessages(texts, talkerHeader, talkerId, removeTalker);
}
void StarTrekEngine::showBridgeScreenTalkerWithMessages(Common::String texts[], Common::String talkerHeader, Common::String talkerId, bool removeTalker) {
if (talkerId == "romula" || talkerId == "pira" || talkerId == "klg1" || talkerId == "klg2" || talkerId == "maddoc")
_sound->playMidiMusicTracks(15, -1);
else if (talkerId == "mudd")
_sound->playMidiMusicTracks(17, -1);
initStarfieldSprite(&_starfieldSprite, new Bitmap(_resource->loadBitmapFile(talkerId)), _starfieldRect);
_starfieldSprite.drawMode = 0;
_currentScreenTalker = loadActorAnim(-1, talkerId, 72 + _starfieldSprite.bitmap->xoffset - 2, 30 + _starfieldSprite.bitmap->yoffset, 1.0);
int i = 0;
Common::String text = texts[i];
while (text != "") {
showTextbox(talkerHeader, text, 160, 190, 44, 0);
text = texts[++i];
}
if (removeTalker) {
removeActorFromScreen(_currentScreenTalker);
initStarfieldSprite(&_starfieldSprite, new StubBitmap(0, 0), _starfieldRect);
}
}
void StarTrekEngine::bridgeLeftClick() {
Sprite *sprite = _gfx->getSpriteAt(_gfx->getMousePos());
int clickedActor = -1;
if (sprite == nullptr)
return;
for (int i = 0; i < NUM_ACTORS; i++) {
Actor *actor = &_actorList[i];
if (sprite == &actor->sprite) {
clickedActor = i;
break;
}
}
if (clickedActor == -1)
return;
for (int i = 0; i < ARRAYSIZE(bridgeActorsAndMenus); ++i) {
BridgeActorAndMenu a = bridgeActorsAndMenus[i];
if (a.id == clickedActor) {
showBridgeMenu(a.menu, a.x, a.y);
break;
}
}
}
void StarTrekEngine::cleanupBridge() {
// TODO
// if (!v_starfieldInitialized)
// sub_12691()
// else
// clearScreenAndDelSeveralSprites()
// v_mouseControllingShip = 0
// v_keyboardControlsMouse = 1
}
void StarTrekEngine::runBridge() {
while (_gameMode == GAMEMODE_BRIDGE && !_resetGameMode) {
handleBridgeEvents();
// TODO: pseudo-3D related functionality
if (_bridgeSequenceToLoad != kSeqNone) {
int bridgeSequence = _bridgeSequenceToLoad;
_bridgeSequenceToLoad = kSeqNone;
playBridgeSequence(bridgeSequence);
}
}
}
void StarTrekEngine::handleBridgeEvents() {
TrekEvent event;
if (popNextEvent(&event)) {
if (_gameIsPaused) {
if (event.type == TREKEVENT_LBUTTONDOWN || event.type == TREKEVENT_KEYDOWN) {
_gameIsPaused = false;
}
return;
}
switch (event.type) {
case TREKEVENT_TICK:
updateActorAnimations();
//updateMouseBitmap();
renderBanBelowSprites();
_gfx->drawAllSprites(false);
renderBanAboveSprites();
_gfx->updateScreen();
_sound->checkLoopMusic();
_frameIndex++;
_roomFrameCounter++;
addAction(ACTION_TICK, _roomFrameCounter & 0xff, (_roomFrameCounter >> 8) & 0xff, 0);
if (_roomFrameCounter >= 2)
_gfx->incPaletteFadeLevel();
break;
case TREKEVENT_LBUTTONDOWN:
bridgeLeftClick();
break;
case TREKEVENT_MOUSEMOVE:
// TODO
break;
case TREKEVENT_RBUTTONDOWN:
// TODO
break;
case TREKEVENT_KEYDOWN:
switch (event.kbd.keycode) {
case Common::KEYCODE_w: // Toggle weapons on/off
handleBridgeMenu(kBridgeChekovWeapons);
break;
case Common::KEYCODE_s: // Toggle shields on/off
handleBridgeMenu(kBridgeSuluShields);
break;
case Common::KEYCODE_a: // Target analysis
handleBridgeMenu(kBridgeSuluTargetAnalysis);
break;
case Common::KEYCODE_d: // Damage control
handleBridgeMenu(kBridgeScottyDamageControl);
break;
case Common::KEYCODE_RETURN:
case Common::KEYCODE_KP_ENTER:
case Common::KEYCODE_F1:
// Fire phasers
// TODO
break;
case Common::KEYCODE_SPACE: // Fire photon torpedoes
// TODO
break;
case Common::KEYCODE_v: // Toggle between the normal bridge view and full screen view
// TODO
break;
case Common::KEYCODE_TAB: // Toggle between movement/fire mode and crew selection mode
// TODO
break;
case Common::KEYCODE_COMMA: // Reduce the main view screen magnification
// TODO
break;
case Common::KEYCODE_PERIOD: // Enlarge the main view screen magnification
// TODO
break;
case Common::KEYCODE_o: // Enter/exit orbit
handleBridgeMenu(kBridgeSuluOrbit);
break;
case Common::KEYCODE_KP5: // Center controls
// TODO
break;
case Common::KEYCODE_n: // Main star navigational map
handleBridgeMenu(kBridgeChekovNavigation);
break;
case Common::KEYCODE_k: // Kirk's options
handleBridgeMenu(kBridgeKirkOptions);
break;
case Common::KEYCODE_t: // Ask Mr. Spock for advice
handleBridgeMenu(kBridgeSpock);
break;
case Common::KEYCODE_c: // Spock's library computer
handleBridgeMenu(kBridgeSpockComputer);
break;
case Common::KEYCODE_h: // Uhura's communication icon
handleBridgeMenu(kBridgeUhura);
break;
case Common::KEYCODE_p: // Pause game
_gameIsPaused = true;
break;
case Common::KEYCODE_e: // Toggle SFX / emergency power
if (event.kbd.flags & Common::KBD_CTRL)
_sound->toggleSfx();
else
handleBridgeMenu(kBridgeScottyEmergencyPower);
break;
case Common::KEYCODE_m:
if (event.kbd.flags & Common::KBD_CTRL)
_sound->toggleMusic();
break;
case Common::KEYCODE_q:
if (event.kbd.flags & Common::KBD_CTRL)
showQuitGamePrompt(20, 20);
break;
case Common::KEYCODE_TILDE: // Ship speed: reverse
// TODO
break;
case Common::KEYCODE_1: // Ship speed: stop
// TODO
break;
case Common::KEYCODE_2:
case Common::KEYCODE_3:
case Common::KEYCODE_4:
case Common::KEYCODE_5:
case Common::KEYCODE_6:
case Common::KEYCODE_7:
case Common::KEYCODE_8:
case Common::KEYCODE_9:
case Common::KEYCODE_0:
// Ship speed: toggle slow -> fast
// TODO
break;
default:
break;
}
break;
default:
break;
}
}
}
void StarTrekEngine::handleBridgeMenu(int menuEvent) {
const char *raiseShieldsText = "#BRID\\B_340#Raising shields.";
const char *lowerShieldsText = "#BRID\\B_337#Lowering shields, Captain.";
const char *armWeaponsText = "#BRID\\B_351#Arming weapons.";
const char *disarmWeaponsText = "#BRID\\B_354#Disarming weapons.";
//const char *emergencyPowerText = "#BRID\\BRID_S32#I don't know how long she can take it, Captain.";
const char *noEmergencyPowerText = "#BRID\\BRID_S41#She can't take it, Captain.";
const char *targetAnalysisOnText = "#BRID\\B_344#Target Analysis On.";
const char *targetAnalysisOffText = "#BRID\\B_343#Target Analysis Off.";
const char *ayeSirText = "#BRID\\BRID_S22#Aye Sir.";
switch (menuEvent) {
case kBridgeKirkCommand:
showBridgeMenu("command", 60, 100);
break;
case kBridgeUnk1:
// TODO
break;
case kBridgeUnk2:
// TODO
break;
case kBridgeStarfieldFullScreen:
// TODO
break;
case kBridgeKirkCaptainsLog: // Kirk, captain's log
captainsLog();
break;
case kBridgeKirkTransporter: // Kirk, transporter
bridgeCrewAction(kBridgeTalkerKirk);
break;
case kBridgeKirkOptions: // Kirk, options
showOptionsMenu(65, 60);
break;
case kBridgeSpock: // Spock, consult
bridgeCrewAction(kBridgeTalkerSpock);
break;
case kBridgeSpockComputer: // Spock, consult computer
handleBridgeComputer();
break;
case kBridgeScottyDamageControl: // Scotty, damage control
showBridgeMenu("repair", 30, 30);
break;
case kBridgeScottyEmergencyPower: // Scotty, emergency power
// TODO: check for emergency power
showTextboxBridge(kBridgeTalkerScotty, noEmergencyPowerText);
break;
case kBridgeUhura: // Uhura, communications
bridgeCrewAction(kBridgeTalkerUhura);
break;
case kBridgeSuluOrbit: // Sulu, orbit
bridgeCrewAction(kBridgeTalkerSulu);
break;
case kBridgeSuluShields: // Sulu, shields
_enterpriseState.shields = !_enterpriseState.shields;
showTextboxBridge(kBridgeTalkerSulu, _enterpriseState.shields ? raiseShieldsText : lowerShieldsText);
break;
case kBridgeChekovNavigation: // Chekov, navigation
bridgeCrewAction(kBridgeTalkerChekov);
break;
case kBridgeChekovWeapons: // Chekov, weapons
_enterpriseState.weapons = !_enterpriseState.weapons;
showTextboxBridge(kBridgeTalkerChekov, _enterpriseState.weapons ? armWeaponsText : disarmWeaponsText);
setBridgeMouseCursor();
break;
case kBridgeChekovRepairShields:
case kBridgeChekovRepairPhasers:
case kBridgeChekovRepairPhotonTorpedoes:
case kBridgeChekovRepairSensors:
case kBridgeChekovRepairBridge:
case kBridgeChekovRepairHull:
case kBridgeChekovRepairWarpDrives:
// TODO: Repair ship part (-1, 4, 2, 6, 1, 0, 7)
showTextboxBridge(kBridgeTalkerScotty, ayeSirText);
break;
case kBridgeSuluTargetAnalysis: // Chekov, target analysis
_enterpriseState.targetAnalysis = !_enterpriseState.targetAnalysis;
showTextboxBridge(kBridgeTalkerSulu, _enterpriseState.targetAnalysis ? targetAnalysisOnText : targetAnalysisOffText);
// TODO: Target analysis
break;
default:
break;
}
}
void StarTrekEngine::showStarMap() {
// HACK: Move to the target planet and play its associated sequence, until the starmap code is implemented
_currentPlanet = _targetPlanet;
switch (_targetPlanet) {
case kPlanetPollux:
_bridgeSequenceToLoad = kSeqArrivedAtPolluxV;
break;
case kPlanetBetaMyamid:
_bridgeSequenceToLoad = kSeqStartElasiPirateBattle;
break;
case kPlanetArk7:
_bridgeSequenceToLoad = kSeqStartRomulanBattle;
break;
case kPlanetHarlequin:
_bridgeSequenceToLoad = kSeqFightElasiShipsAndContactMudd;
break;
case kPlanetDigifal:
_bridgeSequenceToLoad = kSeqStartMissionFeather;
break;
case kPlanetHrakkour:
_bridgeSequenceToLoad = kSeqStartMissionTrial;
break;
case kPlanetAlphaProxima:
// This shouldn't be called for Mission 6 (sins)
break;
}
// TODO
}
void StarTrekEngine::showMissionStartEnterpriseFlyby(Common::String sequence, Common::String name) {
// TODO
}
void StarTrekEngine::startBattle(Common::String enemyShip) {
// TODO
}
void StarTrekEngine::wrongDestinationRandomEncounter() {
_randomEncounterType = _randomSource.getRandomNumberRng(1, 3);
switch (_randomEncounterType) {
case kRandomEncounterKlingon:
_resource->setTxtFileName("klingon");
break;
case kRandomEncounterRomulan:
_resource->setTxtFileName("romulan");
break;
case kRandomEncounterElasi:
_resource->setTxtFileName("elasi");
break;
default:
break;
}
// TODO: The rest
_enterpriseState.underAttack = true;
_sound->loadMusicFile("bridge"); // TODO: check for bridgeb
}
// Used when approaching Beta Myamid / Masada in chapter 2, and Ark 7 in chapter 3
void StarTrekEngine::orbitPlanetSequence(int sequenceId) {
// TODO
}
void StarTrekEngine::orbitPlanet() {
const char *enteringOrbitText = "#BRID\\B_333#Entering standard orbit.";
const char *leavingOrbitText = "#BRID\\B_335#Leaving orbit.";
// TODO: Show starfield
// TODO: Warp to planet, if needed
// TODO: Update sprites
_enterpriseState.inOrbit = !_enterpriseState.inOrbit;
showTextboxBridge(kBridgeTalkerSulu, _enterpriseState.inOrbit ? enteringOrbitText : leavingOrbitText);
}
void StarTrekEngine::captainsLog() {
const char *missionNames[] = {
"Demon World",
"Hijacked",
"Love's Labor Jeopardized",
"Another Fine Mess",
"Feathered Serpent",
"That Old Devil Moon",
"Vengeance"
};
int totalPoints = 0;
for (int i = 0; i < 7; i++)
totalPoints += _missionPoints[i];
Common::String captainsLogMessage = "";
if (_lastMissionId > -1) {
captainsLogMessage = Common::String::format(
"#BRID\\C_007#We have earned %d point",
totalPoints
);
if (totalPoints > 1)
captainsLogMessage += "s";
captainsLogMessage += " for the following recently completed missions:\n";
for (int i = 6; i >= 0; i--) {
captainsLogMessage += missionNames[i] + Common::String::format(": %d point", _missionPoints[i]);
if (_missionPoints[i] > 1)
captainsLogMessage += "s";
captainsLogMessage += ".\n\n";
}
} else {
captainsLogMessage = "#BRID\\C_007#No recent missions have been completed.";
}
showTextboxBridge(kBridgeTalkerCaptainsLog, captainsLogMessage);
}
void StarTrekEngine::loadBridgeComputerTopics() {
Common::MemoryReadStreamEndian *indexFile = _resource->loadFile("db.key");
Common::String line;
while (!indexFile->eos() && !indexFile->err()) {
line = indexFile->readLine();
if (line == "$")
break;
ComputerTopic topic;
topic.fileName = line.substr(0, 7);
topic.topic = line.substr(8);
_computerTopics.push_back(topic);
}
delete indexFile;
}
void StarTrekEngine::handleBridgeComputer() {
Common::String line;
Common::String input = showComputerInputBox();
if (input.size() < 3)
return;
char topics[10][8];
int topicIndex = 0;
memset(topics, 0, ARRAYSIZE(topics) * 8);
for (Common::List<ComputerTopic>::const_iterator i = _computerTopics.begin(), end = _computerTopics.end(); i != end; ++i) {
if (i->topic.hasPrefixIgnoreCase(input)) {
memcpy(topics[topicIndex++], i->fileName.c_str(), i->fileName.size());
if (topicIndex >= ARRAYSIZE(topics))
break;
}
}
showText(&StarTrekEngine::readTextFromFoundComputerTopics, (uintptr)topics, 20, 20, TEXTCOLOR_YELLOW, true, false, true);
}
} // End of namespace StarTrek