diff options
Diffstat (limited to 'engines/mohawk/riven_stacks/domespit.cpp')
-rw-r--r-- | engines/mohawk/riven_stacks/domespit.cpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/engines/mohawk/riven_stacks/domespit.cpp b/engines/mohawk/riven_stacks/domespit.cpp index 4674a24d2f..71a82ab343 100644 --- a/engines/mohawk/riven_stacks/domespit.cpp +++ b/engines/mohawk/riven_stacks/domespit.cpp @@ -22,12 +22,213 @@ #include "mohawk/riven_stacks/domespit.h" +#include "mohawk/cursors.h" +#include "mohawk/riven.h" +#include "mohawk/riven_card.h" +#include "mohawk/riven_graphics.h" + +#include "common/events.h" + namespace Mohawk { namespace RivenStacks { +static const uint32 kDomeSliderDefaultState = 0x01F00000; +static const uint32 kDomeSliderSlotCount = 25; + DomeSpit::DomeSpit(MohawkEngine_Riven *vm, uint16 id) : RivenStack(vm, id) { + _sliderState = kDomeSliderDefaultState; +} + +void DomeSpit::runDomeButtonMovie() { + // This command just plays the video of the button moving down and up. + _vm->_video->playMovieBlockingRiven(2); +} + +void DomeSpit::runDomeCheck() { + // Check if we clicked while the golden frame was showing + + VideoEntryPtr video = _vm->_video->findVideoRiven(1); + assert(video); + + int32 curFrame = video->getCurFrame(); + int32 frameCount = video->getFrameCount(); + + // The final frame of the video is the 'golden' frame (double meaning: the + // frame that is the magic one is the one with the golden symbol) but we + // give a 3 frame leeway in either direction. + if (frameCount - curFrame < 3 || curFrame < 3) + _vm->_vars["domecheck"] = 1; +} + +void DomeSpit::resetDomeSliders(uint16 soundId, uint16 startHotspot) { + // The rightmost slider should move left until it finds the next slider, + // then those two continue until they find the third slider. This continues + // until all five sliders have returned their starting slots. + byte slidersFound = 0; + for (uint32 i = 0; i < kDomeSliderSlotCount; i++) { + if (_sliderState & (1 << i)) { + // A slider occupies this spot. Increase the number of sliders we + // have found, but we're not doing any moving this iteration. + slidersFound++; + } else { + // Move all the sliders we have found over one slot + for (byte j = 0; j < slidersFound; j++) { + _sliderState &= ~(1 << (i - j - 1)); + _sliderState |= 1 << (i - j); + } + + // If we have at least one found slider, it has now moved + // so we should redraw and play a tick sound + if (slidersFound) { + _vm->_sound->playSound(soundId); + drawDomeSliders(startHotspot); + _vm->_system->delayMillis(100); + } + } + } + + // Sanity checks - the slider count should always be 5 and we should end up at + // the default state after moving them all over. + assert(slidersFound == 5); + assert(_sliderState == kDomeSliderDefaultState); +} + +void DomeSpit::checkDomeSliders() { + RivenHotspot *resetSlidersHotspot = _vm->getCard()->getHotspotByName("ResetSliders"); + RivenHotspot *openDomeHotspot = _vm->getCard()->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 + resetSlidersHotspot->enable(false); + openDomeHotspot->enable(true); + } else { + // Set the button hotspot to the reset sliders hotspot + resetSlidersHotspot->enable(true); + openDomeHotspot->enable(false); + } +} + +void DomeSpit::checkSliderCursorChange(uint16 startHotspot) { + // Set the cursor based on _sliderState and what hotspot we're over + for (uint16 i = 0; i < kDomeSliderSlotCount; i++) { + RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + i); + if (hotspot->containsPoint(_vm->_system->getEventManager()->getMousePos())) { + if (_sliderState & (1 << (24 - i))) + _vm->_cursor->setCursor(kRivenOpenHandCursor); + else + _vm->_cursor->setCursor(kRivenMainCursor); + _vm->_system->updateScreen(); + break; + } + } +} + +void DomeSpit::dragDomeSlider(uint16 soundId, uint16 startHotspot) { + int16 foundSlider = -1; + + for (uint16 i = 0; i < kDomeSliderSlotCount; i++) { + RivenHotspot *hotspot = _vm->getCard()->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; + + foundSlider = i; + break; + } + } + + // We're not over any slider + if (foundSlider < 0) + return; + + // We've clicked down, so show the closed hand cursor + _vm->_cursor->setCursor(kRivenClosedHandCursor); + _vm->_system->updateScreen(); + + bool done = false; + while (!done) { + Common::Event event; + while (_vm->_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_MOUSEMOVE: + if (foundSlider < 24 && !(_sliderState & (1 << (23 - foundSlider)))) { + RivenHotspot *nextHotspot = _vm->getCard()->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->getCard()->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; + case Common::EVENT_LBUTTONUP: + done = true; + break; + default: + break; + } + } + _vm->_system->delayMillis(10); + } + + // Check to see if we have the right combination + checkDomeSliders(); +} + +void DomeSpit::drawDomeSliders(uint16 startHotspot) { + Common::Rect dstAreaRect = Common::Rect(200, 250, 420, 319); + + // On pspit, the rect is different by two pixels + // (alternatively, we could just use hotspot 3 here, but only on pspit is there a hotspot for this) + if (_vm->getStack()->getId() == kStackPspit) + dstAreaRect.translate(-2, 0); + + // Find out bitmap id + uint16 bitmapId = _vm->findResourceID(ID_TBMP, "*sliders*"); + + for (uint16 i = 0; i < kDomeSliderSlotCount; i++) { + RivenHotspot *hotspot = _vm->getCard()->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 = hotspot->getRect(); + + if (_sliderState & (1 << (24 - i))) + _vm->_gfx->drawImageRect(bitmapId, srcRect, dstRect); + else + _vm->_gfx->drawImageRect(bitmapId + 1, srcRect, dstRect); + } + + _vm->_gfx->updateScreen(); +} + +void DomeSpit::setDomeSliderState(uint32 sliderState) { + _sliderState = sliderState; +} +uint32 DomeSpit::getDomeSliderState() const { + return _sliderState; } } // End of namespace RivenStacks |