mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-16 14:50:17 +00:00
STARTREK: Warps between rooms
This commit is contained in:
parent
2a588200ed
commit
be8e807a4b
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user