diff --git a/engines/pegasus/module.mk b/engines/pegasus/module.mk index af79e7cd90ee..56a958948e6e 100644 --- a/engines/pegasus/module.mk +++ b/engines/pegasus/module.mk @@ -24,7 +24,7 @@ MODULE_OBJS = \ neighborhood/door.o \ neighborhood/exit.o \ neighborhood/extra.o \ - neighborhood/hotspot.o \ + neighborhood/hotspotinfo.o \ neighborhood/neighborhood.o \ neighborhood/spot.o \ neighborhood/turn.o \ diff --git a/engines/pegasus/neighborhood/hotspot.cpp b/engines/pegasus/neighborhood/hotspotinfo.cpp similarity index 89% rename from engines/pegasus/neighborhood/hotspot.cpp rename to engines/pegasus/neighborhood/hotspotinfo.cpp index 16af1a6d48be..1cd241612cee 100755 --- a/engines/pegasus/neighborhood/hotspot.cpp +++ b/engines/pegasus/neighborhood/hotspotinfo.cpp @@ -27,11 +27,11 @@ #include "common/stream.h" #include "common/textconsole.h" -#include "pegasus/neighborhood/hotspot.h" +#include "pegasus/neighborhood/hotspotinfo.h" namespace Pegasus { -void HotspotTable::loadFromStream(Common::SeekableReadStream *stream) { +void HotspotInfoTable::loadFromStream(Common::SeekableReadStream *stream) { uint32 count = stream->readUint32BE(); _entries.resize(count); @@ -50,11 +50,11 @@ void HotspotTable::loadFromStream(Common::SeekableReadStream *stream) { } } -void HotspotTable::clear() { +void HotspotInfoTable::clear() { _entries.clear(); } -HotspotTable::Entry HotspotTable::findEntry(tHotSpotID hotspot) { +HotspotInfoTable::Entry HotspotInfoTable::findEntry(tHotSpotID hotspot) { for (uint32 i = 0; i < _entries.size(); i++) if (_entries[i].hotspot == hotspot) return _entries[i]; diff --git a/engines/pegasus/neighborhood/hotspot.h b/engines/pegasus/neighborhood/hotspotinfo.h similarity index 92% rename from engines/pegasus/neighborhood/hotspot.h rename to engines/pegasus/neighborhood/hotspotinfo.h index ea7f3bbeea22..3199a515084a 100755 --- a/engines/pegasus/neighborhood/hotspot.h +++ b/engines/pegasus/neighborhood/hotspotinfo.h @@ -23,8 +23,8 @@ * */ -#ifndef PEGASUS_NEIGHBORHOOD_HOTSPOT_H -#define PEGASUS_NEIGHBORHOOD_HOTSPOT_H +#ifndef PEGASUS_NEIGHBORHOOD_HOTSPOTINFO_H +#define PEGASUS_NEIGHBORHOOD_HOTSPOTINFO_H #include "common/array.h" #include "common/endian.h" @@ -37,10 +37,10 @@ namespace Common { namespace Pegasus { -class HotspotTable { +class HotspotInfoTable { public: - HotspotTable() {} - ~HotspotTable() {} + HotspotInfoTable() {} + ~HotspotInfoTable() {} static const uint32 getResTag() { return MKTAG('H', 'S', 'I', 'n'); } diff --git a/engines/pegasus/neighborhood/neighborhood.cpp b/engines/pegasus/neighborhood/neighborhood.cpp index 291c0a97d171..1197c65b9853 100644 --- a/engines/pegasus/neighborhood/neighborhood.cpp +++ b/engines/pegasus/neighborhood/neighborhood.cpp @@ -27,11 +27,14 @@ #include "common/stream.h" #include "pegasus/pegasus.h" +#include "pegasus/game_shell/CGameState.h" #include "pegasus/neighborhood/neighborhood.h" namespace Pegasus { -Neighborhood::Neighborhood(PegasusEngine *vm, const Common::String &resName) : _vm(vm), _resName(resName) { +Neighborhood::Neighborhood(PegasusEngine *vm, const Common::String &resName, tNeighborhoodID id) : _vm(vm), _resName(resName) { + CGameState::SetOpenDoorLocation(kNoRoomID, kNoDirection); + _currentAlternate = 0; } Neighborhood::~Neighborhood() { @@ -58,10 +61,10 @@ void Neighborhood::init() { _extraTable.loadFromStream(stream); delete stream; - stream = _vm->_resFork->getResource(_hotspotTable.getResTag(), _resName); + stream = _vm->_resFork->getResource(_hotspotInfoTable.getResTag(), _resName); if (!stream) - error("Failed to load hotspots"); - _hotspotTable.loadFromStream(stream); + error("Failed to load hotspot info"); + _hotspotInfoTable.loadFromStream(stream); delete stream; stream = _vm->_resFork->getResource(_spotTable.getResTag(), _resName); @@ -91,4 +94,133 @@ void Neighborhood::init() { // TODO: AI, movies, notifications, buncha other stuff } +void Neighborhood::start() { + CGameState::SetCurrentRoom(CGameState::GetLastRoom()); + CGameState::SetCurrentDirection(CGameState::GetLastDirection()); + arriveAt(CGameState::GetNextRoom(), CGameState::GetNextDirection()); +} + +void Neighborhood::arriveAt(tRoomID room, tDirectionConstant direction) { + // TODO +} + +// These functions can be overridden to tweak the exact frames used. + +void Neighborhood::getExitEntry(const tRoomID room, const tDirectionConstant direction, ExitTable::Entry &entry) { + entry = _exitTable.findEntry(room, direction, _currentAlternate); + + if (entry.isEmpty()) + entry = _exitTable.findEntry(room, direction, kNoAlternateID); +} + +TimeValue Neighborhood::getViewTime(const tRoomID room, const tDirectionConstant direction) { + if (CGameState::GetOpenDoorRoom() == room && CGameState::GetOpenDoorDirection() == direction) { + // If we get here, the door entry for this location must exist. + DoorTable::Entry doorEntry = _doorTable.findEntry(room, direction, _currentAlternate); + + if (doorEntry.isEmpty()) + doorEntry = _doorTable.findEntry(room, direction, kNoAlternateID); + + return doorEntry.movieEnd - 1; + } + + ViewTable::Entry viewEntry = _viewTable.findEntry(room, direction, _currentAlternate); + + if (viewEntry.isEmpty()) + viewEntry = _viewTable.findEntry(room, direction, kNoAlternateID); + + return viewEntry.time; +} + +void Neighborhood::getDoorEntry(const tRoomID room, const tDirectionConstant direction, DoorTable::Entry &doorEntry) { + doorEntry = _doorTable.findEntry(room, direction, _currentAlternate); + + if (doorEntry.isEmpty()) + doorEntry = _doorTable.findEntry(room, direction, kNoAlternateID); +} + +tDirectionConstant Neighborhood::getTurnEntry(const tRoomID room, const tDirectionConstant direction, const tTurnDirection turn) { + TurnTable::Entry turnEntry = _turnTable.findEntry(room, direction, turn, _currentAlternate); + + if (turnEntry.isEmpty()) + turnEntry = _turnTable.findEntry(room, direction, turn, kNoAlternateID); + + return turnEntry.turnDirection; +} + +void Neighborhood::findSpotEntry(const tRoomID room, const tDirectionConstant direction, tSpotFlags flags, SpotTable::Entry &spotEntry) { + spotEntry = _spotTable.findEntry(room, direction, flags, _currentAlternate); + + if (spotEntry.isEmpty()) + spotEntry = _spotTable.findEntry(room, direction, flags, kNoAlternateID); +} + +void Neighborhood::getZoomEntry(const tHotSpotID id, ZoomTable::Entry &zoomEntry) { + zoomEntry = _zoomTable.findEntry(id); +} + +void Neighborhood::getHotspotEntry(const tHotSpotID id, HotspotInfoTable::Entry &hotspotEntry) { + hotspotEntry = _hotspotInfoTable.findEntry(id); +} + +void Neighborhood::getExtraEntry(const uint32 id, ExtraTable::Entry &extraEntry) { + extraEntry = _extraTable.findEntry(id); +} + +///////////////////////////////////////////// +// +// "Can" functions: Called to see whether or not a user is allowed to do something + +tCanMoveForwardReason Neighborhood::canMoveForward(ExitTable::Entry &entry) { + DoorTable::Entry door; + + getExitEntry(CGameState::GetCurrentRoom(), CGameState::GetCurrentDirection(), entry); + getDoorEntry(CGameState::GetCurrentRoom(), CGameState::GetCurrentDirection(), door); + + // Fixed this so that doors that don't lead anywhere can be opened, but not walked + // through. + if (door.flags & kDoorPresentMask) { + if (CGameState::IsCurrentDoorOpen()) { + if (entry.exitRoom == kNoRoomID) + return kCantMoveBlocked; + else + return kCanMoveForward; + } else if (door.flags & kDoorLockedMask) { + return kCantMoveDoorLocked; + } else { + return kCantMoveDoorClosed; + } + } else if (entry.exitRoom == kNoRoomID) { + return kCantMoveBlocked; + } + + return kCanMoveForward; +} + +tCanTurnReason Neighborhood::canTurn(tTurnDirection turn, tDirectionConstant &nextDir) { + nextDir = getTurnEntry(CGameState::GetCurrentRoom(), CGameState::GetCurrentDirection(), turn); + + if (nextDir == kNoDirection) + return kCantTurnNoTurn; + + return kCanTurn; +} + +tCanOpenDoorReason Neighborhood::canOpenDoor(DoorTable::Entry &entry) { + getDoorEntry(CGameState::GetCurrentRoom(), CGameState::GetCurrentDirection(), entry); + + if (entry.flags & kDoorPresentMask) { + if (CGameState::IsCurrentDoorOpen()) + return kCantOpenAlreadyOpen; + + if (entry.flags & kDoorLockedMask) + return kCantOpenLocked; + + return kCanOpenDoor; + } + + return kCantOpenNoDoor; +} + + } // End of namespace Pegasus diff --git a/engines/pegasus/neighborhood/neighborhood.h b/engines/pegasus/neighborhood/neighborhood.h index d70628e0d505..0b8be864e129 100644 --- a/engines/pegasus/neighborhood/neighborhood.h +++ b/engines/pegasus/neighborhood/neighborhood.h @@ -31,7 +31,7 @@ #include "pegasus/neighborhood/door.h" #include "pegasus/neighborhood/exit.h" #include "pegasus/neighborhood/extra.h" -#include "pegasus/neighborhood/hotspot.h" +#include "pegasus/neighborhood/hotspotinfo.h" #include "pegasus/neighborhood/spot.h" #include "pegasus/neighborhood/turn.h" #include "pegasus/neighborhood/view.h" @@ -41,25 +41,58 @@ namespace Pegasus { class PegasusEngine; +// Pegasus Prime neighborhood id's +const tNeighborhoodID kCaldoriaID = 0; +const tNeighborhoodID kFullTSAID = 1; +const tNeighborhoodID kFinalTSAID = 2; +const tNeighborhoodID kTinyTSAID = 3; +const tNeighborhoodID kPrehistoricID = 4; +const tNeighborhoodID kMarsID = 5; +const tNeighborhoodID kWSCID = 6; +const tNeighborhoodID kNoradAlphaID = 7; +const tNeighborhoodID kNoradDeltaID = 8; +// The sub chase is not really a neighborhood, but we define a constant that is used +// to allow an easy transition out of Norad Alpha. +const tNeighborhoodID kNoradSubChaseID = 1000; + class Neighborhood { public: - Neighborhood(PegasusEngine *vm, const Common::String &resName); + Neighborhood(PegasusEngine *vm, const Common::String &resName, tNeighborhoodID id); virtual ~Neighborhood(); virtual void init(); + void start(); + + void arriveAt(tRoomID room, tDirectionConstant direction); + + virtual void getExitEntry(const tRoomID room, const tDirectionConstant direction, ExitTable::Entry &entry); + virtual TimeValue getViewTime(const tRoomID room, const tDirectionConstant direction); + virtual void getDoorEntry(const tRoomID room, const tDirectionConstant direction, DoorTable::Entry &doorEntry); + virtual tDirectionConstant getTurnEntry(const tRoomID room, const tDirectionConstant direction, const tTurnDirection turn); + virtual void findSpotEntry(const tRoomID room, const tDirectionConstant direction, tSpotFlags flags, SpotTable::Entry &spotEntry); + virtual void getZoomEntry(const tHotSpotID id, ZoomTable::Entry &zoomEntry); + virtual void getHotspotEntry(const tHotSpotID id, HotspotInfoTable::Entry &hotspotEntry); + virtual void getExtraEntry(const uint32 id, ExtraTable::Entry &extraEntry); -private: + tCanMoveForwardReason canMoveForward(ExitTable::Entry &entry); + tCanTurnReason canTurn(tTurnDirection turn, tDirectionConstant &nextDir); + tCanOpenDoorReason canOpenDoor(DoorTable::Entry &entry); + +protected: PegasusEngine *_vm; Common::String _resName; + tNeighborhoodID _neighborhoodID; DoorTable _doorTable; ExitTable _exitTable; ExtraTable _extraTable; - HotspotTable _hotspotTable; + HotspotInfoTable _hotspotInfoTable; SpotTable _spotTable; TurnTable _turnTable; ViewTable _viewTable; ZoomTable _zoomTable; + + tAlternateID _currentAlternate; }; } // End of namespace Pegasus diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp index d318497e7897..598c97cfec92 100644 --- a/engines/pegasus/pegasus.cpp +++ b/engines/pegasus/pegasus.cpp @@ -141,10 +141,8 @@ Common::Error PegasusEngine::run() { runMainMenu(); break; case kMainGameMode: - if (isDemo()) - changeLocation(kLocPrehistoric); - else - changeLocation(kLocCaldoria); + // NOTE: Prehistoric will be our testing location + changeLocation(kPrehistoricID); mainGameLoop(); break; case kQuitMode: @@ -233,19 +231,19 @@ void PegasusEngine::mainGameLoop() { _video->playMovieCentered("Images/Caldoria/Pullback.movie"); drawInterface(); - Common::String navMovie = Common::String::format("Images/%s/%s.movie", getTimeZoneFolder(_timeZone).c_str(), getTimeZoneDesc(_timeZone).c_str()); + Common::String navMovie = Common::String::format("Images/%s/%s.movie", getTimeZoneFolder(_neighborhood).c_str(), getTimeZoneDesc(_neighborhood).c_str()); _video->playMovie(navMovie, kViewScreenOffset, kViewScreenOffset); _gameMode = kQuitMode; } -void PegasusEngine::changeLocation(TimeZone timeZone) { - _timeZone = timeZone; +void PegasusEngine::changeLocation(tNeighborhoodID neighborhood) { + _neighborhood = neighborhood; // Just a test... - Neighborhood *neighborhood = new Neighborhood(this, getTimeZoneDesc(_timeZone)); - neighborhood->init(); - delete neighborhood; + Neighborhood *neighborhoodPtr = new Neighborhood(this, getTimeZoneDesc(_neighborhood), _neighborhood); + neighborhoodPtr->init(); + delete neighborhoodPtr; } void PegasusEngine::showLoadDialog() { @@ -267,16 +265,16 @@ void PegasusEngine::showLoadDialog() { slc.close(); } -Common::String PegasusEngine::getTimeZoneDesc(TimeZone timeZone) { - static const char *names[] = { "Prehistoric", "Mars", "WSC", "Tiny TSA", "Full TSA", "Norad Alpha", "Caldoria", "Norad Delta" }; - return names[timeZone]; +Common::String PegasusEngine::getTimeZoneDesc(tNeighborhoodID neighborhood) { + static const char *names[] = { "Caldoria", "Full TSA", "Full TSA", "Tiny TSA", "Prehistoric", "Mars", "WSC", "Norad Alpha", "Norad Delta" }; + return names[neighborhood]; } -Common::String PegasusEngine::getTimeZoneFolder(TimeZone timeZone) { - if (timeZone == kLocFullTSA || timeZone == kLocTinyTSA) +Common::String PegasusEngine::getTimeZoneFolder(tNeighborhoodID neighborhood) { + if (neighborhood == kFullTSAID || neighborhood == kTinyTSAID || neighborhood == kFinalTSAID) return "TSA"; - return getTimeZoneDesc(timeZone); + return getTimeZoneDesc(neighborhood); } GUI::Debugger *PegasusEngine::getDebugger() { diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h index d049f58f00e5..d6e312caf557 100644 --- a/engines/pegasus/pegasus.h +++ b/engines/pegasus/pegasus.h @@ -33,6 +33,7 @@ #include "pegasus/graphics.h" #include "pegasus/video.h" +#include "pegasus/neighborhood/neighborhood.h" namespace Video { class Video::QuickTimeDecoder; @@ -105,17 +106,6 @@ struct OverviewHotspot { uint32 time; }; -enum TimeZone { - kLocPrehistoric = 0, - kLocMars = 1, - kLocWSC = 2, - kLocTinyTSA = 3, - kLocFullTSA = 4, - kLocNoradAlpha = 5, - kLocCaldoria = 6, - kLocNoradDelta = 7 -}; - // Taken from JMP PP Resources enum Item { kAIBiochip = 128, @@ -198,16 +188,16 @@ class PegasusEngine : public ::Engine { // Main Game Functions void mainGameLoop(); void loadItemLocationData(); - void changeLocation(TimeZone timeZone); + void changeLocation(tNeighborhoodID neighborhood); // Misc Functions - static Common::String getTimeZoneFolder(TimeZone timeZone); - static Common::String getTimeZoneDesc(TimeZone timeZone); + static Common::String getTimeZoneFolder(tNeighborhoodID neighborhood); + static Common::String getTimeZoneDesc(tNeighborhoodID neighborhood); // Game Variables bool _adventureMode; GameMode _gameMode; - TimeZone _timeZone; + tNeighborhoodID _neighborhood; Common::Array _itemLocationData; // Console