diff options
Diffstat (limited to 'engines/neverhood/navigationscene.cpp')
-rw-r--r-- | engines/neverhood/navigationscene.cpp | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/engines/neverhood/navigationscene.cpp b/engines/neverhood/navigationscene.cpp new file mode 100644 index 0000000000..9752ee618c --- /dev/null +++ b/engines/neverhood/navigationscene.cpp @@ -0,0 +1,225 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "neverhood/navigationscene.h" +#include "neverhood/mouse.h" + +namespace Neverhood { + +NavigationScene::NavigationScene(NeverhoodEngine *vm, Module *parentModule, uint32 navigationListId, int navigationIndex, const byte *itemsTypes) + : Scene(vm, parentModule), _itemsTypes(itemsTypes), _navigationIndex(navigationIndex), _smackerDone(false), + _isWalkingForward(false), _isTurning(false), _smackerFileHash(0), _interactive(true), _leaveSceneAfter(false) { + + _navigationList = _vm->_staticData->getNavigationList(navigationListId); + + if (_navigationIndex < 0) { + _navigationIndex = (int)getGlobalVar(V_NAVIGATION_INDEX); + if (_navigationIndex >= (int)_navigationList->size()) + _navigationIndex = 0; + } + setGlobalVar(V_NAVIGATION_INDEX, _navigationIndex); + + SetUpdateHandler(&NavigationScene::update); + SetMessageHandler(&NavigationScene::handleMessage); + + _smackerPlayer = new SmackerPlayer(_vm, this, (*_navigationList)[_navigationIndex].fileHash, true, true); + addEntity(_smackerPlayer); + addSurface(_smackerPlayer->getSurface()); + + createMouseCursor(); + + _vm->_screen->clear(); + _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); + + sendMessage(_parentModule, 0x100A, _navigationIndex); + +} + +NavigationScene::~NavigationScene() { + _vm->_soundMan->setTwoSoundsPlayFlag(false); + _vm->_soundMan->setSoundThreePlayFlag(false); +} + +int NavigationScene::getNavigationAreaType() { + NPoint mousePos; + mousePos.x = _mouseCursor->getX(); + mousePos.y = _mouseCursor->getY(); + return sendPointMessage(_mouseCursor, 0x2064, mousePos); +} + +void NavigationScene::update() { + if (_smackerFileHash != 0) { + showMouse(false); + openSmacker(_smackerFileHash, false); + _vm->_screen->clear(); + _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); + _smackerDone = false; + /* + if (!_interactive) + _smackerDone = true; + */ + _smackerFileHash = 0; + } else if (_smackerDone) { + if (_leaveSceneAfter) { + _vm->_screen->setSmackerDecoder(NULL); + sendMessage(_parentModule, 0x1009, _navigationIndex); + } else { + const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex]; + createMouseCursor(); + showMouse(true); + _isTurning = false; + _isWalkingForward = false; + _interactive = true; + _vm->_soundMan->setTwoSoundsPlayFlag(false); + _vm->_soundMan->setSoundThreePlayFlag(false); + _smackerDone = false; + openSmacker(navigationItem.fileHash, true); + _vm->_screen->clear(); + _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); + sendMessage(_parentModule, 0x100A, _navigationIndex); + } + } + Scene::update(); +} + +void NavigationScene::openSmacker(uint32 fileHash, bool keepLastFrame) { + // The old Smacker surface is deleted when a new Smacker is opened. + removeSurface(_smackerPlayer->getSurface()); + _smackerPlayer->open(fileHash, keepLastFrame); + addSurface(_smackerPlayer->getSurface()); +} + +uint32 NavigationScene::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + switch (messageNum) { + case 0x0000: + if (_interactive) + sendMessage(_mouseCursor, 0x4002, param); + break; + case 0x0001: + if (_interactive) + handleNavigation(param.asPoint()); + break; + case 0x0009: + if (!_interactive) + _smackerDone = true; + break; + case 0x3002: + _smackerDone = true; + break; + } + return 0; +} + +void NavigationScene::createMouseCursor() { + + const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex]; + uint32 mouseCursorFileHash; + int areaType; + + if (_mouseCursor) { + deleteSprite((Sprite**)&_mouseCursor); + } + + mouseCursorFileHash = navigationItem.mouseCursorFileHash; + if (mouseCursorFileHash == 0) + mouseCursorFileHash = 0x63A40028; + + if (_itemsTypes) { + areaType = _itemsTypes[_navigationIndex]; + } else if (navigationItem.middleSmackerFileHash != 0 || navigationItem.middleFlag) { + areaType = 0; + } else { + areaType = 1; + } + + insertNavigationMouse(mouseCursorFileHash, areaType); + sendPointMessage(_mouseCursor, 0x4002, _vm->getMousePos()); + +} + +void NavigationScene::handleNavigation(const NPoint &mousePos) { + + const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex]; + bool oldIsWalkingForward = _isWalkingForward; + bool oldIsTurning = _isTurning; + uint32 direction = sendPointMessage(_mouseCursor, 0x2064, mousePos); + + switch (direction) { + case 0: + if (navigationItem.leftSmackerFileHash != 0) { + _smackerFileHash = navigationItem.leftSmackerFileHash; + _interactive = false; + _isWalkingForward = false; + _isTurning = true; + do { + _navigationIndex--; + if (_navigationIndex < 0) + _navigationIndex = _navigationList->size() - 1; + } while (!(*_navigationList)[_navigationIndex].interactive); + setGlobalVar(V_NAVIGATION_INDEX, _navigationIndex); + } else { + _vm->_screen->setSmackerDecoder(NULL); + sendMessage(_parentModule, 0x1009, _navigationIndex); + } + break; + case 1: + if (navigationItem.rightSmackerFileHash != 0) { + _smackerFileHash = navigationItem.rightSmackerFileHash; + _interactive = false; + _isWalkingForward = false; + _isTurning = true; + do { + _navigationIndex++; + if (_navigationIndex >= (int)_navigationList->size()) + _navigationIndex = 0; + } while (!(*_navigationList)[_navigationIndex].interactive); + setGlobalVar(V_NAVIGATION_INDEX, _navigationIndex); + } else { + _vm->_screen->setSmackerDecoder(NULL); + sendMessage(_parentModule, 0x1009, _navigationIndex); + } + break; + case 2: + case 3: + case 4: + if (navigationItem.middleFlag) { + _vm->_screen->setSmackerDecoder(NULL); + sendMessage(_parentModule, 0x1009, _navigationIndex); + } else if (navigationItem.middleSmackerFileHash != 0) { + _smackerFileHash = navigationItem.middleSmackerFileHash; + _interactive = false; + _isWalkingForward = true; + _isTurning = false; + _leaveSceneAfter = true; + } + break; + } + + if (oldIsTurning != _isTurning) + _vm->_soundMan->setSoundThreePlayFlag(_isTurning); + + if (oldIsWalkingForward != _isWalkingForward) + _vm->_soundMan->setTwoSoundsPlayFlag(_isWalkingForward); + +} + +} // End of namespace Neverhood |