/* 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 . * */ #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(MIDITRACK_2); _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(MIDITRACK_3); 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(MIDITRACK_0); _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(MIDITRACK_2); startBattle("orion"); // Elasi Pirate battle _enterpriseState.underAttack = false; _sound->playMidiMusicTracks(MIDITRACK_3); 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(MIDITRACK_2); _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(MIDITRACK_2); 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; MidiTracks midiTrack = 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 = 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 = MIDITRACK_13; } else if (score >= 71 && score <= 85) { performanceDescription = "#BRID\\B_214#Well done, Captain. Keep up the good work."; commendationPoints = 2; midiTrack = 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 = MIDITRACK_12; } else if (score == 100) { performanceDescription = "#BRID\\B_195#A perfect mission, Jim! You are a model for all Starfleet!"; commendationPoints = 4; midiTrack = MIDITRACK_14; } _sound->playMidiMusicTracks(midiTrack); 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(MIDITRACK_15); else if (talkerId == "mudd") _sound->playMidiMusicTracks(MIDITRACK_17); 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::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