370 lines
11 KiB
C++
370 lines
11 KiB
C++
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "asylum/puzzles/wheel.h"
|
|
|
|
#include "asylum/resources/special.h"
|
|
#include "asylum/resources/worldstats.h"
|
|
|
|
#include "asylum/system/cursor.h"
|
|
#include "asylum/system/graphics.h"
|
|
#include "asylum/system/screen.h"
|
|
|
|
#include "asylum/views/scene.h"
|
|
|
|
#include "asylum/asylum.h"
|
|
|
|
namespace Asylum {
|
|
|
|
const GameFlag puzzleWheelFlags[32] = {
|
|
kGameFlag253, kGameFlag257, kGameFlag259, kGameFlag254, kGameFlag258,
|
|
kGameFlag260, kGameFlag253, kGameFlag255, kGameFlag259, kGameFlag254,
|
|
kGameFlag256, kGameFlag260, kGameFlag253, kGameFlag255, kGameFlag257,
|
|
kGameFlag254, kGameFlag256, kGameFlag258, kGameFlag255, kGameFlag257,
|
|
kGameFlag259, kGameFlag256, kGameFlag258, kGameFlag260, kGameFlag253,
|
|
kGameFlag254, kGameFlag255, kGameFlag256, kGameFlag257, kGameFlag258,
|
|
kGameFlag259, kGameFlag260
|
|
};
|
|
|
|
const uint32 puzzleWheelContacts[24] = {
|
|
1, 5, 7, 2, 6,
|
|
8, 1, 3, 7, 2,
|
|
4, 8, 1, 3, 5,
|
|
2, 4, 6, 3, 5,
|
|
7, 4, 6, 8
|
|
};
|
|
|
|
const uint32 puzzleWheelSparks[8] = {
|
|
0, 6, 5, 4, 1, 3, 7, 2
|
|
};
|
|
|
|
const uint32 puzzleWheelClockResourceIndexes[16] = {
|
|
39, 40, 42, 44, 46,
|
|
48, 50, 52, 38, 41,
|
|
43, 45, 47, 49, 51,
|
|
53
|
|
};
|
|
|
|
const int16 puzzleWheelPoints[56][2] = {
|
|
{ 0, 0}, { 0, 0}, { 0, 0}, {250, 254}, {122, 24}, {208, 68}, {238, 160},
|
|
{218, 234}, {162, 228}, { 71, 222}, { 22, 165}, { 35, 70}, {278, 0}, {536, 146},
|
|
{122, 24}, {208, 68}, {238, 160}, {218, 234}, {162, 228}, { 71, 222}, { 22, 165},
|
|
{ 35, 70}, {342, 87}, {342, 87}, {342, 87}, {342, 87}, {342, 87}, {342, 87},
|
|
{342, 87}, {342, 87}, {358, 268}, {342, 87}, {342, 87}, {342, 87}, {342, 87},
|
|
{342, 87}, {342, 87}, {342, 87}, {342, 87}, {342, 87}, {342, 87}, {342, 87},
|
|
{342, 87}, {342, 87}, {342, 87}, {342, 87}, {342, 87}, {536, 146}, {406, 106},
|
|
{402, 217}, {369, 128}, {368, 197}, {452, 184}, {470, 144}, {442, 116}, {347, 166}
|
|
};
|
|
|
|
const int16 puzzleWheelRects[4][4] = {
|
|
{425, 268, 491, 407}, {358, 268, 424, 407}, {561, 251, 594, 324}, {280, 276, 310, 400}
|
|
};
|
|
|
|
PuzzleWheel::PuzzleWheel(AsylumEngine *engine) : Puzzle(engine) {
|
|
_currentRect = -1;
|
|
_resourceIndex = 0;
|
|
_resourceIndexClock = 0;
|
|
_resourceIndexLever = 13;
|
|
|
|
_frameIndexWheel = 0;
|
|
memset(&_frameIndexes, 0, sizeof(_frameIndexes));
|
|
memset(&_frameIndexesSparks, -1, sizeof(_frameIndexesSparks));
|
|
|
|
_showTurnedClock = false;
|
|
_turnWheelRight = false;
|
|
_moveLever = false;
|
|
_moveChain = false;
|
|
}
|
|
|
|
PuzzleWheel::~PuzzleWheel() {
|
|
}
|
|
|
|
void PuzzleWheel::saveLoadWithSerializer(Common::Serializer &s) {
|
|
s.syncAsSint32LE(_resourceIndex);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Event Handling
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool PuzzleWheel::init(const AsylumEvent &) {
|
|
getSpecial()->reset(false);
|
|
|
|
getScreen()->setPalette(getWorld()->graphicResourceIds[1]);
|
|
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[1]);
|
|
|
|
updateCursor();
|
|
getCursor()->show();
|
|
|
|
_currentRect = -2;
|
|
|
|
memset(&_frameIndexesSparks, -1, sizeof(_frameIndexesSparks));
|
|
|
|
for (uint32 i = 0; i < 8; i++) {
|
|
if (_vm->isGameFlagSet((GameFlag)(kGameFlag253 + i)))
|
|
_frameIndexes[i + 1] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[i + 14]) - 1;
|
|
else
|
|
_frameIndexes[i + 1] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[i + 4]) - 1;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void PuzzleWheel::updateScreen() {
|
|
getScreen()->clearGraphicsInQueue();
|
|
getScreen()->draw(getWorld()->graphicResourceIds[0]);
|
|
|
|
// Blinking red light
|
|
getScreen()->draw(getWorld()->graphicResourceIds[12], (uint32)_frameIndexes[11], &puzzleWheelPoints[12]);
|
|
_frameIndexes[11] = (_frameIndexes[11] + 1) % (int32)GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[12]);
|
|
|
|
// Clock
|
|
if (_showTurnedClock)
|
|
getScreen()->draw(getWorld()->graphicResourceIds[_resourceIndexClock], (uint32)_frameIndexes[9], Common::Point(342, 87));
|
|
else
|
|
getScreen()->draw(getWorld()->graphicResourceIds[_resourceIndex + 22], 0, Common::Point(342, 87));
|
|
|
|
// Chain
|
|
getScreen()->draw(getWorld()->graphicResourceIds[3], (uint32)_frameIndexes[0], &puzzleWheelPoints[3]);
|
|
|
|
// Update chain frame index
|
|
if (_moveChain) {
|
|
if (!_frameIndexes[0]) {
|
|
getCursor()->hide();
|
|
getSound()->playSound(getWorld()->graphicResourceIds[65]);
|
|
}
|
|
|
|
_frameIndexes[0] = (_frameIndexes[0] + 1) % (int32)GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[3]);
|
|
|
|
if (!_frameIndexes[0]) {
|
|
closeLocks();
|
|
_moveChain = false;
|
|
getCursor()->show();
|
|
}
|
|
}
|
|
|
|
// Locks
|
|
uint32 frameIndex = 1;
|
|
for (uint32 i = 0; i < 8; i++) {
|
|
ResourceId resourceIndex = 0;
|
|
uint32 pointIndex = 0;
|
|
|
|
if (_vm->isGameFlagSet((GameFlag)(kGameFlag253 + i))) {
|
|
resourceIndex = 14 + i;
|
|
pointIndex = 10 + (4 + i);
|
|
} else {
|
|
resourceIndex = 4 + i;
|
|
pointIndex = 4 + i;
|
|
}
|
|
|
|
getScreen()->draw(getWorld()->graphicResourceIds[resourceIndex], (uint32)_frameIndexes[frameIndex], &puzzleWheelPoints[pointIndex]);
|
|
|
|
if (_frameIndexes[frameIndex] != (int32)GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[resourceIndex]) - 1)
|
|
++_frameIndexes[frameIndex];
|
|
|
|
++frameIndex;
|
|
}
|
|
|
|
// Sparks
|
|
for (uint32 i = 0; i < 8; i++) {
|
|
if (_frameIndexesSparks[i] >= 0) {
|
|
getScreen()->draw(getWorld()->graphicResourceIds[57 + i], (uint32)_frameIndexesSparks[i], &puzzleWheelPoints[48 + i]);
|
|
|
|
if (_frameIndexesSparks[i] == (int32)GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[57 + i]) - 1)
|
|
_frameIndexesSparks[i] = -1;
|
|
else
|
|
++_frameIndexesSparks[i];
|
|
}
|
|
}
|
|
|
|
// Lever
|
|
if (_resourceIndexLever == 13)
|
|
getScreen()->draw(getWorld()->graphicResourceIds[_resourceIndexLever], (uint32)_frameIndexes[10], &puzzleWheelPoints[13]);
|
|
else if (_resourceIndexLever == 54)
|
|
getScreen()->draw(getWorld()->graphicResourceIds[_resourceIndexLever], (uint32)_frameIndexes[10], &puzzleWheelPoints[47]);
|
|
|
|
// Update lever frame index
|
|
if (_moveLever) {
|
|
if (!_frameIndexes[10] && _resourceIndexLever == 13) {
|
|
getCursor()->hide();
|
|
getSound()->playSound(getWorld()->graphicResourceIds[67]);
|
|
}
|
|
|
|
_frameIndexes[10] = (_frameIndexes[10] + 1) % (int32)GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[_resourceIndexLever]);
|
|
|
|
if (!_frameIndexes[10]) {
|
|
if (_resourceIndexLever == 54) {
|
|
_resourceIndexLever = 13;
|
|
toggleLocks();
|
|
_moveLever = false;
|
|
getCursor()->show();
|
|
} else {
|
|
_resourceIndexLever = 54;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Wheel
|
|
getScreen()->draw(getWorld()->graphicResourceIds[30], _frameIndexWheel, &puzzleWheelPoints[30]);
|
|
|
|
// Update wheel frame index
|
|
if (_showTurnedClock) {
|
|
if (!_frameIndexes[9]) {
|
|
getCursor()->hide();
|
|
getSound()->playSound(getWorld()->graphicResourceIds[66]);
|
|
}
|
|
|
|
uint32 frameCountWheel = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[30]);
|
|
if (_turnWheelRight)
|
|
_frameIndexWheel = (_frameIndexWheel + 1) % frameCountWheel;
|
|
else
|
|
_frameIndexWheel = (_frameIndexWheel + frameCountWheel - 1) % frameCountWheel;
|
|
|
|
_frameIndexes[9] = (_frameIndexes[9] + 1) % (int32)GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[_resourceIndexClock]);
|
|
|
|
if (!_frameIndexes[9]) {
|
|
_showTurnedClock = false;
|
|
getCursor()->show();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Show elements on screen
|
|
getScene()->drawRain();
|
|
|
|
// Check for completion
|
|
checkFlags();
|
|
}
|
|
|
|
bool PuzzleWheel::mouseLeftDown(const AsylumEvent &) {
|
|
switch (findRect()) {
|
|
default:
|
|
break;
|
|
|
|
case 0: // Wheel right
|
|
_frameIndexes[9] = 0;
|
|
_turnWheelRight = true;
|
|
_showTurnedClock = true;
|
|
|
|
updateIndex();
|
|
break;
|
|
|
|
case 1: // Wheel left
|
|
_frameIndexes[9] = 0;
|
|
_turnWheelRight = false;
|
|
_showTurnedClock = true;
|
|
|
|
updateIndex();
|
|
break;
|
|
|
|
case 2: // Lever
|
|
_moveLever = true;
|
|
break;
|
|
|
|
case 3: // Chain
|
|
_moveChain = true;
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PuzzleWheel::exitPuzzle() {
|
|
getScreen()->clear();
|
|
_vm->switchEventHandler(getScene());
|
|
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Helpers
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PuzzleWheel::updateCursor() {
|
|
int32 index = findRect();
|
|
|
|
if (_currentRect != index) {
|
|
_currentRect = index;
|
|
|
|
getCursor()->set(getWorld()->graphicResourceIds[2], -1, (index == -1) ? kCursorAnimationNone : kCursorAnimationMirror);
|
|
}
|
|
}
|
|
|
|
int32 PuzzleWheel::findRect() {
|
|
for (uint32 i = 0; i < ARRAYSIZE(puzzleWheelRects); i++) {
|
|
if (_vm->rectContains(&puzzleWheelRects[i], getCursor()->position()))
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void PuzzleWheel::updateIndex() {
|
|
if (_turnWheelRight) {
|
|
_resourceIndexClock = puzzleWheelClockResourceIndexes[_resourceIndex];
|
|
_resourceIndex = (_resourceIndex + 7) % ~7;
|
|
} else {
|
|
_resourceIndexClock = puzzleWheelClockResourceIndexes[_resourceIndex + 8];
|
|
_resourceIndex = (_resourceIndex + 1) % ~7;
|
|
}
|
|
|
|
}
|
|
|
|
void PuzzleWheel::checkFlags() {
|
|
for (uint32 i = 0; i < 8; i++)
|
|
if (!_vm->isGameFlagSet(puzzleWheelFlags[i]))
|
|
return;
|
|
|
|
_vm->setGameFlag(kGameFlag261);
|
|
getScreen()->clear();
|
|
_vm->switchEventHandler(getScene());
|
|
}
|
|
|
|
void PuzzleWheel::closeLocks() {
|
|
for (uint32 i = 0; i < 8; i++) {
|
|
if (!_vm->isGameFlagSet(puzzleWheelFlags[24 + i]))
|
|
continue;
|
|
|
|
getSound()->playSound(getWorld()->graphicResourceIds[69]);
|
|
_vm->clearGameFlag(puzzleWheelFlags[24 + i]);
|
|
_frameIndexes[i + 1] = 0;
|
|
}
|
|
}
|
|
|
|
void PuzzleWheel::toggleLocks() {
|
|
memset(&_frameIndexesSparks, -1, sizeof(_frameIndexesSparks));
|
|
|
|
for (int32 i = 0; i < 3; i++) {
|
|
_vm->toggleGameFlag(puzzleWheelFlags[i + 3 * _resourceIndex]);
|
|
|
|
// Update lock frame indexes
|
|
_frameIndexes[puzzleWheelContacts[i + 3 * _resourceIndex]] = 0;
|
|
|
|
// Update sparks frame indexes
|
|
_frameIndexesSparks[puzzleWheelSparks[puzzleWheelContacts[i + 3 * _resourceIndex] - 1]] = 0;
|
|
|
|
if (_vm->isGameFlagSet(puzzleWheelFlags[i]))
|
|
getSound()->playSound(getWorld()->graphicResourceIds[68]);
|
|
else
|
|
getSound()->playSound(getWorld()->graphicResourceIds[69]);
|
|
}
|
|
}
|
|
|
|
} // End of namespace Asylum
|