aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorMatthew Stewart2018-05-15 17:36:11 -0400
committerEugene Sandulenko2018-08-09 08:37:30 +0200
commitbe8e807a4bbf28959e6e07b505d27b8ae622e0ef (patch)
treefe534f114335e952b6343066933d07f0111e0674 /engines
parent2a588200ed4907d56c3927de0acc1fc59d22aa7d (diff)
downloadscummvm-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.cpp155
-rw-r--r--engines/startrek/awaymission.h3
-rw-r--r--engines/startrek/events.cpp2
-rw-r--r--engines/startrek/object.h2
-rw-r--r--engines/startrek/room.h12
-rw-r--r--engines/startrek/startrek.cpp51
-rw-r--r--engines/startrek/startrek.h23
-rw-r--r--engines/startrek/text.cpp2
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;