diff options
author | Paul Gilbert | 2015-03-22 00:52:02 -0400 |
---|---|---|
committer | Paul Gilbert | 2015-03-22 00:52:02 -0400 |
commit | ff02c29e9c2f96ed7e36878163b4b22dc8822255 (patch) | |
tree | 27be9dbd3462943eb16e3558d1a4b087dc701346 /engines/sherlock | |
parent | 7f04ea4425bae0ebac7e51d71dc315b965bf94c9 (diff) | |
download | scummvm-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.cpp | 291 | ||||
-rw-r--r-- | engines/sherlock/objects.h | 6 | ||||
-rw-r--r-- | engines/sherlock/people.cpp | 2 | ||||
-rw-r--r-- | engines/sherlock/people.h | 3 | ||||
-rw-r--r-- | engines/sherlock/scalpel/scalpel.cpp | 21 | ||||
-rw-r--r-- | engines/sherlock/scalpel/scalpel.h | 4 | ||||
-rw-r--r-- | engines/sherlock/scene.cpp | 348 | ||||
-rw-r--r-- | engines/sherlock/scene.h | 20 | ||||
-rw-r--r-- | engines/sherlock/screen.cpp | 63 | ||||
-rw-r--r-- | engines/sherlock/screen.h | 12 | ||||
-rw-r--r-- | engines/sherlock/sherlock.cpp | 3 | ||||
-rw-r--r-- | engines/sherlock/sherlock.h | 4 |
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(); |