From 40a3a3b8353924b7bec4237d622e6ddddaf2aef8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 11 Jun 2015 08:32:31 -0400 Subject: SHERLOCK: RT map display partially working --- engines/sherlock/fonts.cpp | 8 +- engines/sherlock/fonts.h | 2 +- engines/sherlock/music.cpp | 6 + engines/sherlock/music.h | 25 +-- engines/sherlock/scalpel/darts.cpp | 6 +- engines/sherlock/scalpel/darts.h | 6 - engines/sherlock/scene.cpp | 32 ---- engines/sherlock/scene.h | 11 -- engines/sherlock/screen.h | 3 +- engines/sherlock/sherlock.cpp | 6 +- engines/sherlock/sherlock.h | 8 +- engines/sherlock/sound.cpp | 5 - engines/sherlock/sound.h | 2 - engines/sherlock/surface.cpp | 2 - engines/sherlock/surface.h | 1 + engines/sherlock/tattoo/tattoo_map.cpp | 265 +++++++++++++++++++++++++++---- engines/sherlock/tattoo/tattoo_map.h | 15 +- engines/sherlock/tattoo/tattoo_scene.cpp | 32 ++++ engines/sherlock/tattoo/tattoo_scene.h | 11 ++ 19 files changed, 331 insertions(+), 115 deletions(-) (limited to 'engines/sherlock') diff --git a/engines/sherlock/fonts.cpp b/engines/sherlock/fonts.cpp index 8c3abb7189..a9436e36c5 100644 --- a/engines/sherlock/fonts.cpp +++ b/engines/sherlock/fonts.cpp @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * + *F */ #include "common/system.h" @@ -42,13 +42,13 @@ void Fonts::free() { delete _font; } -void Fonts::setFont(int fontNumber) { - _fontNumber = fontNumber; +void Fonts::setFont(int fontNum) { + _fontNumber = fontNum; if (_platform == Common::kPlatform3DO) return; - Common::String fname = Common::String::format("FONT%d.VGS", fontNumber + 1); + Common::String fname = Common::String::format("FONT%d.VGS", fontNum + 1); // Discard any previous font and read in new one delete _font; diff --git a/engines/sherlock/fonts.h b/engines/sherlock/fonts.h index 1013807e4c..0df427ff9c 100644 --- a/engines/sherlock/fonts.h +++ b/engines/sherlock/fonts.h @@ -56,7 +56,7 @@ public: /** * Set the font to use for writing text on the screen */ - void setFont(int fontNumber); + void setFont(int fontNum); /** * Returns the width of a string in pixels diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp index 23ce07aa6f..1d4c6e08ee 100644 --- a/engines/sherlock/music.cpp +++ b/engines/sherlock/music.cpp @@ -197,6 +197,8 @@ Music::Music(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { _musicType = MT_NULL; _musicPlaying = false; _musicOn = false; + _midiOption = false; + _musicVolume = 0; _midiMusicData = NULL; _midiMusicDataSize = 0; @@ -544,4 +546,8 @@ bool Music::waitUntilMSec(uint32 msecTarget, uint32 msecMax, uint32 additionalDe } } +void Music::setMIDIVolume(int volume) { + warning("TODO: Music::setMIDIVolume"); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/music.h b/engines/sherlock/music.h index 1e2b91a603..04b9dbd98e 100644 --- a/engines/sherlock/music.h +++ b/engines/sherlock/music.h @@ -53,28 +53,24 @@ public: }; class Music { -public: - Music(SherlockEngine *vm, Audio::Mixer *mixer); - ~Music(); - private: SherlockEngine *_vm; Audio::Mixer *_mixer; MidiParser_SH *_midiParser; MidiDriver *_midiDriver; Audio::SoundHandle _digitalMusicHandle; - -public: - bool _musicPlaying; - bool _musicOn; - -private: MusicType _musicType; - byte *_midiMusicData; int32 _midiMusicDataSize; - public: + bool _musicPlaying; + bool _musicOn; + int _musicVolume; + bool _midiOption; +public: + Music(SherlockEngine *vm, Audio::Mixer *mixer); + ~Music(); + /** * Saves sound-related settings */ @@ -118,6 +114,11 @@ public: bool waitUntilTick(uint32 tick, uint32 maxTick, uint32 additionalDelay, uint32 noMusicDelay); bool waitUntilMSec(uint32 msecTarget, uint32 maxMSec, uint32 additionalDelay, uint32 noMusicDelay); + + /** + * Sets the volume of the MIDI music with a value ranging from 0 to 127 + */ + void setMIDIVolume(int volume); }; } // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/darts.cpp b/engines/sherlock/scalpel/darts.cpp index cdd3915241..04e4de80f1 100644 --- a/engines/sherlock/scalpel/darts.cpp +++ b/engines/sherlock/scalpel/darts.cpp @@ -117,7 +117,7 @@ void Darts::playDarts() { if (playerNumber == 0) { screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 30), PLAYER_COLOR, "Holmes Wins!"); if (_level < OPPONENTS_COUNT) - setFlagsForDarts(318 + _level); + _vm->setFlagsDirect(318 + _level); } else { screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 30), PLAYER_COLOR, "%s Wins!", _opponent.c_str()); } @@ -548,10 +548,6 @@ bool Darts::findNumberOnBoard(int aim, Common::Point &pt) { return done; } -void Darts::setFlagsForDarts(int flagNum) { - _vm->_flags[ABS(flagNum)] = flagNum >= 0; -} - } // End of namespace Scalpel } // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/darts.h b/engines/sherlock/scalpel/darts.h index d5ea07d444..4368954814 100644 --- a/engines/sherlock/scalpel/darts.h +++ b/engines/sherlock/scalpel/darts.h @@ -114,12 +114,6 @@ private: * Returns the center position for the area of the dartboard with a given number */ bool findNumberOnBoard(int aim, Common::Point &pt); - - /** - * Set a global flag to 0 or 1 depending on whether the passed flag is negative or positive. - * @remarks We don't use the global setFlags method because we don't want to check scene flags - */ - void setFlagsForDarts(int flagNum); public: Darts(ScalpelEngine *vm); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 9100d58e13..c16d1f208b 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -266,8 +266,6 @@ bool Scene::loadScene(const Common::String &filename) { Resources &res = *_vm->_res; SaveManager &saves = *_vm->_saves; Screen &screen = *_vm->_screen; - Sound &sound = *_vm->_sound; - Talk &talk = *_vm->_talk; UserInterface &ui = *_vm->_ui; bool flag; @@ -283,36 +281,6 @@ bool Scene::loadScene(const Common::String &filename) { _cAnim.clear(); _sequenceBuffer.clear(); - // Check if it's a scene we need to keep trakc track of how many times we've visited - for (int idx = (int)_sceneTripCounters.size() - 1; idx >= 0; --idx) { - if (_sceneTripCounters[idx]._sceneNumber == _currentScene) { - if (--_sceneTripCounters[idx]._numTimes == 0) { - _vm->setFlags(_sceneTripCounters[idx]._flag); - _sceneTripCounters.remove_at(idx); - } - } - } - - if (IS_ROSE_TATTOO) { - // Set the NPC paths for the scene - setNPCPath(0); - - // Handle loading music for the scene - if (sound._midiDrvLoaded) { - if (talk._scriptMoreFlag != 1 && talk._scriptMoreFlag != 3) - sound._nextSongName = Common::String::format("res%02d", _currentScene); - - // If it's a new song, then start it up - if (sound._currentSongName.compareToIgnoreCase(sound._nextSongName)) { - if (music.loadSong(sound._nextSongName)) { - sound.setMIDIVolume(sound._musicVolume); - if (music._musicOn) - music.startSong(); - } - } - } - } - // // Load the room resource file for the scene // diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index ab636f7b73..b8b2d2c9b6 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -127,16 +127,6 @@ public: void load(Common::SeekableReadStream &s); }; -struct SceneTripEntry { - bool _flag; - int _sceneNumber; - int _numTimes; - - SceneTripEntry() : _flag(false), _sceneNumber(0), _numTimes(0) {} - SceneTripEntry(bool flag, int sceneNumber, int numTimes) : _flag(flag), - _sceneNumber(sceneNumber), _numTimes(numTimes) {} -}; - class Scene { private: bool _loadingSavedGame; @@ -232,7 +222,6 @@ public: bool _doBgAnimDone; int _tempFadeStyle; int _cAnimFramePause; - Common::Array _sceneTripCounters; public: static Scene *init(SherlockEngine *vm); virtual ~Scene(); diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index c660fefe8c..02c09be629 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -53,8 +53,7 @@ enum { BUTTON_BOTTOM = 248, TALK_FOREGROUND = 12, TALK_NULL = 16, - PEN_COLOR = 250, - MAP_NAME_COLOR = 131 + PEN_COLOR = 250 }; class SherlockEngine; diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 5e2e25fdc1..a7214aae2e 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -59,11 +59,11 @@ SherlockEngine::~SherlockEngine() { delete _events; delete _journal; delete _map; - delete _music; delete _people; delete _saves; delete _scene; delete _screen; + delete _music; delete _sound; delete _talk; delete _ui; @@ -207,6 +207,10 @@ void SherlockEngine::setFlags(int flagNum) { _scene->checkSceneFlags(true); } +void SherlockEngine::setFlagsDirect(int flagNum) { + _flags[ABS(flagNum)] = flagNum >= 0; +} + void SherlockEngine::loadConfig() { // Load sound settings syncSoundSettings(); diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 6ed1ef579f..ad840a6dcf 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -66,7 +66,7 @@ enum GameType { #define SHERLOCK_SCREEN_HEIGHT _vm->_screen->h() #define SHERLOCK_SCENE_HEIGHT (IS_SERRATED_SCALPEL ? 138 : 480) // TODO: Is this the correct scene count for The Case of the Rose Tattoo? -#define SCENES_COUNT (IS_SERRATED_SCALPEL ? 63 : 99) +#define SCENES_COUNT (IS_SERRATED_SCALPEL ? 63 : 101) struct SherlockGameDescription; @@ -199,6 +199,12 @@ public: */ void setFlags(int flagNum); + /** + * Set a global flag to 0 or 1 depending on whether the passed flag is negative or positive. + * @remarks We don't use the global setFlags method because we don't want to check scene flags + */ + void setFlagsDirect(int flagNum); + /** * Saves game configuration information */ diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index bc5f87b48c..16e9b29f85 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -61,7 +61,6 @@ Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { _curPriority = 0; _digiBuf = nullptr; _midiDrvLoaded = false; - _musicVolume = 0; _soundOn = true; _speechOn = true; @@ -246,9 +245,5 @@ void Sound::freeDigiSound() { _soundPlaying = false; } -void Sound::setMIDIVolume(int volume) { - // TODO -} - } // End of namespace Sherlock diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index e1c0777763..9dd2edb9ce 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -58,7 +58,6 @@ public: byte *_digiBuf; bool _midiDrvLoaded; Common::String _currentSongName, _nextSongName; - int _musicVolume; public: Sound(SherlockEngine *vm, Audio::Mixer *mixer); @@ -94,7 +93,6 @@ public: void stopSndFuncPtr(int v1, int v2); void freeDigiSound(); - void setMIDIVolume(int volume); }; } // End of namespace Sherlock diff --git a/engines/sherlock/surface.cpp b/engines/sherlock/surface.cpp index 436227eda2..3005c815ed 100644 --- a/engines/sherlock/surface.cpp +++ b/engines/sherlock/surface.cpp @@ -28,8 +28,6 @@ namespace Sherlock { -const int TRANSPARENCY = 0xFF; - Surface::Surface(uint16 width, uint16 height, Common::Platform platform) : Fonts(), _freePixels(true) { create(width, height, platform); } diff --git a/engines/sherlock/surface.h b/engines/sherlock/surface.h index 49726d55fa..4e9300b0a3 100644 --- a/engines/sherlock/surface.h +++ b/engines/sherlock/surface.h @@ -31,6 +31,7 @@ namespace Sherlock { #define SCALE_THRESHOLD 0x100 +#define TRANSPARENCY 255 struct ImageFrame; diff --git a/engines/sherlock/tattoo/tattoo_map.cpp b/engines/sherlock/tattoo/tattoo_map.cpp index 57c10ca86d..6a09477c89 100644 --- a/engines/sherlock/tattoo/tattoo_map.cpp +++ b/engines/sherlock/tattoo/tattoo_map.cpp @@ -21,12 +21,19 @@ */ #include "sherlock/tattoo/tattoo_map.h" -#include "sherlock/sherlock.h" +#include "sherlock/tattoo/tattoo_scene.h" +#include "sherlock/tattoo/tattoo.h" namespace Sherlock { namespace Tattoo { +#define MAP_NAME_COLOR 131 +#define CLOSEUP_STEPS 30 +#define SCROLL_SPEED 16 + +/*-------------------------------------------------------------------------*/ + void MapEntry::clear() { _iconNum = -1; _description = ""; @@ -43,8 +50,189 @@ TattooMap::TattooMap(SherlockEngine *vm) : Map(vm) { } int TattooMap::show() { - // TODO - return 61; + Events &events = *_vm->_events; + Music &music = *_vm->_music; + Resources &res = *_vm->_res; + TattooScene &scene = *(TattooScene *)_vm->_scene; + Screen &screen = *_vm->_screen; + int result = 0; + + // Check if we need to keep track of how many times player has been to the map + for (uint idx = 0; idx < scene._sceneTripCounters.size(); ++idx) { + SceneTripEntry &entry = scene._sceneTripCounters[idx]; + + if (entry._sceneNumber == OVERHEAD_MAP || entry._sceneNumber == OVERHEAD_MAP2) { + if (--entry._numTimes == 0) { + _vm->setFlagsDirect(entry._flag); + scene._sceneTripCounters.remove_at(idx); + } + } + } + + if (music._midiOption) { + // See if Holmes or Watson is the active character + Common::String song; + if (_vm->readFlags(76)) + // Player is Holmes + song = "Cue9"; + else if (_vm->readFlags(525)) + song = "Cue8"; + else + song = "Cue7"; + + if (music.loadSong(song)) { + music.setMIDIVolume(music._musicVolume); + if (music._musicOn) + music.startSong(); + } + } + + screen.initPaletteFade(1364485); + + // Load the custom mouse cursors for the map + ImageFile cursors("omouse.vgs"); + events.setCursor(cursors[0]._frame); + + // Load the data for the map + _iconImages = new ImageFile("mapicons.vgs"); + loadData(); + + // Load the palette + Common::SeekableReadStream *stream = res.load("map.pal"); + stream->read(screen._cMap, PALETTE_SIZE); + screen.translatePalette(screen._cMap); + delete stream; + + // Load the map image and draw it to the back buffer + ImageFile *map = new ImageFile("map.vgs"); + screen._backBuffer1.create(SHERLOCK_SCREEN_WIDTH * 2, SHERLOCK_SCREEN_HEIGHT * 2, _vm->getPlatform()); + screen._backBuffer1.blitFrom((*map)[0], Common::Point(0, 0)); + delete map; + + screen.clear(); + screen.setPalette(screen._cMap); + drawMapIcons(); + + // Copy the map drawn in the back buffer to the secondary back buffer + screen._backBuffer2.create(SHERLOCK_SCREEN_WIDTH * 2, SHERLOCK_SCREEN_HEIGHT * 2, _vm->getPlatform()); + screen._backBuffer2.blitFrom(screen._backBuffer1); + + // Display the built map to the screen + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + + // Set text display positioning and scroll position + _oldTextBounds.left = _oldTextBounds.top = _oldTextBounds.right = _oldTextBounds.bottom = 0; + _textBounds.left = _textBounds.top = _textBounds.right = _textBounds.bottom = 0; + _currentScroll = _targetScroll = _bigPos; + + do { + // Allow for event processing and get the current mouse position + events.pollEventsAndWait(); + Common::Point mousePos = events.mousePos(); + + checkMapNames(true); + + if (mousePos.x < (SHERLOCK_SCREEN_WIDTH / 6)) + _targetScroll.x -= 2 * SCROLL_SPEED * (SHERLOCK_SCREEN_WIDTH / 6 - mousePos.x) / (SHERLOCK_SCREEN_WIDTH / 6); + if (mousePos.x > (SHERLOCK_SCREEN_WIDTH * 5 / 6)) + _targetScroll.x += 2 * SCROLL_SPEED * (mousePos.x - (SHERLOCK_SCREEN_WIDTH * 5 / 6)) / (SHERLOCK_SCREEN_WIDTH / 6); + if (mousePos.y < (SHERLOCK_SCREEN_HEIGHT / 6)) + _targetScroll.y -= 2 * SCROLL_SPEED * (SHERLOCK_SCREEN_HEIGHT / 6 - mousePos.y) / (SHERLOCK_SCREEN_HEIGHT / 6); + if (mousePos.y > (SHERLOCK_SCREEN_HEIGHT * 5 / 6)) + _targetScroll.y += 2 * SCROLL_SPEED * (mousePos.y - SHERLOCK_SCREEN_HEIGHT * 5 / 6) / (SHERLOCK_SCREEN_HEIGHT / 6); + + if (_targetScroll.x < 0) + _targetScroll.x = 0; + if ((_targetScroll.x + SHERLOCK_SCREEN_WIDTH) > screen._backBuffer1.w()) + _targetScroll.x = screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH; + if (_targetScroll.y < 0) + _targetScroll.y = 0; + if ((_targetScroll.y + SHERLOCK_SCREEN_HEIGHT) > screen._backBuffer1.h()) + _targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT; + + // Check the keyboard + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + + switch (keyState.keycode) { + case Common::KEYCODE_HOME: + case Common::KEYCODE_KP7: + _targetScroll.x = 0; + _targetScroll.y = 0; + break; + + case Common::KEYCODE_END: + case Common::KEYCODE_KP1: + _targetScroll.x = screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH; + _targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT; + break; + + case Common::KEYCODE_PAGEUP: + case Common::KEYCODE_KP9: + _targetScroll.y -= SHERLOCK_SCREEN_HEIGHT; + if (_targetScroll.y < 0) + _targetScroll.y = 0; + break; + + case Common::KEYCODE_PAGEDOWN: + case Common::KEYCODE_KP3: + _targetScroll.y += SHERLOCK_SCREEN_HEIGHT; + if (_targetScroll.y > (screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT)) + _targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT; + break; + + case Common::KEYCODE_SPACE: + events._pressed = false; + events._oldButtons = 0; + events._released = true; + break; + + default: + break; + } + } + + // Handle any scrolling of the map + if (_currentScroll != _targetScroll) { + // If there is a Text description being displayed, restore the area under it + if (_oldTextBounds.width() > 0) + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldTextBounds.left, + _oldTextBounds.top), _oldTextBounds); + + _currentScroll = _targetScroll; + + checkMapNames(false); + slamRect(Common::Rect(_currentScroll.x, _currentScroll.y, _currentScroll.x + SHERLOCK_SCREEN_WIDTH, + _currentScroll.y + SHERLOCK_SCREEN_HEIGHT)); + } + + // Handling if a location has been clicked on + if (events._released && _bgFound != -1) { + // If there is a Text description being displayed, restore the area under it + if (_oldTextBounds.width() > 0) { + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldTextBounds.left, + _oldTextBounds.top), _oldTextBounds); + screen.slamRect(_oldTextBounds); + } + + // Save the current scroll position on the map + _bigPos = _currentScroll; + + showCloseUp(_bgFound); + result = _bgFound + 1; + } + } while (!result && !_vm->shouldQuit()); + + music.stopMusic(); + events.clearEvents(); + delete _textBuffer; + _textBuffer = nullptr; + + // Reset the back buffers back to standard size + screen._backBuffer1.create(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT, _vm->getPlatform()); + screen._backBuffer2.create(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT, _vm->getPlatform()); + + return result; } void TattooMap::loadData() { @@ -108,10 +296,11 @@ void TattooMap::loadData() { } while (stream->pos() < stream->size()); } -void TattooMap::drwaMapIcons() { +void TattooMap::drawMapIcons() { Screen &screen = *_vm->_screen; for (uint idx = 0; idx < _data.size(); ++idx) { + _vm->setFlagsDirect(idx + 1); //***DEBUG*** if (_data[idx]._iconNum != -1 && _vm->readFlags(idx + 1)) { MapEntry &mapEntry = _data[idx]; ImageFrame &img = (*_iconImages)[mapEntry._iconNum]; @@ -124,7 +313,7 @@ void TattooMap::drwaMapIcons() { void TattooMap::checkMapNames(bool slamIt) { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; - Common::Point mousePos = events.mousePos(); + Common::Point mousePos = events.mousePos() + _currentScroll; int dif = 10000; // See if the mouse is pointing at any of the map locations @@ -200,7 +389,7 @@ void TattooMap::checkMapNames(bool slamIt) { // Allocate a new surface _textBuffer = new Surface(width, height, _vm->getPlatform()); - _textBuffer->fillRect(Common::Rect(0, 0, width, height), 255); + _textBuffer->fillRect(Common::Rect(0, 0, width, height), TRANSPARENCY); if (space == nullptr) { // The whole text can be drawn on a single line _textBuffer->writeString(desc, Common::Point(0, 0), BLACK); @@ -243,52 +432,65 @@ void TattooMap::checkMapNames(bool slamIt) { _textBuffer->writeString(line2, Common::Point(xp + 1, 1), MAP_NAME_COLOR); } - // Set the position of the Text Tag - // TODO: take current scroll into account - int xp = (mousePos.x - width / 2); - int yp = (mousePos.y - height / 2); - - _textBounds = Common::Rect(xp, yp, xp + width, yp + height); + // Set the text display position + setTextBounds(); } else if (_bgFound == -1 && _oldBgFound != -1) { // We need to clear a currently displayed name delete _textBuffer; + _textBuffer = nullptr; } _oldBgFound = _bgFound; } else { // Set the new text position - // TODO: take current scroll into account - int xp = (mousePos.x - _textBounds.width() / 2); - int yp = (mousePos.y - _textBounds.height() / 2); - - _textBounds.moveTo(xp, yp); + setTextBounds(); } - // If the text tag was displayed, restore the graphics underneath it + // If the location name was displayed, restore the graphics underneath where it previously was if (_oldTextBounds.width() > 0) screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldTextBounds.left, _oldTextBounds.top), _oldTextBounds); - // See if we need to draw a Text Tag floating with the cursor + // See if we need to draw the currently highlighted location name if (_textBuffer != nullptr) - screen.transBlitFrom(*_textBuffer, Common::Point(_textBounds.left, _textBounds.top)); + screen._backBuffer1.transBlitFrom(*_textBuffer, Common::Point(_textBounds.left, _textBounds.top)); // See if we need to flush the areas associated with the text if (_oldTextBounds.width() > 0) { if (slamIt) - // TODO: Take into account scroll - screen.slamRect(_oldTextBounds); + slamRect(_oldTextBounds); - // If there's no text to display, reset the tag and old tag bounds + // If there's no text to display, reset the display bounds if (_textBuffer == nullptr) { _textBounds.left = _textBounds.top = _textBounds.right = _textBounds.bottom = 0; _oldTextBounds.left = _oldTextBounds.top = _oldTextBounds.right = _oldTextBounds.bottom = 0; } } - // If there's a text to display, then copy the drawn area to the screen + // If there's text to display, then copy the drawn area to the screen if (_textBuffer != nullptr && slamIt) - // TODO: Handle scroll - screen.slamRect(_textBounds); + slamRect(_textBounds); +} + +void TattooMap::setTextBounds() { + Events &events = *_vm->_events; + Common::Point mousePos = events.mousePos(); + + if (_textBuffer == nullptr) { + _textBounds = Common::Rect(0, 0, 0, 0); + } else { + int xp = (mousePos.x - _textBounds.width() / 2) + _currentScroll.x; + int yp = (mousePos.y - _textBounds.height() / 2) + _currentScroll.y; + if (xp < _currentScroll.x) + xp = _currentScroll.x; + if ((xp + _textBounds.width()) >(_currentScroll.x + SHERLOCK_SCREEN_WIDTH)) + xp = _currentScroll.x + SHERLOCK_SCREEN_WIDTH - _textBounds.width(); + if (yp < _currentScroll.y) + yp = _currentScroll.y; + if ((yp + _textBounds.height()) >(_currentScroll.y + SHERLOCK_SCREEN_HEIGHT)) + yp = _currentScroll.y + SHERLOCK_SCREEN_HEIGHT - _textBounds.height(); + + _textBounds = Common::Rect(xp, yp, xp + _textBuffer->w(), yp + _textBuffer->h()); + } } void TattooMap::restoreArea(const Common::Rect &bounds) { @@ -318,8 +520,7 @@ void TattooMap::showCloseUp(int closeUpNum) { bool minimize = false; int scaleVal, newSize; - do - { + do { scaleVal = n; newSize = pic[0].sDrawXSize(n); @@ -366,6 +567,14 @@ void TattooMap::showCloseUp(int closeUpNum) { screen.slamRect(r); } +void TattooMap::slamRect(const Common::Rect &bounds) { + Screen &screen = *_vm->_screen; + Common::Rect r = bounds; + r.translate(-_currentScroll.x, -_currentScroll.y); + + screen.blitFrom(screen._backBuffer1, Common::Point(r.left, r.top), bounds); +} + } // End of namespace Tattoo } // End of namespace Sherlock diff --git a/engines/sherlock/tattoo/tattoo_map.h b/engines/sherlock/tattoo/tattoo_map.h index 079aa46b16..a9753e7587 100644 --- a/engines/sherlock/tattoo/tattoo_map.h +++ b/engines/sherlock/tattoo/tattoo_map.h @@ -34,8 +34,6 @@ class SherlockEngine; namespace Tattoo { -#define CLOSEUP_STEPS 30 - struct MapEntry : Common::Point { int _iconNum; Common::String _description; @@ -52,6 +50,7 @@ private: int _bgFound, _oldBgFound; Surface *_textBuffer; Common::Rect _textBounds, _oldTextBounds; + Common::Point _currentScroll, _targetScroll; /** * Load data needed for the map @@ -61,7 +60,7 @@ private: /** * Draws all available location icons onto the back buffer */ - void drwaMapIcons(); + void drawMapIcons(); /** * Draws the location names of whatever the mouse moves over on the map @@ -77,6 +76,16 @@ private: * This will load a specified close up and zoom it up to the middle of the screen */ void showCloseUp(int closeUpNum); + + /** + * Set the display bounds for the textual description of a location + */ + void setTextBounds(); + + /** + * Copies an area of the map to the screen, taking into account scrolling + */ + void slamRect(const Common::Rect &bounds); public: TattooMap(SherlockEngine *vm); virtual ~TattooMap() {} diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp index 6ef4d2fd77..eaabcfc64b 100644 --- a/engines/sherlock/tattoo/tattoo_scene.cpp +++ b/engines/sherlock/tattoo/tattoo_scene.cpp @@ -59,8 +59,40 @@ TattooScene::TattooScene(SherlockEngine *vm) : Scene(vm) { } bool TattooScene::loadScene(const Common::String &filename) { + Music &music = *_vm->_music; + Sound &sound = *_vm->_sound; + Talk &talk = *_vm->_talk; + TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui; + // Check if it's a scene we need to keep trakc track of how many times we've visited + for (int idx = (int)_sceneTripCounters.size() - 1; idx >= 0; --idx) { + if (_sceneTripCounters[idx]._sceneNumber == _currentScene) { + if (--_sceneTripCounters[idx]._numTimes == 0) { + _vm->setFlags(_sceneTripCounters[idx]._flag); + _sceneTripCounters.remove_at(idx); + } + } + } + + // Set the NPC paths for the scene + setNPCPath(0); + + // Handle loading music for the scene + if (sound._midiDrvLoaded) { + if (talk._scriptMoreFlag != 1 && talk._scriptMoreFlag != 3) + sound._nextSongName = Common::String::format("res%02d", _currentScene); + + // If it's a new song, then start it up + if (sound._currentSongName.compareToIgnoreCase(sound._nextSongName)) { + if (music.loadSong(sound._nextSongName)) { + music.setMIDIVolume(music._musicVolume); + if (music._musicOn) + music.startSong(); + } + } + } + bool result = Scene::loadScene(filename); if (_currentScene != STARTING_INTRO_SCENE) { diff --git a/engines/sherlock/tattoo/tattoo_scene.h b/engines/sherlock/tattoo/tattoo_scene.h index 3c4a3cd0e3..c3b238438e 100644 --- a/engines/sherlock/tattoo/tattoo_scene.h +++ b/engines/sherlock/tattoo/tattoo_scene.h @@ -34,6 +34,16 @@ enum { STARTING_INTRO_SCENE = 91, OVERHEAD_MAP2 = 99, OVERHEAD_MAP = 100 }; +struct SceneTripEntry { + bool _flag; + int _sceneNumber; + int _numTimes; + + SceneTripEntry() : _flag(false), _sceneNumber(0), _numTimes(0) {} + SceneTripEntry(bool flag, int sceneNumber, int numTimes) : _flag(flag), + _sceneNumber(sceneNumber), _numTimes(numTimes) {} +}; + class TattooScene : public Scene { private: int _arrowZone; @@ -95,6 +105,7 @@ protected: public: ImageFile *_mask, *_mask1; CAnimStream _activeCAnim; + Common::Array _sceneTripCounters; public: TattooScene(SherlockEngine *vm); -- cgit v1.2.3