Initial commit
This commit is contained in:
293
engines/asylum/puzzles/board.cpp
Normal file
293
engines/asylum/puzzles/board.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
/* 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 "common/language.h"
|
||||
|
||||
#include "asylum/puzzles/board.h"
|
||||
|
||||
#include "asylum/resources/worldstats.h"
|
||||
|
||||
#include "asylum/system/cursor.h"
|
||||
#include "asylum/system/screen.h"
|
||||
#include "asylum/system/text.h"
|
||||
|
||||
#include "asylum/views/scene.h"
|
||||
|
||||
#include "asylum/asylum.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
PuzzleBoard::PuzzleBoard(AsylumEngine *engine, const PuzzleData *data) : Puzzle(engine) {
|
||||
int i = 0;
|
||||
|
||||
switch (_vm->getLanguage()) {
|
||||
default:
|
||||
case Common::EN_ANY:
|
||||
case Common::RU_RUS:
|
||||
i = 0;
|
||||
break;
|
||||
|
||||
case Common::DE_DEU:
|
||||
i = 1;
|
||||
break;
|
||||
|
||||
case Common::FR_FRA:
|
||||
i = 2;
|
||||
break;
|
||||
|
||||
case Common::HE_ISR:
|
||||
i = 3;
|
||||
break;
|
||||
|
||||
case Common::EU_ESP:
|
||||
i = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(&_data, &data[i], sizeof(PuzzleData));
|
||||
|
||||
// Init board
|
||||
_solved = false;
|
||||
memset(&_charUsed, false, sizeof(_charUsed));
|
||||
memset(&_solvedText, 0, sizeof(_solvedText));
|
||||
_rectIndex = -2;
|
||||
_soundResourceId = kResourceNone;
|
||||
_selectedSlot = -1;
|
||||
_position = 0;
|
||||
}
|
||||
|
||||
void PuzzleBoard::reset() {
|
||||
memset(&_charUsed, false, sizeof(_charUsed));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleBoard::init(const AsylumEvent &) {
|
||||
_rectIndex = -2;
|
||||
_selectedSlot = -1;
|
||||
_solved = false;
|
||||
_soundResourceId = 0;
|
||||
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[32]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[32]);
|
||||
getText()->loadFont(getWorld()->graphicResourceIds[35]);
|
||||
|
||||
// Prepare text to draw
|
||||
_text.clear();
|
||||
|
||||
for (uint32 i = 0; i < _data.soundResourceSize; i++) {
|
||||
_data.soundResources[i].played = false;
|
||||
_text += getText()->get(MAKE_RESOURCE(kResourcePackText, 1068 + _data.soundResources[i].index));
|
||||
_text += ' ';
|
||||
}
|
||||
|
||||
updateScreen();
|
||||
|
||||
getCursor()->show();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PuzzleBoard::updateScreen() {
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[_data.backgroundIndex]);
|
||||
drawText();
|
||||
|
||||
if (!_solved)
|
||||
playSound();
|
||||
|
||||
if (_vm->isGameFlagNotSet(_data.gameFlag)) {
|
||||
if (strcmp(_solvedText, _data.solvedText))
|
||||
return;
|
||||
|
||||
if (_solved) {
|
||||
if (!getSound()->isPlaying(MAKE_RESOURCE(kResourcePackSpeech, 1))) {
|
||||
_vm->setGameFlag(_data.gameFlag);
|
||||
getCursor()->show();
|
||||
getScreen()->clear();
|
||||
_vm->switchEventHandler(getScene());
|
||||
}
|
||||
} else {
|
||||
_solved = true;
|
||||
getCursor()->hide();
|
||||
stopSound();
|
||||
getSound()->playSound(MAKE_RESOURCE(kResourcePackSpeech, 1), false, Config.voiceVolume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PuzzleBoard::exitPuzzle() {
|
||||
if (!stopSound()) {
|
||||
getScreen()->clear();
|
||||
_vm->switchEventHandler(getScene());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleBoard::stopSound() {
|
||||
if (_soundResourceId && getSound()->isPlaying(_soundResourceId)) {
|
||||
getSound()->stopAll(_soundResourceId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PuzzleBoard::drawText() {
|
||||
getText()->loadFont(getWorld()->graphicResourceIds[35]);
|
||||
getText()->draw(0, 99, kTextCenter, Common::Point(25, 50), 16, 590, _text.c_str());
|
||||
|
||||
int32 index = 0;
|
||||
for (int16 x = 215; x < (int16)_data.maxWidth; x += 24) {
|
||||
if (!_solvedText[index])
|
||||
break;
|
||||
|
||||
getText()->setPosition(Common::Point(x, _selectedSlot != index ? 360 : 370));
|
||||
// TODO: Check this for Chinese
|
||||
getText()->drawASCII(_solvedText[index]);
|
||||
|
||||
index += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void PuzzleBoard::playSound() {
|
||||
uint32 index;
|
||||
for (index = 0; index < _data.soundResourceSize; index++) {
|
||||
if (!_data.soundResources[index].played)
|
||||
break;
|
||||
}
|
||||
|
||||
if (index >= _data.soundResourceSize)
|
||||
return;
|
||||
|
||||
if (!_soundResourceId || !getSound()->isPlaying(_soundResourceId)) {
|
||||
_soundResourceId = MAKE_RESOURCE(kResourcePackSharedSound, 2401 + _data.soundResources[index].index);
|
||||
getSound()->playSound(_soundResourceId, false, Config.voiceVolume);
|
||||
_data.soundResources[index].played = true;
|
||||
}
|
||||
}
|
||||
|
||||
int32 PuzzleBoard::findRect() {
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
for (uint32 i = 0; i < _data.charMapSize; i++) {
|
||||
if (mousePos.x >= _data.charMap[i].posX && mousePos.x < _data.charMap[i].posX + 12
|
||||
&& mousePos.y >= _data.charMap[i].posY && mousePos.y < _data.charMap[i].posY + 18)
|
||||
if (!_charUsed[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 PuzzleBoard::checkMouse() {
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
if (mousePos.x >= 215 && mousePos.x < (int16)_data.maxWidth && mousePos.y >= 360 && mousePos.y < 376) {
|
||||
int16 index = (mousePos.x - 215) / 12;
|
||||
|
||||
if (index < 0 || index >= ARRAYSIZE(_solvedText))
|
||||
return -1;
|
||||
|
||||
if (_solvedText[index] != 0 && _solvedText[index] != ' ')
|
||||
return -3;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PuzzleBoard::updateCursor() {
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
if (mousePos.y <= 350) {
|
||||
int32 index = findRect();
|
||||
|
||||
if (index == -1) {
|
||||
if (getCursor()->getResourceId() == getWorld()->graphicResourceIds[34])
|
||||
return;
|
||||
|
||||
_rectIndex = index;
|
||||
|
||||
getCursor()->set(getWorld()->graphicResourceIds[34]);
|
||||
} else {
|
||||
if (getCursor()->getResourceId() == getWorld()->graphicResourceIds[33])
|
||||
return;
|
||||
|
||||
if (index == _rectIndex)
|
||||
return;
|
||||
|
||||
_rectIndex = index;
|
||||
|
||||
getCursor()->set(getWorld()->graphicResourceIds[33]);
|
||||
}
|
||||
} else {
|
||||
if (_vm->isGameFlagSet(_data.gameFlag)) {
|
||||
if (getCursor()->getResourceId() == getWorld()->graphicResourceIds[34])
|
||||
return;
|
||||
|
||||
getCursor()->set(getWorld()->graphicResourceIds[34]);
|
||||
} else {
|
||||
int32 index = checkMouse();
|
||||
|
||||
if (getCursor()->getResourceId() == getWorld()->graphicResourceIds[33])
|
||||
return;
|
||||
|
||||
if (index == _rectIndex)
|
||||
return;
|
||||
|
||||
if (index == -1)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[33], 0, kCursorAnimationNone);
|
||||
else
|
||||
getCursor()->set(getWorld()->graphicResourceIds[33]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PuzzleBoard::checkSlots() {
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
if (mousePos.x >= 215 && mousePos.x < (int16)_data.maxWidth && mousePos.y >= 360 && mousePos.y < 376) {
|
||||
int32 index = (mousePos.x - 215) / 12;
|
||||
|
||||
if (_solvedText[index]) {
|
||||
if (_solvedText[index] == ' ')
|
||||
return;
|
||||
|
||||
if (_selectedSlot == -1) {
|
||||
_selectedSlot = index;
|
||||
} else {
|
||||
SWAP(_solvedText[index], _solvedText[_selectedSlot]);
|
||||
_selectedSlot = -1;
|
||||
}
|
||||
|
||||
updateScreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
100
engines/asylum/puzzles/board.h
Normal file
100
engines/asylum/puzzles/board.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_BOARD_H
|
||||
#define ASYLUM_PUZZLES_BOARD_H
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
#include "asylum/shared.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleBoard : public Puzzle {
|
||||
public:
|
||||
struct SoundResource {
|
||||
int32 index;
|
||||
bool played;
|
||||
};
|
||||
|
||||
struct CharMap {
|
||||
char character;
|
||||
int16 posX, posY;
|
||||
};
|
||||
|
||||
struct PuzzleData {
|
||||
uint32 backgroundIndex;
|
||||
GameFlag gameFlag;
|
||||
uint32 maxWidth;
|
||||
uint32 soundResourceSize;
|
||||
SoundResource soundResources[3];
|
||||
uint32 charMapSize;
|
||||
CharMap charMap[11];
|
||||
bool checkForSpace;
|
||||
uint32 space1Pos, space2Pos;
|
||||
char solvedText[28];
|
||||
};
|
||||
|
||||
PuzzleBoard(AsylumEngine *engine, const PuzzleData *data);
|
||||
|
||||
void reset();
|
||||
|
||||
protected:
|
||||
PuzzleData _data;
|
||||
bool _solved;
|
||||
Common::String _text;
|
||||
bool _charUsed[20];
|
||||
char _solvedText[28]; // KeyHidesTo uses 28 chars, the other puzzles 20
|
||||
uint32 _position;
|
||||
int32 _rectIndex;
|
||||
int32 _selectedSlot;
|
||||
ResourceId _soundResourceId;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void updateScreen();
|
||||
int32 findRect();
|
||||
bool stopSound();
|
||||
void checkSlots();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
bool activate(const AsylumEvent &evt) { return updateScreen(), true; }
|
||||
bool exitPuzzle();
|
||||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void drawText();
|
||||
void playSound();
|
||||
int32 checkMouse();
|
||||
void updateCursor();
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_BOARD_H
|
||||
200
engines/asylum/puzzles/boardkeyhidesto.cpp
Normal file
200
engines/asylum/puzzles/boardkeyhidesto.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/* 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/boardkeyhidesto.h"
|
||||
|
||||
#include "asylum/system/cursor.h"
|
||||
|
||||
#include "asylum/asylum.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
static const PuzzleBoard::PuzzleData puzzleKeyHidesToData[] = {
|
||||
// English
|
||||
{
|
||||
56,
|
||||
kGameFlag283,
|
||||
503,
|
||||
3,
|
||||
{{5, false}, {6, false}, {7, false}},
|
||||
10,
|
||||
{
|
||||
{'I', 30, 53},
|
||||
{'E', 212, 71},
|
||||
{'D', 31, 103},
|
||||
{'H', 447, 134},
|
||||
{'S', 240, 151},
|
||||
{'E', 95, 167},
|
||||
{'O', 372, 182},
|
||||
{'K', 210, 215},
|
||||
{'Y', 440, 247},
|
||||
{'T', 479, 262},
|
||||
{'\0', 0, 0},
|
||||
},
|
||||
true,
|
||||
6, 18,
|
||||
"K E Y H I D E S T O "
|
||||
},
|
||||
// German
|
||||
{
|
||||
56,
|
||||
kGameFlag283,
|
||||
503,
|
||||
3,
|
||||
{{5, false}, {6, false}, {7, false}},
|
||||
9,
|
||||
{
|
||||
{'U', 52, 50},
|
||||
{'R', 28, 66},
|
||||
{'Z', 254, 66},
|
||||
{'E', 40, 82},
|
||||
{'W', 209, 130},
|
||||
{'G', 61, 146},
|
||||
{'T', 33, 162},
|
||||
{'I', 527, 162},
|
||||
{'S', 233, 210},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0}
|
||||
},
|
||||
true,
|
||||
6, 14,
|
||||
"W E G I S T Z U R "
|
||||
},
|
||||
// French
|
||||
{
|
||||
56,
|
||||
kGameFlag283,
|
||||
431,
|
||||
3,
|
||||
{{5, false}, {6, false}, {7, false}},
|
||||
6,
|
||||
{
|
||||
{'L', 357, 66},
|
||||
{'A', 128, 98},
|
||||
{'C', 367, 114},
|
||||
{'L', 237, 130},
|
||||
{'E', 25, 162},
|
||||
{'F', 47, 194},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0}
|
||||
},
|
||||
true,
|
||||
4, 0,
|
||||
"L A C L E F "
|
||||
},
|
||||
// Hebrew
|
||||
{
|
||||
56,
|
||||
kGameFlag283,
|
||||
503,
|
||||
3,
|
||||
{{5, false}, {6, false}, {7, false}},
|
||||
10,
|
||||
{
|
||||
{'\xE7', 593, 58},
|
||||
{'\xEE', 65, 59},
|
||||
{'\xF4', 591, 91},
|
||||
{'\xE0', 203, 106},
|
||||
{'\xE4', 466, 122},
|
||||
{'\xE1', 62, 123},
|
||||
{'\xE9', 468, 155},
|
||||
{'\xFA', 201, 170},
|
||||
{'\xEE', 253, 203},
|
||||
{'\xE7', 210, 218},
|
||||
{'\0', 0, 0},
|
||||
},
|
||||
true,
|
||||
10, 0,
|
||||
"\xE7 \xFA \xF4 \xEE \xE4 \xE0 \xE9 \xE1 \xE7 \xEE "
|
||||
},
|
||||
// Basque
|
||||
{
|
||||
56,
|
||||
kGameFlag283,
|
||||
503,
|
||||
3,
|
||||
{{5, false}, {6, false}, {7, false}},
|
||||
11,
|
||||
{
|
||||
{'A', 45, 56},
|
||||
{'K', 199, 74},
|
||||
{'A', 538, 88},
|
||||
{'D', 276, 121},
|
||||
{'L', 276, 137},
|
||||
{'Z', 170, 152},
|
||||
{'T', 536, 151},
|
||||
{'A', 279, 185},
|
||||
{'I', 494, 200},
|
||||
{'G', 101, 248},
|
||||
{'U', 546, 247}
|
||||
},
|
||||
true,
|
||||
10, 0,
|
||||
"D A U K A G I L T Z A "
|
||||
}
|
||||
};
|
||||
|
||||
PuzzleBoardKeyHidesTo::PuzzleBoardKeyHidesTo(AsylumEngine *engine) : PuzzleBoard(engine, puzzleKeyHidesToData) {
|
||||
}
|
||||
|
||||
void PuzzleBoardKeyHidesTo::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
for (int32 i = 0; i < 12; i++)
|
||||
s.syncAsUint32LE(_charUsed[i]);
|
||||
|
||||
s.syncBytes((byte *)&_solvedText, 28);
|
||||
|
||||
s.syncAsUint32LE(_position);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleBoardKeyHidesTo::mouseLeftDown(const AsylumEvent &) {
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
if (mousePos.y <= 350) {
|
||||
int32 index = findRect();
|
||||
|
||||
if (index != -1 && _position < strlen(_data.solvedText)) {
|
||||
_charUsed[index] = true;
|
||||
_selectedSlot = -1;
|
||||
|
||||
_solvedText[_position++] = _data.charMap[index].character;
|
||||
_solvedText[_position++] = ' ';
|
||||
|
||||
if (_position == _data.space1Pos || _position == _data.space2Pos) {
|
||||
_solvedText[_position++] = ' ';
|
||||
_solvedText[_position++] = ' ';
|
||||
}
|
||||
|
||||
updateScreen();
|
||||
}
|
||||
} else if (_vm->isGameFlagNotSet(kGameFlag283)) {
|
||||
checkSlots();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
47
engines/asylum/puzzles/boardkeyhidesto.h
Normal file
47
engines/asylum/puzzles/boardkeyhidesto.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_BOARDKEYHIDESTO_H
|
||||
#define ASYLUM_PUZZLES_BOARDKEYHIDESTO_H
|
||||
|
||||
#include "asylum/puzzles/board.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleBoardKeyHidesTo : public PuzzleBoard {
|
||||
public:
|
||||
PuzzleBoardKeyHidesTo(AsylumEngine *engine);
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_BOARDKEYHIDESTO_H
|
||||
223
engines/asylum/puzzles/boardsalvation.cpp
Normal file
223
engines/asylum/puzzles/boardsalvation.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
/* 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/boardsalvation.h"
|
||||
|
||||
#include "asylum/system/cursor.h"
|
||||
#include "asylum/system/screen.h"
|
||||
#include "asylum/system/sound.h"
|
||||
|
||||
#include "asylum/views/scene.h"
|
||||
|
||||
#include "asylum/asylum.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
static const PuzzleBoard::PuzzleData puzzleSalvationData[] = {
|
||||
// English
|
||||
{
|
||||
31,
|
||||
kGameFlag281,
|
||||
431,
|
||||
3,
|
||||
{{0, false}, {1, false}, {2, false}},
|
||||
9,
|
||||
{
|
||||
{'I', 61, 53},
|
||||
{'S', 322, 53},
|
||||
{'A', 529, 86},
|
||||
{'L', 256, 117},
|
||||
{'V', 251, 151},
|
||||
{'A', 66, 199},
|
||||
{'T', 436, 229},
|
||||
{'O', 172, 262},
|
||||
{'N', 393, 296},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0}
|
||||
},
|
||||
false,
|
||||
0, 0,
|
||||
"S A L V A T I O N "
|
||||
},
|
||||
// German
|
||||
{
|
||||
31,
|
||||
kGameFlag281,
|
||||
431,
|
||||
3,
|
||||
{{0, false}, {1, false}, {2, false}},
|
||||
8,
|
||||
{
|
||||
{'L', 46, 50},
|
||||
{'O', 133, 82},
|
||||
{'R', 356, 98},
|
||||
{'E', 99, 130},
|
||||
{'N', 120, 146},
|
||||
{'G', 161, 178},
|
||||
{'S', 289, 210},
|
||||
{'U', 371, 226},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0}
|
||||
},
|
||||
false,
|
||||
0, 0,
|
||||
"E R L O S U N G "
|
||||
},
|
||||
// French
|
||||
{
|
||||
31,
|
||||
kGameFlag281,
|
||||
431,
|
||||
3,
|
||||
{{0, false}, {1, false}, {2, false}},
|
||||
7,
|
||||
{
|
||||
{'D', 54, 50},
|
||||
{'U', 266, 66},
|
||||
{'S', 540, 82},
|
||||
{'A', 49, 130},
|
||||
{'L', 199, 162},
|
||||
{'U', 442, 178},
|
||||
{'T', 369, 210},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0}
|
||||
},
|
||||
true,
|
||||
4, 0,
|
||||
"D U S A L U T "
|
||||
},
|
||||
// Hebrew
|
||||
{
|
||||
31,
|
||||
kGameFlag281,
|
||||
431,
|
||||
3,
|
||||
{{0, false}, {1, false}, {2, false}},
|
||||
9,
|
||||
{
|
||||
{'\xE5', 585, 58},
|
||||
{'\xE4', 218, 58},
|
||||
{'\xEC', 134, 87},
|
||||
{'\xE4', 465, 138},
|
||||
{'\xE0', 64, 154},
|
||||
{'\xF2', 523, 203},
|
||||
{'\xE9', 511, 219},
|
||||
{'\xF9', 91, 234},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0}
|
||||
},
|
||||
false,
|
||||
12, 0,
|
||||
"\xE4 \xF2 \xE5 \xF9 \xE9 \xE4 \xEC \xE0 "
|
||||
},
|
||||
// Basque
|
||||
{
|
||||
31,
|
||||
kGameFlag281,
|
||||
455,
|
||||
3,
|
||||
{{0, false}, {1, false}, {2, false}},
|
||||
10,
|
||||
{
|
||||
{'B', 49, 56},
|
||||
{'A', 317, 56},
|
||||
{'O', 546, 85},
|
||||
{'L', 267, 122},
|
||||
{'Z', 157, 152},
|
||||
{'R', 264, 184},
|
||||
{'A', 564, 216},
|
||||
{'I', 452, 231},
|
||||
{'S', 251, 247},
|
||||
{'A', 485, 279},
|
||||
{'\0', 0, 0}
|
||||
},
|
||||
false,
|
||||
0, 0,
|
||||
"S A L B A Z I O R A "
|
||||
},
|
||||
};
|
||||
|
||||
static const uint32 puzzleSalvationSoundResourceIndex[11] = {5, 6, 7, 10, 11, 28, 29, 30, 31, 32, 36};
|
||||
|
||||
PuzzleBoardSalvation::PuzzleBoardSalvation(AsylumEngine *engine) : PuzzleBoard(engine, puzzleSalvationData) {
|
||||
}
|
||||
|
||||
void PuzzleBoardSalvation::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
for (int32 i = 0; i < 9; i++)
|
||||
s.syncAsUint32LE(_charUsed[i]);
|
||||
|
||||
s.syncBytes((byte *)&_solvedText, 20);
|
||||
|
||||
s.syncAsUint32LE(_position);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleBoardSalvation::mouseLeftDown(const AsylumEvent &) {
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
if (mousePos.y <= 350) {
|
||||
int32 index = findRect();
|
||||
|
||||
if (index != -1 && _position < strlen(_data.solvedText)) {
|
||||
_charUsed[index] = true;
|
||||
_selectedSlot = -1;
|
||||
|
||||
_solvedText[_position++] = _data.charMap[index].character;
|
||||
_solvedText[_position++] = ' ';
|
||||
|
||||
if (_position == _data.space1Pos) {
|
||||
_solvedText[_position++] = ' ';
|
||||
_solvedText[_position++] = ' ';
|
||||
}
|
||||
|
||||
updateScreen();
|
||||
}
|
||||
} else if (_vm->isGameFlagNotSet(kGameFlag281)) {
|
||||
checkSlots();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleBoardSalvation::exitPuzzle() {
|
||||
if (!stopSound()) {
|
||||
checkANALText();
|
||||
return PuzzleBoard::exitPuzzle();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleBoardSalvation::checkANALText() {
|
||||
if (!strcmp(_solvedText, "A N A L "))
|
||||
getSound()->playSound(MAKE_RESOURCE(kResourcePackSpeech, puzzleSalvationSoundResourceIndex[rnd(11)]), false, Config.voiceVolume);
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
53
engines/asylum/puzzles/boardsalvation.h
Normal file
53
engines/asylum/puzzles/boardsalvation.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_BOARDSALVATION_H
|
||||
#define ASYLUM_PUZZLES_BOARDSALVATION_H
|
||||
|
||||
#include "asylum/puzzles/board.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleBoardSalvation : public PuzzleBoard {
|
||||
public:
|
||||
PuzzleBoardSalvation(AsylumEngine *engine);
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void checkANALText();
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_BOARDSALVATION_H
|
||||
200
engines/asylum/puzzles/boardyouth.cpp
Normal file
200
engines/asylum/puzzles/boardyouth.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/* 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/boardyouth.h"
|
||||
|
||||
#include "asylum/system/cursor.h"
|
||||
|
||||
#include "asylum/asylum.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
static const PuzzleBoard::PuzzleData puzzleYouthData[] = {
|
||||
// English
|
||||
{
|
||||
55,
|
||||
kGameFlag282,
|
||||
431,
|
||||
2,
|
||||
{{3, false}, {4, false}, {0, false}},
|
||||
8,
|
||||
{
|
||||
{'E', 64, 55},
|
||||
{'U', 26, 69},
|
||||
{'T', 135, 102},
|
||||
{'O', 57, 134},
|
||||
{'H', 417, 152},
|
||||
{'T', 223, 181},
|
||||
{'H', 497, 198},
|
||||
{'Y', 435, 231},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0}
|
||||
},
|
||||
true,
|
||||
6, 0,
|
||||
"T H E Y O U T H "
|
||||
},
|
||||
// German
|
||||
{
|
||||
55,
|
||||
kGameFlag282,
|
||||
503,
|
||||
2,
|
||||
{{3, false}, {4, false}, {0, false}},
|
||||
9,
|
||||
{
|
||||
{'G', 25, 50},
|
||||
{'E', 60, 66},
|
||||
{'D', 471, 82},
|
||||
{'N', 340, 114},
|
||||
{'J', 102, 146},
|
||||
{'U', 311, 162},
|
||||
{'R', 261, 194},
|
||||
{'E', 390, 210},
|
||||
{'D', 470, 226},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0}
|
||||
},
|
||||
true,
|
||||
12, 0,
|
||||
"J U G E N D D E R "
|
||||
},
|
||||
// French
|
||||
{
|
||||
55,
|
||||
kGameFlag282,
|
||||
503,
|
||||
2,
|
||||
{{3, false}, {4, false}, {0, false}},
|
||||
11,
|
||||
{
|
||||
{'E', 64, 50},
|
||||
{'S', 514, 50},
|
||||
{'T', 192, 98},
|
||||
{'J', 297, 114},
|
||||
{'E', 595, 130},
|
||||
{'S', 62, 146},
|
||||
{'U', 376, 146},
|
||||
{'N', 281, 162},
|
||||
{'E', 482, 178},
|
||||
{'E', 66, 194},
|
||||
{'S', 133, 210},
|
||||
},
|
||||
true,
|
||||
6, 0,
|
||||
"E S T J E U N E S S E "
|
||||
},
|
||||
// Hebrew
|
||||
{
|
||||
55,
|
||||
kGameFlag282,
|
||||
431,
|
||||
2,
|
||||
{{3, false}, {4, false}, {0, false}},
|
||||
8,
|
||||
{
|
||||
{'\xF0', 596, 59},
|
||||
{'\xE5', 226, 58},
|
||||
{'\xE4', 113, 74},
|
||||
{'\xE0', 494, 106},
|
||||
{'\xF8', 461, 122},
|
||||
{'\xF2', 76, 155},
|
||||
{'\xFA', 141, 186},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0}
|
||||
},
|
||||
true,
|
||||
10, 0,
|
||||
"\xF8 \xF2 \xE5 \xF0 \xE4 \xFA \xE0 "
|
||||
},
|
||||
// Basque
|
||||
{
|
||||
55,
|
||||
kGameFlag282,
|
||||
431,
|
||||
2,
|
||||
{{3, false}, {4, false}, {0, false}},
|
||||
9,
|
||||
{
|
||||
{'A', 32, 56},
|
||||
{'T', 81, 68},
|
||||
{'K', 124, 102},
|
||||
{'A', 554, 118},
|
||||
{'G', 331, 149},
|
||||
{'Z', 152, 182},
|
||||
{'E', 581, 182},
|
||||
{'I', 304, 198},
|
||||
{'D', 445, 231},
|
||||
{'\0', 0, 0},
|
||||
{'\0', 0, 0}
|
||||
},
|
||||
false,
|
||||
0, 0,
|
||||
"G A Z T E D I A K "
|
||||
},
|
||||
};
|
||||
|
||||
PuzzleBoardYouth::PuzzleBoardYouth(AsylumEngine *engine) : PuzzleBoard(engine, puzzleYouthData) {
|
||||
}
|
||||
|
||||
void PuzzleBoardYouth::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
for (int32 i = 0; i < 9; i++)
|
||||
s.syncAsUint32LE(_charUsed[i]);
|
||||
|
||||
s.syncBytes((byte *)&_solvedText, 20);
|
||||
|
||||
s.syncAsUint32LE(_position);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleBoardYouth::mouseLeftDown(const AsylumEvent &) {
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
if (mousePos.y <= 350) {
|
||||
int32 index = findRect();
|
||||
|
||||
if (index != -1 && _position < strlen(_data.solvedText)) {
|
||||
_charUsed[index] = true;
|
||||
_selectedSlot = -1;
|
||||
|
||||
_solvedText[_position++] = _data.charMap[index].character;
|
||||
_solvedText[_position++] = ' ';
|
||||
|
||||
if (_position == _data.space1Pos) {
|
||||
_solvedText[_position++] = ' ';
|
||||
_solvedText[_position++] = ' ';
|
||||
}
|
||||
|
||||
updateScreen();
|
||||
}
|
||||
} else if (_vm->isGameFlagNotSet(kGameFlag282)) {
|
||||
checkSlots();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
47
engines/asylum/puzzles/boardyouth.h
Normal file
47
engines/asylum/puzzles/boardyouth.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_BOARDYOUTH_H
|
||||
#define ASYLUM_PUZZLES_BOARDYOUTH_H
|
||||
|
||||
#include "asylum/puzzles/board.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleBoardYouth : public PuzzleBoard {
|
||||
public:
|
||||
PuzzleBoardYouth(AsylumEngine *engine);
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_BOARDYOUTH_H
|
||||
173
engines/asylum/puzzles/clock.cpp
Normal file
173
engines/asylum/puzzles/clock.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/* 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/clock.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 uint32 puzzleClockFrameIndexes[28] = {
|
||||
2, 4, 6, 8, 10, 11, 13, 15, 17, 19,
|
||||
21, 0, 19, 21, 0, 2, 4, 6, 8, 9,
|
||||
11, 13, 15, 17, 0, 0, 182, 0
|
||||
};
|
||||
|
||||
const int16 puzzleClockRects[12][4] = {
|
||||
{354, 121, 373, 142}, {384, 119, 405, 146}, {405, 135, 424, 160},
|
||||
{404, 168, 425, 193}, {389, 205, 410, 236}, {359, 240, 383, 270},
|
||||
{325, 255, 341, 284}, {294, 253, 313, 284}, {277, 237, 294, 264},
|
||||
{273, 201, 301, 235}, {290, 168, 315, 195}, {315, 133, 344, 162}
|
||||
};
|
||||
|
||||
PuzzleClock::PuzzleClock(AsylumEngine *engine) : Puzzle(engine) {
|
||||
memset(&_frameIndexes, 0, sizeof(_frameIndexes));
|
||||
_showCursor = false;
|
||||
_rightButtonClicked = false;
|
||||
_currentRect = 0;
|
||||
_currentFrameIndex = 0;
|
||||
}
|
||||
|
||||
PuzzleClock::~PuzzleClock() {
|
||||
}
|
||||
|
||||
void PuzzleClock::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
s.syncAsSint32LE(_frameIndexes[2]);
|
||||
s.syncAsSint32LE(_frameIndexes[1]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleClock::init(const AsylumEvent &) {
|
||||
_currentRect = -2;
|
||||
|
||||
updateCursor();
|
||||
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[6]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[6]);
|
||||
|
||||
getCursor()->show();
|
||||
|
||||
_frameIndexes[1] = 6;
|
||||
_frameIndexes[2] = 10;
|
||||
_currentFrameIndex = 10;
|
||||
_showCursor = false;
|
||||
_rightButtonClicked = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PuzzleClock::updateScreen() {
|
||||
// Draw elements
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[5]);
|
||||
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[2], _frameIndexes[0], Common::Point(322, 187));
|
||||
_frameIndexes[0]++;
|
||||
_frameIndexes[0] %= GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[2]);
|
||||
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[4], _frameIndexes[1], Common::Point(267, 109));
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[3], _frameIndexes[2], Common::Point(274, 124));
|
||||
|
||||
if (_currentFrameIndex == _frameIndexes[2]) {
|
||||
if (_showCursor) {
|
||||
_showCursor = false;
|
||||
getCursor()->show();
|
||||
setFlag();
|
||||
}
|
||||
} else {
|
||||
++_frameIndexes[2];
|
||||
_frameIndexes[2] %= GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[3]);
|
||||
}
|
||||
|
||||
if (_rightButtonClicked) {
|
||||
getScreen()->clear();
|
||||
_vm->switchEventHandler(getScene());
|
||||
} else {
|
||||
if (_vm->isGameFlagSet(kGameFlag511)) {
|
||||
exitPuzzle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PuzzleClock::mouseLeftDown(const AsylumEvent &) {
|
||||
int32 index = findRect();
|
||||
|
||||
if (index == -1)
|
||||
return false;
|
||||
|
||||
_currentFrameIndex = puzzleClockFrameIndexes[index];
|
||||
++_frameIndexes[2];
|
||||
_frameIndexes[2] %= GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[3]);
|
||||
_showCursor = true;
|
||||
|
||||
getCursor()->hide();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleClock::exitPuzzle() {
|
||||
setFlag();
|
||||
_rightButtonClicked = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleClock::updateCursor() {
|
||||
int32 index = findRect();
|
||||
|
||||
if (index != _currentRect) {
|
||||
_currentRect = index;
|
||||
|
||||
if (index == -1)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[7], -1, kCursorAnimationNone);
|
||||
else
|
||||
getCursor()->set(getWorld()->graphicResourceIds[7], -1, kCursorAnimationMirror);
|
||||
}
|
||||
}
|
||||
|
||||
int32 PuzzleClock::findRect() {
|
||||
for (uint32 i = 0; i < ARRAYSIZE(puzzleClockRects); i++) {
|
||||
if (_vm->rectContains(&puzzleClockRects[i], getCursor()->position()))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PuzzleClock::setFlag() {
|
||||
if (_frameIndexes[2] == puzzleClockFrameIndexes[11])
|
||||
_vm->setGameFlag(kGameFlag511);
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
64
engines/asylum/puzzles/clock.h
Normal file
64
engines/asylum/puzzles/clock.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_CLOCK_H
|
||||
#define ASYLUM_PUZZLES_CLOCK_H
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleClock : public Puzzle {
|
||||
public:
|
||||
PuzzleClock(AsylumEngine *engine);
|
||||
~PuzzleClock();
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
uint32 _frameIndexes[3];
|
||||
bool _showCursor;
|
||||
bool _rightButtonClicked;
|
||||
int32 _currentRect;
|
||||
uint32 _currentFrameIndex;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
void updateScreen();
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void updateCursor();
|
||||
int32 findRect();
|
||||
void setFlag();
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_CLOCK_H
|
||||
255
engines/asylum/puzzles/fisherman.cpp
Normal file
255
engines/asylum/puzzles/fisherman.cpp
Normal file
@@ -0,0 +1,255 @@
|
||||
/* 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/fisherman.h"
|
||||
|
||||
#include "asylum/resources/worldstats.h"
|
||||
|
||||
#include "asylum/system/cursor.h"
|
||||
#include "asylum/system/screen.h"
|
||||
|
||||
#include "asylum/views/scene.h"
|
||||
|
||||
#include "asylum/asylum.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
const int16 puzzleFishermanPolygons[31][2] = {
|
||||
{ 10, 53}, {113, 52}, {222, 46}, {328, 51},
|
||||
{426, 51}, {523, 49}, {277, 398}, { 30, 44},
|
||||
{112, 44}, { 93, 400}, { 0, 400}, {130, 44},
|
||||
{210, 44}, {201, 400}, {112, 400}, {224, 44},
|
||||
{315, 44}, {309, 400}, {219, 400}, {326, 44},
|
||||
{411, 44}, {415, 400}, {326, 400}, {422, 44},
|
||||
{506, 44}, {526, 400}, {434, 400}, {523, 44},
|
||||
{607, 44}, {640, 400}, {545, 400}
|
||||
};
|
||||
|
||||
PuzzleFisherman::PuzzleFisherman(AsylumEngine *engine) : Puzzle(engine) {
|
||||
memset(&_state, 0, sizeof(_state));
|
||||
|
||||
_resetPressed = false;
|
||||
_counter = 0;
|
||||
|
||||
_pauseTimer = 0;
|
||||
_allowClick = false;
|
||||
}
|
||||
|
||||
PuzzleFisherman::~PuzzleFisherman() {
|
||||
}
|
||||
|
||||
void PuzzleFisherman::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
for (int i = 0; i < ARRAYSIZE(_state); i++)
|
||||
s.syncAsSint32LE(_state[i]);
|
||||
|
||||
s.syncAsSint32LE(_resetPressed);
|
||||
s.syncAsSint32LE(_counter);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleFisherman::init(const AsylumEvent &evt) {
|
||||
getCursor()->set(getWorld()->graphicResourceIds[47], -1, kCursorAnimationMirror, 7);
|
||||
|
||||
for (uint32 i = 0; i < ARRAYSIZE(_state); i++)
|
||||
if (_vm->isGameFlagNotSet((GameFlag)(kGameFlag801 + i)))
|
||||
_state[i] = false;
|
||||
|
||||
if (_counter == 6) {
|
||||
_vm->clearGameFlag(kGameFlag619);
|
||||
_counter = 0;
|
||||
}
|
||||
|
||||
_allowClick = false;
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[39]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[39]);
|
||||
|
||||
return mouseLeftDown(evt);
|
||||
}
|
||||
|
||||
void PuzzleFisherman::updateScreen() {
|
||||
// Draw background
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
getScreen()->fillRect(0, 0, 640, 480, 251);
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[38], 0, Common::Point(0, 0), kDrawFlagNone, true);
|
||||
|
||||
// Draw 7 graphics
|
||||
for (uint32 i = 0; i < 6; i++) {
|
||||
if (_state[i])
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[40 + i], 0, &puzzleFishermanPolygons[i], kDrawFlagNone, 0, 1);
|
||||
}
|
||||
|
||||
_allowClick = true;
|
||||
|
||||
if (_resetPressed) {
|
||||
++_pauseTimer;
|
||||
|
||||
if (_pauseTimer > 5) {
|
||||
// Reset state
|
||||
memset(&_state, 0, sizeof(_state));
|
||||
|
||||
for (uint32 i = 0; i < 6; i++)
|
||||
_vm->clearGameFlag((GameFlag)(kGameFlag801 + i));
|
||||
|
||||
_resetPressed = false;
|
||||
_allowClick = true;
|
||||
_pauseTimer = 0;
|
||||
// Original bug: if the Sun button was pressed last,
|
||||
// the correct order of buttons wouldn't work until another reset
|
||||
_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (_counter == 6) {
|
||||
++_pauseTimer;
|
||||
|
||||
if (_pauseTimer > 10) {
|
||||
_pauseTimer = 0;
|
||||
|
||||
_vm->setGameFlag(kGameFlag619);
|
||||
getScreen()->setPalette(getWorld()->currentPaletteId);
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PuzzleFisherman::mouseLeftDown(const AsylumEvent &evt) {
|
||||
if (!_allowClick)
|
||||
return false;
|
||||
|
||||
for (uint32 i = 0; i < 6; i++) {
|
||||
if (hitTest(&puzzleFishermanPolygons[i * 4 + 7], evt.mouse)) {
|
||||
if (!_state[i]) {
|
||||
getSound()->playSound(getWorld()->soundResourceIds[9], false, Config.sfxVolume - 10);
|
||||
_state[i] = true;
|
||||
setFlags(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (puzzleFishermanPolygons[6][0] < evt.mouse.x
|
||||
&& puzzleFishermanPolygons[6][1] < evt.mouse.y
|
||||
&& puzzleFishermanPolygons[6][0] + 70 > evt.mouse.x
|
||||
&& puzzleFishermanPolygons[6][1] + 30 > evt.mouse.y) {
|
||||
getSound()->playSound(getWorld()->soundResourceIds[10], false, Config.sfxVolume - 10);
|
||||
|
||||
for (uint32 i = 0; i < 6; i++)
|
||||
_vm->clearGameFlag((GameFlag)(kGameFlag801 + i));
|
||||
|
||||
_resetPressed = true;
|
||||
}
|
||||
|
||||
if (_resetPressed)
|
||||
_allowClick = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleFisherman::exitPuzzle() {
|
||||
getCursor()->hide();
|
||||
getSharedData()->setFlag(kFlag1, true);
|
||||
getScreen()->stopPaletteFade(0, 0, 0);
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleFisherman::updateCursor() {
|
||||
bool found = false;
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
for (uint32 i = 0; i < 6; i++) {
|
||||
if (found)
|
||||
break;
|
||||
|
||||
if (hitTest(&puzzleFishermanPolygons[i * 4 + 7], mousePos)) {
|
||||
if (!_state[i]) {
|
||||
found = true;
|
||||
|
||||
if (getCursor()->getAnimation() != kCursorAnimationMirror)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[47], -1, kCursorAnimationMirror, 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
return;
|
||||
|
||||
if (puzzleFishermanPolygons[6][0] >= mousePos.x
|
||||
|| puzzleFishermanPolygons[6][1] >= mousePos.y
|
||||
|| puzzleFishermanPolygons[6][0] + 70 <= mousePos.x
|
||||
|| puzzleFishermanPolygons[6][1] + 30 <= mousePos.y) {
|
||||
if (getCursor()->getAnimation() != kCursorAnimationNone)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[47], -1, kCursorAnimationNone, 7);
|
||||
else if (getCursor()->getAnimation() != kCursorAnimationMirror)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[47], -1, kCursorAnimationMirror, 7);
|
||||
}
|
||||
}
|
||||
|
||||
void PuzzleFisherman::setFlags(uint32 index) {
|
||||
switch (index) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0:
|
||||
_vm->setGameFlag(kGameFlag801);
|
||||
_counter = (_counter == 2) ? 3 : 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
_vm->setGameFlag(kGameFlag802);
|
||||
_counter = (_counter == 3) ? 4 : 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
_vm->setGameFlag(kGameFlag803);
|
||||
_counter = (_counter == 1) ? 2 : 0;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
_vm->setGameFlag(kGameFlag804);
|
||||
if (_counter == 5) {
|
||||
_allowClick = false;
|
||||
_counter = 6;
|
||||
} else {
|
||||
_counter = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
_vm->setGameFlag(kGameFlag805);
|
||||
_counter = (_counter == 0) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
_vm->setGameFlag(kGameFlag806);
|
||||
_counter = (_counter == 4) ? 5 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
64
engines/asylum/puzzles/fisherman.h
Normal file
64
engines/asylum/puzzles/fisherman.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_FISHERMAN_H
|
||||
#define ASYLUM_PUZZLES_FISHERMAN_H
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleFisherman : public Puzzle {
|
||||
public:
|
||||
PuzzleFisherman(AsylumEngine *engine);
|
||||
~PuzzleFisherman();
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
bool _state[6];
|
||||
int32 _counter;
|
||||
|
||||
int32 _pauseTimer;
|
||||
bool _allowClick;
|
||||
bool _resetPressed;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
void updateScreen();
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void updateCursor();
|
||||
void setFlags(uint32 index);
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_FISHERMAN_H
|
||||
482
engines/asylum/puzzles/hivecontrol.cpp
Normal file
482
engines/asylum/puzzles/hivecontrol.cpp
Normal file
@@ -0,0 +1,482 @@
|
||||
/* 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/hivecontrol.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 Control puzzleHiveControlIntToControl[] = {
|
||||
kControlWingsButton1,
|
||||
kControlWingsButton2,
|
||||
kControlWingsButton3,
|
||||
kControlReset,
|
||||
kControlWheelLeft,
|
||||
kControlWheelRight,
|
||||
kControlButtonRight,
|
||||
kControlButtonLeft,
|
||||
kControlGlyph1,
|
||||
kControlGlyph2,
|
||||
kControlGlyph3,
|
||||
kControlGlyph4,
|
||||
kControlGlyph5,
|
||||
kControlGlyph6
|
||||
};
|
||||
|
||||
PuzzleHiveControl::PuzzleHiveControl(AsylumEngine *engine) : Puzzle(engine) {
|
||||
_rectIndex = 0;
|
||||
_soundVolume = 0;
|
||||
_counter = 0;
|
||||
|
||||
_data_457260 = 0;
|
||||
_data_457264 = 0;
|
||||
|
||||
_prevLeverPosition = 3;
|
||||
_resetFlag = false;
|
||||
memset(&_frameIndexes, 0, sizeof(_frameIndexes));
|
||||
reset();
|
||||
}
|
||||
|
||||
PuzzleHiveControl::~PuzzleHiveControl() {
|
||||
}
|
||||
|
||||
void PuzzleHiveControl::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
// TODO
|
||||
s.skip(6 * 4 * 2);
|
||||
debugC(kDebugLevelSavegame, "[PuzzleHiveControl::saveLoadWithSerializer] Not implemented");
|
||||
|
||||
s.syncAsSint32LE(_soundVolume);
|
||||
}
|
||||
|
||||
void PuzzleHiveControl::reset() {
|
||||
_leverPosition = 3;
|
||||
_leverDelta = 0;
|
||||
_currentControl = kControlNone;
|
||||
_colorL = _colorR = 0;
|
||||
_frameIndexOffset = 0;
|
||||
|
||||
memset(&_glyphFlags, false, sizeof(_glyphFlags));
|
||||
memset(&_wingsState, false, sizeof(_wingsState));
|
||||
|
||||
_frameIndexes[kElementSwirlRim] = 0;
|
||||
if (_leverPosition != _prevLeverPosition) {
|
||||
_leverDelta = (uint32)abs((double)_leverPosition - (double)_prevLeverPosition) * 16 / 5;
|
||||
_currentControl = kControlGlyph4;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleHiveControl::init(const AsylumEvent &) {
|
||||
_controlPoints[kControlWingsButton1] = Common::Point(338, 139);
|
||||
_controlPoints[kControlWingsButton2] = Common::Point(376, 151);
|
||||
_controlPoints[kControlWingsButton3] = Common::Point(403, 162);
|
||||
_controlPoints[kControlReset] = Common::Point(219, 86);
|
||||
_controlPoints[kControlWheelRight] = Common::Point(204, 263);
|
||||
_controlPoints[kControlWheelLeft] = Common::Point(164, 310);
|
||||
_controlPoints[kControlButtonLeft] = Common::Point(320, 375);
|
||||
_controlPoints[kControlButtonRight] = Common::Point(363, 337);
|
||||
_controlPoints[kControlGlyph1] = Common::Point(102, 201);
|
||||
_controlPoints[kControlGlyph2] = Common::Point(101, 171);
|
||||
_controlPoints[kControlGlyph3] = Common::Point(108, 140);
|
||||
_controlPoints[kControlGlyph4] = Common::Point(126, 111);
|
||||
_controlPoints[kControlGlyph5] = Common::Point(140, 85);
|
||||
_controlPoints[kControlGlyph6] = Common::Point(161, 54);
|
||||
|
||||
_rectIndex = -2;
|
||||
_frameIndexes[kElementLever] = (5 - _leverPosition) * (GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[kElementLever]) - 1) / 5;
|
||||
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[29]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[29]);
|
||||
|
||||
getCursor()->show();
|
||||
|
||||
getScreen()->setupTransTables(1, getWorld()->graphicResourceIds[70]);
|
||||
getScreen()->selectTransTable(0);
|
||||
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[73], true, _soundVolume);
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[74], true, Config.ambientVolume);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleHiveControl::mouseLeftDown(const AsylumEvent &) {
|
||||
if (_currentControl != kControlNone)
|
||||
return true;
|
||||
|
||||
_currentControl = findControl();
|
||||
switch (_currentControl) {
|
||||
case kControlNone:
|
||||
break;
|
||||
|
||||
case kControlWingsButton1:
|
||||
getCursor()->hide();
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[81], false, Config.sfxVolume - 10);
|
||||
|
||||
if (_wingsState[1] != _wingsState[2]) {
|
||||
if (_wingsState[0])
|
||||
--_frameIndexOffset;
|
||||
else
|
||||
++_frameIndexOffset;
|
||||
}
|
||||
|
||||
_frameIndexOffset += _wingsState[0] ? -1 : 1;
|
||||
_wingsState[0] = !_wingsState[0];
|
||||
_frameIndexes[kElementLensLeft] = _colorL * 8 + _frameIndexOffset;
|
||||
_frameIndexes[kElementLensRight] = _colorR * 8 + _frameIndexOffset;
|
||||
break;
|
||||
|
||||
case kControlWingsButton2:
|
||||
getCursor()->hide();
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[81], false, Config.sfxVolume - 10);
|
||||
|
||||
if (_wingsState[0] != _wingsState[2]) {
|
||||
if (_wingsState[1])
|
||||
--_frameIndexOffset;
|
||||
else
|
||||
++_frameIndexOffset;
|
||||
}
|
||||
|
||||
_frameIndexOffset += _wingsState[1] ? -2 : 2;
|
||||
_wingsState[1] = !_wingsState[1];
|
||||
_frameIndexes[kElementLensLeft] = _colorL * 8 + _frameIndexOffset;
|
||||
_frameIndexes[kElementLensRight] = _colorR * 8 + _frameIndexOffset;
|
||||
break;
|
||||
|
||||
case kControlWingsButton3:
|
||||
getCursor()->hide();
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[81], false, Config.sfxVolume - 10);
|
||||
|
||||
if (_wingsState[0] != _wingsState[1]) {
|
||||
if (_wingsState[2])
|
||||
--_frameIndexOffset;
|
||||
else
|
||||
++_frameIndexOffset;
|
||||
}
|
||||
|
||||
_frameIndexOffset += (_wingsState[2] ? -3 : 3);
|
||||
_wingsState[2] = !_wingsState[2];
|
||||
_frameIndexes[kElementLensLeft] = _colorL * 8 + _frameIndexOffset;
|
||||
_frameIndexes[kElementLensRight] = _colorR * 8 + _frameIndexOffset;
|
||||
break;
|
||||
|
||||
case kControlReset:
|
||||
getCursor()->hide();
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[78], false, Config.sfxVolume - 10);
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[79], false, Config.sfxVolume - 10);
|
||||
_resetFlag = true;
|
||||
reset();
|
||||
break;
|
||||
|
||||
case kControlWheelLeft:
|
||||
getCursor()->hide();
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[80], false, Config.sfxVolume - 10);
|
||||
_colorL = (_colorL + 1) % 3;
|
||||
break;
|
||||
|
||||
case kControlWheelRight:
|
||||
getCursor()->hide();
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[80], false, Config.sfxVolume - 10);
|
||||
_colorR = (_colorR + 1) % 3;
|
||||
break;
|
||||
|
||||
case kControlButtonLeft:
|
||||
getCursor()->hide();
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[77], false, Config.sfxVolume - 10);
|
||||
|
||||
if (!_glyphFlags[0][_leverPosition]) {
|
||||
_glyphFlags[0][_leverPosition] = puzzleHiveControlHieroglyphs[0][_leverPosition] == _frameIndexes[kElementLensLeft];
|
||||
if (_glyphFlags[0][_leverPosition]) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[83], false, Config.sfxVolume - 10);
|
||||
++_frameIndexes[kElementSwirlRim];
|
||||
|
||||
// Check for puzzle completion
|
||||
if (_frameIndexes[kElementSwirlRim] == 12) {
|
||||
getSound()->stop(getWorld()->graphicResourceIds[73]);
|
||||
getSound()->stop(getWorld()->graphicResourceIds[74]);
|
||||
|
||||
getScreen()->clear();
|
||||
getScreen()->setupTransTables(3, getWorld()->cellShadeMask1, getWorld()->cellShadeMask2, getWorld()->cellShadeMask3);
|
||||
getScreen()->selectTransTable(1);
|
||||
|
||||
_vm->setGameFlag(kGameFlagSolveHiveControl);
|
||||
_vm->switchEventHandler(getScene());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kControlButtonRight:
|
||||
getCursor()->hide();
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[77], false, Config.sfxVolume - 10);
|
||||
if (!_glyphFlags[1][_leverPosition]) {
|
||||
_glyphFlags[1][_leverPosition] = puzzleHiveControlHieroglyphs[1][_leverPosition] == _frameIndexes[kElementLensRight];
|
||||
if (_glyphFlags[1][_leverPosition]) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[83], false, Config.sfxVolume - 10);
|
||||
++_frameIndexes[kElementSwirlRim];
|
||||
|
||||
// Check for puzzle completion
|
||||
if (_frameIndexes[kElementSwirlRim] == 12) {
|
||||
getSound()->stop(getWorld()->graphicResourceIds[73]);
|
||||
getSound()->stop(getWorld()->graphicResourceIds[74]);
|
||||
|
||||
getScreen()->clear();
|
||||
getScreen()->setupTransTables(3, getWorld()->cellShadeMask1, getWorld()->cellShadeMask2, getWorld()->cellShadeMask3);
|
||||
getScreen()->selectTransTable(1);
|
||||
|
||||
_vm->setGameFlag(kGameFlagSolveHiveControl);
|
||||
_vm->switchEventHandler(getScene());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kControlGlyph1:
|
||||
case kControlGlyph2:
|
||||
case kControlGlyph3:
|
||||
case kControlGlyph4:
|
||||
case kControlGlyph5:
|
||||
case kControlGlyph6:
|
||||
_leverPosition = _currentControl - 49;
|
||||
_leverDelta = (uint32)abs((double)_leverPosition - (double)_prevLeverPosition) * (GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[kElementLever]) - 1) / 5;
|
||||
if (_leverDelta)
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[76], false, Config.sfxVolume - 10);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleHiveControl::exitPuzzle() {
|
||||
if (_leverDelta) {
|
||||
_leverDelta = 0;
|
||||
_prevLeverPosition = _leverPosition;
|
||||
_currentControl = kControlNone;
|
||||
}
|
||||
|
||||
getSound()->stop(getWorld()->graphicResourceIds[73]);
|
||||
getSound()->stop(getWorld()->graphicResourceIds[74]);
|
||||
|
||||
getScreen()->clear();
|
||||
getScreen()->setupTransTables(3, getWorld()->cellShadeMask1, getWorld()->cellShadeMask2, getWorld()->cellShadeMask3);
|
||||
getScreen()->selectTransTable(1);
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleHiveControl::updateCursor() {
|
||||
int32 index = findControl();
|
||||
|
||||
if (_rectIndex == index)
|
||||
return;
|
||||
|
||||
_rectIndex = index;
|
||||
if (index == -1)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[30], -1, kCursorAnimationNone);
|
||||
else
|
||||
getCursor()->set(getWorld()->graphicResourceIds[30], -1);
|
||||
}
|
||||
|
||||
Control PuzzleHiveControl::findControl() {
|
||||
for (uint32 i = 0; i < ARRAYSIZE(puzzleHiveControlIntToControl); ++i)
|
||||
if (hitTest1(puzzleHiveControlIntToControl[i], getCursor()->position(), _controlPoints[puzzleHiveControlIntToControl[i]]))
|
||||
return puzzleHiveControlIntToControl[i];
|
||||
|
||||
return kControlNone;
|
||||
}
|
||||
|
||||
void PuzzleHiveControl::updateScreen() {
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[28], 0, Common::Point(0, 0), kDrawFlagNone, 0, 3);
|
||||
|
||||
switch (_currentControl) {
|
||||
case kControlNone:
|
||||
break;
|
||||
case kControlGlyph1:
|
||||
case kControlGlyph2:
|
||||
case kControlGlyph3:
|
||||
case kControlGlyph4:
|
||||
case kControlGlyph5:
|
||||
case kControlGlyph6:
|
||||
if (_leverDelta) {
|
||||
if (_leverPosition > _prevLeverPosition)
|
||||
--_frameIndexes[kElementLever];
|
||||
else
|
||||
++_frameIndexes[kElementLever];
|
||||
--_leverDelta;
|
||||
if (_leverDelta == 0) {
|
||||
_prevLeverPosition = _leverPosition;
|
||||
_currentControl = kControlNone;
|
||||
}
|
||||
} else
|
||||
_currentControl = kControlNone;
|
||||
break;
|
||||
default:
|
||||
_frameIndexes[_currentControl] = (_frameIndexes[_currentControl] + 1) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[_currentControl]);
|
||||
if (_frameIndexes[_currentControl] == 0) {
|
||||
getCursor()->show();
|
||||
if (_currentControl == kControlWheelLeft || _currentControl == kControlWheelRight) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[75], false, Config.sfxVolume - 10);
|
||||
if (_currentControl == kControlWheelLeft)
|
||||
_frameIndexes[kElementLensLeft] = (_frameIndexes[kElementLensLeft] + 8) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[kElementLensLeft]);
|
||||
else
|
||||
_frameIndexes[kElementLensRight] = (_frameIndexes[kElementLensRight] + 8) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[kElementLensRight]);
|
||||
}
|
||||
_currentControl = kControlNone;
|
||||
}
|
||||
}
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementSwirl], _frameIndexes[kElementSwirl], Common::Point(486, 291), kDrawFlagNone, 0, 2);
|
||||
_frameIndexes[kElementSwirl] = (_frameIndexes[kElementSwirl] + 1) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[kElementSwirl]);
|
||||
|
||||
if (_resetFlag) {
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementResetDynamic], _frameIndexes[kElementResetDynamic], Common::Point(211, 77), kDrawFlagNone, 0, 2);
|
||||
_frameIndexes[kElementResetDynamic] = (_frameIndexes[kElementResetDynamic] + 1) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[kElementResetDynamic]);
|
||||
if (_frameIndexes[kElementResetDynamic] == 0) {
|
||||
_resetFlag = false;
|
||||
getCursor()->show();
|
||||
if (!(_wingsState[0] || _wingsState[1] || _wingsState[2])) {
|
||||
_frameIndexes[kElementLensLeft] = 0;
|
||||
_frameIndexes[kElementLensRight] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementFlyHead], _frameIndexes[kElementFlyHead], Common::Point(258, 86), kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementResetStatic], _frameIndexes[kElementResetStatic], Common::Point(232, 77), kDrawFlagNone, 0, 2);
|
||||
_frameIndexes[kElementFlyHead] = (_frameIndexes[kElementFlyHead] + 1) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[kElementFlyHead]);
|
||||
}
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlWingsButton1], _frameIndexes[kControlWingsButton1], _controlPoints[kControlWingsButton1], kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlWingsButton2], _frameIndexes[kControlWingsButton2], _controlPoints[kControlWingsButton2], kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlWingsButton3], _frameIndexes[kControlWingsButton3], _controlPoints[kControlWingsButton3], kDrawFlagNone, 0, 2);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementLever], _frameIndexes[kElementLever], Common::Point(9, 40), kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlReset], _frameIndexes[kControlReset], _controlPoints[kControlReset], kDrawFlagNone, 0, 2);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlWheelRight], _frameIndexes[kControlWheelRight], _controlPoints[kControlWheelRight], kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlWheelLeft], _frameIndexes[kControlWheelLeft], _controlPoints[kControlWheelLeft], kDrawFlagNone, 0, 2);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlButtonLeft], _frameIndexes[kControlButtonLeft], _controlPoints[kControlButtonLeft], kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlButtonRight], _frameIndexes[kControlButtonRight], _controlPoints[kControlButtonRight], kDrawFlagNone, 0, 2);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementWingLeft1], _frameIndexes[kElementWingLeft1], Common::Point(326, 162), kDrawFlagNone, 1, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementWingRight1], _frameIndexes[kElementWingRight1], Common::Point(374, 86), kDrawFlagNone, 1, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementWingLeft2], _frameIndexes[kElementWingLeft2], Common::Point(275, 186), kDrawFlagNone, 1, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementWingRight2], _frameIndexes[kElementWingRight2], Common::Point(419, 59), kDrawFlagNone, 1, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementWingLeft3], _frameIndexes[kElementWingLeft3], Common::Point(386, 196), kDrawFlagNone, 1, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementWingRight3], _frameIndexes[kElementWingRight3], Common::Point(433, 111), kDrawFlagNone, 1, 1);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlGlyph1], _frameIndexes[kControlGlyph1], _controlPoints[kControlGlyph1], kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlGlyph2], _frameIndexes[kControlGlyph2], _controlPoints[kControlGlyph2], kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlGlyph3], _frameIndexes[kControlGlyph3], _controlPoints[kControlGlyph3], kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlGlyph4], _frameIndexes[kControlGlyph4], _controlPoints[kControlGlyph4], kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlGlyph5], _frameIndexes[kControlGlyph5], _controlPoints[kControlGlyph5], kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kControlGlyph6], _frameIndexes[kControlGlyph6], _controlPoints[kControlGlyph6], kDrawFlagNone, 0, 2);
|
||||
|
||||
bool reseted = false;
|
||||
for (uint32 i = 0; i < 3; ++i) {
|
||||
if (_wingsState[i]) {
|
||||
if (_frameIndexes[kElementWingLeft1 + 2*i] != GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[kElementWingLeft1 + 2*i]) - 1)
|
||||
_frameIndexes[kElementWingLeft1 + 2*i] = (_frameIndexes[kElementWingLeft1 + 2*i] + 1) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[kElementWingLeft1 + 2*i]);
|
||||
if (_frameIndexes[kElementWingRight1 + 2*i] != GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[kElementWingRight1 + 2*i]) - 1)
|
||||
_frameIndexes[kElementWingRight1 + 2*i] = (_frameIndexes[kElementWingRight1 + 2*i] + 1) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[kElementWingRight1 + 2*i]);
|
||||
} else {
|
||||
if (_frameIndexes[kElementWingLeft1 + 2*i] > 0) {
|
||||
--_frameIndexes[kElementWingLeft1 + 2*i];
|
||||
if (_resetFlag && _frameIndexes[kElementWingLeft1 + 2*i] == 0 && !reseted) {
|
||||
_frameIndexes[kElementLensLeft] = 0;
|
||||
reseted = true;
|
||||
}
|
||||
}
|
||||
if (_frameIndexes[kElementWingRight1 + 2*i ] > 0) {
|
||||
--_frameIndexes[kElementWingRight1 + 2*i];
|
||||
if (_resetFlag && _frameIndexes[kElementWingRight1 + 2*i] == 0 && !reseted) {
|
||||
_frameIndexes[kElementLensRight] = 0;
|
||||
reseted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementLensLeft], _frameIndexes[kElementLensLeft], Common::Point(305, 216), kDrawFlagNone, 0, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementLensRight], _frameIndexes[kElementLensRight], Common::Point(411, 65), kDrawFlagNone, 0, 2);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementIndicator], _frameIndexes[kElementSwirlRim], Common::Point(158, 148), kDrawFlagNone, 0, 2);
|
||||
|
||||
for (uint32 i = 0; i < 6; ++i) {
|
||||
if (_glyphFlags[0][i])
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[58 + i], 0, Common::Point(104, 58), kDrawFlagNone, 0, 1);
|
||||
if (_glyphFlags[1][i])
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[64 + i], 0, Common::Point(133, 70), kDrawFlagNone, 0, 1);
|
||||
}
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[kElementSwirlRim], _frameIndexes[kElementSwirlRim], Common::Point(458, 278), kDrawFlagNone, 0, 2);
|
||||
|
||||
if (!_data_457260 && !_data_457264)
|
||||
playSound();
|
||||
|
||||
if (_counter) {
|
||||
if (_counter < 30 || getSound()->isPlaying(getWorld()->graphicResourceIds[83])) {
|
||||
++_counter;
|
||||
} else {
|
||||
exitPuzzle();
|
||||
getCursor()->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PuzzleHiveControl::playSound() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
bool PuzzleHiveControl::hitTest1(Control control, const Common::Point &point, const Common::Point &location) {
|
||||
if (control == kControlNone)
|
||||
error("[PuzzleHiveControl::hitTest1] Invalid control");
|
||||
|
||||
GraphicResource resource(_vm);
|
||||
resource.load(getWorld()->graphicResourceIds[control]);
|
||||
GraphicFrame *frame = resource.getFrame(0);
|
||||
Common::Point point1(point.x - location.x, point.y - location.y);
|
||||
|
||||
if (!frame->getRect().contains(point1)) {
|
||||
return false;
|
||||
} else {
|
||||
point1.x -= frame->x;
|
||||
point1.y -= frame->y;
|
||||
return *((byte *)frame->surface.getPixels() + point1.x + frame->surface.pitch * point1.y) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
121
engines/asylum/puzzles/hivecontrol.h
Normal file
121
engines/asylum/puzzles/hivecontrol.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_HIVECONTROL_H
|
||||
#define ASYLUM_PUZZLES_HIVECONTROL_H
|
||||
|
||||
#include "common/hashmap.h"
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
enum Control {
|
||||
kControlNone = -1,
|
||||
kControlWingsButton1 = 34,
|
||||
kControlWingsButton2 = 35,
|
||||
kControlWingsButton3 = 36,
|
||||
kControlReset = 38,
|
||||
kControlWheelLeft = 39,
|
||||
kControlWheelRight = 40,
|
||||
kControlButtonRight = 41,
|
||||
kControlButtonLeft = 42,
|
||||
kControlGlyph1 = 49,
|
||||
kControlGlyph2 = 50,
|
||||
kControlGlyph3 = 51,
|
||||
kControlGlyph4 = 52,
|
||||
kControlGlyph5 = 53,
|
||||
kControlGlyph6 = 54
|
||||
};
|
||||
|
||||
static const uint32 puzzleHiveControlHieroglyphs[2][6] = {
|
||||
{5, 12, 22, 13, 20, 6},
|
||||
{21, 4, 14, 13, 20, 6}
|
||||
};
|
||||
|
||||
class PuzzleHiveControl : public Puzzle {
|
||||
public:
|
||||
PuzzleHiveControl(AsylumEngine *engine);
|
||||
~PuzzleHiveControl();
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
enum Element {
|
||||
kElementSwirl = 31,
|
||||
kElementFlyHead = 32,
|
||||
kElementResetDynamic = 33,
|
||||
kElementLever = 37,
|
||||
kElementWingLeft1 = 43,
|
||||
kElementWingRight1 = 44,
|
||||
kElementWingLeft2 = 45,
|
||||
kElementWingRight2 = 46,
|
||||
kElementWingLeft3 = 47,
|
||||
kElementWingRight3 = 48,
|
||||
kElementLensLeft = 55,
|
||||
kElementLensRight = 56,
|
||||
kElementIndicator = 57,
|
||||
kElementSwirlRim = 71,
|
||||
kElementResetStatic = 72
|
||||
};
|
||||
|
||||
int32 _soundVolume;
|
||||
int32 _rectIndex;
|
||||
uint32 _counter;
|
||||
|
||||
int32 _data_457260;
|
||||
int32 _data_457264;
|
||||
|
||||
uint32 _frameIndexes[73];
|
||||
Common::HashMap<uint32, Common::Point> _controlPoints;
|
||||
|
||||
bool _resetFlag;
|
||||
bool _wingsState[3];
|
||||
bool _glyphFlags[2][6];
|
||||
Control _currentControl;
|
||||
uint32 _colorL, _colorR;
|
||||
uint32 _frameIndexOffset;
|
||||
uint32 _leverPosition, _prevLeverPosition, _leverDelta;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
void updateScreen();
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void updateCursor();
|
||||
Control findControl();
|
||||
void playSound();
|
||||
void reset();
|
||||
bool hitTest1(Control control, const Common::Point &point, const Common::Point &location);
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_HIVECONTROL_H
|
||||
199
engines/asylum/puzzles/hivemachine.cpp
Normal file
199
engines/asylum/puzzles/hivemachine.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/* 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/hivemachine.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 int16 keyPoints[5][2] = {
|
||||
{246, 106}, {377, 171}, {319, 250}, {220, 249}, {167, 154}
|
||||
};
|
||||
|
||||
const int16 indicatorPoints[6][2] = {
|
||||
{260, 410}, {279, 411}, {298, 411}, {318, 412}, {338, 413}, {358, 413}
|
||||
};
|
||||
|
||||
PuzzleHiveMachine::PuzzleHiveMachine(AsylumEngine *engine) : Puzzle(engine) {
|
||||
_counterRed = _counterGreen = _counterKey = 0;
|
||||
_rectIndex = -2;
|
||||
_frameIndex = 0;
|
||||
_frameIndex1 = 0;
|
||||
_soundingNote = kMusicalNoteNone;
|
||||
_notesNumber = 0;
|
||||
_ok = false;
|
||||
}
|
||||
|
||||
PuzzleHiveMachine::~PuzzleHiveMachine() {
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleHiveMachine::init(const AsylumEvent &) {
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[9]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[9]);
|
||||
_rectIndex = -2;
|
||||
|
||||
getCursor()->show();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleHiveMachine::mouseLeftDown(const AsylumEvent &) {
|
||||
if (_rectIndex != -1 && _counterRed == 0) {
|
||||
_soundingNote = MusicalNote(_rectIndex);
|
||||
_melody.push_back(_soundingNote);
|
||||
_notesNumber = (_notesNumber + 1) % 7;
|
||||
_counterKey = 10;
|
||||
_frameIndex1 = 0;
|
||||
playSound();
|
||||
|
||||
if (_melody.size() == 6) {
|
||||
_ok = (_melody[0] == kMusicalNoteB) &&
|
||||
(_melody[1] == kMusicalNoteD) &&
|
||||
(_melody[2] == kMusicalNoteD) &&
|
||||
(_melody[3] == kMusicalNoteA) &&
|
||||
(_melody[4] == kMusicalNoteF) &&
|
||||
(_melody[5] == kMusicalNoteE);
|
||||
if (!_ok) {
|
||||
_melody.clear();
|
||||
_counterRed = 30;
|
||||
} else
|
||||
_counterGreen = 10;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleHiveMachine::exitPuzzle() {
|
||||
_notesNumber = 0;
|
||||
_melody.clear();
|
||||
|
||||
getScreen()->clear();
|
||||
_vm->switchEventHandler(getScene());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleHiveMachine::updateCursor() {
|
||||
int32 index = findRect();
|
||||
|
||||
if (_rectIndex == index)
|
||||
return;
|
||||
|
||||
_rectIndex = index;
|
||||
if (index == -1)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[12], -1, kCursorAnimationNone);
|
||||
else
|
||||
getCursor()->set(getWorld()->graphicResourceIds[12], -1);
|
||||
}
|
||||
|
||||
int32 PuzzleHiveMachine::findRect() {
|
||||
Common::Point mouse = getCursor()->position();
|
||||
GraphicResource resource(_vm);
|
||||
|
||||
for (uint32 i = 0; i < 5; ++i) {
|
||||
resource.load(getWorld()->graphicResourceIds[i + 13]);
|
||||
GraphicFrame *frame = resource.getFrame(0);
|
||||
Common::Point point(mouse.x - keyPoints[i][0], mouse.y - keyPoints[i][1]);
|
||||
|
||||
if (frame->getRect().contains(point)) {
|
||||
point.x -= frame->x;
|
||||
point.y -= frame->y;
|
||||
if (frame->surface.getPixel(point.x, point.y))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PuzzleHiveMachine::updateScreen() {
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[8], 0, Common::Point(0, 0), kDrawFlagNone, 0, 2);
|
||||
|
||||
if (_ok) {
|
||||
if (_counterGreen > 1)
|
||||
--_counterGreen;
|
||||
else if (_counterGreen-- == 1) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[86], false, Config.sfxVolume - 10);
|
||||
_vm->setGameFlag(kGameFlagSolveHiveMachine);
|
||||
_vm->switchEventHandler(getScene());
|
||||
}
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[11], 0, Common::Point(271, 369), kDrawFlagNone, 0, 1);
|
||||
} else if (_counterRed) {
|
||||
if (_counterRed == 1)
|
||||
_notesNumber = 0;
|
||||
else if (_counterRed == 30)
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[85], false, Config.sfxVolume - 10);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[10], 0, Common::Point(318, 372), kDrawFlagNone, 0, 1);
|
||||
|
||||
--_counterRed;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < 5; ++i) {
|
||||
uint32 resourceId = i + 13, frameIndex;
|
||||
if (_soundingNote == MusicalNote(i)) {
|
||||
resourceId += 5;
|
||||
frameIndex = _frameIndex1;
|
||||
} else
|
||||
frameIndex = _frameIndex;
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[resourceId], frameIndex, &keyPoints[i], kDrawFlagNone, 0, 1);
|
||||
}
|
||||
|
||||
if (_counterKey)
|
||||
--_counterKey;
|
||||
else {
|
||||
_soundingNote = kMusicalNoteNone;
|
||||
_frameIndex1 = 0;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < _notesNumber; ++i)
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[84], 0, &indicatorPoints[i], kDrawFlagNone, 0, 1);
|
||||
|
||||
_frameIndex = (_frameIndex + 1) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[13]);
|
||||
if (_counterKey)
|
||||
_frameIndex1 = (_frameIndex1 + 1) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[18]);
|
||||
}
|
||||
|
||||
void PuzzleHiveMachine::playSound() {
|
||||
if (_soundingNote == kMusicalNoteNone)
|
||||
error("[PuzzleHiveMachine::playSound] Invalid sound resource id");
|
||||
|
||||
uint32 soundMap[] = {4, 2, 3, 0, 1};
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[soundMap[_soundingNote] + 23], false, Config.sfxVolume - 10);
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
74
engines/asylum/puzzles/hivemachine.h
Normal file
74
engines/asylum/puzzles/hivemachine.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_HIVEMACHINE_H
|
||||
#define ASYLUM_PUZZLES_HIVEMACHINE_H
|
||||
|
||||
#include "common/array.h"
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleHiveMachine : public Puzzle {
|
||||
public:
|
||||
PuzzleHiveMachine(AsylumEngine *engine);
|
||||
~PuzzleHiveMachine();
|
||||
|
||||
private:
|
||||
enum MusicalNote {
|
||||
kMusicalNoteNone = -1,
|
||||
kMusicalNoteF,
|
||||
kMusicalNoteD,
|
||||
kMusicalNoteE,
|
||||
kMusicalNoteA,
|
||||
kMusicalNoteB
|
||||
};
|
||||
|
||||
uint32 _counterRed, _counterGreen, _counterKey;
|
||||
int32 _rectIndex;
|
||||
uint32 _frameIndex, _frameIndex1;
|
||||
Common::Array<MusicalNote> _melody;
|
||||
MusicalNote _soundingNote;
|
||||
uint32 _notesNumber;
|
||||
bool _ok;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void updateCursor();
|
||||
int32 findRect();
|
||||
void updateScreen();
|
||||
void playSound();
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_HIVEMACHINE_H
|
||||
250
engines/asylum/puzzles/lock.cpp
Normal file
250
engines/asylum/puzzles/lock.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
/* 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/lock.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 int16 puzzleLockPolygons[16][2] = {
|
||||
{159, 293}, {151, 318}, {179, 322}, {185, 298},
|
||||
{212, 303}, {207, 327}, {234, 332}, {239, 308},
|
||||
{149, 333}, {146, 365}, {172, 369}, {176, 338},
|
||||
{202, 345}, {200, 375}, {226, 379}, {231, 347}
|
||||
};
|
||||
|
||||
PuzzleLock::PuzzleLock(AsylumEngine *engine) : Puzzle(engine) {
|
||||
memset(&_frameIndexes, 0, sizeof(_frameIndexes));
|
||||
_frameIndexes[0] = _frameIndexes[1] = _frameIndexes[2] = 4;
|
||||
_incrementLock = false;
|
||||
_counter = 0;
|
||||
memset(&_ticks, 0, sizeof(_ticks));
|
||||
}
|
||||
|
||||
PuzzleLock::~PuzzleLock() {
|
||||
}
|
||||
|
||||
void PuzzleLock::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
s.syncAsSint32LE(_frameIndexes[0]);
|
||||
s.syncAsSint32LE(_frameIndexes[1]);
|
||||
s.syncAsSint32LE(_frameIndexes[2]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleLock::init(const AsylumEvent &) {
|
||||
getScreen()->clear();
|
||||
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[14]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[14]);
|
||||
|
||||
_vm->setGameFlag(kGameFlag115);
|
||||
|
||||
getCursor()->set(getWorld()->graphicResourceIds[41], 0, kCursorAnimationNone);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleLock::update(const AsylumEvent &) {
|
||||
updateCursor();
|
||||
|
||||
// Draw screen
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
getScreen()->fillRect(0, 0, 640, 480, 252);
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[13], 0, Common::Point(0, 0), kDrawFlagNone, true);
|
||||
|
||||
if (_frameIndexes[0] != 32 || _frameIndexes[1] != 28 || _frameIndexes[2] != 0) {
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[15], (uint32)_frameIndexes[0], Common::Point(145, 292), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[15], (uint32)_frameIndexes[1], Common::Point(173, 297), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[15], (uint32)_frameIndexes[2], Common::Point(201, 302), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[40], (uint32)_frameIndexes[3], Common::Point(337, 127), kDrawFlagNone, 0, 1);
|
||||
|
||||
if (_frameIndexes[4] != -1)
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[42], (uint32)_frameIndexes[4], Common::Point(318, 102), kDrawFlagNone, 0, 1);
|
||||
|
||||
if (_frameIndexes[5] != -1)
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[43], (uint32)_frameIndexes[5], Common::Point(318, 99), kDrawFlagNone, 0, 1);
|
||||
|
||||
getScreen()->drawGraphicsInQueue();
|
||||
getScreen()->copyBackBufferToScreen();
|
||||
} else {
|
||||
if (_frameIndexes[6] == 5)
|
||||
getSound()->playSound(getWorld()->soundResourceIds[15], false, Config.sfxVolume - 10);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[16], (uint32)_frameIndexes[6], Common::Point(0, 264), kDrawFlagNone, 0, 1);
|
||||
|
||||
++_counter;
|
||||
|
||||
if (_counter > 9) {
|
||||
++_frameIndexes[6];
|
||||
|
||||
if (_frameIndexes[6] > 7) {
|
||||
getCursor()->hide();
|
||||
getSharedData()->setFlag(kFlag1, true);
|
||||
_vm->setGameFlag(kGameFlag52);
|
||||
getSound()->playSound(getWorld()->soundResourceIds[16], false, Config.sfxVolume - 10);
|
||||
_frameIndexes[6] = 0;
|
||||
_counter = 0;
|
||||
getSharedData()->reset();
|
||||
|
||||
exitPuzzle();
|
||||
} else {
|
||||
getScreen()->drawGraphicsInQueue();
|
||||
getScreen()->copyBackBufferToScreen();
|
||||
_counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update frame indexes
|
||||
for (uint32 i = 0; i < 3; i++) {
|
||||
if (_frameIndexes[i] % ~3 && _frameIndexes[i]) {
|
||||
++_counter;
|
||||
|
||||
if (_counter > 3) {
|
||||
if (_incrementLock)
|
||||
++_frameIndexes[i];
|
||||
else
|
||||
--_frameIndexes[i];
|
||||
|
||||
if (_frameIndexes[i] < 0)
|
||||
_frameIndexes[i] = 43;
|
||||
|
||||
if (_frameIndexes[i] > 43)
|
||||
_frameIndexes[i] = 0;
|
||||
|
||||
_counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < 2; i++) {
|
||||
if (_frameIndexes[i + 4] == -1) {
|
||||
_ticks[i] = _vm->getTick();
|
||||
|
||||
if (rnd(1000) < 10)
|
||||
_frameIndexes[i + 4] = 0;
|
||||
} else {
|
||||
if (_vm->getTick() > _ticks[i] + 200) {
|
||||
++_frameIndexes[i + 4];
|
||||
|
||||
if (_frameIndexes[i + 4] > 24)
|
||||
_frameIndexes[i + 4] = -1;
|
||||
|
||||
_ticks[i] = _vm->getTick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_frameIndexes[3]) {
|
||||
if (_vm->getTick() > _ticks[2] + 100) {
|
||||
++_frameIndexes[3];
|
||||
|
||||
if (_frameIndexes[3] > 15)
|
||||
_frameIndexes[3] = 0;
|
||||
|
||||
_ticks[2] = _vm->getTick();
|
||||
}
|
||||
} else {
|
||||
_ticks[2] = _vm->getTick();
|
||||
|
||||
if (rnd(1000) < 10)
|
||||
_frameIndexes[3] = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleLock::mouseLeftDown(const AsylumEvent &evt) {
|
||||
if (_frameIndexes[6])
|
||||
return false;
|
||||
|
||||
Common::Point mousePos = evt.mouse;
|
||||
|
||||
for (uint32 i = 0; i < 3; i++) {
|
||||
if (hitTest(&puzzleLockPolygons[0], mousePos, 8 + 2 * i)) {
|
||||
if (!(_frameIndexes[i] % ~3))
|
||||
getSound()->playSound(getWorld()->soundResourceIds[14], false, Config.sfxVolume - 10);
|
||||
|
||||
_incrementLock = true;
|
||||
|
||||
++_frameIndexes[i];
|
||||
|
||||
if (_frameIndexes[i] > 43)
|
||||
_frameIndexes[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < 3; i++) {
|
||||
if (hitTest(&puzzleLockPolygons[0], mousePos, 2 * i)) {
|
||||
if (!(_frameIndexes[i] % ~3))
|
||||
getSound()->playSound(getWorld()->soundResourceIds[14], false, Config.sfxVolume - 10);
|
||||
|
||||
_incrementLock = false;
|
||||
|
||||
--_frameIndexes[i];
|
||||
|
||||
if (_frameIndexes[i] < 0)
|
||||
_frameIndexes[i] = 43;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleLock::exitPuzzle() {
|
||||
getScreen()->clear();
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleLock::updateCursor() {
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
for (uint32 i = 0; i < 6; i++) {
|
||||
if (hitTest(&puzzleLockPolygons[0], mousePos, 2 * i)) {
|
||||
if (getCursor()->getAnimation() != kCursorAnimationMirror)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[41]);
|
||||
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
if (getCursor()->getAnimation() == kCursorAnimationMirror)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[41], 0, kCursorAnimationNone);
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
61
engines/asylum/puzzles/lock.h
Normal file
61
engines/asylum/puzzles/lock.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_LOCK_H
|
||||
#define ASYLUM_PUZZLES_LOCK_H
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleLock : public Puzzle {
|
||||
public:
|
||||
PuzzleLock(AsylumEngine *engine);
|
||||
~PuzzleLock();
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
int32 _frameIndexes[7];
|
||||
bool _incrementLock;
|
||||
uint32 _counter;
|
||||
uint32 _ticks[3];
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
bool update(const AsylumEvent &evt);
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void updateCursor();
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_LOCK_H
|
||||
601
engines/asylum/puzzles/morguedoor.cpp
Normal file
601
engines/asylum/puzzles/morguedoor.cpp
Normal file
@@ -0,0 +1,601 @@
|
||||
/* 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/morguedoor.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 {
|
||||
|
||||
PuzzleMorgueDoor::PuzzleMorgueDoor(AsylumEngine *engine) : Puzzle(engine) {
|
||||
memset(&_frameCounts, 0, sizeof(_frameCounts));
|
||||
memset(&_frameIndexes, 0, sizeof(_frameIndexes));
|
||||
_data_4572A4 = false;
|
||||
_data_4572A8 = false;
|
||||
_data_4572AC = false;
|
||||
_data_4572B0 = false;
|
||||
|
||||
_data_45A9D8 = 0;
|
||||
_data_45A9DC = 0;
|
||||
|
||||
_topLeverOpen = false;
|
||||
_bottomLeverOpen = false;
|
||||
_moveTopGear = false;
|
||||
_moveBottomGear = false;
|
||||
_flag5 = false;
|
||||
_flag6 = false;
|
||||
_flag7 = false;
|
||||
}
|
||||
|
||||
PuzzleMorgueDoor::~PuzzleMorgueDoor() {
|
||||
}
|
||||
|
||||
void PuzzleMorgueDoor::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
s.syncAsSint32LE(_frameIndexes[kTopLeverOpened]);
|
||||
s.syncAsSint32LE(_frameIndexes[kBottomLeverOpened]);
|
||||
s.syncAsSint32LE(_frameIndexes[kBottomGear]);
|
||||
s.syncAsSint32LE(_frameIndexes[kTopLever]);
|
||||
s.syncAsSint32LE(_frameIndexes[kBottomLever]);
|
||||
s.syncAsSint32LE(_frameIndexes[kTopRightLever]);
|
||||
s.syncAsSint32LE(_frameIndexes[kTopSmallLever]);
|
||||
s.syncAsSint32LE(_frameIndexes[kBottomSmallLever]);
|
||||
s.syncAsSint32LE(_frameIndexes[kRightGear]);
|
||||
s.syncAsSint32LE(_frameIndexes[kTopGear]);
|
||||
s.syncAsSint32LE(_frameIndexes[kTopRightValve]);
|
||||
s.syncAsSint32LE(_frameIndexes[kCenterValve]);
|
||||
|
||||
s.syncAsSint32LE(_data_45A9D8);
|
||||
s.syncAsSint32LE(_data_45A9DC);
|
||||
s.syncAsSint32LE(_flag6);
|
||||
s.syncAsSint32LE(_flag7);
|
||||
s.syncAsSint32LE(_topLeverOpen);
|
||||
s.syncAsSint32LE(_bottomLeverOpen);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleMorgueDoor::init(const AsylumEvent &evt) {
|
||||
getCursor()->set(getWorld()->graphicResourceIds[33], -1, kCursorAnimationNone, 7);
|
||||
|
||||
_frameCounts[kTopLever] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[21]);
|
||||
_frameCounts[kBottomLever] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[22]);
|
||||
_frameCounts[kTopLeverOpened] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[23]);
|
||||
_frameCounts[kBottomLeverOpened] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[24]);
|
||||
_frameCounts[kTopRightValve] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[25]);
|
||||
_frameCounts[kCenterValve] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[26]);
|
||||
_frameCounts[kRightGear] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[27]);
|
||||
_frameCounts[kTopRightLever] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[28]);
|
||||
_frameCounts[kTopGear] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[31]);
|
||||
_frameCounts[kBottomGear] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[32]);
|
||||
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[20]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[20]);
|
||||
|
||||
return mouseLeftDown(evt);
|
||||
}
|
||||
|
||||
void PuzzleMorgueDoor::updateScreen() {
|
||||
// Draw elements
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
getScreen()->fillRect(0, 0, 640, 480, 252);
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[19], 0, Common::Point(0, 0), kDrawFlagNone, true);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[21], (uint32)_frameIndexes[kTopLever], Common::Point(47, 0), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[22], (uint32)_frameIndexes[kBottomLever], Common::Point(51, 236), kDrawFlagNone, 0, 1);
|
||||
|
||||
if (_topLeverOpen)
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[23], (uint32)_frameIndexes[kTopLeverOpened], Common::Point(80, 0), kDrawFlagNone, 0, 1);
|
||||
|
||||
if (_bottomLeverOpen)
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[24], (uint32)_frameIndexes[kBottomLeverOpened], Common::Point(89, 230), kDrawFlagNone, 0, 1);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[25], (uint32)_frameIndexes[kTopRightValve], Common::Point(515, 41), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[26], (uint32)_frameIndexes[kCenterValve], Common::Point(267, 190), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[27], (uint32)_frameIndexes[kRightGear], Common::Point(388, 105), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[28], (uint32)_frameIndexes[kTopRightLever], Common::Point(491, 143), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[29], (uint32)_frameIndexes[kTopSmallLever], Common::Point(347, 124), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[30], (uint32)_frameIndexes[kBottomSmallLever], Common::Point(346, 339), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[31], (uint32)_frameIndexes[kTopGear], Common::Point(276, 67), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[32], (uint32)_frameIndexes[kBottomGear], Common::Point(278, 378), kDrawFlagNone, 0, 1);
|
||||
|
||||
updateState();
|
||||
}
|
||||
|
||||
bool PuzzleMorgueDoor::mouseLeftDown(const AsylumEvent &evt) {
|
||||
Common::Point mousePos = evt.mouse;
|
||||
|
||||
// Top small lever
|
||||
if (mousePos.x > 347 && mousePos.x < 357
|
||||
&& mousePos.y > 124 && mousePos.y < 154) {
|
||||
_frameIndexes[kTopSmallLever] = 1;
|
||||
getSound()->playSound(getWorld()->soundResourceIds[6], false, Config.sfxVolume - 10);
|
||||
}
|
||||
|
||||
// Bottom small lever
|
||||
if (mousePos.x > 346 && mousePos.x < 356
|
||||
&& mousePos.y > 339 && mousePos.y < 386) {
|
||||
_frameIndexes[kBottomSmallLever] = 1;
|
||||
getSound()->playSound(getWorld()->soundResourceIds[6], false, Config.sfxVolume - 10);
|
||||
}
|
||||
|
||||
// Top Right Valve
|
||||
if (mousePos.x > 515 && mousePos.x < 605
|
||||
&& mousePos.y > 41 && mousePos.y < 120) {
|
||||
if (_frameIndexes[kTopRightValve] == 0) {
|
||||
_frameIndexes[kTopRightValve] = 1;
|
||||
getSound()->playSound(getWorld()->soundResourceIds[1], false, Config.sfxVolume - 10);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Center Valve turning left
|
||||
if (mousePos.x > 267 && mousePos.x < 325
|
||||
&& mousePos.y > 190 && mousePos.y < 320) {
|
||||
if (_frameIndexes[kCenterValve] == 0) {
|
||||
_frameIndexes[kCenterValve] = 1;
|
||||
getSound()->playSound(getWorld()->soundResourceIds[0], false, Config.sfxVolume - 10);
|
||||
_data_4572B0 = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Center Valve turning right
|
||||
if (mousePos.x > 325 && mousePos.x < 383
|
||||
&& mousePos.y > 190 && mousePos.y < 320) {
|
||||
if (_frameIndexes[kCenterValve] == 0) {
|
||||
_frameIndexes[kCenterValve] = 14;
|
||||
getSound()->playSound(getWorld()->soundResourceIds[0], false, Config.sfxVolume - 10);
|
||||
_data_4572B0 = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Top right lever moving left
|
||||
if (mousePos.x > 507 && mousePos.x < 556
|
||||
&& mousePos.y > 124 && mousePos.y < 177) {
|
||||
if (_frameIndexes[kTopRightLever] == 4) {
|
||||
getSound()->playSound(getWorld()->soundResourceIds[2], false, Config.sfxVolume - 10);
|
||||
_data_4572A4 = true;
|
||||
_data_4572AC = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Top right lever moving right
|
||||
if (mousePos.x > 556 && mousePos.x < 605
|
||||
&& mousePos.y > 124 && mousePos.y < 177) {
|
||||
if (_frameIndexes[kTopRightLever] == 4) {
|
||||
getSound()->playSound(getWorld()->soundResourceIds[2], false, Config.sfxVolume - 10);
|
||||
_data_4572A8 = true;
|
||||
_data_4572AC = false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleMorgueDoor::exitPuzzle() {
|
||||
getCursor()->hide();
|
||||
getSharedData()->setFlag(kFlag1, true);
|
||||
getScreen()->stopPaletteFade(0, 0, 0);
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleMorgueDoor::updateCursor() {
|
||||
bool animate = false;
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
if (mousePos.x > 347 && mousePos.x < 357 && mousePos.y > 124 && mousePos.y < 154)
|
||||
animate = true;
|
||||
|
||||
if (mousePos.x > 346 && mousePos.x < 356 && mousePos.y > 339 && mousePos.y < 386)
|
||||
animate = true;
|
||||
|
||||
if (mousePos.x > 515 && mousePos.x < 605 && mousePos.y > 41 && mousePos.y < 120)
|
||||
animate = true;
|
||||
|
||||
if (mousePos.x > 267 && mousePos.x < 325 && mousePos.y > 190 && mousePos.y < 320)
|
||||
animate = true;
|
||||
|
||||
if (mousePos.x > 325 && mousePos.x < 383 && mousePos.y > 190 && mousePos.y < 320)
|
||||
animate = true;
|
||||
|
||||
if (mousePos.x > 507 && mousePos.x < 556 && mousePos.y > 124 && mousePos.y < 177)
|
||||
animate = true;
|
||||
|
||||
if (mousePos.x > 556 && mousePos.x < 605 && mousePos.y > 124 && mousePos.y < 177)
|
||||
animate = true;
|
||||
|
||||
// Default cursor
|
||||
if (animate) {
|
||||
if (getCursor()->getAnimation() != kCursorAnimationMirror) {
|
||||
getCursor()->set(getWorld()->graphicResourceIds[33], -1, kCursorAnimationMirror, 7);
|
||||
}
|
||||
} else if (getCursor()->getAnimation() != kCursorAnimationNone) {
|
||||
getCursor()->set(getWorld()->graphicResourceIds[33], -1, kCursorAnimationNone, 7);
|
||||
}
|
||||
}
|
||||
|
||||
void PuzzleMorgueDoor::updateState() {
|
||||
// Move top gear
|
||||
if (_moveTopGear) {
|
||||
switch (_data_45A9D8) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
--_frameIndexes[kTopGear];
|
||||
|
||||
if (_frameIndexes[kTopGear] < 0) {
|
||||
_data_45A9D8 = 0;
|
||||
_moveTopGear = false;
|
||||
_frameIndexes[kTopGear] = 0;
|
||||
getSound()->stop(getWorld()->soundResourceIds[8]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
--_frameIndexes[kTopGear];
|
||||
|
||||
if (_frameIndexes[kTopGear] < 0) {
|
||||
_data_45A9D8 = 1;
|
||||
_frameIndexes[kTopGear] = 10;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
--_frameIndexes[kTopGear];
|
||||
|
||||
if (_frameIndexes[kTopGear] < 0) {
|
||||
_data_45A9D8 = 2;
|
||||
_frameIndexes[kTopGear] = 10;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_flag6 || _data_45A9D8 < 3)
|
||||
_frameIndexes[kTopLever] = 5 * _data_45A9D8;
|
||||
}
|
||||
|
||||
// Move bottom gear
|
||||
if (_moveBottomGear) {
|
||||
switch (_data_45A9DC) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
--_frameIndexes[kBottomGear];
|
||||
|
||||
if (_frameIndexes[kBottomGear] < 0) {
|
||||
_data_45A9DC = 0;
|
||||
_frameIndexes[kBottomGear] = 0;
|
||||
_moveBottomGear = false;
|
||||
|
||||
getSound()->stop(getWorld()->soundResourceIds[8]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
--_frameIndexes[kBottomGear];
|
||||
|
||||
if (_frameIndexes[kBottomGear] < 0) {
|
||||
_data_45A9DC = 1;
|
||||
_frameIndexes[kBottomGear] = 10;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
--_frameIndexes[kBottomGear];
|
||||
|
||||
if (_frameIndexes[kBottomGear] < 0) {
|
||||
_data_45A9DC = 2;
|
||||
_frameIndexes[kBottomGear] = 10;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_flag7 || _data_45A9DC < 3)
|
||||
_frameIndexes[kBottomLever] = 5 * _data_45A9DC;
|
||||
}
|
||||
|
||||
// Update gears
|
||||
if (_flag5) {
|
||||
--_frameIndexes[kRightGear];
|
||||
|
||||
if (_data_4572AC) {
|
||||
if (_data_45A9D8 < 3)
|
||||
_frameIndexes[kTopGear] = 10 * (14 - _frameIndexes[kRightGear]) / 14;
|
||||
} else {
|
||||
if (_data_45A9DC < 3)
|
||||
_frameIndexes[kBottomGear] = 10 * (14 - _frameIndexes[kRightGear]) / 14;
|
||||
}
|
||||
|
||||
if (!_frameIndexes[kRightGear]) {
|
||||
_flag5 = false;
|
||||
|
||||
if (_data_4572AC) {
|
||||
if (_frameIndexes[kTopLever] < 15)
|
||||
_frameIndexes[kTopLever] += 5;
|
||||
|
||||
if (_data_45A9D8 < 3)
|
||||
++_data_45A9D8;
|
||||
|
||||
if (_data_45A9D8 == 3 && _flag6)
|
||||
_frameIndexes[kTopLever] = _frameCounts[kTopLever] - 1;
|
||||
} else {
|
||||
if (_frameIndexes[kBottomLever] < 15)
|
||||
_frameIndexes[kBottomLever] += 5;
|
||||
|
||||
if (_data_45A9DC < 3)
|
||||
++_data_45A9DC;
|
||||
|
||||
if (_data_45A9DC == 3 && _flag7)
|
||||
_frameIndexes[kBottomLever] = _frameCounts[kBottomLever] - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Update levers & gears
|
||||
if (_frameIndexes[kTopRightValve] % 3 == 1 || (_frameIndexes[kTopRightValve] == 15 && _frameIndexes[kRightGear] > 13))
|
||||
if (_frameIndexes[kRightGear] < 14)
|
||||
++_frameIndexes[kRightGear];
|
||||
|
||||
if (_frameIndexes[kRightGear] > 14 && _frameIndexes[kTopRightValve] == 4)
|
||||
_frameIndexes[kRightGear] = 14;
|
||||
|
||||
if (_data_4572A4) {
|
||||
--_frameIndexes[kTopRightLever];
|
||||
|
||||
if (_frameIndexes[kTopRightLever] < 0) {
|
||||
_frameIndexes[kTopRightLever] = 0;
|
||||
_data_4572A4 = false;
|
||||
|
||||
if (_frameIndexes[kRightGear] == 14) {
|
||||
if (_data_45A9D8 < 3)
|
||||
getSound()->playSound(getWorld()->soundResourceIds[7], false, Config.sfxVolume, getWorld()->reverseStereo ? 2000 : -2000);
|
||||
|
||||
getSound()->playSound(getWorld()->soundResourceIds[5], false, Config.sfxVolume - 100, getWorld()->reverseStereo ? -3000 : 3000);
|
||||
_flag5 = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_data_4572A8) {
|
||||
++_frameIndexes[kTopRightLever];
|
||||
|
||||
if (_frameIndexes[kTopRightLever] > 7) {
|
||||
_frameIndexes[kTopRightLever] = 7;
|
||||
_data_4572A8 = false;
|
||||
|
||||
if (_frameIndexes[kRightGear] == 14) {
|
||||
if (_data_45A9D8 < 3)
|
||||
getSound()->playSound(getWorld()->soundResourceIds[7], false, Config.sfxVolume, getWorld()->reverseStereo ? 2000 : -2000);
|
||||
|
||||
getSound()->playSound(getWorld()->soundResourceIds[5], false, Config.sfxVolume - 100, getWorld()->reverseStereo ? -3000 : 3000);
|
||||
_flag5 = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_frameIndexes[kTopRightLever] > 4)
|
||||
--_frameIndexes[kTopRightLever];
|
||||
else if (_frameIndexes[kTopRightLever] < 4)
|
||||
++_frameIndexes[kTopRightLever];
|
||||
}
|
||||
}
|
||||
|
||||
// Left valve
|
||||
if (_frameIndexes[kTopRightValve])
|
||||
++_frameIndexes[kTopRightValve];
|
||||
|
||||
if (_frameIndexes[kCenterValve]) {
|
||||
if (_data_4572B0) {
|
||||
if (!_flag6 || _frameIndexes[kTopLever] < 15) {
|
||||
if (_flag7 && _frameIndexes[kBottomLever] >= 15) {
|
||||
_frameIndexes[kCenterValve] = 0;
|
||||
getSound()->stop(getWorld()->soundResourceIds[0]);
|
||||
} else {
|
||||
++_frameIndexes[kCenterValve];
|
||||
|
||||
// Update top lever
|
||||
if (_frameIndexes[kTopLever] >= 15) {
|
||||
if (_frameIndexes[kTopLever] == 15)
|
||||
getSound()->playSound(getWorld()->soundResourceIds[4], false, Config.sfxVolume - 10);
|
||||
|
||||
if (_frameIndexes[kTopLever] >= _frameCounts[kTopLever] - 1) {
|
||||
_frameIndexes[kCenterValve] = 0;
|
||||
_topLeverOpen = true;
|
||||
_flag6 = true;
|
||||
} else {
|
||||
++_frameIndexes[kTopLever];
|
||||
}
|
||||
} else {
|
||||
if (_frameIndexes[kCenterValve] >= 14)
|
||||
_frameIndexes[kTopLever] = 5 * _data_45A9D8;
|
||||
else
|
||||
_frameIndexes[kTopLever] = _frameIndexes[kCenterValve] / 3 + 5 * _data_45A9D8;
|
||||
}
|
||||
|
||||
// Update bottom lever
|
||||
if (_frameIndexes[kBottomLever] >= 15) {
|
||||
if (_frameIndexes[kBottomLever] == 15)
|
||||
getSound()->playSound(getWorld()->soundResourceIds[4], false, Config.sfxVolume - 10);
|
||||
|
||||
if (_frameIndexes[kBottomLever] >= _frameCounts[kBottomLever] - 1) {
|
||||
_frameIndexes[kCenterValve] = 0;
|
||||
_bottomLeverOpen = true;
|
||||
_flag7 = true;
|
||||
} else {
|
||||
++_frameIndexes[kBottomLever];
|
||||
}
|
||||
} else {
|
||||
if (_frameIndexes[kCenterValve] >= 14)
|
||||
_frameIndexes[kBottomLever] = 5 * _data_45A9DC;
|
||||
else
|
||||
_frameIndexes[kBottomLever] = _frameIndexes[kCenterValve] / 3 + 5 * _data_45A9DC;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_frameIndexes[kCenterValve] = 0;
|
||||
getSound()->stop(getWorld()->soundResourceIds[0]);
|
||||
}
|
||||
goto updateIndices;
|
||||
}
|
||||
|
||||
if ((!_flag6 && _frameIndexes[kTopLever] >= 15)
|
||||
|| (!_flag7 && _frameIndexes[kBottomLever] >= 15)) {
|
||||
_frameIndexes[kCenterValve] = 0;
|
||||
getSound()->stop(getWorld()->soundResourceIds[0]);
|
||||
} else {
|
||||
--_frameIndexes[kCenterValve];
|
||||
|
||||
// Top lever
|
||||
if (_frameIndexes[kTopLever] >= 15) {
|
||||
if (_frameIndexes[kTopLever] == 20)
|
||||
getSound()->playSound(getWorld()->soundResourceIds[3], false, Config.sfxVolume - 10);
|
||||
|
||||
if (_frameIndexes[kTopLever] <= 15) {
|
||||
_frameIndexes[kCenterValve] = 0;
|
||||
_flag6 = false;
|
||||
} else {
|
||||
--_frameIndexes[kTopLever];
|
||||
}
|
||||
|
||||
_topLeverOpen = false;
|
||||
} else {
|
||||
_frameIndexes[kTopLever] = _frameIndexes[kCenterValve] / 3 + 5 * _data_45A9D8;
|
||||
}
|
||||
|
||||
// Bottom lever
|
||||
if (_frameIndexes[kBottomLever] >= 15) {
|
||||
if (_frameIndexes[kBottomLever] == 20)
|
||||
getSound()->playSound(getWorld()->soundResourceIds[3], false, Config.sfxVolume - 10);
|
||||
|
||||
if (_frameIndexes[kBottomLever] <= 15) {
|
||||
_frameIndexes[kCenterValve] = 0;
|
||||
_flag7 = false;
|
||||
} else {
|
||||
--_frameIndexes[kBottomLever];
|
||||
}
|
||||
|
||||
_bottomLeverOpen = false;
|
||||
} else {
|
||||
_frameIndexes[kBottomLever] = _frameIndexes[kCenterValve] / 3 + 5 * _data_45A9DC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Adjust frame indexes
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
updateIndices:
|
||||
if (_frameIndexes[kTopGear] > _frameCounts[kTopGear] - 1)
|
||||
_frameIndexes[kTopGear] = 0;
|
||||
|
||||
if (_frameIndexes[kBottomGear] > _frameCounts[kBottomGear] - 1)
|
||||
_frameIndexes[kBottomGear] = 0;
|
||||
|
||||
if (_frameIndexes[kBottomLever] > _frameCounts[kBottomLever] - 1)
|
||||
_frameIndexes[kBottomLever] = 0;
|
||||
|
||||
if (_frameIndexes[kTopLeverOpened] > _frameCounts[kTopLeverOpened] - 1 || _frameIndexes[kTopLeverOpened] < 0)
|
||||
_frameIndexes[kTopLeverOpened] = 0;
|
||||
|
||||
if (_frameIndexes[kBottomLeverOpened] > _frameCounts[kBottomLeverOpened] - 1 || _frameIndexes[kBottomLeverOpened] < 0)
|
||||
_frameIndexes[kBottomLeverOpened] = 0;
|
||||
|
||||
if (_frameIndexes[kTopRightValve] > _frameCounts[kTopRightValve] - 1 || _frameIndexes[kTopRightValve] < 0)
|
||||
_frameIndexes[kTopRightValve] = 0;
|
||||
|
||||
if (_frameIndexes[kCenterValve] > _frameCounts[kCenterValve] - 1)
|
||||
_frameIndexes[kCenterValve] = 0;
|
||||
|
||||
if (_frameIndexes[kRightGear] > _frameCounts[kRightGear] - 1)
|
||||
_frameIndexes[kRightGear] = 0;
|
||||
|
||||
if (_frameIndexes[kTopRightLever] > _frameCounts[kTopRightLever] - 1)
|
||||
_frameIndexes[kTopRightLever] = 0;
|
||||
|
||||
// Top small lever
|
||||
if (_frameIndexes[kTopSmallLever] != 0) {
|
||||
++_frameIndexes[kTopSmallLever];
|
||||
|
||||
if (_frameIndexes[kTopSmallLever] > 5) {
|
||||
_frameIndexes[kTopSmallLever] = 0;
|
||||
|
||||
if (_data_45A9D8 > 0) {
|
||||
getSound()->playSound(getWorld()->soundResourceIds[8], false, Config.sfxVolume - 10);
|
||||
_moveTopGear = true;
|
||||
}
|
||||
|
||||
_frameIndexes[kTopGear] = 10;
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom small lever
|
||||
if (_frameIndexes[kBottomSmallLever] != 0) {
|
||||
++_frameIndexes[kBottomSmallLever];
|
||||
|
||||
if (_frameIndexes[kBottomSmallLever] > 5) {
|
||||
_frameIndexes[kBottomSmallLever] = 0;
|
||||
|
||||
if (_data_45A9DC > 0) {
|
||||
getSound()->playSound(getWorld()->soundResourceIds[8], false, Config.sfxVolume - 10);
|
||||
_moveBottomGear = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_flag6 && _flag7) {
|
||||
_vm->setGameFlag(kGameFlag608);
|
||||
_vm->setGameFlag(kGameFlag384);
|
||||
_vm->setGameFlag(kGameFlag391);
|
||||
|
||||
// Original waits for 2000 ticks
|
||||
g_system->delayMillis(2000);
|
||||
|
||||
getCursor()->hide();
|
||||
getSharedData()->setFlag(kFlag1, true);
|
||||
getScreen()->stopPaletteFade(0, 0, 0);
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
90
engines/asylum/puzzles/morguedoor.h
Normal file
90
engines/asylum/puzzles/morguedoor.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_MORGUEDOOR_H
|
||||
#define ASYLUM_PUZZLES_MORGUEDOOR_H
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleMorgueDoor : public Puzzle {
|
||||
public:
|
||||
PuzzleMorgueDoor(AsylumEngine *engine);
|
||||
~PuzzleMorgueDoor();
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
enum PuzzleObject {
|
||||
kTopLever = 0,
|
||||
kBottomLever = 1,
|
||||
kTopLeverOpened = 2,
|
||||
kBottomLeverOpened = 3,
|
||||
kTopRightValve = 4,
|
||||
kCenterValve = 5,
|
||||
kRightGear = 6,
|
||||
kTopRightLever = 7,
|
||||
kTopSmallLever = 8,
|
||||
kBottomSmallLever = 9,
|
||||
kTopGear = 10,
|
||||
kBottomGear = 11
|
||||
};
|
||||
|
||||
int32 _frameCounts[12]; // indexes 8 & 9 aren't used
|
||||
int32 _frameIndexes[12];
|
||||
bool _data_4572A4;
|
||||
bool _data_4572A8;
|
||||
bool _data_4572AC;
|
||||
bool _data_4572B0;
|
||||
|
||||
int32 _data_45A9D8;
|
||||
int32 _data_45A9DC;
|
||||
|
||||
bool _topLeverOpen;
|
||||
bool _bottomLeverOpen;
|
||||
bool _moveTopGear;
|
||||
bool _moveBottomGear;
|
||||
bool _flag5;
|
||||
bool _flag6;
|
||||
bool _flag7;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
void updateScreen();
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void updateCursor();
|
||||
void updateState();
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_MORGUEDOOR_H
|
||||
616
engines/asylum/puzzles/pipes.cpp
Normal file
616
engines/asylum/puzzles/pipes.cpp
Normal file
@@ -0,0 +1,616 @@
|
||||
/* 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 "common/intrinsics.h"
|
||||
|
||||
#include "asylum/puzzles/pipes.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 int16 connectorPoints[21][2] = {
|
||||
{158, 59}, {163, 172}, {168, 272},
|
||||
{202, 59}, {205, 132}, {206, 172},
|
||||
{271, 60}, {272, 131}, {273, 262},
|
||||
{318, 169}, {319, 206}, {318, 261},
|
||||
{380, 72}, {360, 171}, {360, 206},
|
||||
{428, 172}, {401, 242}, {399, 295},
|
||||
{469, 119}, {466, 171}, {460, 294},
|
||||
};
|
||||
|
||||
static const int16 peepholePoints[37][2] = {
|
||||
{140, 65}, {311, 44}, {387, 48}, {475, 72},
|
||||
{189, 67}, {246, 66}, {169, 113}, {215, 106},
|
||||
{280, 105}, {336, 95}, {434, 80}, {248, 136},
|
||||
{303, 154}, {407, 125}, {470, 151}, {193, 180},
|
||||
{347, 176}, {401, 177}, {245, 201}, {325, 196},
|
||||
{347, 212}, {406, 213}, {431, 218}, {174, 228},
|
||||
{217, 234}, {280, 227}, {325, 239}, {370, 244},
|
||||
{467, 239}, {303, 267}, {405, 273}, {356, 293},
|
||||
{436, 294}, {182, 317}, {277, 299}, {324, 291},
|
||||
{461, 323}
|
||||
};
|
||||
|
||||
const uint32 peepholeResources[] = {15, 15, 15, 15, 32, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 32, 32, 15,
|
||||
15, 32, 32, 15, 15, 15, 15, 15, 15, 15, 15, 32, 15, 15, 15, 15, 15, 15, 15};
|
||||
|
||||
static BinNum calcStateFromPosition(ConnectorType type, uint32 position) {
|
||||
assert(position);
|
||||
position--;
|
||||
uint32 shift = !!position + !!(position >> 1) + !!(position >> 2);
|
||||
|
||||
return BinNum((type >> shift | type << (4 - shift)) & 0xF);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Peephole
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool Peephole::marks[peepholesCount];
|
||||
|
||||
void Peephole::startUpWater(bool flag) {
|
||||
if (flag)
|
||||
memset(marks, false, sizeof(marks));
|
||||
|
||||
marks[_id] = true;
|
||||
|
||||
for (auto &connector : _connectors) {
|
||||
for (auto &connectedNode : connector->_connectedNodes) {
|
||||
if (!marks[connectedNode->getId()]) {
|
||||
|
||||
for (uint32 i = 0; i < 4; ++i) {
|
||||
if (isConnected(i) && connectedNode->getId() > 3)
|
||||
connectedNode->_flowValues[i] += _flowValues[i];
|
||||
}
|
||||
|
||||
connectedNode->startUpWater();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Connector
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Connector::Connector() :
|
||||
_id(0),
|
||||
_position(nullptr),
|
||||
_state(kBinNum0000),
|
||||
_isConnected(false),
|
||||
_nextConnector(nullptr),
|
||||
_type(kConnectorTypeI),
|
||||
_nextConnectorPosition(kDirectionNowhere) {
|
||||
memset(_nodes, 0, sizeof(_nodes));
|
||||
}
|
||||
|
||||
void Connector::init(Peephole *n, Peephole *e, Peephole *s, Peephole *w, uint32 pos, ConnectorType type, Connector *nextConnector, Direction nextConnectorPosition) {
|
||||
_nodes[0] = n;
|
||||
_nodes[1] = e;
|
||||
_nodes[2] = s;
|
||||
_nodes[3] = w;
|
||||
|
||||
*_position = pos;
|
||||
_type = type;
|
||||
_state = calcStateFromPosition(_type, *_position);
|
||||
|
||||
_nextConnector = nextConnector;
|
||||
_nextConnectorPosition = nextConnectorPosition;
|
||||
_isConnected = false;
|
||||
|
||||
for (uint32 i = 0; i < 4; ++i) {
|
||||
if (_state & ((uint32)1 << i) && _nodes[i]) {
|
||||
_nodes[i]->connect(this);
|
||||
_connectedNodes.push_back(_nodes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Connector::initGroup() {
|
||||
if (!_isConnected && isReadyForConnection() && _nextConnector->isReadyForConnection())
|
||||
connect(_nextConnector);
|
||||
}
|
||||
|
||||
void Connector::turn(bool updpos) {
|
||||
if (updpos)
|
||||
*_position = (*_position == 8) ? 1 : *_position << 1;
|
||||
BinNum newState = BinNum(_state >> 1 | (_state & 1) << 3);
|
||||
|
||||
uint32 delta = _state ^ newState;
|
||||
uint32 newIndex[2], oldIndex[2];
|
||||
|
||||
if (delta == kBinNum1111) {
|
||||
if (newState == kBinNum0101) {
|
||||
newIndex[0] = 0;
|
||||
newIndex[1] = 2;
|
||||
oldIndex[0] = 1;
|
||||
oldIndex[1] = 3;
|
||||
} else {
|
||||
newIndex[0] = 1;
|
||||
newIndex[1] = 3;
|
||||
oldIndex[0] = 0;
|
||||
oldIndex[1] = 2;
|
||||
}
|
||||
} else {
|
||||
newIndex[0] = (uint32)Common::intLog2(newState & delta);
|
||||
oldIndex[0] = (uint32)Common::intLog2(_state & delta);
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < (uint32)(delta == kBinNum1111 ? 2 : 1); ++i) {
|
||||
if (_nodes[oldIndex[i]]) {
|
||||
_nodes[oldIndex[i]]->disconnect(this);
|
||||
_connectedNodes.remove(_nodes[oldIndex[i]]);
|
||||
}
|
||||
|
||||
if (_nodes[newIndex[i]]) {
|
||||
_nodes[newIndex[i]]->connect(this);
|
||||
_connectedNodes.push_back(_nodes[newIndex[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
_state = newState;
|
||||
|
||||
if (_nextConnector) {
|
||||
if (_isConnected) {
|
||||
if (!(_nextConnectorPosition & _state))
|
||||
disconnect(_nextConnector);
|
||||
} else if (_nextConnectorPosition & _state && _nextConnector->isReadyForConnection()) {
|
||||
connect(_nextConnector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Connector::connect(Connector *connector) {
|
||||
for (auto &connectedNode : _connectedNodes) {
|
||||
connectedNode->connect(connector);
|
||||
connector->_connectedNodes.push_back(connectedNode);
|
||||
}
|
||||
|
||||
for (auto &connectedNode : connector->_connectedNodes) {
|
||||
connectedNode->connect(this);
|
||||
_connectedNodes.push_back(connectedNode);
|
||||
}
|
||||
|
||||
_isConnected = connector->_isConnected = true;
|
||||
|
||||
}
|
||||
|
||||
void Connector::disconnect(Connector *connector) {
|
||||
uint32 i;
|
||||
Common::List<Common::List<Peephole *>::iterator> markedForDeletion;
|
||||
bool flag;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
if (_nodes[i]) {
|
||||
_nodes[i]->disconnect(connector);
|
||||
connector->_connectedNodes.remove(_nodes[i]);
|
||||
}
|
||||
|
||||
for (Common::List<Peephole *>::iterator iter = _connectedNodes.begin(); iter != _connectedNodes.end(); ++iter) {
|
||||
flag = true;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (*iter == _nodes[i]) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
markedForDeletion.push_back(iter);
|
||||
}
|
||||
|
||||
for (Common::List<Common::List<Peephole *>::iterator>::iterator iter1 = markedForDeletion.begin(); iter1 != markedForDeletion.end(); ++iter1) {
|
||||
(*(*iter1))->disconnect(this);
|
||||
_connectedNodes.remove(*(*iter1));
|
||||
}
|
||||
|
||||
_isConnected = connector->_isConnected = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Spider
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Spider::Spider(AsylumEngine *engine, const Common::Rect &rect) : _vm(engine) {
|
||||
_boundingBox = rect;
|
||||
_isAlive = true;
|
||||
_location.x = (int16)rnd((uint16)(_boundingBox.right - _boundingBox.left + 1)) + _boundingBox.left;
|
||||
_location.y = (int16)rnd((uint16)(_boundingBox.bottom - _boundingBox.top + 1)) + _boundingBox.top;
|
||||
_direction = Direction((uint32)1 << rnd(4));
|
||||
_stepsNumber = 0;
|
||||
_steps = 0;
|
||||
|
||||
randomize();
|
||||
}
|
||||
|
||||
void Spider::randomize(Direction excluded) {
|
||||
if (rnd(6) == 5)
|
||||
_delta = Common::Point(0, 0);
|
||||
else {
|
||||
while (_direction == excluded)
|
||||
_direction = Direction((uint32)1 << rnd(4));
|
||||
|
||||
_delta = Common::Point((_direction & kBinNum0010 ? 1 : 0) - (_direction & kBinNum1000 ? 1 : 0), (_direction & kBinNum0100 ? 1 : 0) - (_direction & kBinNum0001 ? 1 : 0));
|
||||
}
|
||||
|
||||
_stepsNumber = rnd(maxStepsNumber - minStepsNumber + 1) + minStepsNumber;
|
||||
_steps = 0;
|
||||
}
|
||||
|
||||
Common::Point Spider::move() {
|
||||
Common::Point previousLocation(_location);
|
||||
|
||||
if (_isAlive) {
|
||||
if (_steps++ > _stepsNumber)
|
||||
randomize();
|
||||
|
||||
if (!_boundingBox.contains(_location + _delta))
|
||||
randomize(_direction);
|
||||
else
|
||||
_location += _delta;
|
||||
}
|
||||
|
||||
return previousLocation;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PuzzlePipes
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
PuzzlePipes::PuzzlePipes(AsylumEngine *engine) : Puzzle(engine) {
|
||||
_previousMusicVolume = 0;
|
||||
_rectIndex = -2;
|
||||
_frameIndex = _frameIndexLever = 0;
|
||||
memset(&_levelFlags, false, sizeof(_levelFlags));
|
||||
_levelFlags[4] = true;
|
||||
memset(&_levelValues, 0, sizeof(_levelValues));
|
||||
memset(&_previousLevels, 0, sizeof(_previousLevels));
|
||||
_isLeverReady = false;
|
||||
memset(&_sinks, 0, sizeof(_sinks));
|
||||
memset(&_sources, 0, sizeof(_sources));
|
||||
_frameIndexSpider = nullptr;
|
||||
|
||||
initResources();
|
||||
setup();
|
||||
}
|
||||
|
||||
PuzzlePipes::~PuzzlePipes() {
|
||||
for (uint32 i = 0; i < _spiders.size(); ++i)
|
||||
delete _spiders[i];
|
||||
if (_frameIndexSpider)
|
||||
delete[] _frameIndexSpider;
|
||||
}
|
||||
|
||||
void PuzzlePipes::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
s.skip(16);
|
||||
for (uint32 i = 0; i < connectorsCount; i++) {
|
||||
s.syncAsUint32LE(_positions[i]);
|
||||
}
|
||||
s.skip(16);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzlePipes::init(const AsylumEvent &) {
|
||||
_previousMusicVolume = getSound()->getMusicVolume();
|
||||
|
||||
if (_previousMusicVolume >= -1000)
|
||||
getSound()->setMusicVolume(-1000);
|
||||
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[41], true, Config.ambientVolume);
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[0]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[0]);
|
||||
|
||||
_rectIndex = -2;
|
||||
|
||||
checkConnections();
|
||||
startUpWater();
|
||||
(void)checkFlags();
|
||||
|
||||
getCursor()->show();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PuzzlePipes::updateScreen() {
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[1], 0, Common::Point(0, 0), kDrawFlagNone, 0, 4);
|
||||
|
||||
for (uint32 i = 0; i < ARRAYSIZE(_connectors); ++i)
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[_connectorResources[_connectors[i].getState()]], 0, &connectorPoints[i], kDrawFlagNone, 0, 1);
|
||||
|
||||
uint32 filled = 0;
|
||||
for (uint32 i = 0; i < 4; ++i) {
|
||||
if (fabs(_levelValues[i] - _previousLevels[i]) > 0.005)
|
||||
_previousLevels[i] += _levelValues[i] > _previousLevels[i] ? 0.01f : -0.01f;
|
||||
else
|
||||
++filled;
|
||||
}
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[18], 0, Common::Point(210, 444 - int16(_previousLevels[0] * 52)), kDrawFlagNone, 0, 3);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[18], 0, Common::Point(276, 455 - int16(_previousLevels[1] * 52)), kDrawFlagNone, 0, 3);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[18], 0, Common::Point(376, 448 - int16(_previousLevels[2] * 52)), kDrawFlagNone, 0, 3);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[18], 0, Common::Point(458, 442 - int16(_previousLevels[3] * 52)), kDrawFlagNone, 0, 3);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[33], 0, Common::Point(204, 377), kDrawFlagNone, 0, 1);
|
||||
|
||||
_frameIndex = (_frameIndex + 1) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[15]);
|
||||
for (uint32 i = 0; i < ARRAYSIZE(_peepholes); ++i)
|
||||
if (_peepholes[i].isConnected())
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[peepholeResources[i]], _frameIndex, &peepholePoints[i], kDrawFlagNone, 0, 1);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[2], _frameIndexLever, Common::Point(540, 90), kDrawFlagNone, 0, 1);
|
||||
_isLeverReady = false;
|
||||
if (_frameIndexLever) {
|
||||
_frameIndexLever = (_frameIndexLever + 1) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[2]);
|
||||
if (!_frameIndexLever) {
|
||||
_isLeverReady = true;
|
||||
getCursor()->show();
|
||||
}
|
||||
}
|
||||
|
||||
if (filled == 4) {
|
||||
if (_levelFlags[0])
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[40], 0, Common::Point(233, 416), kDrawFlagNone, 0, 1);
|
||||
else if (_levelFlags[1])
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[40], 0, Common::Point(299, 431), kDrawFlagNone, 0, 1);
|
||||
else if (_levelFlags[2])
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[40], 0, Common::Point(398, 421), kDrawFlagNone, 0, 1);
|
||||
else if (_levelFlags[3])
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[40], 0, Common::Point(481, 417), kDrawFlagNone, 0, 1);
|
||||
if (!_levelFlags[4])
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[45], 0, Common::Point(518, 108), kDrawFlagNone, 0, 2);
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < _spiders.size(); ++i) {
|
||||
uint32 spiderResourceId = 0;
|
||||
|
||||
switch (_spiders[i]->getDirection()) {
|
||||
default:
|
||||
error("[PuzzlePipes::update] Invalid spider direction (%d)", _spiders[i]->getDirection());
|
||||
|
||||
case kDirectionNh:
|
||||
spiderResourceId = _spiders[i]->isAlive() ? 34 : 37;
|
||||
break;
|
||||
|
||||
case kDirectionEt:
|
||||
spiderResourceId = _spiders[i]->isAlive() ? 35 : 38; // FIXME
|
||||
break;
|
||||
|
||||
case kDirectionSh:
|
||||
spiderResourceId = _spiders[i]->isAlive() ? 36 : 39;
|
||||
break;
|
||||
|
||||
case kDirectionWt:
|
||||
spiderResourceId = _spiders[i]->isAlive() ? 35 : 38;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_spiders[i]->isVisible(Common::Rect(-10, -10, 650, 490))) {
|
||||
uint32 frameCountSpider = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[spiderResourceId]);
|
||||
_frameIndexSpider[i] = _spiders[i]->isActive() ? (_frameIndexSpider[i] + 1) % frameCountSpider : 0;
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[spiderResourceId], _frameIndexSpider[i], _spiders[i]->move(), kDrawFlagNone, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (_isLeverReady) {
|
||||
_vm->clearGameFlag(kGameFlagBrokenPipeSpraying);
|
||||
_vm->clearGameFlag(kGameFlagSmFtnOverflows);
|
||||
_vm->clearGameFlag(kGameFlagFountainFilling);
|
||||
_vm->clearGameFlag(kGameFlagSewerExplodes);
|
||||
|
||||
if (!_levelFlags[4])
|
||||
_vm->setGameFlag((GameFlag)(96 + checkFlags()));
|
||||
getScreen()->clear();
|
||||
getSound()->stop(getWorld()->graphicResourceIds[41]);
|
||||
getSound()->setMusicVolume(_previousMusicVolume);
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
}
|
||||
}
|
||||
|
||||
bool PuzzlePipes::mouseLeftDown(const AsylumEvent &) {
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
if (Common::Rect(540, 90, 590, 250).contains(mousePos)) {
|
||||
if (!_frameIndexLever)
|
||||
++_frameIndexLever;
|
||||
getCursor()->hide();
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[43], false, Config.sfxVolume - 10);
|
||||
} else {
|
||||
if (_rectIndex != -1) {
|
||||
if (_rectIndex < ARRAYSIZE(connectorPoints)) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[42], false, Config.sfxVolume - 10);
|
||||
|
||||
_connectors[_rectIndex].turn();
|
||||
startUpWater();
|
||||
memset(_levelFlags, false, sizeof(_levelFlags));
|
||||
_levelFlags[checkFlags()] = true;
|
||||
} else {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[44], false, Config.sfxVolume - 10);
|
||||
_spiders[_rectIndex - ARRAYSIZE(connectorPoints)]->smash();
|
||||
_frameIndexSpider[_rectIndex - ARRAYSIZE(connectorPoints)] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzlePipes::exitPuzzle() {
|
||||
getScreen()->clear();
|
||||
getSound()->stop(getWorld()->graphicResourceIds[41]);
|
||||
getSound()->setMusicVolume(_previousMusicVolume);
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzlePipes::initResources() {
|
||||
_connectorResources[kBinNum0011] = 4;
|
||||
_connectorResources[kBinNum0110] = 3;
|
||||
_connectorResources[kBinNum1100] = 6;
|
||||
_connectorResources[kBinNum1001] = 5;
|
||||
|
||||
_connectorResources[kBinNum0111] = 7;
|
||||
_connectorResources[kBinNum1110] = 10;
|
||||
_connectorResources[kBinNum1101] = 9;
|
||||
_connectorResources[kBinNum1011] = 8;
|
||||
|
||||
_connectorResources[kBinNum0101] = 11;
|
||||
_connectorResources[kBinNum1010] = 12;
|
||||
}
|
||||
|
||||
void PuzzlePipes::setup() {
|
||||
memset(&_levelValues, 0, sizeof(_levelValues));
|
||||
|
||||
for (uint32 i = 0; i < peepholesCount; ++i)
|
||||
_peepholes[i].setId(i);
|
||||
|
||||
for (uint32 i = 0; i < connectorsCount; ++i) {
|
||||
_connectors[i].setId(i);
|
||||
_connectors[i].setPos(&_positions[i]);
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < 4; ++i) {
|
||||
_sinks[i] = &_peepholes[(peepholesCount - 4) + i];
|
||||
_sources[i] = &_peepholes[i];
|
||||
memset(&_sources[i]->_flowValues, 0, sizeof(_sources[i]->_flowValues));
|
||||
_sources[i]->_flowValues[i] = 1;
|
||||
}
|
||||
|
||||
_connectors[ 0].init( nullptr, _peepholes + 4, _peepholes + 6, _peepholes + 0, 1, kConnectorTypeL);
|
||||
_connectors[ 1].init(_peepholes + 6, _peepholes + 15, _peepholes + 23, nullptr, 1, kConnectorTypeL);
|
||||
_connectors[ 2].init(_peepholes + 23, _peepholes + 24, _peepholes + 33, nullptr, 2, kConnectorTypeL);
|
||||
_connectors[ 3].init( nullptr, _peepholes + 5, _peepholes + 7, _peepholes + 4, 1, kConnectorTypeL);
|
||||
_connectors[ 4].init(_peepholes + 7, _peepholes + 11, nullptr, nullptr, 2, kConnectorTypeL, _connectors + 5, kDirectionSh);
|
||||
_connectors[ 5].init( nullptr, _peepholes + 18, _peepholes + 24, _peepholes + 15, 1, kConnectorTypeT, _connectors + 4, kDirectionNh);
|
||||
_connectors[ 6].init( nullptr, _peepholes + 1, _peepholes + 8, _peepholes + 5, 1, kConnectorTypeL);
|
||||
_connectors[ 7].init(_peepholes + 8, _peepholes + 12, _peepholes + 25, _peepholes + 11, 1, kConnectorTypeT);
|
||||
_connectors[ 8].init(_peepholes + 25, _peepholes + 29, _peepholes + 34, _peepholes + 18, 2, kConnectorTypeT);
|
||||
_connectors[ 9].init(_peepholes + 9, _peepholes + 16, _peepholes + 19, _peepholes + 12, 8, kConnectorTypeT);
|
||||
_connectors[10].init(_peepholes + 19, _peepholes + 20, _peepholes + 26, nullptr, 2, kConnectorTypeL);
|
||||
_connectors[11].init(_peepholes + 26, _peepholes + 31, _peepholes + 35, _peepholes + 29, 2, kConnectorTypeT);
|
||||
_connectors[12].init(_peepholes + 2, _peepholes + 10, nullptr, _peepholes + 9, 2, kConnectorTypeL);
|
||||
_connectors[13].init(_peepholes + 13, _peepholes + 17, nullptr, _peepholes + 16, 1, kConnectorTypeT, _connectors + 14, kDirectionSh);
|
||||
_connectors[14].init( nullptr, _peepholes + 21, _peepholes + 27, _peepholes + 20, 8, kConnectorTypeT, _connectors + 13, kDirectionNh);
|
||||
_connectors[15].init(_peepholes + 10, nullptr, _peepholes + 22, _peepholes + 17, 1, kConnectorTypeI, _connectors + 19, kDirectionEt);
|
||||
_connectors[16].init(_peepholes + 21, _peepholes + 22, _peepholes + 30, _peepholes + 27, 2, kConnectorTypeT);
|
||||
_connectors[17].init(_peepholes + 30, _peepholes + 32, nullptr, _peepholes + 31, 2, kConnectorTypeL);
|
||||
_connectors[18].init(_peepholes + 3, nullptr, _peepholes + 14, _peepholes + 13, 8, kConnectorTypeL);
|
||||
_connectors[19].init(_peepholes + 14, nullptr, _peepholes + 28, nullptr, 4, kConnectorTypeL, _connectors + 15, kDirectionWt);
|
||||
_connectors[20].init(_peepholes + 28, nullptr, _peepholes + 36, _peepholes + 32, 4, kConnectorTypeL);
|
||||
|
||||
_connectors[ 4].initGroup();
|
||||
_connectors[13].initGroup();
|
||||
_connectors[15].initGroup();
|
||||
|
||||
uint32 i = rnd(kBinNum1000);
|
||||
if (i & kBinNum0001)
|
||||
_spiders.push_back(new Spider(_vm, Common::Rect(-10, 45, 92, 315)));
|
||||
if (i & kBinNum0010)
|
||||
_spiders.push_back(new Spider(_vm, Common::Rect(-10, 389, 149, 476)));
|
||||
if (i & kBinNum0100)
|
||||
_spiders.push_back(new Spider(_vm, Common::Rect(544, 225, 650, 490)));
|
||||
|
||||
if (i) {
|
||||
_frameIndexSpider = new uint32[_spiders.size()]();
|
||||
}
|
||||
}
|
||||
|
||||
void PuzzlePipes::updateCursor() {
|
||||
int32 index = findRect();
|
||||
|
||||
if (_rectIndex == index)
|
||||
return;
|
||||
|
||||
_rectIndex = index;
|
||||
// FIXME
|
||||
if (index > -1 || Common::Rect(540, 90, 590, 250).contains(getCursor()->position()))
|
||||
getCursor()->set(getWorld()->graphicResourceIds[16]);
|
||||
else
|
||||
getCursor()->set(getWorld()->graphicResourceIds[16], 0, kCursorAnimationNone);
|
||||
}
|
||||
|
||||
int32 PuzzlePipes::findRect() {
|
||||
for (uint32 i = 0; i < ARRAYSIZE(connectorPoints); ++i)
|
||||
if (Common::Rect(connectorPoints[i][0] - 5, connectorPoints[i][1] - 5, connectorPoints[i][0] + 30, connectorPoints[i][1] + 30).contains(getCursor()->position()))
|
||||
return i;
|
||||
|
||||
for (uint32 i = 0; i < _spiders.size(); ++i)
|
||||
if (_spiders[i]->getPolygon(Common::Rect(10, 10, 30, 30)).contains(getCursor()->position()))
|
||||
return ARRAYSIZE(connectorPoints) + i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32 PuzzlePipes::checkFlags() {
|
||||
uint32 total = _sinks[0]->getLevel1() + _sinks[1]->getLevel1() +_sinks[2]->getLevel1() + _sinks[3]->getLevel1();
|
||||
float temp;
|
||||
uint32 val = 4;
|
||||
|
||||
if (total)
|
||||
for (uint32 i = 0; i < 4; ++i) {
|
||||
temp = _sinks[i]->getLevel1() / float(total);
|
||||
_levelValues[i] = temp * _sinks[i]->getLevel() / 4;
|
||||
if (_levelValues[i] == 1.0)
|
||||
val = i;
|
||||
}
|
||||
else
|
||||
memset(_levelValues, 0, sizeof(_levelValues));
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void PuzzlePipes::checkConnections() {
|
||||
for (uint32 i = 0; i < connectorsCount; i++) {
|
||||
BinNum oldState = _connectors[i].getState(),
|
||||
newState = calcStateFromPosition(_connectors[i].getType(), _positions[i]);
|
||||
if (oldState != newState) {
|
||||
do {
|
||||
_connectors[i].turn(false);
|
||||
} while (_connectors[i].getState() != newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PuzzlePipes::startUpWater() {
|
||||
for (uint32 i = 4; i < peepholesCount; ++i)
|
||||
memset(_peepholes[i]._flowValues, 0, sizeof(_peepholes[i]._flowValues));
|
||||
|
||||
_sources[0]->startUpWater(true);
|
||||
_sources[1]->startUpWater(true);
|
||||
_sources[2]->startUpWater(true);
|
||||
_sources[3]->startUpWater(true);
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
206
engines/asylum/puzzles/pipes.h
Normal file
206
engines/asylum/puzzles/pipes.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_PIPES_H
|
||||
#define ASYLUM_PUZZLES_PIPES_H
|
||||
|
||||
#include "common/list.h"
|
||||
#include "common/hashmap.h"
|
||||
#include "common/array.h"
|
||||
#include "common/random.h"
|
||||
#include "common/str.h"
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
class Connector;
|
||||
|
||||
static const uint32 connectorsCount = 21, peepholesCount = 37;
|
||||
|
||||
enum BinNum {
|
||||
kBinNum0000,
|
||||
kBinNum0001,
|
||||
kBinNum0010,
|
||||
kBinNum0011,
|
||||
kBinNum0100,
|
||||
kBinNum0101,
|
||||
kBinNum0110,
|
||||
kBinNum0111,
|
||||
kBinNum1000,
|
||||
kBinNum1001,
|
||||
kBinNum1010,
|
||||
kBinNum1011,
|
||||
kBinNum1100,
|
||||
kBinNum1101,
|
||||
kBinNum1110,
|
||||
kBinNum1111
|
||||
};
|
||||
|
||||
enum ConnectorType {
|
||||
kConnectorTypeI = kBinNum0101,
|
||||
kConnectorTypeL = kBinNum0110,
|
||||
kConnectorTypeT = kBinNum0111
|
||||
};
|
||||
|
||||
enum Direction {
|
||||
kDirectionNowhere = kBinNum0000,
|
||||
kDirectionNh = kBinNum0001,
|
||||
kDirectionEt = kBinNum0010,
|
||||
kDirectionSh = kBinNum0100,
|
||||
kDirectionWt = kBinNum1000
|
||||
};
|
||||
|
||||
class Peephole {
|
||||
public:
|
||||
Peephole() : _id(0) {}
|
||||
~Peephole() {}
|
||||
|
||||
static bool marks[peepholesCount];
|
||||
uint32 _flowValues[4];
|
||||
|
||||
uint32 getId() { return _id; }
|
||||
void setId(uint32 id) { _id = id; }
|
||||
uint32 getLevel() { return (_flowValues[0] > 0) + (_flowValues[1] > 0) + (_flowValues[2] > 0) + (_flowValues[3] > 0); }
|
||||
uint32 getLevel1() { return _flowValues[0] + _flowValues[1] + _flowValues[2] + _flowValues[3]; }
|
||||
bool isConnected() { return isConnected(0) || isConnected(1) || isConnected(2) || isConnected(3); }
|
||||
|
||||
void connect(Connector *connector) { _connectors.push_back(connector); }
|
||||
void disconnect(Connector *connector) { _connectors.remove(connector); }
|
||||
void startUpWater(bool flag = false);
|
||||
|
||||
private:
|
||||
uint32 _id;
|
||||
Common::List<Connector *> _connectors;
|
||||
|
||||
bool isConnected(uint32 val) { return _flowValues[val]; }
|
||||
};
|
||||
|
||||
class Connector {
|
||||
public:
|
||||
Connector();
|
||||
~Connector() {}
|
||||
|
||||
uint32 getId() { return _id; }
|
||||
void setId(uint32 id) { _id = id; }
|
||||
void setPos(uint32 *pos) { _position = pos; }
|
||||
BinNum getState() { return _state; }
|
||||
ConnectorType getType() { return _type; }
|
||||
|
||||
void init(Peephole *n, Peephole *e, Peephole *s, Peephole *w, uint32 pos, ConnectorType type, Connector *nextConnector = NULL, Direction nextConnectorPosition = kDirectionNowhere);
|
||||
void initGroup();
|
||||
void turn(bool updpos = true);
|
||||
|
||||
private:
|
||||
uint32 _id;
|
||||
BinNum _state;
|
||||
ConnectorType _type;
|
||||
uint32 *_position;
|
||||
Peephole *_nodes[4];
|
||||
Common::List<Peephole *> _connectedNodes;
|
||||
|
||||
Connector *_nextConnector;
|
||||
Direction _nextConnectorPosition;
|
||||
bool _isConnected;
|
||||
|
||||
void connect(Connector *connector);
|
||||
void disconnect(Connector *connector);
|
||||
|
||||
bool isReadyForConnection() { return _state & _nextConnectorPosition; }
|
||||
|
||||
friend void Peephole::startUpWater(bool);
|
||||
};
|
||||
|
||||
class Spider {
|
||||
public:
|
||||
Spider(AsylumEngine *engine, const Common::Rect &rect);
|
||||
~Spider() {}
|
||||
|
||||
bool isAlive() const { return _isAlive; }
|
||||
bool isActive() const { return _delta != Common::Point(0, 0); }
|
||||
bool isVisible(Common::Rect rect) const { return rect.contains(_location); }
|
||||
|
||||
Direction getDirection() const { return _direction; }
|
||||
Common::Rect getPolygon(Common::Rect frame) const { return Common::Rect(_location.x - frame.left, _location.y - frame.top, _location.x + frame.right, _location.y + frame.bottom); }
|
||||
|
||||
Common::Point move();
|
||||
void smash() { _isAlive = false; }
|
||||
private:
|
||||
static const uint32 minStepsNumber = 20, maxStepsNumber = 200;
|
||||
AsylumEngine *_vm;
|
||||
bool _isAlive;
|
||||
Common::Point _location;
|
||||
Common::Point _delta;
|
||||
Common::Rect _boundingBox;
|
||||
Direction _direction;
|
||||
uint32 _stepsNumber;
|
||||
uint32 _steps;
|
||||
|
||||
void randomize(Direction excluded = kDirectionNowhere);
|
||||
};
|
||||
|
||||
class PuzzlePipes : public Puzzle {
|
||||
public:
|
||||
PuzzlePipes(AsylumEngine *engine);
|
||||
~PuzzlePipes();
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
int32 _previousMusicVolume;
|
||||
int32 _rectIndex;
|
||||
uint32 _frameIndex, _frameIndexLever;
|
||||
bool _levelFlags[5];
|
||||
float _levelValues[4], _previousLevels[4];
|
||||
bool _isLeverReady;
|
||||
Common::HashMap<uint32, uint32> _connectorResources;
|
||||
Connector _connectors[connectorsCount];
|
||||
uint32 _positions[connectorsCount];
|
||||
Peephole _peepholes[peepholesCount];
|
||||
Peephole *_sinks[4], *_sources[4];
|
||||
Common::Array<Spider *> _spiders;
|
||||
uint32 *_frameIndexSpider;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
void updateScreen();
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void initResources();
|
||||
void setup();
|
||||
void updateCursor();
|
||||
int32 findRect();
|
||||
uint32 checkFlags();
|
||||
void startUpWater();
|
||||
void checkConnections();
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_PIPES_H
|
||||
121
engines/asylum/puzzles/puzzle.cpp
Normal file
121
engines/asylum/puzzles/puzzle.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/* 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/puzzle.h"
|
||||
|
||||
#include "asylum/resources/polygons.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 {
|
||||
|
||||
Puzzle::Puzzle(AsylumEngine *engine): _vm(engine) {
|
||||
}
|
||||
|
||||
void Puzzle::saveLoadWithSerializer(Common::Serializer &) {
|
||||
// By default, we do not save any data
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool Puzzle::handleEvent(const AsylumEvent &evt) {
|
||||
switch ((int32)evt.type) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case EVENT_ASYLUM_INIT:
|
||||
return init(evt);
|
||||
|
||||
case EVENT_ASYLUM_ACTIVATE:
|
||||
return activate(evt);
|
||||
|
||||
case EVENT_ASYLUM_UPDATE:
|
||||
return update(evt);
|
||||
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
return mouseLeftDown(evt);
|
||||
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
return mouseLeftUp(evt);
|
||||
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
|
||||
return exitPuzzle();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Puzzle::update(const AsylumEvent &evt) {
|
||||
uint32 ticks = _vm->getTick();
|
||||
|
||||
updateCursor();
|
||||
|
||||
if (!getSharedData()->getFlag(kFlagRedraw)) {
|
||||
updateScreen();
|
||||
|
||||
getSharedData()->setFlag(kFlagRedraw, true);
|
||||
}
|
||||
|
||||
if (ticks > getSharedData()->getNextScreenUpdate()) {
|
||||
if (getSharedData()->getFlag(kFlagRedraw)) {
|
||||
if (!getScreen()->isGraphicQueueEmpty())
|
||||
getScreen()->drawGraphicsInQueue();
|
||||
getScreen()->copyBackBufferToScreen();
|
||||
|
||||
getSharedData()->setEventUpdate(getSharedData()->getEventUpdate() ^ 1);
|
||||
|
||||
getSharedData()->setFlag(kFlagRedraw, false);
|
||||
getSharedData()->setNextScreenUpdate(ticks + 40);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Hit test functions
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Puzzle::hitTest(const int16 (*polygonPoint)[2], const Common::Point &point, uint32 index) const {
|
||||
Common::Point p1(polygonPoint[index + 0][0], polygonPoint[index + 0][1]),
|
||||
p2(polygonPoint[index + 1][0], polygonPoint[index + 1][1]),
|
||||
p3(polygonPoint[index + 2][0], polygonPoint[index + 2][1]),
|
||||
p4(polygonPoint[index + 3][0], polygonPoint[index + 3][1]);
|
||||
|
||||
Polygon polygon(p1, p2, p3, p4);
|
||||
|
||||
return polygon.contains(point);
|
||||
}
|
||||
|
||||
bool Puzzle::hitTest(const int16 (*polygonPoint)[2], const Common::Point &point) const {
|
||||
return hitTest(polygonPoint, point, 0);
|
||||
}
|
||||
|
||||
} // end of namespace Asylum
|
||||
76
engines/asylum/puzzles/puzzle.h
Normal file
76
engines/asylum/puzzles/puzzle.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_PUZZLE_H
|
||||
#define ASYLUM_PUZZLES_PUZZLE_H
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
#include "asylum/eventhandler.h"
|
||||
#include "asylum/shared.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
class Screen;
|
||||
class Sound;
|
||||
class VideoPlayer;
|
||||
class Cursor;
|
||||
class GraphicResource;
|
||||
struct GraphicQueueItem;
|
||||
|
||||
class Puzzle : public EventHandler, public Common::Serializable {
|
||||
public:
|
||||
Puzzle(AsylumEngine *engine);
|
||||
virtual ~Puzzle() {};
|
||||
|
||||
bool handleEvent(const AsylumEvent &evt);
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
protected:
|
||||
AsylumEngine *_vm;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual bool init(const AsylumEvent &evt) = 0;
|
||||
virtual bool update(const AsylumEvent &evt);
|
||||
virtual void updateScreen() {};
|
||||
virtual void updateCursor() {};
|
||||
virtual bool activate(const AsylumEvent &evt) { return true; }
|
||||
virtual bool mouseLeftUp(const AsylumEvent &evt) { return true; }
|
||||
virtual bool mouseLeftDown(const AsylumEvent &evt) { return true; }
|
||||
|
||||
virtual bool exitPuzzle() = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Hit test functions
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool hitTest(const int16 (*polygonPoint)[2], const Common::Point &point, uint32 index) const;
|
||||
bool hitTest(const int16 (*polygonPoint)[2], const Common::Point &point) const;
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_PUZZLE_H
|
||||
109
engines/asylum/puzzles/puzzles.cpp
Normal file
109
engines/asylum/puzzles/puzzles.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
/* 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/puzzles.h"
|
||||
|
||||
#include "asylum/puzzles/boardkeyhidesto.h"
|
||||
#include "asylum/puzzles/boardsalvation.h"
|
||||
#include "asylum/puzzles/boardyouth.h"
|
||||
#include "asylum/puzzles/clock.h"
|
||||
#include "asylum/puzzles/fisherman.h"
|
||||
#include "asylum/puzzles/hivecontrol.h"
|
||||
#include "asylum/puzzles/hivemachine.h"
|
||||
#include "asylum/puzzles/lock.h"
|
||||
#include "asylum/puzzles/morguedoor.h"
|
||||
#include "asylum/puzzles/pipes.h"
|
||||
#include "asylum/puzzles/tictactoe.h"
|
||||
#include "asylum/puzzles/timemachine.h"
|
||||
#include "asylum/puzzles/vcr.h"
|
||||
#include "asylum/puzzles/wheel.h"
|
||||
#include "asylum/puzzles/writings.h"
|
||||
|
||||
#include "asylum/asylum.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
Puzzles::Puzzles(AsylumEngine *engine) : _vm(engine) {
|
||||
memset(&_puzzles, 0, sizeof(_puzzles));
|
||||
}
|
||||
|
||||
Puzzles::~Puzzles() {
|
||||
// Cleanup puzzles
|
||||
for (uint i = 0; i < ARRAYSIZE(_puzzles); i++)
|
||||
delete _puzzles[i];
|
||||
}
|
||||
|
||||
void Puzzles::reset() {
|
||||
for (uint i = 0; i < ARRAYSIZE(_puzzles); i++)
|
||||
delete _puzzles[i];
|
||||
|
||||
initPuzzles();
|
||||
}
|
||||
|
||||
EventHandler *Puzzles::getPuzzle(uint32 index) const {
|
||||
if (index >= ARRAYSIZE(_puzzles))
|
||||
error("[AsylumEngine::getPuzzleEventHandler] Invalid index (was: %d - max: %d)", index, ARRAYSIZE(_puzzles));
|
||||
|
||||
if (_puzzles[index] == nullptr)
|
||||
error("[AsylumEngine::getPuzzleEventHandler] This puzzle doesn't have an event handler! (index: %d)", index);
|
||||
|
||||
return (EventHandler *)_puzzles[index];
|
||||
}
|
||||
|
||||
void Puzzles::initPuzzles() {
|
||||
_puzzles[kPuzzleVCR] = new PuzzleVCR(_vm);
|
||||
_puzzles[kPuzzlePipes] = new PuzzlePipes(_vm);
|
||||
_puzzles[kPuzzleTicTacToe] = new PuzzleTicTacToe(_vm);
|
||||
_puzzles[kPuzzleLock] = new PuzzleLock(_vm);
|
||||
_puzzles[kPuzzle4] = nullptr; // No event handler for Puzzle 5
|
||||
_puzzles[kPuzzleWheel] = new PuzzleWheel(_vm);
|
||||
_puzzles[kPuzzleBoardSalvation] = new PuzzleBoardSalvation(_vm);
|
||||
_puzzles[kPuzzleBoardYouth] = new PuzzleBoardYouth(_vm);
|
||||
_puzzles[kPuzzleBoardKeyHidesTo] = new PuzzleBoardKeyHidesTo(_vm);
|
||||
_puzzles[kPuzzleWritings] = new PuzzleWritings(_vm);
|
||||
_puzzles[kPuzzle11] = nullptr;
|
||||
_puzzles[kPuzzleMorgueDoor] = new PuzzleMorgueDoor(_vm);
|
||||
_puzzles[kPuzzleClock] = new PuzzleClock(_vm);
|
||||
_puzzles[kPuzzleTimeMachine] = new PuzzleTimeMachine(_vm);
|
||||
_puzzles[kPuzzleFisherman] = new PuzzleFisherman(_vm);
|
||||
_puzzles[kPuzzleHiveMachine] = new PuzzleHiveMachine(_vm);
|
||||
_puzzles[kPuzzleHiveControl] = new PuzzleHiveControl(_vm);
|
||||
}
|
||||
|
||||
void Puzzles::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
_puzzles[kPuzzleVCR]->saveLoadWithSerializer(s);
|
||||
s.skip(4);
|
||||
_puzzles[kPuzzleLock]->saveLoadWithSerializer(s);
|
||||
_puzzles[kPuzzlePipes]->saveLoadWithSerializer(s);
|
||||
_puzzles[kPuzzleWheel]->saveLoadWithSerializer(s);
|
||||
_puzzles[kPuzzleBoardSalvation]->saveLoadWithSerializer(s);
|
||||
_puzzles[kPuzzleBoardYouth]->saveLoadWithSerializer(s);
|
||||
s.skip(8);
|
||||
_puzzles[kPuzzleBoardKeyHidesTo]->saveLoadWithSerializer(s);
|
||||
_puzzles[kPuzzleMorgueDoor]->saveLoadWithSerializer(s);
|
||||
s.skip(80); // skip Puzzle 11
|
||||
_puzzles[kPuzzleTimeMachine]->saveLoadWithSerializer(s);
|
||||
_puzzles[kPuzzleClock]->saveLoadWithSerializer(s);
|
||||
_puzzles[kPuzzleFisherman]->saveLoadWithSerializer(s);
|
||||
_puzzles[kPuzzleHiveControl]->saveLoadWithSerializer(s);
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
72
engines/asylum/puzzles/puzzles.h
Normal file
72
engines/asylum/puzzles/puzzles.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_PUZZLES_H
|
||||
#define ASYLUM_PUZZLES_PUZZLES_H
|
||||
|
||||
#include "common/serializer.h"
|
||||
|
||||
#include "asylum/shared.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
class EventHandler;
|
||||
class Puzzle;
|
||||
|
||||
class Puzzles : public Common::Serializable {
|
||||
public:
|
||||
Puzzles(AsylumEngine *engine);
|
||||
~Puzzles();
|
||||
|
||||
/**
|
||||
* Resets puzzles
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Gets a message handler.
|
||||
*
|
||||
* @param index Zero-based index of the message handler
|
||||
*
|
||||
* @return The message handler.
|
||||
*/
|
||||
EventHandler *getPuzzle(uint32 index) const;
|
||||
|
||||
// Serializable
|
||||
void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
AsylumEngine *_vm;
|
||||
Puzzle *_puzzles[17];
|
||||
|
||||
/**
|
||||
* Initializes the puzzles
|
||||
*/
|
||||
void initPuzzles();
|
||||
|
||||
// Debug
|
||||
friend class Console;
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_PUZZLES_H
|
||||
581
engines/asylum/puzzles/tictactoe.cpp
Normal file
581
engines/asylum/puzzles/tictactoe.cpp
Normal file
@@ -0,0 +1,581 @@
|
||||
/* 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/tictactoe.h"
|
||||
|
||||
#include "asylum/resources/worldstats.h"
|
||||
|
||||
#include "asylum/system/cursor.h"
|
||||
#include "asylum/system/screen.h"
|
||||
|
||||
#include "asylum/views/scene.h"
|
||||
|
||||
#include "asylum/asylum.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
extern int g_debugPolygons;
|
||||
|
||||
const int16 puzzleTicTacToePolygons[36][2] = {
|
||||
{ 27, 381}, {172, 368}, {190, 474}, { 36, 476},
|
||||
{176, 362}, {294, 328}, {331, 456}, {191, 472},
|
||||
{304, 327}, {426, 306}, {457, 440}, {340, 460},
|
||||
{ 26, 257}, {151, 238}, {169, 356}, { 27, 373},
|
||||
{162, 234}, {275, 214}, {299, 321}, {173, 355},
|
||||
{283, 210}, {403, 173}, {437, 294}, {305, 317},
|
||||
{ 22, 120}, {132, 126}, {146, 223}, { 25, 247},
|
||||
{144, 119}, {247, 87}, {268, 205}, {159, 222},
|
||||
{259, 84}, {380, 73}, {405, 169}, {281, 201}
|
||||
};
|
||||
|
||||
const int16 puzzleTicTacToePositions[9][2] = {
|
||||
{ 62, 367}, {193, 343}, {329, 319},
|
||||
{ 38, 247}, {167, 217}, {296, 193},
|
||||
{ 19, 121}, {147, 98}, {269, 70}
|
||||
};
|
||||
|
||||
static const struct {
|
||||
uint32 field1;
|
||||
uint32 field2;
|
||||
uint32 field3;
|
||||
uint32 winLineX;
|
||||
uint32 winLineO;
|
||||
uint32 frameCount;
|
||||
} puzzleTicTacToeFieldsToCheck[8] = {
|
||||
{0, 1, 2, 1, 9, 14},
|
||||
{3, 4, 5, 2, 10, 14},
|
||||
{6, 7, 8, 3, 11, 14},
|
||||
{0, 3, 6, 4, 12, 10},
|
||||
{8, 5, 2, 6, 14, 10},
|
||||
{0, 4, 8, 8, 16, 4},
|
||||
{4, 1, 7, 5, 13, 10},
|
||||
{4, 6, 2, 7, 15, 4}
|
||||
};
|
||||
|
||||
PuzzleTicTacToe::PuzzleTicTacToe(AsylumEngine *engine) : Puzzle(engine) {
|
||||
_ticker = 0;
|
||||
_frameIndex = 0;
|
||||
_frameCount = 0;
|
||||
_currentPos = 0;
|
||||
_gameOver = false;
|
||||
_winLine = 0;
|
||||
|
||||
// Field
|
||||
memset(&_board, 0, sizeof(_board));
|
||||
memset(&_moveList, 0, sizeof(_moveList));
|
||||
_numberOfPossibleMoves = 0;
|
||||
|
||||
_solveDelay = 0;
|
||||
_brokenLines = 0;
|
||||
}
|
||||
|
||||
PuzzleTicTacToe::~PuzzleTicTacToe() {
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleTicTacToe::init(const AsylumEvent &) {
|
||||
_ticker = 0;
|
||||
_vm->clearGameFlag(kGameFlag114);
|
||||
_vm->clearGameFlag(kGameFlag215);
|
||||
_frameIndex = 0;
|
||||
_currentPos = -1;
|
||||
_gameOver = false;
|
||||
_winLine = -1;
|
||||
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[3]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[3]);
|
||||
|
||||
getCursor()->show();
|
||||
getCursor()->set(getWorld()->graphicResourceIds[12], 4, kCursorAnimationLinear, 4);
|
||||
|
||||
clearBoard();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PuzzleTicTacToe::updateScreen() {
|
||||
if (_ticker) {
|
||||
++_ticker;
|
||||
|
||||
if (_ticker <= 25) {
|
||||
if (_ticker > 20) {
|
||||
if (computerThinks())
|
||||
computerMoves();
|
||||
|
||||
_ticker = 0;
|
||||
}
|
||||
} else {
|
||||
if (_ticker > 40) {
|
||||
getSound()->playSound(getWorld()->soundResourceIds[13], false, Config.sfxVolume - 100);
|
||||
|
||||
_ticker = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[0]);
|
||||
drawField();
|
||||
getScene()->updateAmbientSounds();
|
||||
}
|
||||
|
||||
bool PuzzleTicTacToe::mouseLeftDown(const AsylumEvent &evt) {
|
||||
if (!_vm->isGameFlagNotSet(kGameFlag215) || !_vm->isGameFlagNotSet(kGameFlag114)) {
|
||||
getCursor()->show();
|
||||
exitPuzzle();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_gameOver) {
|
||||
_gameOver = false;
|
||||
_frameIndex = 0;
|
||||
_currentPos = -1;
|
||||
_winLine = -1;
|
||||
clearBoard();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < ARRAYSIZE(_board); i++) {
|
||||
if (hitTest(&puzzleTicTacToePolygons[i * 4], evt.mouse, 0)) {
|
||||
if (_board[i] == ' ') {
|
||||
getSound()->playSound(getWorld()->soundResourceIds[11], false, Config.sfxVolume - 100);
|
||||
_board[i] = 'X';
|
||||
_currentPos = i;
|
||||
_frameIndex = 0;
|
||||
|
||||
getCursor()->hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleTicTacToe::exitPuzzle() {
|
||||
getScreen()->clear();
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Init & update
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleTicTacToe::clearBoard() {
|
||||
_brokenLines = 0;
|
||||
memset(&_board, ' ', sizeof(_board));
|
||||
}
|
||||
|
||||
void PuzzleTicTacToe::drawField() {
|
||||
if (_solveDelay > 0) {
|
||||
--_solveDelay;
|
||||
|
||||
if (_solveDelay < 2) {
|
||||
getCursor()->show();
|
||||
exitPuzzle();
|
||||
_solveDelay = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_debugPolygons) {
|
||||
for (uint32 p = 0; p < ARRAYSIZE(puzzleTicTacToePolygons) - 4; p += 4) {
|
||||
getScreen()->drawLine(&puzzleTicTacToePolygons[p], &puzzleTicTacToePolygons[p + 1]);
|
||||
getScreen()->drawLine(&puzzleTicTacToePolygons[p + 1], &puzzleTicTacToePolygons[p + 2]);
|
||||
getScreen()->drawLine(&puzzleTicTacToePolygons[p + 2], &puzzleTicTacToePolygons[p + 3]);
|
||||
getScreen()->drawLine(&puzzleTicTacToePolygons[p + 3], &puzzleTicTacToePolygons[p]);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw X & O
|
||||
for (int32 i = 0; i < ARRAYSIZE(puzzleTicTacToePositions); i++) {
|
||||
char mark = _board[i];
|
||||
Common::Point point = Common::Point(puzzleTicTacToePositions[i][0], puzzleTicTacToePositions[i][1]);
|
||||
|
||||
if (_currentPos == i) {
|
||||
if (mark == 'O')
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[2], _frameIndex, point);
|
||||
else if (mark == 'X')
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[1], _frameIndex, point);
|
||||
|
||||
// Update _frameIndex
|
||||
++_frameIndex;
|
||||
if (_frameIndex > 14 && mark == 'X') {
|
||||
_currentPos = -1;
|
||||
_frameIndex = 0;
|
||||
_ticker = 1;
|
||||
|
||||
if (checkWin())
|
||||
_gameOver = true;
|
||||
}
|
||||
|
||||
if (_frameIndex > 12 && mark == 'O') {
|
||||
_currentPos = -1;
|
||||
_frameIndex = 0;
|
||||
|
||||
if (!checkWin() || !lookForAWinner())
|
||||
getCursor()->show();
|
||||
}
|
||||
} else {
|
||||
if (mark == 'O')
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[2], 12, point);
|
||||
else if (mark == 'X')
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[1], 14, point);
|
||||
}
|
||||
}
|
||||
|
||||
if (_currentPos == -1 && checkWin())
|
||||
_gameOver = true;
|
||||
|
||||
// Draw win line
|
||||
if (_winLine > 0 && !_ticker) {
|
||||
switch (_winLine) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[5], _frameIndex, Common::Point(38, 345));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[5], _frameIndex, Common::Point(17, 226));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[5], _frameIndex, Common::Point(1, 104));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[6], _frameIndex, Common::Point(43, 117));
|
||||
break;
|
||||
|
||||
case 5:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[6], _frameIndex, Common::Point(176, 104));
|
||||
break;
|
||||
|
||||
case 6:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[6], _frameIndex, Common::Point(299, 85));
|
||||
break;
|
||||
|
||||
case 7:
|
||||
if (_brokenLines == 0)
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[8], _frameIndex, Common::Point(30, 149));
|
||||
else if (_brokenLines == 1)
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[8], _frameIndex, Common::Point(180, 249));
|
||||
else {
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[8], 6, Common::Point(30, 149));
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[8], 6, Common::Point(180, 249));
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[8], _frameIndex, Common::Point(330, 349));
|
||||
}
|
||||
break;
|
||||
|
||||
case 8:
|
||||
if (_brokenLines == 0)
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[10], _frameIndex, Common::Point(69, 66));
|
||||
else if (_brokenLines == 1)
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[10], _frameIndex, Common::Point(-22, 220));
|
||||
else {
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[10], 6, Common::Point( 69, 66));
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[10], 6, Common::Point(-22, 220));
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[10], _frameIndex, Common::Point(-110, 370));
|
||||
}
|
||||
break;
|
||||
|
||||
case 9:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[4], _frameIndex, Common::Point(38, 345));
|
||||
break;
|
||||
|
||||
case 10:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[4], _frameIndex, Common::Point(17, 226));
|
||||
break;
|
||||
|
||||
case 11:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[4], _frameIndex, Common::Point(1, 104));
|
||||
break;
|
||||
|
||||
case 12:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[11], _frameIndex, Common::Point(43, 117));
|
||||
break;
|
||||
|
||||
case 13:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[11], _frameIndex, Common::Point(176, 104));
|
||||
break;
|
||||
|
||||
case 14:
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[11], _frameIndex, Common::Point(299, 85));
|
||||
break;
|
||||
|
||||
case 15:
|
||||
if (_brokenLines == 0)
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[7], _frameIndex, Common::Point(30, 149));
|
||||
else if (_brokenLines == 1)
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[7], _frameIndex, Common::Point(180, 249));
|
||||
else {
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[7], 6, Common::Point(30, 149));
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[7], 6, Common::Point(180, 249));
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[7], _frameIndex, Common::Point(330, 349));
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
if (_brokenLines == 0)
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[9], _frameIndex, Common::Point(69, 66));
|
||||
else if (_brokenLines == 1)
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[9], _frameIndex, Common::Point(-22, 220));
|
||||
else {
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[9], 6, Common::Point(69, 66));
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[9], 6, Common::Point(-22, 220));
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[9], _frameIndex, Common::Point(-110, 370));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (_frameIndex >= _frameCount) {
|
||||
if (_winLine == 7 || _winLine == 8 || _winLine == 15 || _winLine == 16) {
|
||||
if (_brokenLines < 2) {
|
||||
_frameIndex = 0;
|
||||
++_brokenLines;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
++_frameIndex;
|
||||
}
|
||||
|
||||
if (!_solveDelay)
|
||||
_solveDelay = 30;
|
||||
}
|
||||
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[17], 0, Common::Point(0, 0));
|
||||
}
|
||||
|
||||
void PuzzleTicTacToe::getTwoEmpty(uint32 field1, uint32 field2, uint32 field3) {
|
||||
if (_board[field1] != ' ') {
|
||||
_moveList[_numberOfPossibleMoves] = field3;
|
||||
_moveList[_numberOfPossibleMoves + 1] = field2;
|
||||
|
||||
_numberOfPossibleMoves += 2;
|
||||
}
|
||||
|
||||
if (_board[field3] != ' ') {
|
||||
_moveList[_numberOfPossibleMoves] = field1;
|
||||
_moveList[_numberOfPossibleMoves + 1] = field2;
|
||||
|
||||
_numberOfPossibleMoves += 2;
|
||||
}
|
||||
|
||||
if (_board[field2] != ' ') {
|
||||
_moveList[_numberOfPossibleMoves] = field3;
|
||||
_moveList[_numberOfPossibleMoves + 1] = field1;
|
||||
|
||||
_numberOfPossibleMoves += 2;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Game
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleTicTacToe::computerThinks() {
|
||||
if (_gameOver)
|
||||
return false;
|
||||
|
||||
if (!tryToWin()
|
||||
&& !tryNotToLose()
|
||||
&& !expandLine()
|
||||
&& !tryNewLine()
|
||||
&& !arbitraryPlacement()) {
|
||||
if (!_solveDelay)
|
||||
getCursor()->show();
|
||||
|
||||
_gameOver = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PuzzleTicTacToe::GameStatus PuzzleTicTacToe::returnLineData(uint32 field1, uint32 field2, uint32 field3, char mark, uint32 *counterX, uint32 *counterO) const {
|
||||
*counterX = 0;
|
||||
*counterO = 0;
|
||||
GameStatus status = kStatus0;
|
||||
|
||||
if (_board[field1] == 'X')
|
||||
++*counterX;
|
||||
if (_board[field2] == 'X')
|
||||
++*counterX;
|
||||
if (_board[field3] == 'X')
|
||||
++*counterX;
|
||||
|
||||
if (_board[field1] == 'O')
|
||||
++*counterO;
|
||||
if (_board[field2] == 'O')
|
||||
++*counterO;
|
||||
if (_board[field3] == 'O')
|
||||
++*counterO;
|
||||
|
||||
if (mark == 'O') {
|
||||
if (*counterO == 1 && !*counterX)
|
||||
status = kStatusFree;
|
||||
} else if (mark == 'X') {
|
||||
if (!*counterO && *counterX == 1)
|
||||
status = kStatusFree;
|
||||
}
|
||||
|
||||
if (mark == 'O') {
|
||||
if (!*counterO && *counterX == 2)
|
||||
status = kStatusNeedBlocking;
|
||||
} else if (mark == 'X') {
|
||||
if (*counterO == 2 && !*counterX)
|
||||
status = kStatusNeedBlocking;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool PuzzleTicTacToe::expandLine() {
|
||||
uint32 counterX = 0;
|
||||
uint32 counterO = 0;
|
||||
|
||||
for (uint32 i = 0; i < ARRAYSIZE(puzzleTicTacToeFieldsToCheck); i++)
|
||||
if (returnLineData(puzzleTicTacToeFieldsToCheck[i].field1, puzzleTicTacToeFieldsToCheck[i].field2, puzzleTicTacToeFieldsToCheck[i].field3, 'O', &counterX, &counterO) == kStatusFree)
|
||||
getTwoEmpty(puzzleTicTacToeFieldsToCheck[i].field1, puzzleTicTacToeFieldsToCheck[i].field2, puzzleTicTacToeFieldsToCheck[i].field3);
|
||||
|
||||
return (_numberOfPossibleMoves != 0);
|
||||
}
|
||||
|
||||
bool PuzzleTicTacToe::tryNewLine() {
|
||||
uint32 counterX = 0;
|
||||
uint32 counterO = 0;
|
||||
|
||||
for (uint32 i = 0; i < ARRAYSIZE(puzzleTicTacToeFieldsToCheck); i++) {
|
||||
returnLineData(puzzleTicTacToeFieldsToCheck[i].field1, puzzleTicTacToeFieldsToCheck[i].field2, puzzleTicTacToeFieldsToCheck[i].field3, 'O', &counterX, &counterO);
|
||||
|
||||
if (counterX || counterO)
|
||||
continue;
|
||||
|
||||
_moveList[_numberOfPossibleMoves] = puzzleTicTacToeFieldsToCheck[i].field1;
|
||||
_moveList[_numberOfPossibleMoves + 1] = puzzleTicTacToeFieldsToCheck[i].field2;
|
||||
_moveList[_numberOfPossibleMoves + 2] = puzzleTicTacToeFieldsToCheck[i].field3;
|
||||
|
||||
_numberOfPossibleMoves += 3;
|
||||
}
|
||||
|
||||
return (_numberOfPossibleMoves != 0);
|
||||
}
|
||||
|
||||
uint32 PuzzleTicTacToe::returnEmptySlot(uint32 position1, uint32 position2, uint position3) const {
|
||||
if (_board[position1] == ' ')
|
||||
return position1;
|
||||
|
||||
if (_board[position2] == ' ')
|
||||
return position2;
|
||||
|
||||
return position3;
|
||||
}
|
||||
|
||||
bool PuzzleTicTacToe::checkWin() {
|
||||
if (_gameOver)
|
||||
return true;
|
||||
|
||||
if (lookForAWinner() == 1) {
|
||||
_vm->setGameFlag(kGameFlag114);
|
||||
_ticker = 30;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lookForAWinner() == -1) {
|
||||
_vm->setGameFlag(kGameFlag215);
|
||||
_ticker = 30;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 PuzzleTicTacToe::lookForAWinner() {
|
||||
uint32 counterX = 0;
|
||||
uint32 counterO = 0;
|
||||
|
||||
for (uint32 i = 0; i < ARRAYSIZE(puzzleTicTacToeFieldsToCheck); i++) {
|
||||
returnLineData(puzzleTicTacToeFieldsToCheck[i].field1, puzzleTicTacToeFieldsToCheck[i].field2, puzzleTicTacToeFieldsToCheck[i].field3, 'O', &counterX, &counterO);
|
||||
|
||||
if (counterX == 3) {
|
||||
_winLine = puzzleTicTacToeFieldsToCheck[i].winLineX;
|
||||
_frameCount = puzzleTicTacToeFieldsToCheck[i].frameCount;
|
||||
_frameIndex = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (counterO == 3) {
|
||||
_winLine = puzzleTicTacToeFieldsToCheck[i].winLineO;
|
||||
_frameCount = puzzleTicTacToeFieldsToCheck[i].frameCount;
|
||||
_frameIndex = 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PuzzleTicTacToe::strategy(char mark) {
|
||||
uint32 counterX = 0;
|
||||
uint32 counterO = 0;
|
||||
_numberOfPossibleMoves = 0;
|
||||
|
||||
for (uint32 i = 0; i < ARRAYSIZE(puzzleTicTacToeFieldsToCheck); i++) {
|
||||
if (returnLineData(puzzleTicTacToeFieldsToCheck[i].field1, puzzleTicTacToeFieldsToCheck[i].field2, puzzleTicTacToeFieldsToCheck[i].field3, mark, &counterX, &counterO) == kStatusNeedBlocking) {
|
||||
_moveList[_numberOfPossibleMoves] = returnEmptySlot(puzzleTicTacToeFieldsToCheck[i].field1, puzzleTicTacToeFieldsToCheck[i].field2, puzzleTicTacToeFieldsToCheck[i].field3);
|
||||
++_numberOfPossibleMoves;
|
||||
}
|
||||
}
|
||||
|
||||
return (_numberOfPossibleMoves != 0);
|
||||
}
|
||||
|
||||
bool PuzzleTicTacToe::arbitraryPlacement() {
|
||||
_numberOfPossibleMoves = 0;
|
||||
|
||||
for (uint32 i = 0; i < ARRAYSIZE(_board); i++) {
|
||||
if (_board[i] == ' ') {
|
||||
_moveList[_numberOfPossibleMoves] = i;
|
||||
++_numberOfPossibleMoves;
|
||||
}
|
||||
}
|
||||
|
||||
return (_numberOfPossibleMoves != 0);
|
||||
}
|
||||
|
||||
void PuzzleTicTacToe::computerMoves() {
|
||||
_frameIndex = 0;
|
||||
_currentPos = _moveList[rnd(_numberOfPossibleMoves)];
|
||||
|
||||
if (_board[_currentPos] != ' ')
|
||||
error("[PuzzleTicTacToe::computerMoves] Field is already occupied (%d)!", _currentPos);
|
||||
|
||||
_board[_currentPos] = 'O';
|
||||
|
||||
getSound()->playSound(getWorld()->soundResourceIds[12], false, Config.sfxVolume - 100);
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
91
engines/asylum/puzzles/tictactoe.h
Normal file
91
engines/asylum/puzzles/tictactoe.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_TICTACTOE_H
|
||||
#define ASYLUM_PUZZLES_TICTACTOE_H
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleTicTacToe : public Puzzle {
|
||||
public:
|
||||
PuzzleTicTacToe(AsylumEngine *engine);
|
||||
~PuzzleTicTacToe();
|
||||
|
||||
private:
|
||||
enum GameStatus {
|
||||
kStatus0,
|
||||
kStatusFree,
|
||||
kStatusNeedBlocking
|
||||
};
|
||||
|
||||
uint32 _ticker;
|
||||
uint32 _frameIndex;
|
||||
uint32 _frameCount;
|
||||
int32 _currentPos;
|
||||
bool _gameOver;
|
||||
int32 _winLine;
|
||||
|
||||
uint32 _solveDelay;
|
||||
uint32 _brokenLines;
|
||||
|
||||
char _board[9];
|
||||
uint32 _moveList[40];
|
||||
uint32 _numberOfPossibleMoves;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
void updateScreen();
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Init & update
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void clearBoard();
|
||||
void drawField();
|
||||
void getTwoEmpty(uint32 field1, uint32 field2, uint32 field3);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Game
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool computerThinks();
|
||||
GameStatus returnLineData(uint32 field1, uint32 field2, uint32 field3, char mark, uint32 *counterX, uint32 *counterO) const;
|
||||
bool expandLine();
|
||||
bool tryNewLine();
|
||||
uint32 returnEmptySlot(uint32 position1, uint32 position2, uint position3) const;
|
||||
bool checkWin();
|
||||
int32 lookForAWinner();
|
||||
bool strategy(char mark);
|
||||
bool tryToWin() { return strategy('X'); }
|
||||
bool tryNotToLose() { return strategy('O'); }
|
||||
bool arbitraryPlacement();
|
||||
void computerMoves();
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_TICTACTOE_H
|
||||
260
engines/asylum/puzzles/timemachine.cpp
Normal file
260
engines/asylum/puzzles/timemachine.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
/* 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/timemachine.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 int16 puzzleTimeMachineRects[10][4] = {
|
||||
{ 0, 241, 20, 276}, { 0, 285, 20, 320},
|
||||
{117, 245, 137, 280}, {117, 284, 137, 319},
|
||||
{236, 246, 256, 281}, {236, 290, 256, 325},
|
||||
{356, 245, 376, 280}, {356, 287, 376, 322},
|
||||
{476, 248, 496, 283}, {475, 290, 495, 325}
|
||||
};
|
||||
|
||||
const int16 puzzleTimeMachinePoints[5][2] = {
|
||||
{-65, -30}, {-20, -68}, { 25, -106}, { 70, -144}, {115, -182}
|
||||
};
|
||||
|
||||
PuzzleTimeMachine::PuzzleTimeMachine(AsylumEngine *engine) : Puzzle(engine) {
|
||||
_leftButtonClicked = true;
|
||||
_counter = 0;
|
||||
|
||||
memset(&_frameIndexes, 0, sizeof(_frameIndexes));
|
||||
memset(&_frameCounts, 0, sizeof(_frameCounts));
|
||||
memset(&_frameIncrements, 0, sizeof(_frameIncrements));
|
||||
memset(&_state, 0, sizeof(_state));
|
||||
|
||||
_data_45AAA8 = _data_45AAAC = 0;
|
||||
_currentFrameIndex = 0;
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
PuzzleTimeMachine::~PuzzleTimeMachine() {
|
||||
}
|
||||
|
||||
void PuzzleTimeMachine::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
s.syncAsSint32LE(_frameIndexes[0]);
|
||||
s.syncAsSint32LE(_frameIndexes[1]);
|
||||
s.syncAsSint32LE(_frameIndexes[2]);
|
||||
s.syncAsSint32LE(_frameIndexes[3]);
|
||||
s.syncAsSint32LE(_frameIndexes[4]);
|
||||
|
||||
s.skip(4); // Unused
|
||||
|
||||
s.syncBytes((byte *)&_state, sizeof(_state));
|
||||
s.skip(3); // We only use 5 elements i the state array
|
||||
|
||||
s.skip(5 * 4 * 2); // The original saves 4 points that are static data
|
||||
|
||||
s.syncAsSint32LE(_point.x);
|
||||
s.syncAsSint32LE(_point.y);
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
s.syncAsSint32LE(_frameIncrements[i]);
|
||||
|
||||
s.syncAsSint32LE(_currentFrameIndex);
|
||||
|
||||
s.syncAsSint32LE(_data_45AAA8);
|
||||
s.syncAsSint32LE(_data_45AAAC);
|
||||
|
||||
s.syncAsSint32LE(_frameIndexes[5]);
|
||||
}
|
||||
|
||||
void PuzzleTimeMachine::reset() {
|
||||
_frameIndexes[0] = 0;
|
||||
_frameIndexes[1] = 4;
|
||||
_frameIndexes[2] = 20;
|
||||
_frameIndexes[3] = 16;
|
||||
_frameIndexes[4] = 20;
|
||||
|
||||
_index = -1;
|
||||
_index2 = 0;
|
||||
_point.x = _newPoint.x = puzzleTimeMachinePoints[0][0];
|
||||
_point.y = _newPoint.y = puzzleTimeMachinePoints[0][1];
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleTimeMachine::init(const AsylumEvent &evt) {
|
||||
getCursor()->set(getWorld()->graphicResourceIds[62], -1, kCursorAnimationMirror, 7);
|
||||
|
||||
_frameCounts[0] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[35]);
|
||||
_frameCounts[1] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[36]);
|
||||
_frameCounts[2] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[37]);
|
||||
_frameCounts[3] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[38]);
|
||||
_frameCounts[4] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[39]);
|
||||
_frameCounts[5] = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[40]);
|
||||
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[41]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[41]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PuzzleTimeMachine::updateScreen() {
|
||||
// Draw screen elements
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
getScreen()->fillRect(0, 0, 640, 480, 115);
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[34], 0, Common::Point(0, 0), kDrawFlagNone, true);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[35], _frameIndexes[0], Common::Point( 23, 215), kDrawFlagNone, 0, 3);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[36], _frameIndexes[1], Common::Point( 70, 217), kDrawFlagNone, 0, 3);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[37], _frameIndexes[2], Common::Point(189, 217), kDrawFlagNone, 0, 3);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[38], _frameIndexes[3], Common::Point(309, 218), kDrawFlagNone, 0, 3);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[39], _frameIndexes[4], Common::Point(429, 212), kDrawFlagNone, 0, 3);
|
||||
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[40], _frameIndexes[5], _point, kDrawFlagNone, 0, 1);
|
||||
if (_point.x < _newPoint.x)
|
||||
_point += Common::Point(15, -12 - (abs((double)(_point.x - _newPoint.x)) > 15 ? 1 : 0));
|
||||
else if (_point.x > _newPoint.x)
|
||||
_point -= Common::Point(15, -12 - (abs((double)(_point.x - _newPoint.x)) > 15 ? 1 : 0));
|
||||
|
||||
if (_frameIndexes[0] != 28 || _frameIndexes[1] || _frameIndexes[2] || _frameIndexes[3] || _frameIndexes[4]) {
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[43], 0, Common::Point(599, 220), kDrawFlagNone, 0, 2);
|
||||
} else {
|
||||
getSound()->stop(getWorld()->soundResourceIds[17]);
|
||||
getSound()->stop(getWorld()->soundResourceIds[16]);
|
||||
|
||||
if (_vm->isGameFlagNotSet(kGameFlag925))
|
||||
getSound()->playSound(getWorld()->soundResourceIds[18]);
|
||||
|
||||
_vm->setGameFlag(kGameFlag925);
|
||||
|
||||
++_counter;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Show all buttons
|
||||
for (uint32 i = 0; i < ARRAYSIZE(puzzleTimeMachineRects); i += 2) {
|
||||
if ((uint32)_index != i || _leftButtonClicked)
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[44 + i], 0, Common::Point(puzzleTimeMachineRects[i][0], puzzleTimeMachineRects[i][1]), kDrawFlagNone, 0, 5);
|
||||
}
|
||||
|
||||
for (uint32 i = 1; i < ARRAYSIZE(puzzleTimeMachineRects); i += 2) {
|
||||
if ((uint32)_index != i || _leftButtonClicked)
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[44 + i], 0, Common::Point(puzzleTimeMachineRects[i][0], puzzleTimeMachineRects[i][1]), kDrawFlagNone, 0, 5);
|
||||
}
|
||||
|
||||
_leftButtonClicked = true;
|
||||
|
||||
// Check for puzzle completion
|
||||
if (_counter > 30 && _vm->isGameFlagSet(kGameFlag925)) {
|
||||
getCursor()->hide();
|
||||
getSharedData()->setFlag(kFlag1, true);
|
||||
getScreen()->stopPaletteFade(0, 0, 0);
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
}
|
||||
|
||||
// Update frame indexes & increments
|
||||
if (_index != -1) {
|
||||
_frameIndexes[_index / 2] += _frameIncrements[_index / 2];
|
||||
if (_frameIndexes[_index / 2] < 0) {
|
||||
_frameIndexes[_index / 2] = _frameCounts[_index / 2] - 1;
|
||||
} else if (_frameIndexes[_index / 2] > (int32)_frameCounts[_index / 2] - 1) {
|
||||
_frameIndexes[_index / 2] = 0;
|
||||
_frameIncrements[_index / 2] = 0;
|
||||
} else if (!(_frameIndexes[_index / 2] % 4)) {
|
||||
getSound()->playSound(getWorld()->soundResourceIds[15]);
|
||||
_frameIncrements[_index / 2] = 0;
|
||||
_index = -1;
|
||||
}
|
||||
|
||||
_frameIndexes[5] = (_frameIndexes[5] + 1) % _frameCounts[5];
|
||||
}
|
||||
}
|
||||
|
||||
bool PuzzleTimeMachine::mouseLeftDown(const AsylumEvent &evt) {
|
||||
if (_vm->isGameFlagSet(kGameFlag925))
|
||||
return true;
|
||||
|
||||
_leftButtonClicked = false;
|
||||
|
||||
int32 index = -1;
|
||||
for (uint32 i = 0; i < ARRAYSIZE(puzzleTimeMachineRects); i++) {
|
||||
if (_vm->rectContains(&puzzleTimeMachineRects[i], evt.mouse)) {
|
||||
index = i;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1)
|
||||
return true;
|
||||
|
||||
getSound()->playSound(getWorld()->soundResourceIds[14]);
|
||||
if ((_index2 / 2) != (uint32)index / 2) {
|
||||
getSound()->playSound(getWorld()->soundResourceIds[16]);
|
||||
_newPoint.x = puzzleTimeMachinePoints[index / 2][0];
|
||||
_newPoint.y = puzzleTimeMachinePoints[index / 2][1];
|
||||
}
|
||||
|
||||
if (index % 2)
|
||||
_frameIncrements[index / 2] = 1;
|
||||
else
|
||||
_frameIncrements[index / 2] = -1;
|
||||
|
||||
_index = _index2 = index;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleTimeMachine::exitPuzzle() {
|
||||
getCursor()->hide();
|
||||
getSharedData()->setFlag(kFlag1, true);
|
||||
getScreen()->stopPaletteFade(0, 0, 0);
|
||||
_vm->switchEventHandler(getScene());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleTimeMachine::updateCursor() {
|
||||
for (uint32 i = 0; i < ARRAYSIZE(puzzleTimeMachineRects); i++) {
|
||||
if (_vm->rectContains(&puzzleTimeMachineRects[i], getCursor()->position())) {
|
||||
if (getCursor()->getAnimation() != kCursorAnimationMirror)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[62], -1, kCursorAnimationMirror, 7);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (getCursor()->getAnimation())
|
||||
getCursor()->set(getWorld()->graphicResourceIds[62], -1, kCursorAnimationNone, 7);
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
75
engines/asylum/puzzles/timemachine.h
Normal file
75
engines/asylum/puzzles/timemachine.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_TIMEMACHINE_H
|
||||
#define ASYLUM_PUZZLES_TIMEMACHINE_H
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleTimeMachine : public Puzzle {
|
||||
public:
|
||||
PuzzleTimeMachine(AsylumEngine *engine);
|
||||
~PuzzleTimeMachine();
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
bool _leftButtonClicked;
|
||||
uint32 _counter;
|
||||
int32 _frameIndexes[6];
|
||||
uint32 _frameCounts[6];
|
||||
int32 _frameIncrements[5];
|
||||
int32 _index;
|
||||
uint32 _index2;
|
||||
Common::Point _point;
|
||||
Common::Point _newPoint;
|
||||
|
||||
// Unused puzzle variables
|
||||
int8 _state[5];
|
||||
//bool _data_4572BC;
|
||||
//bool _data_4572CC;
|
||||
uint32 _data_45AAA8;
|
||||
uint32 _data_45AAAC;
|
||||
uint32 _currentFrameIndex;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
void updateScreen();
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void updateCursor();
|
||||
void reset();
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_TIMEMACHINE_H
|
||||
596
engines/asylum/puzzles/vcr.cpp
Normal file
596
engines/asylum/puzzles/vcr.cpp
Normal file
@@ -0,0 +1,596 @@
|
||||
/* 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/vcr.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/views/video.h"
|
||||
|
||||
#include "asylum/asylum.h"
|
||||
#include "asylum/respack.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
PuzzleVCR::PuzzleVCR(AsylumEngine *engine): Puzzle(engine) {
|
||||
// reset all states
|
||||
memset(&_jacksState, 0, sizeof(_jacksState));
|
||||
memset(&_holesState, 0, sizeof(_holesState));
|
||||
memset(&_buttonsState, 0, sizeof(_buttonsState));
|
||||
|
||||
_tvScreenFrameIndex = 0;
|
||||
_isAccomplished = false;
|
||||
}
|
||||
|
||||
PuzzleVCR::~PuzzleVCR() {
|
||||
}
|
||||
|
||||
void PuzzleVCR::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
s.syncAsUint32LE(_buttonsState[kPowerButton]);
|
||||
s.syncAsUint32LE(_buttonsState[kRewindButton]);
|
||||
s.syncAsUint32LE(_buttonsState[kPlayButton]);
|
||||
s.syncAsUint32LE(_buttonsState[kStopButton]);
|
||||
|
||||
s.syncAsUint32LE(_holesState[kBlack]);
|
||||
s.syncAsUint32LE(_holesState[kRed]);
|
||||
s.syncAsUint32LE(_holesState[kYellow]);
|
||||
|
||||
|
||||
s.syncAsUint32LE(_jacksState[kBlack]);
|
||||
s.syncAsUint32LE(_jacksState[kRed]);
|
||||
s.syncAsUint32LE(_jacksState[kYellow]);
|
||||
|
||||
s.syncAsUint32LE(_tvScreenFrameIndex);
|
||||
s.syncAsUint32LE(_isAccomplished);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleVCR::init(const AsylumEvent &) {
|
||||
// Load the graphics palette
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[29]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[29]);
|
||||
|
||||
if (_jacksState[kBlack] == kOnHand || _jacksState[kRed] == kOnHand || _jacksState[kYellow] == kOnHand) {
|
||||
getCursor()->hide();
|
||||
getSharedData()->setFlag(kFlag1, true);
|
||||
} else {
|
||||
getCursor()->set(getWorld()->graphicResourceIds[28]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleVCR::mouseLeftDown(const AsylumEvent &evt) {
|
||||
if (_isAccomplished)
|
||||
return true;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Plug-in jacks
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
JackState state = kPluggedOnRed;
|
||||
if (_jacksState[kBlack] != kOnHand) {
|
||||
if (_jacksState[kRed] == kOnHand)
|
||||
state = kPluggedOnYellow;
|
||||
else
|
||||
state = (_jacksState[kYellow] != kOnHand) ? kOnTable : kPluggedOnBlack;
|
||||
}
|
||||
|
||||
if (inPolygon(evt.mouse, kRedHole)) {
|
||||
setJackOnHole(kBlack, state, kPluggedOnRed);
|
||||
} else if (inPolygon(evt.mouse, kYellowHole)) {
|
||||
setJackOnHole(kRed, state, kPluggedOnYellow);
|
||||
} else if (inPolygon(evt.mouse, kBlackHole)) {
|
||||
setJackOnHole(kYellow, state, kPluggedOnBlack);
|
||||
|
||||
if (_holesState[kYellow] != kPluggedOnYellow && _buttonsState[kPowerButton] == kON) {
|
||||
_buttonsState[kStopButton] = kOFF;
|
||||
_buttonsState[kPlayButton] = kOFF;
|
||||
_buttonsState[kRewindButton] = kOFF;
|
||||
_buttonsState[kPowerButton] = kOFF;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Put jacks on table
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Color jack = getJackOnHand();
|
||||
if (jack != kNone) {
|
||||
if (evt.mouse.x >= (int32)puzzleVCRPolygons[kBlackJack][0] && evt.mouse.x <= (int32)puzzleVCRPolygons[kYellowJack][2]
|
||||
&& evt.mouse.y >= (int32)puzzleVCRPolygons[kBlackJack][1] && evt.mouse.y <= (int32)puzzleVCRPolygons[kYellowJack][3]) {
|
||||
|
||||
_jacksState[jack] = kOnTable;
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[50]);
|
||||
getCursor()->show();
|
||||
getSharedData()->setFlag(kFlag1, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Get Jacks from Table
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
getCursor()->show();
|
||||
getSharedData()->setFlag(kFlag1, false);
|
||||
|
||||
|
||||
if (inPolygon(evt.mouse, kBlackJack))
|
||||
pickJack(kBlack);
|
||||
else if (inPolygon(evt.mouse, kRedJack))
|
||||
pickJack(kRed);
|
||||
else if (inPolygon(evt.mouse, kYellowJack))
|
||||
pickJack(kYellow);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// VCR button regions
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (inPolygon(evt.mouse, kRewindButton)) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[39]);
|
||||
|
||||
if (!_buttonsState[kRewindButton])
|
||||
_buttonsState[kRewindButton] = kDownON;
|
||||
else if (_buttonsState[kRewindButton] == kON)
|
||||
_buttonsState[kRewindButton] = kDownOFF;
|
||||
|
||||
} else if (inPolygon(evt.mouse, kPlayButton)) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[39]);
|
||||
|
||||
if (!_buttonsState[kPlayButton])
|
||||
_buttonsState[kPlayButton] = kDownON;
|
||||
else if (_buttonsState[kPlayButton] == kON)
|
||||
_buttonsState[kPlayButton] = kDownOFF;
|
||||
|
||||
} else if (inPolygon(evt.mouse, kStopButton)) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[39]);
|
||||
|
||||
if (!_buttonsState[kStopButton])
|
||||
_buttonsState[kStopButton] = kDownON;
|
||||
else if (_buttonsState[kStopButton] == kON)
|
||||
_buttonsState[kStopButton] = kDownOFF;
|
||||
|
||||
} else if (inPolygon(evt.mouse, kPowerButton)) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[39]);
|
||||
|
||||
if (!_buttonsState[kPowerButton] && _holesState[kYellow] == kPluggedOnRed) {
|
||||
_buttonsState[kPowerButton] = kDownON;
|
||||
} else {
|
||||
_buttonsState[kPowerButton] = kDownOFF;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleVCR::mouseLeftUp(const AsylumEvent &) {
|
||||
if (_isAccomplished)
|
||||
return true;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Power
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (_buttonsState[kPowerButton] == kDownON) {
|
||||
if (!getSound()->isPlaying(getWorld()->graphicResourceIds[47]))
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[47], true);
|
||||
|
||||
_buttonsState[kPowerButton] = kON;
|
||||
_buttonsState[kStopButton] = kON;
|
||||
_buttonsState[kPlayButton] = kON;
|
||||
_buttonsState[kRewindButton] = kON;
|
||||
} else if (_buttonsState[kPowerButton] == kDownOFF) {
|
||||
_buttonsState[kPowerButton] = kOFF;
|
||||
_buttonsState[kStopButton] = kOFF;
|
||||
_buttonsState[kPlayButton] = kOFF;
|
||||
_buttonsState[kRewindButton] = kOFF;
|
||||
|
||||
getSound()->stop(getWorld()->graphicResourceIds[47]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Rewind
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (_buttonsState[kRewindButton] == kDownOFF) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[46]);
|
||||
_buttonsState[kRewindButton] = kON;
|
||||
} else if (_buttonsState[kRewindButton] == kDownON) {
|
||||
_buttonsState[kRewindButton] = kOFF;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Play
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (_buttonsState[kPlayButton] == kDownOFF) {
|
||||
_buttonsState[kPlayButton] = kON;
|
||||
|
||||
if (_holesState[kBlack] == kPluggedOnYellow
|
||||
&& _holesState[kRed] == kPluggedOnBlack
|
||||
&& _holesState[kYellow] == kPluggedOnRed) {
|
||||
getCursor()->hide();
|
||||
_vm->setGameFlag(kGameFlagSolveVCRPuzzle);
|
||||
_isAccomplished = true;
|
||||
}
|
||||
} else if (_buttonsState[kPlayButton] == kDownON) {
|
||||
_buttonsState[kPlayButton] = kOFF;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Stop
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (_buttonsState[kStopButton] == kDownOFF) {
|
||||
_buttonsState[kStopButton] = kON;
|
||||
} else if (_buttonsState[kStopButton] == kDownON) {
|
||||
_buttonsState[kStopButton] = kOFF;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleVCR::exitPuzzle() {
|
||||
getSound()->stop(getWorld()->graphicResourceIds[47]);
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
getScreen()->clear();
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Drawing
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleVCR::updateScreen() {
|
||||
// Draw background
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
getScreen()->fillRect(0, 0, 640, 480, 252);
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[0], 0, Common::Point(0, 0), kDrawFlagNone, true);
|
||||
|
||||
updateBlackJack();
|
||||
updateRedJack();
|
||||
updateYellowJack();
|
||||
|
||||
updatePowerButton();
|
||||
updateRewindButton();
|
||||
updatePlayButton();
|
||||
updateStopButton();
|
||||
|
||||
if (_buttonsState[kPowerButton] == kON) {
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[22], _tvScreenFrameIndex, Common::Point(0, 37), kDrawFlagNone, 0, 1);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[23], _tvScreenFrameIndex++, Common::Point(238, 22), kDrawFlagNone, 0, 1);
|
||||
|
||||
_tvScreenFrameIndex %= GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[22]);
|
||||
}
|
||||
|
||||
if (_isAccomplished) {
|
||||
getCursor()->show();
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[0]);
|
||||
|
||||
getScreen()->clearDefaultColor();
|
||||
for (int16 barSize = 0; barSize < 84; barSize += 4) {
|
||||
getScreen()->drawWideScreenBars(barSize);
|
||||
_vm->_system->updateScreen();
|
||||
}
|
||||
|
||||
// Palette fade
|
||||
getScreen()->paletteFade(0, 25, 10);
|
||||
getScreen()->clear();
|
||||
|
||||
getScene()->updateScreen();
|
||||
getScreen()->drawWideScreenBars(82);
|
||||
getSound()->stop(getWorld()->graphicResourceIds[47]);
|
||||
getSound()->playMusic(kResourceNone, 0);
|
||||
getScreen()->clear();
|
||||
|
||||
getVideo()->play(2, getScene());
|
||||
|
||||
if (getWorld()->musicCurrentResourceIndex != kMusicStopped)
|
||||
getSound()->playMusic(MAKE_RESOURCE(kResourcePackMusic, getWorld()->musicCurrentResourceIndex));
|
||||
|
||||
getScreen()->paletteFade(0, 2, 1);
|
||||
getScreen()->clear();
|
||||
|
||||
// setupPalette();
|
||||
getScreen()->setupPalette(nullptr, 0, 0);
|
||||
|
||||
int paletteId = _vm->checkGameVersion("Demo") ? 20 : 28;
|
||||
getScreen()->setPalette(MAKE_RESOURCE(kResourcePackTowerCells, paletteId));
|
||||
getScreen()->setGammaLevel(MAKE_RESOURCE(kResourcePackTowerCells, paletteId));
|
||||
}
|
||||
}
|
||||
|
||||
void PuzzleVCR::updateCursor() {
|
||||
Color jack = getJackOnHand();
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
if (mousePos.x)
|
||||
mousePos.x = 465;
|
||||
|
||||
if (jack == kNone) {
|
||||
if (inPolygon(mousePos, kRewindButton)
|
||||
|| inPolygon(mousePos, kStopButton)
|
||||
|| inPolygon(mousePos, kPlayButton)
|
||||
|| inPolygon(mousePos, kPowerButton)
|
||||
|| inPolygon(mousePos, kBlackJack)
|
||||
|| inPolygon(mousePos, kRedJack)
|
||||
|| inPolygon(mousePos, kYellowJack)) {
|
||||
if (getCursor()->getAnimation() != kCursorAnimationMirror)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[28]);
|
||||
} else if ((inPolygon(mousePos, kRedHole) && _holesState[kBlack])
|
||||
|| (inPolygon(mousePos, kYellowHole) && _holesState[kRed])
|
||||
|| (inPolygon(mousePos, kBlackHole) && _holesState[kYellow])) {
|
||||
if (getCursor()->getAnimation() != kCursorAnimationMirror)
|
||||
getCursor()->set(getWorld()->graphicResourceIds[28]);
|
||||
} else {
|
||||
if (getCursor()->getAnimation())
|
||||
getCursor()->set(getWorld()->graphicResourceIds[28], kCursorAnimationNone);
|
||||
}
|
||||
} else {
|
||||
getCursor()->hide();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Update Jack
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleVCR::updateJack(Color jack, const VCRDrawInfo &onTable, const VCRDrawInfo &pluggedOnRed, const VCRDrawInfo &pluggedOnYellow, const VCRDrawInfo &pluggedOnBlack, int32 resourceOnHandIndex) {
|
||||
GraphicQueueItem item;
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
switch (_jacksState[jack]) {
|
||||
default:
|
||||
return;
|
||||
|
||||
case kOnTable:
|
||||
item.resourceId = getWorld()->graphicResourceIds[onTable.resourceId];
|
||||
item.source = onTable.point;
|
||||
item.priority = 3;
|
||||
break;
|
||||
|
||||
case kPluggedOnRed:
|
||||
item.resourceId = getWorld()->graphicResourceIds[pluggedOnRed.resourceId];
|
||||
item.source = Common::Point(329, 407);
|
||||
item.priority = 3;
|
||||
break;
|
||||
|
||||
case kPluggedOnYellow:
|
||||
item.resourceId = getWorld()->graphicResourceIds[pluggedOnYellow.resourceId];
|
||||
item.source = Common::Point(402, 413);
|
||||
item.priority = 3;
|
||||
break;
|
||||
|
||||
case kPluggedOnBlack:
|
||||
item.resourceId = getWorld()->graphicResourceIds[pluggedOnBlack.resourceId];
|
||||
item.source = Common::Point(477, 418);
|
||||
item.priority = 3;
|
||||
break;
|
||||
|
||||
case kOnHand:
|
||||
// Jack
|
||||
item.resourceId = getWorld()->graphicResourceIds[resourceOnHandIndex];
|
||||
item.source = Common::Point(mousePos.x - 114, mousePos.y < 356 ? 342 : mousePos.y - 14);
|
||||
item.priority = 1;
|
||||
getScreen()->addGraphicToQueue(item);
|
||||
|
||||
// Shadow
|
||||
item.resourceId = getWorld()->graphicResourceIds[30];
|
||||
item.source = Common::Point(mousePos.x - (mousePos.y < 356 ? 0 : (mousePos.y - 356) / 4), 450);
|
||||
item.priority = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
getScreen()->addGraphicToQueue(item);
|
||||
}
|
||||
|
||||
void PuzzleVCR::updateBlackJack() {
|
||||
VCRDrawInfo onTable;
|
||||
onTable.resourceId = 1;
|
||||
onTable.point = Common::Point(0, 411);
|
||||
|
||||
VCRDrawInfo pluggedOnRed;
|
||||
pluggedOnRed.resourceId = 5;
|
||||
|
||||
VCRDrawInfo pluggedOnYellow;
|
||||
pluggedOnYellow.resourceId = 8;
|
||||
|
||||
VCRDrawInfo pluggedOnBlack;
|
||||
pluggedOnBlack.resourceId = 11;
|
||||
|
||||
updateJack(kBlack, onTable, pluggedOnRed, pluggedOnYellow, pluggedOnBlack, 27);
|
||||
}
|
||||
|
||||
void PuzzleVCR::updateRedJack() {
|
||||
VCRDrawInfo onTable;
|
||||
onTable.resourceId = 2;
|
||||
onTable.point = Common::Point(76, 428);
|
||||
|
||||
VCRDrawInfo pluggedOnRed;
|
||||
pluggedOnRed.resourceId = 4;
|
||||
|
||||
VCRDrawInfo pluggedOnYellow;
|
||||
pluggedOnYellow.resourceId = 7;
|
||||
|
||||
VCRDrawInfo pluggedOnBlack;
|
||||
pluggedOnBlack.resourceId = 10;
|
||||
|
||||
updateJack(kRed, onTable, pluggedOnRed, pluggedOnYellow, pluggedOnBlack, 25);
|
||||
}
|
||||
|
||||
void PuzzleVCR::updateYellowJack() {
|
||||
VCRDrawInfo onTable;
|
||||
onTable.resourceId = 3;
|
||||
onTable.point = Common::Point(187, 439);
|
||||
|
||||
VCRDrawInfo pluggedOnRed;
|
||||
pluggedOnRed.resourceId = 6;
|
||||
|
||||
VCRDrawInfo pluggedOnYellow;
|
||||
pluggedOnYellow.resourceId = 9;
|
||||
|
||||
VCRDrawInfo pluggedOnBlack;
|
||||
pluggedOnBlack.resourceId = 12;
|
||||
|
||||
updateJack(kYellow, onTable, pluggedOnRed, pluggedOnYellow, pluggedOnBlack, 26);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Update Button
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PuzzleVCR::updateButton(VCRRegions button, const VCRDrawInfo &btON, const VCRDrawInfo &btDown) {
|
||||
GraphicQueueItem item;
|
||||
|
||||
switch (_buttonsState[button]) {
|
||||
default:
|
||||
return;
|
||||
|
||||
case kON:
|
||||
item.resourceId = getWorld()->graphicResourceIds[btON.resourceId];
|
||||
item.source = btON.point;
|
||||
item.priority = 3;
|
||||
break;
|
||||
|
||||
case kDownON:
|
||||
case kDownOFF:
|
||||
item.resourceId = getWorld()->graphicResourceIds[btDown.resourceId];
|
||||
item.source = btDown.point;
|
||||
item.priority = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
getScreen()->addGraphicToQueue(item);
|
||||
}
|
||||
|
||||
void PuzzleVCR::updatePowerButton() {
|
||||
VCRDrawInfo btON;
|
||||
btON.resourceId = 17;
|
||||
btON.point = Common::Point(512, 347);
|
||||
|
||||
VCRDrawInfo btDown;
|
||||
btDown.resourceId = 21;
|
||||
btDown.point = Common::Point(506, 343);
|
||||
|
||||
updateButton(kPowerButton, btON, btDown);
|
||||
}
|
||||
|
||||
void PuzzleVCR::updateRewindButton() {
|
||||
VCRDrawInfo btON;
|
||||
btON.resourceId = 14;
|
||||
btON.point = Common::Point(248, 347);
|
||||
|
||||
VCRDrawInfo btDown;
|
||||
btDown.resourceId = 18;
|
||||
btDown.point = Common::Point(245, 344);
|
||||
|
||||
updateButton(kRewindButton, btON, btDown);
|
||||
}
|
||||
|
||||
void PuzzleVCR::updatePlayButton() {
|
||||
VCRDrawInfo btON;
|
||||
btON.resourceId = 16;
|
||||
btON.point = Common::Point(401, 359);
|
||||
|
||||
VCRDrawInfo btDown;
|
||||
btDown.resourceId = 20;
|
||||
btDown.point = Common::Point(391, 355);
|
||||
|
||||
updateButton(kPlayButton, btON, btDown);
|
||||
}
|
||||
|
||||
void PuzzleVCR::updateStopButton() {
|
||||
VCRDrawInfo btON;
|
||||
btON.resourceId = 15;
|
||||
btON.point = Common::Point(330, 354);
|
||||
|
||||
VCRDrawInfo btDown;
|
||||
btDown.resourceId = 19;
|
||||
btDown.point = Common::Point(326, 350);
|
||||
|
||||
updateButton(kStopButton, btON, btDown);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int PuzzleVCR::inPolygon(const Common::Point &point, int polygonIndex) const {
|
||||
return _vm->rectContains(&puzzleVCRPolygons[polygonIndex], point);
|
||||
}
|
||||
|
||||
PuzzleVCR::Color PuzzleVCR::getJackOnHand() const {
|
||||
Color jack = kNone;
|
||||
if (_jacksState[kBlack] == kOnHand)
|
||||
jack = kBlack;
|
||||
else if (_jacksState[kRed] == kOnHand)
|
||||
jack = kRed;
|
||||
else if (_jacksState[kYellow] == kOnHand)
|
||||
jack = kYellow;
|
||||
|
||||
return jack;
|
||||
}
|
||||
|
||||
void PuzzleVCR::setJackOnHole(Color hole, JackState state, JackState newState) {
|
||||
bool isYellow = (hole == kYellow);
|
||||
|
||||
if (_holesState[hole]) {
|
||||
if (isYellow)
|
||||
getSound()->stop(getWorld()->graphicResourceIds[47]);
|
||||
|
||||
_jacksState[_holesState[hole] - 1] = kOnHand;
|
||||
_holesState[hole] = kOnTable;
|
||||
|
||||
if (state != kOnTable) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[44]);
|
||||
_holesState[hole] = state;
|
||||
|
||||
if (isYellow) {
|
||||
if (state != kPluggedOnYellow && _buttonsState[kPowerButton] == kON)
|
||||
getSound()->stop(getWorld()->graphicResourceIds[47]);
|
||||
}
|
||||
|
||||
_jacksState[state - 1] = newState;
|
||||
} else {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[43]);
|
||||
getCursor()->hide();
|
||||
getSharedData()->setFlag(kFlag1, true);
|
||||
}
|
||||
} else if (state != kOnTable) {
|
||||
getSound()->playSound(getWorld()->graphicResourceIds[44]);
|
||||
_holesState[hole] = state;
|
||||
|
||||
if (isYellow) {
|
||||
if (state != kPluggedOnYellow && _buttonsState[kPowerButton] == kON)
|
||||
getSound()->stop(getWorld()->graphicResourceIds[47]);
|
||||
}
|
||||
|
||||
_jacksState[state - 1] = newState;
|
||||
}
|
||||
}
|
||||
|
||||
void PuzzleVCR::pickJack(Color jack) {
|
||||
getCursor()->hide();
|
||||
getSharedData()->setFlag(kFlag1, true);
|
||||
_jacksState[jack] = kOnHand;
|
||||
}
|
||||
|
||||
} // end of namespace Asylum
|
||||
146
engines/asylum/puzzles/vcr.h
Normal file
146
engines/asylum/puzzles/vcr.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_VCR_H
|
||||
#define ASYLUM_PUZZLES_VCR_H
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
#include "asylum/shared.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
typedef struct VCRDrawInfo {
|
||||
int32 resourceId;
|
||||
Common::Point point;
|
||||
} VCRDrawInfo;
|
||||
|
||||
const int16 puzzleVCRPolygons[10][4] = {
|
||||
{0x0F7, 0x157, 0x13A, 0x183}, // rewind button region
|
||||
{0x14B, 0x15C, 0x17B, 0x18B}, // stop button region
|
||||
{0x18C, 0x161, 0x1D2, 0x18F}, // play button region
|
||||
{0x1FB, 0x156, 0x233, 0x185}, // rec button region
|
||||
{0x154, 0x196, 0x173, 0x1AF}, // red jack hole region
|
||||
{0x19A, 0x19B, 0x1B9, 0x1B3}, // yellow jack hole region
|
||||
{0x1E3, 0x1A0, 0x202, 0x1BC}, // black jack hole region
|
||||
{0x0, 0x19B, 0x3C, 0x1E0}, // black jack on table region
|
||||
{0x4C, 0x1AC, 0x0A0, 0x1E0}, // red jack on table region
|
||||
{0x0BB, 0x1B7, 0x0F0, 0x1E0} // yellow jack on table region
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Puzzle 1
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class PuzzleVCR : public Puzzle {
|
||||
public:
|
||||
PuzzleVCR(AsylumEngine *engine);
|
||||
~PuzzleVCR();
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
enum Color {
|
||||
kNone = -1,
|
||||
kBlack = 0,
|
||||
kRed = 1,
|
||||
kYellow = 2
|
||||
};
|
||||
|
||||
enum JackState {
|
||||
kOnTable = 0,
|
||||
kPluggedOnRed = 1,
|
||||
kPluggedOnYellow = 2,
|
||||
kPluggedOnBlack = 3,
|
||||
kOnHand = 4
|
||||
};
|
||||
|
||||
enum VCRRegions {
|
||||
kRewindButton = 0,
|
||||
kStopButton = 1,
|
||||
kPlayButton = 2,
|
||||
kPowerButton = 3,
|
||||
kRedHole = 4,
|
||||
kYellowHole = 5,
|
||||
kBlackHole = 6,
|
||||
kBlackJack = 7,
|
||||
kRedJack = 8,
|
||||
kYellowJack = 9
|
||||
};
|
||||
|
||||
enum ButtonState {
|
||||
kOFF = 0,
|
||||
kON = 1,
|
||||
kDownON = 2,
|
||||
kDownOFF = 3
|
||||
};
|
||||
|
||||
JackState _jacksState[3];
|
||||
JackState _holesState[3];
|
||||
ButtonState _buttonsState[4];
|
||||
uint32 _tvScreenFrameIndex;
|
||||
bool _isAccomplished;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool mouseLeftUp(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Drawing
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void updateScreen();
|
||||
void updateCursor();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Updates
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void updateJack(Color jack, const VCRDrawInfo &onTable, const VCRDrawInfo &pluggedOnRed, const VCRDrawInfo &pluggedOnYellow, const VCRDrawInfo &pluggedOnBlack, int32 resourceOnHandIndex);
|
||||
void updateBlackJack();
|
||||
void updateRedJack();
|
||||
void updateYellowJack();
|
||||
|
||||
void updateButton(VCRRegions button, const VCRDrawInfo &btON, const VCRDrawInfo &btDown);
|
||||
void updatePowerButton();
|
||||
void updateRewindButton();
|
||||
void updatePlayButton();
|
||||
void updateStopButton();
|
||||
|
||||
void updateTVSync();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int inPolygon(const Common::Point &point, int polyIdx) const;
|
||||
Color getJackOnHand() const;
|
||||
void setJackOnHole(Color hole, JackState state, JackState newState);
|
||||
void pickJack(Color jack);
|
||||
|
||||
};
|
||||
|
||||
} // end of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_VCR_H
|
||||
369
engines/asylum/puzzles/wheel.cpp
Normal file
369
engines/asylum/puzzles/wheel.cpp
Normal file
@@ -0,0 +1,369 @@
|
||||
/* 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
|
||||
74
engines/asylum/puzzles/wheel.h
Normal file
74
engines/asylum/puzzles/wheel.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_WHEEL_H
|
||||
#define ASYLUM_PUZZLES_WHEEL_H
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleWheel : public Puzzle {
|
||||
public:
|
||||
PuzzleWheel(AsylumEngine *engine);
|
||||
~PuzzleWheel();
|
||||
|
||||
// Serializable
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &s);
|
||||
|
||||
private:
|
||||
int32 _currentRect;
|
||||
int32 _resourceIndex;
|
||||
uint32 _resourceIndexClock;
|
||||
uint32 _resourceIndexLever;
|
||||
uint32 _frameIndexWheel;
|
||||
int32 _frameIndexes[12];
|
||||
int32 _frameIndexesSparks[8];
|
||||
|
||||
bool _showTurnedClock;
|
||||
bool _turnWheelRight;
|
||||
bool _moveLever;
|
||||
bool _moveChain;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
void updateScreen();
|
||||
bool mouseLeftDown(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void updateCursor();
|
||||
int32 findRect();
|
||||
void updateIndex();
|
||||
void checkFlags();
|
||||
void closeLocks();
|
||||
void toggleLocks();
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_WHEEL_H
|
||||
167
engines/asylum/puzzles/writings.cpp
Normal file
167
engines/asylum/puzzles/writings.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
/* 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/writings.h"
|
||||
|
||||
#include "asylum/resources/actor.h"
|
||||
#include "asylum/resources/worldstats.h"
|
||||
|
||||
#include "asylum/system/cursor.h"
|
||||
#include "asylum/system/graphics.h"
|
||||
#include "asylum/system/screen.h"
|
||||
#include "asylum/system/text.h"
|
||||
|
||||
#include "asylum/views/scene.h"
|
||||
|
||||
#include "asylum/asylum.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
PuzzleWritings::PuzzleWritings(AsylumEngine *engine) : Puzzle(engine) {
|
||||
_frameIndex = 0;
|
||||
_hasGlassMagnifier = false;
|
||||
}
|
||||
|
||||
PuzzleWritings::~PuzzleWritings() {
|
||||
_textSurface.free();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PuzzleWritings::init(const AsylumEvent &) {
|
||||
if (getScene()->getActor()->inventory.getSelectedItem() == 3)
|
||||
_hasGlassMagnifier = true;
|
||||
else
|
||||
_hasGlassMagnifier = false;
|
||||
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[10]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[10]);
|
||||
|
||||
if (_hasGlassMagnifier) {
|
||||
getCursor()->hide();
|
||||
getSharedData()->setFlag(kFlag1, true);
|
||||
_vm->setGameFlag(kGameFlag481);
|
||||
} else {
|
||||
getCursor()->set(getWorld()->graphicResourceIds[61], -1, kCursorAnimationNone, 7);
|
||||
}
|
||||
|
||||
_textSurface.create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
// Draw background
|
||||
getScreen()->fillRect(0, 0, 640, 480, 253);
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[5], 0, Common::Point(0, 0), kDrawFlagNone, true);
|
||||
|
||||
// Draw all lines of text
|
||||
int textId;
|
||||
switch (_vm->getLanguage()) {
|
||||
default:
|
||||
case Common::EN_ANY:
|
||||
textId = 1825;
|
||||
break;
|
||||
|
||||
case Common::DE_DEU:
|
||||
textId = 1748;
|
||||
break;
|
||||
|
||||
case Common::FR_FRA:
|
||||
textId = 1729;
|
||||
break;
|
||||
}
|
||||
|
||||
getText()->loadFont(getWorld()->graphicResourceIds[42]);
|
||||
for (int i = 0; i < 10; i++, textId++)
|
||||
getText()->draw(0, 99, kTextNormal, Common::Point(70 + 60 * (i & 1), 45 + 30 * i), 16, 590,
|
||||
getText()->get(MAKE_RESOURCE(kResourcePackText, textId)));
|
||||
|
||||
getText()->drawCentered(Common::Point(10, 375), 590, getText()->get(MAKE_RESOURCE(kResourcePackText, textId++)));
|
||||
getText()->drawCentered(Common::Point(10, 405), 590, getText()->get(MAKE_RESOURCE(kResourcePackText, textId)));
|
||||
|
||||
_textSurface.copyFrom(*getScreen()->getSurface());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PuzzleWritings::update(const AsylumEvent &) {
|
||||
// Adjust palette
|
||||
if (rnd(10) < 7) {
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[6]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[6]);
|
||||
} else {
|
||||
getScreen()->setPalette(getWorld()->graphicResourceIds[10]);
|
||||
getScreen()->setGammaLevel(getWorld()->graphicResourceIds[10]);
|
||||
}
|
||||
|
||||
// Compute frame index
|
||||
Common::Point mousePos = getCursor()->position();
|
||||
|
||||
if (mousePos.x > 50 && mousePos.x < 530 && mousePos.y > 20 && mousePos.y < 430) {
|
||||
if (_frameIndex < 26)
|
||||
++_frameIndex;
|
||||
} else {
|
||||
if (_frameIndex > 0)
|
||||
--_frameIndex;
|
||||
}
|
||||
|
||||
// Draw background
|
||||
getScreen()->clearGraphicsInQueue();
|
||||
getScreen()->fillRect(0, 0, 640, 480, 253);
|
||||
getScreen()->draw(getWorld()->graphicResourceIds[4], 0, Common::Point(0, 0), kDrawFlagNone, true);
|
||||
|
||||
if (_hasGlassMagnifier) {
|
||||
mousePos -= Common::Point(50, 50);
|
||||
Common::Rect eyeBall = Common::Rect(0, 0, 640, 480).findIntersectingRect(Common::Rect(mousePos.x + 20, mousePos.y + 20,
|
||||
mousePos.x + 100, mousePos.y + 100));
|
||||
Graphics::Surface subArea, *subArea1;
|
||||
subArea = _textSurface.getSubArea(eyeBall);
|
||||
subArea1 = subArea.scale(3 * eyeBall.width() / 4, 3 * eyeBall.height() / 4);
|
||||
eyeBall.left += 9;
|
||||
eyeBall.top += 9;
|
||||
|
||||
int16 dw, dh;
|
||||
dw = MAX(0, eyeBall.left + subArea1->w - 640);
|
||||
dh = MAX(0, eyeBall.top + subArea1->h - 480);
|
||||
getScreen()->copyToBackBuffer((byte *)subArea1->getPixels(), subArea1->pitch, eyeBall.left, eyeBall.top, subArea1->w - dw, subArea1->h - dh);
|
||||
|
||||
subArea1->free();
|
||||
delete subArea1;
|
||||
|
||||
getScreen()->addGraphicToQueueMasked(getWorld()->graphicResourceIds[9], 0, mousePos, getWorld()->graphicResourceIds[8], mousePos, kDrawFlagNone, 2);
|
||||
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[7], (uint32)_frameIndex, mousePos, kDrawFlagNone, 0, 1);
|
||||
}
|
||||
|
||||
getScreen()->drawGraphicsInQueue();
|
||||
getScreen()->copyBackBufferToScreen();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PuzzleWritings::exitPuzzle() {
|
||||
getCursor()->hide();
|
||||
getSharedData()->setFlag(kFlag1, true);
|
||||
getScreen()->stopPaletteFade(0, 0, 0);
|
||||
|
||||
_vm->switchEventHandler(getScene());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Asylum
|
||||
53
engines/asylum/puzzles/writings.h
Normal file
53
engines/asylum/puzzles/writings.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASYLUM_PUZZLES_WRITINGS_H
|
||||
#define ASYLUM_PUZZLES_WRITINGS_H
|
||||
|
||||
#include "asylum/puzzles/puzzle.h"
|
||||
#include "asylum/system/graphics.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
class AsylumEngine;
|
||||
|
||||
class PuzzleWritings : public Puzzle {
|
||||
public:
|
||||
PuzzleWritings(AsylumEngine *engine);
|
||||
~PuzzleWritings();
|
||||
|
||||
private:
|
||||
int32 _frameIndex;
|
||||
|
||||
bool _hasGlassMagnifier;
|
||||
Graphics::Surface _textSurface;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Handling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool init(const AsylumEvent &evt);
|
||||
bool update(const AsylumEvent &evt);
|
||||
bool exitPuzzle();
|
||||
};
|
||||
|
||||
} // End of namespace Asylum
|
||||
|
||||
#endif // ASYLUM_PUZZLES_WRITINGS_H
|
||||
Reference in New Issue
Block a user