mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-16 14:50:17 +00:00
428 lines
12 KiB
C++
428 lines
12 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 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 "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 Common::Point puzzleWheelPoints[56] = {
|
|
Common::Point( 0, 0),
|
|
Common::Point( 0, 0),
|
|
Common::Point( 0, 0),
|
|
Common::Point(250, 254),
|
|
Common::Point(122, 24),
|
|
Common::Point(208, 68), // 5
|
|
Common::Point(238, 160),
|
|
Common::Point(218, 234),
|
|
Common::Point(162, 228),
|
|
Common::Point( 71, 222),
|
|
Common::Point( 22, 165), // 10
|
|
Common::Point( 35, 70),
|
|
Common::Point(278, 0),
|
|
Common::Point(536, 146),
|
|
Common::Point(122, 24),
|
|
Common::Point(208, 68), // 15
|
|
Common::Point(238, 160),
|
|
Common::Point(218, 234),
|
|
Common::Point(162, 228),
|
|
Common::Point( 71, 222),
|
|
Common::Point( 22, 165), // 20
|
|
Common::Point( 35, 70),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87), // 25
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(358, 268), // 30
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87), // 35
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87), // 40
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87),
|
|
Common::Point(342, 87), // 45
|
|
Common::Point(342, 87),
|
|
Common::Point(536, 146),
|
|
Common::Point(406, 106),
|
|
Common::Point(402, 217),
|
|
Common::Point(369, 128), // 50
|
|
Common::Point(368, 197),
|
|
Common::Point(452, 184),
|
|
Common::Point(470, 144),
|
|
Common::Point(442, 116),
|
|
Common::Point(347, 166) // 55
|
|
};
|
|
|
|
const Common::Rect puzzleWheelRects[4] = {
|
|
Common::Rect(425, 268, 491, 407),
|
|
Common::Rect(358, 268, 424, 407),
|
|
Common::Rect(561, 251, 594, 324),
|
|
Common::Rect(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;
|
|
}
|
|
|
|
bool PuzzleWheel::update(const AsylumEvent &) {
|
|
updateCursor();
|
|
|
|
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();
|
|
getScreen()->drawGraphicsInQueue();
|
|
getScreen()->copyBackBufferToScreen();
|
|
|
|
// Check for completion
|
|
checkFlags();
|
|
|
|
return true;
|
|
}
|
|
|
|
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::mouseRightDown(const AsylumEvent &) {
|
|
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 (puzzleWheelRects[i].contains(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
|