scummvm/engines/mohawk/riven_stacks/domespit.cpp

228 lines
7.6 KiB
C++
Raw Normal View History

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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.
*
*/
#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 "mohawk/riven_video.h"
namespace Mohawk {
namespace RivenStacks {
static const uint32 kDomeSliderDefaultState = 0x01F00000;
static const uint32 kDomeSliderSlotCount = 25;
DomeSpit::DomeSpit(MohawkEngine_Riven *vm, uint16 id, const char *sliderBmpName, const char *sliderBgBmpName) :
RivenStack(vm, id),
_sliderBmpName(sliderBmpName),
_sliderBgBmpName(sliderBgBmpName) {
_sliderState = kDomeSliderDefaultState;
}
void DomeSpit::runDomeButtonMovie() {
// This command just plays the video of the button moving down and up.
// The original displayed images of the button going down
RivenVideo *video = _vm->_video->openSlot(2);
video->playBlocking();
}
void DomeSpit::runDomeCheck() {
// Check if we clicked while the golden frame was showing
const RivenVideo *video = _vm->_video->getSlot(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 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->playCardSound("aBigTic");
drawDomeSliders(startHotspot);
_vm->delay(20);
}
}
}
// 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
int16 sliderSlot = getSliderSlotAtPos(startHotspot, getMousePosition());
if (sliderSlot >= 0 && isSliderAtSlot(sliderSlot)) {
_vm->_cursor->setCursor(kRivenOpenHandCursor);
} else {
_vm->_cursor->setCursor(kRivenMainCursor);
}
}
int16 DomeSpit::getSliderSlotAtPos(uint16 startHotspot, const Common::Point &pos) const {
for (uint16 i = 0; i < kDomeSliderSlotCount; i++) {
RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + i);
if (hotspot->containsPoint(pos)) {
return i;
}
}
return -1;
}
bool DomeSpit::isSliderAtSlot(int16 slot) const {
return _sliderState & (1 << (24 - slot));
}
void DomeSpit::dragDomeSlider(uint16 startHotspot) {
int16 draggedSliderSlot = getSliderSlotAtPos(startHotspot, getMousePosition());
// We're not over any slider
if (draggedSliderSlot < 0 || !isSliderAtSlot(draggedSliderSlot)) {
return;
}
// We've clicked down, so show the closed hand cursor
_vm->_cursor->setCursor(kRivenClosedHandCursor);
while (mouseIsDown() && !_vm->shouldQuit()) {
int16 hoveredHotspot = getSliderSlotAtPos(startHotspot, getMousePosition());
if (hoveredHotspot >= 0) {
if (hoveredHotspot > draggedSliderSlot && draggedSliderSlot < 24 && !isSliderAtSlot(draggedSliderSlot + 1)) {
// We've moved the slider right one space
_sliderState &= ~(_sliderState & (1 << (24 - draggedSliderSlot)));
draggedSliderSlot++;
_sliderState |= 1 << (24 - draggedSliderSlot);
// Now play a click sound and redraw
_vm->_sound->playCardSound("aBigTic");
drawDomeSliders(startHotspot);
}
if (hoveredHotspot < draggedSliderSlot && draggedSliderSlot > 0 && !isSliderAtSlot(draggedSliderSlot - 1)) {
// We've moved the slider left one space
_sliderState &= ~(_sliderState & (1 << (24 - draggedSliderSlot)));
draggedSliderSlot--;
_sliderState |= 1 << (24 - draggedSliderSlot);
// Now play a click sound and redraw
_vm->_sound->playCardSound("aBigTic");
drawDomeSliders(startHotspot);
}
}
_vm->doFrame();
}
// 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, buildCardResourceName(_sliderBmpName));
uint16 bgBitmapId = _vm->findResourceID(ID_TBMP, buildCardResourceName(_sliderBgBmpName));
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(bgBitmapId, srcRect, dstRect);
}
_vm->_gfx->updateScreen();
}
Common::String DomeSpit::buildCardResourceName(const Common::String &name) const {
return Common::String::format("%d_%s", _vm->getCard()->getId(), name.c_str());
}
void DomeSpit::setDomeSliderState(uint32 sliderState) {
_sliderState = sliderState;
}
uint32 DomeSpit::getDomeSliderState() const {
return _sliderState;
}
} // End of namespace RivenStacks
} // End of namespace Mohawk