mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
This is a major change, which allows us to read room texts directly from RDF files in a deterministic way. The previous attempt to read texts on the fly failed with some texts at runtime, which made it unreliable. Additionally, the scope of all room text IDs has been reduced to each room. With this change, it's now possible to support text in CD and floppy versions and support multiple game languages, without hardcoding all of the game texts in the engine source. This is 50% done (29 out of 55 rooms), with the following left to be done: - MUDD mission rooms (need to improve the text reader for these) - TRIAL mission rooms (need to improve the text reader for these) - SINS mission rooms (need to improve the text reader for these) - The rest of VENG mission rooms The DEMON, TUG, LOVE, FEATHER and part of the VENG mission rooms have been converted.
1383 lines
48 KiB
C++
1383 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 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "startrek/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
|