aboutsummaryrefslogtreecommitdiff
path: root/engines/sherlock/scene.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sherlock/scene.cpp')
-rw-r--r--engines/sherlock/scene.cpp348
1 files changed, 345 insertions, 3 deletions
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 13315b065b..92a8757fd8 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -22,10 +22,42 @@
#include "sherlock/scene.h"
#include "sherlock/sherlock.h"
+#include "sherlock/scalpel/scalpel.h"
#include "sherlock/decompress.h"
namespace Sherlock {
+// Main Menu control locations
+const int MENU_POINTS[12][4] = {
+ { 13, 153, 72, 165 },
+ { 13, 169, 72, 181 },
+ { 13, 185, 72, 197 },
+ { 88, 153, 152, 165 },
+ { 88, 169, 152, 181 },
+ { 88, 185, 152, 197 },
+ { 165, 153, 232, 165 },
+ { 165, 169, 232, 181 },
+ { 165, 185, 233, 197 },
+ { 249, 153, 305, 165 },
+ { 249, 169, 305, 181 },
+ { 249, 185, 305, 197 }
+};
+
+// Inventory control locations */
+const int INVENTORY_POINTS[8][3] = {
+ { 4, 50, 28 },
+ { 52, 99, 76 },
+ { 101, 140, 122 },
+ { 142, 187, 165 },
+ { 189, 219, 197 },
+ { 221, 251, 233 },
+ { 253, 283, 265 },
+ { 285, 315, 293 }
+};
+
+/*----------------------------------------------------------------*/
+
+
void BgFileHeader::synchronize(Common::SeekableReadStream &s) {
_numStructs = s.readUint16LE();
_numImages = s.readUint16LE();
@@ -89,7 +121,8 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) {
_goToRoom = -1;
_changes = false;
_charPoint = _oldCharPoint = 0;
- _windowOpen = _infoFlag = false;
+ _windowOpen = false;
+ _infoFlag = false;
_keyboardInput = 0;
_walkedInScene = false;
_ongoingCans = 0;
@@ -102,6 +135,10 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) {
_menuMode = STD_MODE;
_invMode = INVMODE_0;
_restoreFlag = false;
+ _invLookFlag = false;
+ _lookHelp = false;
+ _animating = 0;
+ _doBgAnimDone = true;
_controlPanel = new ImageFile("controls.vgs");
_controls = nullptr; // new ImageFile("menu.all");
@@ -236,7 +273,7 @@ bool Scene::loadScene(const Common::String &filename) {
_bgShapes[idx]._sequences = &_sequenceBuffer[_bgShapes[idx]._sequenceOffset];
_bgShapes[idx]._misc = 0;
_bgShapes[idx]._seqCounter = 0;
- _bgShapes[idx]._seqcounter2 = 0;
+ _bgShapes[idx]._seqCounter2 = 0;
_bgShapes[idx]._seqStack = 0;
_bgShapes[idx]._frameNumber = -1;
_bgShapes[idx]._position = Common::Point(0, 0);
@@ -799,7 +836,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) {
Talk &talk = *_vm->_talk;
Common::Point tpPos, walkPos;
int tpDir, walkDir;
- int tFrames;
+ int tFrames = 0;
int gotoCode = -1;
// Validation
@@ -996,8 +1033,52 @@ int Scene::startCAnim(int cAnimNum, int playRate) {
return 1;
}
+/**
+ * Print the description of an object
+ */
void Scene::printObjDesc(const Common::String &str, bool firstTime) {
+ /* TODO
+
+ Events &events = *_vm->_events;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+ int savedSelector;
+
+ if (str.hasPrefix("_")) {
+ _lookScriptFlag = true;
+ events.setCursor(MAGNIFY);
+ savedSelector = _selector;
+ talk.talkTo(str.c_str() + 1);
+ _lookScriptFlag = false;
+
+ if (talk._talkToAbort) {
+ events.setCursor(ARROW);
+ return;
+ }
+
+ // Check if looking at an inventory object
+ if (!_invLookFlag) {
+ // See if this look was called by a right button click or not
+ if (!_lookHelp) {
+ // If it wasn't a right button click, then we need depress
+ // the look button before we close the window. So save a copy of the
+ // menu area, and draw the controls onto it
+ Surface tempSurface((*_controls)[0]._frame->w, (*_controls)[0]._frame->h);
+ tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
+ Common::Rect(MENU_POINTS[0][0], MENU_POINTS[0][1],
+ MENU_POINTS[0][0] + tempSurface.w, MENU_POINTS[0][1] + tempSurface.h));
+ screen._backBuffer2.transBlitFrom((*_controls)[0]._frame,
+ Common::Point(MENU_POINTS[0][0], MENU_POINTS[0][1]));
+
+ banishWindow(1);
+ events.setCursor(MAGNIFY);
+
+ }
+ }
+ }
+
// TODO
+ */
}
/**
@@ -1047,9 +1128,270 @@ void Scene::doBgAnim() {
if (_restoreFlag) {
if (people[AL]._type == CHARACTER)
people[AL].checkSprite();
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE)
+ _bgShapes[idx].checkObject(_bgShapes[idx]);
+ }
+
+ if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
+ people._portrait.checkObject(people._portrait);
+
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ if (_canimShapes[idx]._type != INVALID && _canimShapes[idx]._type != REMOVE)
+ _canimShapes[idx].checkObject(_bgShapes[0]);
+ }
+
+ if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel)
+ ((Scalpel::ScalpelEngine *)_vm)->eraseMirror12();
+
+ // Restore the back buffer from the back buffer 2 in the changed area
+ Common::Rect bounds(people[AL]._oldPosition.x, people[AL]._oldPosition.y,
+ people[AL]._oldPosition.x + people[AL]._oldSize.x,
+ people[AL]._oldPosition.y + people[AL]._oldSize.y);
+ Common::Point pt(bounds.left, bounds.top);
+
+ if (people[AL]._type == CHARACTER)
+ screen.restoreBackground(bounds);
+ else if (people[AL]._type == REMOVE)
+ screen._backBuffer.blitFrom(screen._backBuffer2, pt, bounds);
+
+ for (uint idx = 0; _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE)
+ screen.restoreBackground(bounds);
+ }
+
+ if (people._portraitLoaded)
+ screen.restoreBackground(Common::Rect(
+ people._portrait._oldPosition.x, people._portrait._oldPosition.y,
+ people._portrait._oldPosition.x + people._portrait._oldSize.x,
+ people._portrait._oldPosition.y + people._portrait._oldSize.y
+ ));
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == NO_SHAPE && ((o._flags & 1) == 0)) {
+ // Restore screen area
+ screen._backBuffer.blitFrom(screen._backBuffer2, o._position,
+ Common::Rect(o._position.x, o._position.y,
+ o._position.x + o._noShapeSize.x, o._position.y + o._noShapeSize.y));
+
+ o._oldPosition = o._position;
+ o._oldSize = o._noShapeSize;
+ }
+ }
+
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &o = _canimShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE)
+ screen.restoreBackground(Common::Rect(o._oldPosition.x, o._oldPosition.y,
+ o._oldPosition.x + o._oldSize.x, o._oldPosition.y + o._oldSize.y));
+ }
+ }
+
+ //
+ // Update the background objects and canimations
+ //
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE || o._type == NO_SHAPE)
+ o.adjustObject();
}
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ if (_canimShapes[idx]._type != INVALID)
+ _canimShapes[idx].adjustObject();
+ }
+
+ if (people[AL]._type == CHARACTER && people._holmesOn)
+ people[AL].adjustSprite();
+
+ // Flag the bg shapes which need to be redrawn
+ checkBgShapes(people[AL]._imageFrame,
+ Common::Point(people[AL]._position.x / 100, people[AL]._position.y / 100));
+
+ if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel)
+ ((Scalpel::ScalpelEngine *)_vm)->doMirror12();
+
+ // Draw all active shapes which are behind the person
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND)
+ screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
+ }
+
+ // Draw all canimations which are behind the person
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &o = _canimShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) {
+ screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
+ }
+ }
+
+ // Draw all active shapes which are HAPPEN and behind the person
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND)
+ screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
+ }
+
+ // Draw all canimations which are NORMAL and behind the person
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &o = _canimShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) {
+ screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
+ }
+ }
+
+ // Draw the person if not animating
+ if (people[AL]._type == CHARACTER && people.isHolmesActive()) {
+ // If Holmes is too far to the right, move him back so he's on-screen
+ int xRight = SHERLOCK_SCREEN_WIDTH - 2 - people[AL]._imageFrame->_frame.w;
+ int tempX = MIN(people[AL]._position.x / 100, xRight);
+
+ bool flipped = people[AL]._frameNumber == WALK_LEFT || people[AL]._frameNumber == STOP_LEFT ||
+ people[AL]._frameNumber == WALK_UPLEFT || people[AL]._frameNumber == STOP_UPLEFT ||
+ people[AL]._frameNumber == WALK_DOWNRIGHT || people[AL]._frameNumber == STOP_DOWNRIGHT;
+ screen._backBuffer.transBlitFrom(people[AL]._imageFrame->_frame,
+ Common::Point(tempX, people[AL]._position.y / 100 - people[AL]._imageFrame->_frame.h), flipped);
+ }
+
+ // Draw all static and active shapes are NORMAL and are in front of the person
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD)
+ screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
+ }
+
+ // Draw all static and active canimations that are NORMAL and are in front of the person
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &o = _canimShapes[idx];
+ if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_BEHIND) {
+ screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
+ }
+ }
+
+ // Draw all static and active shapes that are in front of the person
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD)
+ screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
+ }
+
+ // Draw any active portrait
+ if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
+ screen._backBuffer.transBlitFrom(people._portrait._imageFrame->_frame,
+ people._portrait._position, people._portrait._flags & 2);
+
+ // Draw all static and active canimations that are in front of the person
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &o = _canimShapes[idx];
+ if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) {
+ screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
+ }
+ }
+
+ // Draw all NO_SHAPE shapes which have flag bit 0 clear
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == NO_SHAPE && (o._flags & 1) == 0)
+ screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
+ }
+
+ // Bring the newly built picture to the screen
+ if (_animating == 2) {
+ _animating = 0;
+ screen.slamRect(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
+ } else {
+ if (people[AL]._type != INVALID && ((_goToRoom == -1 || _ongoingCans == 0))) {
+ if (people[AL]._type == REMOVE) {
+ screen.slamRect(Common::Rect(
+ people[AL]._oldPosition.x, people[AL]._oldPosition.y,
+ people[AL]._oldPosition.x + people[AL]._oldSize.x,
+ people[AL]._oldPosition.y + people[AL]._oldSize.y
+ ));
+ } else {
+ screen.flushImage(people[AL]._imageFrame,
+ Common::Point(people[AL]._position.x / 100, people[AL]._position.y / 100),
+ &people[AL]._oldPosition.x, &people[AL]._oldPosition.y,
+ &people[AL]._oldSize.x, &people[AL]._oldSize.y);
+ }
+ }
+
+ if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel)
+ ((Scalpel::ScalpelEngine *)_vm)->flushMirror12();
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if ((o._type == ACTIVE_BG_SHAPE || o._type == REMOVE) && _goToRoom == -1) {
+ screen.flushImage(o._imageFrame, o._position,
+ &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
+ }
+ }
+
+ if (people._portraitLoaded) {
+ if (people._portrait._type == REMOVE)
+ screen.slamRect(Common::Rect(
+ people._portrait._position.x, people._portrait._position.y,
+ people._portrait._position.x + people._portrait._delta.x,
+ people._portrait._position.y + people._portrait._delta.y
+ ));
+ else
+ screen.flushImage(people._portrait._imageFrame, people._portrait._position,
+ &people._portrait._oldPosition.x, &people._portrait._oldPosition.y,
+ &people._portrait._oldSize.x, &people._portrait._oldSize.y);
+
+ if (people._portrait._type == REMOVE)
+ people._portrait._type = INVALID;
+ }
+
+ if (_goToRoom == -1) {
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == NO_SHAPE && (o._flags & 1) == 0) {
+ screen.slamArea(o._position.x, o._position.y, o._oldSize.x, o._oldSize.y);
+ screen.slamArea(o._oldPosition.x, o._oldPosition.y, o._oldSize.x, o._oldSize.y);
+ } else if (o._type == HIDE_SHAPE) {
+ screen.flushImage(o._imageFrame, o._position,
+ &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
+ }
+ }
+ }
+
+ for (int idx = _canimShapes.size() - 1; idx >= 0; --idx) {
+ Object &o = _canimShapes[idx];
+ if (o._type == REMOVE) {
+ if (_goToRoom == -1)
+ screen.slamArea(o._position.x, o._position.y, o._delta.x, o._delta.y);
+
+ _canimShapes.remove_at(idx);
+ } else if (o._type == ACTIVE_BG_SHAPE) {
+ screen.flushImage(o._imageFrame, o._position,
+ &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
+ }
+ }
+ }
+
+ _restoreFlag = true;
+
+ events.wait(1);
+ _doBgAnimDone = true;
+
+ // Check if the method was called for calling a portrait, and a talk was
+ // interrupting it. This talk file would not have been executed at the time,
+ // since we needed to finish the 'doBgAnim' to finish clearing the portrait
+ if (people._clearingThePortrait && _vm->_scriptMoreFlag == 3) {
+ // Reset the flags and call to talk
+ people._clearingThePortrait = _vm->_scriptMoreFlag = 0;
+ talk.talkTo(_vm->_scriptName);
+ }
+}
+
+void Scene::clearInfo() {
// TODO
}
+
} // End of namespace Sherlock