aboutsummaryrefslogtreecommitdiff
path: root/engines/sherlock
diff options
context:
space:
mode:
authorPaul Gilbert2015-03-22 00:52:02 -0400
committerPaul Gilbert2015-03-22 00:52:02 -0400
commitff02c29e9c2f96ed7e36878163b4b22dc8822255 (patch)
tree27be9dbd3462943eb16e3558d1a4b087dc701346 /engines/sherlock
parent7f04ea4425bae0ebac7e51d71dc315b965bf94c9 (diff)
downloadscummvm-rg350-ff02c29e9c2f96ed7e36878163b4b22dc8822255.tar.gz
scummvm-rg350-ff02c29e9c2f96ed7e36878163b4b22dc8822255.tar.bz2
scummvm-rg350-ff02c29e9c2f96ed7e36878163b4b22dc8822255.zip
SHERLOCK: Implemented doBgAnim
Diffstat (limited to 'engines/sherlock')
-rw-r--r--engines/sherlock/objects.cpp291
-rw-r--r--engines/sherlock/objects.h6
-rw-r--r--engines/sherlock/people.cpp2
-rw-r--r--engines/sherlock/people.h3
-rw-r--r--engines/sherlock/scalpel/scalpel.cpp21
-rw-r--r--engines/sherlock/scalpel/scalpel.h4
-rw-r--r--engines/sherlock/scene.cpp348
-rw-r--r--engines/sherlock/scene.h20
-rw-r--r--engines/sherlock/screen.cpp63
-rw-r--r--engines/sherlock/screen.h12
-rw-r--r--engines/sherlock/sherlock.cpp3
-rw-r--r--engines/sherlock/sherlock.h4
12 files changed, 751 insertions, 26 deletions
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 5a93ce6869..6b681b42e9 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -28,6 +28,8 @@
namespace Sherlock {
+#define START_FRAME 0
+
#define UPPER_LIMIT 0
#define LOWER_LIMIT CONTROLS_Y
#define LEFT_LIMIT 0
@@ -37,6 +39,10 @@ namespace Sherlock {
#define CLEAR_DIST_X 5
#define CLEAR_DIST_Y 0
+#define INFO_FOREGROUND 11
+#define INFO_BACKGROUND 1
+
+
SherlockEngine *Sprite::_vm;
/**
@@ -83,7 +89,7 @@ void Sprite::adjustSprite() {
Scene &scene = *_vm->_scene;
Talk &talk = *_vm->_talk;
- if (_type == INVALID || (_type == CHARACTER && _vm->_animating))
+ if (_type == INVALID || (_type == CHARACTER && scene._animating))
return;
if (!talk._talkCounter && _type == CHARACTER && _walkCount) {
@@ -457,7 +463,7 @@ void Object::synchronize(Common::SeekableReadStream &s) {
_seqStack = s.readByte();
_seqTo = s.readByte();
_descOffset = s.readUint16LE();
- _seqcounter2 = s.readByte();
+ _seqCounter2 = s.readByte();
_seqSize = s.readUint16LE();
s.skip(1);
_aMove.synchronize(s);
@@ -487,7 +493,7 @@ void Object::toggleHidden() {
_sequences[_frameNumber] = _seqTo + SEQ_TO_CODE + 128;
_seqTo = 0;
- _seqCounter = _seqcounter2 = 0;
+ _seqCounter = _seqCounter2 = 0;
_seqStack = 0;
_frameNumber = -1;
@@ -544,7 +550,7 @@ void Object::checkObject(Object &o) {
if (v >= 228) {
// Goto code found
v -= 228;
- _seqcounter2 = _seqCounter;
+ _seqCounter2 = _seqCounter;
_seqStack = _frameNumber + 1;
setObjSequence(v, false);
} else if (v >= SOUND_CODE && (v <= (SOUND_CODE + 29))) {
@@ -631,29 +637,290 @@ void Object::checkObject(Object &o) {
} while (codeFound);
}
-bool Object::checkEndOfSequence() const {
- // TODO
- return false;
+/**
+ * This will check to see if the object has reached the end of a sequence.
+ * If it has, it switch to whichever next sequence should be started.
+ * @returns true if the end of a sequence was reached
+ */
+bool Object::checkEndOfSequence() {
+ Screen &screen = *_vm->_screen;
+ int checkFrame = _allow ? MAX_FRAME : 32000;
+ bool result = false;
+
+ if (_type == REMOVE || _type == INVALID)
+ return false;
+
+ if (_sequences[_frameNumber] == 0 || _frameNumber >= checkFrame) {
+ result = true;
+
+ if (_frameNumber >= (checkFrame - 1)) {
+ _frameNumber = START_FRAME;
+ } else {
+ // Determine next sequence to use
+ int seq = _sequences[_frameNumber + 1];
+
+ if (seq == 99) {
+ --_frameNumber;
+ screen._backBuffer.transBlitFrom(_imageFrame->_frame, _position);
+ screen._backBuffer2.transBlitFrom(_imageFrame->_frame, _position);
+ _type = INVALID;
+ } else {
+ setObjSequence(seq, false);
+ }
+ }
+ }
+
+ if (_allow && _frameNumber == 0) {
+ // canimation just ended
+ if (_type != NO_SHAPE && _type != REMOVE) {
+ _type = REMOVE;
+
+ if (!_countCAnimFrames) {
+ // Save details before shape is removed
+ _delta.x = _imageFrame->_frame.w;
+ _delta.y = _imageFrame->_frame.h;
+ _position = _imageFrame->_offset;
+
+ // Free the images
+ delete _images;
+ }
+ } else {
+ _type = INVALID;
+ }
+ }
+
+ return result;
}
+/**
+ * Scans through the sequences array and finds the designated sequence.
+ * It then sets the frame number of the start of that sequence
+ */
void Object::setObjSequence(int seq, bool wait) {
- // TODO
+ Scene &scene = *_vm->_scene;
+ int checkFrame = _allow ? MAX_FRAME : 32000;
+
+ if (seq >= 128) {
+ // Loop the sequence until the count exceeded
+ seq -= 128;
+
+ ++_seqCounter;
+ if (_seqCounter >= seq) {
+ // Go to next sequence
+ if (_seqStack) {
+ _frameNumber = _seqStack;
+ _seqStack = 0;
+ _seqCounter = _seqCounter2;
+ _seqCounter2 = 0;
+ if (_frameNumber >= checkFrame)
+ _frameNumber = START_FRAME;
+
+ return;
+ }
+
+ _frameNumber += 2;
+ if (_frameNumber >= checkFrame)
+ _frameNumber = 0;
+
+ _seqCounter = 0;
+ if (_sequences[_frameNumber] == 0)
+ seq = _sequences[_frameNumber + 1];
+ else
+ return;
+ } else {
+ // Find beginning of sequence
+ do {
+ --_frameNumber;
+ } while (_frameNumber > 0 && _sequences[_frameNumber] != 0);
+
+ if (_frameNumber != 0)
+ _frameNumber += 2;
+
+ return;
+ }
+ } else {
+ // Reset sequence counter
+ _seqCounter = 0;
+ }
+
+ int idx = 0;
+ int seqCc = 0;
+
+ while (seqCc < seq && idx < checkFrame) {
+ ++idx;
+ if (_sequences[idx] == 0) {
+ ++seqCc;
+ idx += 2;
+ }
+ }
+
+ if (idx >= checkFrame)
+ idx = 0;
+ _frameNumber = idx;
+
+ if (wait) {
+ seqCc = idx;
+ while (_sequences[idx] != 0)
+ ++idx;
+
+ idx = idx - seqCc + 2;
+ for (; idx > 0; --idx)
+ scene.doBgAnim();
+ }
}
/**
* Checks for codes
* @param name The name to check for codes
-* @param messages If provided, any messages to be returned
+* @param messages Provides a lookup list of messages that can be printed
* @returns 0 if no codes are found, 1 if codes were found
*/
int Object::checkNameForCodes(const Common::String &name, Common::StringArray *messages) {
+ People &people = *_vm->_people;
+ Scene &scene = *_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+ bool printed = false;
+ char ch;
+ const char *p;
+
+ scene.toggleObject(name);
+
+ if (name.hasPrefix("*")) {
+ // A code was found
+ printed = true;
+ ch = toupper(name[1]);
+
+ switch (ch) {
+ case 'C':
+ talk.talkTo(name.c_str() + 2);
+ break;
+
+ case 'T':
+ case 'B':
+ case 'F':
+ case 'W':
+ // Nothing: action was already done before canimation
+ break;
+
+ case 'G':
+ case 'A': {
+ // G: Have object go somewhere
+ // A: Add onto existing co-ordinates
+ Common::String sx(name.c_str() + 2, name.c_str() + 5);
+ Common::String sy(name.c_str() + 6, name.c_str() + 9);
+
+ if (ch == 'G')
+ _position = Common::Point(atoi(sx.c_str()), atoi(sy.c_str()));
+ else
+ _position += Common::Point(atoi(sx.c_str()), atoi(sy.c_str()));
+ break;
+ }
+
+ default:
+ if (ch >= '0' && ch <= '9') {
+ scene._goToRoom = atoi(name.c_str() + 1);
+
+ if (scene._goToRoom < 97 && _vm->_map[scene._goToRoom].x) {
+ _vm->_over.x = _vm->_map[scene._goToRoom].x * 100 - 600;
+ _vm->_over.y = _vm->_map[scene._goToRoom].y * 100 + 900;
+ }
+
+ if ((p = strchr(name.c_str(), ',')) != nullptr) {
+ ++p;
+
+ Common::String s(p, p + 3);
+ scene._hsavedPos.x = atoi(s.c_str());
+
+ s = Common::String(p + 3, p + 6);
+ scene._hsavedPos.y = atoi(s.c_str());
+
+ s = Common::String(p + 6, p + 9);
+ scene._hsavedFs = atoi(s.c_str());
+ if (scene._hsavedFs == 0)
+ scene._hsavedFs = 10;
+ } else if ((p = strchr(name.c_str(), '/')) != nullptr) {
+ scene._hsavedPos = Common::Point(1, 0);
+ scene._hsavedFs = 100 + atoi(p + 1);
+ }
+ } else {
+ scene._goToRoom = 100;
+ }
+
+ people[AL]._position = Common::Point(0, 0);
+ break;
+ }
+ } else if (name.hasPrefix("!")) {
+ // Message attached to canimation
+ int messageNum = atoi(name.c_str() + 1);
+ scene._infoFlag++;
+ scene.clearInfo();
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND,
+ (*messages)[messageNum].c_str());
+ _vm->_menuCounter = 25;
+ } else if (name.hasPrefix("@")) {
+ // Message attached to canimation
+ scene._infoFlag++;
+ scene.clearInfo();
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND,
+ "%s", name.c_str() + 1);
+ printed = true;
+ _vm->_menuCounter = 25;
+ }
- // TODO
- return 0;
+ return printed;
}
+/**
+ * Handle setting any flags associated with the object
+ */
void Object::setFlagsAndToggles() {
- // TODO
+ Scene &scene = *_vm->_scene;
+ Talk &talk = *_vm->_talk;
+
+ for (int useIdx = 0; useIdx < 4; ++useIdx) {
+ if (_use[useIdx]._useFlag) {
+ if (!_vm->readFlags(_use[useIdx]._useFlag))
+ _vm->setFlags(_use[useIdx]._useFlag);
+ }
+
+ if (_use[useIdx]._cAnimSpeed) {
+ if (_use[useIdx]._cAnimNum == 0)
+ // 0 is really a 10
+ scene.startCAnim(_use[useIdx]._cAnimNum - 1, _use[useIdx]._cAnimSpeed);
+ }
+
+ if (!talk._talkToAbort) {
+ for (int idx = 0; idx < 4; ++idx)
+ scene.toggleObject(_use[useIdx]._names[idx]);
+ }
+ }
+}
+
+/**
+ * Adjusts the sprite's position and animation sequence, advancing by 1 frame.
+ * If the end of the sequence is reached, the appropriate action is taken.
+ */
+void Object::adjustObject() {
+ if (_type == REMOVE)
+ return;
+
+ _position += _delta;
+
+ if (_position.y > LOWER_LIMIT)
+ _position.y = LOWER_LIMIT;
+
+ if (_type != NO_SHAPE) {
+ int frame = _frameNumber;
+ if (frame == -1)
+ frame = 0;
+
+ int imgNum = _sequences[frame];
+ if (imgNum > _maxFrames)
+ imgNum = 1;
+
+ _imageFrame = &(*_images)[imgNum - 1];
+ }
}
/*----------------------------------------------------------------*/
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index d099718d5b..ee82faf99c 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -143,7 +143,7 @@ class Object {
private:
static SherlockEngine *_vm;
- bool checkEndOfSequence() const;
+ bool checkEndOfSequence();
void setObjSequence(int seq, bool wait);
public:
@@ -190,7 +190,7 @@ public:
int _seqStack; // Allows gosubs to return to calling frame
int _seqTo; // Allows 1-5, 8-3 type sequences encoded in 2 bytes
uint _descOffset; // Tells where description starts in DescText
- int _seqcounter2; // Counter of calling frame sequence
+ int _seqCounter2; // Counter of calling frame sequence
uint _seqSize; // Tells where description starts
ActionType _aMove;
UseType _use[4];
@@ -204,6 +204,8 @@ public:
int checkNameForCodes(const Common::String &name, Common::StringArray *messages);
void setFlagsAndToggles();
+
+ void adjustObject();
};
struct CAnim {
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index 43d3422f1a..d2fbb3d8c5 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -56,6 +56,8 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) {
_holmesOn = true;
_oldWalkSequence = -1;
_allowWalkAbort = false;
+ _portraitLoaded = false;
+ _clearingThePortrait = false;
}
People::~People() {
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index d2d7e92512..7c218671c9 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -64,6 +64,9 @@ public:
Common::Point _walkDest;
Common::Stack<Common::Point> _walkTo;
bool _holmesOn;
+ bool _portraitLoaded;
+ Object _portrait;
+ bool _clearingThePortrait;
public:
People(SherlockEngine *vm);
~People();
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index bb9c6c0bc2..1fe1901212 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -336,6 +336,27 @@ void ScalpelEngine::startScene() {
_chessResult = _scene->_goToRoom;
}
+/**
+ * Takes care of clearing the mirror in scene 12, in case anything drew over it
+ */
+void ScalpelEngine::eraseMirror12() {
+ // TODO
+}
+
+/**
+ * Takes care of drawing Holme's reflection onto the mirror in scene 12
+ */
+void ScalpelEngine::doMirror12() {
+ // TODO
+}
+
+/**
+ * This clears the mirror in scene 12 in case anything messed draw over it
+ */
+void ScalpelEngine::flushMirror12() {
+ // TODO
+}
+
} // End of namespace Scalpel
} // End of namespace Scalpel
diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h
index b096599ee1..2d5deeb882 100644
--- a/engines/sherlock/scalpel/scalpel.h
+++ b/engines/sherlock/scalpel/scalpel.h
@@ -51,6 +51,10 @@ protected:
public:
ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
virtual ~ScalpelEngine();
+
+ void eraseMirror12();
+ void doMirror12();
+ void flushMirror12();
};
} // End of namespace Scalpel
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
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index f48d45c34e..4b76739402 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -116,6 +116,10 @@ private:
Common::String _cAnimStr;
MenuMode _menuMode;
InvMode _invMode;
+ bool _lookScriptFlag;
+ int _selector;
+ bool _invLookFlag;
+ bool _lookHelp;
bool loadScene(const Common::String &filename);
@@ -125,15 +129,9 @@ private:
void transitionToScene();
- int toggleObject(const Common::String &name);
-
void updateBackground();
void checkBgShapes(ImageFrame *frame, const Common::Point &pt);
-
- int startCAnim(int cAnimNum, int playRate);
-
- void doBgAnim();
public:
int _currentScene;
int _goToRoom;
@@ -170,6 +168,8 @@ public:
int _hsavedFs;
Common::Array<Object> _canimShapes;
bool _restoreFlag;
+ int _animating;
+ bool _doBgAnimDone;
public:
Scene(SherlockEngine *vm);
~Scene();
@@ -183,6 +183,14 @@ public:
Exit *checkForExit(const Common::Rect &r);
void printObjDesc(const Common::String &str, bool firstTime);
+
+ int startCAnim(int cAnimNum, int playRate);
+
+ int toggleObject(const Common::String &name);
+
+ void doBgAnim();
+
+ void clearInfo();
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index e6c11b8cf4..f8f1d56e67 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -231,4 +231,67 @@ void Screen::verticalTransition() {
}
}
+/**
+ * Prints the text passed onto the back buffer at the given position and color.
+ * The string is then blitted to the screen
+ */
+void Screen::print(const Common::Point &pt, int fgColor, int bgColor, const char *format, ...) {
+ // TODO
+}
+
+/**
+ * Copies a section of the second back buffer into the main back buffer
+ */
+void Screen::restoreBackground(const Common::Rect &r) {
+ Common::Rect tempRect = r;
+ tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
+
+ if (tempRect.isValidRect())
+ _backBuffer.blitFrom(_backBuffer2, Common::Point(tempRect.left, tempRect.top), tempRect);
+}
+
+/**
+ * Copies a given area to the screen
+ */
+void Screen::slamArea(int16 xp, int16 yp, int16 w, int16 h) {
+ slamRect(Common::Rect(xp, yp, xp + w, yp + h));
+}
+
+/**
+ * Copies a given area to the screen
+ */
+void Screen::slamRect(const Common::Rect &r) {
+ Common::Rect tempRect = r;
+ tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+
+ if (tempRect.isValidRect())
+ blitFrom(_backBuffer, Common::Point(tempRect.left, tempRect.top), tempRect);
+}
+
+/**
+ * Copy an image from the back buffer to the screen, taking care of both the
+ * new area covered by the shape as well as the old area, which must be restored
+ */
+void Screen::flushImage(ImageFrame *frame, const Common::Point &pt,
+ int16 *xp, int16 *yp, int16 *w, int16 *h) {
+ Common::Point imgPos = pt + frame->_offset;
+ Common::Rect newBounds(imgPos.x, imgPos.y, imgPos.x + frame->_frame.w, imgPos.y + frame->_frame.h);
+ Common::Rect oldBounds(*xp, *yp, *xp + *w, *yp + *h);
+
+ // See if the areas of the old and new overlap, and if so combine the areas
+ if (newBounds.intersects(oldBounds)) {
+ newBounds.extend(oldBounds);
+ slamRect(newBounds);
+ } else {
+ // The two areas are independent, so copy them both
+ slamRect(newBounds);
+ slamRect(oldBounds);
+ }
+
+ *xp = newBounds.left;
+ *yp = newBounds.top;
+ *w = newBounds.width();
+ *h = newBounds.height();
+}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index 2c5e585475..87453ba36d 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -26,8 +26,8 @@
#include "common/list.h"
#include "common/rect.h"
#include "graphics/surface.h"
-
#include "sherlock/graphics.h"
+#include "sherlock/resources.h"
namespace Sherlock {
@@ -75,6 +75,16 @@ public:
void randomTransition();
void verticalTransition();
+
+ void print(const Common::Point &pt, int fgColor, int bgColor, const char *format, ...);
+
+ void restoreBackground(const Common::Rect &r);
+
+ void slamArea(int16 xp, int16 yp, int16 w, int16 h);
+ void slamRect(const Common::Rect &r);
+
+ void flushImage(ImageFrame *frame, const Common::Point &pt,
+ int16 *xp, int16 *yp, int16 *w, int16 *h);
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp
index 637660e001..330da6075b 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -45,7 +45,8 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam
_justLoaded = false;
_onChessboard = false;
_slowChess = false;
- _animating = false;
+ _menuCounter = 0;
+ _scriptMoreFlag = 0;
}
SherlockEngine::~SherlockEngine() {
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index 1c95b10ff3..92aee9cdc3 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -98,7 +98,9 @@ public:
Common::Array<Common::Point> _map; // Map locations for each scene
bool _onChessboard;
bool _slowChess;
- bool _animating;
+ int _menuCounter;
+ int _scriptMoreFlag;
+ Common::String _scriptName;
public:
SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
virtual ~SherlockEngine();