mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
It's now possible to use the menu system and talk to some crewmates. The game now starts in bridge mode, and it's possible to beam down by using Kirk's transporter icon.
389 lines
9.4 KiB
C++
389 lines
9.4 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 "base/plugins.h"
|
|
#include "base/version.h"
|
|
#include "common/archive.h"
|
|
#include "common/config-manager.h"
|
|
#include "common/debug-channels.h"
|
|
#include "common/error.h"
|
|
#include "common/events.h"
|
|
#include "common/file.h"
|
|
#include "common/macresman.h"
|
|
|
|
#include "graphics/pixelformat.h"
|
|
#include "graphics/surface.h"
|
|
|
|
#include "engines/util.h"
|
|
#include "video/qt_decoder.h"
|
|
|
|
#include "startrek/console.h"
|
|
#include "startrek/iwfile.h"
|
|
#include "startrek/lzss.h"
|
|
#include "startrek/resource.h"
|
|
#include "startrek/room.h"
|
|
#include "startrek/startrek.h"
|
|
|
|
namespace StarTrek {
|
|
|
|
StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gamedesc) :
|
|
Engine(syst),
|
|
_gameDescription(gamedesc),
|
|
_randomSource("Star Trek"),
|
|
_kirkActor(&_actorList[0]),
|
|
_spockActor(&_actorList[1]),
|
|
_mccoyActor(&_actorList[2]),
|
|
_redshirtActor(&_actorList[3]),
|
|
_sineTable(1024),
|
|
_cosineTable(1024) {
|
|
|
|
if (getPlatform() != Common::kPlatformDOS)
|
|
error("Only DOS versions of Star Trek: 25th Anniversary are currently supported");
|
|
else if (getGameType() == GType_STJR)
|
|
error("Star Trek: Judgment Rites is not yet supported");
|
|
|
|
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound");
|
|
DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics");
|
|
DebugMan.addDebugChannel(kDebugSavegame, "savegame", "Savegames");
|
|
DebugMan.addDebugChannel(kDebugSpace, "space", "Space and Pseudo-3D");
|
|
DebugMan.addDebugChannel(kDebugGeneral, "general", "General");
|
|
|
|
_gfx = nullptr;
|
|
_activeMenu = nullptr;
|
|
_sound = nullptr;
|
|
_room = nullptr;
|
|
_resource = nullptr;
|
|
|
|
memset(_actionOnWalkCompletionInUse, 0, sizeof(_actionOnWalkCompletionInUse));
|
|
|
|
_clockTicks = 0;
|
|
|
|
_musicEnabled = true;
|
|
_sfxEnabled = true;
|
|
_word_467a6 = true;
|
|
_musicWorking = true;
|
|
_sfxWorking = true;
|
|
_finishedPlayingSpeech = false;
|
|
|
|
_lookActionBitmapIndex = 0;
|
|
|
|
_mouseControllingShip = false;
|
|
_keyboardControlsMouse = true;
|
|
|
|
_inQuitGameMenu = false;
|
|
_textDisplayMode = TEXTDISPLAY_SUBTITLES;
|
|
_textboxVar2 = 0;
|
|
_textboxVar6 = 0;
|
|
_textboxHasMultipleChoices = false;
|
|
|
|
_missionToLoad = "";
|
|
_roomIndexToLoad = 0;
|
|
_mapFile = nullptr;
|
|
_iwFile = nullptr;
|
|
|
|
_showSubtitles = true;
|
|
Common::fill(_r3List, _r3List + NUM_SPACE_OBJECTS, (R3 *)nullptr);
|
|
Common::fill(_orderedR3List, _orderedR3List + NUM_SPACE_OBJECTS, (R3 *)nullptr);
|
|
|
|
for (int i = 0; i < NUM_OBJECTS; i++)
|
|
_itemList[i] = g_itemList[i];
|
|
|
|
for (int i = 0; i < MAX_BAN_FILES; i++)
|
|
_banFiles[i] = nullptr;
|
|
|
|
const Common::FSNode gameDataDir(ConfMan.get("path"));
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "patches");
|
|
}
|
|
|
|
StarTrekEngine::~StarTrekEngine() {
|
|
delete _activeMenu->nextMenu;
|
|
delete _activeMenu;
|
|
|
|
delete _gfx;
|
|
delete _sound;
|
|
delete _resource;
|
|
}
|
|
|
|
Common::Error StarTrekEngine::run() {
|
|
bool isDemo = getFeatures() & GF_DEMO;
|
|
_resource = new Resource(getPlatform(), isDemo);
|
|
_gfx = new Graphics(this);
|
|
_sound = new Sound(this);
|
|
setDebugger(new Console(this));
|
|
|
|
initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
initializeEventsAndMouse();
|
|
loadBridgeComputerTopics();
|
|
|
|
_gfx->setMouseBitmap(!isDemo ? "pushbtn" : "cursor");
|
|
|
|
bool loadedSave = false;
|
|
|
|
if (ConfMan.hasKey("save_slot")) {
|
|
if (!loadGame(ConfMan.getInt("save_slot")))
|
|
error("Failed to load savegame %d", ConfMan.getInt("save_slot"));
|
|
loadedSave = true;
|
|
}
|
|
|
|
if (!loadedSave) {
|
|
if (!isDemo) {
|
|
playIntro();
|
|
_missionToLoad = "DEMON";
|
|
runGameMode(GAMEMODE_BRIDGE, false);
|
|
} else {
|
|
_missionToLoad = "DEMO";
|
|
runGameMode(GAMEMODE_AWAYMISSION, false);
|
|
}
|
|
} else {
|
|
_roomIndexToLoad = -1;
|
|
runGameMode(_gameMode, true);
|
|
}
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
Common::Error StarTrekEngine::runGameMode(int mode, bool resume) {
|
|
_gfx->toggleMouse(true);
|
|
|
|
if (!resume) { // Only run this if not just resuming from a savefile
|
|
_frameIndex = 0;
|
|
_lastGameMode = -1;
|
|
_gameMode = mode;
|
|
|
|
_sound->stopAllVocSounds();
|
|
|
|
_resetGameMode = true;
|
|
if (_gameMode == GAMEMODE_START)
|
|
_gameMode = GAMEMODE_BRIDGE;
|
|
}
|
|
|
|
while (true) {
|
|
if (_resetGameMode) {
|
|
if (!_sound->_loopingAudioName.empty())
|
|
_sound->playVoc(_sound->_loopingAudioName);
|
|
_resetGameMode = false;
|
|
}
|
|
TrekEvent event;
|
|
|
|
if (_gameMode != _lastGameMode) {
|
|
// Cleanup previous game mode
|
|
switch (_lastGameMode) {
|
|
case GAMEMODE_BRIDGE:
|
|
cleanupBridge();
|
|
break;
|
|
|
|
case GAMEMODE_AWAYMISSION:
|
|
cleanupAwayMission();
|
|
break;
|
|
|
|
case GAMEMODE_BEAMDOWN:
|
|
case GAMEMODE_BEAMUP:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
_lastGameMode = _gameMode;
|
|
|
|
// Load next game mode
|
|
switch (_gameMode) {
|
|
case GAMEMODE_BRIDGE:
|
|
_sound->loadMusicFile("bridge");
|
|
initBridge(false); // TODO: param
|
|
break;
|
|
|
|
case GAMEMODE_AWAYMISSION:
|
|
initAwayMission();
|
|
break;
|
|
|
|
case GAMEMODE_BEAMDOWN:
|
|
_awayMission.redshirtDead = false;
|
|
_sound->loadMusicFile("ground");
|
|
runTransportSequence("teled");
|
|
_gameMode = GAMEMODE_AWAYMISSION;
|
|
continue; // Back to start of loop
|
|
|
|
case GAMEMODE_BEAMUP:
|
|
runTransportSequence("teleb");
|
|
_gameMode = GAMEMODE_BRIDGE;
|
|
//sub_15c61();
|
|
_sound->stopAllVocSounds();
|
|
_sound->playVoc("bridloop");
|
|
continue; // Back to start of loop
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Run current game mode
|
|
switch (_gameMode) {
|
|
case GAMEMODE_BRIDGE:
|
|
popNextEvent(&event);
|
|
runBridge();
|
|
break;
|
|
|
|
case GAMEMODE_AWAYMISSION:
|
|
runAwayMission();
|
|
break;
|
|
|
|
case GAMEMODE_BEAMDOWN:
|
|
case GAMEMODE_BEAMUP:
|
|
error("Can't be here.");
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
void StarTrekEngine::runTransportSequence(const Common::String &name) {
|
|
const uint16 crewmanTransportPositions[][2] = {
|
|
{ 0x8e, 0x7c },
|
|
{ 0xbe, 0x7c },
|
|
{ 0x7e, 0x72 },
|
|
{ 0xaa, 0x72 }
|
|
};
|
|
|
|
_sound->stopAllVocSounds();
|
|
_gfx->fadeoutScreen();
|
|
actorFunc1();
|
|
initActors();
|
|
|
|
_gfx->setBackgroundImage("transprt");
|
|
_gfx->clearPri();
|
|
_gfx->loadPalette("palette");
|
|
_gfx->copyBackgroundScreen();
|
|
_system->updateScreen();
|
|
_system->delayMillis(10);
|
|
|
|
for (int i = 0; i < (_awayMission.redshirtDead ? 3 : 4); i++) {
|
|
Common::String filename = getCrewmanAnimFilename(i, name);
|
|
int x = crewmanTransportPositions[i][0];
|
|
int y = crewmanTransportPositions[i][1];
|
|
loadActorAnim(i, filename, x, y, 1.0);
|
|
_actorList[i].animationString.clear();
|
|
}
|
|
|
|
if (_missionToLoad.equalsIgnoreCase("feather") && name[4] == 'b') {
|
|
loadActorAnim(9, "qteleb", 0x61, 0x79, 1.0);
|
|
} else if (_missionToLoad.equalsIgnoreCase("trial")) {
|
|
if (name[4] == 'd') {
|
|
loadActorAnim(9, "qteled", 0x61, 0x79, 1.0);
|
|
}
|
|
/* TODO
|
|
else if (word_51156 >= 3) {
|
|
loadActorAnim(9, "qteleb", 0x61, 0x79, 1.0);
|
|
}
|
|
*/
|
|
}
|
|
|
|
loadActorAnim(8, "transc", 0, 0, 1.0);
|
|
|
|
// TODO: redraw mouse and sprite_52c4e?
|
|
|
|
_gfx->drawAllSprites();
|
|
_gfx->fadeinScreen();
|
|
|
|
_sound->playSoundEffectIndex(0x0a);
|
|
|
|
if (name.equalsIgnoreCase("teled"))
|
|
_sound->playSoundEffectIndex(0x08);
|
|
else
|
|
_sound->playSoundEffectIndex(0x09);
|
|
|
|
while (_actorList[0].field62 == 0) {
|
|
TrekEvent event;
|
|
if (popNextEvent(&event)) {
|
|
if (event.type == TREKEVENT_TICK) {
|
|
// TODO: redraw sprite_52c4e?
|
|
_frameIndex++;
|
|
updateActorAnimations();
|
|
_gfx->drawAllSprites();
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: redraw sprite_52c4e?
|
|
|
|
_gfx->drawAllSprites();
|
|
_gfx->fadeoutScreen();
|
|
actorFunc1();
|
|
initActors();
|
|
}
|
|
|
|
void StarTrekEngine::playMovie(Common::String filename) {
|
|
if (getPlatform() == Common::kPlatformMacintosh)
|
|
playMovieMac(filename);
|
|
else
|
|
error("Interplay MVE not yet supported");
|
|
}
|
|
|
|
void StarTrekEngine::playMovieMac(Common::String filename) {
|
|
// Swap to 16bpp mode
|
|
initGraphics(512, 384, NULL);
|
|
|
|
Video::QuickTimeDecoder *qtDecoder = new Video::QuickTimeDecoder();
|
|
|
|
if (!qtDecoder->loadFile(filename))
|
|
error("Could not open '%s'", filename.c_str());
|
|
|
|
bool continuePlaying = true;
|
|
|
|
qtDecoder->start();
|
|
|
|
while (!qtDecoder->endOfVideo() && !shouldQuit() && continuePlaying) {
|
|
if (qtDecoder->needsUpdate()) {
|
|
const ::Graphics::Surface *frame = qtDecoder->decodeNextFrame();
|
|
|
|
if (frame) {
|
|
::Graphics::Surface *convertedFrame = frame->convertTo(_system->getScreenFormat());
|
|
_system->copyRectToScreen(convertedFrame->getPixels(), convertedFrame->pitch, 0, 0, convertedFrame->w, convertedFrame->h);
|
|
_system->updateScreen();
|
|
convertedFrame->free();
|
|
delete convertedFrame;
|
|
}
|
|
}
|
|
|
|
Common::Event event;
|
|
while (g_system->getEventManager()->pollEvent(event))
|
|
if (event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE)
|
|
continuePlaying = false;
|
|
|
|
_system->delayMillis(10);
|
|
}
|
|
|
|
delete qtDecoder;
|
|
|
|
// Swap back to 8bpp mode
|
|
initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
}
|
|
|
|
uint16 StarTrekEngine::getRandomWord() {
|
|
return _randomSource.getRandomNumber(0xffff);
|
|
}
|
|
|
|
} // End of namespace StarTrek
|