diff options
author | Matthew Stewart | 2018-05-15 17:36:11 -0400 |
---|---|---|
committer | Eugene Sandulenko | 2018-08-09 08:37:30 +0200 |
commit | be8e807a4bbf28959e6e07b505d27b8ae622e0ef (patch) | |
tree | fe534f114335e952b6343066933d07f0111e0674 /engines | |
parent | 2a588200ed4907d56c3927de0acc1fc59d22aa7d (diff) | |
download | scummvm-rg350-be8e807a4bbf28959e6e07b505d27b8ae622e0ef.tar.gz scummvm-rg350-be8e807a4bbf28959e6e07b505d27b8ae622e0ef.tar.bz2 scummvm-rg350-be8e807a4bbf28959e6e07b505d27b8ae622e0ef.zip |
STARTREK: Warps between rooms
Diffstat (limited to 'engines')
-rw-r--r-- | engines/startrek/awaymission.cpp | 155 | ||||
-rw-r--r-- | engines/startrek/awaymission.h | 3 | ||||
-rw-r--r-- | engines/startrek/events.cpp | 2 | ||||
-rw-r--r-- | engines/startrek/object.h | 2 | ||||
-rw-r--r-- | engines/startrek/room.h | 12 | ||||
-rw-r--r-- | engines/startrek/startrek.cpp | 51 | ||||
-rw-r--r-- | engines/startrek/startrek.h | 23 | ||||
-rw-r--r-- | engines/startrek/text.cpp | 2 |
8 files changed, 184 insertions, 66 deletions
diff --git a/engines/startrek/awaymission.cpp b/engines/startrek/awaymission.cpp index 16ce842eb7..efa603d69d 100644 --- a/engines/startrek/awaymission.cpp +++ b/engines/startrek/awaymission.cpp @@ -51,7 +51,7 @@ void StarTrekEngine::runAwayMission() { if (!_commandQueue.empty()) { // sub_200e7(); // sub_20118(); - runAwayMissionCycle(); + handleAwayMissionCommand(); } } } @@ -61,16 +61,13 @@ void StarTrekEngine::cleanupAwayMission() { } void StarTrekEngine::loadRoom(const Common::String &missionName, int roomIndex) { - if (_room != nullptr) - delete _room; - _keyboardControlsMouse = true; _missionName = _missionToLoad; - _roomIndex = _roomIndexToLoad; + _roomIndex = roomIndex; _roomFrameCounter = 0; - _awayMission.field1d = 0; + _awayMission.transitioningIntoRoom = 0; _gfx->fadeoutScreen(); _sound->stopAllVocSounds(); @@ -82,7 +79,7 @@ void StarTrekEngine::loadRoom(const Common::String &missionName, int roomIndex) _gfx->loadPalette("palette"); _gfx->copyBackgroundScreen(); - _room = new Room(this, _screenName); + _room = SharedPtr<Room>(new Room(this, _screenName)); // Original sets up bytes 0-3 of rdf file as "remote function caller" @@ -110,13 +107,27 @@ void StarTrekEngine::initAwayCrewPositions(int warpEntryIndex) { memset(_awayMission.field25, 0xff, 4); switch (warpEntryIndex) { - case 0: - break; + case 0: // 0-3: Read warp positions from RDF file case 1: - break; case 2: - break; case 3: + for (int i = 0; i < (_awayMission.redshirtDead ? 3 : 4); i++) { + Common::String anim = getCrewmanAnimFilename(i, "walk"); + + int16 rdfOffset = RDF_ROOM_ENTRY_POSITIONS + warpEntryIndex * 32 + i * 8; + + int16 srcX = _room->readRdfWord(rdfOffset + 0); // Position to spawn at + int16 srcY = _room->readRdfWord(rdfOffset + 2); + int16 destX = _room->readRdfWord(rdfOffset + 4); // Position to walk to + int16 destY = _room->readRdfWord(rdfOffset + 6); + + objectWalkToPosition(i, anim, srcX, srcY, destX, destY); + } + + _kirkObject->walkingIntoRoom = 1; + _kirkObject->field66 = 0xff; + _awayMission.transitioningIntoRoom = 1; + _warpHotspotsActive = false; break; case 4: // Crew is beaming in. warpEntryIndex -= 4; @@ -125,11 +136,11 @@ void StarTrekEngine::initAwayCrewPositions(int warpEntryIndex) { Common::Point warpPos = _room->getBeamInPosition(i); loadObjectAnimWithRoomScaling(i, animFilename, warpPos.x, warpPos.y); } - _kirkObject->field64 = 1; + _kirkObject->walkingIntoRoom = 1; _kirkObject->field66 = 0xff; - _awayMission.field1d = 1; + _awayMission.transitioningIntoRoom = 1; playSoundEffectIndex(0x09); - // word_466f2 = 0; + _warpHotspotsActive = false; break; case 5: break; @@ -154,13 +165,13 @@ void StarTrekEngine::handleAwayMissionEvents() { // sub_22de0(); _frameIndex++; _roomFrameCounter++; - // sub_20099(0, _roomFrameCounter & 0xff, (_roomFrameCounter >> 8) & 0xff, 0); + addCommand(Command(COMMAND_TICK, _roomFrameCounter & 0xff, (_roomFrameCounter >> 8) & 0xff, 0)); if (_roomFrameCounter >= 2) _gfx->incPaletteFadeLevel(); break; case TREKEVENT_LBUTTONDOWN: - //if (_awayMission.field1d != 0) // FIXME: uncomment - // break; + if (_awayMission.transitioningIntoRoom != 0) + break; switch (_awayMission.mapFileLoaded) { case 1: if (_awayMission.field1c == 0) { @@ -204,6 +215,14 @@ void StarTrekEngine::handleAwayMissionEvents() { } } +void StarTrekEngine::unloadRoom() { + _gfx->fadeoutScreen(); + // sub_2394b(); // TODO + objectFunc1(); + _room.reset(); + _mapFile.reset(); +} + /** * Similar to loadObjectAnim, but scale is determined by the y-position in the room. The * further up (away) the object is, the smaller it is. @@ -226,12 +245,108 @@ uint16 StarTrekEngine::getObjectScaleAtPosition(int16 y) { return ((_playerObjectScale * (y - var08)) >> 8) + var0a; } -Room *StarTrekEngine::getRoom() { +SharedPtr<Room> StarTrekEngine::getRoom() { return _room; } -void StarTrekEngine::runAwayMissionCycle() { - // TODO +void StarTrekEngine::addCommand(const Command &command) { + if (command.type != COMMAND_TICK) + debug("Command %d: %x, %x, %x", command.type, command.b1, command.b2, command.b3); + _commandQueue.push(command); +} + +void StarTrekEngine::handleAwayMissionCommand() { + Command command = _commandQueue.pop(); + + if ((command.type == COMMAND_FINISHED_BEAMING_IN || command.type == FINISHED_ENTERING_ROOM) && command.b1 == 0xff) { + _awayMission.transitioningIntoRoom = 0; + _warpHotspotsActive = true; + return; + } + else if (command.type == FINISHED_ENTERING_ROOM && command.b1 >= 0xe0) { // TODO + return; + } + + switch (command.type) { // TODO: everything + case COMMAND_TOUCHED_WARP: + // if (!sub_203e1(command.type)) // Probably calls RDF code + { + byte warpIndex = command.b1; + int16 roomIndex = _room->readRdfWord(RDF_WARP_ROOM_INDICES + warpIndex * 2); + unloadRoom(); + _sound->loadMusicFile("ground"); + loadRoom(_missionName, roomIndex); + initAwayCrewPositions(warpIndex ^ 1); + } + break; + } +} + +/** + * Returns true if the given position is contained in a polygon? + * + * The data passed contains the following words in this order: + * * Index of polygon (unused here) + * * Number of vertices in polygon + * * For each vertex: x and y coordinates. + */ +bool StarTrekEngine::isPointInPolygon(int16 *data, int16 x, int16 y) { + int16 numVertices = data[1]; + int16 *vertData = &data[2]; + + for (int i = 0; i < numVertices; i++) { + Common::Point p1(vertData[0], vertData[1]); + Common::Point p2; + if (i == numVertices - 1) // Loop to 1st vertex + p2 = Common::Point(data[2], data[3]); + else + p2 = Common::Point(vertData[2], vertData[3]); + + if ((p2.x - p1.x) * (y - p1.y) - (p2.y - p1.y) * (x - p1.x) < 0) + return false; + + vertData += 2; + } + + return true; +} + +void StarTrekEngine::checkTouchedLoadingZone(int16 x, int16 y) { + int16 offset = _room->getFirstDoorPolygonOffset(); + + while (offset != _room->getDoorPolygonEndOffset()) { + if (isPointInPolygon((int16*)(_room->_rdfData + offset), x, y)) { + uint16 var = _room->readRdfWord(offset); + if (_activeDoorWarpHotspot != var) { + _activeDoorWarpHotspot = var; + addCommand(Command(COMMAND_7, var & 0xff, 0, 0)); + } + return; + } + + int16 numVertices = _room->readRdfWord(offset + 2); + offset += numVertices * 4 + 4; + } + _activeDoorWarpHotspot = -1; + + if (_awayMission.field24 == 0 && _warpHotspotsActive) { + offset = _room->getFirstWarpPolygonOffset(); + + while (offset != _room->getWarpPolygonEndOffset()) { + if (isPointInPolygon((int16*)(_room->_rdfData + offset), x, y)) { + uint16 var = _room->readRdfWord(offset); + if (_activeWarpHotspot != var) { + _activeWarpHotspot = var; + addCommand(Command(COMMAND_TOUCHED_WARP, var & 0xff, 0, 0)); + } + return; + } + + int16 numVertices = _room->readRdfWord(offset + 2); + offset += numVertices * 4 + 4; + } + } + _activeWarpHotspot = -1; } /** diff --git a/engines/startrek/awaymission.h b/engines/startrek/awaymission.h index f2a9ca68c4..2036b604c3 100644 --- a/engines/startrek/awaymission.h +++ b/engines/startrek/awaymission.h @@ -28,9 +28,10 @@ struct AwayMission { int16 mouseX; int16 mouseY; byte field1c; - byte field1d; // Set while beaming in? + byte transitioningIntoRoom; // Set while beaming in or walking into a room bool redshirtDead; byte mapFileLoaded; + byte field24; int8 field25[4]; bool rdfRunNextCommand; diff --git a/engines/startrek/events.cpp b/engines/startrek/events.cpp index 354dfb1c77..f36ce6a1d2 100644 --- a/engines/startrek/events.cpp +++ b/engines/startrek/events.cpp @@ -41,6 +41,8 @@ void StarTrekEngine::pollSystemEvents() { addEventToQueue(trekEvent); break; case Common::EVENT_LBUTTONDOWN: + // TODO: what happens when mouse click is outside normal screen bounds? + // (apparently this can happen) trekEvent.type = TREKEVENT_LBUTTONDOWN; addEventToQueue(trekEvent); break; diff --git a/engines/startrek/object.h b/engines/startrek/object.h index eb0f3dacad..cdcae7403f 100644 --- a/engines/startrek/object.h +++ b/engines/startrek/object.h @@ -48,7 +48,7 @@ struct Object { Common::Point pos; uint16 field60; uint16 field62; - uint16 field64; + uint16 walkingIntoRoom; // Walking or beaming into a room? uint16 field66; char animationString2[8]; uint16 field70; diff --git a/engines/startrek/room.h b/engines/startrek/room.h index a06d2af94f..e9bbbd01db 100644 --- a/engines/startrek/room.h +++ b/engines/startrek/room.h @@ -34,6 +34,12 @@ namespace StarTrek { class StarTrekEngine; +// Offsets of data in RDF files + +const int RDF_WARP_ROOM_INDICES = 0x22; +const int RDF_ROOM_ENTRY_POSITIONS = 0x2a; +const int RDF_BEAM_IN_POSITIONS = 0xaa; + class Room { public: @@ -49,6 +55,12 @@ public: int16 getVar0a() { return readRdfWord(0x0a); } int16 getVar0c() { return readRdfWord(0x0c); } + // Warp-related stuff + int16 getFirstWarpPolygonOffset() { return readRdfWord(0x16); } + int16 getWarpPolygonEndOffset() { return readRdfWord(0x18); } + int16 getFirstDoorPolygonOffset() { return readRdfWord(0x1a); } + int16 getDoorPolygonEndOffset() { return readRdfWord(0x1c); } + Common::Point getBeamInPosition(int crewmanIndex); byte *_rdfData; diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp index 15c991e227..82fe2e1a77 100644 --- a/engines/startrek/startrek.cpp +++ b/engines/startrek/startrek.cpp @@ -54,7 +54,6 @@ StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gam _gfx = nullptr; _sound = nullptr; _macResFork = nullptr; - _room = nullptr; _clockTicks = 0; @@ -78,8 +77,6 @@ StarTrekEngine::~StarTrekEngine() { delete _gfx; delete _sound; delete _macResFork; - - delete _room; } Common::Error StarTrekEngine::run() { @@ -103,26 +100,6 @@ Common::Error StarTrekEngine::run() { runGameMode(GAMEMODE_AWAYMISSION); return Common::kNoError; - - -#if 1 - _room = new Room(this, "DEMON0"); - _gfx->loadPalette("PALETTE"); - _gfx->loadPri("DEMON0.PRI"); - - _sound->loadMusicFile("GROUND"); - - - while (true) { - _gfx->showOptionsMenu(0, 0); - } - - while (!shouldQuit()) { - pollSystemEvents(); - } - - return Common::kNoError; -#endif } Common::Error StarTrekEngine::runGameMode(int mode) { @@ -298,10 +275,10 @@ void StarTrekEngine::playSoundEffectIndex(int index) { case 0x08: _sound->playVoc("TRANSDEM"); break; - case 0x09: + case 0x09: // Beaming in? _sound->playVoc("TRANSMAT"); break; - case 0x0a: + case 0x0a: // Beaming out? _sound->playVoc("TRANSENE"); break; case 0x10: // Menu selection sound @@ -376,7 +353,7 @@ int StarTrekEngine::loadObjectAnim(int objectIndex, const Common::String &animNa drawObjectToScreen(object, animName, x, y, scale, true); } - object->field64 = 0; + object->walkingIntoRoom = 0; object->field66 = 0; return objectIndex; @@ -391,7 +368,7 @@ bool StarTrekEngine::objectWalkToPosition(int objectIndex, const Common::String Object *object = &_objectList[objectIndex]; - object->field64 = 0; + object->walkingIntoRoom = 0; if (isPositionSolid(destX, destY)) return false; @@ -408,7 +385,7 @@ bool StarTrekEngine::objectWalkToPosition(int objectIndex, const Common::String object->dest.x = destX; object->dest.y = destY; object->field92 = 0; - object->field64 = 0; + object->walkingIntoRoom = 0; object->iwDestPosition = -1; object->iwSrcPosition = -1; @@ -458,8 +435,8 @@ void StarTrekEngine::updateObjectAnimations() { if (object->animFrame != nextAnimFrame) { if (nextAnimFrame == object->numAnimFrames - 1) { object->field62++; - if (object->field64 != 0) { - // sub_20099(10, object->field66, 0, 0); + if (object->walkingIntoRoom != 0) { + addCommand(Command(COMMAND_FINISHED_BEAMING_IN, object->field66, 0, 0)); } } } @@ -500,10 +477,8 @@ void StarTrekEngine::updateObjectAnimations() { case 1: // Walking if (_frameIndex < object->frameToStartNextAnim) break; - /* - if (i == 0) // TODO: Kirk only - sub_22c2d(object->pos.x, object->pos.y); - */ + if (i == 0) // Kirk only + checkTouchedLoadingZone(object->pos.x, object->pos.y); if (object->field90 != 0) { Sprite *sprite = &object->sprite; int loops; @@ -530,9 +505,9 @@ void StarTrekEngine::updateObjectAnimations() { } else { // object->field90 == 0 if (object->iwSrcPosition == -1) { - if (object->field64 != 0) { - object->field64 = 0; - //addCommand(COMMAND_12, object->field66 & 0xff, 0, 0); // TODO + if (object->walkingIntoRoom != 0) { + object->walkingIntoRoom = 0; + addCommand(Command(FINISHED_ENTERING_ROOM, object->field66 & 0xff, 0, 0)); } object->sprite.bitmap.reset(); @@ -1287,7 +1262,7 @@ void StarTrekEngine::playMovieMac(Common::String filename) { delete qtDecoder; // Swap back to 8bpp mode - initGraphics(320, 200); + initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT); } } // End of namespace StarTrek diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h index 0c3273f394..7560efa8d7 100644 --- a/engines/startrek/startrek.h +++ b/engines/startrek/startrek.h @@ -100,14 +100,20 @@ struct TrekEvent { enum Commands { COMMAND_TICK = 0, COMMAND_CLICKED_ON_OBJECT = 1, - COMMAND_12 = 12 + COMMAND_TOUCHED_WARP = 6, + COMMAND_7 = 7, // Doors? (Or just hotspots activated by Kirk moving there?) + COMMAND_FINISHED_BEAMING_IN = 10, + FINISHED_ENTERING_ROOM = 12 }; struct Command { byte type; - byte b1; // These depend on command type? + byte b1; byte b2; byte b3; + + Command(byte _type, byte _b1, byte _b2, byte _b3) + : type(_type), b1(_b1), b2(_b2), b3(_b3) {} }; const int MAX_OBJECTS = 0x20; @@ -132,14 +138,18 @@ private: void loadRoom(const Common::String &missionName, int roomIndex); void initAwayCrewPositions(int warpEntryIndex); void handleAwayMissionEvents(); + void unloadRoom(); int loadObjectAnimWithRoomScaling(int objectIndex, const Common::String &animName, int16 x, int16 y); uint16 getObjectScaleAtPosition(int16 y); - void runAwayMissionCycle(); + void addCommand(const Command &command); + void handleAwayMissionCommand(); + bool isPointInPolygon(int16 *data, int16 x, int16 y); + void checkTouchedLoadingZone(int16 x, int16 y); bool isPositionSolid(int16 x, int16 y); public: - Room *getRoom(); + SharedPtr<Room> getRoom(); private: // Transporter room @@ -232,6 +242,9 @@ public: Common::Queue<Command> _commandQueue; AwayMission _awayMission; + bool _warpHotspotsActive; + int16 _activeWarpHotspot; + int16 _activeDoorWarpHotspot; Object _objectList[MAX_OBJECTS]; Object * const _kirkObject; @@ -271,7 +284,7 @@ public: private: Common::MacResManager *_macResFork; - Room *_room; + SharedPtr<Room> _room; SharedPtr<IWFile> _iwFile; }; diff --git a/engines/startrek/text.cpp b/engines/startrek/text.cpp index ef5a746756..945ff31468 100644 --- a/engines/startrek/text.cpp +++ b/engines/startrek/text.cpp @@ -387,7 +387,7 @@ int Graphics::handleMenuEvents(uint32 ticksUntilClickingEnabled, bool arg4) { * Text getter for showText which reads from an rdf file. */ String Graphics::readTextFromRdf(int choiceIndex, uintptr data, String *headerTextOutput) { - Room *room = _vm->getRoom(); + SharedPtr<Room> room = _vm->getRoom(); int rdfVar = (size_t)data; |