/* 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 . * */ #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