aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2015-06-08 08:31:51 -0400
committerPaul Gilbert2015-06-08 08:31:51 -0400
commitf5a1b626b710c368e79ab27c13cf2be4ccdcb30f (patch)
treed9c49fe86f3c9d32430f9ca3da512cf9613ce63e /engines
parentae64cca8f01f4e56873ac6afa58610366ea8238a (diff)
downloadscummvm-rg350-f5a1b626b710c368e79ab27c13cf2be4ccdcb30f.tar.gz
scummvm-rg350-f5a1b626b710c368e79ab27c13cf2be4ccdcb30f.tar.bz2
scummvm-rg350-f5a1b626b710c368e79ab27c13cf2be4ccdcb30f.zip
SHERLOCK: Move Scalpel map code to ScalpelMap
Diffstat (limited to 'engines')
-rw-r--r--engines/sherlock/map.cpp529
-rw-r--r--engines/sherlock/map.h128
-rw-r--r--engines/sherlock/objects.cpp11
-rw-r--r--engines/sherlock/people.cpp50
-rw-r--r--engines/sherlock/people.h12
-rw-r--r--engines/sherlock/scalpel/scalpel.cpp8
-rw-r--r--engines/sherlock/scalpel/scalpel_map.cpp528
-rw-r--r--engines/sherlock/scalpel/scalpel_map.h130
-rw-r--r--engines/sherlock/scalpel/scalpel_people.cpp53
-rw-r--r--engines/sherlock/scalpel/scalpel_people.h6
-rw-r--r--engines/sherlock/scalpel/scalpel_scene.cpp230
-rw-r--r--engines/sherlock/scalpel/scalpel_scene.h21
-rw-r--r--engines/sherlock/scalpel/scalpel_talk.cpp6
-rw-r--r--engines/sherlock/scene.cpp224
-rw-r--r--engines/sherlock/scene.h22
-rw-r--r--engines/sherlock/tattoo/tattoo_map.cpp4
-rw-r--r--engines/sherlock/tattoo/tattoo_map.h5
-rw-r--r--engines/sherlock/tattoo/tattoo_people.cpp4
-rw-r--r--engines/sherlock/tattoo/tattoo_people.h6
-rw-r--r--engines/sherlock/tattoo/tattoo_scene.cpp4
-rw-r--r--engines/sherlock/tattoo/tattoo_scene.h9
21 files changed, 1038 insertions, 952 deletions
diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp
index 3f9c9f5e75..fbccaf244f 100644
--- a/engines/sherlock/map.cpp
+++ b/engines/sherlock/map.cpp
@@ -28,31 +28,6 @@
namespace Sherlock {
-MapPaths::MapPaths() {
- _numLocations = 0;
-}
-
-void MapPaths::load(int numLocations, Common::SeekableReadStream &s) {
- _numLocations = numLocations;
- _paths.resize(_numLocations * _numLocations);
-
- for (int idx = 0; idx < (numLocations * numLocations); ++idx) {
- Common::Array<byte> &path = _paths[idx];
- int v;
-
- do {
- v = s.readByte();
- path.push_back(v);
- } while (v && v < 254);
- }
-}
-
-const byte *MapPaths::getPath(int srcLocation, int destLocation) {
- return &_paths[srcLocation * _numLocations + destLocation][0];
-}
-
-/*----------------------------------------------------------------*/
-
Map *Map::init(SherlockEngine *vm) {
if (vm->getGameID() == GType_SerratedScalpel)
return new Scalpel::ScalpelMap(vm);
@@ -60,506 +35,9 @@ Map *Map::init(SherlockEngine *vm) {
return new Tattoo::TattooMap(vm);
}
-Map::Map(SherlockEngine *vm): _vm(vm), _topLine(g_system->getWidth(), 12, vm->getPlatform()) {
- _active = false;
- _mapCursors = nullptr;
- _shapes = nullptr;
- _iconShapes = nullptr;
- _point = 0;
- _placesShown = false;
- _cursorIndex = -1;
- _drawMap = false;
- _overPos = Point32(130 * FIXED_INT_MULTIPLIER, 126 * FIXED_INT_MULTIPLIER);
- _charPoint = 0;
- _oldCharPoint = 0;
- _frameChangeFlag = false;
-
- // Initialise the initial walk sequence set
- _walkSequences.resize(MAX_HOLMES_SEQUENCE);
- for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) {
- _walkSequences[idx]._sequences.resize(MAX_FRAME);
- Common::fill(&_walkSequences[idx]._sequences[0], &_walkSequences[idx]._sequences[0] + MAX_FRAME, 0);
- }
-
- if (!_vm->isDemo())
- loadData();
-}
-
-void Map::loadPoints(int count, const int *xList, const int *yList, const int *transList) {
- for (int idx = 0; idx < count; ++idx, ++xList, ++yList, ++transList) {
- _points.push_back(MapEntry(*xList, *yList, *transList));
- }
-}
-
-void Map::loadSequences(int count, const byte *seq) {
- for (int idx = 0; idx < count; ++idx, seq += MAX_FRAME)
- Common::copy(seq, seq + MAX_FRAME, &_walkSequences[idx]._sequences[0]);
-}
-
-void Map::loadData() {
- // TODO: Remove this
- if (_vm->getGameID() == GType_RoseTattoo)
- return;
-
- // Load the list of location names
- Common::SeekableReadStream *txtStream = _vm->_res->load(
- _vm->getGameID() == GType_SerratedScalpel ? "chess.txt" : "map.txt");
-
- int streamSize = txtStream->size();
- while (txtStream->pos() < streamSize) {
- Common::String line;
- char c;
- while ((c = txtStream->readByte()) != '\0')
- line += c;
-
- _locationNames.push_back(line);
- }
-
- delete txtStream;
-
- // Load the path data
- Common::SeekableReadStream *pathStream = _vm->_res->load("chess.pth");
-
- // Get routes between different locations on the map
- _paths.load(31, *pathStream);
-
- // Load in the co-ordinates that the paths refer to
- _pathPoints.resize(208);
- for (uint idx = 0; idx < _pathPoints.size(); ++idx) {
- _pathPoints[idx].x = pathStream->readSint16LE();
- _pathPoints[idx].y = pathStream->readSint16LE();
- }
-
- delete pathStream;
-}
-
-int Map::show() {
- Events &events = *_vm->_events;
- People &people = *_vm->_people;
- Screen &screen = *_vm->_screen;
- bool changed = false, exitFlag = false;
- _active = true;
-
- // Set font and custom cursor for the map
- int oldFont = screen.fontNumber();
- screen.setFont(0);
-
- // Initial screen clear
- screen._backBuffer1.clear();
- screen.clear();
-
- // Load the entire map
- ImageFile bigMap("bigmap.vgs");
- screen.setPalette(bigMap._palette);
-
- // Load need sprites
- setupSprites();
-
- screen._backBuffer1.blitFrom(bigMap[0], Common::Point(-_bigPos.x, -_bigPos.y));
- screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
- screen._backBuffer1.blitFrom(bigMap[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
- screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
-
- _drawMap = true;
- _charPoint = -1;
- _point = -1;
- people[AL]._position = _lDrawnPos = _overPos;
-
- // Show place icons
- showPlaces();
- saveTopLine();
- _placesShown = true;
-
- // Keep looping until either a location is picked, or the game is ended
- while (!_vm->shouldQuit() && !exitFlag) {
- events.pollEventsAndWait();
- events.setButtonState();
-
- // Keyboard handling
- if (events.kbHit()) {
- Common::KeyState keyState = events.getKey();
-
- if (keyState.keycode == Common::KEYCODE_RETURN || keyState.keycode == Common::KEYCODE_SPACE) {
- // Both space and enter simulate a mouse release
- events._pressed = false;
- events._released = true;
- events._oldButtons = 0;
- }
- }
-
- // Ignore scrolling attempts until the screen is drawn
- if (!_drawMap) {
- Common::Point pt = events.mousePos();
-
- // Check for vertical map scrolling
- if ((pt.y > (SHERLOCK_SCREEN_HEIGHT - 10) && _bigPos.y < 200) || (pt.y < 10 && _bigPos.y > 0)) {
- if (pt.y > (SHERLOCK_SCREEN_HEIGHT - 10))
- _bigPos.y += 10;
- else
- _bigPos.y -= 10;
-
- changed = true;
- }
-
- // Check for horizontal map scrolling
- if ((pt.x > (SHERLOCK_SCREEN_WIDTH - 10) && _bigPos.x < 315) || (pt.x < 10 && _bigPos.x > 0)) {
- if (pt.x > (SHERLOCK_SCREEN_WIDTH - 10))
- _bigPos.x += 15;
- else
- _bigPos.x -= 15;
-
- changed = true;
- }
- }
-
- if (changed) {
- // Map has scrolled, so redraw new map view
- changed = false;
-
- screen._backBuffer1.blitFrom(bigMap[0], Common::Point(-_bigPos.x, -_bigPos.y));
- screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
- screen._backBuffer1.blitFrom(bigMap[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
- screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
-
- showPlaces();
- _placesShown = false;
-
- saveTopLine();
- _savedPos.x = -1;
- updateMap(true);
- } else if (!_drawMap) {
- if (!_placesShown) {
- showPlaces();
- _placesShown = true;
- }
-
- if (_cursorIndex == 0) {
- Common::Point pt = events.mousePos();
- highlightIcon(Common::Point(pt.x - 4 + _bigPos.x, pt.y + _bigPos.y));
- }
- updateMap(false);
- }
-
- if ((events._released || events._rightReleased) && _point != -1) {
- if (people[AL]._walkCount == 0) {
- people._walkDest = _points[_point] + Common::Point(4, 9);
- _charPoint = _point;
-
- // Start walking to selected location
- walkTheStreets();
-
- // Show wait cursor
- _cursorIndex = 1;
- events.setCursor((*_mapCursors)[_cursorIndex]._frame);
- }
- }
-
- // Check if a scene has beeen selected and we've finished "moving" to it
- if (people[AL]._walkCount == 0) {
- if (_charPoint >= 1 && _charPoint < (int)_points.size())
- exitFlag = true;
- }
-
- if (_drawMap) {
- _drawMap = false;
-
- if (screen._fadeStyle)
- screen.randomTransition();
- else
- screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
- }
-
- // Wait for a frame
- events.wait(1);
- }
-
- freeSprites();
- _overPos = people[AL]._position;
-
- // Reset font
- screen.setFont(oldFont);
-
- _active = false;
- return _charPoint;
-}
-
-void Map::setupSprites() {
- Events &events = *_vm->_events;
- People &people = *_vm->_people;
- Scene &scene = *_vm->_scene;
- _savedPos.x = -1;
-
- _mapCursors = new ImageFile("omouse.vgs");
- _cursorIndex = 0;
- events.setCursor((*_mapCursors)[_cursorIndex]._frame);
-
- _shapes = new ImageFile("mapicon.vgs");
- _iconShapes = new ImageFile("overicon.vgs");
- _iconSave.create((*_shapes)[4]._width, (*_shapes)[4]._height, _vm->getPlatform());
- Person &p = people[AL];
- p._description = " ";
- p._type = CHARACTER;
- p._position = Common::Point(12400, 5000);
- p._sequenceNumber = 0;
- p._images = _shapes;
- p._imageFrame = nullptr;
- p._frameNumber = 0;
- p._delta = Common::Point(0, 0);
- p._oldSize = Common::Point(0, 0);
- p._oldSize = Common::Point(0, 0);
- p._misc = 0;
- p._walkCount = 0;
- p._allow = 0;
- p._noShapeSize = Common::Point(0, 0);
- p._goto = Common::Point(28000, 15000);
- p._status = 0;
- p._walkSequences = _walkSequences;
- p.setImageFrame();
- scene._bgShapes.clear();
-}
-
-void Map::freeSprites() {
- delete _mapCursors;
- delete _shapes;
- delete _iconShapes;
- _iconSave.free();
-}
-
-void Map::showPlaces() {
- Screen &screen = *_vm->_screen;
-
- for (uint idx = 0; idx < _points.size(); ++idx) {
- const MapEntry &pt = _points[idx];
-
- if (pt.x != 0 && pt.y != 0) {
- if (pt.x >= _bigPos.x && (pt.x - _bigPos.x) < SHERLOCK_SCREEN_WIDTH
- && pt.y >= _bigPos.y && (pt.y - _bigPos.y) < SHERLOCK_SCREEN_HEIGHT) {
- if (_vm->readFlags(idx)) {
- screen._backBuffer1.transBlitFrom((*_iconShapes)[pt._translate],
- Common::Point(pt.x - _bigPos.x - 6, pt.y - _bigPos.y - 12));
- }
- }
- }
- }
-}
-
-void Map::saveTopLine() {
- _topLine.blitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12));
-}
-
-void Map::eraseTopLine() {
- Screen &screen = *_vm->_screen;
- screen._backBuffer1.blitFrom(_topLine, Common::Point(0, 0));
- screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, _topLine.h());
-}
-
-void Map::showPlaceName(int idx, bool highlighted) {
- People &people = *_vm->_people;
- Screen &screen = *_vm->_screen;
-
- Common::String name = _locationNames[idx];
- int width = screen.stringWidth(name);
-
- if (!_cursorIndex) {
- saveIcon(people[AL]._imageFrame, _lDrawnPos);
-
- bool flipped = people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT
- || people[AL]._sequenceNumber == MAP_UPLEFT;
- screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, _lDrawnPos, flipped);
- }
-
- if (highlighted) {
- int xp = (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(name)) / 2;
- screen.gPrint(Common::Point(xp + 2, 2), 0, "%s", name.c_str());
- screen.gPrint(Common::Point(xp + 1, 1), 0, "%s", name.c_str());
- screen.gPrint(Common::Point(xp, 0), 12, "%s", name.c_str());
-
- screen.slamArea(xp, 0, width + 2, 15);
- }
-}
-
-void Map::updateMap(bool flushScreen) {
- Events &events = *_vm->_events;
- People &people = *_vm->_people;
- Screen &screen = *_vm->_screen;
- Common::Point osPos = _savedPos;
- Common::Point osSize = _savedSize;
- Common::Point hPos;
-
- if (_cursorIndex >= 1) {
- if (++_cursorIndex > (1 + 8))
- _cursorIndex = 1;
-
- events.setCursor((*_mapCursors)[(_cursorIndex + 1) / 2]._frame);
- }
-
- if (!_drawMap && !flushScreen)
- restoreIcon();
- else
- _savedPos.x = -1;
-
- people[AL].adjustSprite();
-
- _lDrawnPos.x = hPos.x = people[AL]._position.x / FIXED_INT_MULTIPLIER - _bigPos.x;
- _lDrawnPos.y = hPos.y = people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL].frameHeight() - _bigPos.y;
-
- // Draw the person icon
- saveIcon(people[AL]._imageFrame, hPos);
- if (people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT
- || people[AL]._sequenceNumber == MAP_UPLEFT)
- screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, hPos, true);
- else
- screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, hPos, false);
-
- if (flushScreen) {
- screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
- } else if (!_drawMap) {
- if (hPos.x > 0 && hPos.y >= 0 && hPos.x < SHERLOCK_SCREEN_WIDTH && hPos.y < SHERLOCK_SCREEN_HEIGHT)
- screen.flushImage(people[AL]._imageFrame, Common::Point(people[AL]._position.x / FIXED_INT_MULTIPLIER - _bigPos.x,
- people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL].frameHeight() - _bigPos.y),
- &people[AL]._oldPosition.x, &people[AL]._oldPosition.y, &people[AL]._oldSize.x, &people[AL]._oldSize.y);
-
- if (osPos.x != -1)
- screen.slamArea(osPos.x, osPos.y, osSize.x, osSize.y);
- }
-}
-
-void Map::walkTheStreets() {
- People &people = *_vm->_people;
- Common::Array<Common::Point> tempPath;
-
- // Get indexes into the path lists for the start and destination scenes
- int start = _points[_oldCharPoint]._translate;
- int dest = _points[_charPoint]._translate;
-
- // Get pointer to start of path
- const byte *path = _paths.getPath(start, dest);
-
- // Add in destination position
- people._walkTo.clear();
- Common::Point destPos = people._walkDest;
-
- // Check for any intermediate points between the two locations
- if (path[0] || _charPoint > 50 || _oldCharPoint > 50) {
- people[AL]._sequenceNumber = -1;
-
- if (_charPoint == 51 || _oldCharPoint == 51) {
- people.setWalking();
- } else {
- bool reversePath = false;
-
- // Check for moving the path backwards or forwards
- if (path[0] == 255) {
- reversePath = true;
- SWAP(start, dest);
- path = _paths.getPath(start, dest);
- }
-
- do {
- int idx = *path++;
- tempPath.push_back(_pathPoints[idx - 1] + Common::Point(4, 4));
- } while (*path != 254);
-
- // Load up the path to use
- people._walkTo.clear();
-
- if (reversePath) {
- for (int idx = (int)tempPath.size() - 1; idx >= 0; --idx)
- people._walkTo.push(tempPath[idx]);
- } else {
- for (int idx = 0; idx < (int)tempPath.size(); ++idx)
- people._walkTo.push(tempPath[idx]);
- }
-
- people._walkDest = people._walkTo.pop() + Common::Point(12, 6);
- people.setWalking();
- }
- } else {
- people[AL]._walkCount = 0;
- }
-
- // Store the final destination icon position
- people._walkTo.push(destPos);
-}
-
-void Map::saveIcon(ImageFrame *src, const Common::Point &pt) {
- Screen &screen = *_vm->_screen;
- Common::Point size(src->_width, src->_height);
- Common::Point pos = pt;
-
- if (pos.x < 0) {
- size.x += pos.x;
- pos.x = 0;
- }
-
- if (pos.y < 0) {
- size.y += pos.y;
- pos.y = 0;
- }
-
- if ((pos.x + size.x) > SHERLOCK_SCREEN_WIDTH)
- size.x -= (pos.x + size.x) - SHERLOCK_SCREEN_WIDTH;
-
- if ((pos.y + size.y) > SHERLOCK_SCREEN_HEIGHT)
- size.y -= (pos.y + size.y) - SHERLOCK_SCREEN_HEIGHT;
-
- if (size.x < 1 || size.y < 1 || pos.x >= SHERLOCK_SCREEN_WIDTH || pos.y >= SHERLOCK_SCREEN_HEIGHT || _drawMap) {
- // Flag as the area not needing to be saved
- _savedPos.x = -1;
- return;
- }
-
- assert(size.x <= _iconSave.w() && size.y <= _iconSave.h());
- _iconSave.blitFrom(screen._backBuffer1, Common::Point(0, 0),
- Common::Rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y));
- _savedPos = pos;
- _savedSize = size;
-}
-
-void Map::restoreIcon() {
- Screen &screen = *_vm->_screen;
-
- if (_savedPos.x >= 0 && _savedPos.y >= 0 && _savedPos.x <= SHERLOCK_SCREEN_WIDTH
- && _savedPos.y < SHERLOCK_SCREEN_HEIGHT)
- screen._backBuffer1.blitFrom(_iconSave, _savedPos, Common::Rect(0, 0, _savedSize.x, _savedSize.y));
-}
-
-void Map::highlightIcon(const Common::Point &pt) {
- int oldPoint = _point;
-
- // Iterate through the icon list
- bool done = false;
- for (int idx = 0; idx < (int)_points.size(); ++idx) {
- const MapEntry &entry = _points[idx];
-
- // Check whether the mouse is over a given icon
- if (entry.x != 0 && entry.y != 0) {
- if (Common::Rect(entry.x - 8, entry.y - 8, entry.x + 9, entry.y + 9).contains(pt)) {
- done = true;
-
- if (_point != idx && _vm->readFlags(idx)) {
- // Changed to a new valid (visible) location
- eraseTopLine();
- showPlaceName(idx, true);
- _point = idx;
- }
- }
- }
- }
-
- if (!done) {
- // No icon was highlighted
- if (_point != -1) {
- // No longer highlighting previously highlighted icon, so erase it
- showPlaceName(_point, false);
- eraseTopLine();
- }
-
- _point = -1;
- } else if (oldPoint != -1 && oldPoint != _point) {
- showPlaceName(oldPoint, false);
- eraseTopLine();
- }
+Map::Map(SherlockEngine *vm) : _vm(vm) {
+ _charPoint = _oldCharPoint = 0;
+ _active = _frameChangeFlag = false;
}
void Map::synchronize(Serializer &s) {
@@ -570,4 +48,5 @@ void Map::synchronize(Serializer &s) {
s.syncAsSint16LE(_oldCharPoint);
}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h
index d47edb299a..2569e18187 100644
--- a/engines/sherlock/map.h
+++ b/engines/sherlock/map.h
@@ -23,12 +23,6 @@
#ifndef SHERLOCK_MAP_H
#define SHERLOCK_MAP_H
-#include "common/scummsys.h"
-#include "common/array.h"
-#include "common/rect.h"
-#include "common/str.h"
-#include "common/str-array.h"
-#include "sherlock/surface.h"
#include "sherlock/objects.h"
#include "sherlock/saveload.h"
@@ -36,140 +30,24 @@ namespace Sherlock {
class SherlockEngine;
-struct MapEntry : Common::Point {
- int _translate;
-
- MapEntry() : Common::Point(), _translate(-1) {}
-
- MapEntry(int posX, int posY, int translate) : Common::Point(posX, posY), _translate(translate) {}
-};
-
-class MapPaths {
-private:
- int _numLocations;
- Common::Array< Common::Array<byte> > _paths;
-
-public:
- MapPaths();
-
- /**
- * Load the data for the paths between locations on the map
- */
- void load(int numLocations, Common::SeekableReadStream &s);
-
- /**
- * Get the path between two locations on the map
- */
- const byte *getPath(int srcLocation, int destLocation);
-};
-
class Map {
protected:
SherlockEngine *_vm;
- Common::Array<MapEntry> _points; // Map locations for each scene
- Common::StringArray _locationNames;
- MapPaths _paths;
- Common::Array<Common::Point> _pathPoints;
- Common::Point _savedPos;
- Common::Point _savedSize;
- Surface _topLine;
- ImageFile *_mapCursors;
- ImageFile *_shapes;
- ImageFile *_iconShapes;
- WalkSequences _walkSequences;
- Point32 _lDrawnPos;
- int _point;
- bool _placesShown;
- int _cursorIndex;
- bool _drawMap;
- Surface _iconSave;
-protected:
- Map(SherlockEngine *vm);
-
- /**
- * Load data needed for the map
- */
- void loadData();
-
- /**
- * Load and initialize all the sprites that are needed for the map display
- */
- void setupSprites();
-
- /**
- * Free the sprites and data used by the map
- */
- void freeSprites();
-
- /**
- * Draws an icon for every place that's currently known
- */
- void showPlaces();
-
- /**
- * Makes a copy of the top rows of the screen that are used to display location names
- */
- void saveTopLine();
- /**
- * Erases anything shown in the top line by restoring the previously saved original map background
- */
- void eraseTopLine();
-
- /**
- * Prints the name of the specified icon
- */
- void showPlaceName(int idx, bool highlighted);
-
- /**
- * Update all on-screen sprites to account for any scrolling of the map
- */
- void updateMap(bool flushScreen);
-
- /**
- * Handle moving icon for player from their previous location on the map to a destination location
- */
- void walkTheStreets();
-
- /**
- * Save the area under the player's icon
- */
- void saveIcon(ImageFrame *src, const Common::Point &pt);
-
- /**
- * Restore the area under the player's icon
- */
- void restoreIcon();
-
- /**
- * Handles highlighting map icons, showing their names
- */
- void highlightIcon(const Common::Point &pt);
+ Map(SherlockEngine *vm);
public:
- bool _active;
Point32 _overPos;
Point32 _bigPos;
int _charPoint, _oldCharPoint;
+ bool _active;
bool _frameChangeFlag;
public:
static Map *init(SherlockEngine *vm);
- const MapEntry &operator[](int idx) { return _points[idx]; }
-
- /**
- * Loads the list of points for locations on the map for each scene
- */
- void loadPoints(int count, const int *xList, const int *yList, const int *transList);
-
- /**
- * Load the sequence data for player icon animations
- */
- void loadSequences(int count, const byte *seq);
-
/**
* Show the map
*/
- int show();
+ virtual int show() = 0;
/**
* Synchronize the data for a savegame
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 1e57d00253..d27cbeda2e 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -25,6 +25,7 @@
#include "sherlock/objects.h"
#include "sherlock/people.h"
#include "sherlock/scene.h"
+#include "sherlock/scalpel/scalpel_map.h"
#include "sherlock/scalpel/scalpel_people.h"
namespace Sherlock {
@@ -1212,7 +1213,6 @@ void Object::setObjTalkSequence(int seq) {
}
int Object::checkNameForCodes(const Common::String &name, const char *const messages[]) {
- Map &map = *_vm->_map;
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
Screen &screen = *_vm->_screen;
@@ -1257,9 +1257,12 @@ int Object::checkNameForCodes(const Common::String &name, const char *const mess
if (ch >= '0' && ch <= '9') {
scene._goToScene = atoi(name.c_str() + 1);
- if (IS_SERRATED_SCALPEL && scene._goToScene < 97 && map[scene._goToScene].x) {
- map._overPos.x = (map[scene._goToScene].x - 6) * FIXED_INT_MULTIPLIER;
- map._overPos.y = (map[scene._goToScene].y + 9) * FIXED_INT_MULTIPLIER;
+ if (IS_SERRATED_SCALPEL && scene._goToScene < 97) {
+ Scalpel::ScalpelMap &map = *(Scalpel::ScalpelMap *)_vm->_map;
+ if (map[scene._goToScene].x) {
+ map._overPos.x = (map[scene._goToScene].x - 6) * FIXED_INT_MULTIPLIER;
+ map._overPos.y = (map[scene._goToScene].y + 9) * FIXED_INT_MULTIPLIER;
+ }
}
const char *p;
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index 9416ae9119..143e53242e 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -425,56 +425,6 @@ assert(_player._position.y >= 10000);/***DEBUG****/
_player._frameNumber = oldFrame;
}
-void People::gotoStand(Sprite &sprite) {
- Map &map = *_vm->_map;
- _walkTo.clear();
- sprite._walkCount = 0;
-
- switch (sprite._sequenceNumber) {
- case Scalpel::WALK_UP:
- sprite._sequenceNumber = Scalpel::STOP_UP;
- break;
- case Scalpel::WALK_DOWN:
- sprite._sequenceNumber = Scalpel::STOP_DOWN;
- break;
- case Scalpel::TALK_LEFT:
- case Scalpel::WALK_LEFT:
- sprite._sequenceNumber = Scalpel::STOP_LEFT;
- break;
- case Scalpel::TALK_RIGHT:
- case Scalpel::WALK_RIGHT:
- sprite._sequenceNumber = Scalpel::STOP_RIGHT;
- break;
- case Scalpel::WALK_UPRIGHT:
- sprite._sequenceNumber = Scalpel::STOP_UPRIGHT;
- break;
- case Scalpel::WALK_UPLEFT:
- sprite._sequenceNumber = Scalpel::STOP_UPLEFT;
- break;
- case Scalpel::WALK_DOWNRIGHT:
- sprite._sequenceNumber = Scalpel::STOP_DOWNRIGHT;
- break;
- case Scalpel::WALK_DOWNLEFT:
- sprite._sequenceNumber = Scalpel::STOP_DOWNLEFT;
- break;
- default:
- break;
- }
-
- // Only restart frame at 0 if the sequence number has changed
- if (_oldWalkSequence != -1 || sprite._sequenceNumber == Scalpel::STOP_UP)
- sprite._frameNumber = 0;
-
- if (map._active) {
- sprite._sequenceNumber = 0;
- _player._position.x = (map[map._charPoint].x - 6) * FIXED_INT_MULTIPLIER;
- _player._position.y = (map[map._charPoint].y + 10) * FIXED_INT_MULTIPLIER;
- }
-
- _oldWalkSequence = -1;
- _allowWalkAbort = true;
-}
-
void People::walkToCoords(const Point32 &destPos, int destDir) {
Events &events = *_vm->_events;
Scene &scene = *_vm->_scene;
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index c4abf397b2..c15248cc02 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -159,12 +159,6 @@ public:
void setWalking();
/**
- * Bring a moving character to a standing position. If the Scalpel chessboard
- * is being displayed, then the chraracter will always face down.
- */
- void gotoStand(Sprite &sprite);
-
- /**
* Walk to the co-ordinates passed, and then face the given direction
*/
void walkToCoords(const Point32 &destPos, int destDir);
@@ -195,6 +189,12 @@ public:
* Change the sequence of the scene background object associated with the current speaker.
*/
virtual void setTalkSequence(int speaker, int sequenceNum = 1) = 0;
+
+ /**
+ * Bring a moving character to a standing position. If the Scalpel chessboard
+ * is being displayed, then the chraracter will always face down.
+ */
+ virtual void gotoStand(Sprite &sprite) = 0;
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index f6a6bc9cc2..abca2997f6 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -22,6 +22,7 @@
#include "engines/util.h"
#include "sherlock/scalpel/scalpel.h"
+#include "sherlock/scalpel/scalpel_map.h"
#include "sherlock/scalpel/scalpel_people.h"
#include "sherlock/scalpel/scalpel_scene.h"
#include "sherlock/scalpel/tsage/logo.h"
@@ -205,9 +206,10 @@ void ScalpelEngine::initialize() {
if (!isDemo()) {
// Load the map co-ordinates for each scene and sequence data
- _map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]);
- _map->loadSequences(3, &MAP_SEQUENCES[0][0]);
- _map->_oldCharPoint = BAKER_ST_EXTERIOR;
+ ScalpelMap &map = *(ScalpelMap *)_map;
+ map.loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]);
+ map.loadSequences(3, &MAP_SEQUENCES[0][0]);
+ map._oldCharPoint = BAKER_ST_EXTERIOR;
}
// Load the inventory
diff --git a/engines/sherlock/scalpel/scalpel_map.cpp b/engines/sherlock/scalpel/scalpel_map.cpp
index 5c45302c51..613587d2e5 100644
--- a/engines/sherlock/scalpel/scalpel_map.cpp
+++ b/engines/sherlock/scalpel/scalpel_map.cpp
@@ -20,12 +20,540 @@
*
*/
+#include "common/system.h"
#include "sherlock/scalpel/scalpel_map.h"
+#include "sherlock/events.h"
+#include "sherlock/people.h"
+#include "sherlock/screen.h"
+#include "sherlock/sherlock.h"
namespace Sherlock {
namespace Scalpel {
+MapPaths::MapPaths() {
+ _numLocations = 0;
+}
+
+void MapPaths::load(int numLocations, Common::SeekableReadStream &s) {
+ _numLocations = numLocations;
+ _paths.resize(_numLocations * _numLocations);
+
+ for (int idx = 0; idx < (numLocations * numLocations); ++idx) {
+ Common::Array<byte> &path = _paths[idx];
+ int v;
+
+ do {
+ v = s.readByte();
+ path.push_back(v);
+ } while (v && v < 254);
+ }
+}
+
+const byte *MapPaths::getPath(int srcLocation, int destLocation) {
+ return &_paths[srcLocation * _numLocations + destLocation][0];
+}
+
+/*----------------------------------------------------------------*/
+
+ScalpelMap::ScalpelMap(SherlockEngine *vm): Map(vm), _topLine(g_system->getWidth(), 12, vm->getPlatform()) {
+ _mapCursors = nullptr;
+ _shapes = nullptr;
+ _iconShapes = nullptr;
+ _point = 0;
+ _placesShown = false;
+ _cursorIndex = -1;
+ _drawMap = false;
+ _overPos = Point32(130 * FIXED_INT_MULTIPLIER, 126 * FIXED_INT_MULTIPLIER);
+ _frameChangeFlag = false;
+
+ // Initialise the initial walk sequence set
+ _walkSequences.resize(MAX_HOLMES_SEQUENCE);
+ for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) {
+ _walkSequences[idx]._sequences.resize(MAX_FRAME);
+ Common::fill(&_walkSequences[idx]._sequences[0], &_walkSequences[idx]._sequences[0] + MAX_FRAME, 0);
+ }
+
+ if (!_vm->isDemo())
+ loadData();
+}
+
+void ScalpelMap::loadPoints(int count, const int *xList, const int *yList, const int *transList) {
+ for (int idx = 0; idx < count; ++idx, ++xList, ++yList, ++transList) {
+ _points.push_back(MapEntry(*xList, *yList, *transList));
+ }
+}
+
+void ScalpelMap::loadSequences(int count, const byte *seq) {
+ for (int idx = 0; idx < count; ++idx, seq += MAX_FRAME)
+ Common::copy(seq, seq + MAX_FRAME, &_walkSequences[idx]._sequences[0]);
+}
+
+void ScalpelMap::loadData() {
+ // TODO: Remove this
+ if (_vm->getGameID() == GType_RoseTattoo)
+ return;
+
+ // Load the list of location names
+ Common::SeekableReadStream *txtStream = _vm->_res->load(
+ _vm->getGameID() == GType_SerratedScalpel ? "chess.txt" : "map.txt");
+
+ int streamSize = txtStream->size();
+ while (txtStream->pos() < streamSize) {
+ Common::String line;
+ char c;
+ while ((c = txtStream->readByte()) != '\0')
+ line += c;
+
+ _locationNames.push_back(line);
+ }
+
+ delete txtStream;
+
+ // Load the path data
+ Common::SeekableReadStream *pathStream = _vm->_res->load("chess.pth");
+
+ // Get routes between different locations on the map
+ _paths.load(31, *pathStream);
+
+ // Load in the co-ordinates that the paths refer to
+ _pathPoints.resize(208);
+ for (uint idx = 0; idx < _pathPoints.size(); ++idx) {
+ _pathPoints[idx].x = pathStream->readSint16LE();
+ _pathPoints[idx].y = pathStream->readSint16LE();
+ }
+
+ delete pathStream;
+}
+
+int ScalpelMap::show() {
+ Events &events = *_vm->_events;
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ bool changed = false, exitFlag = false;
+ _active = true;
+
+ // Set font and custom cursor for the map
+ int oldFont = screen.fontNumber();
+ screen.setFont(0);
+
+ // Initial screen clear
+ screen._backBuffer1.clear();
+ screen.clear();
+
+ // Load the entire map
+ ImageFile bigMap("bigmap.vgs");
+ screen.setPalette(bigMap._palette);
+
+ // Load need sprites
+ setupSprites();
+
+ screen._backBuffer1.blitFrom(bigMap[0], Common::Point(-_bigPos.x, -_bigPos.y));
+ screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+ screen._backBuffer1.blitFrom(bigMap[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
+ screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+
+ _drawMap = true;
+ _charPoint = -1;
+ _point = -1;
+ people[AL]._position = _lDrawnPos = _overPos;
+
+ // Show place icons
+ showPlaces();
+ saveTopLine();
+ _placesShown = true;
+
+ // Keep looping until either a location is picked, or the game is ended
+ while (!_vm->shouldQuit() && !exitFlag) {
+ events.pollEventsAndWait();
+ events.setButtonState();
+
+ // Keyboard handling
+ if (events.kbHit()) {
+ Common::KeyState keyState = events.getKey();
+
+ if (keyState.keycode == Common::KEYCODE_RETURN || keyState.keycode == Common::KEYCODE_SPACE) {
+ // Both space and enter simulate a mouse release
+ events._pressed = false;
+ events._released = true;
+ events._oldButtons = 0;
+ }
+ }
+
+ // Ignore scrolling attempts until the screen is drawn
+ if (!_drawMap) {
+ Common::Point pt = events.mousePos();
+
+ // Check for vertical map scrolling
+ if ((pt.y > (SHERLOCK_SCREEN_HEIGHT - 10) && _bigPos.y < 200) || (pt.y < 10 && _bigPos.y > 0)) {
+ if (pt.y > (SHERLOCK_SCREEN_HEIGHT - 10))
+ _bigPos.y += 10;
+ else
+ _bigPos.y -= 10;
+
+ changed = true;
+ }
+
+ // Check for horizontal map scrolling
+ if ((pt.x > (SHERLOCK_SCREEN_WIDTH - 10) && _bigPos.x < 315) || (pt.x < 10 && _bigPos.x > 0)) {
+ if (pt.x > (SHERLOCK_SCREEN_WIDTH - 10))
+ _bigPos.x += 15;
+ else
+ _bigPos.x -= 15;
+
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ // Map has scrolled, so redraw new map view
+ changed = false;
+
+ screen._backBuffer1.blitFrom(bigMap[0], Common::Point(-_bigPos.x, -_bigPos.y));
+ screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+ screen._backBuffer1.blitFrom(bigMap[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
+ screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+
+ showPlaces();
+ _placesShown = false;
+
+ saveTopLine();
+ _savedPos.x = -1;
+ updateMap(true);
+ } else if (!_drawMap) {
+ if (!_placesShown) {
+ showPlaces();
+ _placesShown = true;
+ }
+
+ if (_cursorIndex == 0) {
+ Common::Point pt = events.mousePos();
+ highlightIcon(Common::Point(pt.x - 4 + _bigPos.x, pt.y + _bigPos.y));
+ }
+ updateMap(false);
+ }
+
+ if ((events._released || events._rightReleased) && _point != -1) {
+ if (people[AL]._walkCount == 0) {
+ people._walkDest = _points[_point] + Common::Point(4, 9);
+ _charPoint = _point;
+
+ // Start walking to selected location
+ walkTheStreets();
+
+ // Show wait cursor
+ _cursorIndex = 1;
+ events.setCursor((*_mapCursors)[_cursorIndex]._frame);
+ }
+ }
+
+ // Check if a scene has beeen selected and we've finished "moving" to it
+ if (people[AL]._walkCount == 0) {
+ if (_charPoint >= 1 && _charPoint < (int)_points.size())
+ exitFlag = true;
+ }
+
+ if (_drawMap) {
+ _drawMap = false;
+
+ if (screen._fadeStyle)
+ screen.randomTransition();
+ else
+ screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
+ }
+
+ // Wait for a frame
+ events.wait(1);
+ }
+
+ freeSprites();
+ _overPos = people[AL]._position;
+
+ // Reset font
+ screen.setFont(oldFont);
+
+ _active = false;
+ return _charPoint;
+}
+
+void ScalpelMap::setupSprites() {
+ Events &events = *_vm->_events;
+ People &people = *_vm->_people;
+ Scene &scene = *_vm->_scene;
+ _savedPos.x = -1;
+
+ _mapCursors = new ImageFile("omouse.vgs");
+ _cursorIndex = 0;
+ events.setCursor((*_mapCursors)[_cursorIndex]._frame);
+
+ _shapes = new ImageFile("mapicon.vgs");
+ _iconShapes = new ImageFile("overicon.vgs");
+ _iconSave.create((*_shapes)[4]._width, (*_shapes)[4]._height, _vm->getPlatform());
+ Person &p = people[AL];
+ p._description = " ";
+ p._type = CHARACTER;
+ p._position = Common::Point(12400, 5000);
+ p._sequenceNumber = 0;
+ p._images = _shapes;
+ p._imageFrame = nullptr;
+ p._frameNumber = 0;
+ p._delta = Common::Point(0, 0);
+ p._oldSize = Common::Point(0, 0);
+ p._oldSize = Common::Point(0, 0);
+ p._misc = 0;
+ p._walkCount = 0;
+ p._allow = 0;
+ p._noShapeSize = Common::Point(0, 0);
+ p._goto = Common::Point(28000, 15000);
+ p._status = 0;
+ p._walkSequences = _walkSequences;
+ p.setImageFrame();
+ scene._bgShapes.clear();
+}
+
+void ScalpelMap::freeSprites() {
+ delete _mapCursors;
+ delete _shapes;
+ delete _iconShapes;
+ _iconSave.free();
+}
+
+void ScalpelMap::showPlaces() {
+ Screen &screen = *_vm->_screen;
+
+ for (uint idx = 0; idx < _points.size(); ++idx) {
+ const MapEntry &pt = _points[idx];
+
+ if (pt.x != 0 && pt.y != 0) {
+ if (pt.x >= _bigPos.x && (pt.x - _bigPos.x) < SHERLOCK_SCREEN_WIDTH
+ && pt.y >= _bigPos.y && (pt.y - _bigPos.y) < SHERLOCK_SCREEN_HEIGHT) {
+ if (_vm->readFlags(idx)) {
+ screen._backBuffer1.transBlitFrom((*_iconShapes)[pt._translate],
+ Common::Point(pt.x - _bigPos.x - 6, pt.y - _bigPos.y - 12));
+ }
+ }
+ }
+ }
+}
+
+void ScalpelMap::saveTopLine() {
+ _topLine.blitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12));
+}
+
+void ScalpelMap::eraseTopLine() {
+ Screen &screen = *_vm->_screen;
+ screen._backBuffer1.blitFrom(_topLine, Common::Point(0, 0));
+ screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, _topLine.h());
+}
+
+void ScalpelMap::showPlaceName(int idx, bool highlighted) {
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+
+ Common::String name = _locationNames[idx];
+ int width = screen.stringWidth(name);
+
+ if (!_cursorIndex) {
+ saveIcon(people[AL]._imageFrame, _lDrawnPos);
+
+ bool flipped = people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT
+ || people[AL]._sequenceNumber == MAP_UPLEFT;
+ screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, _lDrawnPos, flipped);
+ }
+
+ if (highlighted) {
+ int xp = (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(name)) / 2;
+ screen.gPrint(Common::Point(xp + 2, 2), 0, "%s", name.c_str());
+ screen.gPrint(Common::Point(xp + 1, 1), 0, "%s", name.c_str());
+ screen.gPrint(Common::Point(xp, 0), 12, "%s", name.c_str());
+
+ screen.slamArea(xp, 0, width + 2, 15);
+ }
+}
+
+void ScalpelMap::updateMap(bool flushScreen) {
+ Events &events = *_vm->_events;
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ Common::Point osPos = _savedPos;
+ Common::Point osSize = _savedSize;
+ Common::Point hPos;
+
+ if (_cursorIndex >= 1) {
+ if (++_cursorIndex > (1 + 8))
+ _cursorIndex = 1;
+
+ events.setCursor((*_mapCursors)[(_cursorIndex + 1) / 2]._frame);
+ }
+
+ if (!_drawMap && !flushScreen)
+ restoreIcon();
+ else
+ _savedPos.x = -1;
+
+ people[AL].adjustSprite();
+
+ _lDrawnPos.x = hPos.x = people[AL]._position.x / FIXED_INT_MULTIPLIER - _bigPos.x;
+ _lDrawnPos.y = hPos.y = people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL].frameHeight() - _bigPos.y;
+
+ // Draw the person icon
+ saveIcon(people[AL]._imageFrame, hPos);
+ if (people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT
+ || people[AL]._sequenceNumber == MAP_UPLEFT)
+ screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, hPos, true);
+ else
+ screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, hPos, false);
+
+ if (flushScreen) {
+ screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
+ } else if (!_drawMap) {
+ if (hPos.x > 0 && hPos.y >= 0 && hPos.x < SHERLOCK_SCREEN_WIDTH && hPos.y < SHERLOCK_SCREEN_HEIGHT)
+ screen.flushImage(people[AL]._imageFrame, Common::Point(people[AL]._position.x / FIXED_INT_MULTIPLIER - _bigPos.x,
+ people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL].frameHeight() - _bigPos.y),
+ &people[AL]._oldPosition.x, &people[AL]._oldPosition.y, &people[AL]._oldSize.x, &people[AL]._oldSize.y);
+
+ if (osPos.x != -1)
+ screen.slamArea(osPos.x, osPos.y, osSize.x, osSize.y);
+ }
+}
+
+void ScalpelMap::walkTheStreets() {
+ People &people = *_vm->_people;
+ Common::Array<Common::Point> tempPath;
+
+ // Get indexes into the path lists for the start and destination scenes
+ int start = _points[_oldCharPoint]._translate;
+ int dest = _points[_charPoint]._translate;
+
+ // Get pointer to start of path
+ const byte *path = _paths.getPath(start, dest);
+
+ // Add in destination position
+ people._walkTo.clear();
+ Common::Point destPos = people._walkDest;
+
+ // Check for any intermediate points between the two locations
+ if (path[0] || _charPoint > 50 || _oldCharPoint > 50) {
+ people[AL]._sequenceNumber = -1;
+
+ if (_charPoint == 51 || _oldCharPoint == 51) {
+ people.setWalking();
+ } else {
+ bool reversePath = false;
+
+ // Check for moving the path backwards or forwards
+ if (path[0] == 255) {
+ reversePath = true;
+ SWAP(start, dest);
+ path = _paths.getPath(start, dest);
+ }
+
+ do {
+ int idx = *path++;
+ tempPath.push_back(_pathPoints[idx - 1] + Common::Point(4, 4));
+ } while (*path != 254);
+
+ // Load up the path to use
+ people._walkTo.clear();
+
+ if (reversePath) {
+ for (int idx = (int)tempPath.size() - 1; idx >= 0; --idx)
+ people._walkTo.push(tempPath[idx]);
+ } else {
+ for (int idx = 0; idx < (int)tempPath.size(); ++idx)
+ people._walkTo.push(tempPath[idx]);
+ }
+
+ people._walkDest = people._walkTo.pop() + Common::Point(12, 6);
+ people.setWalking();
+ }
+ } else {
+ people[AL]._walkCount = 0;
+ }
+
+ // Store the final destination icon position
+ people._walkTo.push(destPos);
+}
+
+void ScalpelMap::saveIcon(ImageFrame *src, const Common::Point &pt) {
+ Screen &screen = *_vm->_screen;
+ Common::Point size(src->_width, src->_height);
+ Common::Point pos = pt;
+
+ if (pos.x < 0) {
+ size.x += pos.x;
+ pos.x = 0;
+ }
+
+ if (pos.y < 0) {
+ size.y += pos.y;
+ pos.y = 0;
+ }
+
+ if ((pos.x + size.x) > SHERLOCK_SCREEN_WIDTH)
+ size.x -= (pos.x + size.x) - SHERLOCK_SCREEN_WIDTH;
+
+ if ((pos.y + size.y) > SHERLOCK_SCREEN_HEIGHT)
+ size.y -= (pos.y + size.y) - SHERLOCK_SCREEN_HEIGHT;
+
+ if (size.x < 1 || size.y < 1 || pos.x >= SHERLOCK_SCREEN_WIDTH || pos.y >= SHERLOCK_SCREEN_HEIGHT || _drawMap) {
+ // Flag as the area not needing to be saved
+ _savedPos.x = -1;
+ return;
+ }
+
+ assert(size.x <= _iconSave.w() && size.y <= _iconSave.h());
+ _iconSave.blitFrom(screen._backBuffer1, Common::Point(0, 0),
+ Common::Rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y));
+ _savedPos = pos;
+ _savedSize = size;
+}
+
+void ScalpelMap::restoreIcon() {
+ Screen &screen = *_vm->_screen;
+
+ if (_savedPos.x >= 0 && _savedPos.y >= 0 && _savedPos.x <= SHERLOCK_SCREEN_WIDTH
+ && _savedPos.y < SHERLOCK_SCREEN_HEIGHT)
+ screen._backBuffer1.blitFrom(_iconSave, _savedPos, Common::Rect(0, 0, _savedSize.x, _savedSize.y));
+}
+
+void ScalpelMap::highlightIcon(const Common::Point &pt) {
+ int oldPoint = _point;
+
+ // Iterate through the icon list
+ bool done = false;
+ for (int idx = 0; idx < (int)_points.size(); ++idx) {
+ const MapEntry &entry = _points[idx];
+
+ // Check whether the mouse is over a given icon
+ if (entry.x != 0 && entry.y != 0) {
+ if (Common::Rect(entry.x - 8, entry.y - 8, entry.x + 9, entry.y + 9).contains(pt)) {
+ done = true;
+
+ if (_point != idx && _vm->readFlags(idx)) {
+ // Changed to a new valid (visible) location
+ eraseTopLine();
+ showPlaceName(idx, true);
+ _point = idx;
+ }
+ }
+ }
+ }
+
+ if (!done) {
+ // No icon was highlighted
+ if (_point != -1) {
+ // No longer highlighting previously highlighted icon, so erase it
+ showPlaceName(_point, false);
+ eraseTopLine();
+ }
+
+ _point = -1;
+ } else if (oldPoint != -1 && oldPoint != _point) {
+ showPlaceName(oldPoint, false);
+ eraseTopLine();
+ }
+}
} // End of namespace Scalpel
diff --git a/engines/sherlock/scalpel/scalpel_map.h b/engines/sherlock/scalpel/scalpel_map.h
index 4fb41421bb..e61375f116 100644
--- a/engines/sherlock/scalpel/scalpel_map.h
+++ b/engines/sherlock/scalpel/scalpel_map.h
@@ -24,7 +24,12 @@
#define SHERLOCK_SCALPEL_MAP_H
#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/str-array.h"
+#include "sherlock/surface.h"
#include "sherlock/map.h"
+#include "sherlock/resources.h"
namespace Sherlock {
@@ -32,9 +37,132 @@ class SherlockEngine;
namespace Scalpel {
+
+struct MapEntry : Common::Point {
+ int _translate;
+
+ MapEntry() : Common::Point(), _translate(-1) {}
+
+ MapEntry(int posX, int posY, int translate) : Common::Point(posX, posY), _translate(translate) {}
+};
+
+class MapPaths {
+private:
+ int _numLocations;
+ Common::Array< Common::Array<byte> > _paths;
+
+public:
+ MapPaths();
+
+ /**
+ * Load the data for the paths between locations on the map
+ */
+ void load(int numLocations, Common::SeekableReadStream &s);
+
+ /**
+ * Get the path between two locations on the map
+ */
+ const byte *getPath(int srcLocation, int destLocation);
+};
+
class ScalpelMap: public Map {
+private:
+ Common::Array<MapEntry> _points; // Map locations for each scene
+ Common::StringArray _locationNames;
+ MapPaths _paths;
+ Common::Array<Common::Point> _pathPoints;
+ Common::Point _savedPos;
+ Common::Point _savedSize;
+ Surface _topLine;
+ ImageFile *_mapCursors;
+ ImageFile *_shapes;
+ ImageFile *_iconShapes;
+ WalkSequences _walkSequences;
+ Point32 _lDrawnPos;
+ int _point;
+ bool _placesShown;
+ int _cursorIndex;
+ bool _drawMap;
+ Surface _iconSave;
+protected:
+ /**
+ * Load data needed for the map
+ */
+ void loadData();
+
+ /**
+ * Load and initialize all the sprites that are needed for the map display
+ */
+ void setupSprites();
+
+ /**
+ * Free the sprites and data used by the map
+ */
+ void freeSprites();
+
+ /**
+ * Draws an icon for every place that's currently known
+ */
+ void showPlaces();
+
+ /**
+ * Makes a copy of the top rows of the screen that are used to display location names
+ */
+ void saveTopLine();
+
+ /**
+ * Erases anything shown in the top line by restoring the previously saved original map background
+ */
+ void eraseTopLine();
+
+ /**
+ * Prints the name of the specified icon
+ */
+ void showPlaceName(int idx, bool highlighted);
+
+ /**
+ * Update all on-screen sprites to account for any scrolling of the map
+ */
+ void updateMap(bool flushScreen);
+
+ /**
+ * Handle moving icon for player from their previous location on the map to a destination location
+ */
+ void walkTheStreets();
+
+ /**
+ * Save the area under the player's icon
+ */
+ void saveIcon(ImageFrame *src, const Common::Point &pt);
+
+ /**
+ * Restore the area under the player's icon
+ */
+ void restoreIcon();
+
+ /**
+ * Handles highlighting map icons, showing their names
+ */
+ void highlightIcon(const Common::Point &pt);
public:
- ScalpelMap(SherlockEngine *vm) : Map(vm) {}
+ ScalpelMap(SherlockEngine *vm);
+
+ const MapEntry &operator[](int idx) { return _points[idx]; }
+
+ /**
+ * Loads the list of points for locations on the map for each scene
+ */
+ void loadPoints(int count, const int *xList, const int *yList, const int *transList);
+
+ /**
+ * Load the sequence data for player icon animations
+ */
+ void loadSequences(int count, const byte *seq);
+
+ /**
+ * Show the map
+ */
+ virtual int show();
};
} // End of namespace Scalpel
diff --git a/engines/sherlock/scalpel/scalpel_people.cpp b/engines/sherlock/scalpel/scalpel_people.cpp
index 2b76eea55e..80e6061e8b 100644
--- a/engines/sherlock/scalpel/scalpel_people.cpp
+++ b/engines/sherlock/scalpel/scalpel_people.cpp
@@ -21,6 +21,7 @@
*/
#include "sherlock/scalpel/scalpel_people.h"
+#include "sherlock/scalpel/scalpel_map.h"
#include "sherlock/sherlock.h"
namespace Sherlock {
@@ -86,7 +87,6 @@ void ScalpelPeople::setTalking(int speaker) {
}
}
-
void ScalpelPeople::synchronize(Serializer &s) {
s.syncAsByte(_holmesOn);
s.syncAsSint32LE(_player._position.x);
@@ -130,6 +130,57 @@ void ScalpelPeople::setTalkSequence(int speaker, int sequenceNum) {
}
}
+void ScalpelPeople::gotoStand(Sprite &sprite) {
+ ScalpelMap &map = *(ScalpelMap *)_vm->_map;
+ _walkTo.clear();
+ sprite._walkCount = 0;
+
+ switch (sprite._sequenceNumber) {
+ case Scalpel::WALK_UP:
+ sprite._sequenceNumber = STOP_UP;
+ break;
+ case WALK_DOWN:
+ sprite._sequenceNumber = STOP_DOWN;
+ break;
+ case TALK_LEFT:
+ case WALK_LEFT:
+ sprite._sequenceNumber = STOP_LEFT;
+ break;
+ case TALK_RIGHT:
+ case WALK_RIGHT:
+ sprite._sequenceNumber = STOP_RIGHT;
+ break;
+ case WALK_UPRIGHT:
+ sprite._sequenceNumber = STOP_UPRIGHT;
+ break;
+ case WALK_UPLEFT:
+ sprite._sequenceNumber = STOP_UPLEFT;
+ break;
+ case WALK_DOWNRIGHT:
+ sprite._sequenceNumber = STOP_DOWNRIGHT;
+ break;
+ case WALK_DOWNLEFT:
+ sprite._sequenceNumber = STOP_DOWNLEFT;
+ break;
+ default:
+ break;
+ }
+
+ // Only restart frame at 0 if the sequence number has changed
+ if (_oldWalkSequence != -1 || sprite._sequenceNumber == Scalpel::STOP_UP)
+ sprite._frameNumber = 0;
+
+ if (map._active) {
+ sprite._sequenceNumber = 0;
+ _player._position.x = (map[map._charPoint].x - 6) * FIXED_INT_MULTIPLIER;
+ _player._position.y = (map[map._charPoint].y + 10) * FIXED_INT_MULTIPLIER;
+ }
+
+ _oldWalkSequence = -1;
+ _allowWalkAbort = true;
+}
+
+
} // End of namespace Scalpel
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_people.h b/engines/sherlock/scalpel/scalpel_people.h
index 6981157103..1f14ceee0e 100644
--- a/engines/sherlock/scalpel/scalpel_people.h
+++ b/engines/sherlock/scalpel/scalpel_people.h
@@ -60,6 +60,12 @@ public:
* Change the sequence of the scene background object associated with the specified speaker.
*/
virtual void setTalkSequence(int speaker, int sequenceNum = 1);
+
+ /**
+ * Bring a moving character to a standing position. If the Scalpel chessboard
+ * is being displayed, then the chraracter will always face down.
+ */
+ virtual void gotoStand(Sprite &sprite);
};
} // End of namespace Scalpel
diff --git a/engines/sherlock/scalpel/scalpel_scene.cpp b/engines/sherlock/scalpel/scalpel_scene.cpp
index e0ad3a7b6d..95a58be99d 100644
--- a/engines/sherlock/scalpel/scalpel_scene.cpp
+++ b/engines/sherlock/scalpel/scalpel_scene.cpp
@@ -21,16 +21,34 @@
*/
#include "sherlock/scalpel/scalpel_scene.h"
+#include "sherlock/scalpel/scalpel_map.h"
#include "sherlock/scalpel/scalpel_people.h"
#include "sherlock/scalpel/scalpel.h"
#include "sherlock/events.h"
#include "sherlock/people.h"
#include "sherlock/screen.h"
+#include "sherlock/sherlock.h"
namespace Sherlock {
namespace Scalpel {
+bool ScalpelScene::loadScene(const Common::String &filename) {
+ ScalpelMap &map = *(ScalpelMap *)_vm->_map;
+ bool result = Scene::loadScene(filename);
+
+ if (!_vm->isDemo()) {
+ // Reset the previous map location and position on overhead map
+ map._oldCharPoint = _currentScene;
+
+ map._overPos.x = (map[_currentScene].x - 6) * FIXED_INT_MULTIPLIER;
+ map._overPos.y = (map[_currentScene].y + 9) * FIXED_INT_MULTIPLIER;
+
+ }
+
+ return result;
+}
+
void ScalpelScene::drawAllShapes() {
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
@@ -467,6 +485,218 @@ void ScalpelScene::doBgAnim() {
}
}
+int ScalpelScene::startCAnim(int cAnimNum, int playRate) {
+ Events &events = *_vm->_events;
+ ScalpelMap &map = *(ScalpelMap *)_vm->_map;
+ People &people = *_vm->_people;
+ Resources &res = *_vm->_res;
+ Talk &talk = *_vm->_talk;
+ UserInterface &ui = *_vm->_ui;
+ Point32 tpPos, walkPos;
+ int tpDir, walkDir;
+ int tFrames = 0;
+ int gotoCode = -1;
+
+ // Validation
+ if (cAnimNum >= (int)_cAnim.size())
+ // number out of bounds
+ return -1;
+ if (_canimShapes.size() >= 3 || playRate == 0)
+ // Too many active animations, or invalid play rate
+ return 0;
+
+ CAnim &cAnim = _cAnim[cAnimNum];
+ if (playRate < 0) {
+ // Reverse direction
+ walkPos = cAnim._teleportPos;
+ walkDir = cAnim._teleportDir;
+ tpPos = cAnim._goto;
+ tpDir = cAnim._gotoDir;
+ } else {
+ // Forward direction
+ walkPos = cAnim._goto;
+ walkDir = cAnim._gotoDir;
+ tpPos = cAnim._teleportPos;
+ tpDir = cAnim._teleportDir;
+ }
+
+ CursorId oldCursor = events.getCursor();
+ events.setCursor(WAIT);
+
+ if (walkPos.x != -1) {
+ // Holmes must walk to the walk point before the cAnimation is started
+ if (people[AL]._position != walkPos)
+ people.walkToCoords(walkPos, walkDir);
+ }
+
+ if (talk._talkToAbort)
+ return 1;
+
+ // Add new anim shape entry for displaying the animation
+ _canimShapes.push_back(Object());
+ Object &cObj = _canimShapes[_canimShapes.size() - 1];
+
+ // Copy the canimation into the bgShapes type canimation structure so it can be played
+ cObj._allow = cAnimNum + 1; // Keep track of the parent structure
+ cObj._name = _cAnim[cAnimNum]._name; // Copy name
+
+ // Remove any attempt to draw object frame
+ if (cAnim._type == NO_SHAPE && cAnim._sequences[0] < 100)
+ cAnim._sequences[0] = 0;
+
+ cObj._sequences = cAnim._sequences;
+ cObj._images = nullptr;
+ cObj._position = cAnim._position;
+ cObj._delta = Common::Point(0, 0);
+ cObj._type = cAnim._type;
+ cObj._flags = cAnim._flags;
+
+ cObj._maxFrames = 0;
+ cObj._frameNumber = -1;
+ cObj._sequenceNumber = cAnimNum;
+ cObj._oldPosition = Common::Point(0, 0);
+ cObj._oldSize = Common::Point(0, 0);
+ cObj._goto = Common::Point(0, 0);
+ cObj._status = 0;
+ cObj._misc = 0;
+ cObj._imageFrame = nullptr;
+
+ if (cAnim._name.size() > 0 && cAnim._type != NO_SHAPE) {
+ if (tpPos.x != -1)
+ people[AL]._type = REMOVE;
+
+ Common::String fname = cAnim._name + ".vgs";
+ if (!res.isInCache(fname)) {
+ // Set up RRM scene data
+ Common::SeekableReadStream *rrmStream = res.load(_rrmName);
+ rrmStream->seek(44 + cAnimNum * 4);
+ rrmStream->seek(rrmStream->readUint32LE());
+
+ // Load the canimation into the cache
+ Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream->readStream(cAnim._size) :
+ Resources::decompressLZ(*rrmStream, cAnim._size);
+ res.addToCache(fname, *imgStream);
+
+ delete imgStream;
+ delete rrmStream;
+ }
+
+ // Now load the resource as an image
+ cObj._images = new ImageFile(fname);
+ cObj._imageFrame = &(*cObj._images)[0];
+ cObj._maxFrames = cObj._images->size();
+
+ int frames = 0;
+ if (playRate < 0) {
+ // Reverse direction
+ // Count number of frames
+ while (cObj._sequences[frames] && frames < MAX_FRAME)
+ ++frames;
+ } else {
+ // Forward direction
+ Object::_countCAnimFrames = true;
+
+ while (cObj._type == ACTIVE_BG_SHAPE) {
+ cObj.checkObject();
+ ++frames;
+
+ if (frames >= 1000)
+ error("CAnim has infinite loop sequence");
+ }
+
+ if (frames > 1)
+ --frames;
+
+ Object::_countCAnimFrames = false;
+
+ cObj._type = cAnim._type;
+ cObj._frameNumber = -1;
+ cObj._position = cAnim._position;
+ cObj._delta = Common::Point(0, 0);
+ }
+
+ // Return if animation has no frames in it
+ if (frames == 0)
+ return -2;
+
+ ++frames;
+ int repeat = ABS(playRate);
+ int dir;
+
+ if (playRate < 0) {
+ // Play in reverse
+ dir = -2;
+ cObj._frameNumber = frames - 3;
+ } else {
+ dir = 0;
+ }
+
+ tFrames = frames - 1;
+ int pauseFrame = (_cAnimFramePause) ? frames - _cAnimFramePause : -1;
+
+ while (--frames) {
+ if (frames == pauseFrame)
+ ui.printObjectDesc();
+
+ doBgAnim();
+
+ // Repeat same frame
+ int temp = repeat;
+ while (--temp > 0) {
+ cObj._frameNumber--;
+ doBgAnim();
+
+ if (_vm->shouldQuit())
+ return 0;
+ }
+
+ cObj._frameNumber += dir;
+ }
+
+ people[AL]._type = CHARACTER;
+ }
+
+ // Teleport to ending coordinates if necessary
+ if (tpPos.x != -1) {
+ people[AL]._position = tpPos; // Place the player
+ people[AL]._sequenceNumber = tpDir;
+ people.gotoStand(people[AL]);
+ }
+
+ if (playRate < 0)
+ // Reverse direction - set to end sequence
+ cObj._frameNumber = tFrames - 1;
+
+ if (cObj._frameNumber <= 26)
+ gotoCode = cObj._sequences[cObj._frameNumber + 3];
+
+ // Unless anim shape has already been freed, set it to REMOVE so doBgAnim can free it
+ if (_canimShapes.indexOf(cObj) != -1)
+ cObj.checkObject();
+
+ if (gotoCode > 0 && !talk._talkToAbort) {
+ _goToScene = gotoCode;
+
+ if (_goToScene < 97 && map[_goToScene].x) {
+ map._overPos = map[_goToScene];
+ }
+ }
+
+ people.loadWalk();
+
+ if (tpPos.x != -1 && !talk._talkToAbort) {
+ // Teleport to ending coordinates
+ people[AL]._position = tpPos;
+ people[AL]._sequenceNumber = tpDir;
+
+ people.gotoStand(people[AL]);
+ }
+
+ events.setCursor(oldCursor);
+
+ return 1;
+}
+
} // End of namespace Scalpel
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_scene.h b/engines/sherlock/scalpel/scalpel_scene.h
index 88c7581f59..f79892e4e6 100644
--- a/engines/sherlock/scalpel/scalpel_scene.h
+++ b/engines/sherlock/scalpel/scalpel_scene.h
@@ -44,6 +44,17 @@ private:
void doBgAnimCheckCursor();
protected:
/**
+ * Loads the data associated for a given scene. The room resource file's format is:
+ * BGHEADER: Holds an index for the rest of the file
+ * STRUCTS: The objects for the scene
+ * IMAGES: The graphic information for the structures
+ *
+ * The _misc field of the structures contains the number of the graphic image
+ * that it should point to after loading; _misc is then set to 0.
+ */
+ virtual bool loadScene(const Common::String &filename);
+
+ /**
* Checks all the background shapes. If a background shape is animating,
* it will flag it as needing to be drawn. If a non-animating shape is
* colliding with another shape, it will also flag it as needing drawing
@@ -61,6 +72,16 @@ public:
* Draw all objects and characters.
*/
virtual void doBgAnim();
+
+ /**
+ * Attempt to start a canimation sequence. It will load the requisite graphics, and
+ * then copy the canim object into the _canimShapes array to start the animation.
+ *
+ * @param cAnimNum The canim object within the current scene
+ * @param playRate Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc.
+ * A negative playRate can also be specified to play the animation in reverse
+ */
+ virtual int startCAnim(int cAnimNum, int playRate);
};
} // End of namespace Scalpel
diff --git a/engines/sherlock/scalpel/scalpel_talk.cpp b/engines/sherlock/scalpel/scalpel_talk.cpp
index 217ed9b2a4..3dc99c236b 100644
--- a/engines/sherlock/scalpel/scalpel_talk.cpp
+++ b/engines/sherlock/scalpel/scalpel_talk.cpp
@@ -21,7 +21,9 @@
*/
#include "sherlock/scalpel/scalpel_talk.h"
+#include "sherlock/scalpel/scalpel_map.h"
#include "sherlock/scalpel/scalpel_people.h"
+#include "sherlock/scalpel/scalpel_scene.h"
#include "sherlock/scalpel/scalpel_user_interface.h"
#include "sherlock/sherlock.h"
#include "sherlock/screen.h"
@@ -289,12 +291,12 @@ OpcodeReturn ScalpelTalk::cmdSwitchSpeaker(const byte *&str) {
}
OpcodeReturn ScalpelTalk::cmdGotoScene(const byte *&str) {
- Map &map = *_vm->_map;
+ ScalpelMap &map = *(ScalpelMap *)_vm->_map;
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
scene._goToScene = str[1] - 1;
- if (scene._goToScene != 100) {
+ if (scene._goToScene != OVERHEAD_MAP) {
// Not going to the map overview
map._oldCharPoint = scene._goToScene;
map._overPos.x = (map[scene._goToScene].x - 6) * FIXED_INT_MULTIPLIER;
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index c43887438e..9100d58e13 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -261,7 +261,6 @@ void Scene::freeScene() {
bool Scene::loadScene(const Common::String &filename) {
Events &events = *_vm->_events;
- Map &map = *_vm->_map;
Music &music = *_vm->_music;
People &people = *_vm->_people;
Resources &res = *_vm->_res;
@@ -629,17 +628,6 @@ bool Scene::loadScene(const Common::String &filename) {
_walkedInScene = false;
saves._justLoaded = false;
- if (!_vm->isDemo()) {
- // Reset the previous map location and position on overhead map
- map._oldCharPoint = _currentScene;
-
- if (IS_SERRATED_SCALPEL) {
- map._overPos.x = (map[_currentScene].x - 6) * FIXED_INT_MULTIPLIER;
- map._overPos.y = (map[_currentScene].y + 9) * FIXED_INT_MULTIPLIER;
-
- }
- }
-
events.clearEvents();
return flag;
}
@@ -914,218 +902,6 @@ Exit *Scene::checkForExit(const Common::Rect &r) {
return nullptr;
}
-int Scene::startCAnim(int cAnimNum, int playRate) {
- Events &events = *_vm->_events;
- Map &map = *_vm->_map;
- People &people = *_vm->_people;
- Resources &res = *_vm->_res;
- Talk &talk = *_vm->_talk;
- UserInterface &ui = *_vm->_ui;
- Point32 tpPos, walkPos;
- int tpDir, walkDir;
- int tFrames = 0;
- int gotoCode = -1;
-
- // Validation
- if (cAnimNum >= (int)_cAnim.size())
- // number out of bounds
- return -1;
- if (_canimShapes.size() >= 3 || playRate == 0)
- // Too many active animations, or invalid play rate
- return 0;
-
- CAnim &cAnim = _cAnim[cAnimNum];
- if (playRate < 0) {
- // Reverse direction
- walkPos = cAnim._teleportPos;
- walkDir = cAnim._teleportDir;
- tpPos = cAnim._goto;
- tpDir = cAnim._gotoDir;
- } else {
- // Forward direction
- walkPos = cAnim._goto;
- walkDir = cAnim._gotoDir;
- tpPos = cAnim._teleportPos;
- tpDir = cAnim._teleportDir;
- }
-
- CursorId oldCursor = events.getCursor();
- events.setCursor(WAIT);
-
- if (walkPos.x != -1) {
- // Holmes must walk to the walk point before the cAnimation is started
- if (people[AL]._position != walkPos)
- people.walkToCoords(walkPos, walkDir);
- }
-
- if (talk._talkToAbort)
- return 1;
-
- // Add new anim shape entry for displaying the animation
- _canimShapes.push_back(Object());
- Object &cObj = _canimShapes[_canimShapes.size() - 1];
-
- // Copy the canimation into the bgShapes type canimation structure so it can be played
- cObj._allow = cAnimNum + 1; // Keep track of the parent structure
- cObj._name = _cAnim[cAnimNum]._name; // Copy name
-
- // Remove any attempt to draw object frame
- if (cAnim._type == NO_SHAPE && cAnim._sequences[0] < 100)
- cAnim._sequences[0] = 0;
-
- cObj._sequences = cAnim._sequences;
- cObj._images = nullptr;
- cObj._position = cAnim._position;
- cObj._delta = Common::Point(0, 0);
- cObj._type = cAnim._type;
- cObj._flags = cAnim._flags;
-
- cObj._maxFrames = 0;
- cObj._frameNumber = -1;
- cObj._sequenceNumber = cAnimNum;
- cObj._oldPosition = Common::Point(0, 0);
- cObj._oldSize = Common::Point(0, 0);
- cObj._goto = Common::Point(0, 0);
- cObj._status = 0;
- cObj._misc = 0;
- cObj._imageFrame = nullptr;
-
- if (cAnim._name.size() > 0 && cAnim._type != NO_SHAPE) {
- if (tpPos.x != -1)
- people[AL]._type = REMOVE;
-
- Common::String fname = cAnim._name + ".vgs";
- if (!res.isInCache(fname)) {
- // Set up RRM scene data
- Common::SeekableReadStream *rrmStream = res.load(_rrmName);
- rrmStream->seek(44 + cAnimNum * 4);
- rrmStream->seek(rrmStream->readUint32LE());
-
- // Load the canimation into the cache
- Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream->readStream(cAnim._size) :
- Resources::decompressLZ(*rrmStream, cAnim._size);
- res.addToCache(fname, *imgStream);
-
- delete imgStream;
- delete rrmStream;
- }
-
- // Now load the resource as an image
- cObj._images = new ImageFile(fname);
- cObj._imageFrame = &(*cObj._images)[0];
- cObj._maxFrames = cObj._images->size();
-
- int frames = 0;
- if (playRate < 0) {
- // Reverse direction
- // Count number of frames
- while (cObj._sequences[frames] && frames < MAX_FRAME)
- ++frames;
- } else {
- // Forward direction
- Object::_countCAnimFrames = true;
-
- while (cObj._type == ACTIVE_BG_SHAPE) {
- cObj.checkObject();
- ++frames;
-
- if (frames >= 1000)
- error("CAnim has infinite loop sequence");
- }
-
- if (frames > 1)
- --frames;
-
- Object::_countCAnimFrames = false;
-
- cObj._type = cAnim._type;
- cObj._frameNumber = -1;
- cObj._position = cAnim._position;
- cObj._delta = Common::Point(0, 0);
- }
-
- // Return if animation has no frames in it
- if (frames == 0)
- return -2;
-
- ++frames;
- int repeat = ABS(playRate);
- int dir;
-
- if (playRate < 0) {
- // Play in reverse
- dir = -2;
- cObj._frameNumber = frames - 3;
- } else {
- dir = 0;
- }
-
- tFrames = frames - 1;
- int pauseFrame = (_cAnimFramePause) ? frames - _cAnimFramePause : -1;
-
- while (--frames) {
- if (frames == pauseFrame)
- ui.printObjectDesc();
-
- doBgAnim();
-
- // Repeat same frame
- int temp = repeat;
- while (--temp > 0) {
- cObj._frameNumber--;
- doBgAnim();
-
- if (_vm->shouldQuit())
- return 0;
- }
-
- cObj._frameNumber += dir;
- }
-
- people[AL]._type = CHARACTER;
- }
-
- // Teleport to ending coordinates if necessary
- if (tpPos.x != -1) {
- people[AL]._position = tpPos; // Place the player
- people[AL]._sequenceNumber = tpDir;
- people.gotoStand(people[AL]);
- }
-
- if (playRate < 0)
- // Reverse direction - set to end sequence
- cObj._frameNumber = tFrames - 1;
-
- if (cObj._frameNumber <= 26)
- gotoCode = cObj._sequences[cObj._frameNumber + 3];
-
- // Unless anim shape has already been freed, set it to REMOVE so doBgAnim can free it
- if (_canimShapes.indexOf(cObj) != -1)
- cObj.checkObject();
-
- if (gotoCode > 0 && !talk._talkToAbort) {
- _goToScene = gotoCode;
-
- if (_goToScene < 97 && map[_goToScene].x) {
- map._overPos = map[_goToScene];
- }
- }
-
- people.loadWalk();
-
- if (tpPos.x != -1 && !talk._talkToAbort) {
- // Teleport to ending coordinates
- people[AL]._position = tpPos;
- people[AL]._sequenceNumber = tpDir;
-
- people.gotoStand(people[AL]);
- }
-
- events.setCursor(oldCursor);
-
- return 1;
-}
-
int Scene::findBgShape(const Common::Rect &r) {
if (!_doBgAnimDone)
// New frame hasn't been drawn yet
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 11fd1da149..ab636f7b73 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -139,7 +139,6 @@ struct SceneTripEntry {
class Scene {
private:
- Common::String _rrmName;
bool _loadingSavedGame;
/**
@@ -173,6 +172,7 @@ private:
void saveSceneStatus();
protected:
SherlockEngine *_vm;
+ Common::String _rrmName;
/**
* Loads the data associated for a given scene. The room resource file's format is:
@@ -260,16 +260,6 @@ public:
Exit *checkForExit(const Common::Rect &r);
/**
- * Attempt to start a canimation sequence. It will load the requisite graphics, and
- * then copy the canim object into the _canimShapes array to start the animation.
- *
- * @param cAnimNum The canim object within the current scene
- * @param playRate Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc.
- * A negative playRate can also be specified to play the animation in reverse
- */
- int startCAnim(int cAnimNum, int playRate);
-
- /**
* Scans through the object list to find one with a matching name, and will
* call toggleHidden with all matches found. Returns the numer of matches found
*/
@@ -319,6 +309,16 @@ public:
* to be drawn
*/
virtual void updateBackground();
+
+ /**
+ * Attempt to start a canimation sequence. It will load the requisite graphics, and
+ * then copy the canim object into the _canimShapes array to start the animation.
+ *
+ * @param cAnimNum The canim object within the current scene
+ * @param playRate Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc.
+ * A negative playRate can also be specified to play the animation in reverse
+ */
+ virtual int startCAnim(int cAnimNum, int playRate) = 0;
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_map.cpp b/engines/sherlock/tattoo/tattoo_map.cpp
index 9dd35a9de6..ced7ed9a58 100644
--- a/engines/sherlock/tattoo/tattoo_map.cpp
+++ b/engines/sherlock/tattoo/tattoo_map.cpp
@@ -26,6 +26,10 @@ namespace Sherlock {
namespace Tattoo {
+int TattooMap::show() {
+ // TODO
+ return 61;
+}
} // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/tattoo_map.h b/engines/sherlock/tattoo/tattoo_map.h
index 97a330adab..15dd90e78a 100644
--- a/engines/sherlock/tattoo/tattoo_map.h
+++ b/engines/sherlock/tattoo/tattoo_map.h
@@ -35,6 +35,11 @@ namespace Tattoo {
class TattooMap : public Map {
public:
TattooMap(SherlockEngine *vm) : Map(vm) {}
+
+ /**
+ * Show the map
+ */
+ virtual int show();
};
} // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/tattoo_people.cpp b/engines/sherlock/tattoo/tattoo_people.cpp
index 6952c876c0..61f79c471c 100644
--- a/engines/sherlock/tattoo/tattoo_people.cpp
+++ b/engines/sherlock/tattoo/tattoo_people.cpp
@@ -222,6 +222,10 @@ void TattooPeople::synchronize(Serializer &s) {
}
}
+void TattooPeople::gotoStand(Sprite &sprite) {
+ error("TODO: gotoStand");
+}
+
} // End of namespace Tattoo
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_people.h b/engines/sherlock/tattoo/tattoo_people.h
index c4f0bfd3ed..e4216d080e 100644
--- a/engines/sherlock/tattoo/tattoo_people.h
+++ b/engines/sherlock/tattoo/tattoo_people.h
@@ -96,6 +96,12 @@ public:
* Change the sequence of the scene background object associated with the specified speaker.
*/
virtual void setTalkSequence(int speaker, int sequenceNum = 1);
+
+ /**
+ * Bring a moving character to a standing position. If the Scalpel chessboard
+ * is being displayed, then the chraracter will always face down.
+ */
+ virtual void gotoStand(Sprite &sprite);
};
} // End of namespace Scalpel
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index 51e0eb1110..6ef4d2fd77 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -770,6 +770,10 @@ void TattooScene::setupBGArea(const byte cMap[PALETTE_SIZE]) {
}
}
+int TattooScene::startCAnim(int cAnimNum, int playRate) {
+ error("TODO: startCAnim");
+}
+
} // End of namespace Tattoo
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_scene.h b/engines/sherlock/tattoo/tattoo_scene.h
index 78ab1e6521..3c4a3cd0e3 100644
--- a/engines/sherlock/tattoo/tattoo_scene.h
+++ b/engines/sherlock/tattoo/tattoo_scene.h
@@ -109,6 +109,15 @@ public:
*/
virtual void updateBackground();
+ /**
+ * Attempt to start a canimation sequence. It will load the requisite graphics, and
+ * then copy the canim object into the _canimShapes array to start the animation.
+ *
+ * @param cAnimNum The canim object within the current scene
+ * @param playRate Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc.
+ * A negative playRate can also be specified to play the animation in reverse
+ */
+ virtual int startCAnim(int cAnimNum, int playRate);
};
} // End of namespace Tattoo