Initial commit
This commit is contained in:
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
|
||||
Reference in New Issue
Block a user