diff options
author | Matthew Stewart | 2018-05-23 01:01:36 -0400 |
---|---|---|
committer | Eugene Sandulenko | 2018-08-09 08:37:30 +0200 |
commit | bd79e4d653f9476de1501de149589e583e47411d (patch) | |
tree | 99de3438a254bdead699ea458bd5c914d4df3544 | |
parent | 66b4ec36bdfb19a5242325e58c3180bc79574c89 (diff) | |
download | scummvm-rg350-bd79e4d653f9476de1501de149589e583e47411d.tar.gz scummvm-rg350-bd79e4d653f9476de1501de149589e583e47411d.tar.bz2 scummvm-rg350-bd79e4d653f9476de1501de149589e583e47411d.zip |
STARTREK: Begin on room-specific code for room 1
-rw-r--r-- | engines/startrek/action.h | 65 | ||||
-rw-r--r-- | engines/startrek/awaymission.cpp | 120 | ||||
-rw-r--r-- | engines/startrek/awaymission.h | 15 | ||||
-rw-r--r-- | engines/startrek/module.mk | 3 | ||||
-rw-r--r-- | engines/startrek/object.h | 1 | ||||
-rw-r--r-- | engines/startrek/room.cpp | 161 | ||||
-rw-r--r-- | engines/startrek/room.h | 73 | ||||
-rw-r--r-- | engines/startrek/rooms/demon0.cpp | 538 | ||||
-rw-r--r-- | engines/startrek/rooms/function_map.h | 83 | ||||
-rw-r--r-- | engines/startrek/startrek.cpp | 15 | ||||
-rw-r--r-- | engines/startrek/startrek.h | 68 | ||||
-rw-r--r-- | engines/startrek/text.cpp | 6 |
12 files changed, 1021 insertions, 127 deletions
diff --git a/engines/startrek/action.h b/engines/startrek/action.h new file mode 100644 index 0000000000..68d5823000 --- /dev/null +++ b/engines/startrek/action.h @@ -0,0 +1,65 @@ +/* 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. + * + */ + +#ifndef STARTREK_ACTION_H +#define STARTREK_ACTION_H + + +enum Acton { + ACTION_TICK = 0, + + ACTION_WALK = 1, // Actions 1-5 are directly usable on away missions. + ACTION_USE = 2, + ACTION_GET = 3, + ACTION_LOOK = 4, + ACTION_TALK = 5, + + ACTION_TOUCHED_WARP = 6, + ACTION_TOUCHED_HOTSPOT = 7, // Doors? (Or just hotspots activated by Kirk moving there?) + ACTION_FINISHED_BEAMING_IN = 10, + ACTION_FINISHED_ENTERING_ROOM = 12, + ACTION_OPTIONS = 13 // Not really an action, but selectable from action menu +}; + +struct Action { + byte type; + byte b1; + byte b2; + byte b3; + + Action(byte _type, byte _b1, byte _b2, byte _b3) + : type(_type), + b1(_b1), + b2(_b2), + b3(_b3) {} + + + // ACTION_USE, ACTION_GET, ACTION_LOOK, ACTION_TALK + byte activeObject() { return b1; } + byte passiveObject() { return b2; } + + bool operator==(const Action &a) const { + return type == a.type && b1 == a.b1 && b2 == a.b2 && b3 == a.b3; + } +}; + +#endif diff --git a/engines/startrek/awaymission.cpp b/engines/startrek/awaymission.cpp index 16d4591304..5db0271da1 100644 --- a/engines/startrek/awaymission.cpp +++ b/engines/startrek/awaymission.cpp @@ -21,6 +21,7 @@ */ #include "startrek/iwfile.h" +#include "startrek/room.h" #include "startrek/startrek.h" namespace StarTrek { @@ -50,11 +51,11 @@ void StarTrekEngine::runAwayMission() { _awayMission.mouseX = mousePos.x; _awayMission.mouseY = mousePos.y; - assert(_commandQueue.size() <= 16); - if (!_commandQueue.empty()) { + assert(_actionQueue.size() <= 16); + if (!_actionQueue.empty()) { // sub_200e7(); // sub_20118(); - handleAwayMissionCommand(); + handleAwayMissionAction(); } } } @@ -101,7 +102,7 @@ void StarTrekEngine::loadRoom(const Common::String &missionName, int roomIndex) // TODO: RDF vars 1e/1f and 20/21; relates to BAN files? - _commandQueue.clear(); + _actionQueue.clear(); } void StarTrekEngine::initAwayCrewPositions(int warpEntryIndex) { @@ -168,7 +169,7 @@ void StarTrekEngine::handleAwayMissionEvents() { // sub_22de0(); _frameIndex++; _roomFrameCounter++; - addCommand(Command(COMMAND_TICK, _roomFrameCounter & 0xff, (_roomFrameCounter >> 8) & 0xff, 0)); + addAction(Action(ACTION_TICK, _roomFrameCounter & 0xff, (_roomFrameCounter >> 8) & 0xff, 0)); if (_roomFrameCounter >= 2) _gfx->incPaletteFadeLevel(); break; @@ -209,11 +210,15 @@ void StarTrekEngine::handleAwayMissionEvents() { int clickedObject = findObjectAt(_gfx->getMousePos()); hideInventoryIcons(); - if (clickedObject == OBJECT_INVENTORY_ICON) + if (clickedObject == OBJECT_INVENTORY_ICON) { clickedObject = showInventoryMenu(50, 50, false); - if (clickedObject == -1) - clickedObject = -2; + // -1 means "clicked on something unknown"; -2 means "clicked on + // nothing". In the case of the inventory, either one clicks on an + // inventory item, or no action is performed. + if (clickedObject == -1) + clickedObject = -2; + } _awayMission.passiveObject = clickedObject; @@ -223,18 +228,18 @@ void StarTrekEngine::handleAwayMissionEvents() { bool passiveIsItem = _awayMission.passiveObject >= ITEMS_START && _awayMission.passiveObject <= ITEMS_END; // FIXME: "<= ITEMS_END" doesn't make sense? if (clickedObject == -2) - goto checkAddCommand; - if (checkItemInteractionExists(ACTION_USE, _awayMission.activeObject, _awayMission.passiveObject, 0)) - goto checkAddCommand; + goto checkAddAction; + if (_room->actionHasCode(Action(ACTION_USE, _awayMission.activeObject, _awayMission.passiveObject, 0))) + goto checkAddAction; if (_awayMission.activeObject == OBJECT_MCCOY) { - if (checkItemInteractionExists(ACTION_USE, OBJECT_IMEDKIT, _awayMission.passiveObject, 0)) - goto checkAddCommand; - if (checkItemInteractionExists(ACTION_USE, OBJECT_IMEDKIT, _awayMission.passiveObject, 0)) - goto checkAddCommand; + if (_room->actionHasCode(Action(ACTION_USE, OBJECT_IMEDKIT, _awayMission.passiveObject, 0))) + goto checkAddAction; + if (_room->actionHasCode(Action(ACTION_USE, OBJECT_IMEDKIT, _awayMission.passiveObject, 0))) + goto checkAddAction; } else if (_awayMission.activeObject == OBJECT_SPOCK) { - if (checkItemInteractionExists(ACTION_USE, OBJECT_ISTRICOR, _awayMission.passiveObject, 0)) - goto checkAddCommand; + if (_room->actionHasCode(Action(ACTION_USE, OBJECT_ISTRICOR, _awayMission.passiveObject, 0))) + goto checkAddAction; } if ((activeIsCrewman && passiveIsCrewman) @@ -243,7 +248,7 @@ void StarTrekEngine::handleAwayMissionEvents() { if (_awayMission.passiveObject == OBJECT_ICOMM) { if (sub_2330c()) break; - addCommand(Command(ACTION_USE, OBJECT_ICOMM, 0, 0)); + addAction(Action(ACTION_USE, OBJECT_ICOMM, 0, 0)); _sound->playVoc("commun30"); if (_awayMission.activeObject <= OBJECT_REDSHIRT) { goto checkShowInventory; @@ -258,11 +263,11 @@ void StarTrekEngine::handleAwayMissionEvents() { goto checkShowInventory; } -checkAddCommand: +checkAddAction: if (!sub_2330c()) { if (clickedObject != -2) - addCommand(Command(_awayMission.activeAction, _awayMission.activeObject, _awayMission.passiveObject, 0)); + addAction(Action(_awayMission.activeAction, _awayMission.activeObject, _awayMission.passiveObject, 0)); checkShowInventory: if (!(_awayMission.field24 & 1)) @@ -290,7 +295,7 @@ checkShowInventory: break; if (clickedObject != -2) - addCommand(Command(_awayMission.activeAction, _awayMission.activeObject, 0, 0)); + addAction(Action(_awayMission.activeAction, _awayMission.activeObject, 0, 0)); if (_awayMission.activeAction == ACTION_LOOK && !(_awayMission.field24 & 1)) showInventoryIcons(false); @@ -310,19 +315,18 @@ checkShowInventory: hideInventoryIcons(); playSoundEffectIndex(0x07); _awayMission.activeAction = showActionMenu(); - if (_awayMission.activeAction == ACTION_USE) { // TODO - /* - int16 clickedObject = sub_22f08(); + if (_awayMission.activeAction == ACTION_USE) { + //int16 clickedObject = selectObjectForGetAction(); // TODO + int16 clickedObject = 0; if (clickedObject == -1) break; else _awayMission.activeObject = clickedObject; - */ } if (_awayMission.activeAction == ACTION_USE && _awayMission.activeObject == OBJECT_ICOMM && (_awayMission.field24 & 1) == 0) { // TODO if (!sub_2330c()) { - addCommand(Command(_awayMission.activeAction, _awayMission.activeObject, 0, 0)); + addAction(Action(_awayMission.activeAction, _awayMission.activeObject, 0, 0)); _sound->playVoc("communic"); _awayMission.activeAction = ACTION_WALK; } @@ -376,54 +380,57 @@ SharedPtr<Room> StarTrekEngine::getRoom() { return _room; } -void StarTrekEngine::addCommand(const Command &command) { - if (command.type != COMMAND_TICK) - debug("Command %d: %x, %x, %x", command.type, command.gen.b1, command.gen.b2, command.gen.b3); - _commandQueue.push(command); -} - -bool StarTrekEngine::checkItemInteractionExists(int action, int activeItem, int passiveItem, int16 arg6) { - // TODO - return false; +void StarTrekEngine::addAction(const Action &action) { + if (action.type != ACTION_TICK) + debug("Action %d: %x, %x, %x", action.type, action.b1, action.b2, action.b3); + _actionQueue.push(action); } -void StarTrekEngine::handleAwayMissionCommand() { - Command command = _commandQueue.pop(); +void StarTrekEngine::handleAwayMissionAction() { + Action action = _actionQueue.pop(); - if ((command.type == COMMAND_FINISHED_BEAMING_IN || command.type == COMMAND_FINISHED_ENTERING_ROOM) && command.gen.b1 == 0xff) { + if ((action.type == ACTION_FINISHED_BEAMING_IN || action.type == ACTION_FINISHED_ENTERING_ROOM) && action.b1 == 0xff) { _awayMission.transitioningIntoRoom = 0; _warpHotspotsActive = true; return; } - else if (command.type == COMMAND_FINISHED_ENTERING_ROOM && command.gen.b1 >= 0xe0) { // TODO + else if (action.type == ACTION_FINISHED_ENTERING_ROOM && action.b1 >= 0xe0) { // TODO return; } - switch (command.type) { // TODO: everything + if (_room->handleAction(action)) + return; + + // Action not defined for the room, check for default behaviour + + switch (action.type) { // TODO: everything - case COMMAND_WALK: // TODO + case ACTION_WALK: // TODO + warning("Unhandled walk action: %d %d %d", action.b1, action.b2, action.b3); break; - case COMMAND_USE: // TODO + case ACTION_USE: // TODO + warning("Unhandled use action: %d %d %d", action.b1, action.b2, action.b3); break; - case COMMAND_GET: // TODO + case ACTION_GET: // TODO + warning("Unhandled get action: %d %d %d", action.b1, action.b2, action.b3); break; - case COMMAND_LOOK: - if (command.action.activeObject >= ITEMS_START && command.action.activeObject < ITEMS_END) { - int i = command.action.activeObject - ITEMS_START; + case ACTION_LOOK: + if (action.activeObject() >= ITEMS_START && action.activeObject() < ITEMS_END) { + int i = action.activeObject() - ITEMS_START; Common::String text = getItemDescription(_itemList[i].textIndex); showTextbox("", text, 20, 20, TEXTCOLOR_YELLOW, 0); } - else if (command.action.activeObject == OBJECT_KIRK) + else if (action.activeObject() == OBJECT_KIRK) showTextbox("", getItemDescription(0x49), 20, 20, TEXTCOLOR_YELLOW, 0); - else if (command.action.activeObject == OBJECT_SPOCK) + else if (action.activeObject() == OBJECT_SPOCK) showTextbox("", getItemDescription(0x4a), 20, 20, TEXTCOLOR_YELLOW, 0); - else if (command.action.activeObject == OBJECT_MCCOY) + else if (action.activeObject() == OBJECT_MCCOY) showTextbox("", getItemDescription(0x4b), 20, 20, TEXTCOLOR_YELLOW, 0); else { - if (command.action.activeObject == OBJECT_REDSHIRT) + if (action.activeObject() == OBJECT_REDSHIRT) showTextbox("", getItemDescription(0x4c), 20, 20, TEXTCOLOR_YELLOW, 0); // Show generic "nothing of note" text. @@ -434,13 +441,14 @@ void StarTrekEngine::handleAwayMissionCommand() { } break; - case COMMAND_TALK: // TODO + case ACTION_TALK: // TODO + warning("Unhandled talk action: %d %d %d", action.b1, action.b2, action.b3); break; - case COMMAND_TOUCHED_WARP: - // if (!sub_203e1(command.type)) // Probably calls RDF code + case ACTION_TOUCHED_WARP: + // if (!sub_203e1(action.type)) // Probably calls RDF code { - byte warpIndex = command.gen.b1; + byte warpIndex = action.b1; int16 roomIndex = _room->readRdfWord(RDF_WARP_ROOM_INDICES + warpIndex * 2); unloadRoom(); _sound->loadMusicFile("ground"); @@ -488,7 +496,7 @@ void StarTrekEngine::checkTouchedLoadingZone(int16 x, int16 y) { uint16 var = _room->readRdfWord(offset); if (_activeDoorWarpHotspot != var) { _activeDoorWarpHotspot = var; - addCommand(Command(COMMAND_7, var & 0xff, 0, 0)); + addAction(Action(ACTION_TOUCHED_HOTSPOT, var & 0xff, 0, 0)); } return; } @@ -506,7 +514,7 @@ void StarTrekEngine::checkTouchedLoadingZone(int16 x, int16 y) { uint16 var = _room->readRdfWord(offset); if (_activeWarpHotspot != var) { _activeWarpHotspot = var; - addCommand(Command(COMMAND_TOUCHED_WARP, var & 0xff, 0, 0)); + addAction(Action(ACTION_TOUCHED_WARP, var & 0xff, 0, 0)); } return; } diff --git a/engines/startrek/awaymission.h b/engines/startrek/awaymission.h index 8972306f41..b89e9cf0fe 100644 --- a/engines/startrek/awaymission.h +++ b/engines/startrek/awaymission.h @@ -34,10 +34,23 @@ struct AwayMission { byte activeAction; byte activeObject; // The item that is going to be used on something byte passiveObject; // The item that the active item is used on (or the item looked at, etc). + + // If this is true after calling room-specific RDF code, the game will continue to run + // any "default" code for the event, if any. + bool rdfStillDoDefaultAction; + byte field24; int8 field25[4]; - bool rdfRunNextCommand; + // Demon Word: nonzero if a rude response was given to the prelate. + int16 field29; + + byte field33; + byte field36; + byte field38; + byte field3a; + + int16 missionScore; }; // Size: 0x129 bytes diff --git a/engines/startrek/module.mk b/engines/startrek/module.mk index cdaa44449e..b011c06c7a 100644 --- a/engines/startrek/module.mk +++ b/engines/startrek/module.mk @@ -17,7 +17,8 @@ MODULE_OBJS = \ sound.o \ sprite.o \ startrek.o \ - text.o + text.o \ + rooms/demon0.o diff --git a/engines/startrek/object.h b/engines/startrek/object.h index 71c9f8448c..2cfbbd2611 100644 --- a/engines/startrek/object.h +++ b/engines/startrek/object.h @@ -42,6 +42,7 @@ class FileStream; // other, ie. object 0 (kirk) interacts with object 32 (a hotspot) via ACTION_LOOK. const int ACTORS_START = 0; +const int SCALED_ACTORS_END = 8; // Only first 8 actors have room scaling applied? const int ACTORS_END = 32; const int NUM_ACTORS = ACTORS_END - ACTORS_START; diff --git a/engines/startrek/room.cpp b/engines/startrek/room.cpp index 8cef65d13a..555a72126b 100644 --- a/engines/startrek/room.cpp +++ b/engines/startrek/room.cpp @@ -18,24 +18,33 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL: https://scummvm-startrek.googlecode.com/svn/trunk/graphics.h $ - * $Id: graphics.h 2 2009-09-12 20:13:40Z clone2727 $ - * */ #include "startrek/filestream.h" #include "startrek/room.h" #include "startrek/startrek.h" +#include "rooms/function_map.h" namespace StarTrek { -Room::Room(StarTrekEngine *vm, Common::String name) : _vm(vm) { +Room::Room(StarTrekEngine *vm, const Common::String &name) : _vm(vm) { SharedPtr<FileStream> rdfFile = _vm->loadFile(name + ".RDF"); int size = rdfFile->size(); _rdfData = new byte[size]; rdfFile->read(_rdfData, size); + + // Find room-specific code table + if (name == "DEMON0") { + _roomActionList = demon0ActionList; + _numRoomActions = sizeof(demon0ActionList) / sizeof(RoomAction); + } + else { + warning("Room \"%s\" unimplemented", name.c_str()); + _numRoomActions = 0; + return; + } } Room::~Room() { @@ -46,9 +55,153 @@ uint16 Room::readRdfWord(int offset) { return _rdfData[offset] | (_rdfData[offset+1]<<8); } +bool Room::actionHasCode(const Action &action) { + RoomAction *roomActionPtr = _roomActionList; + int n = _numRoomActions; + + while (n-- > 0) { + if (action == roomActionPtr->action) + return true; + roomActionPtr++; + } + return false; +} + +bool Room::handleAction(const Action &action) { + RoomAction *roomActionPtr = _roomActionList; + int n = _numRoomActions; + + while (n-- > 0) { + if (action == roomActionPtr->action) { + _vm->_awayMission.rdfStillDoDefaultAction = false; + (this->*(roomActionPtr->funcPtr))(); + if (!_vm->_awayMission.rdfStillDoDefaultAction) + return true; + } + roomActionPtr++; + } + return false; +} + Common::Point Room::getBeamInPosition(int crewmanIndex) { int base = 0xaa + crewmanIndex * 4; return Common::Point(readRdfWord(base), readRdfWord(base + 2)); } + +// Interface for room-specific code + +void Room::loadActorAnim(int actorIndex, Common::String anim, int16 x, int16 y, uint16 field66) { + Actor *actor = &_vm->_actorList[actorIndex]; + + if (x == -1 || y == -1) { + x = actor->sprite.pos.x; + y = actor->sprite.pos.y; + } + + if (actorIndex >= 0 && actorIndex < SCALED_ACTORS_END) + _vm->loadActorAnimWithRoomScaling(actorIndex, anim, x, y); + else + _vm->loadActorAnim(actorIndex, anim, x, y, 256); + + if (field66 != 0) { + actor->walkingIntoRoom = 1; + actor->field66 = field66; + } +} + +void Room::loadActorStandAnim(int actorIndex) { + if (_vm->_awayMission.redshirtDead && actorIndex == OBJECT_REDSHIRT) + _vm->removeActorFromScreen(actorIndex); + else { + Actor *actor = &_vm->_actorList[actorIndex]; + if (actor->animationString[0] == '\0') + _vm->removeActorFromScreen(actorIndex); + else + _vm->initStandAnim(actorIndex); + } +} + +/** + * This is exactly the same as "loadActorAnim", but the game calls it at different times? + */ +void Room::loadActorAnim2(int actorIndex, Common::String anim, int16 x, int16 y, uint16 field66) { + loadActorAnim(actorIndex, anim, x, y, field66); +} + +// TODO: replace "rdfOffset" with a pointer, so we no longer read from RDF files? (This +// may be necessary to support other platforms; can't leave offsets hardcoded.) +int Room::showRoomSpecificText(const char **array) { + Common::String speaker; + byte textColor; + + if (array[0] != nullptr && array[0][0] != '\0') { // TODO + speaker = Common::String(array[0]); + if (speaker.equalsIgnoreCase("Capt. Kirk")) + textColor = TEXTCOLOR_YELLOW; + else if (speaker.equalsIgnoreCase("Mr. Spock")) + textColor = TEXTCOLOR_BLUE; + else if (speaker.equalsIgnoreCase("Dr. McCoy")) + textColor = TEXTCOLOR_BLUE; + else if (speaker.equalsIgnoreCase("Mr. Chekov")) + textColor = TEXTCOLOR_YELLOW; + else if (speaker.equalsIgnoreCase("Mr. Scott")) + textColor = TEXTCOLOR_RED; + else if (speaker.hasPrefixIgnoreCase("Lt")) + textColor = TEXTCOLOR_RED; + else if (speaker.hasPrefixIgnoreCase("Ensign")) + textColor = TEXTCOLOR_RED; + else + textColor = TEXTCOLOR_GREY; + } + else + textColor = TEXTCOLOR_YELLOW; + + return _vm->showText(&StarTrekEngine::readTextFromArray, (uintptr)array, 20, 20, textColor, true, false, false); +} + +void Room::giveItem(int item) { + _vm->_itemList[item - ITEMS_START].have = true; +} + +void Room::loadRoomIndex(int roomIndex, int spawnIndex) { + if (_vm->_awayMission.field24 != 0) + return; + + _vm->unloadRoom(); + _vm->_sound->loadMusicFile("ground"); + + _vm->loadRoom(_vm->_missionName, roomIndex); + _vm->initAwayCrewPositions(spawnIndex % 6); + + // TODO: "retrieveStackVars" call returns program counter directly to beginning of + // away mission loop. How to handle this? +} + +void Room::walkCrewman(int actorIndex, int16 destX, int16 destY, uint16 field66) { + if (!(actorIndex >= OBJECT_KIRK && actorIndex < OBJECT_REDSHIRT)) + error("Tried to walk a non PC"); + + Actor *actor = &_vm->_actorList[actorIndex]; + Common::String anim = _vm->getCrewmanAnimFilename(actorIndex, "walk"); + bool success = _vm->actorWalkToPosition(actorIndex, anim, actor->pos.x, actor->pos.y, destX, destY); + + if (success && field66 != 0) { + actor->walkingIntoRoom = 1; + actor->field66 = field66; + } +} + +void Room::playSoundEffectIndex(int soundEffect) { + _vm->playSoundEffectIndex(soundEffect); +} + +void Room::playMidiMusicTracks(int startTrack, int loopTrack) { + _vm->playMidiMusicTracks(startTrack, loopTrack); +} + +void Room::playVoc(Common::String filename) { + _vm->_sound->playVoc(filename); +} + } diff --git a/engines/startrek/room.h b/engines/startrek/room.h index b6a69c38b9..cb00815cff 100644 --- a/engines/startrek/room.h +++ b/engines/startrek/room.h @@ -27,12 +27,21 @@ #include "common/ptr.h" #include "common/str.h" +#include "startrek/startrek.h" + using Common::SharedPtr; namespace StarTrek { class StarTrekEngine; +class Room; + +// Per-room action functions +struct RoomAction { + const Action action; + void (Room::*funcPtr)(); +}; // Offsets of data in RDF files @@ -43,7 +52,7 @@ const int RDF_BEAM_IN_POSITIONS = 0xaa; class Room { public: - Room(StarTrekEngine *vm, Common::String name); + Room(StarTrekEngine *vm, const Common::String &name); ~Room(); // Helper stuff for RDF access @@ -55,8 +64,13 @@ public: uint16 getVar0a() { return readRdfWord(0x0a); } uint16 getVar0c() { return readRdfWord(0x0c); } + // words 0x0e and 0x10 in RDF file are pointers to start and end of event code. + // That code is instead rewritten on a per-room basis. + bool actionHasCode(const Action &action); + bool handleAction(const Action &action); + uint16 getFirstHotspot() { return readRdfWord(0x12); } - uint16 getHotspotEnd() { return readRdfWord(0x14); } + uint16 getHotspotEnd() { return readRdfWord(0x14); } // Warp-related stuff uint16 getFirstWarpPolygonOffset() { return readRdfWord(0x16); } @@ -66,10 +80,65 @@ public: Common::Point getBeamInPosition(int crewmanIndex); +public: byte *_rdfData; private: StarTrekEngine *_vm; + + RoomAction *_roomActionList; + int _numRoomActions; + + + // Interface for room-specific code + void loadActorAnim(int actorIndex, Common::String anim, int16 x, int16 y, uint16 field66); // Cmd 0x00 + void loadActorStandAnim(int actorIndex); // Cmd 0x01 + void loadActorAnim2(int actorIndex, Common::String anim, int16 x, int16 y, uint16 field66);// Cmd 0x02 + int showRoomSpecificText(const char **textAddr); // Cmd 0x03 + void giveItem(int item); // Cmd 0x04 + void loadRoomIndex(int roomIndex, int spawnIndex); // Cmd 0x06 + void walkCrewman(int actorIndex, int16 destX, int16 destY, uint16 field66); // Cmd 0x08 + void playSoundEffectIndex(int soundEffect); // Cmd 0x0f + void playMidiMusicTracks(int startTrack, int loopTrack); // Cmd 0x10 + void playVoc(Common::String filename); // Cmd 0x15 + + // Room-specific code +public: + // DEMON0 + void demon0Tick1(); + void demon0Tick2(); + void demon0Tick60(); + void demon0Tick100(); + void demon0Tick140(); + void demon0TouchedWarp0(); + void demon0TouchedHotspot1(); + void demon0TouchedHotspot0(); + void demon0TalkToPrelate(); + void demon0LookAtPrelate(); + void demon0UsePhaserOnSnow(); + void demon0UsePhaserOnSign(); + void demon0UsePhaserOnShelter(); + void demon0UsePhaserOnPrelate(); + void demon0LookAtSign(); + void demon0LookAtTrees(); + void demon0LookAtSnow(); + void demon0LookAnywhere(); + void demon0LookAtBushes(); + void demon0LookAtKirk(); + void demon0LookAtMcCoy(); + void demon0LookAtRedShirt(); + void demon0LookAtSpock(); + void demon0LookAtShelter(); + void demon0TalkToKirk(); + void demon0TalkToRedshirt(); + void demon0TalkToMcCoy(); + void demon0TalkToSpock(); + void demon0AskPrelateAboutSightings(); + void useSTricorderAnywhere(); + void useMTricorderAnywhere(); + void useMTricorderOnPrelate(); + + void demon0BadResponse(); }; } diff --git a/engines/startrek/rooms/demon0.cpp b/engines/startrek/rooms/demon0.cpp new file mode 100644 index 0000000000..f687eaaaa3 --- /dev/null +++ b/engines/startrek/rooms/demon0.cpp @@ -0,0 +1,538 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "startrek/room.h" + +namespace StarTrek { + +void Room::demon0Tick1() { + playVoc("DEM0LOOP"); + loadActorAnim(9, "s0r0d3", 252, 153, 0); + loadActorAnim(10, "s0r0d4", 158, 130, 0); +} + +void Room::demon0Tick2() { + if (_vm->_awayMission.field33 == 1) + return; + loadActorAnim(8, "prel", 120, 190, 0); +} + +void Room::demon0Tick60() { + if (_vm->_awayMission.field33 == 1) + return; + loadActorAnim2(8, "prelclap", 120, 190, 0); +} + +void Room::demon0Tick100() { + const char *text[] = { + "Prel. Angiven", + "#DEM0\\DEM0_036#This is so much better, gentlefolk. We are honored at your presence and hope you will find peace here in our haven.", + "" + }; + + showRoomSpecificText(text); +} + +void Room::demon0Tick140() { + const char *text[] = { + "Dr. McCoy", + "#DEM0\\DEM0_016#Captain, the flora on this planet is very interesting. I wonder how useful it may be for medicinal purposes.", + "" + }; + + if (_vm->_awayMission.field38 == 1) + return; + + showRoomSpecificText(text); + + _vm->_awayMission.field38 = 1; +} + +void Room::demon0TouchedWarp0() { + _vm->_awayMission.field3a = 1; + _vm->_awayMission.rdfStillDoDefaultAction = true; +} + +void Room::demon0TouchedHotspot1() { + if (_rdfData[0xcd] != 1) // FIXME: not portable to mac/amiga? + return; + loadActorAnim2(9, "s0r0d1", 254, 153, 1); + playSoundEffectIndex(0x05); +} + +void Room::demon0TouchedHotspot0() { + if (_rdfData[0xcd] != 1) // FIXME: not portable to mac/amiga? + return; + loadActorAnim2(10, "s0r0d2", 158, 130, 2); + playSoundEffectIndex(0x05); +} + +void Room::demon0TalkToPrelate() { + const char *options1[] = { + "Capt. Kirk", + "#DEM0\\DEM0_006#I'm Captain James T. Kirk of the U.S.S. Enterprise. We have received word that alien lifeforms are creating problems at your mining facilities at Idyll Mountain. Tell me more.", + "#DEM0\\DEM0_008#Most High Prelate Angiven, I am honored to meet you. I consider it my divine duty to assist you in any possible way with the spawn of the devil.", + "#DEM0\\DEM0_003#Been seeing ghosts and bogeymen eh? I find that a little hard to believe.", + "" + }; + const char *firstResponse0[] = { + "Prel. Angiven", + "#DEM0\\DEM0_038#Certainly, Captain Kirk. Not aliens, per se -- we have encountered what we believe are demons at Idyll Mountain, creatures surely emerging from the very gates of Hell. Our God would not test us thus without reason, so we believe your might and insight are our God's method to help us discover what is going on.", + "" + }; + const char *firstResponse1[] = { + "Prel. Angiven", + "#DEM0\\DEM0_032#Captain Kirk. I had no idea we were blessed with one of our order in the ranks of Starfleet. We believe we have located the very Gates of Hell below Idyll Mountain.", + "" + }; + const char *options2[] = { + "Capt. Kirk", + "#DEM0\\DEM0_002#Aside from seeing demons, has any hard data been collected? Any evidence I could see?", + "#DEM0\\DEM0_005#Demons? Gates of Hell? This is the 23rd Century!", + "" + }; + const char *secondResponse[] = { + "Prel. Angiven", + "#DEM0\\DEM0_031#A skeptic would consider everything merely anecdotal or unproven. My people will gladly tell you their own stories, so you need not hear it secondhand through me.", + "" + }; + const char *options3[] = { + "Capt. Kirk", + "#DEM0\\DEM0_010#What can you tell me about the mine itself?", + "#DEM0\\DEM0_012#You're wasting the time of a starship capable of destroying this planet with campfire stories? No wonder you were dumped out here in the middle of nowhere.", + "" + }; + const char *thirdResponse[] = { + "Prel. Angiven", + "#DEM0\\DEM0_035#The area is exceptionally stable tectonically, and easy for our machinery to work in, praise God. We've mined for hafnium and a variety of useful trace elements. The deeper we dig, however, the more anomalous the variety of minerals seems to be. Our Ignaciate, Brother Stephen, has his own theories about why this might be. Either way, the anomalies inspired Brother Kandrey to conduct studies inside the mine. Yesterday, he reported discovering a strange door -- a gate to Hell, surely, for the demons caused a cave-in immediately. Kandrey was trapped, unconscious, and the demons prevent us from rescuing him. We can only hope he is still alive.", + "" + }; + + const char *badConclusion[] = { + "Prel. Angiven", + "#DEM0\\DEM0_037#We need your help, Kirk. You may have no respect for our beliefs, but I hope you will look beyond that. Godspeed.", + "" + }; + const char *goodConclusion[] = { + "Prel. Angiven", + "#DEM0\\DEM0_034#Thank you for your courtesy, Kirk. May you receive the guidance and protection of our God as you complete this divine mission.", + "" + }; + + if (_vm->_awayMission.field33 != 0) + return; + + _vm->_awayMission.missionScore += 3; + _vm->_awayMission.field33 = 1; + + const char **response = nullptr; + + switch (showRoomSpecificText(options1)) { + case 0: + response = firstResponse0; + break; + case 1: + response = firstResponse1; + break; + case 2: + demon0BadResponse(); + break; + } + + if (response != nullptr) + showRoomSpecificText(response); + + if (showRoomSpecificText(options2) == 1) + demon0BadResponse(); + + showRoomSpecificText(secondResponse); + + if (showRoomSpecificText(options3) == 1) + demon0BadResponse(); + + showRoomSpecificText(thirdResponse); + + if (_vm->_awayMission.field29 != 0) + showRoomSpecificText(badConclusion); + else + showRoomSpecificText(goodConclusion); +} + +void Room::demon0LookAtPrelate() { + const char *text[] = { + nullptr, + "#DEM0\\DEM0N004#High Prelate Angiven waits patiently for you to decide what you will do next.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0UsePhaserOnSnow() { + const char *text[] = { + "Ensign Everts", + "#DEM0\\DEM0_039#Aw, Captain, please don't melt the snow. I've never seen it before.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0UsePhaserOnSign() { + const char *text[] = { + "Dr. McCoy", + "#DEM0\\DEM0_017#Quite the vandal aren't we, Jim?", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0UsePhaserOnShelter() { + const char *text1[] = { + "Dr. McCoy", + "#DEM0\\DEM0_015#Burning down their house is not the best way to gain their confidence Jim!", + "" + }; + const char *text2[] = { + "Mr. Spock", + "#DEM0\\DEM0_013#Captain, Doctor McCoy is correct.", + "" + }; + const char *text3[] = { + "Ensign Everts", + "#DEM0\\DEM0_040#Is he always this trigger happy on ground missions?", + "" + }; + showRoomSpecificText(text1); + showRoomSpecificText(text2); + if (!_vm->_awayMission.redshirtDead) + showRoomSpecificText(text3); +} + +void Room::demon0UsePhaserOnPrelate() { + const char *text[] = { + "Dr. McCoy", + "#DEM0\\DEM0_020#Jim! Are you out of your mind?", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0LookAtSign() { + const char *text[] = { + "Sign", + "All mining equipment use this road.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0LookAtTrees() { + const char *text[] = { + nullptr, + "#DEM0\\DEM0N006#On the other side of the trees is Idyll Mountain. A tall, forbidding place. You have a vague feeling of danger.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0LookAtSnow() { + const char *text[] = { + nullptr, + "#DEM0\\DEM0N007#Remnants of a recent snowfall cover the ground.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0LookAnywhere() { + const char *text[] = { + nullptr, + "#DEM0\\DEM0N000#A beautiful, snow covered scene with a path leading off to Mount Idyll.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0LookAtBushes() { + const char *text[] = { + nullptr, + "#DEM0\\DEM0N010#Various bushes and shrubs grow along the edge of the forest.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0LookAtKirk() { + const char *text[] = { + nullptr, + "#DEM0\\DEM0N005#James Tiberius Kirk, Captain of the Enterprise. He's always happy to run an errand of mercy.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0LookAtMcCoy() { + const char *text[] = { + nullptr, + "#DEM0\\DEM0N002#Dr. Leonard McCoy, the finest doctor in Starfleet, wishes that he were on a warmer planet.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0LookAtRedShirt() { + const char *text[] = { + nullptr, + "#DEM0\\DEM0N003#Ensign Everts, who has never been this close to snow before in his life, gazes with child-like fascination at the ground.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0LookAtSpock() { + const char *text[] = { + nullptr, + "#DEM0\\DEM0N009#Spock raises an eyebrow.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0LookAtShelter() { + const char *text[] = { + nullptr, + "#DEM0\\DEM0N001#A quickly constructed spartan shelter, primarily used by fledgling colonies.", + "" + }; + showRoomSpecificText(text); +} + +void Room::demon0TalkToKirk() { + const char *text1[] = { + "Capt. Kirk", + "#DEM0\\DEM0_009#This planet's as beautiful as everyone says it is.", + "" + }; + const char *text2[] = { + "Dr. McCoy", + "#DEM0\\DEM0_027#The trees. The fresh air. The freezing cold...", + "" + }; + const char *text3[] = { + "Capt. Kirk", + "#DEM0\\DEM0_004#C'mon Bones, the cold will improve your circulation.", + "" + }; + const char *text4[] = { + "Dr. McCoy", + "#DEM0\\DEM0_024#Some people get too much circulation!", + "" + }; + + showRoomSpecificText(text1); + showRoomSpecificText(text2); + showRoomSpecificText(text3); + showRoomSpecificText(text4); +} + +void Room::demon0TalkToRedshirt() { + const char *text1[] = { + "Ensign Everts", + "#DEM0\\DEM0_043#I've never seen snow like this before. This is great!", + "" + }; + const char *text2[] = { + "Dr. McCoy", + "#DEM0\\DEM0_026#You mean you've never built a snowman, ensign?", + "" + }; + const char *text3[] = { + "Ensign Everts", + "#DEM0\\DEM0_042#I've never even thrown a snowball. Do you think anyone would mind?", + "" + }; + const char *text4[] = { + "Dr. McCoy", + "#DEM0\\DEM0_025#Well...", + "" + }; + const char *text5[] = { + "Capt. Kirk", + "#DEM0\\DEM0_007#Later Ensign. We have work to do.", + "" + }; + const char *text6[] = { + "Ensign Everts", + "#DEM0\\DEM0_044#Of course, sir.", + "" + }; + + showRoomSpecificText(text1); + showRoomSpecificText(text2); + showRoomSpecificText(text3); + showRoomSpecificText(text4); + showRoomSpecificText(text5); + showRoomSpecificText(text6); +} + +void Room::demon0TalkToMcCoy() { + if (_vm->_awayMission.field33 == 1) { + const char *text1[] = { + "Capt. Kirk", + "#DEM0\\DEM0_011#You look rather cold, Bones.", + "" + }; + const char *text2[] = { + "Dr. McCoy", + "#DEM0\\DEM0_023#I'm not cold, I'm freezing! And that damn transporter just had to set me down in the middle of a snow drift!", + "" + }; + const char *text3[] = { + "Mr. Spock", + "#DEM0\\DEM0_029#A centimeter of snow does not technically constitute a drift, Doctor.", + "" + }; + const char *text4[] = { + "Ensign Everts", + "#DEM0\\DEM0_041#And doctors say that patients complain too much!", + "" + }; + + showRoomSpecificText(text1); + showRoomSpecificText(text2); + showRoomSpecificText(text3); + if (!_vm->_awayMission.redshirtDead) + showRoomSpecificText(text4); + } + else { + const char *text1[] = { + "Dr. McCoy", + "#DEM0\\DEM0_019#I don't know if the problem is real, the result of a new illness, or mass hysteria. But at the very least, there's an injured miner who needs my help.", + "" + }; + + showRoomSpecificText(text1); + if (_vm->_awayMission.field36 != 1) { + demon0AskPrelateAboutSightings(); + } + } +} + +void Room::demon0TalkToSpock() { + const char *text1[] = { + "Mr. Spock", + "#DEM0\\DEM0_014#Captain, demons and supernatural creatures are, almost by definition, illogical. Yet it is evident these people believe what they have seen. Barring illness or mass hysteria, I agree that a real problem seems to exist.", + "" + }; + + if (_vm->_awayMission.field33 == 1) { + showRoomSpecificText(text1); + } + else { + showRoomSpecificText(text1); + if (_vm->_awayMission.field36 != 1) + demon0AskPrelateAboutSightings(); + } +} + +void Room::demon0AskPrelateAboutSightings() { + const char *text2[] = { + "Capt. Kirk", + "#DEM0\\DEM0_001#Doctor, you need to investigate the possibility of disease, mental or physical, among these people, before we go chasing up the mountains. Prelate Angiven, may we see those who have encountered the demons?", + "" + }; + const char *text3[] = { + "Prel. Angiven", + "#DEM0\\DEM0_030#They are already gathered in the chapel, and will cooperate in any way with you. First door on my right.", + "" + }; + + showRoomSpecificText(text2); + showRoomSpecificText(text3); + + _vm->_awayMission.field36 = 1; +} + +void Room::useSTricorderAnywhere() { + loadActorAnim2(OBJECT_SPOCK, "sscans", -1, -1, 0); + playSoundEffectIndex(0x04); + + const char *text[] = { + "Mr. Spock", + "#DEM0\\DEM0_028#Captain, reading the rocks in this area, I find that this locality may have been disturbed in the distant past. Recent disturbances created by the colonists' construction and mining prevent me from discovering anything further.", + "" + }; + + showRoomSpecificText(text); +} + +void Room::useMTricorderAnywhere() { + loadActorAnim2(OBJECT_MCCOY, "mscans", -1, -1, 0); + playSoundEffectIndex(0x04); + + const char *text[] = { + "Dr. McCoy", + "#DEM0\\DEM0_021#Jim, I am not picking up any unusual life here, just native lifeforms and the settlers. The colonists are all human, except for the one Tellarite. If there are demons here, they don't register on my tricorder.", + "" + }; + showRoomSpecificText(text); +} + +void Room::useMTricorderOnPrelate() { + loadActorAnim2(OBJECT_MCCOY, "mscans", -1, -1, 0); + playSoundEffectIndex(0x04); + + if (_vm->_awayMission.field33 == 1) { + const char *text[] = { + "Dr. McCoy", + "#DEM0\\DEM0_018#His blood pressure's up a bit, but he believes he's telling the truth.", + "" + }; + showRoomSpecificText(text); + } + else { + const char *text[] = { + "Dr. McCoy", + "#DEM0\\DEM0_022#The man's in perfect health.", + "" + }; + showRoomSpecificText(text); + } +} + +// Helper functions +void Room::demon0BadResponse() { + const char *text[] = { + "Prel. Angiven", + "#DEM0\\DEM0_033#Starfleet recognizes our freedom to worship and believe as we see fit, Captain. I am surprised that you do not share that feeling. Rest assured that Starfleet Command will be informed of your rudeness.", + "" + }; + + if (_vm->_awayMission.field29 != 0) + return; + + _vm->_awayMission.missionScore -= 3; + _vm->_awayMission.field29 = 1; + + showRoomSpecificText(text); +} +} + diff --git a/engines/startrek/rooms/function_map.h b/engines/startrek/rooms/function_map.h new file mode 100644 index 0000000000..6b5dfd0307 --- /dev/null +++ b/engines/startrek/rooms/function_map.h @@ -0,0 +1,83 @@ +/* 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. + * + */ + +#ifndef STARTREK_FUNCTIONMAP_H +#define STARTREK_FUNCTIONMAP_H + +#include "startrek/action.h" +#include "startrek/room.h" + +namespace StarTrek { + +RoomAction demon0ActionList[] = { + { Action(ACTION_TICK, 1, 0, 0), &Room::demon0Tick1 }, + { Action(ACTION_TICK, 2, 0, 0), &Room::demon0Tick2 }, + { Action(ACTION_TICK, 60, 0, 0), &Room::demon0Tick60 }, + { Action(ACTION_TICK, 100, 0, 0), &Room::demon0Tick100 }, + { Action(ACTION_TICK, 140, 0, 0), &Room::demon0Tick140 }, + + { Action(ACTION_TOUCHED_WARP, 0, 0, 0), &Room::demon0TouchedWarp0 }, + + // TODO: Walk events; entered room event; beamed in event + + { Action(ACTION_TOUCHED_HOTSPOT, 1, 0, 0), &Room::demon0TouchedHotspot1 }, + { Action(ACTION_TOUCHED_HOTSPOT, 0, 0, 0), &Room::demon0TouchedHotspot0 }, + + { Action(ACTION_TALK, 8, 0, 0), &Room::demon0TalkToPrelate }, + { Action(ACTION_LOOK, 8, 0, 0), &Room::demon0LookAtPrelate }, + + { Action(ACTION_USE, OBJECT_IPHASERS, 0x23, 0), &Room::demon0UsePhaserOnSnow }, + { Action(ACTION_USE, OBJECT_IPHASERK, 0x23, 0), &Room::demon0UsePhaserOnSnow }, + { Action(ACTION_USE, OBJECT_IPHASERS, 0x25, 0), &Room::demon0UsePhaserOnSign }, + { Action(ACTION_USE, OBJECT_IPHASERK, 0x25, 0), &Room::demon0UsePhaserOnSign }, + { Action(ACTION_USE, OBJECT_IPHASERK, 0x20, 0), &Room::demon0UsePhaserOnShelter }, + { Action(ACTION_USE, OBJECT_IPHASERK, 8, 0), &Room::demon0UsePhaserOnPrelate }, + + { Action(ACTION_LOOK, 0x25, 0, 0), &Room::demon0LookAtSign }, + { Action(ACTION_LOOK, 0x21, 0, 0), &Room::demon0LookAtTrees }, + { Action(ACTION_LOOK, 0x22, 0, 0), &Room::demon0LookAtTrees }, + { Action(ACTION_LOOK, 0x23, 0, 0), &Room::demon0LookAtSnow }, + { Action(ACTION_LOOK, 0xff, 0, 0), &Room::demon0LookAnywhere }, + { Action(ACTION_LOOK, 0x24, 0, 0), &Room::demon0LookAtBushes }, + + { Action(ACTION_LOOK, 0, 0, 0), &Room::demon0LookAtKirk }, + { Action(ACTION_LOOK, 2, 0, 0), &Room::demon0LookAtMcCoy }, + { Action(ACTION_LOOK, 3, 0, 0), &Room::demon0LookAtRedShirt }, + { Action(ACTION_LOOK, 1, 0, 0), &Room::demon0LookAtSpock }, + + { Action(ACTION_LOOK, 9, 0, 0), &Room::demon0LookAtShelter }, // Door 1 + { Action(ACTION_LOOK, 10, 0, 0), &Room::demon0LookAtShelter }, // Door 2 + { Action(ACTION_LOOK, 0x20, 0, 0), &Room::demon0LookAtShelter }, // Shelter itself + + { Action(ACTION_TALK, 0, 0, 0), &Room::demon0TalkToKirk }, + { Action(ACTION_TALK, 3, 0, 0), &Room::demon0TalkToRedshirt }, + { Action(ACTION_TALK, 2, 0, 0), &Room::demon0TalkToMcCoy }, + { Action(ACTION_TALK, 1, 0, 0), &Room::demon0TalkToSpock }, + + { Action(ACTION_USE, OBJECT_ISTRICOR, 0xff, 0), &Room::useSTricorderAnywhere }, + { Action(ACTION_USE, OBJECT_IMTRICOR, 0xff, 0), &Room::useMTricorderAnywhere }, + { Action(ACTION_USE, OBJECT_IMTRICOR, 8, 0), &Room::useMTricorderOnPrelate }, +}; + +} + +#endif diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp index 5e64682566..0c1b6d8ade 100644 --- a/engines/startrek/startrek.cpp +++ b/engines/startrek/startrek.cpp @@ -36,6 +36,7 @@ #include "startrek/filestream.h" #include "startrek/iwfile.h" #include "startrek/lzss.h" +#include "startrek/room.h" #include "startrek/startrek.h" namespace StarTrek { @@ -71,7 +72,7 @@ StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gam _keyboardControlsMouse = true; _inQuitGameMenu = false; - _textDisplayMode = TEXTDISPLAY_WAIT; + _textDisplayMode = TEXTDISPLAY_SUBTITLES; _textboxVar2 = 0; _textboxVar6 = 0; _textboxHasMultipleChoices = false; @@ -320,6 +321,10 @@ void StarTrekEngine::playSoundEffectIndex(int index) { } } +void StarTrekEngine::playMidiMusicTracks(int startTrack, int loopTrack) { + _sound->playMidiMusicTracks(startTrack, loopTrack); +} + void StarTrekEngine::playSpeech(const Common::String &filename) { _sound->playSpeech(filename.c_str()); } @@ -446,7 +451,7 @@ void StarTrekEngine::updateActorAnimations() { if (nextAnimFrame == actor->numAnimFrames - 1) { actor->field62++; if (actor->walkingIntoRoom != 0) { - addCommand(Command(COMMAND_FINISHED_BEAMING_IN, actor->field66, 0, 0)); + addAction(Action(ACTION_FINISHED_BEAMING_IN, actor->field66, 0, 0)); } } } @@ -517,7 +522,7 @@ void StarTrekEngine::updateActorAnimations() { if (actor->iwSrcPosition == -1) { if (actor->walkingIntoRoom != 0) { actor->walkingIntoRoom = 0; - addCommand(Command(COMMAND_FINISHED_ENTERING_ROOM, actor->field66 & 0xff, 0, 0)); + addAction(Action(ACTION_FINISHED_ENTERING_ROOM, actor->field66 & 0xff, 0, 0)); } actor->sprite.bitmap.reset(); @@ -981,7 +986,7 @@ void StarTrekEngine::updateMouseBitmap() { true, // ACTION_LOOK true // ACTION_TALK }; - const bool worksOnHotspots[] = { // True if the action reacts with hotspots? + const bool worksOnHotspots[] = { // True if the action reacts with hotspots false, // ACTION_WALK true, // ACTION_USE true, // ACTION_GET @@ -1048,7 +1053,7 @@ void StarTrekEngine::showInventoryIcons(bool showItem) { _inventoryIconSprite.pos.y = 10; _inventoryIconSprite.drawMode = 2; _inventoryIconSprite.drawPriority = 15; - _inventoryIconSprite.drawPriority2 = 15; + _inventoryIconSprite.drawPriority2 = 8; _inventoryIconSprite.setBitmap(_gfx->loadBitmap("inv00")); } diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h index 5301f4d7c1..217a06652b 100644 --- a/engines/startrek/startrek.h +++ b/engines/startrek/startrek.h @@ -36,12 +36,12 @@ #include "engines/engine.h" +#include "startrek/action.h" #include "startrek/awaymission.h" #include "startrek/filestream.h" #include "startrek/graphics.h" #include "startrek/items.h" #include "startrek/object.h" -#include "startrek/room.h" #include "startrek/sound.h" @@ -55,6 +55,7 @@ namespace Common { namespace StarTrek { class StarTrekEngine; +class Room; typedef String (StarTrekEngine::*TextGetterFunc)(int, uintptr, String *); @@ -94,7 +95,10 @@ enum TextDisplayMode { }; enum TextColor { - TEXTCOLOR_YELLOW = 0xb0 + TEXTCOLOR_GREY = 0x88, + TEXTCOLOR_RED = 0xa1, + TEXTCOLOR_YELLOW = 0xb0, + TEXTCOLOR_BLUE = 0xc0 }; // Keeps track of data for a list of buttons making up a menu @@ -161,55 +165,6 @@ struct TrekEvent { uint32 tick; }; -// Commands: Signals that can be passed to "handleAwayMissionCommands" or to room-specfiic -// code. -enum Commands { - COMMAND_TICK = 0, - COMMAND_WALK = 1, // Commands 1-5 correspond to Actions of the same number. - COMMAND_USE = 2, - COMMAND_GET = 3, - COMMAND_LOOK = 4, - COMMAND_TALK = 5, - COMMAND_TOUCHED_WARP = 6, - COMMAND_7 = 7, // Doors? (Or just hotspots activated by Kirk moving there?) - COMMAND_FINISHED_BEAMING_IN = 10, - COMMAND_FINISHED_ENTERING_ROOM = 12 -}; - -struct Command { - byte type; - - union { // FIXME: using unions in a dangeous way here... - struct { - byte b1; - byte b2; - byte b3; - } gen; - - struct { - byte activeObject; - byte passiveObject; - } action; - }; - - Command(byte _type, byte _b1, byte _b2, byte _b3) - : type(_type) { - gen.b1 = _b1; - gen.b2 = _b2; - gen.b3 = _b3; - } -}; - -// Actions that can be used on away missions. -enum Acton { - ACTION_WALK = 1, - ACTION_USE = 2, - ACTION_GET = 3, - ACTION_LOOK = 4, - ACTION_TALK = 5, - ACTION_OPTIONS = 13 // Not really an action, but selectable from action menu -}; - struct StarTrekGameDescription; class Graphics; @@ -220,7 +175,7 @@ class StarTrekEngine : public ::Engine { protected: Common::Error run(); -private: +public: // Game modes Common::Error runGameMode(int mode); @@ -234,9 +189,9 @@ private: void unloadRoom(); int loadActorAnimWithRoomScaling(int actorIndex, const Common::String &animName, int16 x, int16 y); uint16 getActorScaleAtPosition(int16 y); - void addCommand(const Command &command); + void addAction(const Action &action); bool checkItemInteractionExists(int action, int activeItem, int passiveItem, int16 arg6); - void handleAwayMissionCommand(); + void handleAwayMissionAction(); bool isPointInPolygon(int16 *data, int16 x, int16 y); void checkTouchedLoadingZone(int16 x, int16 y); @@ -255,6 +210,7 @@ public: // Running the game void playSoundEffectIndex(int index); + void playMidiMusicTracks(int startTrack, int loopTrack); void playSpeech(const Common::String &filename); void stopPlayingSpeech(); @@ -405,8 +361,8 @@ public: Common::String _txtFilename; Common::String _loadedText; // TODO: might be OK to delete this - // Queue of "commands" (ie. next frame, clicked on object) for away mission or bridge - Common::Queue<Command> _commandQueue; + // Queue of "actions" (ie. next frame, clicked on object) for away mission or bridge + Common::Queue<Action> _actionQueue; AwayMission _awayMission; bool _warpHotspotsActive; diff --git a/engines/startrek/text.cpp b/engines/startrek/text.cpp index 11602bf60e..2df5e3bed1 100644 --- a/engines/startrek/text.cpp +++ b/engines/startrek/text.cpp @@ -25,6 +25,7 @@ #include "graphics/cursorman.h" #include "startrek/graphics.h" +#include "startrek/room.h" namespace StarTrek { @@ -136,7 +137,7 @@ void StarTrekEngine::showTextbox(String headerText, const String &mainText, int headerText += ' '; } - int commandParam = (maxTextLines < 0 ? 0 : maxTextLines); + int actionParam = (maxTextLines < 0 ? 0 : maxTextLines); if (maxTextLines < 0) maxTextLines = -maxTextLines; @@ -152,7 +153,8 @@ void StarTrekEngine::showTextbox(String headerText, const String &mainText, int showText(&StarTrekEngine::readTextFromArray, (uintptr)strings, xoffset, yoffset, textColor, false, maxTextLines, false); - addCommand(Command(COMMAND_TALK, commandParam, 0, 0)); + if (actionParam != 0) + addAction(Action(ACTION_TALK, actionParam, 0, 0)); } String StarTrekEngine::skipTextAudioPrompt(const String &str) { |