diff options
-rw-r--r-- | engines/sherlock/people.cpp | 16 | ||||
-rw-r--r-- | engines/sherlock/scene.cpp | 66 | ||||
-rw-r--r-- | engines/sherlock/scene.h | 15 |
3 files changed, 80 insertions, 17 deletions
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index c108d333b9..349be671a4 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -124,11 +124,10 @@ void Person::goAllTheWay() { if (i == -1) i = scene._walkDirectory[_destZone][_srcZone]; - int count = scene._walkData[i]; - ++i; + const WalkArray &points = scene._walkPoints[i]; // See how many points there are between the src and dest zones - if (!count || count == -1) { + if (!points._pointsCount || points._pointsCount == -1) { // There are none, so just walk to the new zone setWalking(); } else { @@ -137,14 +136,11 @@ void Person::goAllTheWay() { _walkTo.clear(); if (scene._walkDirectory[_srcZone][_destZone] != -1) { - i += 3 * (count - 1); - for (int idx = 0; idx < count; ++idx, i -= 3) { - _walkTo.push(Common::Point(READ_LE_UINT16(&scene._walkData[i]), - scene._walkData[i + 2])); - } + for (int idx = (int)points.size() - 1; idx >= 0; --idx) + _walkTo.push(points[idx]); } else { - for (int idx = 0; idx < count; ++idx, i += 3) { - _walkTo.push(Common::Point(READ_LE_UINT16(&scene._walkData[i]), scene._walkData[i + 2])); + for (int idx = 0; idx < (int)points.size(); ++idx) { + _walkTo.push(points[idx]); } } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index c4b87cf444..47e5c89bdb 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -193,6 +193,18 @@ void ScaleZone::load(Common::SeekableReadStream &s) { /*----------------------------------------------------------------*/ +void WalkArray::load(Common::SeekableReadStream &s, bool isRoseTattoo) { + _pointsCount = (int8)s.readByte(); + + for (int idx = 0; idx < _pointsCount; ++idx) { + int x = s.readSint16LE(); + int y = isRoseTattoo ? s.readSint16LE() : s.readByte(); + push_back(Common::Point(x, y)); + } +} + +/*----------------------------------------------------------------*/ + Scene *Scene::init(SherlockEngine *vm) { if (vm->getGameID() == GType_SerratedScalpel) return new Scalpel::ScalpelScene(vm); @@ -285,7 +297,7 @@ void Scene::freeScene() { _sequenceBuffer.clear(); _descText.clear(); - _walkData.clear(); + _walkPoints.clear(); _cAnim.clear(); _bgShapes.clear(); _zones.clear(); @@ -538,9 +550,12 @@ bool Scene::loadScene(const Common::String &filename) { if (rrmStream->readByte() != (IS_SERRATED_SCALPEL ? 254 : 251)) error("Invalid scene path data"); - // Load the walk directory + // Load the walk directory and walk data assert(_zones.size() < MAX_ZONES); + + for (uint idx1 = 0; idx1 < _zones.size(); ++idx1) { + Common::fill(&_walkDirectory[idx1][0], &_walkDirectory[idx1][MAX_ZONES], 0); for (uint idx2 = 0; idx2 < _zones.size(); ++idx2) _walkDirectory[idx1][idx2] = rrmStream->readSint16LE(); } @@ -550,12 +565,31 @@ bool Scene::loadScene(const Common::String &filename) { Common::SeekableReadStream *walkStream = !_lzwMode ? rrmStream : res.decompress(*rrmStream, size); - _walkData.resize(size); - walkStream->read(&_walkData[0], size); + int startPos = walkStream->pos(); + while ((walkStream->pos() - startPos) < size) { + _walkPoints.push_back(WalkArray()); + _walkPoints[_walkPoints.size() - 1]._fileOffset = walkStream->pos() - startPos; + _walkPoints[_walkPoints.size() - 1].load(*walkStream, IS_ROSE_TATTOO); + } if (_lzwMode) delete walkStream; + // Translate the file offsets of the walk directory to indexes in the loaded walk data + for (uint idx1 = 0; idx1 < _zones.size(); ++idx1) { + for (uint idx2 = 0; idx2 < _zones.size(); ++idx2) { + int fileOffset = _walkDirectory[idx1][idx2]; + if (fileOffset == -1) + continue; + + uint dataIndex = 0; + while (dataIndex < _walkPoints.size() && _walkPoints[dataIndex]._fileOffset != fileOffset) + ++dataIndex; + assert(dataIndex < _walkPoints.size()); + _walkDirectory[idx1][idx2] = dataIndex; + } + } + if (IS_ROSE_TATTOO) { // Read in the entrance _entrance.load(*rrmStream); @@ -781,8 +815,28 @@ bool Scene::loadScene(const Common::String &filename) { // === WALK DATA === Read in the walk data roomStream->seek(header3DO_walkData_offset); - _walkData.resize(header3DO_walkData_size); - roomStream->read(&_walkData[0], header3DO_walkData_size); + + int startPos = roomStream->pos(); + while ((roomStream->pos() - startPos) < header3DO_walkData_size) { + _walkPoints.push_back(WalkArray()); + _walkPoints[_walkPoints.size() - 1]._fileOffset = roomStream->pos() - startPos; + _walkPoints[_walkPoints.size() - 1].load(*roomStream, false); + } + + // Translate the file offsets of the walk directory to indexes in the loaded walk data + for (uint idx1 = 0; idx1 < _zones.size(); ++idx1) { + for (uint idx2 = 0; idx2 < _zones.size(); ++idx2) { + int fileOffset = _walkDirectory[idx1][idx2]; + if (fileOffset == -1) + continue; + + uint dataIndex = 0; + while (dataIndex < _walkPoints.size() && _walkPoints[dataIndex]._fileOffset != fileOffset) + ++dataIndex; + assert(dataIndex < _walkPoints.size()); + _walkDirectory[idx1][idx2] = dataIndex; + } + } // === EXITS === Read in the exits roomStream->seek(header3DO_exits_offset); diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 2cf8b803b4..799433fd53 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -131,6 +131,19 @@ public: void load(Common::SeekableReadStream &s); }; +class WalkArray : public Common::Array < Common::Point > { +public: + int _pointsCount; + int _fileOffset; + + WalkArray() : _pointsCount(0), _fileOffset(-1) {} + + /** + * Load data for the walk array entry + */ + void load(Common::SeekableReadStream &s, bool isRoseTattoo); +}; + class Scene { private: bool _loadingSavedGame; @@ -213,7 +226,7 @@ public: Common::Array<byte> _sequenceBuffer; Common::Array<SceneImage> _images; int _walkDirectory[MAX_ZONES][MAX_ZONES]; - Common::Array<byte> _walkData; + Common::Array<WalkArray> _walkPoints; Common::Array<Exit> _exits; int _exitZone; SceneEntry _entrance; |