From 099b3b3d8ff4729b5556f07f0e4476555ce7659c Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sat, 6 Aug 2016 06:41:04 +0200 Subject: MOHAWK: Move the hotspot list to RivenCard Also replace all hardcoded accesses to the hotspot array with hotspot queries. --- engines/mohawk/console.cpp | 8 +- engines/mohawk/riven.cpp | 110 +++++++++--------- engines/mohawk/riven.h | 5 +- engines/mohawk/riven_card.cpp | 77 ++++++++++++- engines/mohawk/riven_card.h | 29 ++++- engines/mohawk/riven_external.cpp | 230 +++++++++++++++++++++++--------------- engines/mohawk/riven_external.h | 4 +- engines/mohawk/riven_scripts.cpp | 26 ++--- 8 files changed, 313 insertions(+), 176 deletions(-) diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index 4be76930c5..41dd535c3a 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -510,10 +510,12 @@ bool RivenConsole::Cmd_ChangeStack(int argc, const char **argv) { } bool RivenConsole::Cmd_Hotspots(int argc, const char **argv) { - debugPrintf("Current card (%d) has %d hotspots:\n", _vm->getCurCard()->getId(), _vm->_hotspots.size()); + Common::Array hotspots = _vm->_card->getHotspots(); - for (uint16 i = 0; i < _vm->_hotspots.size(); i++) { - RivenHotspot *hotspot = _vm->_hotspots[i]; + debugPrintf("Current card (%d) has %d hotspots:\n", _vm->getCurCard()->getId(), hotspots.size()); + + for (uint16 i = 0; i < hotspots.size(); i++) { + RivenHotspot *hotspot = hotspots[i]; debugPrintf("Hotspot %d, index %d, BLST ID %d (", i, hotspot->getIndex(), hotspot->getBlstId()); if (hotspot->isEnabled()) diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index d09ecfd3fa..8e30080972 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -103,9 +103,6 @@ MohawkEngine_Riven::~MohawkEngine_Riven() { delete _scriptMan; delete _optionsDialog; delete _rnd; - for (uint i = 0; i < _hotspots.size(); i++) { - delete _hotspots[i]; - } delete g_atrusJournalRect1; delete g_atrusJournalRect2; delete g_cathJournalRect2; @@ -257,8 +254,7 @@ void MohawkEngine_Riven::handleEvents() { case Common::KEYCODE_F4: _showHotspots = !_showHotspots; if (_showHotspots) { - for (uint16 i = 0; i < _hotspots.size(); i++) - _gfx->drawRect(_hotspots[i]->getRect(), _hotspots[i]->isEnabled()); + _card->drawHotspotRects(); needsUpdate = true; } else refreshCard(); @@ -267,7 +263,7 @@ void MohawkEngine_Riven::handleEvents() { runDialog(*_optionsDialog); if (_optionsDialog->getLoadSlot() >= 0) loadGameState(_optionsDialog->getLoadSlot()); - updateZipMode(); + _card->initializeZipMode(); break; case Common::KEYCODE_r: // Return to the main menu in the demo on ctrl+r @@ -406,16 +402,13 @@ void MohawkEngine_Riven::refreshCard() { // Clear any timer still floating around removeTimer(); - loadHotspots(_card->getId()); - _gfx->clearWaterEffects(); _video->stopVideos(); _card->open(); if (_showHotspots) - for (uint16 i = 0; i < _hotspots.size(); i++) - _gfx->drawRect(_hotspots[i]->getRect(), _hotspots[i]->isEnabled()); + _card->drawHotspotRects(); // Now we need to redraw the cursor if necessary and handle mouse over scripts updateCurrentHotspot(); @@ -424,55 +417,9 @@ void MohawkEngine_Riven::refreshCard() { installCardTimer(); } -void MohawkEngine_Riven::loadHotspots(uint16 id) { - for (uint i = 0; i < _hotspots.size(); i++) { - delete _hotspots[i]; - } - - Common::SeekableReadStream *inStream = getResource(ID_HSPT, id); - - uint16 hotspotCount = inStream->readUint16BE(); - _hotspots.resize(hotspotCount); - - for (uint16 i = 0; i < hotspotCount; i++) { - _hotspots[i] = new RivenHotspot(this, inStream); - } - - delete inStream; - updateZipMode(); -} - -void MohawkEngine_Riven::updateZipMode() { - // Check if a zip mode hotspot is enabled by checking the name/id against the ZIPS records. - - for (uint32 i = 0; i < _hotspots.size(); i++) { - if (_hotspots[i]->isZip()) { - if (_vars["azip"] != 0) { - // Check if a zip mode hotspot is enabled by checking the name/id against the ZIPS records. - Common::String hotspotName = _hotspots[i]->getName(); - - bool foundMatch = false; - - if (!hotspotName.empty()) - for (uint16 j = 0; j < _zipModeData.size(); j++) - if (_zipModeData[j].name == hotspotName) { - foundMatch = true; - break; - } - - _hotspots[i]->enable(foundMatch); - } else // Disable the hotspot if zip mode is disabled - _hotspots[i]->enable(false); - } - } -} - void MohawkEngine_Riven::checkHotspotChange() { - RivenHotspot *hotspot = nullptr; - for (uint16 i = 0; i < _hotspots.size(); i++) - if (_hotspots[i]->isEnabled() && _hotspots[i]->containsPoint(_eventMan->getMousePos())) { - hotspot = _hotspots[i]; - } + Common::Point mousePos = _eventMan->getMousePos(); + RivenHotspot *hotspot = _card->getHotspotContainingPoint(mousePos); if (hotspot) { if (_curHotspot != hotspot) { @@ -596,6 +543,38 @@ Common::String MohawkEngine_Riven::getName(uint16 nameResource, uint16 nameID) { return name; } +int16 MohawkEngine_Riven::getIdFromName(uint16 nameResource, const Common::String &name) { + //TODO: Use proper data structures + + Common::SeekableReadStream *nameStream = getResource(ID_NAME, nameResource); + uint16 fieldCount = nameStream->readUint16BE(); + uint16 *stringOffsets = new uint16[fieldCount]; + + for (uint16 i = 0; i < fieldCount; i++) + stringOffsets[i] = nameStream->readUint16BE(); + for (uint16 i = 0; i < fieldCount; i++) + nameStream->readUint16BE(); // Skip unknown values + + for (uint16 i = 0; i < fieldCount; i++) { + nameStream->seek(stringOffsets[i], SEEK_CUR); + + Common::String readName; + char c = (char)nameStream->readByte(); + while (c) { + readName += c; + c = (char)nameStream->readByte(); + } + + if (readName.equalsIgnoreCase(name)) { + return i; + } + } + + delete nameStream; + delete[] stringOffsets; + return -1; +} + uint16 MohawkEngine_Riven::matchRMAPToCard(uint32 rmapCode) { uint16 index = 0; Common::SeekableReadStream *rmapStream = getResource(ID_RMAP, 1); @@ -920,7 +899,7 @@ void MohawkEngine_Riven::checkSunnerAlertClick() { return; // Only set the sunners variable on the forward hotspot - if ((rmapCode == 0x79bd && _curHotspot->getIndex() != 2) || (rmapCode == 0x7beb && _curHotspot->getIndex() != 3)) + if (_curHotspot->getBlstId() != 3) return; // If the alert video is no longer playing, we have nothing left to do @@ -942,6 +921,19 @@ void MohawkEngine_Riven::addZipVisitedCard(uint16 cardId, uint16 cardNameId) { _zipModeData.push_back(zip); } +bool MohawkEngine_Riven::isZipVisitedCard(const Common::String &hotspotName) const { + bool foundMatch = false; + + if (!hotspotName.empty()) + for (uint16 j = 0; j < _zipModeData.size(); j++) + if (_zipModeData[j].name == hotspotName) { + foundMatch = true; + break; + } + + return foundMatch; +} + bool ZipMode::operator== (const ZipMode &z) const { return z.name == name && z.id == id; } diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h index b2e3bf04d3..4cff24eb94 100644 --- a/engines/mohawk/riven.h +++ b/engines/mohawk/riven.h @@ -135,10 +135,8 @@ private: void handleEvents(); // Hotspot related functions and variables - void loadHotspots(uint16); void checkInventoryClick(); bool _showHotspots; - void updateZipMode(); void checkHotspotChange(); // Variables @@ -159,6 +157,7 @@ public: void changeToStack(uint16); void refreshCard(); Common::String getName(uint16 nameResource, uint16 nameID); + int16 getIdFromName(uint16 nameResource, const Common::String &name); Common::String getStackName(uint16 stack) const; RivenCard *getCurCard() const { return _card; } uint16 getCurStack() const { return _curStack; } @@ -166,12 +165,12 @@ public: uint32 getCurCardRMAP(); // Hotspot functions/variables - Common::Array _hotspots; RivenHotspot *_curHotspot; Common::Array _zipModeData; RivenHotspot *getCurHotspot() const { return _curHotspot; } void updateCurrentHotspot(); void addZipVisitedCard(uint16 cardId, uint16 cardNameId); + bool isZipVisitedCard(const Common::String &hotspotName) const; // Variables RivenVariableMap _vars; diff --git a/engines/mohawk/riven_card.cpp b/engines/mohawk/riven_card.cpp index 4193eea111..b3ec0657a0 100644 --- a/engines/mohawk/riven_card.cpp +++ b/engines/mohawk/riven_card.cpp @@ -33,12 +33,15 @@ RivenCard::RivenCard(MohawkEngine_Riven *vm, uint16 id) : _vm(vm), _id(id) { loadCardResource(id); + loadHotspots(id); loadCardPictureList(id); loadCardSoundList(id); } RivenCard::~RivenCard() { - + for (uint i = 0; i < _hotspots.size(); i++) { + delete _hotspots[i]; + } } void RivenCard::loadCardResource(uint16 id) { @@ -69,6 +72,20 @@ void RivenCard::initializeZipMode() { if (_zipModePlace) { _vm->addZipVisitedCard(_id, _name); } + + // Check if a zip mode hotspot is enabled by checking the name/id against the ZIPS records. + for (uint32 i = 0; i < _hotspots.size(); i++) { + if (_hotspots[i]->isZip()) { + if (_vm->_vars["azip"] != 0) { + // Check if a zip mode hotspot is enabled by checking the name/id against the ZIPS records. + Common::String hotspotName = _hotspots[i]->getName(); + bool visited = _vm->isZipVisitedCard(hotspotName); + + _hotspots[i]->enable(visited); + } else // Disable the hotspot if zip mode is disabled + _hotspots[i]->enable(false); + } + } } void RivenCard::runScript(uint16 scriptType) { @@ -196,6 +213,60 @@ SLSTRecord RivenCard::getSound(uint16 index) const { error("Could not find sound %d in card %d", index, _id); } +void RivenCard::loadHotspots(uint16 id) { + Common::SeekableReadStream *inStream = _vm->getResource(ID_HSPT, id); + + uint16 hotspotCount = inStream->readUint16BE(); + _hotspots.resize(hotspotCount); + + for (uint16 i = 0; i < hotspotCount; i++) { + _hotspots[i] = new RivenHotspot(_vm, inStream); + } + + delete inStream; +} + +void RivenCard::drawHotspotRects() { + for (uint16 i = 0; i < _hotspots.size(); i++) + _vm->_gfx->drawRect(_hotspots[i]->getRect(), _hotspots[i]->isEnabled()); +} + +RivenHotspot *RivenCard::getHotspotContainingPoint(const Common::Point &point) const { + RivenHotspot *hotspot = nullptr; + for (uint16 i = 0; i < _hotspots.size(); i++) + if (_hotspots[i]->isEnabled() && _hotspots[i]->containsPoint(point)) { + hotspot = _hotspots[i]; + } + + return hotspot; +} + +Common::Array RivenCard::getHotspots() const { + return _hotspots; +} + +RivenHotspot *RivenCard::getHotspotByName(const Common::String &name) const { + int16 nameId = _vm->getIdFromName(HotspotNames, name); + + for (uint i = 0; i < _hotspots.size(); i++) { + if (_hotspots[i]->getNameId() == nameId) { + return _hotspots[i]; + } + } + + error("Card %d does not have an hotspot named %s", _id, name.c_str()); +} + +RivenHotspot *RivenCard::getHotspotByBlstId(const uint16 blstId) const { + for (uint i = 0; i < _hotspots.size(); i++) { + if (_hotspots[i]->getBlstId() == blstId) { + return _hotspots[i]; + } + } + + return nullptr; +} + RivenHotspot::RivenHotspot(MohawkEngine_Riven *vm, Common::ReadStream *stream) : _vm(vm) { loadFromStream(stream); @@ -289,4 +360,8 @@ void RivenHotspot::setRect(const Common::Rect &rect) { _rect = rect; } +int16 RivenHotspot::getNameId() const { + return _nameResource; +} + } // End of namespace Mohawk diff --git a/engines/mohawk/riven_card.h b/engines/mohawk/riven_card.h index e7745fca1e..10b77275ab 100644 --- a/engines/mohawk/riven_card.h +++ b/engines/mohawk/riven_card.h @@ -31,6 +31,8 @@ namespace Mohawk { +class RivenHotspot; + /** * A game view * @@ -74,12 +76,30 @@ public: /** Get the card's sound description with the specified index */ SLSTRecord getSound(uint16 index) const; + /** Draw borders for all the hotspots in the card */ + void drawHotspotRects(); + + /** Enable the zip hotspots if they match to already visited locations */ + void initializeZipMode(); + + /** Get the hotspot containing the specified point */ + RivenHotspot *getHotspotContainingPoint(const Common::Point &point) const; + + /** Get the hotspot with the specified name */ + RivenHotspot *getHotspotByName(const Common::String &name) const; + + /** Get the hotspot with the specified BLST id */ + RivenHotspot *getHotspotByBlstId(const uint16 blstId) const; + + /** Get all the hotspots in the card. To be used for debugging features only */ + Common::Array getHotspots() const; + private: void loadCardResource(uint16 id); + void loadHotspots(uint16 id); void loadCardPictureList(uint16 id); void loadCardSoundList(uint16 id); - void initializeZipMode(); void defaultLoadScript(); MohawkEngine_Riven *_vm; @@ -90,6 +110,8 @@ private: uint16 _zipModePlace; RivenScriptList _scripts; + Common::Array _hotspots; + // Resource lists Common::Array _pictureList; Common::Array _soundList; @@ -132,7 +154,10 @@ public: /** Get the hotspot's name from the current stack's name list */ Common::String getName() const; - /** Get the hotspot's index in the view */ + /** Get the hotspot's name id */ + int16 getNameId() const; + + /** Get the hotspot's order in the view */ uint16 getIndex() const; /** Get the hotspot's enable list id */ diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 8c0711840d..88718db1a6 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -312,23 +312,27 @@ void RivenExternal::resetDomeSliders(uint16 soundId, uint16 startHotspot) { assert(_sliderState == kDomeSliderDefaultState); } -void RivenExternal::checkDomeSliders(uint16 resetSlidersHotspot, uint16 openDomeHotspot) { +void RivenExternal::checkDomeSliders() { + RivenHotspot *resetSlidersHotspot = _vm->getCurCard()->getHotspotByName("ResetSliders"); + RivenHotspot *openDomeHotspot = _vm->getCurCard()->getHotspotByName("OpenDome"); + // Let's see if we're all matched up... if (_vm->_vars["adomecombo"] == _sliderState) { // Set the button hotspot to the open dome hotspot - _vm->_hotspots[resetSlidersHotspot]->enable(false); - _vm->_hotspots[openDomeHotspot]->enable(true); + resetSlidersHotspot->enable(false); + openDomeHotspot->enable(true); } else { // Set the button hotspot to the reset sliders hotspot - _vm->_hotspots[resetSlidersHotspot]->enable(true); - _vm->_hotspots[openDomeHotspot]->enable(false); + resetSlidersHotspot->enable(true); + openDomeHotspot->enable(false); } } void RivenExternal::checkSliderCursorChange(uint16 startHotspot) { // Set the cursor based on _sliderState and what hotspot we're over for (uint16 i = 0; i < kDomeSliderSlotCount; i++) { - if (_vm->_hotspots[i + startHotspot]->containsPoint(_vm->_system->getEventManager()->getMousePos())) { + RivenHotspot *hotspot = _vm->getCurCard()->getHotspotByBlstId(startHotspot + i); + if (hotspot->containsPoint(_vm->_system->getEventManager()->getMousePos())) { if (_sliderState & (1 << (24 - i))) _vm->_cursor->setCursor(kRivenOpenHandCursor); else @@ -339,11 +343,12 @@ void RivenExternal::checkSliderCursorChange(uint16 startHotspot) { } } -void RivenExternal::dragDomeSlider(uint16 soundId, uint16 resetSlidersHotspot, uint16 openDomeHotspot, uint16 startHotspot) { +void RivenExternal::dragDomeSlider(uint16 soundId, uint16 startHotspot) { int16 foundSlider = -1; for (uint16 i = 0; i < kDomeSliderSlotCount; i++) { - if (_vm->_hotspots[i + startHotspot]->containsPoint(_vm->_system->getEventManager()->getMousePos())) { + RivenHotspot *hotspot = _vm->getCurCard()->getHotspotByBlstId(startHotspot + i); + if (hotspot->containsPoint(_vm->_system->getEventManager()->getMousePos())) { // If the slider is not at this hotspot, we can't do anything else if (!(_sliderState & (1 << (24 - i)))) return; @@ -367,24 +372,30 @@ void RivenExternal::dragDomeSlider(uint16 soundId, uint16 resetSlidersHotspot, u while (_vm->_system->getEventManager()->pollEvent(event)) { switch (event.type) { case Common::EVENT_MOUSEMOVE: - if (foundSlider < 24 && !(_sliderState & (1 << (23 - foundSlider))) && _vm->_hotspots[foundSlider + startHotspot + 1]->containsPoint(event.mouse)) { - // We've moved the slider right one space - _sliderState &= ~(_sliderState & (1 << (24 - foundSlider))); - foundSlider++; - _sliderState |= 1 << (24 - foundSlider); - - // Now play a click sound and redraw - _vm->_sound->playSound(soundId); - drawDomeSliders(startHotspot); - } else if (foundSlider > 0 && !(_sliderState & (1 << (25 - foundSlider))) && _vm->_hotspots[foundSlider + startHotspot - 1]->containsPoint(event.mouse)) { - // We've moved the slider left one space - _sliderState &= ~(_sliderState & (1 << (24 - foundSlider))); - foundSlider--; - _sliderState |= 1 << (24 - foundSlider); - - // Now play a click sound and redraw - _vm->_sound->playSound(soundId); - drawDomeSliders(startHotspot); + if (foundSlider < 24 && !(_sliderState & (1 << (23 - foundSlider)))) { + RivenHotspot *nextHotspot = _vm->getCurCard()->getHotspotByBlstId(startHotspot + foundSlider + 1); + if (nextHotspot->containsPoint(event.mouse)) { + // We've moved the slider right one space + _sliderState &= ~(_sliderState & (1 << (24 - foundSlider))); + foundSlider++; + _sliderState |= 1 << (24 - foundSlider); + + // Now play a click sound and redraw + _vm->_sound->playSound(soundId); + drawDomeSliders(startHotspot); + } + } else if (foundSlider > 0 && !(_sliderState & (1 << (25 - foundSlider)))) { + RivenHotspot *previousHotspot = _vm->getCurCard()->getHotspotByBlstId(startHotspot + foundSlider - 1); + if (previousHotspot->containsPoint(event.mouse)) { + // We've moved the slider left one space + _sliderState &= ~(_sliderState & (1 << (24 - foundSlider))); + foundSlider--; + _sliderState |= 1 << (24 - foundSlider); + + // Now play a click sound and redraw + _vm->_sound->playSound(soundId); + drawDomeSliders(startHotspot); + } } else _vm->_system->updateScreen(); // A normal update for the cursor break; @@ -399,7 +410,7 @@ void RivenExternal::dragDomeSlider(uint16 soundId, uint16 resetSlidersHotspot, u } // Check to see if we have the right combination - checkDomeSliders(resetSlidersHotspot, openDomeHotspot); + checkDomeSliders(); } void RivenExternal::drawDomeSliders(uint16 startHotspot) { @@ -414,10 +425,12 @@ void RivenExternal::drawDomeSliders(uint16 startHotspot) { uint16 bitmapId = _vm->findResourceID(ID_TBMP, "*sliders*"); for (uint16 i = 0; i < kDomeSliderSlotCount; i++) { - Common::Rect srcRect = _vm->_hotspots[startHotspot + i]->getRect(); + RivenHotspot *hotspot = _vm->getCurCard()->getHotspotByBlstId(startHotspot + i); + + Common::Rect srcRect = hotspot->getRect(); srcRect.translate(-dstAreaRect.left, -dstAreaRect.top); // Adjust the rect so it's in the destination area - Common::Rect dstRect = _vm->_hotspots[startHotspot + i]->getRect(); + Common::Rect dstRect = hotspot->getRect(); if (_sliderState & (1 << (24 - i))) _vm->_gfx->drawImageRect(bitmapId, srcRect, dstRect); @@ -449,14 +462,17 @@ void RivenExternal::xaatrusopenbook(uint16 argc, uint16 *argv) { uint32 &page = _vm->_vars["aatruspage"]; // Set hotspots depending on the page + RivenHotspot *openBook = _vm->_card->getHotspotByName("openBook"); + RivenHotspot *nextPage = _vm->_card->getHotspotByName("nextpage"); + RivenHotspot *prevPage = _vm->_card->getHotspotByName("prevpage"); if (page == 1) { - _vm->_hotspots[1]->enable(false); - _vm->_hotspots[2]->enable(false); - _vm->_hotspots[3]->enable(true); + prevPage->enable(false); + nextPage->enable(false); + openBook->enable(true); } else { - _vm->_hotspots[1]->enable(true); - _vm->_hotspots[2]->enable(true); - _vm->_hotspots[3]->enable(false); + prevPage->enable(true); + nextPage->enable(true); + openBook->enable(false); } // Draw the image of the page @@ -514,14 +530,17 @@ void RivenExternal::xacathopenbook(uint16 argc, uint16 *argv) { uint32 page = _vm->_vars["acathpage"]; // Set hotspots depending on the page + RivenHotspot *openBook = _vm->_card->getHotspotByName("openBook"); + RivenHotspot *nextPage = _vm->_card->getHotspotByName("nextpage"); + RivenHotspot *prevPage = _vm->_card->getHotspotByName("prevpage"); if (page == 1) { - _vm->_hotspots[1]->enable(false); - _vm->_hotspots[2]->enable(false); - _vm->_hotspots[3]->enable(true); + prevPage->enable(false); + nextPage->enable(false); + openBook->enable(true); } else { - _vm->_hotspots[1]->enable(true); - _vm->_hotspots[2]->enable(true); - _vm->_hotspots[3]->enable(false); + prevPage->enable(true); + nextPage->enable(true); + openBook->enable(false); } // Draw the image of the page @@ -946,12 +965,16 @@ void RivenExternal::xbait(uint16 argc, uint16 *argv) { _vm->_cursor->setCursor(kRivenMainCursor); _vm->_system->updateScreen(); + RivenHotspot *bait = _vm->getCurCard()->getHotspotByBlstId(9); + RivenHotspot *baitPlate = _vm->getCurCard()->getHotspotByBlstId(16); + // Set the bait if we put it on the plate - if (_vm->_hotspots[9]->containsPoint(_vm->_system->getEventManager()->getMousePos())) { + if (baitPlate->containsPoint(_vm->_system->getEventManager()->getMousePos())) { _vm->_vars["bbait"] = 1; _vm->getCurCard()->drawPicture(4); - _vm->_hotspots[3]->enable(false); // Disable bait hotspot - _vm->_hotspots[9]->enable(true); // Enable baitplate hotspot + + bait->enable(false); // Disable bait hotspot + baitPlate->enable(true); // Enable baitplate hotspot } } @@ -1005,33 +1028,36 @@ void RivenExternal::xbaitplate(uint16 argc, uint16 *argv) { _vm->_cursor->setCursor(kRivenMainCursor); _vm->_system->updateScreen(); + RivenHotspot *bait = _vm->getCurCard()->getHotspotByBlstId(9); + RivenHotspot *baitPlate = _vm->getCurCard()->getHotspotByBlstId(16); + // Set the bait if we put it on the plate, remove otherwise - if (_vm->_hotspots[9]->containsPoint(_vm->_system->getEventManager()->getMousePos())) { + if (baitPlate->containsPoint(_vm->_system->getEventManager()->getMousePos())) { _vm->_vars["bbait"] = 1; _vm->getCurCard()->drawPicture(4); - _vm->_hotspots[3]->enable(false); // Disable bait hotspot - _vm->_hotspots[9]->enable(true); // Enable baitplate hotspot + bait->enable(false); // Disable bait hotspot + baitPlate->enable(true); // Enable baitplate hotspot } else { _vm->_vars["bbait"] = 0; - _vm->_hotspots[3]->enable(true); // Enable bait hotspot - _vm->_hotspots[9]->enable(false); // Disable baitplate hotspot + bait->enable(true); // Enable bait hotspot + baitPlate->enable(false); // Disable baitplate hotspot } } void RivenExternal::xbisland190_opencard(uint16 argc, uint16 *argv) { - checkDomeSliders(27, 28); + checkDomeSliders(); } void RivenExternal::xbisland190_resetsliders(uint16 argc, uint16 *argv) { - resetDomeSliders(41, 2); + resetDomeSliders(41, 9); } void RivenExternal::xbisland190_slidermd(uint16 argc, uint16 *argv) { - dragDomeSlider(41, 27, 28, 2); + dragDomeSlider(41, 9); } void RivenExternal::xbisland190_slidermw(uint16 argc, uint16 *argv) { - checkSliderCursorChange(2); + checkSliderCursorChange(9); } void RivenExternal::xbscpbtn(uint16 argc, uint16 *argv) { @@ -1192,10 +1218,12 @@ void RivenExternal::xgrotatepins(uint16 argc, uint16 *argv) { void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) { // Handle a click on a section of an island + RivenHotspot *panel = _vm->getCurCard()->getHotspotByBlstId(13); + // Get our mouse position and adjust it to the beginning of the hotspot Common::Point mousePos = _vm->_system->getEventManager()->getMousePos(); - mousePos.x -= _vm->_hotspots[3]->getRect().left; - mousePos.y -= _vm->_hotspots[3]->getRect().top; + mousePos.x -= panel->getRect().left; + mousePos.y -= panel->getRect().top; // And now adjust it to which box we hit mousePos.x /= 10; @@ -1280,19 +1308,19 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) { } void RivenExternal::xgisland25_opencard(uint16 argc, uint16 *argv) { - checkDomeSliders(28, 29); + checkDomeSliders(); } void RivenExternal::xgisland25_resetsliders(uint16 argc, uint16 *argv) { - resetDomeSliders(16, 2); + resetDomeSliders(16, 11); } void RivenExternal::xgisland25_slidermd(uint16 argc, uint16 *argv) { - dragDomeSlider(16, 28, 29, 2); + dragDomeSlider(16, 11); } void RivenExternal::xgisland25_slidermw(uint16 argc, uint16 *argv) { - checkSliderCursorChange(2); + checkSliderCursorChange(11); } void RivenExternal::xgscpbtn(uint16 argc, uint16 *argv) { @@ -1340,9 +1368,11 @@ void RivenExternal::xgrviewer(uint16 argc, uint16 *argv) { } // Calculate how much we're moving - static const uint16 hotspotPositions[] = { 2, 1, 5, 4, 3 }; + Common::String buttonName = _vm->_curHotspot->getName(); + uint32 buttonPos = buttonName.lastChar() - '0'; + uint32 &curPos = _vm->_vars["grviewpos"]; - uint32 newPos = curPos + hotspotPositions[_vm->_curHotspot->getIndex() - 2]; + uint32 newPos = curPos + buttonPos; // Now play the movie VideoHandle handle = _vm->_video->playMovieRiven(1); @@ -1409,9 +1439,11 @@ void RivenExternal::xglviewer(uint16 argc, uint16 *argv) { // (It shows the village from the middle of the lake) // Calculate how much we're moving - static const uint16 hotspotPositions[] = { 1, 5, 4, 2, 0, 0, 3 }; + Common::String buttonName = _vm->_curHotspot->getName(); + uint32 buttonPos = buttonName.lastChar() - '0'; + uint32 &curPos = _vm->_vars["glviewpos"]; - uint32 newPos = curPos + hotspotPositions[_vm->_curHotspot->getIndex() - 2]; + uint32 newPos = curPos + buttonPos; // Now play the movie VideoHandle handle = _vm->_video->playMovieRiven(1); @@ -1756,15 +1788,15 @@ void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) { } void RivenExternal::xjdome25_resetsliders(uint16 argc, uint16 *argv) { - resetDomeSliders(81, 2); + resetDomeSliders(81, 10); } void RivenExternal::xjdome25_slidermd(uint16 argc, uint16 *argv) { - dragDomeSlider(81, 29, 28, 2); + dragDomeSlider(81, 10); } void RivenExternal::xjdome25_slidermw(uint16 argc, uint16 *argv) { - checkSliderCursorChange(2); + checkSliderCursorChange(10); } void RivenExternal::xjscpbtn(uint16 argc, uint16 *argv) { @@ -1995,8 +2027,10 @@ void RivenExternal::xschool280_playwhark(uint16 argc, uint16 *argv) { } // Enable the correct hotspots for the movement now - _vm->_hotspots[2]->enable(!_vm->_hotspots[2]->isEnabled()); - _vm->_hotspots[3]->enable(!_vm->_hotspots[3]->isEnabled()); + RivenHotspot *rotateLeft = _vm->getCurCard()->getHotspotByName("rotateLeft"); + RivenHotspot *rotateRight = _vm->getCurCard()->getHotspotByName("rotateRight"); + rotateLeft->enable(!rotateLeft->isEnabled()); + rotateRight->enable(!rotateRight->isEnabled()); // Update the cursor _vm->updateCurrentHotspot(); @@ -2046,15 +2080,15 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) { uint32 endTime = argv[2] * 1000 / 600; // Track down our hotspot - // Of course, they're not in any sane order... - static const uint16 hotspotMap[] = { 1, 3, 2, 0 }; - Common::Rect hotspotRect = _vm->_hotspots[hotspotMap[argv[3] - 1]]->getRect(); + Common::String hotspotName = Common::String::format("touchBook%d", argv[3]); + RivenHotspot *hotspot = _vm->getCurCard()->getHotspotByName(hotspotName); + Common::Rect hotspotRect = hotspot->getRect(); debug(0, "xbookclick:"); debug(0, "\tVideo Code = %d", argv[0]); debug(0, "\tStart Time = %dms", startTime); debug(0, "\tEnd Time = %dms", endTime); - debug(0, "\tHotspot = %d -> %d", argv[3], hotspotMap[argv[3] - 1]); + debug(0, "\tHotspot = %d -> %s", argv[3], hotspotName.c_str()); // Just let the video play while we wait until Gehn opens the trap book for us while (video->getTime() < startTime && !_vm->shouldQuit()) { @@ -2157,9 +2191,13 @@ void RivenExternal::xooffice30_closebook(uint16 argc, uint16 *argv) { _vm->_video->playMovieBlockingRiven(1); // Set the hotspots into their correct states - _vm->_hotspots[2]->enable(false); - _vm->_hotspots[5]->enable(false); - _vm->_hotspots[6]->enable(true); + RivenHotspot *closeBook = _vm->getCurCard()->getHotspotByName("closeBook"); + RivenHotspot *nullHotspot = _vm->getCurCard()->getHotspotByName("null"); + RivenHotspot *openBook = _vm->getCurCard()->getHotspotByName("openBook"); + + closeBook->enable(false); + nullHotspot->enable(false); + openBook->enable(true); // We now need to draw PLST 1 and refresh, but PLST 1 is // drawn when refreshing anyway, so don't worry about that. @@ -2284,19 +2322,19 @@ void RivenExternal::xpisland290_domecheck(uint16 argc, uint16 *argv) { } void RivenExternal::xpisland25_opencard(uint16 argc, uint16 *argv) { - checkDomeSliders(31, 5); + checkDomeSliders(); } void RivenExternal::xpisland25_resetsliders(uint16 argc, uint16 *argv) { - resetDomeSliders(10, 6); + resetDomeSliders(10, 14); } void RivenExternal::xpisland25_slidermd(uint16 argc, uint16 *argv) { - dragDomeSlider(10, 31, 5, 6); + dragDomeSlider(10, 14); } void RivenExternal::xpisland25_slidermw(uint16 argc, uint16 *argv) { - checkSliderCursorChange(6); + checkSliderCursorChange(14); } // ------------------------------------------------------------------------------------ @@ -2484,7 +2522,8 @@ void RivenExternal::xtisland390_covercombo(uint16 argc, uint16 *argv) { // If we have hit the correct 5 buttons in a row, activate the hotspot to open up the // telescope cover. - _vm->_hotspots[9]->enable(correctDigits == 5); + RivenHotspot *openCover = _vm->getCurCard()->getHotspotByName("openCover"); + openCover->enable(correctDigits == 5); } // Atrus' Journal and Trap Book are added to inventory @@ -2614,20 +2653,23 @@ void RivenExternal::xt7600_setupmarbles(uint16 argc, uint16 *argv) { void RivenExternal::setMarbleHotspots() { // Set the hotspots for (uint16 i = 0; i < kMarbleCount; i++) { - uint32 &marblePos = _vm->_vars[s_marbleNames[i]]; + uint32 marblePos = _vm->_vars[s_marbleNames[i]]; + RivenHotspot *marbleHotspot = _vm->getCurCard()->getHotspotByName(s_marbleNames[i]); if (marblePos == 0) // In the receptacle - _vm->_hotspots[i + 3]->setRect(_marbleBaseHotspots[i]); + marbleHotspot->setRect(_marbleBaseHotspots[i]); else // On the grid - _vm->_hotspots[i + 3]->setRect(generateMarbleGridRect(getMarbleX(marblePos), getMarbleY(marblePos))); + marbleHotspot->setRect(generateMarbleGridRect(getMarbleX(marblePos), getMarbleY(marblePos))); } } void RivenExternal::xt7800_setup(uint16 argc, uint16 *argv) { // First, let's store the base receptacle hotspots for the marbles if (_marbleBaseHotspots.empty()) - for (uint16 i = 0; i < kMarbleCount; i++) - _marbleBaseHotspots.push_back(_vm->_hotspots[i + 3]->getRect()); + for (uint16 i = 0; i < kMarbleCount; i++) { + RivenHotspot *marbleHotspot = _vm->getCurCard()->getHotspotByName(s_marbleNames[i]); + _marbleBaseHotspots.push_back(marbleHotspot->getRect()); + } // Move the marble hotspots based on their position variables setMarbleHotspots(); @@ -2640,7 +2682,9 @@ void RivenExternal::drawMarbles() { if (_vm->_vars["themarble"] - 1 == i) continue; - Common::Rect rect = _vm->_hotspots[i + 3]->getRect(); + RivenHotspot *marbleHotspot = _vm->getCurCard()->getHotspotByName(s_marbleNames[i]); + + Common::Rect rect = marbleHotspot->getRect(); // Trim the rect down a bit rect.left += 3; rect.top += 3; @@ -2662,11 +2706,13 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) { uint32 &marble = _vm->_vars["themarble"]; marble = 0; - for (uint32 i = 0; i < kMarbleCount; i++) - if (_vm->_hotspots[i + 3]->containsPoint(_vm->_system->getEventManager()->getMousePos())) { + for (uint32 i = 0; i < kMarbleCount; i++) { + RivenHotspot *marbleHotspot = _vm->getCurCard()->getHotspotByName(s_marbleNames[i]); + if (marbleHotspot->containsPoint(_vm->_system->getEventManager()->getMousePos())) { marble = i + 1; break; } + } // xtakeit() shouldn't be called if we're not on a marble hotspot assert(marble != 0); @@ -2735,19 +2781,19 @@ void RivenExternal::xtisland4990_domecheck(uint16 argc, uint16 *argv) { } void RivenExternal::xtisland5056_opencard(uint16 argc, uint16 *argv) { - checkDomeSliders(29, 30); + checkDomeSliders(); } void RivenExternal::xtisland5056_resetsliders(uint16 argc, uint16 *argv) { - resetDomeSliders(37, 3); + resetDomeSliders(37, 24); } void RivenExternal::xtisland5056_slidermd(uint16 argc, uint16 *argv) { - dragDomeSlider(37, 29, 30, 3); + dragDomeSlider(37, 24); } void RivenExternal::xtisland5056_slidermw(uint16 argc, uint16 *argv) { - checkSliderCursorChange(3); + checkSliderCursorChange(24); } void RivenExternal::xtatboundary(uint16 argc, uint16 *argv) { diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h index 58dfde1a00..f1740f4cc2 100644 --- a/engines/mohawk/riven_external.h +++ b/engines/mohawk/riven_external.h @@ -64,9 +64,9 @@ private: void runDomeCheck(); void runDomeButtonMovie(); void resetDomeSliders(uint16 soundId, uint16 startHotspot); - void checkDomeSliders(uint16 resetSlidersHotspot, uint16 openDomeHotspot); + void checkDomeSliders(); void checkSliderCursorChange(uint16 startHotspot); - void dragDomeSlider(uint16 soundId, uint16 resetSlidersHotspot, uint16 openDomeHotspot, uint16 startHotspot); + void dragDomeSlider(uint16 soundId, uint16 startHotspot); void drawDomeSliders(uint16 startHotspot); void drawMarbles(); void setMarbleHotspots(); diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index c299f86296..f43c33f7b3 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -358,11 +358,9 @@ void RivenSimpleCommand::mohawkSwitch(uint16 op, uint16 argc, uint16 *argv) { // Command 9: enable hotspot (blst_id) void RivenSimpleCommand::enableHotspot(uint16 op, uint16 argc, uint16 *argv) { - for (uint16 i = 0; i < _vm->_hotspots.size(); i++) { - if (_vm->_hotspots[i]->getBlstId() == argv[0]) { - debug(2, "Enabling hotspot with BLST ID %d", argv[0]); - _vm->_hotspots[i]->enable(true); - } + RivenHotspot *hotspot = _vm->getCurCard()->getHotspotByBlstId(argv[0]); + if (hotspot) { + hotspot->enable(true); } // Recheck our current hotspot because it may have now changed @@ -371,11 +369,9 @@ void RivenSimpleCommand::enableHotspot(uint16 op, uint16 argc, uint16 *argv) { // Command 10: disable hotspot (blst_id) void RivenSimpleCommand::disableHotspot(uint16 op, uint16 argc, uint16 *argv) { - for (uint16 i = 0; i < _vm->_hotspots.size(); i++) { - if (_vm->_hotspots[i]->getBlstId() == argv[0]) { - debug(2, "Disabling hotspot with BLST ID %d", argv[0]); - _vm->_hotspots[i]->enable(false); - } + RivenHotspot *hotspot = _vm->getCurCard()->getHotspotByBlstId(argv[0]); + if (hotspot) { + hotspot->enable(false); } // Recheck our current hotspot because it may have now changed @@ -600,10 +596,12 @@ void RivenSimpleCommand::activateBLST(uint16 op, uint16 argc, uint16 *argv) { uint16 enabled = blst->readUint16BE(); uint16 hotspotID = blst->readUint16BE(); - if (argv[0] == index) - for (uint16 j = 0; j < _vm->_hotspots.size(); j++) - if (_vm->_hotspots[j]->getBlstId() == hotspotID) - _vm->_hotspots[j]->enable(enabled == 1); + if (argv[0] == index) { + RivenHotspot *hotspot = _vm->getCurCard()->getHotspotByBlstId(hotspotID); + if (hotspot) { + hotspot->enable(enabled == 1); + } + } } delete blst; -- cgit v1.2.3