From 78e0d6a3f1bd0ee050e5cd0ca3599f86dcf25813 Mon Sep 17 00:00:00 2001 From: johndoe123 Date: Sun, 5 May 2013 00:12:33 +0200 Subject: NEVERHOOD: Move module files to own subdirectory --- engines/neverhood/detection.cpp | 1 - engines/neverhood/gamemodule.cpp | 42 +- engines/neverhood/module.cpp | 4 +- engines/neverhood/module.mk | 42 +- engines/neverhood/module1000.cpp | 1699 ---------------- engines/neverhood/module1000.h | 300 --- engines/neverhood/module1100.cpp | 707 ------- engines/neverhood/module1100.h | 130 -- engines/neverhood/module1200.cpp | 1102 ---------- engines/neverhood/module1200.h | 216 -- engines/neverhood/module1300.cpp | 1835 ----------------- engines/neverhood/module1300.h | 295 --- engines/neverhood/module1400.cpp | 1621 --------------- engines/neverhood/module1400.h | 281 --- engines/neverhood/module1500.cpp | 134 -- engines/neverhood/module1500.h | 58 - engines/neverhood/module1600.cpp | 1412 ------------- engines/neverhood/module1600.h | 183 -- engines/neverhood/module1700.cpp | 279 --- engines/neverhood/module1700.h | 72 - engines/neverhood/module1800.cpp | 181 -- engines/neverhood/module1800.h | 46 - engines/neverhood/module1900.cpp | 650 ------ engines/neverhood/module1900.h | 143 -- engines/neverhood/module2000.cpp | 160 -- engines/neverhood/module2000.h | 55 - engines/neverhood/module2100.cpp | 336 ---- engines/neverhood/module2100.h | 92 - engines/neverhood/module2200.cpp | 2564 ------------------------ engines/neverhood/module2200.h | 375 ---- engines/neverhood/module2300.cpp | 186 -- engines/neverhood/module2300.h | 48 - engines/neverhood/module2400.cpp | 992 --------- engines/neverhood/module2400.h | 182 -- engines/neverhood/module2500.cpp | 546 ----- engines/neverhood/module2500.h | 101 - engines/neverhood/module2600.cpp | 348 ---- engines/neverhood/module2600.h | 74 - engines/neverhood/module2700.cpp | 1211 ----------- engines/neverhood/module2700.h | 182 -- engines/neverhood/module2800.cpp | 3205 ------------------------------ engines/neverhood/module2800.h | 505 ----- engines/neverhood/module2900.cpp | 439 ---- engines/neverhood/module2900.h | 102 - engines/neverhood/module3000.cpp | 1548 --------------- engines/neverhood/module3000.h | 255 --- engines/neverhood/modules/module1000.cpp | 1699 ++++++++++++++++ engines/neverhood/modules/module1000.h | 300 +++ engines/neverhood/modules/module1100.cpp | 707 +++++++ engines/neverhood/modules/module1100.h | 130 ++ engines/neverhood/modules/module1200.cpp | 1102 ++++++++++ engines/neverhood/modules/module1200.h | 216 ++ engines/neverhood/modules/module1300.cpp | 1835 +++++++++++++++++ engines/neverhood/modules/module1300.h | 295 +++ engines/neverhood/modules/module1400.cpp | 1621 +++++++++++++++ engines/neverhood/modules/module1400.h | 281 +++ engines/neverhood/modules/module1500.cpp | 134 ++ engines/neverhood/modules/module1500.h | 58 + engines/neverhood/modules/module1600.cpp | 1412 +++++++++++++ engines/neverhood/modules/module1600.h | 183 ++ engines/neverhood/modules/module1700.cpp | 279 +++ engines/neverhood/modules/module1700.h | 72 + engines/neverhood/modules/module1800.cpp | 181 ++ engines/neverhood/modules/module1800.h | 46 + engines/neverhood/modules/module1900.cpp | 650 ++++++ engines/neverhood/modules/module1900.h | 143 ++ engines/neverhood/modules/module2000.cpp | 160 ++ engines/neverhood/modules/module2000.h | 55 + engines/neverhood/modules/module2100.cpp | 336 ++++ engines/neverhood/modules/module2100.h | 92 + engines/neverhood/modules/module2200.cpp | 2564 ++++++++++++++++++++++++ engines/neverhood/modules/module2200.h | 375 ++++ engines/neverhood/modules/module2300.cpp | 186 ++ engines/neverhood/modules/module2300.h | 48 + engines/neverhood/modules/module2400.cpp | 992 +++++++++ engines/neverhood/modules/module2400.h | 182 ++ engines/neverhood/modules/module2500.cpp | 546 +++++ engines/neverhood/modules/module2500.h | 101 + engines/neverhood/modules/module2600.cpp | 348 ++++ engines/neverhood/modules/module2600.h | 74 + engines/neverhood/modules/module2700.cpp | 1211 +++++++++++ engines/neverhood/modules/module2700.h | 182 ++ engines/neverhood/modules/module2800.cpp | 3205 ++++++++++++++++++++++++++++++ engines/neverhood/modules/module2800.h | 505 +++++ engines/neverhood/modules/module2900.cpp | 439 ++++ engines/neverhood/modules/module2900.h | 102 + engines/neverhood/modules/module3000.cpp | 1548 +++++++++++++++ engines/neverhood/modules/module3000.h | 255 +++ 88 files changed, 24894 insertions(+), 24895 deletions(-) delete mode 100644 engines/neverhood/module1000.cpp delete mode 100644 engines/neverhood/module1000.h delete mode 100644 engines/neverhood/module1100.cpp delete mode 100644 engines/neverhood/module1100.h delete mode 100644 engines/neverhood/module1200.cpp delete mode 100644 engines/neverhood/module1200.h delete mode 100644 engines/neverhood/module1300.cpp delete mode 100644 engines/neverhood/module1300.h delete mode 100644 engines/neverhood/module1400.cpp delete mode 100644 engines/neverhood/module1400.h delete mode 100644 engines/neverhood/module1500.cpp delete mode 100644 engines/neverhood/module1500.h delete mode 100644 engines/neverhood/module1600.cpp delete mode 100644 engines/neverhood/module1600.h delete mode 100644 engines/neverhood/module1700.cpp delete mode 100644 engines/neverhood/module1700.h delete mode 100644 engines/neverhood/module1800.cpp delete mode 100644 engines/neverhood/module1800.h delete mode 100644 engines/neverhood/module1900.cpp delete mode 100644 engines/neverhood/module1900.h delete mode 100644 engines/neverhood/module2000.cpp delete mode 100644 engines/neverhood/module2000.h delete mode 100644 engines/neverhood/module2100.cpp delete mode 100644 engines/neverhood/module2100.h delete mode 100644 engines/neverhood/module2200.cpp delete mode 100644 engines/neverhood/module2200.h delete mode 100644 engines/neverhood/module2300.cpp delete mode 100644 engines/neverhood/module2300.h delete mode 100644 engines/neverhood/module2400.cpp delete mode 100644 engines/neverhood/module2400.h delete mode 100644 engines/neverhood/module2500.cpp delete mode 100644 engines/neverhood/module2500.h delete mode 100644 engines/neverhood/module2600.cpp delete mode 100644 engines/neverhood/module2600.h delete mode 100644 engines/neverhood/module2700.cpp delete mode 100644 engines/neverhood/module2700.h delete mode 100644 engines/neverhood/module2800.cpp delete mode 100644 engines/neverhood/module2800.h delete mode 100644 engines/neverhood/module2900.cpp delete mode 100644 engines/neverhood/module2900.h delete mode 100644 engines/neverhood/module3000.cpp delete mode 100644 engines/neverhood/module3000.h create mode 100644 engines/neverhood/modules/module1000.cpp create mode 100644 engines/neverhood/modules/module1000.h create mode 100644 engines/neverhood/modules/module1100.cpp create mode 100644 engines/neverhood/modules/module1100.h create mode 100644 engines/neverhood/modules/module1200.cpp create mode 100644 engines/neverhood/modules/module1200.h create mode 100644 engines/neverhood/modules/module1300.cpp create mode 100644 engines/neverhood/modules/module1300.h create mode 100644 engines/neverhood/modules/module1400.cpp create mode 100644 engines/neverhood/modules/module1400.h create mode 100644 engines/neverhood/modules/module1500.cpp create mode 100644 engines/neverhood/modules/module1500.h create mode 100644 engines/neverhood/modules/module1600.cpp create mode 100644 engines/neverhood/modules/module1600.h create mode 100644 engines/neverhood/modules/module1700.cpp create mode 100644 engines/neverhood/modules/module1700.h create mode 100644 engines/neverhood/modules/module1800.cpp create mode 100644 engines/neverhood/modules/module1800.h create mode 100644 engines/neverhood/modules/module1900.cpp create mode 100644 engines/neverhood/modules/module1900.h create mode 100644 engines/neverhood/modules/module2000.cpp create mode 100644 engines/neverhood/modules/module2000.h create mode 100644 engines/neverhood/modules/module2100.cpp create mode 100644 engines/neverhood/modules/module2100.h create mode 100644 engines/neverhood/modules/module2200.cpp create mode 100644 engines/neverhood/modules/module2200.h create mode 100644 engines/neverhood/modules/module2300.cpp create mode 100644 engines/neverhood/modules/module2300.h create mode 100644 engines/neverhood/modules/module2400.cpp create mode 100644 engines/neverhood/modules/module2400.h create mode 100644 engines/neverhood/modules/module2500.cpp create mode 100644 engines/neverhood/modules/module2500.h create mode 100644 engines/neverhood/modules/module2600.cpp create mode 100644 engines/neverhood/modules/module2600.h create mode 100644 engines/neverhood/modules/module2700.cpp create mode 100644 engines/neverhood/modules/module2700.h create mode 100644 engines/neverhood/modules/module2800.cpp create mode 100644 engines/neverhood/modules/module2800.h create mode 100644 engines/neverhood/modules/module2900.cpp create mode 100644 engines/neverhood/modules/module2900.h create mode 100644 engines/neverhood/modules/module3000.cpp create mode 100644 engines/neverhood/modules/module3000.h diff --git a/engines/neverhood/detection.cpp b/engines/neverhood/detection.cpp index e5bfd292ad..4f70c63299 100644 --- a/engines/neverhood/detection.cpp +++ b/engines/neverhood/detection.cpp @@ -235,4 +235,3 @@ SaveStateDescriptor NeverhoodMetaEngine::querySaveMetaInfos(const char *target, #else REGISTER_PLUGIN_STATIC(NEVERHOOD, PLUGIN_TYPE_ENGINE, NeverhoodMetaEngine); #endif - diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp index 99aea5d938..49682b0d29 100644 --- a/engines/neverhood/gamemodule.cpp +++ b/engines/neverhood/gamemodule.cpp @@ -24,27 +24,27 @@ #include "neverhood/graphics.h" #include "neverhood/menumodule.h" -#include "neverhood/module1000.h" -#include "neverhood/module1100.h" -#include "neverhood/module1200.h" -#include "neverhood/module1300.h" -#include "neverhood/module1400.h" -#include "neverhood/module1500.h" -#include "neverhood/module1600.h" -#include "neverhood/module1700.h" -#include "neverhood/module1800.h" -#include "neverhood/module1900.h" -#include "neverhood/module2000.h" -#include "neverhood/module2100.h" -#include "neverhood/module2200.h" -#include "neverhood/module2300.h" -#include "neverhood/module2400.h" -#include "neverhood/module2500.h" -#include "neverhood/module2600.h" -#include "neverhood/module2700.h" -#include "neverhood/module2800.h" -#include "neverhood/module2900.h" -#include "neverhood/module3000.h" +#include "neverhood/modules/module1000.h" +#include "neverhood/modules/module1100.h" +#include "neverhood/modules/module1200.h" +#include "neverhood/modules/module1300.h" +#include "neverhood/modules/module1400.h" +#include "neverhood/modules/module1500.h" +#include "neverhood/modules/module1600.h" +#include "neverhood/modules/module1700.h" +#include "neverhood/modules/module1800.h" +#include "neverhood/modules/module1900.h" +#include "neverhood/modules/module2000.h" +#include "neverhood/modules/module2100.h" +#include "neverhood/modules/module2200.h" +#include "neverhood/modules/module2300.h" +#include "neverhood/modules/module2400.h" +#include "neverhood/modules/module2500.h" +#include "neverhood/modules/module2600.h" +#include "neverhood/modules/module2700.h" +#include "neverhood/modules/module2800.h" +#include "neverhood/modules/module2900.h" +#include "neverhood/modules/module3000.h" namespace Neverhood { diff --git a/engines/neverhood/module.cpp b/engines/neverhood/module.cpp index 93b4134f6b..e384b5a4d2 100644 --- a/engines/neverhood/module.cpp +++ b/engines/neverhood/module.cpp @@ -23,8 +23,8 @@ #include "neverhood/module.h" #include "neverhood/navigationscene.h" #include "neverhood/smackerscene.h" -#include "neverhood/module1000.h" -#include "neverhood/module1500.h" +#include "neverhood/modules/module1000.h" +#include "neverhood/modules/module1500.h" namespace Neverhood { diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk index 59effb593c..c7bfbb6460 100644 --- a/engines/neverhood/module.mk +++ b/engines/neverhood/module.mk @@ -13,27 +13,27 @@ MODULE_OBJS = \ menumodule.o \ microtiles.o \ module.o \ - module1000.o \ - module1100.o \ - module1200.o \ - module1300.o \ - module1400.o \ - module1500.o \ - module1600.o \ - module1700.o \ - module1800.o \ - module1900.o \ - module2000.o \ - module2100.o \ - module2200.o \ - module2300.o \ - module2400.o \ - module2500.o \ - module2600.o \ - module2700.o \ - module2800.o \ - module2900.o \ - module3000.o \ + modules/module1000.o \ + modules/module1100.o \ + modules/module1200.o \ + modules/module1300.o \ + modules/module1400.o \ + modules/module1500.o \ + modules/module1600.o \ + modules/module1700.o \ + modules/module1800.o \ + modules/module1900.o \ + modules/module2000.o \ + modules/module2100.o \ + modules/module2200.o \ + modules/module2300.o \ + modules/module2400.o \ + modules/module2500.o \ + modules/module2600.o \ + modules/module2700.o \ + modules/module2800.o \ + modules/module2900.o \ + modules/module3000.o \ mouse.o \ navigationscene.o \ neverhood.o \ diff --git a/engines/neverhood/module1000.cpp b/engines/neverhood/module1000.cpp deleted file mode 100644 index 096072b7b6..0000000000 --- a/engines/neverhood/module1000.cpp +++ /dev/null @@ -1,1699 +0,0 @@ -/* 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/module1000.h" - -namespace Neverhood { - -Module1000::Module1000(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - debug("Create Module1000(%d)", which); - - _musicFileHash = getGlobalVar(V_ENTRANCE_OPEN) ? 0x81106480 : 0x00103144; - - _vm->_soundMan->addMusic(0x03294419, 0x061880C6); - _vm->_soundMan->addMusic(0x03294419, _musicFileHash); - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else if (which == 0) - createScene(0, 0); - else if (which == 1) - createScene(1, 1); - -} - -Module1000::~Module1000() { - _vm->_soundMan->deleteMusicGroup(0x03294419); -} - -void Module1000::createScene(int sceneNum, int which) { - debug("Module1000::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _vm->_soundMan->startMusic(0x061880C6, 0, 0); - _childObject = new Scene1001(_vm, this, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - _vm->_soundMan->startMusic(0x061880C6, 0, 0); - _childObject = new Scene1002(_vm, this, which); - break; - case 2: - _vm->gameState().sceneNum = 2; - _vm->_soundMan->startMusic(0x061880C6, 0, 0); - createStaticScene(0xC084110C, 0x41108C00); - break; - case 3: - _vm->gameState().sceneNum = 3; - _vm->_soundMan->stopMusic(0x061880C6, 0, 2); - _childObject = new Scene1004(_vm, this, which); - break; - case 4: - _vm->gameState().sceneNum = 4; - _vm->_soundMan->stopMusic(0x061880C6, 0, 0); - _vm->_soundMan->startMusic(_musicFileHash, 0, 0); - _childObject = new Scene1005(_vm, this, which); - break; - } - SetUpdateHandler(&Module1000::updateScene); - _childObject->handleUpdate(); -} - -void Module1000::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 2) - createScene(2, 0); - else - createScene(1, 0); - break; - case 1: - if (_moduleResult == 1) - leaveModule(0); - else if (_moduleResult == 2) { - if (_vm->isDemo()) - // Demo version returns to the same scene - createScene(1, 2); - else - createScene(3, 0); - } else - createScene(0, 1); - break; - case 2: - createScene(0, 2); - break; - case 3: - if (_moduleResult == 1) - createScene(4, 0); - else - createScene(1, 2); - break; - case 4: - _vm->_soundMan->stopMusic(_musicFileHash, 0, 1); - createScene(3, 1); - break; - } - } -} - -// Scene1001 - -AsScene1001Door::AsScene1001Door(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100) { - - createSurface(800, 137, 242); - _x = 726; - _y = 440; - stShowIdleDoor(); - loadSound(1, 0xED403E03); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1001Door::handleMessage); -} - -uint32 AsScene1001Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - hammerHitsDoor(); - break; - case 0x3002: - gotoNextState(); - break; - } - return 0; -} - -void AsScene1001Door::hammerHitsDoor() { - switch (getGlobalVar(V_DOOR_STATUS)) { - case 0: - case 1: - playSound(0, 0x65482F03); - startAnimation(0x624C0498, 1, 3); - NextState(&AsScene1001Door::stShowIdleDoor); - break; - case 2: - playSound(1); - startAnimation(0x624C0498, 6, 6); - NextState(&AsScene1001Door::stBustedDoorMove); - break; - default: - // Nothing - break; - } - incGlobalVar(V_DOOR_STATUS, 1); -} - -void AsScene1001Door::stShowIdleDoor() { - switch (getGlobalVar(V_DOOR_STATUS)) { - case 1: - startAnimation(0x624C0498, 4, -1); - _newStickFrameIndex = 4; - break; - case 2: - startAnimation(0x624C0498, 1, -1); - _newStickFrameIndex = 1; - break; - case 3: - stopAnimation(); - setVisible(false); - break; - default: - startAnimation(0x624C0498, 0, -1); - _newStickFrameIndex = 0; - break; - } -} - -void AsScene1001Door::stBustedDoorMove() { - setGlobalVar(V_DOOR_BUSTED, 1); - startAnimation(0x624C0498, 6, 6); - NextState(&AsScene1001Door::stBustedDoorGone); - _x = 30; -} - -void AsScene1001Door::stBustedDoorGone() { - playSound(0); - stopAnimation(); - setVisible(false); -} - -AsScene1001Hammer::AsScene1001Hammer(NeverhoodEngine *vm, Sprite *asDoor) - : AnimatedSprite(vm, 1100), _asDoor(asDoor) { - - _x = 547; - _y = 206; - createSurface(900, 177, 192); - startAnimation(0x022C90D4, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1001Hammer::handleMessage); -} - -uint32 AsScene1001Hammer::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x00352100) - sendMessage(_asDoor, 0x2000, 0); - else if (param.asInteger() == 0x0A1A0109) - playSound(0, 0x66410886); - break; - case 0x2000: - startAnimation(0x022C90D4, 1, -1); - playSound(0, 0xE741020A); - _newStickFrameIndex = STICK_LAST_FRAME; - break; - } - return 0; -} - -AsScene1001Window::AsScene1001Window(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1200) { - - _x = 320; - _y = 240; - createSurface(100, 66, 129); - startAnimation(0xC68C2299, 0, -1); - _newStickFrameIndex = 0; - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1001Window::handleMessage); -} - -uint32 AsScene1001Window::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x0E0A1410) - playSound(0, 0x60803F10); - break; - case 0x2001: - startAnimation(0xC68C2299, 0, -1); - break; - case 0x3002: - SetMessageHandler(NULL); - setGlobalVar(V_WINDOW_OPEN, 1); - setVisible(false); - break; - } - return 0; -} - -AsScene1001Lever::AsScene1001Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int deltaXType) - : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - - createSurface(1010, 71, 73); - setDoDeltaX(deltaXType); - startAnimation(0x04A98C36, 0, -1); - _newStickFrameIndex = 0; - _x = x; - _y = y; - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1001Lever::handleMessage); -} - -uint32 AsScene1001Lever::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x00C0C444) - sendMessage(_parentScene, 0x480F, 0); - else if (param.asInteger() == 0xC41A02C0) - playSound(0, 0x40581882); - break; - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x3002: - startAnimation(0x04A98C36, 0, -1); - _newStickFrameIndex = 0; - break; - case 0x480F: - startAnimation(0x04A98C36, 0, -1); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -SsCommonButtonSprite::SsCommonButtonSprite(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, int surfacePriority, uint32 soundFileHash) - : StaticSprite(vm, fileHash, surfacePriority), _parentScene(parentScene), _countdown(0) { - - _priority = 1100; - _soundFileHash = soundFileHash ? soundFileHash : 0x44141000; - setVisible(false); - SetUpdateHandler(&SsCommonButtonSprite::update); - SetMessageHandler(&SsCommonButtonSprite::handleMessage); -} - -void SsCommonButtonSprite::update() { - if (_countdown != 0 && (--_countdown) == 0) - setVisible(false); -} - -uint32 SsCommonButtonSprite::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x480B: - sendMessage(_parentScene, 0x480B, 0); - setVisible(true); - _countdown = 8; - playSound(0, _soundFileHash); - break; - } - return messageResult; -} - -Scene1001::Scene1001(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _asDoor(NULL), _asWindow(NULL) { - - Sprite *tempSprite; - - SetMessageHandler(&Scene1001::handleMessage); - - setHitRects(0x004B4860); - setBackground(0x4086520E); - setPalette(0x4086520E); - insertScreenMouse(0x6520A400); - - if (which < 0) { - // Restoring game - setRectList(0x004B49F0); - insertKlaymen(200, 433); - setMessageList(0x004B4888); - } else if (which == 1) { - // Klaymen entering from the right - setRectList(0x004B49F0); - insertKlaymen(640, 433); - setMessageList(0x004B4898); - } else if (which == 2) { - // Klaymen returning from looking through the window - setRectList(0x004B49F0); - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { - insertKlaymen(390, 433); - _klaymen->setDoDeltaX(1); - } else { - insertKlaymen(300, 433); - } - setMessageList(0x004B4970); - } else { - // Klaymen sleeping - setRectList(0x004B4A00); - insertKlaymen(200, 433); - setMessageList(0x004B4890); - } - - tempSprite = insertStaticSprite(0x2080A3A8, 1300); - - _klaymen->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480); - - if (!getGlobalVar(V_DOOR_BUSTED)) { - _asDoor = insertSprite(); - _asDoor->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480); - } - - _asLever = insertSprite(this, 150, 433, 1); - - insertStaticSprite(0x809861A6, 950); - insertStaticSprite(0x89C03848, 1100); - - _ssButton = insertSprite(this, 0x15288120, 100, 0); - - if (!getGlobalVar(V_WINDOW_OPEN)) { - tempSprite = insertStaticSprite(0x8C066150, 200); - _asWindow = insertSprite(); - _asWindow->setClipRect(tempSprite->getDrawRect()); - } - - _asHammer = insertSprite(_asDoor); - -} - -Scene1001::~Scene1001() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX()); -} - -uint32 Scene1001::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = 0; - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x00342624) { - sendEntityMessage(_klaymen, 0x1014, _asLever); - setMessageList2(0x004B4910); - messageResult = 1; - } else if (param.asInteger() == 0x21E64A00) { - if (getGlobalVar(V_DOOR_BUSTED)) { - setMessageList(0x004B48A8); - } else { - setMessageList(0x004B48C8); - } - messageResult = 1; - } else if (param.asInteger() == 0x040424D0) { - sendEntityMessage(_klaymen, 0x1014, _ssButton); - } else if (param.asInteger() == 0x80006358) { - if (getGlobalVar(V_WINDOW_OPEN)) { - setMessageList(0x004B4938); - } else { - setMessageList(0x004B4960); - } - } - break; - case 0x2002: - setRectList(0x004B49F0); - break; - case 0x480B: - sendMessage(_asWindow, 0x2001, 0); - break; - case 0x480F: - sendMessage(_asHammer, 0x2000, 0); - break; - } - return messageResult; -} - -// Scene1002 - -AsScene1002Ring::AsScene1002Ring(NeverhoodEngine *vm, Scene *parentScene, bool isSpecial, int16 x, int16 y, int16 clipY1, bool isRingLow) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _isSpecial(isSpecial) { - - SetUpdateHandler(&AsScene1002Ring::update); - - if (_isSpecial) { - createSurface(990, 68, 314); - if (isRingLow) { - startAnimation(0x04103090, 0, -1); - SetMessageHandler(&AsScene1002Ring::hmRingHangingLow); - } else { - startAnimation(0xA85C4011, _vm->_rnd->getRandomNumber(15), -1); - SetMessageHandler(&AsScene1002Ring::hmRingIdle); - } - } else { - createSurface(990, 68, 138); - startAnimation(0xA85C4011, _vm->_rnd->getRandomNumber(15), -1); - SetMessageHandler(&AsScene1002Ring::hmRingIdle); - } - - setClipRect(0, clipY1, 640, 480); - - _x = x; - _y = y; - - setDoDeltaX(_vm->_rnd->getRandomNumber(1)); - -} - -void AsScene1002Ring::update() { - updateAnim(); - updatePosition(); -} - -uint32 AsScene1002Ring::hmRingIdle(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4806: - setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0); - sendMessage(_parentScene, 0x4806, 0); - SetMessageHandler(&AsScene1002Ring::hmRingPulled1); - startAnimation(_isSpecial ? 0x87502558 : 0x80DD4010, 0, -1); - break; - case 0x480F: - setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0); - sendMessage(_parentScene, 0x480F, 0); - SetMessageHandler(&AsScene1002Ring::hmRingPulled2); - startAnimation(0x861A2020, 0, -1); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -uint32 AsScene1002Ring::hmRingPulled1(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - startAnimation(_isSpecial ? 0x78D0A812 : 0xB85D2A10, 0, -1); - SetMessageHandler(&AsScene1002Ring::hmRingHangingLow); - break; - case 0x4807: - sendMessage(_parentScene, 0x4807, 0); - setDoDeltaX(_vm->_rnd->getRandomNumber(1)); - startAnimation(0x8258A030, 0, -1); - SetMessageHandler(&AsScene1002Ring::hmRingReleased); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -uint32 AsScene1002Ring::hmRingPulled2(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - startAnimation(0x04103090, 0, -1); - SetMessageHandler(&AsScene1002Ring::hmRingHangingLow); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -uint32 AsScene1002Ring::hmRingHangingLow(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4807: - sendMessage(_parentScene, 0x4807, 0); - setDoDeltaX(_vm->_rnd->getRandomNumber(1)); - startAnimation(0x8258A030, 0, -1); - SetMessageHandler(&AsScene1002Ring::hmRingReleased); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -uint32 AsScene1002Ring::hmRingReleased(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = hmRingIdle(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x05410F72) - playSound(0, 0x21EE40A9); - break; - case 0x3002: - startAnimation(0xA85C4011, 0, -1); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -AsScene1002Door::AsScene1002Door(NeverhoodEngine *vm, NRect &clipRect) - : StaticSprite(vm, 1200) { - - loadSprite(0x1052370F, kSLFDefDrawOffset | kSLFSetPosition, 800, 526, getGlobalVar(V_FLYTRAP_RING_DOOR) ? 49 : 239); - setClipRect(clipRect); - SetUpdateHandler(&AsScene1002Door::update); - SetMessageHandler(&AsScene1002Door::handleMessage); - SetSpriteUpdate(NULL); -} - -void AsScene1002Door::update() { - handleSpriteUpdate(); - updatePosition(); -} - -uint32 AsScene1002Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4808: - setGlobalVar(V_FLYTRAP_RING_DOOR, 1); - SetSpriteUpdate(&AsScene1002Door::suOpenDoor); - break; - case 0x4809: - setGlobalVar(V_FLYTRAP_RING_DOOR, 0); - SetSpriteUpdate(&AsScene1002Door::suCloseDoor); - break; - } - return messageResult; -} - -void AsScene1002Door::suOpenDoor() { - if (_y > 49) { - _y -= 8; - if (_y < 49) { - SetSpriteUpdate(NULL); - _y = 49; - } - _needRefresh = true; - } -} - -void AsScene1002Door::suCloseDoor() { - if (_y < 239) { - _y += 8; - if (_y > 239) { - SetSpriteUpdate(NULL); - _y = 239; - } - _needRefresh = true; - } -} - -AsScene1002BoxingGloveHitEffect::AsScene1002BoxingGloveHitEffect(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1400) { - - createSurface(1025, 88, 165); - setVisible(false); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1002BoxingGloveHitEffect::handleMessage); -} - -uint32 AsScene1002BoxingGloveHitEffect::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2004: - _x = ((Sprite*)sender)->getX() - 98; - _y = ((Sprite*)sender)->getY() - 111; - startAnimation(0x0422255A, 0, -1); - setVisible(true); - break; - case 0x3002: - stopAnimation(); - setVisible(false); - break; - } - return messageResult; -} - -AsScene1002DoorSpy::AsScene1002DoorSpy(NeverhoodEngine *vm, NRect &clipRect, Scene *parentScene, Sprite *asDoor, Sprite *asScene1002BoxingGloveHitEffect) - : AnimatedSprite(vm, 1300), _clipRect(clipRect), _parentScene(parentScene), _asDoor(asDoor), _asBoxingGloveHitEffect(asScene1002BoxingGloveHitEffect) { - - createSurface(800, 136, 147); - setClipRect(clipRect); - suDoorSpy(); - loadSound(0, 0xC0C40298); - startAnimation(0x586C1D48, 0, 0); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1002DoorSpy::handleMessage); - SetSpriteUpdate(&AsScene1002DoorSpy::suDoorSpy); -} - -uint32 AsScene1002DoorSpy::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0xA61CA1C2) - sendMessage(_asBoxingGloveHitEffect, 0x2004, 0); - else if (param.asInteger() == 0x14CE0620) - playSound(0); - break; - case 0x2003: - stDoorSpyBoxingGlove(); - break; - } - return messageResult; -} - -uint32 AsScene1002DoorSpy::hmDoorSpyAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1002DoorSpy::suDoorSpy() { - _x = _asDoor->getX() + 34; - _y = _asDoor->getY() + 175; -} - -void AsScene1002DoorSpy::stDoorSpyIdle() { - setClipRect(_clipRect); - _parentScene->setSurfacePriority(getSurface(), 800); - startAnimation(0x586C1D48, 0, 0); - SetMessageHandler(&AsScene1002DoorSpy::handleMessage); -} - -void AsScene1002DoorSpy::stDoorSpyBoxingGlove() { - setClipRect(0, 0, 640, 480); - _parentScene->setSurfacePriority(getSurface(), 1200); - startAnimation(0x586C1D48, 1, -1); - SetMessageHandler(&AsScene1002DoorSpy::hmDoorSpyAnimation); - NextState(&AsScene1002DoorSpy::stDoorSpyIdle); -} - -SsCommonPressButton::SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash) - : StaticSprite(vm, 1100), _parentScene(parentScene), _status(0) { - - _soundFileHash = soundFileHash != 0 ? soundFileHash : 0x44141000; - _fileHashes[0] = fileHash1; - _fileHashes[1] = fileHash2; - createSurface(surfacePriority, 40, 40); - loadSprite(fileHash1, kSLFDefDrawOffset | kSLFDefPosition); - setVisible(false); - SetUpdateHandler(&SsCommonPressButton::update); - SetMessageHandler(&SsCommonPressButton::handleMessage); -} - -void SsCommonPressButton::setFileHashes(uint32 fileHash1, uint32 fileHash2) { - _fileHashes[0] = fileHash1; - _fileHashes[1] = fileHash2; - loadSprite(_status == 2 ? fileHash2 : fileHash1, kSLFDefDrawOffset | kSLFDefPosition); -} - -void SsCommonPressButton::update() { - if (_countdown != 0 && (--_countdown) == 0) { - if (_status == 1) { - _status = 2; - loadSprite(_fileHashes[1], kSLFDefDrawOffset | kSLFDefPosition); - _countdown = 4; - } else if (_status == 2) { - _status = 3; - loadSprite(_fileHashes[0], kSLFDefDrawOffset | kSLFDefPosition); - _countdown = 4; - } else if (_status == 3) { - _status = 0; - setVisible(false); - } - } -} - -uint32 SsCommonPressButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x480B: - sendMessage(_parentScene, 0x480B, 0); - _status = 1; - _countdown = 4; - setVisible(true); - playSound(0, _soundFileHash); - break; - } - return messageResult; -} - -AsScene1002VenusFlyTrap::AsScene1002VenusFlyTrap(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, bool isSecond) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _klaymen(klaymen), _isSecond(isSecond), _countdown(0) { - - createSurface(995, 175, 195); - if (!_isSecond) { - if (getGlobalVar(V_FLYTRAP_RING_DOOR)) { - setDoDeltaX(1); - _x = 366; - _y = 435; - stRingGrabbed(); - } else { - _x = 174 + getGlobalVar(V_FLYTRAP_POSITION_1) * 32; - _y = 435; - stIdle(); - } - } else { - _x = 186 + getGlobalVar(V_FLYTRAP_POSITION_2) * 32; - _y = 364; - if (getGlobalVar(V_FLYTRAP_RING_BRIDGE) || getGlobalVar(V_FLYTRAP_RING_FENCE)) { - stRingGrabbed(); - } else { - stIdle(); - } - } - _flags = 4; - SetUpdateHandler(&AsScene1002VenusFlyTrap::update); - SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage); - SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); -} - -void AsScene1002VenusFlyTrap::update() { - if (_countdown != 0 && (--_countdown == 0)) - gotoNextState(); - AnimatedSprite::update(); -} - -void AsScene1002VenusFlyTrap::upIdle() { - if (_countdown == 0 && _klaymen->getX() - 20 > _x) - setDoDeltaX(1); - else if (_klaymen->getX() + 20 < _x) - setDoDeltaX(0); - update(); -} - -uint32 AsScene1002VenusFlyTrap::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x000890C4) - playSound(0, 0xC21190D8); - else if (param.asInteger() == 0x522200A0) - playSound(0, 0x931080C8); - break; - case 0x1011: - if (_isSecond) { - if (_x >= 154 && _x <= 346) { - sendMessage(_parentScene, 0x2000, 0); - messageResult = 1; - } - } else { - if (_x >= 174 && _x <= 430) { - sendMessage(_parentScene, 0x2000, 0); - messageResult = 1; - } - } - break; - case 0x480B: - setDoDeltaX(param.asInteger() != 0 ? 1 : 0); - if (!_isSecond) { - if (getGlobalVar(V_FLYTRAP_RING_DOOR)) - stRelease(); - else - stWalk(); - } else { - if (getGlobalVar(V_FLYTRAP_RING_BRIDGE) || getGlobalVar(V_FLYTRAP_RING_FENCE)) - stRelease(); - else - stWalk(); - } - break; - case 0x480C: - if (_isSecond) { - if (_x >= 154 && _x <= 346) - messageResult = 1; - else - messageResult = 0; - } else { - if (_x >= 174 && _x <= 430) - messageResult = 1; - else - messageResult = 0; - } - break; - case 0x480E: - if (param.asInteger() == 1) - stGrabRing(); - break; - case 0x4810: - swallowKlaymen(); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 995); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1015); - break; - } - return messageResult; -} - -uint32 AsScene1002VenusFlyTrap::hmAnimationSimple(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -uint32 AsScene1002VenusFlyTrap::hmAnimationExt(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x000890C4) - playSound(0, 0xC21190D8); - else if (param.asInteger() == 0x41881801) { - if (_isSecond) { - if (_x > 330) - sendMessage(_klaymen, 0x4811, 2); - else - sendMessage(_klaymen, 0x4811, 0); - } else { - sendMessage(_klaymen, 0x4811, 0); - } - } else if (param.asInteger() == 0x522200A0) - playSound(0, 0x931080C8); - break; - case 0x3002: - gotoNextState(); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 995); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1015); - break; - } - return messageResult; -} - -void AsScene1002VenusFlyTrap::stWalkBack() { - setDoDeltaX(2); - startAnimation(0xC4080034, 0, -1); - SetUpdateHandler(&AsScene1002VenusFlyTrap::update); - SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt); - NextState(&AsScene1002VenusFlyTrap::stIdle); -} - -void AsScene1002VenusFlyTrap::stWalk() { - startAnimation(0xC4080034, 0, -1); - SetUpdateHandler(&AsScene1002VenusFlyTrap::update); - SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple); - NextState(&AsScene1002VenusFlyTrap::stIdle); -} - -void AsScene1002VenusFlyTrap::stRelease() { - sendMessage(_parentScene, 0x4807, 0); - startAnimation(0x82292851, 0, -1); - SetUpdateHandler(&AsScene1002VenusFlyTrap::update); - SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple); - NextState(&AsScene1002VenusFlyTrap::stIdle); -} - -void AsScene1002VenusFlyTrap::stGrabRing() { - setDoDeltaX(1); - startAnimation(0x86A82A11, 0, -1); - SetUpdateHandler(&AsScene1002VenusFlyTrap::update); - SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple); - NextState(&AsScene1002VenusFlyTrap::stRingGrabbed); -} - -void AsScene1002VenusFlyTrap::stRingGrabbed() { - startAnimation(0xB5A86034, 0, -1); - SetUpdateHandler(&AsScene1002VenusFlyTrap::update); - SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage); -} - -void AsScene1002VenusFlyTrap::stKlaymenInside() { - startAnimation(0x31303094, 0, -1); - SetUpdateHandler(&AsScene1002VenusFlyTrap::update); - SetMessageHandler(NULL); - NextState(&AsScene1002VenusFlyTrap::stKlaymenInsideMoving); - _countdown = 24; -} - -void AsScene1002VenusFlyTrap::stIdle() { - startAnimation(0xC8204250, 0, -1); - SetUpdateHandler(&AsScene1002VenusFlyTrap::upIdle); - SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage); - if (_isSecond) { - if (_x >= 154 && _x <= 346) - setGlobalVar(V_FLYTRAP_POSITION_2, (_x - 186) / 32); - else { - NextState(&AsScene1002VenusFlyTrap::stWalkBack); - _countdown = 12; - } - } else { - if (_x >= 174 && _x <= 430) - setGlobalVar(V_FLYTRAP_POSITION_1, (_x - 174) / 32); - else { - NextState(&AsScene1002VenusFlyTrap::stWalkBack); - _countdown = 12; - } - } -} - -void AsScene1002VenusFlyTrap::stKlaymenInsideMoving() { - startAnimation(0x152920C4, 0, -1); - SetUpdateHandler(&AsScene1002VenusFlyTrap::update); - SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt); - NextState(&AsScene1002VenusFlyTrap::stSpitOutKlaymen); -} - -void AsScene1002VenusFlyTrap::stSpitOutKlaymen() { - startAnimation(0x84001117, 0, -1); - SetUpdateHandler(&AsScene1002VenusFlyTrap::update); - SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt); - NextState(&AsScene1002VenusFlyTrap::stIdle); -} - -void AsScene1002VenusFlyTrap::swallowKlaymen() { - if (_x - 15 < _klaymen->getX() && _x + 15 > _klaymen->getX()) { - if (_isSecond) - setDoDeltaX(_x > 265 && _x < 330 ? 1 : 0); - else - setDoDeltaX(_x > 320 ? 1 : 0); - sendMessage(_klaymen, 0x2001, 0); - startAnimation(0x8C2C80D4, 0, -1); - SetUpdateHandler(&AsScene1002VenusFlyTrap::update); - SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt); - NextState(&AsScene1002VenusFlyTrap::stKlaymenInside); - } -} - -AsScene1002OutsideDoorBackground::AsScene1002OutsideDoorBackground(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1200), _countdown(0) { - - createSurface(850, 186, 212); - _x = 320; - _y = 240; - if (getGlobalVar(V_FLYTRAP_RING_DOOR)) { - startAnimation(0x004A4495, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - } else - setVisible(false); - SetUpdateHandler(&AsScene1002OutsideDoorBackground::update); - SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage); -} - -void AsScene1002OutsideDoorBackground::update() { - if (_countdown != 0 && (--_countdown == 0)) { - if (_isDoorClosed) - stCloseDoor(); - else - stOpenDoor(); - } - AnimatedSprite::update(); -} - -uint32 AsScene1002OutsideDoorBackground::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageResult) { - case 0x4808: - _isDoorClosed = false; - _countdown = 2; - break; - case 0x4809: - _isDoorClosed = true; - _countdown = 2; - break; - } - return messageResult; -} - -uint32 AsScene1002OutsideDoorBackground::hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = handleMessage(messageNum, param, sender); - switch (messageResult) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1002OutsideDoorBackground::stOpenDoor() { - startAnimation(0x004A4495, 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - setVisible(true); - SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage); -} - -void AsScene1002OutsideDoorBackground::stCloseDoor() { - startAnimation(0x004A4495, -1, -1); - _playBackwards = true; - setVisible(true); - SetMessageHandler(&AsScene1002OutsideDoorBackground::hmAnimation); - NextState(&AsScene1002OutsideDoorBackground::stDoorClosed); -} - -void AsScene1002OutsideDoorBackground::stDoorClosed() { - setVisible(false); - stopAnimation(); -} - -AsScene1002KlaymenLadderHands::AsScene1002KlaymenLadderHands(NeverhoodEngine *vm, Klaymen *klaymen) - : AnimatedSprite(vm, 1200), _klaymen(klaymen) { - - createSurface(1200, 40, 163); - setVisible(false); - SetUpdateHandler(&AsScene1002KlaymenLadderHands::update); - SetMessageHandler(&Sprite::handleMessage); -} - -void AsScene1002KlaymenLadderHands::update() { - if (_klaymen->getCurrAnimFileHash() == 0x3A292504) { - startAnimation(0xBA280522, _klaymen->getFrameIndex(), -1); - _newStickFrameIndex = _klaymen->getFrameIndex(); - setVisible(true); - _x = _klaymen->getX(); - _y = _klaymen->getY(); - setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0); - } else if (_klaymen->getCurrAnimFileHash() == 0x122D1505) { - startAnimation(0x1319150C, _klaymen->getFrameIndex(), -1); - _newStickFrameIndex = _klaymen->getFrameIndex(); - setVisible(true); - _x = _klaymen->getX(); - _y = _klaymen->getY(); - setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0); - } else - setVisible(false); - AnimatedSprite::update(); -} - -AsScene1002KlaymenPeekHand::AsScene1002KlaymenPeekHand(NeverhoodEngine *vm, Scene *parentScene, Klaymen *klaymen) - : AnimatedSprite(vm, 1200), _parentScene(parentScene), _klaymen(klaymen), - _isClipRectSaved(false) { - - createSurface(1000, 33, 41); - setVisible(false); - SetUpdateHandler(&AsScene1002KlaymenPeekHand::update); - SetMessageHandler(&AsScene1002KlaymenPeekHand::handleMessage); -} - -void AsScene1002KlaymenPeekHand::update() { - if (_klaymen->getCurrAnimFileHash() == 0xAC20C012 && _klaymen->getFrameIndex() < 50) { - startAnimation(0x9820C913, _klaymen->getFrameIndex(), -1); - _newStickFrameIndex = _klaymen->getFrameIndex(); - setVisible(true); - _x = _klaymen->getX(); - _y = _klaymen->getY(); - setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0); - } else - setVisible(false); - AnimatedSprite::update(); -} - -uint32 AsScene1002KlaymenPeekHand::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x4AB28209) { - sendMessage(_parentScene, 0x1022, 1200); - _isClipRectSaved = true; - _savedClipRect = _surface->getClipRect(); - setClipRect(0, 0, 640, 480); - } else if (param.asInteger() == 0x88001184) { - sendMessage(_parentScene, 0x1022, 1000); - if (_isClipRectSaved) - setClipRect(_savedClipRect); - } - break; - } - return messageResult; -} - -Scene1002::Scene1002(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _isKlaymenFloor(false), _isClimbingLadder(false) { - - NRect tempClipRect; - Sprite *tempSprite; - - SetUpdateHandler(&Scene1002::update); - SetMessageHandler(&Scene1002::handleMessage); - - setHitRects(0x004B4138); - setBackground(0x12C23307); - setPalette(0x12C23307); - - insertStaticSprite(0x06149428, 1100); - insertStaticSprite(0x312C8774, 1100); - - _ssLadderArch = insertStaticSprite(0x152C1313, 1015); - _ssLadderArchPart1 = insertStaticSprite(0x060000A0, 1200); - _ssLadderArchPart2 = insertStaticSprite(0xB2A423B0, 1100); - _ssLadderArchPart3 = insertStaticSprite(0x316E0772, 1100); - - _ssCeiling = insertStaticSprite(0x316C4BB4, 1015); - - if (which < 0) { - // Restoring game - if (_vm->_gameState.which == 0) { - // Klaymen on top - insertKlaymen(90, 226); - _asKlaymenLadderHands = insertSprite(_klaymen); - setMessageList(0x004B4270); - _klaymen->setClipRect(31, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart3->getDrawRect().y2()); - _asKlaymenLadderHands->getSurface()->getClipRect() = _klaymen->getSurface()->getClipRect(); - _klaymen->setRepl(64, 0); - } else { - // Klaymen on the floor - insertKlaymen(379, 435); - _asKlaymenLadderHands = insertSprite(_klaymen); - setMessageList(0x004B4270); - _klaymen->setClipRect(_ssLadderArch->getDrawRect().x, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart1->getDrawRect().y2()); - _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); - } - } else if (which == 1) { - // Klaymen entering from the right - insertKlaymen(650, 435); - _asKlaymenLadderHands = insertSprite(_klaymen); - setMessageList(0x004B4478); - _klaymen->setClipRect(_ssLadderArch->getDrawRect().x, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart1->getDrawRect().y2()); - _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); - _vm->_gameState.which = 1; - } else if (which == 2) { - // Klaymen coming up the ladder - insertKlaymen(68, 645); - _asKlaymenLadderHands = insertSprite(_klaymen); - setMessageList(0x004B4298); - _klaymen->setClipRect(_ssLadderArch->getDrawRect().x, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart1->getDrawRect().y2()); - _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); - _vm->_gameState.which = 1; - sendMessage(_klaymen, 0x4820, 0); - } else { - // Klaymen entering from the left, peeking - insertKlaymen(90, 226); - _asKlaymenLadderHands = insertSprite(_klaymen); - setMessageList(0x004B4470); - _klaymen->setClipRect(31, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart3->getDrawRect().y2()); - _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); - _asKlaymenPeekHand = insertSprite(this, _klaymen); - _asKlaymenPeekHand->setClipRect(_klaymen->getClipRect()); - _klaymen->setRepl(64, 0); - _vm->_gameState.which = 0; - } - - insertScreenMouse(0x23303124); - - tempSprite = insertStaticSprite(0xB3242310, 825); - tempClipRect.set(tempSprite->getDrawRect().x, tempSprite->getDrawRect().y, - _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart2->getDrawRect().y2()); - - _asRing1 = insertSprite(this, false, 258, 191, _ssCeiling->getDrawRect().y, false); - _asRing2 = insertSprite(this, false, 297, 189, _ssCeiling->getDrawRect().y, false); - _asRing3 = insertSprite(this, true, 370, 201, _ssCeiling->getDrawRect().y, getGlobalVar(V_FLYTRAP_RING_DOOR)); - _asRing4 = insertSprite(this, false, 334, 191, _ssCeiling->getDrawRect().y, false); - _asRing5 = insertSprite(this, false, 425, 184, _ssCeiling->getDrawRect().y, false); - - _asDoor = insertSprite(tempClipRect); - tempSprite = insertSprite(); - _asDoorSpy = insertSprite(tempClipRect, this, _asDoor, tempSprite); - _ssPressButton = insertSprite(this, 0x00412692, 0x140B60BE, 800, 0); - _asVenusFlyTrap = insertSprite(this, _klaymen, false); - addCollisionSprite(_asVenusFlyTrap); - - sendEntityMessage(_klaymen, 0x2007, _asVenusFlyTrap); - - _asOutsideDoorBackground = insertSprite(); - - setRectList(0x004B43A0); - - loadSound(1, 0x60755842); - loadSound(2, 0x616D5821); - -} - -Scene1002::~Scene1002() { -} - -void Scene1002::update() { - Scene::update(); - if (!_isKlaymenFloor && _klaymen->getY() > 230) { - _klaymen->setClipRect(_ssLadderArch->getDrawRect().x, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart1->getDrawRect().y2()); - _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); - deleteSprite(&_ssLadderArchPart3); - _klaymen->clearRepl(); - _isKlaymenFloor = true; - _vm->_gameState.which = 1; - } -} - -uint32 Scene1002::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = 0; - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0xE6EE60E1) { - if (getGlobalVar(V_FLYTRAP_RING_DOOR)) - setMessageList(0x004B4428); - else - setMessageList(0x004B4448); - messageResult = 1; - } else if (param.asInteger() == 0x4A845A00) - sendEntityMessage(_klaymen, 0x1014, _asRing1); - else if (param.asInteger() == 0x43807801) - sendEntityMessage(_klaymen, 0x1014, _asRing2); - else if (param.asInteger() == 0x46C26A01) { - if (getGlobalVar(V_FLYTRAP_RING_DOOR)) { - setMessageList(0x004B44B8); - } else { - sendEntityMessage(_klaymen, 0x1014, _asRing3); - if (_asVenusFlyTrap->getX() - 10 < 366 && _asVenusFlyTrap->getX() + 10 > 366) { - setGlobalVar(V_FLYTRAP_RING_EATEN, 1); - setMessageList(0x004B44A8); - } else { - setMessageList(0x004B44A0); - } - } - messageResult = 1; - } else if (param.asInteger() == 0x468C7B11) - sendEntityMessage(_klaymen, 0x1014, _asRing4); - else if (param.asInteger() == 0x42845B19) - sendEntityMessage(_klaymen, 0x1014, _asRing5); - else if (param.asInteger() == 0xC0A07458) - sendEntityMessage(_klaymen, 0x1014, _ssPressButton); - break; - case 0x1024: - sendMessage(_parentModule, 0x1024, param.asInteger()); - break; - case 0x2000: - if (_isClimbingLadder) { - setMessageList2(0x004B43D0); - } else { - if (_klaymen->getY() > 420) { - sendEntityMessage(_klaymen, 0x1014, _asVenusFlyTrap); - setMessageList2(0x004B4480); - } else if (_klaymen->getY() > 227) { - setMessageList2(0x004B41E0); - } else { - setMessageList2(0x004B4148); - } - } - break; - case 0x2002: - _messageList = NULL; - break; - case 0x2005: - _isClimbingLadder = true; - setRectList(0x004B4418); - break; - case 0x2006: - _isClimbingLadder = false; - setRectList(0x004B43A0); - break; - case 0x4806: - if (sender == _asRing1) { - setGlobalVar(V_RADIO_ENABLED, 0); - playSound(0, 0x665198C0); - } else if (sender == _asRing2) { - setGlobalVar(V_RADIO_ENABLED, 0); - playSound(0, 0xE2D389C0); - } else if (sender == _asRing3) { - setGlobalVar(V_RADIO_ENABLED, 0); - playSound(1); - sendMessage(_asDoor, 0x4808, 0); - sendMessage(_asOutsideDoorBackground, 0x4808, 0); - } else if (sender == _asRing4) { - setGlobalVar(V_RADIO_ENABLED, 0); - playSound(0, 0xE0558848); - } else if (sender == _asRing5) { - setGlobalVar(V_RADIO_ENABLED, 1); - playSound(0, 0x44014282); - } - break; - case 0x4807: - if (sender == _asRing3) { - playSound(2); - sendMessage(_asDoor, 0x4809, 0); - sendMessage(_asOutsideDoorBackground, 0x4809, 0); - } else if (sender == _asVenusFlyTrap) { - if (getGlobalVar(V_FLYTRAP_RING_DOOR)) { - sendMessage(_asRing3, 0x4807, 0); - } - } - break; - case 0x480B: - sendEntityMessage(_klaymen, 0x1014, _asDoorSpy); - break; - case 0x480F: - setGlobalVar(V_RADIO_ENABLED, 0); - playSound(1); - sendMessage(_asDoor, 0x4808, 0); - sendMessage(_asOutsideDoorBackground, 0x4808, 0); - break; - case 0x8000: - setSpriteSurfacePriority(_ssCeiling, 995); - setSpriteSurfacePriority(_ssLadderArch, 995); - break; - case 0x8001: - setSpriteSurfacePriority(_ssCeiling, 1015); - setSpriteSurfacePriority(_ssLadderArch, 1015); - break; - } - return messageResult; -} - -// StaticScene - -StaticScene::StaticScene(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 cursorFileHash) - : Scene(vm, parentModule) { - - SetMessageHandler(&StaticScene::handleMessage); - - setBackground(backgroundFileHash); - setPalette(backgroundFileHash); - insertPuzzleMouse(cursorFileHash, 20, 620); -} - -uint32 StaticScene::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) - leaveScene(0); - break; - } - return 0; -} - -// Scene1004 - -AsScene1004TrashCan::AsScene1004TrashCan(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100) { - - _x = 330; - _y = 327; - createSurface(800, 56, 50); - setVisible(false); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1004TrashCan::handleMessage); -} - -uint32 AsScene1004TrashCan::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x225A8587) - playSound(0, 0x109AFC4C); - break; - case 0x2002: - startAnimation(0xEB312C11, 0, -1); - setVisible(true); - break; - case 0x3002: - stopAnimation(); - setVisible(false); - break; - } - return 0; -} - -Scene1004::Scene1004(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _paletteAreaStatus(-1) { - - Sprite *tempSprite; - - SetUpdateHandler(&Scene1004::update); - SetMessageHandler(&Scene1004::handleMessage); - - setBackground(0x50C03005); - - if (getGlobalVar(V_ENTRANCE_OPEN)) { - setPalette(0xA30BA329); - _palette->addBasePalette(0xA30BA329, 0, 256, 0); - } else { - setPalette(0x50C03005); - _palette->addBasePalette(0x50C03005, 0, 256, 0); - } - addEntity(_palette); - - insertScreenMouse(0x03001504); - - if (which < 0) { - // Restoring game - setRectList(0x004B7C70); - insertKlaymen(330, 327); - setMessageList(0x004B7C18); - } else if (which == 1) { - // Klaymen returning from reading a note - setRectList(0x004B7C70); - insertKlaymen(330, 327); - setMessageList(0x004B7C08); - } else { - // Klaymen coming down the ladder - loadDataResource(0x01900A04); - insertKlaymen(_dataResource.getPoint(0x80052A29).x, 27); - setMessageList(0x004B7BF0); - } - - updatePaletteArea(); - - _asKlaymenLadderHands = insertSprite(_klaymen); - - insertStaticSprite(0x800034A0, 1100); - insertStaticSprite(0x64402020, 1100); - insertStaticSprite(0x3060222E, 1300); - tempSprite = insertStaticSprite(0x0E002004, 1300); - - _klaymen->setClipRect(0, tempSprite->getDrawRect().y, 640, 480); - _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); - - _asTrashCan = insertSprite(); - -} - -void Scene1004::update() { - Scene::update(); - updatePaletteArea(); -} - -uint32 Scene1004::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = 0; - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x926500A1) { - setMessageList(0x004B7C20); - messageResult = 1; - } - break; - case 0x2000: - loadDataResource(0x01900A04); - break; - case 0x2001: - setRectList(0x004B7C70); - break; - case 0x2002: - sendMessage(_asTrashCan, 0x2002, 0); - break; - } - return messageResult; -} - -void Scene1004::updatePaletteArea() { - if (_klaymen->getY() < 150) { - if (_paletteAreaStatus != 0) { - _paletteAreaStatus = 0; - _palette->addBasePalette(0x406B0D10, 0, 64, 0); - _palette->startFadeToPalette(12); - } - } else { - if (_paletteAreaStatus != 1) { - _paletteAreaStatus = 1; - _palette->addBasePalette(0x24332243, 0, 64, 0); - _palette->startFadeToPalette(12); - } - } -} - -// Scene1005 - -Scene1005::Scene1005(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - SetMessageHandler(&Scene1005::handleMessage); - - if (getGlobalVar(V_ENTRANCE_OPEN)) { - setBackground(0x2800E011); - setPalette(0x2800E011); - insertStaticSprite(0x492D5AD7, 100); - insertPuzzleMouse(0x0E015288, 20, 620); - } else { - setBackground(0x8870A546); - setPalette(0x8870A546); - insertStaticSprite(0x40D1E0A9, 100); - insertStaticSprite(0x149C00A6, 100); - insertPuzzleMouse(0x0A54288F, 20, 620); - } - - drawTextToBackground(); - -} - -uint32 Scene1005::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) - leaveScene(0); - break; - } - return 0; -} - -void Scene1005::drawTextToBackground() { - TextResource textResource(_vm); - const char *textStart, *textEnd; - int16 y = 36; - uint32 textIndex = getTextIndex(); - FontSurface *fontSurface = FontSurface::createFontSurface(_vm, getGlobalVar(V_ENTRANCE_OPEN) ? 0x283CE401 : 0xC6604282); - textResource.load(0x80283101); - textStart = textResource.getString(textIndex, textEnd); - while (textStart < textEnd) { - fontSurface->drawString(_background->getSurface(), 188, y, (const byte*)textStart); - y += 36; - textStart += strlen(textStart) + 1; - } - delete fontSurface; -} - -uint32 Scene1005::getTextIndex() { - uint32 textIndex; - textIndex = getTextIndex1(); - if (getGlobalVar(V_ENTRANCE_OPEN)) { - textIndex = getTextIndex2(); - } - if (getGlobalVar(V_TEXT_FLAG1) && getGlobalVar(V_TEXT_INDEX) == textIndex) { - textIndex = getTextIndex3(); - } else { - setGlobalVar(V_TEXT_FLAG1, 1); - setGlobalVar(V_TEXT_INDEX, textIndex); - } - return textIndex; -} - -uint32 Scene1005::getTextIndex1() { - uint32 textIndex; - if (getGlobalVar(V_WORLDS_JOINED)) { - if (!getGlobalVar(V_DOOR_PASSED)) - textIndex = 18; - else if (!getGlobalVar(V_ROBOT_TARGET)) - textIndex = 19; - else if (getGlobalVar(V_ROBOT_HIT)) { - if (!getGlobalVar(V_ENTRANCE_OPEN)) - textIndex = 23; - else if (!getSubVar(VA_HAS_KEY, 0) && !getSubVar(VA_IS_KEY_INSERTED, 0)) - textIndex = 24; - else if (!getGlobalVar(V_HAS_FINAL_KEY)) - textIndex = 26; - else if (!getSubVar(VA_HAS_KEY, 1) && !getSubVar(VA_IS_KEY_INSERTED, 1)) - textIndex = 27; - else if (!getGlobalVar(V_HAS_FINAL_KEY)) - textIndex = 28; - else - textIndex = 29; - } else if (!getGlobalVar(V_FELL_DOWN_HOLE)) - textIndex = 20; - else if (!getGlobalVar(V_SEEN_SYMBOLS_NO_LIGHT)) - textIndex = 21; - else - textIndex = 22; - } else if (getGlobalVar(V_BOLT_DOOR_UNLOCKED)) { - if (!getGlobalVar(V_WALL_BROKEN)) - textIndex = 12; - else if (!getGlobalVar(V_STAIRS_DOWN_ONCE)) - textIndex = 13; - else if (!getGlobalVar(V_RADIO_ENABLED)) - textIndex = 50; - else if (!getGlobalVar(V_UNUSED)) - textIndex = 14; - else if (!getGlobalVar(V_BEEN_SHRINKING_ROOM)) - textIndex = 15; - else if (!getGlobalVar(V_BEEN_STATUE_ROOM)) - textIndex = 16; - else - textIndex = 17; - } else if (!getGlobalVar(V_FLYTRAP_RING_EATEN)) { - textIndex = 0; - } else if (getGlobalVar(V_CREATURE_EXPLODED)) { - if (!getGlobalVar(V_TILE_PUZZLE_SOLVED)) - textIndex = 4; - else if (!getGlobalVar(V_HAS_TEST_TUBE)) - textIndex = 5; - else if (!getSubVar(VA_LOCKS_DISABLED, 0x40119852)) - textIndex = 6; - else if (!getGlobalVar(V_WATER_RUNNING)) - textIndex = 7; - else if (!getGlobalVar(V_NOTES_PUZZLE_SOLVED)) - textIndex = 8; - else if (!getSubVar(VA_LOCKS_DISABLED, 0x304008D2)) - textIndex = 9; - else if (!getSubVar(VA_LOCKS_DISABLED, 0x01180951)) - textIndex = 10; - else - textIndex = 11; - } else if (!getGlobalVar(V_CREATURE_ANGRY)) { - textIndex = 1; - } else if (getGlobalVar(V_TNT_DUMMY_BUILT)) { - textIndex = 3; - } else { - textIndex = 2; - } - return textIndex; -} - -uint32 Scene1005::getTextIndex2() { - uint32 textIndex = getGlobalVar(V_TEXT_COUNTING_INDEX1); - if (textIndex + 1 >= 10) { - setGlobalVar(V_TEXT_COUNTING_INDEX1, 0); - textIndex = 0; - } else { - setGlobalVar(V_TEXT_COUNTING_INDEX1, textIndex + 1); - } - return textIndex + 40; -} - -uint32 Scene1005::getTextIndex3() { - uint32 textIndex = getGlobalVar(V_TEXT_COUNTING_INDEX2); - if (textIndex + 1 >= 10) { - setGlobalVar(V_TEXT_COUNTING_INDEX2, 0); - textIndex = 0; - } else { - setGlobalVar(V_TEXT_COUNTING_INDEX2, textIndex + 1); - } - return textIndex + 30; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module1000.h b/engines/neverhood/module1000.h deleted file mode 100644 index 897d026470..0000000000 --- a/engines/neverhood/module1000.h +++ /dev/null @@ -1,300 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE1000_H -#define NEVERHOOD_MODULE1000_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" - -namespace Neverhood { - -// Module1000 - -class Module1000 : public Module { -public: - Module1000(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module1000(); -protected: - int _sceneNum; - uint32 _musicFileHash; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -// Scene1001 - -class AsScene1001Door : public AnimatedSprite { -public: - AsScene1001Door(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void hammerHitsDoor(); - void stShowIdleDoor(); - void stBustedDoorMove(); - void stBustedDoorGone(); -}; - -class AsScene1001Hammer : public AnimatedSprite { -public: - AsScene1001Hammer(NeverhoodEngine *vm, Sprite *asDoor); -protected: - Sprite *_asDoor; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1001Window : public AnimatedSprite { -public: - AsScene1001Window(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1001Lever : public AnimatedSprite { -public: - AsScene1001Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int deltaXType); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsCommonButtonSprite : public StaticSprite { -public: - SsCommonButtonSprite(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, int surfacePriority, uint32 soundFileHash); -protected: - Scene *_parentScene; - uint32 _soundFileHash; - int16 _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene1001 : public Scene { -public: - Scene1001(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Scene1001(); -protected: - Sprite *_asHammer; - Sprite *_asDoor; - Sprite *_asWindow; - Sprite *_asLever; - Sprite *_ssButton; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -// TODO: Move this to some common file since it's used several times - -class StaticScene : public Scene { -public: - StaticScene(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 cursorFileHash); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -// Scene1002 - -class AsScene1002Ring : public AnimatedSprite { -public: - AsScene1002Ring(NeverhoodEngine *vm, Scene *parentScene, bool isSpecial, int16 x, int16 y, int16 clipY1, bool isRingLow); -protected: - Scene *_parentScene; - bool _isSpecial; - void update(); - uint32 hmRingIdle(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmRingPulled1(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmRingPulled2(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmRingHangingLow(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmRingReleased(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1002Door : public StaticSprite { -public: - AsScene1002Door(NeverhoodEngine *vm, NRect &clipRect); -protected: - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suOpenDoor(); - void suCloseDoor(); -}; - -class AsScene1002BoxingGloveHitEffect : public AnimatedSprite { -public: - AsScene1002BoxingGloveHitEffect(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1002DoorSpy : public AnimatedSprite { -public: - AsScene1002DoorSpy(NeverhoodEngine *vm, NRect &clipRect, Scene *parentScene, Sprite *asDoor, Sprite *asScene1002BoxingGloveHitEffect); -protected: - Scene *_parentScene; - Sprite *_asDoor; - Sprite *_asBoxingGloveHitEffect; - NRect _clipRect; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmDoorSpyAnimation(int messageNum, const MessageParam ¶m, Entity *sender); - void suDoorSpy(); - void stDoorSpyIdle(); - void stDoorSpyBoxingGlove(); -}; - -class SsCommonPressButton : public StaticSprite { -public: - SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash); - void setFileHashes(uint32 fileHash1, uint32 fileHash2); -protected: - Scene *_parentScene; - uint32 _soundFileHash; - uint32 _fileHashes[2]; - int _status; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1002VenusFlyTrap : public AnimatedSprite { -public: - AsScene1002VenusFlyTrap(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, bool isSecond); -protected: - Scene *_parentScene; - Sprite *_klaymen; - int _countdown; - bool _isSecond; - void update(); - void upIdle(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmAnimationSimple(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmAnimationExt(int messageNum, const MessageParam ¶m, Entity *sender); - void stWalkBack(); - void stWalk(); - void stRelease(); - void stGrabRing(); - void stRingGrabbed(); - void stKlaymenInside(); - void stIdle(); - void stKlaymenInsideMoving(); - void stSpitOutKlaymen(); - void swallowKlaymen(); -}; - -class AsScene1002OutsideDoorBackground : public AnimatedSprite { -public: - AsScene1002OutsideDoorBackground(NeverhoodEngine *vm); -protected: - int _countdown; - bool _isDoorClosed; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender); - void stOpenDoor(); - void stCloseDoor(); - void stDoorClosed(); -}; - -class AsScene1002KlaymenLadderHands : public AnimatedSprite { -public: - AsScene1002KlaymenLadderHands(NeverhoodEngine *vm, Klaymen *klaymen); -protected: - Klaymen *_klaymen; - void update(); -}; - -class AsScene1002KlaymenPeekHand : public AnimatedSprite { -public: - AsScene1002KlaymenPeekHand(NeverhoodEngine *vm, Scene *parentScene, Klaymen *klaymen); -protected: - Scene *_parentScene; - Klaymen *_klaymen; - bool _isClipRectSaved; - NRect _savedClipRect; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene1002 : public Scene { -public: - Scene1002(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Scene1002(); -protected: - Sprite *_asRing1; - Sprite *_asRing2; - Sprite *_asRing3; - Sprite *_asRing4; - Sprite *_asRing5; - Sprite *_asDoor; - Sprite *_asDoorSpy; - Sprite *_asVenusFlyTrap; - Sprite *_ssLadderArch; - Sprite *_ssLadderArchPart1; - Sprite *_ssLadderArchPart2; - Sprite *_ssLadderArchPart3; - Sprite *_ssCeiling; - Sprite *_asKlaymenLadderHands; - Sprite *_asKlaymenPeekHand; - Sprite *_asOutsideDoorBackground; - Sprite *_ssPressButton; - bool _isKlaymenFloor; - bool _isClimbingLadder; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -// Scene1004 - -class AsScene1004TrashCan : public AnimatedSprite { -public: - AsScene1004TrashCan(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene1004 : public Scene { -public: - Scene1004(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_asKlaymenLadderHands; - Sprite *_asTrashCan; - int _paletteAreaStatus; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void updatePaletteArea(); -}; - -// Scene1005 - -class Scene1005 : public Scene { -public: - Scene1005(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void drawTextToBackground(); - uint32 getTextIndex(); - uint32 getTextIndex1(); - uint32 getTextIndex2(); - uint32 getTextIndex3(); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE1000_H */ diff --git a/engines/neverhood/module1100.cpp b/engines/neverhood/module1100.cpp deleted file mode 100644 index 067018dea0..0000000000 --- a/engines/neverhood/module1100.cpp +++ /dev/null @@ -1,707 +0,0 @@ -/* 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/module1100.h" -#include "neverhood/gamemodule.h" -#include "neverhood/navigationscene.h" - -namespace Neverhood { - -static const uint32 kModule1100SoundList[] = { - 0x90805C50, - 0xB288D450, - 0x98C05840, - 0x98A01500, - 0xB4005E50, - 0x92025040, - 0x90035066, - 0x74E01054, - 0 -}; - -Module1100::Module1100(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - if (which < 0) { - createScene(_vm->gameState().sceneNum, -1); - } else if (which == 1) { - createScene(8, 1); - } else { - createScene(8, 3); - } - - _vm->_soundMan->addSoundList(0x0002C818, kModule1100SoundList); - _vm->_soundMan->setSoundListParams(kModule1100SoundList, true, 50, 600, 20, 250); - _vm->_soundMan->setSoundParams(0x74E01054, false, 100, 200, 10, 20); - _vm->_soundMan->setSoundVolume(0x74E01054, 60); - _vm->_soundMan->playTwoSounds(0x0002C818, 0x41861371, 0x43A2507F, 0); - -} - -Module1100::~Module1100() { - _vm->_soundMan->deleteGroup(0x0002C818); -} - -void Module1100::createScene(int sceneNum, int which) { - static const uint32 kSmackerFileHashList06[] = {0x10880805, 0x1088081D, 0}; - static const uint32 kSmackerFileHashList07[] = {0x00290321, 0x01881000, 0}; - debug("Module1100::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _countdown = 65; - createNavigationScene(0x004B8430, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - _countdown = 50; - createNavigationScene(0x004B8460, which); - break; - case 2: - _vm->gameState().sceneNum = 2; - if (getGlobalVar(V_ROBOT_TARGET)) { - createNavigationScene(0x004B84F0, which); - } else { - createNavigationScene(0x004B8490, which); - } - break; - case 3: - _vm->gameState().sceneNum = 3; - if (getGlobalVar(V_ROBOT_TARGET)) { - createNavigationScene(0x004B8580, which); - } else { - createNavigationScene(0x004B8550, which); - } - break; - case 4: - _vm->gameState().sceneNum = 4; - _childObject = new Scene1105(_vm, this); - break; - case 5: - _vm->gameState().sceneNum = 5; - if (getGlobalVar(V_ROBOT_TARGET)) - createSmackerScene(0x04180001, true, false, false); - else - createSmackerScene(0x04180007, true, false, false); - break; - case 6: - _vm->gameState().sceneNum = 6; - _vm->_soundMan->deleteSoundGroup(0x0002C818); - createSmackerScene(kSmackerFileHashList06, true, true, false); - break; - case 7: - _vm->gameState().sceneNum = 7; - _vm->_soundMan->setSoundParams(0x74E01054, false, 0, 0, 0, 0); - createSmackerScene(kSmackerFileHashList07, true, true, false); - break; - case 8: - _vm->gameState().sceneNum = 8; - _childObject = new Scene1109(_vm, this, which); - break; - case 1002: - _vm->gameState().sceneNum = 2; - _countdown = 40; - _vm->_soundMan->setTwoSoundsPlayFlag(true); - createSmackerScene(0x00012211, true, true, false); - break; - } - SetUpdateHandler(&Module1100::updateScene); - _childObject->handleUpdate(); -} - -void Module1100::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - _countdown = 0; - _vm->_soundMan->playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64, 0); - _vm->_soundMan->setSoundVolume(0x48498E46, 65); - _vm->_soundMan->setSoundVolume(0x50399F64, 65); - if (_moduleResult == 0) - createScene(1, 0); - else if (_moduleResult == 1) - createScene(8, 0); - break; - case 1: - _vm->_soundMan->playTwoSounds(0x0002C818, 0x41861371, 0x43A2507F, 0); - if (getGlobalVar(V_ROBOT_HIT)) { - if (_moduleResult == 0) - createScene(6, -1); - else if (_moduleResult == 1) - createScene(0, 1); - } else { - if (_moduleResult == 0) - createScene(2, 0); - else if (_moduleResult == 1) - createScene(0, 1); - } - break; - case 2: - _vm->_soundMan->setSoundParams(0x74E01054, false, 0, 0, 0, 0); - if (_navigationAreaType == 3) - createScene(7, -1); - else if (_moduleResult == 1) - createScene(3, 0); - else if (_moduleResult == 2) - createScene(1002, -1); - break; - case 3: - if (_moduleResult == 0) - createScene(4, 0); - else if (_moduleResult == 1) - createScene(2, 3); - break; - case 4: - if (_moduleResult == 0) - createScene(3, 0); - else if (_moduleResult == 1) - createScene(5, -1); - break; - case 5: - _vm->_soundMan->setTwoSoundsPlayFlag(false); - if (getGlobalVar(V_ROBOT_TARGET)) - createScene(3, 0); - else - createScene(4, 0); - break; - case 6: - _vm->_soundMan->setTwoSoundsPlayFlag(false); - leaveModule(1); - break; - case 7: - _vm->_soundMan->setTwoSoundsPlayFlag(false); - createScene(2, 2); - break; - case 8: - if (_moduleResult == 0) - createScene(0, 0); - else if (_moduleResult == 1) - leaveModule(0); - break; - case 1002: - _vm->_soundMan->setTwoSoundsPlayFlag(false); - _countdown = 0; - _vm->_soundMan->playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64, 0); - createScene(1, 1); - break; - } - } else { - switch (_sceneNum) { - case 0: - if (navigationScene()->isWalkingForward() && _countdown != 0 && (--_countdown == 0)) { - _vm->_soundMan->playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64, 0); - _vm->_soundMan->setSoundVolume(0x48498E46, 65); - _vm->_soundMan->setSoundVolume(0x50399F64, 65); - } - break; - case 1: - if (navigationScene()->isWalkingForward() && _countdown != 0 && (--_countdown == 0)) - _vm->_soundMan->playTwoSounds(0x0002C818, 0x41861371, 0x43A2507F, 0); - break; - case 2: - _vm->_soundMan->setSoundParams(0x74E01054, !navigationScene()->isWalkingForward(), 0, 0, 0, 0); - break; - case 5: - case 6: - case 7: - case 1002: - if (_countdown != 0 && (--_countdown == 0)) { - _vm->_soundMan->playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64, 0); - _vm->_soundMan->setSoundVolume(0x48498E46, 65); - _vm->_soundMan->setSoundVolume(0x50399F64, 65); - } - break; - } - } -} - -static const uint32 kScene1105FileHashes[] = { - 0x00028006, - 0x0100A425, - 0x63090415, - 0x082100C4, - 0x0068C607, - 0x00018344, - 0x442090E4, - 0x0400E004, - 0x5020A054, - 0xB14A891E -}; - -static const uint32 kScene1105BackgroundFileHashes[] = { - 0x20018662, - 0x20014202, - 0x20012202, - 0x20010002 // CHECKME: This used ?? -}; - -static const uint32 kSsScene1105SymbolDieFileHashes[] = { - 0, - 0x90898414, - 0x91098414, - 0x92098414, - 0x94098414, - 0x98098414, - 0x80098414, - 0xB0098414, - 0xD0098414, - 0x10098414 -}; - -SsScene1105Button::SsScene1105Button(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, NRect &collisionBounds) - : StaticSprite(vm, fileHash, 200), _parentScene(parentScene), _countdown(0) { - - _collisionBounds = collisionBounds; - SetMessageHandler(&SsScene1105Button::handleMessage); - SetUpdateHandler(&SsScene1105Button::update); - setVisible(false); -} - -void SsScene1105Button::update() { - if (_countdown != 0 && (--_countdown == 0)) { - sendMessage(_parentScene, 0x4807, 0); - setVisible(false); - } -} - -uint32 SsScene1105Button::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_countdown == 0) { - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - } - break; - case 0x480B: - _countdown = 8; - setVisible(true); - playSound(0, 0x44141000); - break; - } - return messageResult; -} - -SsScene1105Symbol::SsScene1105Symbol(NeverhoodEngine *vm, uint32 fileHash, int16 x, int16 y) - : StaticSprite(vm, 0) { - - loadSprite(fileHash, kSLFCenteredDrawOffset | kSLFSetPosition, 200, x, y); -} - -void SsScene1105Symbol::hide() { - setVisible(false); - _needRefresh = true; - updatePosition(); -} - -SsScene1105SymbolDie::SsScene1105SymbolDie(NeverhoodEngine *vm, uint dieIndex, int16 x, int16 y) - : StaticSprite(vm, 1100), _dieIndex(dieIndex) { - - _x = x; - _y = y; - createSurface(200, 50, 50); - loadSymbolSprite(); - SetMessageHandler(&SsScene1105SymbolDie::handleMessage); -} - -uint32 SsScene1105SymbolDie::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - loadSymbolSprite(); - break; - } - return messageResult; -} - -void SsScene1105SymbolDie::loadSymbolSprite() { - loadSprite(kSsScene1105SymbolDieFileHashes[getSubVar(VA_CURR_DICE_NUMBERS, _dieIndex)], kSLFCenteredDrawOffset); -} - -void SsScene1105SymbolDie::hide() { - setVisible(false); - _needRefresh = true; - updatePosition(); -} - -AsScene1105TeddyBear::AsScene1105TeddyBear(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - - createSurface(100, 556, 328); - _x = 320; - _y = 240; - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1105TeddyBear::handleMessage); - startAnimation(0x65084002, 0, -1); - _newStickFrameIndex = 0; - setVisible(false); - _needRefresh = true; - updatePosition(); - loadSound(0, 0xCE840261); - loadSound(1, 0xCCA41A62); -} - -uint32 AsScene1105TeddyBear::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2002: - if (getGlobalVar(V_ROBOT_TARGET)) { - startAnimation(0x6B0C0432, 0, -1); - playSound(0); - } else { - startAnimation(0x65084002, 0, -1); - playSound(1); - } - break; - case 0x3002: - sendMessage(_parentScene, 0x2003, 0); - stopAnimation(); - break; - } - return messageResult; -} - -void AsScene1105TeddyBear::show() { - setVisible(true); - _needRefresh = true; - updatePosition(); -} - -void AsScene1105TeddyBear::hide() { - setVisible(false); - _needRefresh = true; - updatePosition(); -} - -SsScene1105OpenButton::SsScene1105OpenButton(NeverhoodEngine *vm, Scene *parentScene) - : StaticSprite(vm, 900), _parentScene(parentScene), _countdown(0), _isClicked(false) { - - loadSprite(0x8228A46C, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); - setVisible(false); - loadSound(0, 0x44045140); - SetUpdateHandler(&SsScene1105OpenButton::update); - SetMessageHandler(&SsScene1105OpenButton::handleMessage); -} - -void SsScene1105OpenButton::update() { - updatePosition(); - if (_countdown != 0 && (--_countdown == 0)) { - setVisible(false); - sendMessage(_parentScene, 0x2001, 0); - } -} - -uint32 SsScene1105OpenButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = 0; - Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_countdown == 0 && !_isClicked) { - playSound(0); - setVisible(true); - _isClicked = true; - _countdown = 4; - } - messageResult = 1; - break; - } - return messageResult; -} - -Scene1105::Scene1105(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule), _countdown(0), _isPanelOpen(false), _isActionButtonClicked(false), _doMoveTeddy(false), - _isClosePanelDone(false), _leaveResult(0), _backgroundIndex(0) { - - Sprite *ssOpenButton; - - _vm->gameModule()->initMemoryPuzzle(); - - SetUpdateHandler(&Scene1105::update); - SetMessageHandler(&Scene1105::handleMessage); - - setBackground(0x20010002); - setPalette(0x20010002); - - _asTeddyBear = insertSprite(this); - ssOpenButton = insertSprite(this); - addCollisionSprite(ssOpenButton); - insertPuzzleMouse(0x10006208, 20, 620); - - loadSound(0, 0x48442057); - loadSound(1, 0xC025014F); - loadSound(2, 0x68E25540); - -} - -uint32 Scene1105::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = 0; - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { - if (!_isActionButtonClicked && _backgroundIndex == 0) { - if (_isPanelOpen) { - _isPanelOpen = false; - _backgroundIndex = 15; - SetUpdateHandler(&Scene1105::upClosePanel); - } else - _isPanelOpen = true; - _leaveResult = 0; - } - } - break; - case 0x2001: - showMouse(false); - _backgroundIndex = 24; - SetUpdateHandler(&Scene1105::upOpenPanel); - break; - case 0x2003: - _backgroundIndex = 24; - _leaveResult = 1; - SetUpdateHandler(&Scene1105::upClosePanel); - break; - case 0x4807: - if (sender == _ssActionButton) { - if (getSubVar(VA_GOOD_DICE_NUMBERS, 0) == getSubVar(VA_CURR_DICE_NUMBERS, 0) && - getSubVar(VA_GOOD_DICE_NUMBERS, 1) == getSubVar(VA_CURR_DICE_NUMBERS, 1) && - getSubVar(VA_GOOD_DICE_NUMBERS, 2) == getSubVar(VA_CURR_DICE_NUMBERS, 2)) { - setGlobalVar(V_ROBOT_TARGET, 1); - playSound(2); - _doMoveTeddy = true; - } else { - sendMessage(_asTeddyBear, 0x2002, 0); - } - showMouse(false); - _isActionButtonClicked = true; - } - break; - case 0x4826: - if (_isPanelOpen) { - if (sender == _ssActionButton) { - sendMessage(_ssActionButton, 0x480B, 0); - _isPanelOpen = false; - } else if (!getGlobalVar(V_ROBOT_TARGET)) { - if (sender == _ssSymbol1UpButton) { - if (getSubVar(VA_CURR_DICE_NUMBERS, 0) < 9) { - incSubVar(VA_CURR_DICE_NUMBERS, 0, +1); - sendMessage(_ssSymbol1UpButton, 0x480B, 0); - sendMessage(_ssSymbolDice[0], 0x2000, 0); - } - } else if (sender == _ssSymbol1DownButton) { - if (getSubVar(VA_CURR_DICE_NUMBERS, 0) > 1) { - incSubVar(VA_CURR_DICE_NUMBERS, 0, -1); - sendMessage(_ssSymbol1DownButton, 0x480B, 0); - sendMessage(_ssSymbolDice[0], 0x2000, 0); - } - } else if (sender == _ssSymbol2UpButton) { - if (getSubVar(VA_CURR_DICE_NUMBERS, 1) < 9) { - incSubVar(VA_CURR_DICE_NUMBERS, 1, +1); - sendMessage(_ssSymbol2UpButton, 0x480B, 0); - sendMessage(_ssSymbolDice[1], 0x2000, 0); - } - } else if (sender == _ssSymbol2DownButton) { - if (getSubVar(VA_CURR_DICE_NUMBERS, 1) > 1) { - incSubVar(VA_CURR_DICE_NUMBERS, 1, -1); - sendMessage(_ssSymbol2DownButton, 0x480B, 0); - sendMessage(_ssSymbolDice[1], 0x2000, 0); - } - } else if (sender == _ssSymbol3UpButton) { - if (getSubVar(VA_CURR_DICE_NUMBERS, 2) < 9) { - incSubVar(VA_CURR_DICE_NUMBERS, 2, +1); - sendMessage(_ssSymbol3UpButton, 0x480B, 0); - sendMessage(_ssSymbolDice[2], 0x2000, 0); - } - } else if (sender == _ssSymbol3DownButton) { - if (getSubVar(VA_CURR_DICE_NUMBERS, 2) > 1) { - incSubVar(VA_CURR_DICE_NUMBERS, 2, -1); - sendMessage(_ssSymbol3DownButton, 0x480B, 0); - sendMessage(_ssSymbolDice[2], 0x2000, 0); - } - } - } - } - break; - } - return messageResult; -} - -void Scene1105::createObjects() { - _ssSymbols[0] = insertSprite(kScene1105FileHashes[getSubVar(VA_DICE_MEMORY_SYMBOLS, 0)], 161, 304); - _ssSymbols[1] = insertSprite(kScene1105FileHashes[getSubVar(VA_DICE_MEMORY_SYMBOLS, 1)], 294, 304); - _ssSymbols[2] = insertSprite(kScene1105FileHashes[getSubVar(VA_DICE_MEMORY_SYMBOLS, 2)], 440, 304); - - _ssSymbolDice[0] = insertSprite(0, 206, 304); - _ssSymbolDice[1] = insertSprite(1, 339, 304); - _ssSymbolDice[2] = insertSprite(2, 485, 304); - - _ssSymbol1UpButton = insertSprite(this, 0x08002860, NRect(146, 362, 192, 403)); - addCollisionSprite(_ssSymbol1UpButton); - _ssSymbol1DownButton = insertSprite(this, 0x42012460, NRect(147, 404, 191, 442)); - addCollisionSprite(_ssSymbol1DownButton); - _ssSymbol2UpButton = insertSprite(this, 0x100030A0, NRect(308, 361, 355, 402)); - addCollisionSprite(_ssSymbol2UpButton); - _ssSymbol2DownButton = insertSprite(this, 0x840228A0, NRect(306, 406, 352, 445)); - addCollisionSprite(_ssSymbol2DownButton); - _ssSymbol3UpButton = insertSprite(this, 0x20000120, NRect(476, 358, 509, 394)); - addCollisionSprite(_ssSymbol3UpButton); - _ssSymbol3DownButton = insertSprite(this, 0x08043121, NRect(463, 401, 508, 438)); - addCollisionSprite(_ssSymbol3DownButton); - _ssActionButton = insertSprite(this, 0x8248AD35, NRect(280, 170, 354, 245)); - addCollisionSprite(_ssActionButton); - - _isPanelOpen = true; - - _asTeddyBear->show(); - - insertPuzzleMouse(0x18666208, 20, 620); - -} - -void Scene1105::upOpenPanel() { - Scene::update(); - if (_backgroundIndex != 0) { - _backgroundIndex--; - if (_backgroundIndex < 6 && _backgroundIndex % 2 == 0) { - uint32 backgroundFileHash = kScene1105BackgroundFileHashes[_backgroundIndex / 2]; - changeBackground(backgroundFileHash); - _palette->addPalette(backgroundFileHash, 0, 256, 0); - } - if (_backgroundIndex == 10) - playSound(0); - if (_backgroundIndex == 0) { - SetUpdateHandler(&Scene1105::update); - _countdown = 2; - } - } -} - -void Scene1105::upClosePanel() { - Scene::update(); - if (_backgroundIndex != 0) { - _backgroundIndex--; - if (_backgroundIndex == 14) { - showMouse(false); - _ssSymbols[0]->hide(); - _ssSymbols[1]->hide(); - _ssSymbols[2]->hide(); - _ssSymbolDice[0]->hide(); - _ssSymbolDice[1]->hide(); - _ssSymbolDice[2]->hide(); - } - if (_backgroundIndex < 6 && _backgroundIndex % 2 == 0) { - uint32 backgroundFileHash = kScene1105BackgroundFileHashes[3 - _backgroundIndex / 2]; // CHECKME - if (_backgroundIndex == 4) { - playSound(1); - _asTeddyBear->hide(); - } - changeBackground(backgroundFileHash); - _palette->addPalette(backgroundFileHash, 0, 256, 0); - } - if (_backgroundIndex == 0) { - SetUpdateHandler(&Scene1105::update); - _isClosePanelDone = true; - } - } -} - -void Scene1105::update() { - - // DEBUG: Show the correct code - debug("(%d, %d) (%d, %d) (%d, %d)", - getSubVar(VA_GOOD_DICE_NUMBERS, 0), getSubVar(VA_CURR_DICE_NUMBERS, 0), - getSubVar(VA_GOOD_DICE_NUMBERS, 1), getSubVar(VA_CURR_DICE_NUMBERS, 1), - getSubVar(VA_GOOD_DICE_NUMBERS, 2), getSubVar(VA_CURR_DICE_NUMBERS, 2)); - - Scene::update(); - if (_countdown != 0 && (--_countdown == 0)) - createObjects(); - if (_isClosePanelDone && !isSoundPlaying(1)) - leaveScene(_leaveResult); - if (_doMoveTeddy && !isSoundPlaying(2)) { - sendMessage(_asTeddyBear, 0x2002, 0); - _doMoveTeddy = false; - } -} - -Scene1109::Scene1109(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - SetMessageHandler(&Scene1109::handleMessage); - - setBackground(0x8449E02F); - setPalette(0x8449E02F); - insertScreenMouse(0x9E02B84C); - - _sprite1 = insertStaticSprite(0x600CEF01, 1100); - - if (which < 0) { - // Restoring game - insertKlaymen(140, 436); - setMessageList(0x004B6260); - sendMessage(this, 0x2000, 0); - } else if (which == 1) { - // Klaymen teleporting in - insertKlaymen(450, 436); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B6268, false); - sendMessage(this, 0x2000, 1); - } else if (which == 2) { - // Klaymen teleporting out - insertKlaymen(450, 436); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B6318, false); - sendMessage(this, 0x2000, 1); - } else if (which == 3) { - // Klaymen returning from teleporter console - insertKlaymen(450, 436); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B6278, false); - sendMessage(this, 0x2000, 1); - } else { - // Klaymen entering from the left - insertKlaymen(0, 436); - setMessageList(0x004B6258); - sendMessage(this, 0x2000, 0); - } - - _klaymen->setClipRect(0, 0, _sprite1->getDrawRect().x2(), 480); - -} - -uint32 Scene1109::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - if (param.asInteger()) { - setRectList(0x004B63A8); - _klaymen->setKlaymenIdleTable3(); - } else { - setRectList(0x004B6398); - _klaymen->setKlaymenIdleTable1(); - } - break; - } - return 0; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module1100.h b/engines/neverhood/module1100.h deleted file mode 100644 index e3fb7cba10..0000000000 --- a/engines/neverhood/module1100.h +++ /dev/null @@ -1,130 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE1100_H -#define NEVERHOOD_MODULE1100_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" - -namespace Neverhood { - -// Module1100 - -class Module1100 : public Module { -public: - Module1100(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module1100(); -protected: - int _sceneNum; - int _countdown; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -class SsScene1105Button : public StaticSprite { -public: - SsScene1105Button(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, NRect &collisionBounds); -protected: - Scene *_parentScene; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsScene1105Symbol : public StaticSprite { -public: - SsScene1105Symbol(NeverhoodEngine *vm, uint32 fileHash, int16 x, int16 y); - void hide(); -}; - -class SsScene1105SymbolDie : public StaticSprite { -public: - SsScene1105SymbolDie(NeverhoodEngine *vm, uint dieIndex, int16 x, int16 y); - void hide(); -protected: - uint _dieIndex; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void loadSymbolSprite(); -}; - -class AsScene1105TeddyBear : public AnimatedSprite { -public: - AsScene1105TeddyBear(NeverhoodEngine *vm, Scene *parentScene); - void show(); - void hide(); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsScene1105OpenButton : public StaticSprite { -public: - SsScene1105OpenButton(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - int _countdown; - bool _isClicked; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene1105 : public Scene { -public: - Scene1105(NeverhoodEngine *vm, Module *parentModule); -protected: - int _countdown; - int _backgroundIndex; - bool _isPanelOpen; - bool _isActionButtonClicked; - bool _doMoveTeddy; - bool _isClosePanelDone; - int _leaveResult; - AsScene1105TeddyBear *_asTeddyBear; - SsScene1105Symbol *_ssSymbols[3]; - SsScene1105SymbolDie *_ssSymbolDice[3]; - Sprite *_ssSymbol1UpButton; - Sprite *_ssSymbol1DownButton; - Sprite *_ssSymbol2UpButton; - Sprite *_ssSymbol2DownButton; - Sprite *_ssSymbol3UpButton; - Sprite *_ssSymbol3DownButton; - Sprite *_ssActionButton; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void createObjects(); - void upOpenPanel(); - void upClosePanel(); - void update(); -}; - -class Scene1109 : public Scene { -public: - Scene1109(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_sprite1; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE1100_H */ diff --git a/engines/neverhood/module1200.cpp b/engines/neverhood/module1200.cpp deleted file mode 100644 index 1536114df8..0000000000 --- a/engines/neverhood/module1200.cpp +++ /dev/null @@ -1,1102 +0,0 @@ -/* 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/module1200.h" - -namespace Neverhood { - -Module1200::Module1200(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - SetMessageHandler(&Module1200::handleMessage); - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else if (which == 1) - createScene(0, 2); - else - createScene(0, 0); - - _vm->_soundMan->addMusic(0x00478311, 0x62222CAE); - _vm->_soundMan->startMusic(0x62222CAE, 0, 0); -} - -Module1200::~Module1200() { - _vm->_soundMan->deleteMusicGroup(0x00478311); -} - -void Module1200::createScene(int sceneNum, int which) { - debug("Module1200::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _childObject = new Scene1201(_vm, this, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - _childObject = new Scene1202(_vm, this); - break; - case 2: - _vm->gameState().sceneNum = 2; - _vm->_soundMan->stopMusic(0x62222CAE, 0, 0); - createSmackerScene(0x31890001, true, true, false); - setGlobalVar(V_SEEN_CREATURE_EXPLODE_VID, 1); - break; - } - SetUpdateHandler(&Module1200::updateScene); - _childObject->handleUpdate(); -} - -void Module1200::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 1) - createScene(1, 0); - else if (_moduleResult == 2) { - if (getGlobalVar(V_CREATURE_EXPLODED) && !getGlobalVar(V_SEEN_CREATURE_EXPLODE_VID)) - createScene(2, -1); - else - leaveModule(1); - } else - leaveModule(0); - break; - case 1: - createScene(0, 1); - break; - case 2: - _vm->_soundMan->startMusic(0x62222CAE, 0, 0); - createScene(0, 3); - break; - } - } -} - -// Scene1201 - -static const uint32 kScene1201InitArray[] = { - 1, 0, 2, 4, 5, 3, 6, 7, 8, 10, 9, 11, 13, 14, 12, 16, 17, 15 -}; - -static const NPoint kScene1201PointArray[] = { - {218, 193}, {410, 225}, {368, 277}, - {194, 227}, {366, 174}, {458, 224}, - {242, 228}, {512, 228}, {458, 277}, - {217, 233}, {458, 173}, {410, 276}, - {203, 280}, {371, 226}, {508, 279}, - {230, 273}, {410, 171}, {493, 174} -}; - -static const uint32 kScene1201TntFileHashList1[] = { - 0x2098212D, 0x1600437E, 0x1600437E, - 0x00A840E3, 0x1A1830F6, 0x1A1830F6, - 0x00212062, 0x384010B6, 0x384010B6, - 0x07A01080, 0xD80C2837, 0xD80C2837, - 0x03A22092, 0xD8802CB6, 0xD8802CB6, - 0x03A93831, 0xDA460476, 0xDA460476 -}; - -static const uint32 kScene1201TntFileHashList2[] = { - 0x3040C676, 0x10914448, 0x10914448, - 0x3448A066, 0x1288C049, 0x1288C049, - 0x78C0E026, 0x3098D05A, 0x3098D05A, - 0x304890E6, 0x1284E048, 0x1284E048, - 0xB140A1E6, 0x5088A068, 0x5088A068, - 0x74C4C866, 0x3192C059, 0x3192C059 -}; - -SsScene1201Tnt::SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 pointIndex, int16 clipY2) - : StaticSprite(vm, 900) { - - int16 x = kScene1201PointArray[pointIndex].x; - int16 y = kScene1201PointArray[pointIndex].y; - if (x < 300) - loadSprite(kScene1201TntFileHashList1[elemIndex], kSLFDefDrawOffset | kSLFDefPosition, 50); - else - loadSprite(kScene1201TntFileHashList2[elemIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 50, x, y); - setClipRect(0, 0, 640, clipY2); -} - -AsScene1201Tape::AsScene1201Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 nameHash, int surfacePriority, int16 x, int16 y, uint32 fileHash) - : AnimatedSprite(vm, fileHash, surfacePriority, x, y), _parentScene(parentScene), _nameHash(nameHash) { - - if (!getSubVar(VA_HAS_TAPE, _nameHash) && !getSubVar(VA_IS_TAPE_INSERTED, _nameHash)) { - SetMessageHandler(&AsScene1201Tape::handleMessage); - } else { - setVisible(false); - SetMessageHandler(NULL); - } -} - -uint32 AsScene1201Tape::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x4806: - setSubVar(VA_HAS_TAPE, _nameHash, 1); - setVisible(false); - SetMessageHandler(NULL); - break; - } - return messageResult; -} - -AsScene1201TntManRope::AsScene1201TntManRope(NeverhoodEngine *vm, bool isDummyHanging) - : AnimatedSprite(vm, 1200) { - - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1201TntManRope::handleMessage); - createSurface(10, 34, 149); - _x = 202; - _y = -32; - if (isDummyHanging) { - startAnimation(0x928F0C10, 15, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - } else { - startAnimation(0x928F0C10, 0, -1); - _newStickFrameIndex = 0; - } -} - -uint32 AsScene1201TntManRope::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x02060018) - playSound(0, 0x47900E06); - break; - case 0x2006: - startAnimation(0x928F0C10, 1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - break; - } - return messageResult; -} - -AsScene1201RightDoor::AsScene1201RightDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen) - : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown(0) { - - createSurface1(0xD088AC30, 100); - _x = 320; - _y = 240; - SetUpdateHandler(&AsScene1201RightDoor::update); - SetMessageHandler(&AsScene1201RightDoor::handleMessage); - _newStickFrameIndex = STICK_LAST_FRAME; - if (isOpen) { - startAnimation(0xD088AC30, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - _countdown = 25; - } else { - stopAnimation(); - setVisible(false); - } -} - -void AsScene1201RightDoor::update() { - if (_countdown != 0 && (--_countdown == 0)) - stCloseDoor(); - AnimatedSprite::update(); -} - -uint32 AsScene1201RightDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - case 0x4829: - stOpenDoor(); - break; - } - return messageResult; -} - -void AsScene1201RightDoor::stOpenDoor() { - startAnimation(0xD088AC30, 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - setVisible(true); - playSound(0, calcHash("fxDoorOpen20")); -} - -void AsScene1201RightDoor::stCloseDoor() { - startAnimation(0xD088AC30, -1, -1); - _playBackwards = true; - setVisible(true); - playSound(0, calcHash("fxDoorClose20")); - NextState(&AsScene1201RightDoor::stCloseDoorDone); -} - -void AsScene1201RightDoor::stCloseDoorDone() { - stopAnimation(); - setVisible(false); -} - -AsScene1201KlaymenHead::AsScene1201KlaymenHead(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1200) { - - createSurface(1200, 69, 98); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1201KlaymenHead::handleMessage); - SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); - setVisible(false); -} - -uint32 AsScene1201KlaymenHead::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2006: - _x = 436; - _y = 339; - startAnimation(0xA060C599, 0, -1); - setVisible(true); - break; - case 0x3002: - stopAnimation(); - setVisible(false); - gotoNextState(); - break; - } - return messageResult; -} - -AsScene1201TntMan::AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sprite *asTntManRope, bool isComingDown) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _asTntManRope(asTntManRope), - _isMoving(false) { - - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1201TntMan::handleMessage); - createSurface(990, 106, 181); - _x = 201; - if (isComingDown) { - _y = 297; - stComingDown(); - } else { - _y = 334; - stStanding(); - } -} - -AsScene1201TntMan::~AsScene1201TntMan() { - _vm->_soundMan->deleteSoundGroup(0x01D00560); -} - -uint32 AsScene1201TntMan::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x092870C0) - sendMessage(_asTntManRope, 0x2006, 0); - else if (param.asInteger() == 0x11CA0144) - playSound(0, 0x51800A04); - break; - case 0x1011: - sendMessage(_parentScene, 0x2002, 0); - messageResult = 1; - break; - case 0x480B: - if (!_isMoving) { - _sprite = (Sprite*)sender; - stMoving(); - } - break; - } - return messageResult; - -} - -uint32 AsScene1201TntMan::hmComingDown(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = AsScene1201TntMan::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1201TntMan::suMoving() { - _x = _sprite->getX() + 100; -} - -void AsScene1201TntMan::stStanding() { - startAnimation(0x654913D0, 0, -1); - SetMessageHandler(&AsScene1201TntMan::handleMessage); - SetSpriteUpdate(NULL); -} - -void AsScene1201TntMan::stComingDown() { - startAnimation(0x356803D0, 0, -1); - SetMessageHandler(&AsScene1201TntMan::hmComingDown); - SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); - NextState(&AsScene1201TntMan::stStanding); -} - -void AsScene1201TntMan::stMoving() { - _vm->_soundMan->addSound(0x01D00560, 0x4B044624); - _vm->_soundMan->playSoundLooping(0x4B044624); - _isMoving = true; - startAnimation(0x85084190, 0, -1); - SetMessageHandler(&AsScene1201TntMan::handleMessage); - SetSpriteUpdate(&AsScene1201TntMan::suMoving); - _newStickFrameIndex = STICK_LAST_FRAME; -} - -AsScene1201TntManFlame::AsScene1201TntManFlame(NeverhoodEngine *vm, Sprite *asTntMan) - : AnimatedSprite(vm, 1200), _asTntMan(asTntMan) { - - createSurface1(0x828C0411, 995); - SetUpdateHandler(&AsScene1201TntManFlame::update); - SetMessageHandler(&Sprite::handleMessage); - SetSpriteUpdate(&AsScene1201TntManFlame::suUpdate); - startAnimation(0x828C0411, 0, -1); - setVisible(false); -} - -AsScene1201TntManFlame::~AsScene1201TntManFlame() { - _vm->_soundMan->deleteSoundGroup(0x041080A4); -} - -void AsScene1201TntManFlame::update() { - AnimatedSprite::update(); - if (getGlobalVar(V_TNT_DUMMY_FUSE_LIT)) { - setVisible(true); - SetUpdateHandler(&AnimatedSprite::update); - _vm->_soundMan->addSound(0x041080A4, 0x460A1050); - _vm->_soundMan->playSoundLooping(0x460A1050); - } -} - -void AsScene1201TntManFlame::suUpdate() { - _x = _asTntMan->getX() - 18; - _y = _asTntMan->getY() - 158; -} - -AsScene1201Match::AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _countdown(0) { - - createSurface(1100, 57, 60); - SetUpdateHandler(&AsScene1201Match::update); - SetMessageHandler(&AsScene1201Match::hmOnDoorFrameAboutToMove); - SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); - switch (getGlobalVar(V_MATCH_STATUS)) { - case 0: - _x = 521; - _y = 112; - _status = 0; - stIdleOnDoorFrame(); - break; - case 1: - _x = 521; - _y = 112; - _status = 2; - stOnDoorFrameAboutToMove(); - loadSound(0, 0xD00230CD); - break; - case 2: - setDoDeltaX(1); - _x = 403; - _y = 337; - _status = 0; - stIdleOnFloor(); - break; - } -} - -void AsScene1201Match::update() { - if (_countdown != 0 && (--_countdown == 0)) - gotoNextState(); - updateAnim(); - handleSpriteUpdate(); - updatePosition(); -} - -uint32 AsScene1201Match::hmOnDoorFrameAboutToMove(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x86668011) - playSound(0); - break; - } - return messageResult; -} - -uint32 AsScene1201Match::hmOnDoorFrameMoving(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = hmOnDoorFrameAboutToMove(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -uint32 AsScene1201Match::hmIdle(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = hmOnDoorFrameAboutToMove(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x2001, 0); - messageResult = 1; - break; - case 0x4806: - setVisible(false); - setGlobalVar(V_MATCH_STATUS, 3); - break; - } - return messageResult; -} - -void AsScene1201Match::stOnDoorFrameMoving() { - startAnimation(0x00842374, 0, -1); - SetMessageHandler(&AsScene1201Match::hmOnDoorFrameMoving); - if (_status == 0) { - NextState(&AsScene1201Match::stFallingFromDoorFrame); - } else { - NextState(&AsScene1201Match::stOnDoorFrameAboutToMove); - } -} - -void AsScene1201Match::stFallingFromDoorFrame() { - setGlobalVar(V_MATCH_STATUS, 2); - _x -= 199; - _y += 119; - startAnimation(0x018D0240, 0, -1); - SetMessageHandler(&AsScene1201Match::hmOnDoorFrameMoving); - NextState(&AsScene1201Match::stIdleOnFloor); -} - -void AsScene1201Match::stOnDoorFrameAboutToMove() { - startAnimation(0x00842374, 0, -1); - SetMessageHandler(&AsScene1201Match::hmOnDoorFrameAboutToMove); - _newStickFrameIndex = 0; - if (_status != 0) { - _countdown = 36; - _status--; - NextState(&AsScene1201Match::stOnDoorFrameMoving); - } -} - -void AsScene1201Match::stIdleOnDoorFrame() { - startAnimation(0x00842374, 0, -1); - SetMessageHandler(&AsScene1201Match::hmIdle); - _newStickFrameIndex = 0; -} - -void AsScene1201Match::stIdleOnFloor() { - setDoDeltaX(1); - _x = 403; - _y = 337; - startAnimation(0x00842374, 0, -1); - SetMessageHandler(&AsScene1201Match::hmIdle); - _newStickFrameIndex = 0; -} - -AsScene1201Creature::AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen) - : AnimatedSprite(vm, 900), _parentScene(parentScene), _klaymen(klaymen), _klaymenTooClose(false) { - - // NOTE: _countdown2 and _countdown3 were unused/without effect and thus removed - - createSurface(1100, 203, 199); - SetUpdateHandler(&AsScene1201Creature::update); - SetMessageHandler(&AsScene1201Creature::hmWaiting); - _x = 540; - _y = 320; - stWaiting(); -} - -void AsScene1201Creature::update() { - bool oldKlaymenTooClose = _klaymenTooClose; - _klaymenTooClose = _klaymen->getX() >= 385; - if (_klaymenTooClose != oldKlaymenTooClose) - stWaiting(); - if (_countdown != 0 && (--_countdown == 0)) - gotoNextState(); - updateAnim(); - handleSpriteUpdate(); - updatePosition(); -} - -uint32 AsScene1201Creature::hmWaiting(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x02060018) - playSound(0, 0xCD298116); - break; - case 0x2004: - GotoState(&AsScene1201Creature::stStartReachForTntDummy); - break; - case 0x2006: - GotoState(&AsScene1201Creature::stPincerSnapKlaymen); - break; - } - return messageResult; -} - -uint32 AsScene1201Creature::hmPincerSnap(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = hmWaiting(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -uint32 AsScene1201Creature::hmPincerSnapKlaymen(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x02060018) { - playSound(0, 0xCD298116); - sendMessage(_parentScene, 0x4814, 0); - sendMessage(_klaymen, 0x4814, 0); - } - break; - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1201Creature::stWaiting() { - startAnimation(0x08081513, 0, -1); - SetMessageHandler(&AsScene1201Creature::hmWaiting); - NextState(&AsScene1201Creature::stPincerSnap); - _countdown = 36; -} - -void AsScene1201Creature::stPincerSnap() { - if (!_klaymenTooClose) { - startAnimation(0xCA287133, 0, -1); - SetMessageHandler(&AsScene1201Creature::hmPincerSnap); - NextState(&AsScene1201Creature::stWaiting); - } -} - -void AsScene1201Creature::stStartReachForTntDummy() { - startAnimation(0x08081513, 0, -1); - SetMessageHandler(&AsScene1201Creature::hmWaiting); - NextState(&AsScene1201Creature::stReachForTntDummy); - _countdown = 48; -} - -void AsScene1201Creature::stReachForTntDummy() { - startAnimation(0x5A201453, 0, -1); - SetMessageHandler(&AsScene1201Creature::hmWaiting); - _countdown = 0; -} - -void AsScene1201Creature::stPincerSnapKlaymen() { - startAnimation(0xCA287133, 0, -1); - SetMessageHandler(&AsScene1201Creature::hmPincerSnapKlaymen); - NextState(&AsScene1201Creature::stWaiting); - _countdown = 0; -} - -AsScene1201LeftDoor::AsScene1201LeftDoor(NeverhoodEngine *vm, Sprite *klaymen) - : AnimatedSprite(vm, 1100), _klaymen(klaymen) { - - _x = 320; - _y = 240; - createSurface(800, 55, 199); - if (_klaymen->getX() < 100) { - startAnimation(0x508A111B, 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - playSound(0, calcHash("fxDoorOpen03")); - } else { - startAnimation(0x508A111B, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - } - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1201LeftDoor::handleMessage); -} - -uint32 AsScene1201LeftDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4809: - stCloseDoor(); - break; - } - return messageResult; -} - -void AsScene1201LeftDoor::stCloseDoor() { - startAnimation(0x508A111B, -1, -1); - _playBackwards = true; - _newStickFrameIndex = 0; -} - -Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _creatureExploded(false), _asMatch(NULL), _asTntMan(NULL), - _asCreature(NULL), _asTntManRope(NULL), _asLeftDoor(NULL), _asRightDoor(NULL), _asTape(NULL) { - - int16 topY1, topY2, topY3, topY4; - int16 x1, x2; - Sprite *tempSprite; - - SetUpdateHandler(&Scene1201::update); - SetMessageHandler(&Scene1201::handleMessage); - - setHitRects(0x004AEBD0); - - if (!getSubVar(VA_IS_PUZZLE_INIT, 0xE8058B52)) { - setSubVar(VA_IS_PUZZLE_INIT, 0xE8058B52, 1); - for (uint32 index = 0; index < 18; index++) - setSubVar(VA_TNT_POSITIONS, index, kScene1201InitArray[index]); - } - - insertScreenMouse(0x9A2C0409); - - _asTape = insertSprite(this, 3, 1100, 243, 340, 0x9148A011); - addCollisionSprite(_asTape); - - tempSprite = insertStaticSprite(0x03C82530, 100); - topY1 = tempSprite->getY() + tempSprite->getDrawRect().height; - - tempSprite = insertStaticSprite(0x88182069, 200); - topY2 = tempSprite->getY() + tempSprite->getDrawRect().height; - - tempSprite = insertStaticSprite(0x476014E0, 300); - topY3 = tempSprite->getY() + tempSprite->getDrawRect().height; - - tempSprite = insertStaticSprite(0x04063110, 500); - topY4 = tempSprite->getY() + 1; - - _asTntManRope = insertSprite(getGlobalVar(V_TNT_DUMMY_BUILT) && which != 1); - _asTntManRope->setClipRect(0, topY4, 640, 480); - - insertStaticSprite(0x400B04B0, 1200); - - tempSprite = insertStaticSprite(0x40295462, 1200); - x1 = tempSprite->getX(); - - tempSprite = insertStaticSprite(0xA29223FA, 1200); - x2 = tempSprite->getX() + tempSprite->getDrawRect().width; - - _asKlaymenHead = insertSprite(); - - if (which < 0) { - // Restoring game - insertKlaymen(364, 333); - setMessageList(0x004AEC08); - } else if (which == 3) { - // Klaymen standing after the weasel exploded - insertKlaymen(400, 329); - setMessageList(0x004AEC08); - } else if (which == 2) { - // Klaymen entering from the right - if (getGlobalVar(V_CREATURE_ANGRY) && !getGlobalVar(V_CREATURE_EXPLODED)) { - insertKlaymen(374, 333); - setMessageList(0x004AEC08); - } else { - insertKlaymen(640, 329); - setMessageList(0x004AEC20); - } - } else if (which == 1) { - // Klaymen returning from the TNT console - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { - insertKlaymen(364, 333); - _klaymen->setDoDeltaX(1); - } else { - insertKlaymen(246, 333); - } - setMessageList(0x004AEC30); - } else { - // Klaymen entering from the left - insertKlaymen(0, 336); - setMessageList(0x004AEC10); - } - - _klaymen->setClipRect(x1, 0, x2, 480); - _klaymen->setRepl(64, 0); - - if (getGlobalVar(V_CREATURE_ANGRY) && !getGlobalVar(V_CREATURE_EXPLODED)) { - setBackground(0x4019A2C4); - setPalette(0x4019A2C4); - _asRightDoor = NULL; - } else { - setBackground(0x40206EC5); - setPalette(0x40206EC5); - _asRightDoor = insertSprite(_klaymen, which == 2); - } - - if (getGlobalVar(V_TNT_DUMMY_BUILT)) { - insertStaticSprite(0x10002ED8, 500); - if (!getGlobalVar(V_CREATURE_EXPLODED)) { - _asTntMan = insertSprite(this, _asTntManRope, which == 1); - _asTntMan->setClipRect(x1, 0, x2, 480); - _asTntMan->setRepl(64, 0); - addCollisionSprite(_asTntMan); - tempSprite = insertSprite(_asTntMan); - tempSprite->setClipRect(x1, 0, x2, 480); - } - - uint32 tntIndex = 1; - while (tntIndex < 18) { - uint32 elemIndex = getSubVar(VA_TNT_POSITIONS, tntIndex); - int16 clipY2; - if (kScene1201PointArray[elemIndex].y < 175) - clipY2 = topY1; - else if (kScene1201PointArray[elemIndex].y < 230) - clipY2 = topY2; - else - clipY2 = topY3; - insertSprite(tntIndex, getSubVar(VA_TNT_POSITIONS, tntIndex), clipY2); - elemIndex = getSubVar(VA_TNT_POSITIONS, tntIndex + 1); - if (kScene1201PointArray[elemIndex].y < 175) - clipY2 = topY1; - else if (kScene1201PointArray[elemIndex].y < 230) - clipY2 = topY2; - else - clipY2 = topY3; - insertSprite(tntIndex + 1, getSubVar(VA_TNT_POSITIONS, tntIndex + 1), clipY2); - tntIndex += 3; - } - - if (getGlobalVar(V_CREATURE_ANGRY) && !getGlobalVar(V_CREATURE_EXPLODED)) { - setRectList(0x004AEE58); - } else { - setRectList(0x004AEDC8); - } - - } else { - - insertStaticSprite(0x8E8A1981, 900); - - uint32 tntIndex = 0; - while (tntIndex < 18) { - uint32 elemIndex = getSubVar(VA_TNT_POSITIONS, tntIndex); - int16 clipY2; - if (kScene1201PointArray[elemIndex].x < 300) { - clipY2 = 480; - } else { - if (kScene1201PointArray[elemIndex].y < 175) - clipY2 = topY1; - else if (kScene1201PointArray[elemIndex].y < 230) - clipY2 = topY2; - else - clipY2 = topY3; - } - insertSprite(tntIndex, getSubVar(VA_TNT_POSITIONS, tntIndex), clipY2); - tntIndex++; - } - - if (getGlobalVar(V_CREATURE_ANGRY) && !getGlobalVar(V_CREATURE_EXPLODED)) - setRectList(0x004AEE18); - else - setRectList(0x004AED88); - - } - - tempSprite = insertStaticSprite(0x63D400BC, 900); - - _asLeftDoor = insertSprite(_klaymen); - _asLeftDoor->setClipRect(x1, tempSprite->getDrawRect().y, tempSprite->getDrawRect().x2(), 480); - - if (getGlobalVar(V_CREATURE_ANGRY) && getGlobalVar(V_MATCH_STATUS) == 0) - setGlobalVar(V_MATCH_STATUS, 1); - - _asMatch = NULL; - - if (getGlobalVar(V_MATCH_STATUS) < 3) { - _asMatch = insertSprite(this); - addCollisionSprite(_asMatch); - } - - if (getGlobalVar(V_CREATURE_ANGRY) && getGlobalVar(V_CREATURE_EXPLODED) == 0) { - _asCreature = insertSprite(this, _klaymen); - _asCreature->setClipRect(x1, 0, x2, 480); - } - -} - -Scene1201::~Scene1201() { - if (_creatureExploded) - setGlobalVar(V_CREATURE_EXPLODED, 1); - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); -} - -void Scene1201::update() { - Scene::update(); - if (_asMatch && getGlobalVar(V_MATCH_STATUS) == 3) - deleteSprite(&_asMatch); -} - -uint32 Scene1201::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x07053000) { - _creatureExploded = true; - sendMessage(_asCreature, 0x2004, 0); - } else if (param.asInteger() == 0x140E5744) - sendMessage(_asCreature, 0x2005, 0); - else if (param.asInteger() == 0x40253C40) { - _canAcceptInput = false; - sendMessage(_asCreature, 0x2006, 0); - } else if (param.asInteger() == 0x090EB048) { - if (_klaymen->getX() < 572) - setMessageList2(0x004AEC90); - else - setMessageList2(0x004AEC20); - } - break; - case 0x2001: - if (getGlobalVar(V_MATCH_STATUS) == 0) - setMessageList2(0x004AECB0); - else { - sendEntityMessage(_klaymen, 0x1014, _asMatch); - setMessageList2(0x004AECC0); - } - break; - case 0x2002: - if (getGlobalVar(V_TNT_DUMMY_FUSE_LIT)) { - // Move the TNT dummy if the fuse is burning - sendEntityMessage(_klaymen, 0x1014, _asTntMan); - setMessageList2(0x004AECF0, false); - } else if (getGlobalVar(V_MATCH_STATUS) == 3) { - // Light the TNT dummy if we have the match - sendEntityMessage(_klaymen, 0x1014, _asTntMan); - if (_klaymen->getX() > _asTntMan->getX()) - setMessageList(0x004AECD0); - else - setMessageList(0x004AECE0); - } - break; - case 0x4814: - cancelMessageList(); - break; - case 0x4826: - if (sender == _asTape) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004AED38); - } - break; - case 0x4829: - sendMessage(_asRightDoor, 0x4829, 0); - break; - case 0x8000: - sendMessage(_asKlaymenHead, 0x2006, 0); - break; - } - return messageResult; -} - -// Scene1202 - -static const uint32 kScene1202Table[] = { - 1, 2, 0, 4, 5, 3, 7, 8, 6, 10, 11, 9, 13, 14, 12, 16, 17, 15 -}; - -static const NPoint kScene1202Points[] = { - {203, 140}, {316, 212}, {277, 264}, - {176, 196}, {275, 159}, {366, 212}, - {230, 195}, {412, 212}, {368, 263}, - {204, 192}, {365, 164}, {316, 262}, - {191, 255}, {280, 213}, {406, 266}, - {214, 254}, {316, 158}, {402, 161} -}; - -static const uint32 kScene1202FileHashes[] = { - 0x1AC00B8, 0x1AC14B8, 0x1AC14B8, - 0x1AC30B8, 0x1AC14B8, 0x1AC14B8, - 0x1AC00B8, 0x1AC14B8, 0x1AC14B8, - 0x1AC90B8, 0x1AC18B8, 0x1AC18B8, - 0x1AC30B8, 0x1AC14B8, 0x1AC14B8, - 0x1AC50B8, 0x1AC14B8, 0x1AC14B8 -}; - -AsScene1202TntItem::AsScene1202TntItem(NeverhoodEngine *vm, Scene *parentScene, int itemIndex) - : AnimatedSprite(vm, 900), _parentScene(parentScene), _itemIndex(itemIndex) { - - int positionIndex; - - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1202TntItem::hmShowIdle); - positionIndex = getSubVar(VA_TNT_POSITIONS, _itemIndex); - createSurface(900, 37, 67); - _x = kScene1202Points[positionIndex].x; - _y = kScene1202Points[positionIndex].y; - stShowIdle(); -} - -uint32 AsScene1202TntItem::hmShowIdle(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x2000, _itemIndex); - messageResult = 1; - break; - case 0x2001: - _newPosition = (int)param.asInteger(); - stChangePositionFadeOut(); - break; - } - return messageResult; -} - -uint32 AsScene1202TntItem::hmChangePosition(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1202TntItem::stShowIdle() { - startAnimation(kScene1202FileHashes[_itemIndex], 0, -1); - SetMessageHandler(&AsScene1202TntItem::hmShowIdle); - _newStickFrameIndex = 0; -} - -void AsScene1202TntItem::stChangePositionFadeOut() { - startAnimation(kScene1202FileHashes[_itemIndex], 0, -1); - SetMessageHandler(&AsScene1202TntItem::hmChangePosition); - NextState(&AsScene1202TntItem::stChangePositionFadeIn); -} - -void AsScene1202TntItem::stChangePositionFadeIn() { - _x = kScene1202Points[_newPosition].x; - _y = kScene1202Points[_newPosition].y; - startAnimation(kScene1202FileHashes[_itemIndex], 6, -1); - _playBackwards = true; - SetMessageHandler(&AsScene1202TntItem::hmChangePosition); - NextState(&AsScene1202TntItem::stChangePositionDone); -} - -void AsScene1202TntItem::stChangePositionDone() { - sendMessage(_parentScene, 0x2002, _itemIndex); - stShowIdle(); -} - -Scene1202::Scene1202(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule), _paletteResource(vm), - _soundToggle(true), _isPuzzleSolved(false), _counter(0), _clickedIndex(-1) { - - SetMessageHandler(&Scene1202::handleMessage); - SetUpdateHandler(&Scene1202::update); - - setBackground(0x60210ED5); - setPalette(0x60210ED5); - addEntity(_palette); - - _paletteResource.load(0x60250EB5); - _paletteResource.copyPalette(_paletteData); - - insertPuzzleMouse(0x10ED160A, 20, 620); - - for (int tntIndex = 0; tntIndex < 18; tntIndex++) { - _asTntItems[tntIndex] = insertSprite(this, tntIndex); - addCollisionSprite(_asTntItems[tntIndex]); - } - - insertStaticSprite(0x8E8419C1, 1100); - - if (getGlobalVar(V_TNT_DUMMY_BUILT)) - SetMessageHandler(&Scene1202::hmSolved); - - playSound(0, 0x40106542); - loadSound(1, 0x40005446); - loadSound(2, 0x40005446); // Same sound as slot 1 - loadSound(3, 0x68E25540); - -} - -Scene1202::~Scene1202() { - if (isSolved()) - setGlobalVar(V_TNT_DUMMY_BUILT, 1); -} - -void Scene1202::update() { - Scene::update(); - if (_isPuzzleSolved) { - if (!isSoundPlaying(3)) - leaveScene(0); - } else if (_counter == 0 && isSolved()) { - _clickedIndex = 0; - SetMessageHandler(&Scene1202::hmSolved); - setGlobalVar(V_TNT_DUMMY_BUILT, 1); - _palette->copyToBasePalette(_paletteData); - _palette->startFadeToPalette(24); - playSound(3); - _isPuzzleSolved = true; - } else if (_clickedIndex >= 0 && _counter == 0) { - // Swap TNT positions - int destIndex = kScene1202Table[_clickedIndex]; - sendMessage(_asTntItems[_clickedIndex], 0x2001, getSubVar(VA_TNT_POSITIONS, destIndex)); - sendMessage(_asTntItems[destIndex], 0x2001, getSubVar(VA_TNT_POSITIONS, _clickedIndex)); - int temp = getSubVar(VA_TNT_POSITIONS, destIndex); - setSubVar(VA_TNT_POSITIONS, destIndex, getSubVar(VA_TNT_POSITIONS, _clickedIndex)); - setSubVar(VA_TNT_POSITIONS, _clickedIndex, temp); - _counter = 2; - _clickedIndex = -1; - playSound(_soundToggle ? 1 : 2); - _soundToggle = !_soundToggle; - } -} - -uint32 Scene1202::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = 0; - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && !_isPuzzleSolved) - leaveScene(0); - break; - case 0x2000: - _clickedIndex = (int)param.asInteger(); - break; - case 0x2002: - _counter--; - break; - } - return messageResult; -} - -uint32 Scene1202::hmSolved(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) - leaveScene(0); - break; - } - return 0; -} - -bool Scene1202::isSolved() { - return - getSubVar(VA_TNT_POSITIONS, 0) == 0 && getSubVar(VA_TNT_POSITIONS, 3) == 3 && - getSubVar(VA_TNT_POSITIONS, 6) == 6 && getSubVar(VA_TNT_POSITIONS, 9) == 9 && - getSubVar(VA_TNT_POSITIONS, 12) == 12 && getSubVar(VA_TNT_POSITIONS, 15) == 15; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module1200.h b/engines/neverhood/module1200.h deleted file mode 100644 index f6f97b4131..0000000000 --- a/engines/neverhood/module1200.h +++ /dev/null @@ -1,216 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE1200_H -#define NEVERHOOD_MODULE1200_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" - -namespace Neverhood { - -// Module1200 - -class Module1200 : public Module { -public: - Module1200(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module1200(); -protected: - int _sceneNum; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -// Scene1201 - -class AsScene1201Tape : public AnimatedSprite { -public: - AsScene1201Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 nameHash, int surfacePriority, int16 x, int16 y, uint32 fileHash); -protected: - Scene *_parentScene; - uint32 _nameHash; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1201TntManRope : public AnimatedSprite { -public: - AsScene1201TntManRope(NeverhoodEngine *vm, bool isDummyHanging); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1201RightDoor : public AnimatedSprite { -public: - AsScene1201RightDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen); -protected: - Sprite *_klaymen; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stOpenDoor(); - void stCloseDoor(); - void stCloseDoorDone(); -}; - -class AsScene1201KlaymenHead : public AnimatedSprite { -public: - AsScene1201KlaymenHead(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1201TntMan : public AnimatedSprite { -public: - AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sprite *asTntManRope, bool isDown); - virtual ~AsScene1201TntMan(); -protected: - Scene *_parentScene; - Sprite *_asTntManRope; - Sprite *_sprite; - bool _isMoving; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmComingDown(int messageNum, const MessageParam ¶m, Entity *sender); - void suMoving(); - void stStanding(); - void stComingDown(); - void stMoving(); -}; - -class AsScene1201TntManFlame : public AnimatedSprite { -public: - AsScene1201TntManFlame(NeverhoodEngine *vm, Sprite *asTntMan); - ~AsScene1201TntManFlame(); -protected: - Sprite *_asTntMan; - void update(); - void suUpdate(); -}; - -class AsScene1201Match : public AnimatedSprite { -public: - AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - int _countdown; - int _status; - void update(); - uint32 hmOnDoorFrameAboutToMove(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmOnDoorFrameMoving(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmIdle(int messageNum, const MessageParam ¶m, Entity *sender); - void stOnDoorFrameMoving(); - void stFallingFromDoorFrame(); - void stOnDoorFrameAboutToMove(); - void stIdleOnDoorFrame(); - void stIdleOnFloor(); -}; - -class AsScene1201Creature : public AnimatedSprite { -public: - AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen); -protected: - Scene *_parentScene; - Sprite *_klaymen; - int _countdown; - bool _klaymenTooClose; - void update(); - uint32 hmWaiting(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmPincerSnap(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmPincerSnapKlaymen(int messageNum, const MessageParam ¶m, Entity *sender); - void stWaiting(); - void stPincerSnap(); - void stStartReachForTntDummy(); - void stReachForTntDummy(); - void stPincerSnapKlaymen(); -}; - -class AsScene1201LeftDoor : public AnimatedSprite { -public: - AsScene1201LeftDoor(NeverhoodEngine *vm, Sprite *klaymen); -protected: - Sprite *_klaymen; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stCloseDoor(); -}; - -class SsScene1201Tnt : public StaticSprite { -public: - SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 pointIndex, int16 clipY2); -protected: - uint32 _elemIndex; -}; - -class Scene1201 : public Scene { -public: - Scene1201(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Scene1201(); -protected: - Sprite *_asMatch; - AsScene1201TntMan *_asTntMan; - Sprite *_asCreature; - Sprite *_asTntManRope; - Sprite *_asLeftDoor; - Sprite *_asRightDoor; - Sprite *_asTape; - Sprite *_asKlaymenHead; - bool _creatureExploded; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -// Scene1202 - -class AsScene1202TntItem : public AnimatedSprite { -public: - AsScene1202TntItem(NeverhoodEngine *vm, Scene *parentScene, int index); -protected: - Scene *_parentScene; - int _itemIndex, _newPosition; - uint32 hmShowIdle(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmChangePosition(int messageNum, const MessageParam ¶m, Entity *sender); - void stShowIdle(); - void stChangePositionFadeOut(); - void stChangePositionFadeIn(); - void stChangePositionDone(); -}; - -class Scene1202 : public Scene { -public: - Scene1202(NeverhoodEngine *vm, Module *parentModule); - virtual ~Scene1202(); -protected: - PaletteResource _paletteResource; - Sprite *_asTntItems[18]; - int _counter; - int _clickedIndex; - byte _paletteData[1024]; - bool _isPuzzleSolved; - bool _soundToggle; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmSolved(int messageNum, const MessageParam ¶m, Entity *sender); - bool isSolved(); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE1200_H */ diff --git a/engines/neverhood/module1300.cpp b/engines/neverhood/module1300.cpp deleted file mode 100644 index 162d710f46..0000000000 --- a/engines/neverhood/module1300.cpp +++ /dev/null @@ -1,1835 +0,0 @@ -/* 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/module1300.h" -#include "neverhood/module1000.h" -#include "neverhood/module1200.h" -#include "neverhood/module1400.h" -#include "neverhood/module2200.h" -#include "neverhood/gamemodule.h" -#include "neverhood/diskplayerscene.h" -#include "neverhood/menumodule.h" -#include "neverhood/navigationscene.h" -#include "neverhood/smackerscene.h" - -namespace Neverhood { - -static const uint32 kModule1300SoundList[] = { - 0x16805648, - 0x16805C48, - 0xB4964448, - 0x96A05481, - 0xD0E14441, - 0x90815450, - 0 -}; - -Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - _vm->_soundMan->addMusic(0x61C090, 0x00203197); - _vm->_soundMan->addSoundList(0x61C090, kModule1300SoundList); - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 50, 600, 20, 150); - _vm->_soundMan->playTwoSounds(0x61C090, 0x48498E46, 0x50399F64, 0); - _vm->_soundMan->setSoundVolume(0x48498E46, 70); - _vm->_soundMan->setSoundVolume(0x50399F64, 70); - - if (which < 0) { - if (_vm->gameState().sceneNum >= 1 && _vm->gameState().sceneNum <= 17) - createScene(_vm->gameState().sceneNum, -1); - else - createScene(11, 0); - } else { - switch (which) { - case 0: - createScene(11, 0); - break; - case 1: - createScene(13, 0); - break; - case 2: - createScene(14, 0); - break; - case 3: - createScene(15, 0); - break; - case 4: - createScene(7, 0); - break; - case 5: - createScene(5, 1); - break; - case 6: - createScene(5, 5); - break; - case 7: - createScene(3, 0); - break; - case 8: - createScene(1, 0); - break; - case 9: - createScene(2, 0); - break; - case 10: - createScene(6, 0); - break; - case 11: - createScene(4, 0); - break; - default: - createScene(12, 0); - break; - } - } - -} - -Module1300::~Module1300() { - _vm->_soundMan->deleteGroup(0x61C090); -} - -void Module1300::createScene(int sceneNum, int which) { - debug("Module1300::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 1: - _vm->gameState().sceneNum = 1; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->startMusic(0x00203197, 0, 2); - _childObject = new Scene1302(_vm, this, which); - break; - case 2: - _vm->gameState().sceneNum = 2; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - _childObject = new Scene1303(_vm, this); - break; - case 3: - _vm->gameState().sceneNum = 3; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - _childObject = new Scene1304(_vm, this, which); - break; - case 4: - _vm->gameState().sceneNum = 4; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->startMusic(0x00203197, 0, 2); - _childObject = new Scene1305(_vm, this, which); - break; - case 5: - _vm->gameState().sceneNum = 5; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->startMusic(0x00203197, 0, 2); - _childObject = new Scene1306(_vm, this, which); - break; - case 6: - _vm->gameState().sceneNum = 6; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->startMusic(0x00203197, 0, 2); - _childObject = new Scene1307(_vm, this); - break; - case 7: - _vm->gameState().sceneNum = 7; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->startMusic(0x00203197, 0, 2); - _childObject = new Scene1308(_vm, this, which); - break; - case 8: - _vm->gameState().sceneNum = 8; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - _childObject = new DiskplayerScene(_vm, this, 1); - break; - case 9: - _vm->gameState().sceneNum = 9; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - createSmackerScene(0x20082818, true, true, false); - break; - case 10: - _vm->gameState().sceneNum = 10; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - createSmackerScene(0x20082828, true, true, false); - break; - case 11: - _vm->gameState().sceneNum = 11; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - createNavigationScene(0x004B27A8, which); - break; - case 12: - _vm->gameState().sceneNum = 12; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - createNavigationScene(0x004B2718, which); - break; - case 13: - _vm->gameState().sceneNum = 13; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - createNavigationScene(0x004B27D8, which); - break; - case 14: - _vm->gameState().sceneNum = 14; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - createNavigationScene(0x004B2808, which); - break; - case 15: - _vm->gameState().sceneNum = 15; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - createNavigationScene(0x004B2838, which); - break; - case 16: - _vm->gameState().sceneNum = 16; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - _childObject = new Scene1317(_vm, this); - break; - case 17: - _vm->gameState().sceneNum = 17; - _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->stopMusic(0x00203197, 0, 2); - _childObject = new CreditsScene(_vm, this, false); - break; - } - SetUpdateHandler(&Module1300::updateScene); - _childObject->handleUpdate(); -} - -void Module1300::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 1: - if (_moduleResult == 1) - createScene(4, 0); - else - createScene(7, 1); - break; - case 2: - createScene(5, 3); - break; - case 3: - createScene(15, 0); - break; - case 4: - createScene(16, -1); - break; - case 5: - if (_moduleResult == 2) - createScene(8, 0); - else if (_moduleResult == 3) - createScene(2, 0); - else if (_moduleResult == 0) - leaveModule(0); - else if (_moduleResult == 1) - createScene(10, -1); - break; - case 6: - createScene(7, 2); - break; - case 7: - if (_moduleResult == 0) - createScene(13, 0); - else if (_moduleResult == 1) - createScene(1, 0); - else if (_moduleResult == 2) - createScene(6, 0); - break; - case 8: - createScene(5, 2); - break; - case 9: - createScene(5, 0); - break; - case 10: - createScene(14, 0); - break; - case 11: - if (_moduleResult == 0) - createScene(12, 0); - else if (_moduleResult == 1) - createScene(11, 1); - break; - case 12: - if (_moduleResult == 0) - createScene(14, 1); - else if (_moduleResult == 1) - createScene(15, 1); - else if (_moduleResult == 3) - createScene(11, 1); - else if (_moduleResult == 5) - createScene(13, 1); - break; - case 13: - if (_moduleResult == 0) - createScene(12, 2); - else if (_moduleResult == 1) - createScene(7, 0); - break; - case 14: - if (_moduleResult == 0) - createScene(12, 3); - else if (_moduleResult == 1) - createScene(9, -1); - break; - case 15: - if (_moduleResult == 0) - createScene(12, 4); - else if (_moduleResult == 1) - createScene(3, 0); - break; - case 16: - createScene(17, -1); - break; - case 17: - leaveModule(1); - break; - } - } -} - -AsScene1302Bridge::AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - - _x = 320; - _y = 240; - createSurface1(0x88148150, 500); - if (!getGlobalVar(V_FLYTRAP_RING_BRIDGE)) { - startAnimation(0x88148150, 0, -1); - _newStickFrameIndex = 0; - } else { - startAnimation(0x88148150, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - } - loadSound(0, 0x68895082); - loadSound(1, 0x689BD0C1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1302Bridge::handleMessage); -} - -uint32 AsScene1302Bridge::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - case 0x4808: - stLowerBridge(); - break; - case 0x4809: - stRaiseBridge(); - break; - } - return messageResult; -} - -void AsScene1302Bridge::stLowerBridge() { - startAnimation(0x88148150, 0, -1); - playSound(1); - NextState(&AsScene1302Bridge::cbLowerBridgeEvent); -} - -void AsScene1302Bridge::stRaiseBridge() { - startAnimation(0x88148150, 7, -1); - _playBackwards = true; - _newStickFrameIndex = 0; - playSound(0); -} - -void AsScene1302Bridge::cbLowerBridgeEvent() { - sendMessage(_parentScene, 0x2032, 0); - startAnimation(0x88148150, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; -} - -SsScene1302Fence::SsScene1302Fence(NeverhoodEngine *vm) - : StaticSprite(vm, 0x11122122, 200) { - - _firstY = _y; - if (getGlobalVar(V_FLYTRAP_RING_FENCE)) - _y += 152; - loadSound(0, 0x7A00400C); - loadSound(1, 0x78184098); - SetUpdateHandler(&SsScene1302Fence::update); - SetMessageHandler(&SsScene1302Fence::handleMessage); - SetSpriteUpdate(NULL); -} - -void SsScene1302Fence::update() { - handleSpriteUpdate(); - updatePosition(); -} - -uint32 SsScene1302Fence::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4808: - playSound(0); - SetMessageHandler(NULL); - SetSpriteUpdate(&SsScene1302Fence::suMoveDown); - break; - case 0x4809: - playSound(1); - SetMessageHandler(NULL); - SetSpriteUpdate(&SsScene1302Fence::suMoveUp); - break; - } - return messageResult; -} - -void SsScene1302Fence::suMoveDown() { - if (_y < _firstY + 152) - _y += 8; - else { - SetMessageHandler(&SsScene1302Fence::handleMessage); - SetSpriteUpdate(NULL); - } -} - -void SsScene1302Fence::suMoveUp() { - if (_y > _firstY) - _y -= 8; - else { - SetMessageHandler(&SsScene1302Fence::handleMessage); - SetSpriteUpdate(NULL); - } -} - -Scene1302::Scene1302(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - SetMessageHandler(&Scene1302::handleMessage); - - setHitRects(0x004B0858); - setRectList(0x004B0A38); - setBackground(0x420643C4); - setPalette(0x420643C4); - insertScreenMouse(0x643C0428); - - _class595 = insertStaticSprite(0xB0420130, 1015); - _sprite1 = insertStaticSprite(0x942FC224, 300); - _sprite2 = insertStaticSprite(0x70430830, 1200); - _sprite2->setVisible(false); - _sprite3 = insertStaticSprite(0x16E01E20, 1100); - _asRing1 = insertSprite(this, false, 218, 122, _class595->getDrawRect().y, false); - _asRing2 = insertSprite(this, true, 218 + 32, 132, _class595->getDrawRect().y, getGlobalVar(V_FLYTRAP_RING_BRIDGE)); - _asRing3 = insertSprite(this, false, 218 + 32 + 32, 122, _class595->getDrawRect().y, false); - _asRing4 = insertSprite(this, true, 218 + 32 + 32 + 32, 132, _class595->getDrawRect().y, getGlobalVar(V_FLYTRAP_RING_FENCE)); - _asRing5 = insertSprite(this, false, 218 + 32 + 32 + 32 + 32, 115, _class595->getDrawRect().y, false); - _asBridge = insertSprite(this); - _ssFence = insertSprite(); - _ssFence->setClipRect(0, 0, 640, _sprite1->getDrawRect().y2()); - - if (which < 0) { - // Restoring game - insertKlaymen(380, 364); - setMessageList(0x004B0868); - } else { - // Klaymen entering from back - insertKlaymen(293, 330); - setMessageList(0x004B0870); - } - - _klaymen->setClipRect(0, 0, _sprite3->getDrawRect().x2(), 480); - - _asVenusFlyTrap = insertSprite(this, _klaymen, true); - addCollisionSprite(_asVenusFlyTrap); - - sendEntityMessage(_klaymen, 0x2007, _asVenusFlyTrap); - -} - -uint32 Scene1302::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = 0; - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x4A845A00) - sendEntityMessage(_klaymen, 0x1014, _asRing1); - else if (param.asInteger() == 0x43807801) { - if (!getGlobalVar(V_FLYTRAP_RING_BRIDGE)) { - sendEntityMessage(_klaymen, 0x1014, _asRing2); - if (_asVenusFlyTrap->getX() - 10 < 218 + 32 && _asVenusFlyTrap->getX() + 10 > 218 + 32) - setMessageList(0x004B0940); - else - setMessageList(0x004B0938); - } else - setMessageList(0x004B0950); - messageResult = 1; - } else if (param.asInteger() == 0x46C26A01) - sendEntityMessage(_klaymen, 0x1014, _asRing3); - else if (param.asInteger() == 0x468C7B11) { - if (!getGlobalVar(V_FLYTRAP_RING_FENCE)) { - sendEntityMessage(_klaymen, 0x1014, _asRing4); - if (_asVenusFlyTrap->getX() - 10 < 218 + 32 + 32 + 32 && _asVenusFlyTrap->getX() + 10 > 218 + 32 + 32 + 32) - setMessageList(0x004B0940); - else - setMessageList(0x004B0938); - } else - setMessageList(0x004B0950); - messageResult = 1; - } else if (param.asInteger() == 0x42845B19) - sendEntityMessage(_klaymen, 0x1014, _asRing5); - else if (param.asInteger() == 0x430A6060) { - if (getGlobalVar(V_FLYTRAP_RING_BRIDGE)) - setMessageList2(0x004B0910); - else - cancelMessageList(); - } else if (param.asInteger() == 0x012E2070) { - if (getGlobalVar(V_FLYTRAP_RING_BRIDGE)) - setMessageList2(0x004B0968); - else - cancelMessageList(); - } else if (param.asInteger() == 0x11C40840) { - if (_asVenusFlyTrap->getX() >= 260 && _asVenusFlyTrap->getX() <= 342) - setMessageList(0x004B0878); - else - setMessageList(0x004B0978); - } - break; - case 0x2000: - if (_klaymen->getY() > 360) { - sendEntityMessage(_klaymen, 0x1014, _asVenusFlyTrap); - setMessageList2(0x004B08F0); - } else - setMessageList2(0x004B0920); - break; - case 0x2002: - if (_klaymen->getX() > 545) - leaveScene(1); - break; - case 0x2032: - _sprite2->setVisible(true); - break; - case 0x4806: - sendMessage(_parentModule, 0x1024, 2); - if (sender == _asRing1) - playSound(0, 0x665198C0); - else if (sender == _asRing2) { - sendMessage(_asBridge, 0x4808, 0); - setGlobalVar(V_FLYTRAP_RING_BRIDGE, 1); - } else if (sender == _asRing3) - playSound(0, 0xE2D389C0); - else if (sender == _asRing4) { - sendMessage(_ssFence, 0x4808, 0); - setGlobalVar(V_FLYTRAP_RING_FENCE, 1); - } else if (sender == _asRing5) - playSound(0, 0x40428A09); - break; - case 0x4807: - if (sender == _asRing2) { - sendMessage(_asBridge, 0x4809, 0); - setGlobalVar(V_FLYTRAP_RING_BRIDGE, 0); - _sprite2->setVisible(false); - } else if (sender == _asRing4) { - sendMessage(_ssFence, 0x4809, 0); - setGlobalVar(V_FLYTRAP_RING_FENCE, 0); - } else if (sender == _asVenusFlyTrap) { - if (getGlobalVar(V_FLYTRAP_RING_BRIDGE)) - sendMessage(_asRing2, 0x4807, 0); - else - sendMessage(_asRing4, 0x4807, 0); - } - break; - case 0x480F: - if (sender == _asRing2) { - playSound(0, 0x60755842); - sendMessage(_asBridge, 0x4808, 0); - setGlobalVar(V_FLYTRAP_RING_BRIDGE, 1); - } else if (sender == _asRing4) { - playSound(0, 0x60755842); - sendMessage(_ssFence, 0x4808, 0); - setGlobalVar(V_FLYTRAP_RING_FENCE, 1); - } - break; - case 0x482A: - sendMessage(_asVenusFlyTrap, 0x482B, 0); - break; - case 0x482B: - sendMessage(_asVenusFlyTrap, 0x482A, 0); - break; - case 0x8000: - setSpriteSurfacePriority(_class595, 995); - break; - case 0x8001: - setSpriteSurfacePriority(_class595, 1015); - break; - } - return messageResult; -} - -AsScene1303Balloon::AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - - createSurface(200, 128, 315); - _x = 289; - _y = 390; - startAnimation(0x800278D2, 0, -1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1303Balloon::handleMessage); - SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); -} - -uint32 AsScene1303Balloon::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x2000: - stPopBalloon(); - break; - } - return messageResult; -} - -uint32 AsScene1303Balloon::hmBalloonPopped(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x020B0003) - playSound(0, 0x742B0055); - break; - case 0x3002: - playSound(0, 0x470007EE); - stopAnimation(); - setVisible(false); - SetMessageHandler(NULL); - break; - } - return messageResult; -} - -void AsScene1303Balloon::stPopBalloon() { - startAnimation(0xAC004CD0, 0, -1); - SetMessageHandler(&AsScene1303Balloon::hmBalloonPopped); -} - -Scene1303::Scene1303(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule) { - - SetMessageHandler(&Scene1303::handleMessage); - - setRectList(0x004AF9E8); - setBackground(0x01581A9C); - setPalette(0x01581A9C); - insertScreenMouse(0x81A9801D); - - if (!getGlobalVar(V_BALLOON_POPPED)) { - _asBalloon = insertSprite(this); - addCollisionSprite(_asBalloon); - } - - _sprite1 = insertStaticSprite(0xA014216B, 1100); - - insertKlaymen(207, 332); - setMessageList(0x004AF9A0); - - _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); - -} - -uint32 Scene1303::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - setGlobalVar(V_BALLOON_POPPED, 1); - sendMessage(_asBalloon, 0x2000, 0); - break; - case 0x4826: - if (sender == _asBalloon && getGlobalVar(V_HAS_NEEDLE)) - setMessageList(0x004AF9B8); - break; - } - return 0; -} - -AsScene1304Needle::AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y) - : AnimatedSprite(vm, 0x548E9411, surfacePriority, x, y), _parentScene(parentScene) { - - // NOTE: Skipped check if Klaymen already has the needle since that's done in the scene itself - SetMessageHandler(&AsScene1304Needle::handleMessage); -} - -uint32 AsScene1304Needle::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x4806: - setGlobalVar(V_HAS_NEEDLE, 1); - setVisible(false); - SetMessageHandler(NULL); - break; - } - return messageResult; -} - -Scene1304::Scene1304(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _asNeedle(NULL) { - - SetMessageHandler(&Scene1304::handleMessage); - - setRectList(0x004B91A8); - setBackground(0x062C0214); - setPalette(0x062C0214); - insertScreenMouse(0xC021006A); - - if (getGlobalVar(V_BALLOON_POPPED)) { - _asKey = insertSprite(this, 0, 1100, 278, 347); - addCollisionSprite(_asKey); - } else { - _asKey = insertSprite(0x80106018, 100, 279, 48); - } - - if (!getGlobalVar(V_HAS_NEEDLE)) { - _asNeedle = insertSprite(this, 1100, 278, 347); - addCollisionSprite(_asNeedle); - } - - _sprite1 = insertStaticSprite(0x0562E621, 1100); - insertStaticSprite(0x012AE033, 1100); - insertStaticSprite(0x090AF033, 1100); - - if (which < 0) { - // Restoring game - insertKlaymen(217, 347); - setMessageList(0x004B90E8); - } else { - // Klaymen entering from the left - insertKlaymen(100, 347); - setMessageList(0x004B90F0); - } - - _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); - -} - -uint32 Scene1304::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x415634A4) { - if (getGlobalVar(V_BALLOON_POPPED)) - cancelMessageList(); - else - setMessageList(0x004B9158); - } - break; - case 0x4826: - if (sender == _asNeedle) { - sendEntityMessage(_klaymen, 0x1014, _asNeedle); - setMessageList(0x004B9130); - } else if (sender == _asKey) { - sendEntityMessage(_klaymen, 0x1014, _asKey); - setMessageList(0x004B9140); - } - break; - } - return 0; -} - -Scene1305::Scene1305(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - SetMessageHandler(&Scene1305::handleMessage); - - setRectList(0x004B6E98); - setBackground(0x28801B64); - setPalette(0x28801B64); - insertScreenMouse(0x01B60280); - - if (which < 0) { - // Restoring game - insertKlaymen(212, 441); - setMessageList(0x004B6E40); - } else { - // Klaymen enters falling - insertKlaymen(212, 441); - setMessageList(0x004B6E48); - } - -} - -uint32 Scene1305::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - return Scene::handleMessage(messageNum, param, sender); -} - -AsScene1306Elevator::AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _asElevatorDoor(asElevatorDoor), _isUp(false), _isDown(true), - _countdown(0) { - - _x = 320; - _y = 240; - createSurface1(0x043B0270, 100); - startAnimation(0x043B0270, 0, -1); - _newStickFrameIndex = 0; - loadSound(0, 0x1C100E83); - loadSound(1, 0x1C08CEC5); - loadSound(2, 0x5D011E87); - SetMessageHandler(&AsScene1306Elevator::handleMessage); -} - -void AsScene1306Elevator::update() { - if (_isUp && _countdown != 0 && (--_countdown == 0)) - stGoingDown(); - AnimatedSprite::update(); - if (_currFrameIndex == 7) { - playSound(1); - _asElevatorDoor->setVisible(false); - } -} - -void AsScene1306Elevator::upGoingDown() { - AnimatedSprite::update(); - if (_currFrameIndex == 5) - _asElevatorDoor->setVisible(true); -} - -uint32 AsScene1306Elevator::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2001: - if (_isUp) - _countdown = 144; - messageResult = _isUp ? 1 : 0; - break; - case 0x3002: - gotoNextState(); - break; - case 0x4808: - if (_isDown) - stGoingUp(); - break; - } - return messageResult; -} - -void AsScene1306Elevator::stGoingUp() { - setVisible(true); - _isDown = false; - startAnimation(0x043B0270, 0, -1); - playSound(0); - SetUpdateHandler(&AsScene1306Elevator::update); - NextState(&AsScene1306Elevator::cbGoingUpEvent); -} - -void AsScene1306Elevator::cbGoingUpEvent() { - sendMessage(_parentScene, 0x4808, 0); - _isUp = true; - _countdown = 144; - stopAnimation(); - setVisible(false); - SetUpdateHandler(&AsScene1306Elevator::update); -} - -void AsScene1306Elevator::stGoingDown() { - _isUp = false; - setVisible(true); - startAnimation(0x043B0270, -1, -1); - _playBackwards = true; - playSound(1); - SetUpdateHandler(&AsScene1306Elevator::upGoingDown); - NextState(&AsScene1306Elevator::cbGoingDownEvent); -} - -void AsScene1306Elevator::cbGoingDownEvent() { - _isDown = true; - sendMessage(_parentScene, 0x4809, 0); - stopAnimation(); - SetUpdateHandler(&AsScene1306Elevator::update); -} - -Scene1306::Scene1306(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) - setGlobalVar(V_KEY3_LOCATION, 4); - - SetMessageHandler(&Scene1306::handleMessage); - - setBackground(0x05303114); - setPalette(0x05303114); - insertScreenMouse(0x0311005B); - - if (getGlobalVar(V_KEY3_LOCATION) == 4) { - _asKey = insertSprite(this, 2, 1100, 435, 445); - addCollisionSprite(_asKey); - } - - _ssButton = insertSprite(this, 0x404A36A0, 100, 0x440C1000); - _asTape = insertSprite(this, 19, 1100, 359, 445, 0x9148A011); - _asElevatorDoor = insertSprite(0x043B0270, 90, 320, 240); - _asElevatorDoor->startAnimation(0x043B0270, 6, -1); - _asElevatorDoor->setNewHashListIndex(6); - _asElevator = insertSprite(this, _asElevatorDoor); - _sprite1 = insertStaticSprite(0x036A1EE0, 80); - insertStaticSprite(0x00042313, 1100); - - if (which < 0) { - // Resoring game - insertKlaymen(380, 440); - setMessageList(0x004AFAD0); - sendMessage(this, 0x2000, 0); - addCollisionSprite(_asTape); - } else if (which == 1) { - // Klaymen teleporting in - insertKlaymen(136, 440); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004AFAF0); - sendMessage(this, 0x2000, 1); - addCollisionSprite(_asTape); - } else if (which == 2) { - // Klaymen returning from diskplayer - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { - insertKlaymen(515, 440); - _klaymen->setDoDeltaX(1); - } else { - insertKlaymen(355, 440); - } - setMessageList(0x004AFBC8); - sendMessage(this, 0x2000, 0); - addCollisionSprite(_asTape); - } else if (which == 3) { - // Klaymen returning from window - insertKlaymen(534, 440); - setMessageList(0x004AFC30); - sendMessage(this, 0x2000, 0); - addCollisionSprite(_asTape); - } else if (which == 4) { - // Klaymen teleporting out - insertKlaymen(136, 440); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004AFC38); - sendMessage(this, 0x2000, 1); - addCollisionSprite(_asTape); - } else if (which == 5) { - // Klaymen returning from teleporter - insertKlaymen(136, 440); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004AFB00); - sendMessage(this, 0x2000, 1); - addCollisionSprite(_asTape); - } else { - // Klaymen coming up in elevator - insertKlaymen(286, 408); - setSurfacePriority(_asElevator->getSurface(), 1100); - setSurfacePriority(_asElevatorDoor->getSurface(), 1090); - setSurfacePriority(_sprite1->getSurface(), 1080); - sendMessage(this, 0x2000, 0); - SetMessageHandler(&Scene1306::handleMessage416EB0); - clearRectList(); - sendMessage(_asElevator, 0x4808, 0); - } - -} - -Scene1306::~Scene1306() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); -} - -uint32 Scene1306::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x402064D8) - sendEntityMessage(_klaymen, 0x1014, _ssButton); - else if (param.asInteger() == 0x01C66840) { - if (sendMessage(_asElevator, 0x2001, 0) != 0) - setMessageList(0x004AFBD8); - else - setMessageList(0x004AFAE0); - } else if (param.asInteger() == 0x8E646E00) { - setMessageList(0x004AFAD8); - clearRectList(); - SetMessageHandler(&Scene1306::handleMessage416EB0); - } - break; - case 0x2000: - if (param.asInteger() != 0) { - setRectList(0x004AFD28); - _klaymen->setKlaymenIdleTable3(); - } else { - setRectList(0x004AFD18); - _klaymen->setKlaymenIdleTable1(); - } - break; - case 0x480B: - if (sender == _ssButton) - sendMessage(_asElevator, 0x4808, 0); - break; - case 0x4826: - if (sender == _asKey) { - if (_klaymen->getX() >= 249) { - sendEntityMessage(_klaymen, 0x1014, _asKey); - setMessageList(0x004AFC58); - } - } else if (sender == _asTape) { - if (_klaymen->getX() >= 249) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004AFC68); - } - } - break; - case 0x482A: - setSurfacePriority(_asElevator->getSurface(), 1100); - setSurfacePriority(_asElevatorDoor->getSurface(), 1090); - setSurfacePriority(_sprite1->getSurface(), 1080); - break; - case 0x482B: - setSurfacePriority(_asElevator->getSurface(), 100); - setSurfacePriority(_asElevatorDoor->getSurface(), 90); - setSurfacePriority(_sprite1->getSurface(), 80); - sendMessage(this, 0x2000, 0); - addCollisionSprite(_asTape); - break; - } - return 0; -} - -uint32 Scene1306::handleMessage416EB0(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4808: - setMessageList(0x004AFBD0); - SetMessageHandler(&Scene1306::handleMessage); - break; - case 0x4809: - leaveScene(1); - break; - case 0x482A: - setSurfacePriority(_asElevator->getSurface(), 1100); - setSurfacePriority(_asElevatorDoor->getSurface(), 1090); - setSurfacePriority(_sprite1->getSurface(), 1080); - break; - case 0x482B: - setSurfacePriority(_asElevator->getSurface(), 100); - setSurfacePriority(_asElevatorDoor->getSurface(), 90); - setSurfacePriority(_sprite1->getSurface(), 80); - sendMessage(this, 0x2000, 0); - addCollisionSprite(_asTape); - break; - } - return 0; -} - -static const uint32 kAsScene1307KeyResourceList1[] = { - 0x0438069C, 0x45B0023C, 0x05700217 -}; - -static const uint32 kAsScene1307KeyResourceList2[] = { - 0x04441334, 0x061433F0, 0x06019390 -}; - -static const uint32 kAsScene1307KeyResourceList3[] = { - 0x11A80030, 0x178812B1, 0x1488121C -}; - -static const uint32 *kAsScene1307KeyResourceLists[] = { - kAsScene1307KeyResourceList1, - kAsScene1307KeyResourceList2, - kAsScene1307KeyResourceList3 -}; - -static const int kAsScene1307KeySurfacePriorities[] = { - 700, 500, 300, 100 -}; - -const uint kAsScene1307KeyPointsCount = 12; - -static const NPoint kAsScene1307KeyPoints[] = { - {-2, 0}, {-5, 0}, { 5, 0}, - {12, 0}, {17, 0}, {25, 0}, - {16, -2}, {10, -6}, { 0, -7}, - {-7, -3}, {-3, 4}, { 2, 2} -}; - -const uint kAsScene1307KeyFrameIndicesCount = 20; - -static const int16 kAsScene1307KeyFrameIndices[] = { - 1, 4, 8, 11, 15, 16, 17, 17, 17, 16, - 15, 14, 12, 10, 9, 7, 5, 3, 2, 1 -}; - -const int kAsScene1307KeyDivValue = 200; -const int16 kAsScene1307KeyXDelta = 70; -const int16 kAsScene1307KeyYDelta = -12; - -AsScene1307Key::AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _keyIndex(keyIndex), _clipRects(clipRects), - _isClickable(true) { - - NPoint pt; - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; - - _dataResource.load(0x22102142); - _pointList = _dataResource.getPointArray(0xAC849240); - pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; - _x = pt.x; - _y = pt.y; - createSurface(kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4], 190, 148); - startAnimation(fileHashes[0], 0, -1); - loadSound(0, 0xDC4A1280); - loadSound(1, 0xCC021233); - loadSound(2, 0xC4C23844); - loadSound(3, 0xC4523208); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1307Key::handleMessage); -} - -uint32 AsScene1307Key::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_isClickable) { - sendMessage(_parentScene, 0x4826, 0); - stRemoveKey(); - messageResult = 1; - } - break; - case 0x2000: - _isClickable = param.asInteger() != 0; - break; - case 0x2001: - setSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex, param.asInteger()); - stMoveKey(); - break; - case 0x2003: - playSound(3); - stUnlock(); - break; - case 0x2004: - playSound(2); - stInsert(); - break; - } - return messageResult; -} - -void AsScene1307Key::suRemoveKey() { - if (_pointIndex < kAsScene1307KeyPointsCount) { - _x += kAsScene1307KeyPoints[_pointIndex].x; - _y += kAsScene1307KeyPoints[_pointIndex].y; - updateBounds(); - _pointIndex++; - } else { - SetSpriteUpdate(NULL); - } -} - -void AsScene1307Key::suInsertKey() { - if (_pointIndex < kAsScene1307KeyPointsCount) { - _x -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].x; - _y -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].y; - updateBounds(); - _pointIndex++; - if (_pointIndex == 7) - playSound(0); - } else { - SetSpriteUpdate(NULL); - sendMessage(_parentScene, 0x2002, 0); - } -} - -void AsScene1307Key::suMoveKey() { - if (_pointIndex < kAsScene1307KeyFrameIndicesCount) { - _frameIndex += kAsScene1307KeyFrameIndices[_pointIndex]; - _x = _prevX + (_deltaX * _frameIndex) / kAsScene1307KeyDivValue; - _y = _prevY + (_deltaY * _frameIndex) / kAsScene1307KeyDivValue; - updateBounds(); - _pointIndex++; - } else { - NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; - _x = pt.x + kAsScene1307KeyXDelta; - _y = pt.y + kAsScene1307KeyYDelta; - stInsertKey(); - } -} - -void AsScene1307Key::stRemoveKey() { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; - _pointIndex = 0; - startAnimation(fileHashes[0], 0, -1); - playSound(1); - SetSpriteUpdate(&AsScene1307Key::suRemoveKey); -} - -void AsScene1307Key::stInsertKey() { - _pointIndex = 0; - sendMessage(_parentScene, 0x1022, kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]); - setClipRect(_clipRects[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]); - _newStickFrameIndex = STICK_LAST_FRAME; - SetSpriteUpdate(&AsScene1307Key::suInsertKey); -} - -void AsScene1307Key::stMoveKey() { - NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; - int16 newX = pt.x + kAsScene1307KeyXDelta; - int16 newY = pt.y + kAsScene1307KeyYDelta; - sendMessage(_parentScene, 0x1022, 1000); - setClipRect(0, 0, 640, 480); - _prevX = _x; - _prevY = _y; - if (newX == _x && newY == _y) { - stInsertKey(); - } else { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; - _pointIndex = 0; - _frameIndex = 0; - _deltaX = newX - _x; - _deltaY = newY - _y; - startAnimation(fileHashes[0], 0, -1); - SetSpriteUpdate(&AsScene1307Key::suMoveKey); - } -} - -void AsScene1307Key::stUnlock() { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; - startAnimation(fileHashes[1], 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; -} - -void AsScene1307Key::stInsert() { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; - startAnimation(fileHashes[2], 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; -} - -Scene1307::Scene1307(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule), _countdown(0), _asCurrKey(NULL), - _isInsertingKey(false), _doLeaveScene(false), _isPuzzleSolved(false) { - - Sprite *tempSprite; - - _vm->gameModule()->initKeySlotsPuzzle(); - - _dataResource.load(0x22102142); - _keyHolePoints = _dataResource.getPointArray(0xAC849240); - - for (uint i = 0; i < 16; i++) { - NPoint pt = (*_keyHolePoints)[i]; - _keyHoleRects[i].x1 = pt.x - 15; - _keyHoleRects[i].y1 = pt.y - 15; - _keyHoleRects[i].x2 = pt.x + 15; - _keyHoleRects[i].y2 = pt.y + 15; - } - - SetMessageHandler(&Scene1307::handleMessage); - SetUpdateHandler(&Scene1307::update); - - setBackground(0xA8006200); - setPalette(0xA8006200); - addEntity(_palette); - insertPuzzleMouse(0x06204A88, 20, 620); - - tempSprite = insertStaticSprite(0x00A3621C, 800); - _clipRects[0].set(tempSprite->getDrawRect().x, 0, 640, 480); - tempSprite = insertStaticSprite(0x00A3641C, 600); - _clipRects[1].set(tempSprite->getDrawRect().x, 0, 640, 480); - tempSprite = insertStaticSprite(0x00A3681C, 400); - _clipRects[2].set(tempSprite->getDrawRect().x, 0, 640, 480); - tempSprite = insertStaticSprite(0x00A3701C, 200); - _clipRects[3].set(tempSprite->getDrawRect().x, 0, 640, 480); - - for (uint keyIndex = 0; keyIndex < 3; keyIndex++) { - if (getSubVar(VA_IS_KEY_INSERTED, keyIndex)) { - _asKeys[keyIndex] = insertSprite(this, keyIndex, _clipRects); - addCollisionSprite(_asKeys[keyIndex]); - } else { - _asKeys[keyIndex] = NULL; - } - } - - loadSound(0, 0x68E25540); - -} - -void Scene1307::update() { - Scene::update(); - if (_countdown && (--_countdown == 0)) - _doLeaveScene = true; - else if (_countdown == 20) - _palette->startFadeToWhite(40); - if (_doLeaveScene && !isSoundPlaying(0)) { - leaveScene(1); - setGlobalVar(V_KEYDOOR_UNLOCKED, 1); - } -} - -uint32 Scene1307::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = 0; - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (!_isPuzzleSolved) { - if (param.asPoint().x > 20 && param.asPoint().x < 620) { - if (_asCurrKey && !_isInsertingKey) { - int16 mouseX = param.asPoint().x; - int16 mouseY = param.asPoint().y; - uint clickedKeyHoleIndex; - for (clickedKeyHoleIndex = 0; clickedKeyHoleIndex < 16; clickedKeyHoleIndex++) { - if (mouseX >= _keyHoleRects[clickedKeyHoleIndex].x1 && mouseX <= _keyHoleRects[clickedKeyHoleIndex].x2 && - mouseY >= _keyHoleRects[clickedKeyHoleIndex].y1 && mouseY <= _keyHoleRects[clickedKeyHoleIndex].y2) - break; - } - if (clickedKeyHoleIndex < 16) { - // Check if the clicked keyhole is already occupied with a key - bool occupied = false; - for (uint keyIndex = 0; keyIndex < 3 && !occupied; keyIndex++) { - if (getSubVar(VA_IS_KEY_INSERTED, keyIndex) && _asKeys[keyIndex] != _asCurrKey) { - if (getSubVar(VA_CURR_KEY_SLOT_NUMBERS, keyIndex) == clickedKeyHoleIndex) - occupied = true; - } - } - if (!occupied) { - // If the keyhole is free, insert the current key - sendMessage(_asCurrKey, 0x2001, clickedKeyHoleIndex); - _isInsertingKey = true; - _mouseClicked = false; - } - } - } - } else if (_countdown == 0 && !_asCurrKey && !_isInsertingKey) - leaveScene(0); - } - break; - case 0x2002: - // Check if all keys are in the correct keyholes - if (getSubVar(VA_IS_KEY_INSERTED, 0) && getSubVar(VA_CURR_KEY_SLOT_NUMBERS, 0) == getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 0) && - getSubVar(VA_IS_KEY_INSERTED, 1) && getSubVar(VA_CURR_KEY_SLOT_NUMBERS, 1) == getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 1) && - getSubVar(VA_IS_KEY_INSERTED, 2) && getSubVar(VA_CURR_KEY_SLOT_NUMBERS, 2) == getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 2)) { - // Play unlock animations for all keys - for (uint keyIndex = 0; keyIndex < 3; keyIndex++) { - if (_asKeys[keyIndex]) - sendMessage(_asKeys[keyIndex], 0x2003, 1); - } - playSound(0); - _isPuzzleSolved = true; - _countdown = 47; - } else { - for (uint keyIndex = 0; keyIndex < 3; keyIndex++) - if (getSubVar(VA_IS_KEY_INSERTED, keyIndex) && _asKeys[keyIndex]) - sendMessage(_asKeys[keyIndex], 0x2000, 1); - sendMessage(_asCurrKey, 0x2004, 1); - } - _asCurrKey = NULL; - _isInsertingKey = false; - break; - case 0x4826: - _asCurrKey = (Sprite*)sender; - for (uint keyIndex = 0; keyIndex < 3; keyIndex++) - if (getSubVar(VA_IS_KEY_INSERTED, keyIndex) && _asKeys[keyIndex]) - sendMessage(_asKeys[keyIndex], 0x2000, 0); - break; - } - return messageResult; -} - -static const uint32 kScene1308NumberFileHashes[] = { - 0x08006320, 0x10006320, 0x20006320, - 0x40006320, 0x80006320, 0x00006321, - 0x00006322, 0x00006324, 0x00006328, - 0x08306320, 0x10306320, 0x20306320, - 0x40306320, 0x80306320, 0x00306321, - 0x00306322 -}; - -AsScene1308JaggyDoor::AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 0xBA0AE050, 1100, 320, 240), _parentScene(parentScene) { - - setVisible(false); - stopAnimation(); - SetMessageHandler(&AsScene1308JaggyDoor::handleMessage); -} - -uint32 AsScene1308JaggyDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - case 0x4808: - stOpenDoor(); - break; - case 0x4809: - stCloseDoor(); - break; - } - return messageResult; -} - -void AsScene1308JaggyDoor::stOpenDoor() { - startAnimation(0xBA0AE050, 0, -1); - setVisible(true); - playSound(0, calcHash("fxDoorOpen38")); - NextState(&AsScene1308JaggyDoor::stOpenDoorDone); -} - -void AsScene1308JaggyDoor::stOpenDoorDone() { - sendMessage(_parentScene, 0x2000, 0); - stopAnimation(); - setVisible(false); -} - -void AsScene1308JaggyDoor::stCloseDoor() { - startAnimation(0xBA0AE050, -1, -1); - _playBackwards = true; - setVisible(true); - playSound(0, calcHash("fxDoorClose38")); - NextState(&AsScene1308JaggyDoor::stCloseDoorDone); -} - -void AsScene1308JaggyDoor::stCloseDoorDone() { - sendMessage(_parentScene, 0x2001, 0); - stopAnimation(); -} - -AsScene1308KeyboardDoor::AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 0xA08A0851, 1100, 320, 240), _parentScene(parentScene) { - - playSound(0, 0x51456049); - SetMessageHandler(&AsScene1308KeyboardDoor::handleMessage); - NextState(&AsScene1308KeyboardDoor::stFallingKeys); -} - -uint32 AsScene1308KeyboardDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1308KeyboardDoor::stFallingKeys() { - startAnimation(0x6238B191, 0, -1); - _x = 580; - _y = 383; - NextState(&AsScene1308KeyboardDoor::stFallingKeysDone); -} - -void AsScene1308KeyboardDoor::stFallingKeysDone() { - sendMessage(_parentScene, 0x2004, 0); - stopAnimation(); - setVisible(false); -} - -AsScene1308LightWallSymbols::AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 0x80180A10, 100, 320, 240), _parentScene(parentScene) { - - setVisible(false); - stopAnimation(); - Entity::_priority = 1200; - SetMessageHandler(&AsScene1308LightWallSymbols::handleMessage); -} - -uint32 AsScene1308LightWallSymbols::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2002: - stFadeIn(); - break; - case 0x2003: - stFadeOut(); - break; - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1308LightWallSymbols::stFadeIn() { - startAnimation(0x80180A10, 0, -1); - setVisible(true); - _newStickFrameIndex = STICK_LAST_FRAME; -} - -void AsScene1308LightWallSymbols::stFadeOut() { - startAnimation(0x80180A10, -1, -1); - _playBackwards = true; - NextState(&AsScene1308LightWallSymbols::stFadeOutDone); -} - -void AsScene1308LightWallSymbols::stFadeOutDone() { - sendMessage(_parentScene, 0x2003, 0); - stopAnimation(); - setVisible(false); -} - -SsScene1308Number::SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index) - : StaticSprite(vm, fileHash, 100) { - - setVisible(false); - _x = _spriteResource.getPosition().x + index * 20; - updatePosition(); -} - -AsScene1308Mouse::AsScene1308Mouse(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100) { - - _x = 286; - _y = 429; - createSurface1(0xA282C472, 100); - startAnimation(0xA282C472, 0, -1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1308Mouse::handleMessage); -} - -uint32 AsScene1308Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x66382026) - playSound(0, 0x0CD84468); - else if (param.asInteger() == 0x6E28061C) - playSound(0, 0x78C8402C); - else if (param.asInteger() == 0x462F0410) - playSound(0, 0x60984E28); - break; - } - return messageResult; -} - -Scene1308::Scene1308(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _isProjecting(false), _asProjector(NULL) { - - _vm->gameModule()->initKeySlotsPuzzle(); - - SetMessageHandler(&Scene1308::handleMessage); - - setBackground(0x41024202); - setPalette(0x41024202); - insertScreenMouse(0x24206418); - - _asTape = insertSprite(this, 17, 1100, 502, 445, 0x9148A011); - addCollisionSprite(_asTape); - - if (getGlobalVar(V_MOUSE_SUCKED_IN)) { - insertSprite(); - insertSprite(0x461A1490, 200, 235, 429); - } - - _sprite1 = insertStaticSprite(0x0A042060, 1100); - _asJaggyDoor = insertSprite(this); - _asLightWallSymbols = insertSprite(this); - _ssNumber1 = insertSprite(kScene1308NumberFileHashes[getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 1)], 0); - _ssNumber2 = insertSprite(kScene1308NumberFileHashes[getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 0)], 1); - _ssNumber3 = insertSprite(kScene1308NumberFileHashes[getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 2)], 2); - _sprite2 = insertStaticSprite(0x40043120, 995); - _sprite3 = insertStaticSprite(0x43003100, 995); - _sprite4 = NULL; - - if (which < 0) { - // Restoring game - insertKlaymen(380, 440); - setMessageList(0x004B57C0); - if (getGlobalVar(V_KEYDOOR_UNLOCKED)) { - _sprite4 = insertStaticSprite(0x0101A624, 1100); - setRectList(0x004B5990); - } else { - _sprite5 = insertStaticSprite(0x080811A0, 100); - setRectList(0x004B5980); - } - } else if (which == 1) { - // Klaymen entering from the right - insertKlaymen(640, 440); - setMessageList(0x004B57C8); - if (getGlobalVar(V_KEYDOOR_UNLOCKED)) { - _sprite4 = insertStaticSprite(0x0101A624, 1100); - setRectList(0x004B5990); - } else { - _sprite5 = insertStaticSprite(0x080811A0, 100); - setRectList(0x004B5980); - } - } else if (which == 2) { - // Klaymen returning from keyslots panel - insertKlaymen(475, 440); - setMessageList(0x004B58B0); - if (getGlobalVar(V_KEYDOOR_UNLOCKED)) { - _sprite5 = insertSprite(this); - _sprite4 = insertStaticSprite(0x0101A624, 1100); - _sprite4->setVisible(false); - } else { - _sprite5 = insertStaticSprite(0x080811A0, 100); - setRectList(0x004B5980); - } - } else { - // Klaymen entering from the left - insertKlaymen(41, 440); - setMessageList(0x004B57D0); - sendMessage(_asJaggyDoor, 0x4808, 0); - _sprite1->setVisible(false); - if (getGlobalVar(V_KEYDOOR_UNLOCKED)) { - _sprite4 = insertStaticSprite(0x0101A624, 1100); - _klaymen->setVisible(false); - } else { - _sprite5 = insertStaticSprite(0x080811A0, 100); - _klaymen->setVisible(false); - } - } - - if (_sprite4) - _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite4->getDrawRect().x2(), 480); - else - _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); - - if (getGlobalVar(V_PROJECTOR_LOCATION) == 4) { - _asProjector = insertSprite(this, _klaymen, (Sprite*)NULL); - addCollisionSprite(_asProjector); - _asProjector->setClipRect(0, 0, 640, _sprite2->getDrawRect().y2()); - _asProjector->setRepl(64, 0); - } - -} - -uint32 Scene1308::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x88C11390) { - setRectList(0x004B59A0); - _isProjecting = true; - } else if (param.asInteger() == 0x08821382) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - if (getGlobalVar(V_KEYDOOR_UNLOCKED)) - setRectList(0x004B5990); - else - setRectList(0x004B5980); - _isProjecting = false; - } else if (param.asInteger() == 0x4AC68808) { - clearRectList(); - sendMessage(_asJaggyDoor, 0x4809, 0); - _sprite1->setVisible(false); - _klaymen->setVisible(false); - } - break; - case 0x1022: - if (sender == _asProjector) { - if (param.asInteger() >= 1000) - setSurfacePriority(_sprite3->getSurface(), 1100); - else - setSurfacePriority(_sprite3->getSurface(), 995); - } - break; - case 0x2000: - if (getGlobalVar(V_KEYDOOR_UNLOCKED)) - setRectList(0x004B5990); - else - setRectList(0x004B5980); - setMessageList(0x004B57E8, false); - _sprite1->setVisible(true); - _klaymen->setVisible(true); - break; - case 0x2001: - leaveScene(0); - break; - case 0x2003: - _ssNumber1->setVisible(false); - _ssNumber2->setVisible(false); - _ssNumber3->setVisible(false); - break; - case 0x2004: - _sprite4->setVisible(true); - setRectList(0x004B5990); - break; - case 0x4807: - sendMessage(_asLightWallSymbols, 0x2003, 0); - break; - case 0x480F: - sendMessage(_asLightWallSymbols, 0x2002, 0); - _ssNumber1->setVisible(true); - _ssNumber2->setVisible(true); - _ssNumber3->setVisible(true); - break; - case 0x4826: - if (sender == _asProjector) { - if (_isProjecting) - setMessageList2(0x004B5868); - else { - if (param.asInteger() == 1) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - setMessageList2(0x004B5848); - } else if (sendMessage(_asProjector, 0x480C, _klaymen->getX() <= _asProjector->getX() ? 0 : 1) != 0) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - setMessageList2(0x004B5830); - } else - setMessageList2(0x004B5800); - } - } else if (sender == _asTape) { - if (_isProjecting) - setMessageList2(0x004B5868); - else if (_messageListStatus != 2) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList2(0x004B58E0); - } - } - break; - } - return 0; -} - -Scene1317::Scene1317(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule) { - - SetMessageHandler(&Scene1317::handleMessage); - _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, 0x08982841, true, false)); - _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); - insertScreenMouse(0x08284011); - showMouse(false); - _smackerFileHash = 0; - _keepLastSmackerFrame = false; -} - -void Scene1317::update() { - if (_smackerFileHash) { - _smackerPlayer->open(_smackerFileHash, _keepLastSmackerFrame); - _smackerFileHash = 0; - } - Scene::update(); -} - -void Scene1317::upChooseKing() { - if (!_klaymenBlinks && _klaymenBlinkCountdown != 0 && (--_klaymenBlinkCountdown == 0)) - _klaymenBlinks = true; - - if (!_klaymenBlinks && _smackerPlayer->getFrameNumber() + 1 >= 2) { - _smackerPlayer->rewind(); - } else if (_klaymenBlinks && _smackerPlayer->getFrameNumber() + 1 >= 6) { - _smackerPlayer->rewind(); - _klaymenBlinks = false; - _klaymenBlinkCountdown = _vm->_rnd->getRandomNumber(30 - 1) + 15; - } - - if (!_klaymenBlinks && _decisionCountdown != 0 && (--_decisionCountdown == 0)) - stNoDecisionYet(); - - if (_smackerFileHash) { - _smackerPlayer->open(_smackerFileHash, _keepLastSmackerFrame); - _smackerFileHash = 0; - } - - Scene::update(); - -} - -uint32 Scene1317::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - stChooseKing(); - break; - } - return messageResult; -} - -uint32 Scene1317::hmChooseKing(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x >= 21 && param.asPoint().y >= 24 && - param.asPoint().x <= 261 && param.asPoint().y <= 280) { - stHoborgAsKing(); - } else if (param.asPoint().x >= 313 && param.asPoint().y >= 184 && - param.asPoint().x <= 399 && param.asPoint().y <= 379) { - stKlaymenAsKing(); - } else if (param.asPoint().x >= 347 && param.asPoint().y >= 380 && - param.asPoint().x <= 418 && param.asPoint().y <= 474) { - stKlaymenAsKing(); - } - break; - } - return messageResult; -} - -uint32 Scene1317::hmHoborgAsKing(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - stEndMovie(); - break; - } - return messageResult; -} - -uint32 Scene1317::hmEndMovie(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - leaveScene(0); - break; - } - return messageResult; -} - -void Scene1317::stChooseKing() { - showMouse(true); - _smackerFileHash = 0x10982841; - _keepLastSmackerFrame = true; - _decisionCountdown = 450; - _klaymenBlinks = false; - _klaymenBlinkCountdown = _vm->_rnd->getRandomNumber(30 - 1) + 15; - SetMessageHandler(&Scene1317::hmChooseKing); - SetUpdateHandler(&Scene1317::upChooseKing); -} - -void Scene1317::stNoDecisionYet() { - showMouse(false); - _smackerFileHash = 0x20982841; - _keepLastSmackerFrame = false; - SetMessageHandler(&Scene1317::handleMessage); - SetUpdateHandler(&Scene1317::update); -} - -void Scene1317::stHoborgAsKing() { - showMouse(false); - _smackerFileHash = 0x40982841; - _keepLastSmackerFrame = false; - SetMessageHandler(&Scene1317::hmHoborgAsKing); - SetUpdateHandler(&Scene1317::update); -} - -void Scene1317::stKlaymenAsKing() { - showMouse(false); - _smackerFileHash = 0x80982841; - _keepLastSmackerFrame = false; - SetMessageHandler(&Scene1317::hmEndMovie); - SetUpdateHandler(&Scene1317::update); -} - -void Scene1317::stEndMovie() { - showMouse(false); - _smackerFileHash = 0x40800711; - _keepLastSmackerFrame = false; - SetMessageHandler(&Scene1317::hmEndMovie); - SetUpdateHandler(&Scene1317::update); -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module1300.h b/engines/neverhood/module1300.h deleted file mode 100644 index 147bfd0645..0000000000 --- a/engines/neverhood/module1300.h +++ /dev/null @@ -1,295 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE1300_H -#define NEVERHOOD_MODULE1300_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/smackerplayer.h" - -namespace Neverhood { - -// Module1300 - -class Module1300 : public Module { -public: - Module1300(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module1300(); -protected: - int _sceneNum; - uint32 _musicFileHash; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -class AsScene1302Bridge : public AnimatedSprite { -public: - AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stLowerBridge(); - void stRaiseBridge(); - void cbLowerBridgeEvent(); -}; - -class SsScene1302Fence : public StaticSprite { -public: - SsScene1302Fence(NeverhoodEngine *vm); -protected: - int16 _firstY; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suMoveDown(); - void suMoveUp(); -}; - -class Scene1302 : public Scene { -public: - Scene1302(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_asVenusFlyTrap; - Sprite *_asBridge; - Sprite *_ssFence; - Sprite *_asRing1; - Sprite *_asRing2; - Sprite *_asRing3; - Sprite *_asRing4; - Sprite *_asRing5; - Sprite *_class595; - Sprite *_sprite1; - Sprite *_sprite2; - Sprite *_sprite3; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1303Balloon : public AnimatedSprite { -public: - AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmBalloonPopped(int messageNum, const MessageParam ¶m, Entity *sender); - void stPopBalloon(); -}; - -class Scene1303 : public Scene { -public: - Scene1303(NeverhoodEngine *vm, Module *parentModule); -protected: - Sprite *_sprite1; - Sprite *_asBalloon; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1304Needle : public AnimatedSprite { -public: - AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene1304 : public Scene { -public: - Scene1304(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_sprite1; - Sprite *_asKey; - Sprite *_asNeedle; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene1305 : public Scene { -public: - Scene1305(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1306Elevator : public AnimatedSprite { -public: - AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor); -protected: - Scene *_parentScene; - AnimatedSprite *_asElevatorDoor; - bool _isUp; - bool _isDown; - int _countdown; - void update(); - void upGoingDown(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stGoingUp(); - void cbGoingUpEvent(); - void stGoingDown(); - void cbGoingDownEvent(); -}; - -class Scene1306 : public Scene { -public: - Scene1306(NeverhoodEngine *vm, Module *parentModule, int which); - ~Scene1306(); -protected: - Sprite *_ssButton; - Sprite *_asTape; - AnimatedSprite *_asElevatorDoor; - Sprite *_asElevator; - Sprite *_sprite1; - Sprite *_asKey; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 handleMessage416EB0(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1307Key : public AnimatedSprite { -public: - AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects); -protected: - Scene *_parentScene; - NPointArray *_pointList; - uint _pointIndex; - int _frameIndex; - uint _keyIndex; - NRect *_clipRects; - bool _isClickable; - int16 _prevX, _prevY; - int16 _deltaX, _deltaY; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suRemoveKey(); - void suInsertKey(); - void suMoveKey(); - void stRemoveKey(); - void stInsertKey(); - void stMoveKey(); - void stUnlock(); - void stInsert(); -}; - -class Scene1307 : public Scene { -public: - Scene1307(NeverhoodEngine *vm, Module *parentModule); -protected: - NPointArray *_keyHolePoints; - NRect _keyHoleRects[16]; - NRect _clipRects[4]; - Sprite *_asKeys[3]; - int _countdown; - Sprite *_asCurrKey; - bool _isInsertingKey; - bool _doLeaveScene; - bool _isPuzzleSolved; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene1308JaggyDoor : public AnimatedSprite { -public: - AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stOpenDoor(); - void stOpenDoorDone(); - void stCloseDoor(); - void stCloseDoorDone(); -}; - -class AsScene1308KeyboardDoor : public AnimatedSprite { -public: - AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stFallingKeys(); - void stFallingKeysDone(); -}; - -class AsScene1308LightWallSymbols : public AnimatedSprite { -public: - AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stFadeIn(); - void stFadeOut(); - void stFadeOutDone(); -}; - -class SsScene1308Number : public StaticSprite { -public: - SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index); -}; - -class AsScene1308Mouse : public AnimatedSprite { -public: - AsScene1308Mouse(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene1308 : public Scene { -public: - Scene1308(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_asTape; - Sprite *_asJaggyDoor; - Sprite *_asLightWallSymbols; - Sprite *_ssNumber1; - Sprite *_ssNumber2; - Sprite *_ssNumber3; - AnimatedSprite *_asProjector; - Sprite *_sprite1; - Sprite *_sprite2; - Sprite *_sprite3; - Sprite *_sprite4; - Sprite *_sprite5; - bool _isProjecting; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene1317 : public Scene { -public: - Scene1317(NeverhoodEngine *vm, Module *parentModule); -protected: - SmackerPlayer *_smackerPlayer; - bool _klaymenBlinks; - int _klaymenBlinkCountdown; - int _decisionCountdown; - uint32 _smackerFileHash; - bool _keepLastSmackerFrame; - void update(); - void upChooseKing(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmChooseKing(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmHoborgAsKing(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmEndMovie(int messageNum, const MessageParam ¶m, Entity *sender); - void stChooseKing(); - void stNoDecisionYet(); - void stHoborgAsKing(); - void stKlaymenAsKing(); - void stEndMovie(); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE1300_H */ diff --git a/engines/neverhood/module1400.cpp b/engines/neverhood/module1400.cpp deleted file mode 100644 index 8aa0632e90..0000000000 --- a/engines/neverhood/module1400.cpp +++ /dev/null @@ -1,1621 +0,0 @@ -/* 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/module1400.h" -#include "neverhood/module1000.h" -#include "neverhood/module2100.h" -#include "neverhood/module2200.h" -#include "neverhood/diskplayerscene.h" -#include "neverhood/gamemodule.h" - -namespace Neverhood { - -Module1400::Module1400(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - _vm->_soundMan->addMusic(0x00AD0012, 0x06333232); - _vm->_soundMan->addMusic(0x00AD0012, 0x624A220E); - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else - createScene(0, 0); - -} - -Module1400::~Module1400() { - _vm->_soundMan->deleteMusicGroup(0x00AD0012); -} - -void Module1400::createScene(int sceneNum, int which) { - debug("Module1400::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _vm->_soundMan->startMusic(0x06333232, 0, 2); - _childObject = new Scene1401(_vm, this, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - _vm->_soundMan->stopMusic(0x06333232, 0, 2); - _vm->_soundMan->stopMusic(0x624A220E, 0, 2); - _childObject = new Scene1402(_vm, this, which); - break; - case 2: - _vm->gameState().sceneNum = 2; - _vm->_soundMan->stopMusic(0x06333232, 0, 2); - _vm->_soundMan->startMusic(0x624A220E, 0, 2); - _childObject = new Scene1403(_vm, this, which); - break; - case 3: - _vm->gameState().sceneNum = 3; - _vm->_soundMan->startMusic(0x06333232, 0, 2); - _childObject = new Scene1404(_vm, this, which); - break; - case 4: - _vm->gameState().sceneNum = 4; - _vm->_soundMan->startMusic(0x06333232, 0, 2); - _childObject = new Scene1405(_vm, this); - break; - case 5: - _vm->gameState().sceneNum = 5; - _vm->_soundMan->stopMusic(0x06333232, 0, 2); - _childObject = new DiskplayerScene(_vm, this, 2); - break; - case 6: - _vm->gameState().sceneNum = 6; - _vm->_soundMan->stopMusic(0x06333232, 0, 2); - _childObject = new Scene1407(_vm, this); - break; - } - SetUpdateHandler(&Module1400::updateScene); - _childObject->handleUpdate(); -} - -void Module1400::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 1) - createScene(1, 0); - else if (_moduleResult == 2) - createScene(3, 0); - else - leaveModule(0); - break; - case 1: - if (_moduleResult == 1) - createScene(2, 0); - else if (_moduleResult == 2) - createScene(6, -1); - else - createScene(0, 1); - break; - case 2: - createScene(1, 1); - break; - case 3: - if (_moduleResult == 1) - createScene(4, 0); - else if (_moduleResult == 2) - createScene(5, -1); - else - createScene(0, 2); - break; - case 4: - createScene(3, 1); - break; - case 5: - createScene(3, 2); - break; - case 6: - createScene(1, 2); - break; - } - } -} - -// Scene1401 - -AsScene1401Pipe::AsScene1401Pipe(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100), _countdown1(0), _countdown2(0) { - - createSurface(900, 152, 147); - _x = 454; - _y = 217; - startAnimation(0x4C210500, 0, -1); - SetUpdateHandler(&AsScene1401Pipe::update); - SetMessageHandler(&AsScene1401Pipe::handleMessage); -} - -AsScene1401Pipe::~AsScene1401Pipe() { - _vm->_soundMan->deleteSoundGroup(0x01104C08); -} - -void AsScene1401Pipe::update() { - AnimatedSprite::update(); - if (_countdown1 != 0 && (--_countdown1 == 0)) - stDoneSucking(); - if (_countdown2 != 0 && (--_countdown2 == 0)) { - _vm->_soundMan->addSound(0x01104C08, 0x4A116437); - _vm->_soundMan->playSoundLooping(0x4A116437); - } -} - -void AsScene1401Pipe::upSuckInProjector() { - AnimatedSprite::update(); - if (_countdown1 != 0) - _countdown1--; -} - -uint32 AsScene1401Pipe::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x0A8A1490) - playSound(1, 0x6AB6666F); - break; - case 0x2000: - _countdown1 = 70; - _countdown2 = 8; - stStartSucking(); - break; - case 0x483A: - stSuckInProjector(); - break; - } - return messageResult; -} - -uint32 AsScene1401Pipe::hmSuckInProjector(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - if (_countdown1 != 0) - stStartSucking(); - else - stDoneSucking(); - SetMessageHandler(&AsScene1401Pipe::handleMessage); - SetUpdateHandler(&AsScene1401Pipe::update); - break; - } - return messageResult; -} - -void AsScene1401Pipe::stStartSucking() { - startAnimation(0x4C240100, 0, -1); - playSound(0, 0x4A30063F); -} - -void AsScene1401Pipe::stDoneSucking() { - _vm->_soundMan->deleteSound(0x4A116437); - playSound(0, 0x4A120435); - startAnimation(0x4C210500, 0, -1); -} - -void AsScene1401Pipe::stSuckInProjector() { - startAnimation(0x6C210810, 0, -1); - SetUpdateHandler(&AsScene1401Pipe::upSuckInProjector); - SetMessageHandler(&AsScene1401Pipe::hmSuckInProjector); -} - -AsScene1401Mouse::AsScene1401Mouse(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100) { - - createSurface(100, 71, 41); - _x = 478; - _y = 433; - startAnimation(0xA282C472, 0, -1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1401Mouse::handleMessage); -} - -uint32 AsScene1401Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x66382026) - playSound(0, 0x0CD84468); - else if (param.asInteger() == 0x6E28061C) - playSound(0, 0x78C8402C); - else if (param.asInteger() == 0x462F0410) - playSound(0, 0x60984E28); - break; - case 0x4839: - stSuckedIn(); - break; - } - return messageResult; -} - -void AsScene1401Mouse::suSuckedIn() { - AnimatedSprite::updateDeltaXY(); - if (_collisionBounds.y1 <= 150) { - playSound(0, 0x0E32247F); - stopAnimation(); - setVisible(false); - SetMessageHandler(NULL); - SetSpriteUpdate(NULL); - } -} - -void AsScene1401Mouse::stSuckedIn() { - startAnimation(0x34880040, 0, -1); - SetSpriteUpdate(&AsScene1401Mouse::suSuckedIn); -} - -AsScene1401Cheese::AsScene1401Cheese(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100) { - - createSurface(200, 152, 147); - _x = 427; - _y = 433; - startAnimation(0x461A1490, 0, -1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1401Cheese::handleMessage); -} - -uint32 AsScene1401Cheese::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4839: - stSuckedIn(); - break; - } - return messageResult; -} - -void AsScene1401Cheese::suSuckedIn() { - AnimatedSprite::updateDeltaXY(); - if (_collisionBounds.y1 <= 150) { - playSound(0, 0x18020439); - stopAnimation(); - setVisible(false); - SetMessageHandler(NULL); - SetSpriteUpdate(NULL); - } -} - -void AsScene1401Cheese::stSuckedIn() { - startAnimation(0x103B8020, 0, -1); - SetSpriteUpdate(&AsScene1401Cheese::suSuckedIn); -} - -AsScene1401BackDoor::AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen) - : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown(0), _isOpen(isOpen) { - - _x = 320; - _y = 240; - createSurface1(0x04551900, 100); - if (isOpen) { - startAnimation(0x04551900, -1, -1); - _countdown = 48; - } else { - stopAnimation(); - setVisible(false); - } - _newStickFrameIndex = STICK_LAST_FRAME; - SetUpdateHandler(&AsScene1401BackDoor::update); - SetMessageHandler(&AsScene1401BackDoor::handleMessage); -} - -void AsScene1401BackDoor::update() { - if (_countdown != 0 && (--_countdown == 0)) - stCloseDoor(); - AnimatedSprite::update(); -} - - -uint32 AsScene1401BackDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2001: - if (_isOpen) - _countdown = 168; - messageResult = _isOpen ? 1 : 0; - break; - case 0x3002: - gotoNextState(); - break; - case 0x4808: - _countdown = 168; - if (!_isOpen) - stOpenDoor(); - break; - } - return messageResult; -} - -void AsScene1401BackDoor::stOpenDoor() { - _isOpen = true; - setVisible(true); - startAnimation(0x04551900, 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - playSound(0, calcHash("fxDoorOpen24")); -} - -void AsScene1401BackDoor::stCloseDoor() { - _isOpen = false; - setVisible(true); - startAnimation(0x04551900, -1, -1); - playSound(0, calcHash("fxDoorClose24")); - _playBackwards = true; - NextState(&AsScene1401BackDoor::stCloseDoorDone); -} - -void AsScene1401BackDoor::stCloseDoorDone() { - stopAnimation(); - setVisible(false); -} - -static const AsCommonProjectorItem kAsCommonProjectorItems[] = { - {{154, 453}, 4, 2, 0, 0, 1}, - {{104, 391}, 4, -1, -1, 1, 1}, - {{ 22, 447}, 6, -1, -1, 1, 1}, - {{112, 406}, 2, -1, -1, 1, 0}, - {{262, 433}, 1, 1, 0, 0, 0} -}; - -AsCommonProjector::AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _klaymen(klaymen), _asPipe(asPipe) { - - _asProjectorItem = &kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)]; - createSurface(990, 101, 182); - startAnimation(0x10E3042B, 0, -1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsCommonProjector::handleMessage); - _x = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; - _lockedInSlot = true; - moveProjector(); - setDoDeltaX(1); - if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex) - stStayLockedInSlot(); - loadSound(2, 0xC8C2507C); -} - -AsCommonProjector::~AsCommonProjector() { - _vm->_soundMan->deleteSoundGroup(0x05331081); -} - -uint32 AsCommonProjector::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x4807: - setGlobalVar(V_PROJECTOR_SLOT, (_x - _asProjectorItem->point.x) / 108); - if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex) - stStartLockedInSlot(); - else - stIdle(); - break; - case 0x480B: - if (param.asInteger() != 1) { - if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount) - incGlobalVar(V_PROJECTOR_SLOT, 1); - } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0) - incGlobalVar(V_PROJECTOR_SLOT, -1); - stMoving(); - break; - case 0x480C: - // Check if the projector can be moved - if (param.asInteger() != 1) - messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0; - else - messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0; - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - case 0x4839: - stStartSuckedIn(); - break; - } - return messageResult; -} - -uint32 AsCommonProjector::hmLockedInSlot(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (param.asPoint().x - _x >= 17 && param.asPoint().x - _x <= 56 && - param.asPoint().y - _y >= -120 && param.asPoint().y - _y <= -82) { - sendMessage(_parentScene, 0x4826, 1); - } else - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x4807: - sendMessage(_parentScene, 0x4807, 0); - stStopProjecting(); - break; - case 0x480B: - if (param.asInteger() != 1) { - if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount) - incGlobalVar(V_PROJECTOR_SLOT, 1); - } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0) - incGlobalVar(V_PROJECTOR_SLOT, -1); - stTurnToFront(); - break; - case 0x480C: - // Check if the projector can be moved - if (param.asInteger() != 1) - messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0; - else - messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0; - break; - case 0x480F: - stStartProjecting(); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -uint32 AsCommonProjector::hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsCommonProjector::suMoving() { - if (_x <= _klaymen->getX()) - _x = _klaymen->getX() - 100; - else - _x = _klaymen->getX() + 100; - moveProjector(); - if (_beforeMoveX == _x) { - if (getGlobalVar(V_PROJECTOR_SLOT) == 0 && _asProjectorItem->leftBorderLeaves != 0) { - sendMessage(_parentScene, 0x1019, 0); - incGlobalVar(V_PROJECTOR_LOCATION, -1); - setGlobalVar(V_PROJECTOR_SLOT, kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)].maxSlotCount); - } else if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->maxSlotCount && _asProjectorItem->rightBorderLeaves != 0) { - sendMessage(_parentScene, 0x1019, 1); - incGlobalVar(V_PROJECTOR_LOCATION, +1); - setGlobalVar(V_PROJECTOR_SLOT, 0); - } - } - Sprite::updateBounds(); -} - -void AsCommonProjector::moveProjector() { - - bool nowLockedInSlot = false; - - _y = _asProjectorItem->point.y; - - if (_asProjectorItem->index1 != -1) { - int16 elX = _asProjectorItem->index1 * 108 + _asProjectorItem->point.x; - if (elX - 20 < _x && elX + 20 > _x) { - nowLockedInSlot = true; - _y = _asProjectorItem->point.y + 10; - } - } - - if (_asProjectorItem->lockSlotIndex != -1) { - int16 elX = _asProjectorItem->lockSlotIndex * 108 + _asProjectorItem->point.x; - if (elX - 20 < _x && elX + 20 > _x) { - nowLockedInSlot = true; - _y = _asProjectorItem->point.y + 10; - } - } - - if (_lockedInSlot && !nowLockedInSlot) - _lockedInSlot = false; - else if (!_lockedInSlot && nowLockedInSlot) { - playSound(1, 0x5440E474); - _lockedInSlot = true; - } - -} - -void AsCommonProjector::stSuckedIn() { - AnimatedSprite::updateDeltaXY(); - if (_collisionBounds.y1 <= 150) { - sendMessage(_asPipe, 0x483A, 0); - stopAnimation(); - setVisible(false); - SetMessageHandler(&Sprite::handleMessage); - SetSpriteUpdate(NULL); - } -} - -void AsCommonProjector::stIdle() { - startAnimation(0x10E3042B, 0, -1); - SetMessageHandler(&AsCommonProjector::handleMessage); - SetSpriteUpdate(NULL); -} - -void AsCommonProjector::stMoving() { - _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; - startAnimation(0x14A10137, 0, -1); - playSound(1, 0xEC008474); - SetMessageHandler(&AsCommonProjector::handleMessage); - SetSpriteUpdate(&AsCommonProjector::suMoving); -} - -void AsCommonProjector::stStartLockedInSlot() { - startAnimation(0x80C32213, 0, -1); - SetMessageHandler(&AsCommonProjector::hmAnimation); - SetSpriteUpdate(NULL); - NextState(&AsCommonProjector::stStayLockedInSlot); -} - -void AsCommonProjector::stStayLockedInSlot() { - startAnimation(0xD23B207F, 0, -1); - SetMessageHandler(&AsCommonProjector::hmLockedInSlot); - SetSpriteUpdate(NULL); -} - -void AsCommonProjector::stStartProjecting() { - startAnimation(0x50A80517, 0, -1); - setGlobalVar(V_PROJECTOR_ACTIVE, 1); - playSound(0, 0xCC4A8456); - _vm->_soundMan->addSound(0x05331081, 0xCE428854); - _vm->_soundMan->playSoundLooping(0xCE428854); - SetMessageHandler(&AsCommonProjector::hmAnimation); - SetSpriteUpdate(NULL); - NextState(&AsCommonProjector::stLockedInSlot); -} - -void AsCommonProjector::stLockedInSlot() { - sendMessage(_parentScene, 0x480F, 0); - startAnimation(0xD833207F, 0, -1); - SetMessageHandler(&AsCommonProjector::hmLockedInSlot); - SetSpriteUpdate(NULL); -} - -void AsCommonProjector::stStopProjecting() { - startAnimation(0x50A94417, 0, -1); - setGlobalVar(V_PROJECTOR_ACTIVE, 0); - playSound(0, 0xCC4A8456); - _vm->_soundMan->deleteSound(0xCE428854); - SetMessageHandler(&AsCommonProjector::hmAnimation); - SetSpriteUpdate(NULL); - NextState(&AsCommonProjector::stStayLockedInSlot); -} - -void AsCommonProjector::stTurnToFront() { - _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; - startAnimation(0x22CB4A33, 0, -1); - SetMessageHandler(&AsCommonProjector::hmAnimation); - SetSpriteUpdate(&AsCommonProjector::suMoving); - NextState(&AsCommonProjector::stMoving); -} - -void AsCommonProjector::stStartSuckedIn() { - setGlobalVar(V_PROJECTOR_LOCATION, 4); - setGlobalVar(V_PROJECTOR_SLOT, 0); - startAnimation(0x708D4712, 0, -1); - playSound(2); - SetMessageHandler(&Sprite::handleMessage); - SetSpriteUpdate(&AsCommonProjector::stSuckedIn); -} - -Scene1401::Scene1401(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _projectorBorderFlag(false), _ssFloorButton(NULL), _asProjector(NULL), - _asPipe(NULL), _asMouse(NULL), _asCheese(NULL), _asBackDoor(NULL), - _sprite1(NULL), _sprite2(NULL), _sprite3(NULL), _ssButton(NULL) { - - SetMessageHandler(&Scene1401::handleMessage); - SetUpdateHandler(&Scene1401::update); - - setRectList(0x004B6758); - setBackground(0x08221FA5); - setPalette(0x08221FA5); - insertScreenMouse(0x21FA108A); - - _ssFloorButton = insertSprite(this, 0x980F3124, 0x12192892, 100, 0); - _asPipe = insertSprite(); - - if (!getGlobalVar(V_MOUSE_SUCKED_IN)) { - _asMouse = insertSprite(); - _asCheese = insertSprite(); - } - - _sprite3 = insertStaticSprite(0xA82BA811, 1100); - insertStaticSprite(0x0A116C60, 1100); - _ssButton = insertSprite(this, 0xB84B1100, 100, 0); - _sprite1 = insertStaticSprite(0x38EA100C, 1005); - _sprite2 = insertStaticSprite(0x98D0223C, 1200); - _sprite2->setVisible(false); - - if (which < 0) { - // Restoring game - insertKlaymen(380, 447); - setMessageList(0x004B65C8); - _sprite1->setVisible(false); - } else if (which == 1) { - // Klaymen entering from the left - insertKlaymen(0, 447); - setMessageList(0x004B65D0); - _sprite1->setVisible(false); - } else if (which == 2) { - // Klaymen entering from the right - insertKlaymen(660, 447); - setMessageList(0x004B65D8); - _sprite1->setVisible(false); - } else { - // Klaymen entering from the back - insertKlaymen(290, 413); - setMessageList(0x004B65E8); - _sprite1->setVisible(false); - } - - if (getGlobalVar(V_PROJECTOR_LOCATION) == 2) { - _asProjector = insertSprite(this, _klaymen, _asPipe); - addCollisionSprite(_asProjector); - if (getGlobalVar(V_PROJECTOR_SLOT) == 6) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - _klaymen->setX(_asProjector->getX() + 100); - _klaymen->updateBounds(); - setMessageList(0x004B6670); - } else if (getGlobalVar(V_PROJECTOR_SLOT) == 0) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - _klaymen->setX(_asProjector->getX() - 100); - _klaymen->updateBounds(); - setMessageList(0x004B6670); - } - _asProjector->setClipRect(_sprite3->getDrawRect().x, _sprite2->getDrawRect().y, 640, 480); - } - - _klaymen->setClipRect(_sprite3->getDrawRect().x, 0, 640, 480); - - if (which == 0 && _asProjector) - sendMessage(_asProjector, 0x482B, 0); - - _asBackDoor = insertSprite(_klaymen, which == 0); - -} - -void Scene1401::update() { - Scene::update(); - if (_asProjector && !_projectorBorderFlag && _asProjector->getY() < 360) { - _sprite2->setVisible(true); - _projectorBorderFlag = true; - } else - _sprite2->setVisible(false); -} - -uint32 Scene1401::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x02144CB1) - sendEntityMessage(_klaymen, 0x1014, _ssFloorButton); - else if (param.asInteger() == 0x402064D8) - sendEntityMessage(_klaymen, 0x1014, _ssButton); - else if (param.asInteger() == 0x01C66840) { - if (sendMessage(_asBackDoor, 0x2001, 0) != 0) - setMessageList(0x004B6690); - else - setMessageList(0x004B66B0); - } - break; - case 0x1019: - if (param.asInteger() != 0) - leaveScene(2); - else - leaveScene(1); - break; - case 0x480B: - if (sender == _ssFloorButton) { - sendMessage(_asPipe, 0x2000, 0); - if (!getGlobalVar(V_MOUSE_SUCKED_IN)) { - sendMessage(_asMouse, 0x4839, 0); - sendMessage(_asCheese, 0x4839, 0); - setGlobalVar(V_MOUSE_SUCKED_IN, 1); - } - if (_asProjector && _asProjector->getX() > 404 && _asProjector->getX() < 504) - sendMessage(_asProjector , 0x4839, 0); - } else if (sender == _ssButton) - sendMessage(_asBackDoor, 0x4808, 0); - break; - case 0x4826: - if (sender == _asProjector) { - if (sendMessage(_asProjector, 0x480C, _klaymen->getX() > _asProjector->getX() ? 1 : 0) != 0) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - setMessageList2(0x004B6658); - } else - setMessageList2(0x004B65F0); - } - break; - case 0x482A: - _sprite1->setVisible(true); - if (_asProjector) - sendMessage(_asProjector, 0x482B, 0); - break; - case 0x482B: - _sprite1->setVisible(false); - if (_asProjector) - sendMessage(_asProjector, 0x482A, 0); - break; - } - return 0; -} - -// Scene1402 - -SsScene1402BridgePart::SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority) - : StaticSprite(vm, fileHash, surfacePriority) { - - SetFilterY(&Sprite::defFilterY); - SetUpdateHandler(&StaticSprite::updatePosition); -} - -AsScene1402PuzzleBox::AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status) - : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - - createSurface(900, 347, 230); - - SetFilterY(&Sprite::defFilterY); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1402PuzzleBox::handleMessage); - _x = 279; - _y = 270; - if (status == 2) { - // Puzzle box after the puzzle was solved - startAnimation(0x20060259, 0, -1); - playSound(0, 0x419014AC); - loadSound(1, 0x61901C29); - NextState(&AsScene1402PuzzleBox::stMoveDownSolvedDone); - } else if (status == 1) { - // Puzzle box appears - startAnimation(0x210A0213, 0, -1); - playSound(0, 0x41809C6C); - NextState(&AsScene1402PuzzleBox::stMoveUpDone); - } else { - // Puzzle box is here - startAnimation(0x20060259, -1, -1); - loadSound(1, 0x61901C29); - _newStickFrameIndex = STICK_LAST_FRAME; - } -} - -uint32 AsScene1402PuzzleBox::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2002: - playSound(1); - startAnimation(0x20060259, -1, -1); - _playBackwards = true; - NextState(&AsScene1402PuzzleBox::stMoveDownDone); - break; - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1402PuzzleBox::stMoveUpDone() { - sendMessage(_parentScene, 0x2000, 0); - stopAnimation(); - setVisible(false); -} - -void AsScene1402PuzzleBox::stMoveDownDone() { - sendMessage(_parentScene, 0x2001, 0); - stopAnimation(); - setVisible(false); -} - -void AsScene1402PuzzleBox::stMoveDownSolvedDone() { - sendMessage(_parentScene, 0x2003, 0); - stopAnimation(); -} - -Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _isShaking(false), _asPuzzleBox(NULL), _asProjector(NULL) { - - SetMessageHandler(&Scene1402::handleMessage); - - _vm->_screen->setYOffset(0); - - setBackground(0x231482F0); - setBackgroundY(-10); - setPalette(0x231482F0); - _palette->addPalette(0x91D3A391, 0, 64, 0); - insertScreenMouse(0x482F4239); - - _ssBridgePart1 = insertSprite(0x15402D64, 1100); - _ssBridgePart2 = insertSprite(0x10A02120, 1100); - _ssBridgePart3 = insertSprite(0x60882BE0, 1100); - - if (getGlobalVar(V_MOUSE_PUZZLE_SOLVED)) - setRectList(0x004B0C48); - else - setRectList(0x004B0C98); - - if (which < 0) { - // Restoring game - insertKlaymen(377, 391); - setMessageList(0x004B0B48); - if (!getGlobalVar(V_MOUSE_PUZZLE_SOLVED)) - _asPuzzleBox = insertSprite(this, 0); - } else if (which == 1) { - // Klaymen entering from the left - insertKlaymen(42, 391); - setMessageList(0x004B0B50); - } else if (which == 2) { - // Klaymen returning from the puzzle box - insertKlaymen(377, 391); - setMessageList(0x004B0B60); - _klaymen->setDoDeltaX(1); - if (getGlobalVar(V_MOUSE_PUZZLE_SOLVED)) { - _asPuzzleBox = insertSprite(this, 1); - clearRectList(); - showMouse(false); - startShaking(); - } else - _asPuzzleBox = insertSprite(this, 0); - } else { - // Klaymen entering from the right - insertKlaymen(513, 391); - setMessageList(0x004B0B58); - if (!getGlobalVar(V_MOUSE_PUZZLE_SOLVED)) { - _asPuzzleBox = insertSprite(this, 2); - startShaking(); - } - } - - if (_asPuzzleBox) - _asPuzzleBox->setClipRect(0, 0, 640, _ssBridgePart3->getDrawRect().y2()); - - if (getGlobalVar(V_PROJECTOR_LOCATION) == 1) { - _asProjector = insertSprite(this, _klaymen, (Sprite*)NULL); - addCollisionSprite(_asProjector); - if (getGlobalVar(V_PROJECTOR_SLOT) == 4) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - _klaymen->setX(_asProjector->getX() + 100); - _klaymen->updateBounds(); - setMessageList(0x004B0BD0); - } else if (getGlobalVar(V_PROJECTOR_SLOT) == 0) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - _klaymen->setX(_asProjector->getX() - 100); - _klaymen->updateBounds(); - setMessageList(0x004B0BD0); - } - _asProjector->setClipRect(_ssBridgePart1->getDrawRect().x, 0, _ssBridgePart2->getDrawRect().x, _ssBridgePart3->getDrawRect().y2()); - } - - _klaymen->setClipRect(_ssBridgePart1->getDrawRect().x, 0, _ssBridgePart2->getDrawRect().x2(), _ssBridgePart3->getDrawRect().y2()); - -} - -void Scene1402::upShaking() { - if (_isShaking) { - setBackgroundY(_vm->_rnd->getRandomNumber(10 - 1) - 10); - _vm->_screen->setYOffset(-10 - getBackgroundY()); - } else { - setBackgroundY(-10); - _vm->_screen->setYOffset(0); - SetUpdateHandler(&Scene::update); - } - Scene::update(); - if (_asPuzzleBox) - _asPuzzleBox->setClipRect(0, 0, 640, _ssBridgePart3->getDrawRect().y2()); - _klaymen->setClipRect(_ssBridgePart1->getDrawRect().x, 0, _ssBridgePart2->getDrawRect().x2(), _ssBridgePart3->getDrawRect().y2()); -} - -uint32 Scene1402::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x00F43389) { - if (getGlobalVar(V_MOUSE_PUZZLE_SOLVED)) - leaveScene(0); - else { - clearRectList(); - _klaymen->setVisible(false); - showMouse(false); - sendMessage(_asPuzzleBox, 0x2002, 0); - startShaking(); - } - } - break; - case 0x1019: - if (param.asInteger()) - leaveScene(0); - else - leaveScene(1); - break; - case 0x2000: - stopShaking(); - showMouse(true); - setRectList(0x004B0C48); - break; - case 0x2001: - stopShaking(); - leaveScene(0); - break; - case 0x2003: - stopShaking(); - break; - case 0x4826: - if (sender == _asProjector) { - if (sendMessage(_asProjector, 0x480C, _klaymen->getX() > _asProjector->getX() ? 1 : 0) != 0) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - setMessageList2(0x004B0BB8); - } else - setMessageList2(0x004B0B68); - } - break; - } - return 0; -} - -void Scene1402::startShaking() { - _isShaking = true; - SetUpdateHandler(&Scene1402::upShaking); -} - -void Scene1402::stopShaking() { - _isShaking = false; -} - -// Scene1407 - -static const int16 kScene1407MouseFloorY[] = { - 106, 150, 191, 230, 267, 308, 350, 395 -}; - -static const struct { - int16 x; - int16 floorIndex; - int16 sectionIndex; - int16 nextHoleIndex; -} kScene1407MouseHoles[] = { - {125, 0, 0, 7}, - {452, 7, 21, 0}, - {337, 4, 11, 4}, - {286, 6, 17, 6}, - {348, 6, 17, 39}, - {536, 6, 18, 42}, - {111, 1, 3, 18}, - {203, 1, 3, 38}, - {270, 1, 3, 9}, - {197, 5, 14, 3}, - {252, 5, 14, 35}, - {297, 5, 14, 7}, - {359, 5, 14, 8}, - {422, 4, 12, 26}, - {467, 4, 12, 2}, - {539, 4, 12, 40}, - {111, 5, 13, 17}, - {211, 0, 1, 20}, - {258, 0, 1, 11}, - {322, 0, 1, 16}, - { 99, 6, 16, 31}, - {142, 6, 16, 27}, - {194, 6, 16, 12}, - {205, 2, 6, 45}, - {264, 2, 6, 10}, - { 98, 4, 10, 2}, - {152, 4, 10, 37}, - {199, 4, 10, 13}, - {258, 4, 10, 16}, - {100, 7, 19, 43}, - {168, 7, 19, 23}, - {123, 3, 8, 14}, - {181, 3, 8, 39}, - {230, 3, 8, 28}, - {292, 3, 8, 22}, - {358, 3, 8, 36}, - {505, 3, 9, 44}, - {400, 2, 7, 34}, - {454, 2, 7, 32}, - {532, 2, 7, 46}, - {484, 5, 15, 25}, - {529, 5, 15, 30}, - {251, 7, 20, 48}, - {303, 7, 20, 21}, - {360, 7, 20, 33}, - {503, 0, 2, 5}, - {459, 1, 4, 19}, - {530, 1, 4, 42}, - {111, 2, 5, 47}, - {442, 6, 18, 1} -}; - -static const struct { - int16 x1, x2; - int16 goodHoleIndex; -} kScene1407MouseSections[] = { - {100, 149, 0}, - {182, 351, 17}, - {430, 524, 45}, - { 89, 293, 7}, - {407, 555, 47}, - { 89, 132, 48}, - {178, 303, 23}, - {367, 551, 38}, - {105, 398, 31}, - {480, 537, 36}, - { 84, 275, 27}, - {318, 359, 2}, - {402, 560, 15}, - { 91, 132, 16}, - {179, 400, 10}, - {461, 552, 41}, - { 86, 218, 21}, - {267, 376, 4}, - {420, 560, 49}, - { 77, 188, 30}, - {237, 394, 44}, - {438, 515, 5} -}; - -AsScene1407Mouse::AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _currSectionIndex(0) { - - createSurface(100, 117, 45); - _x = 108; - _y = 106; - stIdleLookAtGoodHole(); - SetUpdateHandler(&AnimatedSprite::update); -} - -void AsScene1407Mouse::suWalkTo() { - int16 xdelta = _walkDestX - _x; - if (xdelta > _deltaX) - xdelta = _deltaX; - else if (xdelta < -_deltaX) - xdelta = -_deltaX; - _deltaX = 0; - if (_walkDestX == _x) - sendMessage(this, 0x1019, 0); - else { - _x += xdelta; - updateBounds(); - } -} - -void AsScene1407Mouse::upGoThroughHole() { - if (_countdown != 0 && (--_countdown == 0)) { - SetUpdateHandler(&AnimatedSprite::update); - gotoNextState(); - } - AnimatedSprite::update(); -} - -uint32 AsScene1407Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - { - int16 mouseX = param.asPoint().x; - int16 mouseY = param.asPoint().y; - int holeIndex; - for (holeIndex = 0; holeIndex < 50; holeIndex++) { - int16 holeX = kScene1407MouseHoles[holeIndex].x; - int16 holeY = kScene1407MouseFloorY[kScene1407MouseHoles[holeIndex].floorIndex]; - if (mouseX >= holeX - 14 && mouseX <= holeX + 14 && mouseY >= holeY - 36 && mouseY <= holeY) - break; - } - if (holeIndex < 50 && kScene1407MouseHoles[holeIndex].sectionIndex == _currSectionIndex) { - _nextHoleIndex = kScene1407MouseHoles[holeIndex].nextHoleIndex; - _walkDestX = kScene1407MouseHoles[holeIndex].x; - stWalkToHole(); - } else { - if (mouseX < kScene1407MouseSections[_currSectionIndex].x1) - _walkDestX = kScene1407MouseSections[_currSectionIndex].x1; - else if (mouseX > kScene1407MouseSections[_currSectionIndex].x2) - _walkDestX = kScene1407MouseSections[_currSectionIndex].x2; - else - _walkDestX = mouseX; - stWalkToDest(); - } - } - break; - case 0x1019: - gotoNextState(); - break; - case 0x2001: - { - // Reset the position - // Find the nearest hole and go through it, and exit at the first hole - int16 distance = 640; - int matchIndex = 50; - for (int index = 0; index < 50; index++) - if (kScene1407MouseHoles[index].sectionIndex == _currSectionIndex && - ABS(kScene1407MouseHoles[index].x - _x) < distance) { - matchIndex = index; - distance = ABS(kScene1407MouseHoles[index].x - _x); - } - if (matchIndex < 50) { - _nextHoleIndex = 0; - _walkDestX = kScene1407MouseHoles[matchIndex].x; - stWalkToHole(); - } - } - break; - } - return messageResult; -} - -void AsScene1407Mouse::stIdleLookAtGoodHole() { - setDoDeltaX(kScene1407MouseHoles[kScene1407MouseSections[_currSectionIndex].goodHoleIndex].x < _x ? 1 : 0); - startAnimation(0x72215194, 0, -1); - SetMessageHandler(&AsScene1407Mouse::handleMessage); - SetSpriteUpdate(NULL); -} - -void AsScene1407Mouse::stWalkToDest() { - if (_walkDestX != _x) { - setDoDeltaX(_walkDestX < _x ? 1 : 0); - startAnimation(0x22291510, 0, -1); - SetMessageHandler(&AsScene1407Mouse::handleMessage); - SetSpriteUpdate(&AsScene1407Mouse::suWalkTo); - NextState(&AsScene1407Mouse::stIdleLookAtGoodHole); - } -} - -void AsScene1407Mouse::stWalkToHole() { - setDoDeltaX(_walkDestX < _x ? 1 : 0); - startAnimation(0x22291510, 0, -1); - SetMessageHandler(&AsScene1407Mouse::handleMessage); - SetSpriteUpdate(&AsScene1407Mouse::suWalkTo); - NextState(&AsScene1407Mouse::stGoThroughHole); -} - -void AsScene1407Mouse::stGoThroughHole() { - startAnimation(0x72215194, 0, -1); - setVisible(false); - _countdown = 12; - SetUpdateHandler(&AsScene1407Mouse::upGoThroughHole); - SetMessageHandler(NULL); - SetSpriteUpdate(NULL); - NextState(&AsScene1407Mouse::stArriveAtHole); -} - -void AsScene1407Mouse::stArriveAtHole() { - _currSectionIndex = kScene1407MouseHoles[_nextHoleIndex].sectionIndex; - _x = kScene1407MouseHoles[_nextHoleIndex].x; - _y = kScene1407MouseFloorY[kScene1407MouseHoles[_nextHoleIndex].floorIndex]; - if (_nextHoleIndex == 1) { - sendMessage(_parentScene, 0x2000, 0); - _walkDestX = 512; - stWalkToDest(); - setVisible(true); - } else { - _walkDestX = _x + 14; - stWalkToDest(); - setVisible(true); - } -} - -Scene1407::Scene1407(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule), _puzzleSolvedCountdown(0), _resetButtonCountdown(0) { - - SetMessageHandler(&Scene1407::handleMessage); - SetUpdateHandler(&Scene1407::update); - - setBackground(0x00442225); - setPalette(0x00442225); - insertPuzzleMouse(0x4222100C, 20, 620); - - _asMouse = insertSprite(this); - _ssResetButton = insertStaticSprite(0x12006600, 100); - _ssResetButton->setVisible(false); - -} - -void Scene1407::update() { - Scene::update(); - if (_puzzleSolvedCountdown != 0 && (--_puzzleSolvedCountdown == 0)) - leaveScene(1); - else if (_resetButtonCountdown != 0 && (--_resetButtonCountdown == 0)) - _ssResetButton->setVisible(false); -} - -uint32 Scene1407::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (_puzzleSolvedCountdown == 0) { - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { - // Exit scene - leaveScene(0); - } else if (param.asPoint().x >= 75 && param.asPoint().x <= 104 && - param.asPoint().y >= 62 && param.asPoint().y <= 90) { - // The reset button was clicked - sendMessage(_asMouse, 0x2001, 0); - _ssResetButton->setVisible(true); - playSound(0, 0x44045000); - _resetButtonCountdown = 12; - } else { - // Handle the mouse - sendMessage(_asMouse, messageNum, param); - } - } - break; - case 0x2000: - // The mouse got the cheese (nomnom) - setGlobalVar(V_MOUSE_PUZZLE_SOLVED, 1); - playSound(0, 0x68E25540); - showMouse(false); - _puzzleSolvedCountdown = 72; - break; - } - return 0; -} - -// Scene1403 - -Scene1403::Scene1403(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _asProjector(NULL), _isProjecting(false) { - - SetMessageHandler(&Scene1403::handleMessage); - - setRectList(0x004B1FF8); - setBackground(0x2110A234); - setPalette(0x2110A234); - insertScreenMouse(0x0A230219); - - _sprite1 = insertStaticSprite(0x01102A33, 100); - _sprite1->setVisible(false); - _sprite2 = insertStaticSprite(0x04442520, 995); - _sprite3 = insertStaticSprite(0x08742271, 995); - _asTape1 = insertSprite(this, 12, 1100, 201, 468, 0x9148A011); - addCollisionSprite(_asTape1); - _asTape1->setRepl(64, 0); - _asTape2 = insertSprite(this, 16, 1100, 498, 468, 0x9048A093); - addCollisionSprite(_asTape2); - _asTape2->setRepl(64, 0); - - if (which < 0) { - // Restoring game - insertKlaymen(380, 463); - setMessageList(0x004B1F18); - } else { - // Klaymen entering from the right - insertKlaymen(640, 463); - setMessageList(0x004B1F20); - } - _klaymen->setRepl(64, 0); - - if (getGlobalVar(V_PROJECTOR_LOCATION) == 0) { - _asProjector = insertSprite(this, _klaymen, (Sprite*)NULL); - addCollisionSprite(_asProjector); - if (getGlobalVar(V_PROJECTOR_SLOT) == 4) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - _klaymen->setX(_asProjector->getX() + 100); - _klaymen->updateBounds(); - setMessageList(0x004B1F70); - } - _asProjector->setClipRect(0, 0, 640, _sprite2->getDrawRect().y2()); - _asProjector->setRepl(64, 0); - } - -} - -uint32 Scene1403::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x88C11390) { - setRectList(0x004B2008); - _isProjecting = true; - } else if (param.asInteger() == 0x08821382) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - setRectList(0x004B1FF8); - _isProjecting = false; - } - break; - case 0x1019: - leaveScene(0); - break; - case 0x1022: - if (sender == _asProjector) { - if (param.asInteger() >= 1000) - setSurfacePriority(_sprite3->getSurface(), 1100); - else - setSurfacePriority(_sprite3->getSurface(), 995); - } - break; - case 0x4807: - _sprite1->setVisible(false); - break; - case 0x480F: - _sprite1->setVisible(true); - break; - case 0x4826: - if (sender == _asProjector) { - if (_isProjecting) - setMessageList2(0x004B1FA8); - else if (param.asInteger() == 1) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - setMessageList2(0x004B1F88); - } else if (sendMessage(_asProjector, 0x480C, _klaymen->getX() > _asProjector->getX() ? 1 : 0) != 0) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - setMessageList2(0x004B1F58); - } else - setMessageList2(0x004B1F28); - } else if (sender == _asTape1 || sender == _asTape2) { - if (_isProjecting) - setMessageList2(0x004B1FA8); - else if (_messageListStatus != 2) { - sendEntityMessage(_klaymen, 0x1014, sender); - setMessageList2(0x004B1FB8); - } - } - break; - } - return 0; -} - -// Scene1404 - -Scene1404::Scene1404(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _asProjector(NULL), _asKey(NULL) { - - if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) - setGlobalVar(V_KEY3_LOCATION, 5); - - SetMessageHandler(&Scene1404::handleMessage); - - setRectList(0x004B8D80); - setBackground(0xAC0B006F); - setPalette(0xAC0B006F); - _palette->addPalette(0x00801510, 0, 65, 0); - insertScreenMouse(0xB006BAC8); - - if (getGlobalVar(V_KEY3_LOCATION) == 5) { - _asKey = insertSprite(this, 2, 1100, 267, 411); - addCollisionSprite(_asKey); - } - - _sprite1 = insertStaticSprite(0x1900A1F8, 1100); - _asTape = insertSprite(this, 14, 1100, 281, 411, 0x9148A011); - addCollisionSprite(_asTape); - - if (which < 0) { - // Restoring game - insertKlaymen(376, 406); - setMessageList(0x004B8C28); - } else if (which == 1) { - // Klaymen returning from the tiles puzzle - insertKlaymen(376, 406); - setMessageList(0x004B8C30); - } else if (which == 2) { - // Klaymen returning from the diskplayer - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { - insertKlaymen(347, 406); - _klaymen->setDoDeltaX(1); - } else { - insertKlaymen(187, 406); - } - setMessageList(0x004B8D28); - } else { - // Klaymen entering from the left - insertKlaymen(30, 406); - setMessageList(0x004B8C38); - } - - if (getGlobalVar(V_PROJECTOR_LOCATION) == 3) { - _asProjector = insertSprite(this, _klaymen, (Sprite*)NULL); - addCollisionSprite(_asProjector); - if (getGlobalVar(V_PROJECTOR_SLOT) == 0) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - _klaymen->setX(_asProjector->getX() - 100); - _klaymen->updateBounds(); - setMessageList(0x004B8CB8); - } - _asProjector->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); - } - - _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); - -} - -Scene1404::~Scene1404() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); -} - -uint32 Scene1404::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x410650C2) { - if (_asProjector && _asProjector->getX() == 220) - setMessageList(0x004B8C40); - else - setMessageList(0x004B8CE8); - } - break; - case 0x1019: - leaveScene(0); - break; - case 0x4826: - if (sender == _asProjector) { - if (sendMessage(_asProjector, 0x480C, _klaymen->getX() > _asProjector->getX() ? 1 : 0) != 0) { - sendEntityMessage(_klaymen, 0x1014, _asProjector); - setMessageList2(0x004B8CA0); - } else - setMessageList2(0x004B8C40); - } else if (sender == _asTape && _messageListStatus != 2) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004B8CD0); - } else if (sender == _asKey && _messageListStatus != 2) { - sendEntityMessage(_klaymen, 0x1014, _asKey); - setMessageList(0x004B8D18); - } - break; - } - return 0; -} - -// Scene1405 - -static const NPoint kAsScene1405TileItemPositions[] = { - {100, 80}, {162, 78}, {222, 76}, {292, 76}, - {356, 82}, {422, 84}, {488, 86}, {550, 90}, - {102, 134}, {164, 132}, {224, 136}, {294, 136}, - {360, 136}, {422, 138}, {484, 144}, {548, 146}, - { 98, 196}, {160, 200}, {228, 200}, {294, 202}, - {360, 198}, {424, 200}, {482, 202}, {548, 206}, - { 98, 260}, {160, 264}, {226, 260}, {296, 262}, - {358, 260}, {424, 262}, {486, 264}, {550, 266}, - { 94, 322}, {160, 316}, {226, 316}, {296, 320}, - {358, 322}, {422, 324}, {488, 322}, {550, 322}, - { 98, 380}, {160, 376}, {226, 376}, {294, 378}, - {356, 380}, {420, 380}, {490, 378}, {552, 376} -}; - -AsScene1405Tile::AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _tileIndex(tileIndex), _countdown(0), _isShowing(false) { - - loadSound(0, 0x05308101); - setSoundPan(0, (tileIndex % 8 * 4 + 4) * 25 / 8); - _x = kAsScene1405TileItemPositions[_tileIndex].x; - _y = kAsScene1405TileItemPositions[_tileIndex].y; - createSurface1(0x844B805C, 1100); - setVisible(false); - if (getSubVar(VA_IS_TILE_MATCH, _tileIndex)) - _countdown = _vm->_rnd->getRandomNumber(36 - 1) + 1; - startAnimation(0x844B805C, getSubVar(VA_TILE_SYMBOLS, _tileIndex), -1); - _newStickFrameIndex = (int16)getSubVar(VA_TILE_SYMBOLS, _tileIndex); - SetUpdateHandler(&AsScene1405Tile::update); - SetMessageHandler(&AsScene1405Tile::handleMessage); -} - -void AsScene1405Tile::update() { - updateAnim(); - updatePosition(); - if (_countdown != 0 && (--_countdown == 0)) - show(); -} - -uint32 AsScene1405Tile::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (getSubVar(VA_IS_TILE_MATCH, _tileIndex) == 0 && _parentScene->getCountdown() == 0) { - show(); - sendMessage(_parentScene, 0x2000, _tileIndex); - } - messageResult = 1; - break; - } - return messageResult; -} - -void AsScene1405Tile::show() { - if (!_isShowing) { - _isShowing = true; - playSound(0); - setVisible(true); - } -} - -void AsScene1405Tile::hide() { - if (_isShowing) { - _isShowing = false; - playSound(0); - setVisible(false); - } -} - -Scene1405::Scene1405(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule), _selectFirstTile(true), _tilesLeft(48), _countdown(0) { - - _vm->gameModule()->initMemoryPuzzle(); - - SetUpdateHandler(&Scene1405::update); - SetMessageHandler(&Scene1405::handleMessage); - - setBackground(0x0C0C007D); - setPalette(0x0C0C007D); - insertPuzzleMouse(0xC00790C8, 20, 620); - - for (uint32 tileIndex = 0; tileIndex < 48; tileIndex++) { - _tiles[tileIndex] = insertSprite(this, tileIndex); - addCollisionSprite(_tiles[tileIndex]); - if (getSubVar(VA_IS_TILE_MATCH, tileIndex)) - _tilesLeft--; - } - - loadSound(0, 0x68E25540); -} - -void Scene1405::update() { - Scene::update(); - if (_countdown != 0 && (--_countdown == 0)) { - _tilesLeft = 48; - _tiles[_firstTileIndex]->hide(); - _tiles[_secondTileIndex]->hide(); - for (uint32 i = 0; i < 48; i++) { - if (getSubVar(VA_IS_TILE_MATCH, i)) { - _tiles[i]->hide(); - setSubVar(VA_IS_TILE_MATCH, i, 0); - } - } - } -} - -uint32 Scene1405::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) - leaveScene(0); - break; - case 0x2000: - if (_selectFirstTile) { - _firstTileIndex = param.asInteger(); - _selectFirstTile = false; - } else { - _secondTileIndex = param.asInteger(); - if (_firstTileIndex != _secondTileIndex) { - _selectFirstTile = true; - if (getSubVar(VA_TILE_SYMBOLS, _secondTileIndex) == getSubVar(VA_TILE_SYMBOLS, _firstTileIndex)) { - setSubVar(VA_IS_TILE_MATCH, _firstTileIndex, 1); - setSubVar(VA_IS_TILE_MATCH, _secondTileIndex, 1); - _tilesLeft -= 2; - if (_tilesLeft == 0) - playSound(0); - } else - _countdown = 10; - } - } - break; - } - return 0; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module1400.h b/engines/neverhood/module1400.h deleted file mode 100644 index 14857062c1..0000000000 --- a/engines/neverhood/module1400.h +++ /dev/null @@ -1,281 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE1400_H -#define NEVERHOOD_MODULE1400_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/module1200.h" - -namespace Neverhood { - -class Module1400 : public Module { -public: - Module1400(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module1400(); -protected: - int _sceneNum; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -// Scene1401 - -class AsScene1401Pipe : public AnimatedSprite { -public: - AsScene1401Pipe(NeverhoodEngine *vm); - virtual ~AsScene1401Pipe(); -protected: - int _countdown1; - int _countdown2; - void update(); - void upSuckInProjector(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmSuckInProjector(int messageNum, const MessageParam ¶m, Entity *sender); - void stStartSucking(); - void stDoneSucking(); - void stSuckInProjector(); -}; - -class AsScene1401Mouse : public AnimatedSprite { -public: - AsScene1401Mouse(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suSuckedIn(); - void stSuckedIn(); -}; - -class AsScene1401Cheese : public AnimatedSprite { -public: - AsScene1401Cheese(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suSuckedIn(); - void stSuckedIn(); -}; - -class AsScene1401BackDoor : public AnimatedSprite { -public: - AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen); -protected: - Sprite *_klaymen; - int _countdown; - bool _isOpen; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stOpenDoor(); - void stCloseDoor(); - void stCloseDoorDone(); -}; - -struct AsCommonProjectorItem { - NPoint point; - int8 maxSlotCount; - int8 lockSlotIndex; - int8 index1; - int8 leftBorderLeaves; - int8 rightBorderLeaves; -}; - -class AsCommonProjector : public AnimatedSprite { -public: - AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe); - virtual ~AsCommonProjector(); -protected: - Scene *_parentScene; - Sprite *_klaymen; - Sprite *_asPipe; - const AsCommonProjectorItem *_asProjectorItem; - int16 _beforeMoveX; - bool _lockedInSlot; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmLockedInSlot(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender); - void suMoving(); - void moveProjector(); - void stSuckedIn(); - void stIdle(); - void stMoving(); - void stStartLockedInSlot(); - void stStayLockedInSlot(); - void stStartProjecting(); - void stLockedInSlot(); - void stStopProjecting(); - void stTurnToFront(); - void stStartSuckedIn(); -}; - -class Scene1401 : public Scene { -public: - Scene1401(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - bool _projectorBorderFlag; - Sprite *_ssFloorButton; - AsCommonProjector *_asProjector; - Sprite *_asPipe; - Sprite *_asMouse; - Sprite *_asCheese; - Sprite *_asBackDoor; - Sprite *_sprite1; - Sprite *_sprite2; - Sprite *_sprite3; - Sprite *_ssButton; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -// Scene1402 - -class SsScene1402BridgePart : public StaticSprite { -public: - SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority); -}; - -class AsScene1402PuzzleBox : public AnimatedSprite { -public: - AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stMoveUpDone(); - void stMoveDownDone(); - void stMoveDownSolvedDone(); -}; - -class Scene1402 : public Scene { -public: - Scene1402(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_ssBridgePart1; - Sprite *_ssBridgePart2; - Sprite *_ssBridgePart3; - Sprite *_asPuzzleBox; - AsCommonProjector *_asProjector; - bool _isShaking; - void upShaking(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void startShaking(); - void stopShaking(); -}; - -// Scene1407 - -class AsScene1407Mouse : public AnimatedSprite { -public: - AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - int16 _walkDestX; - int16 _currSectionIndex; - int16 _nextHoleIndex; - int _countdown; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suWalkTo(); - void upGoThroughHole(); - void stIdleLookAtGoodHole(); - void stWalkToDest(); - void stWalkToHole(); - void stGoThroughHole(); - void stArriveAtHole(); -}; - -class Scene1407 : public Scene { -public: - Scene1407(NeverhoodEngine *vm, Module *parentModule); -protected: - Sprite *_asMouse; - Sprite *_ssResetButton; - int _puzzleSolvedCountdown; - int _resetButtonCountdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -// Scene1403 - -class Scene1403 : public Scene { -public: - Scene1403(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_sprite1; - Sprite *_sprite2; - Sprite *_sprite3; - AsScene1201Tape *_asTape1; - AsScene1201Tape *_asTape2; - AsCommonProjector *_asProjector; - bool _isProjecting; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -// Scene1404 - -class Scene1404 : public Scene { -public: - Scene1404(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Scene1404(); -protected: - Sprite *_sprite1; - Sprite *_asTape; - AsCommonProjector *_asProjector; - Sprite *_asKey; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -// Scene1405 - -class Scene1405; - -class AsScene1405Tile : public AnimatedSprite { -public: - AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex); - void show(); - void hide(); -protected: - Scene1405 *_parentScene; - bool _isShowing; - uint32 _tileIndex; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene1405 : public Scene { -public: - Scene1405(NeverhoodEngine *vm, Module *parentModule); - int getCountdown() const { return _countdown; } -protected: - bool _selectFirstTile; - int _firstTileIndex; - int _secondTileIndex; - int _tilesLeft; - int _countdown; - AsScene1405Tile *_tiles[48]; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE1400_H */ diff --git a/engines/neverhood/module1500.cpp b/engines/neverhood/module1500.cpp deleted file mode 100644 index c49e968dca..0000000000 --- a/engines/neverhood/module1500.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* 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/module1500.h" - -namespace Neverhood { - -Module1500::Module1500(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else - createScene(3, -1); - -} - -void Module1500::createScene(int sceneNum, int which) { - debug("Module1500::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _childObject = new Scene1501(_vm, this, 0x8420221D, 0xA61024C4, 150, 48); - break; - case 1: - _vm->gameState().sceneNum = 1; - _childObject = new Scene1501(_vm, this, 0x30050A0A, 0x58B45E58, 110, 48); - break; - case 2: - _vm->gameState().sceneNum = 2; - sendMessage(_parentModule, 0x0800, 0); - createSmackerScene(0x001A0005, true, true, true); - break; - case 3: - _vm->gameState().sceneNum = 3; - _childObject = new Scene1501(_vm, this, 0x0CA04202, 0, 110, 48); - break; - } - SetUpdateHandler(&Module1500::updateScene); - _childObject->handleUpdate(); -} - -void Module1500::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - createScene(1, -1); - break; - case 1: - createScene(2, -1); - break; - case 3: - createScene(0, -1); - break; - default: - leaveModule(0); - break; - } - } -} - -// Scene1501 - -Scene1501::Scene1501(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 soundFileHash, int countdown2, int countdown3) - : Scene(vm, parentModule), _countdown3(countdown3), _countdown2(countdown2), _countdown1(0), _skip(false) { - - SetUpdateHandler(&Scene1501::update); - SetMessageHandler(&Scene1501::handleMessage); - - setBackground(backgroundFileHash); - setPalette(); - addEntity(_palette); - _palette->addBasePalette(backgroundFileHash, 0, 256, 0); - _palette->startFadeToPalette(12); - - if (soundFileHash != 0) - playSound(0, soundFileHash); - -} - -void Scene1501::update() { - Scene::update(); - if (_countdown1 != 0) { - _countdown1--; - if (_countdown1 == 0) { - _vm->_screen->clear(); - leaveScene(0); - } - } else if ((_countdown2 != 0 && (--_countdown2 == 0)) || (_countdown2 == 0 && !isSoundPlaying(0))) { - _countdown1 = 12; - _palette->startFadeToBlack(11); - } - - if (_countdown3 != 0) - _countdown3--; - - if (_countdown3 == 0 && _skip && _countdown1 == 0) { - _countdown1 = 12; - _palette->startFadeToBlack(11); - } - -} - -uint32 Scene1501::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0009: - _skip = true; - break; - } - return messageResult; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module1500.h b/engines/neverhood/module1500.h deleted file mode 100644 index c17cb4516c..0000000000 --- a/engines/neverhood/module1500.h +++ /dev/null @@ -1,58 +0,0 @@ -/* 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. - * - */ - -// TODO: I couldn't come up with a better name than 'Module' so far - -#ifndef NEVERHOOD_MODULE1500_H -#define NEVERHOOD_MODULE1500_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/smackerscene.h" - -namespace Neverhood { - -class Module1500 : public Module { -public: - Module1500(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - int _sceneNum; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -class Scene1501 : public Scene { -public: - Scene1501(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 soundFileHash, int countdown2, int countdown3); -protected: - int _countdown1; - int _countdown2; - int _countdown3; - bool _skip; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE1500_H */ diff --git a/engines/neverhood/module1600.cpp b/engines/neverhood/module1600.cpp deleted file mode 100644 index cc1aa2c3de..0000000000 --- a/engines/neverhood/module1600.cpp +++ /dev/null @@ -1,1412 +0,0 @@ -/* 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/module1600.h" -#include "neverhood/gamemodule.h" -#include "neverhood/module1200.h" -#include "neverhood/module2200.h" - -namespace Neverhood { - -static const uint32 kModule1600SoundList[] = { - 0x90805C50, 0x90804450, 0xB4005E60, - 0x91835066, 0x90E14440, 0 -}; - -Module1600::Module1600(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else if (which == 1) - createScene(4, 1); - else if (which == 2) - createScene(5, 0); - else if (which == 3) - createScene(6, 1); - else if (which == 4) - createScene(1, 0); - else - createScene(0, 0); - - _vm->_soundMan->addSoundList(0x1A008D8, kModule1600SoundList); - _vm->_soundMan->setSoundListParams(kModule1600SoundList, true, 50, 600, 5, 150); - _vm->_soundMan->playTwoSounds(0x1A008D8, 0x41861371, 0x43A2507F, 0); - -} - -Module1600::~Module1600() { - _vm->_soundMan->deleteGroup(0x1A008D8); -} - -void Module1600::createScene(int sceneNum, int which) { - debug("Module1600::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - createNavigationScene(0x004B39D0, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - createNavigationScene(0x004B3A30, which); - break; - case 2: - _vm->gameState().sceneNum = 2; - createNavigationScene(0x004B3A60, which); - break; - case 3: - _vm->gameState().sceneNum = 3; - createNavigationScene(0x004B3A90, which); - break; - case 4: - _vm->gameState().sceneNum = 4; - createNavigationScene(0x004B3B20, which); - break; - case 5: - _vm->gameState().sceneNum = 5; - createNavigationScene(0x004B3B50, which); - break; - case 6: - _vm->gameState().sceneNum = 6; - createNavigationScene(0x004B3B80, which); - break; - case 7: - _vm->gameState().sceneNum = 7; - _childObject = new Scene1608(_vm, this, which); - break; - case 8: - _vm->gameState().sceneNum = 8; - _childObject = new Scene1609(_vm, this); - break; - case 1001: - _vm->gameState().sceneNum = 1; - if (getGlobalVar(V_TALK_COUNTING_INDEX) == 1) - createSmackerScene(0x80050200, true, true, false); - else if (getGlobalVar(V_TALK_COUNTING_INDEX) == 2) - createSmackerScene(0x80090200, true, true, false); - else - createSmackerScene(0x80000200, true, true, false); - if (getGlobalVar(V_TALK_COUNTING_INDEX) >= 2) - setGlobalVar(V_TALK_COUNTING_INDEX, 0); - else - incGlobalVar(V_TALK_COUNTING_INDEX, +1); - break; - } - SetUpdateHandler(&Module1600::updateScene); - _childObject->handleUpdate(); -} - -void Module1600::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 0) - createScene(2, 0); - else if (_moduleResult == 1) - createScene(1, 0); - else if (_moduleResult == 2) - leaveModule(4); - break; - case 1: - if (_moduleResult == 0) - createScene(1001, -1); - else if (_moduleResult == 1) - createScene(0, 3); - break; - case 2: - if (_moduleResult == 0) - createScene(3, 0); - else if (_moduleResult == 1) - createScene(0, 2); - break; - case 3: - if (_moduleResult == 0) - createScene(5, 0); - else if (_moduleResult == 2) - createScene(6, 0); - else if (_moduleResult == 3) - createScene(2, 1); - else if (_moduleResult == 4) - createScene(4, 0); - break; - case 4: - if (_moduleResult == 0) - leaveModule(1); - else if (_moduleResult == 1) - createScene(3, 1); - break; - case 5: - if (_moduleResult == 0) - leaveModule(2); - else if (_moduleResult == 1) - createScene(3, 3); - break; - case 6: - if (_moduleResult == 0) - createScene(8, -1); - else if (_moduleResult == 1) - createScene(3, 5); - break; - case 7: - createScene(6, 1); - break; - case 8: - if (_moduleResult == 0) - createScene(6, 0); - else - createScene(7, 0); - break; - case 1001: - createScene(1, 0); - break; - } - } -} - -AsCommonCar::AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) - : AnimatedSprite(vm, 1000), _parentScene(parentScene) { - - createSurface(200, 556, 328); - _x = x; - _y = y; - - _inMainArea = false; - _exitDirection = 0; - _currPointIndex = 0; - _hasAgainDestPoint = false; - _stepError = 0; - _hasAgainDestPointIndex = false; - _steps = 0; - _isBraking = false; - _yMoveTotalSteps = 0; - _isBusy = false; - _isIdle = false; - _isMoving = true; - _rectFlag = false; - _newDeltaXType = -1; - _soundCounter = 0; - _pathPoints = NULL; - _currMoveDirection = 0; - - startAnimation(0xD4220027, 0, -1); - setDoDeltaX(getGlobalVar(V_CAR_DELTA_X)); - - SetUpdateHandler(&AsCommonCar::update); - SetMessageHandler(&AsCommonCar::handleMessage); - SetSpriteUpdate(NULL); -} - -AsCommonCar::~AsCommonCar() { - if (_finalizeStateCb == AnimationCallback(&AsCommonCar::evTurnCarDone)) - setGlobalVar(V_CAR_DELTA_X, !getGlobalVar(V_CAR_DELTA_X)); -} - -void AsCommonCar::setPathPoints(NPointArray *pathPoints) { - _pathPoints = pathPoints; -} - -void AsCommonCar::update() { - if (_newDeltaXType >= 0) { - setDoDeltaX(_newDeltaXType); - _newDeltaXType = -1; - } - AnimatedSprite::update(); - if (_hasAgainDestPoint && _yMoveTotalSteps == 0 && !_isBusy) { - _hasAgainDestPoint = false; - _hasAgainDestPointIndex = false; - sendPointMessage(this, 0x2004, _againDestPoint); - } else if (_hasAgainDestPointIndex && _yMoveTotalSteps == 0 && !_isBusy) { - _hasAgainDestPointIndex = false; - sendMessage(this, 0x2003, _againDestPointIndex); - } - updateMovement(); - updateSound(); -} - -void AsCommonCar::upIdle() { - update(); - if (++_idleCounter >= _idleCounterMax) - stIdleBlink(); - updateSound(); -} - -uint32 AsCommonCar::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1019: - SetSpriteUpdate(NULL); - break; - case 0x2002: - // Set the current position without moving - _currPointIndex = param.asInteger(); - _stepError = 0; - _x = pathPoint(_currPointIndex).x; - _y = pathPoint(_currPointIndex).y; - break; - case 0x2003: - // Move to a point by its index - { - int newPointIndex = param.asInteger(); - if (_yMoveTotalSteps <= 0 && !_isBusy) { - _destX = pathPoint(newPointIndex).x; - _destY = pathPoint(newPointIndex).y; - if (_currPointIndex < newPointIndex) { - moveToNextPoint(); - } else if (_currPointIndex == newPointIndex && _stepError == 0) { - if (_currPointIndex == 0) { - _yMoveTotalSteps = 0; - sendMessage(_parentScene, 0x2005, 0); - } else if (_currPointIndex == (int)_pathPoints->size()) { - _yMoveTotalSteps = 0; - sendMessage(_parentScene, 0x2006, 0); - } - } else { - moveToPrevPoint(); - } - } else { - _hasAgainDestPointIndex = true; - _againDestPointIndex = newPointIndex; - } - } - break; - case 0x2004: - // Move to the point closest to the parameter point - { - int minMatchIndex = -1; - int minMatchDistance, distance; - NPoint pt = param.asPoint(); - if (_yMoveTotalSteps <= 0 && !_isBusy) { - // Check if we're already exiting (or something) - if ((pt.x <= 20 && _exitDirection == 1) || - (pt.x >= 620 && _exitDirection == 3) || - (pt.y <= 20 && _exitDirection == 2) || - (pt.y >= 460 && _exitDirection == 4)) - break; - _destX = pt.x; - _destY = pt.y; - minMatchDistance = calcDistance(_destX, _destY, _x, _y) + 1; - for (int i = _currPointIndex + 1; i < (int)_pathPoints->size(); i++) { - distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y); - if (distance >= minMatchDistance) - break; - minMatchDistance = distance; - minMatchIndex = i; - } - for (int i = _currPointIndex; i >= 0; i--) { - distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y); - if (distance >= minMatchDistance) - break; - minMatchDistance = distance; - minMatchIndex = i; - } - if (minMatchIndex == -1) { - if (_currPointIndex == 0) - moveToPrevPoint(); - else - SetSpriteUpdate(NULL); - } else { - if (minMatchIndex > _currPointIndex) - moveToNextPoint(); - else - moveToPrevPoint(); - } - } else { - _hasAgainDestPoint = true; - _againDestPoint = pt; - } - } - break; - case 0x2007: - _yMoveTotalSteps = param.asInteger(); - _steps = 0; - _isBraking = false; - _lastDistance = 640; - SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint); - break; - case 0x2008: - _yMoveTotalSteps = param.asInteger(); - _steps = 0; - _isBraking = false; - _lastDistance = 640; - SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint); - break; - case 0x2009: - stEnterCar(); - break; - case 0x200A: - stLeaveCar(); - break; - case 0x200E: - stTurnCar(); - break; - case 0x200F: - stCarAtHome(); - _newDeltaXType = param.asInteger(); - break; - } - return messageResult; -} - -uint32 AsCommonCar::hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = AsCommonCar::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (_isBusy && param.asInteger() == 0x025424A2) - gotoNextState(); - break; - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -uint32 AsCommonCar::hmLeaveCar(int messageNum, const MessageParam ¶m, Entity *sender) { - switch (messageNum) { - case 0x2009: - stEnterCar(); - break; - case 0x3002: - sendMessage(_parentScene, 0x200A, 0); - SetMessageHandler(&AsCommonCar::handleMessage); - break; - } - return 0; -} - -void AsCommonCar::stCarAtHome() { - bool doDeltaX = _doDeltaX; - SetSpriteUpdate(NULL); - _hasAgainDestPoint = false; - _hasAgainDestPointIndex = false; - _isBraking = false; - _isBusy = false; - _isIdle = false; - _isMoving = false; - _rectFlag = false; - NextState(&AsCommonCar::stLeanForwardIdle); - startAnimation(0x35698F78, 0, -1); - setDoDeltaX(doDeltaX ? 1 : 0); - _currMoveDirection = 0; - _newMoveDirection = 0; - _steps = 0; - _idleCounter = 0; - _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24; - SetUpdateHandler(&AsCommonCar::upIdle); - SetMessageHandler(&AsCommonCar::handleMessage); - FinalizeState(&AsCommonCar::evIdleDone); -} - -void AsCommonCar::updateTurnMovement() { - if (_turnMoveStatus == 1) { - _lastDistance = 640; - _isIdle = false; - _isBraking = false; - SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint); - } else if (_turnMoveStatus == 2) { - _lastDistance = 640; - _isIdle = false; - _isBraking = false; - SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint); - } -} - -void AsCommonCar::updateMovement() { - if (_isBraking && !_isIdle && !_isBusy) { - gotoNextState(); - _isMoving = false; - _isIdle = true; - startAnimation(0x192ADD30, 0, -1); - SetUpdateHandler(&AsCommonCar::update); - SetMessageHandler(&AsCommonCar::hmAnimation); - NextState(&AsCommonCar::stLeanForwardIdle); - } else if (!_isBraking && _steps && _isIdle) { - gotoNextState(); - _isIdle = false; - startAnimation(0x9966B138, 0, -1); - SetUpdateHandler(&AsCommonCar::update); - SetMessageHandler(&AsCommonCar::hmAnimation); - NextState(&AsCommonCar::stUpdateMoveDirection); - } else if (_newMoveDirection != _currMoveDirection && _isMoving && !_isBusy) { - gotoNextState(); - _currMoveDirection = _newMoveDirection; - stUpdateMoveDirection(); - } -} - -void AsCommonCar::stEnterCar() { - startAnimation(0xA86A9538, 0, -1); - SetUpdateHandler(&AsCommonCar::update); - SetMessageHandler(&AsCommonCar::hmAnimation); - NextState(&AsCommonCar::stLeanForwardIdle); -} - -void AsCommonCar::stLeaveCar() { - startAnimation(0xA86A9538, -1, -1); - _playBackwards = true; - SetUpdateHandler(&AsCommonCar::update); - SetMessageHandler(&AsCommonCar::hmLeaveCar); -} - -void AsCommonCar::stLeanForwardIdle() { - startAnimation(0x35698F78, 0, -1); - _currMoveDirection = 0; - _newMoveDirection = 0; - _steps = 0; - _idleCounter = 0; - _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24; - SetUpdateHandler(&AsCommonCar::upIdle); - SetMessageHandler(&AsCommonCar::handleMessage); - FinalizeState(&AsCommonCar::evIdleDone); -} - -void AsCommonCar::evIdleDone() { - SetUpdateHandler(&AsCommonCar::update); -} - -void AsCommonCar::stIdleBlink() { - startAnimation(0xB579A77C, 0, -1); - _idleCounter = 0; - _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24; - SetUpdateHandler(&AsCommonCar::update); - SetMessageHandler(&AsCommonCar::hmAnimation); - NextState(&AsCommonCar::stLeanForwardIdle); -} - -void AsCommonCar::stUpdateMoveDirection() { - _isMoving = true; - if (_currMoveDirection == 1) - startAnimation(0xD4AA03A4, 0, -1); - else if (_currMoveDirection == 3) - startAnimation(0xD00A1364, 0, -1); - else if ((_currMoveDirection == 2 && _doDeltaX) || (_currMoveDirection == 4 && !_doDeltaX)) - stTurnCar(); - else - startAnimation(0xD4220027, 0, -1); - setGlobalVar(V_CAR_DELTA_X, _doDeltaX ? 1 : 0); -} - -void AsCommonCar::moveToNextPoint() { - if (_currPointIndex >= (int)_pathPoints->size() - 1) { - _yMoveTotalSteps = 0; - sendMessage(this, 0x1019, 0); - sendMessage(_parentScene, 0x2006, 0); - } else { - NPoint nextPt = pathPoint(_currPointIndex + 1); - NPoint currPt = pathPoint(_currPointIndex); - if (ABS(nextPt.y - currPt.y) <= ABS(nextPt.x - currPt.x) && - ((_currMoveDirection == 2 && nextPt.x < currPt.x) || - (_currMoveDirection == 4 && nextPt.x >= currPt.x))) { - if (_currMoveDirection == 2) - _currMoveDirection = 4; - else if (_currMoveDirection == 4) - _currMoveDirection = 2; - if (_isIdle) - stTurnCarMoveToNextPoint(); - else - stBrakeMoveToNextPoint(); - } else { - if (_steps == 0) { - gotoNextState(); - _isIdle = false; - startAnimation(0x9966B138, 0, -1); - SetMessageHandler(&AsCommonCar::hmAnimation); - SetUpdateHandler(&AsCommonCar::update); - NextState(&AsCommonCar::stUpdateMoveDirection); - } - _isBraking = false; - SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint); - _lastDistance = 640; - } - } -} - -void AsCommonCar::stBrakeMoveToNextPoint() { - gotoNextState(); - _isBusy = true; - _isBraking = true; - startAnimation(0x192ADD30, 0, -1); - SetUpdateHandler(&AsCommonCar::update); - SetMessageHandler(&AsCommonCar::hmAnimation); - NextState(&AsCommonCar::stTurnCarMoveToNextPoint); -} - -void AsCommonCar::stTurnCar() { - // Turn to left/right #1 - gotoNextState(); - _isBusy = true; - startAnimation(0xF46A0324, 0, -1); - SetUpdateHandler(&AsCommonCar::update); - SetMessageHandler(&AsCommonCar::hmAnimation); - FinalizeState(&AsCommonCar::evTurnCarDone); - _turnMoveStatus = 0; - updateTurnMovement(); -} - -void AsCommonCar::stTurnCarMoveToNextPoint() { - // Turn to left/right #2 - gotoNextState(); - _isBusy = true; - startAnimation(0xF46A0324, 0, -1); - SetUpdateHandler(&AsCommonCar::update); - SetMessageHandler(&AsCommonCar::hmAnimation); - FinalizeState(&AsCommonCar::evTurnCarDone); - _turnMoveStatus = 1; - updateTurnMovement(); -} - -void AsCommonCar::stTurnCarMoveToPrevPoint() { - // Turn to left/right #3 - FinalizeState(NULL); - _isBusy = true; - startAnimation(0xF46A0324, 0, -1); - SetUpdateHandler(&AsCommonCar::update); - SetMessageHandler(&AsCommonCar::hmAnimation); - FinalizeState(&AsCommonCar::evTurnCarDone); - _turnMoveStatus = 2; - updateTurnMovement(); -} - -void AsCommonCar::moveToPrevPoint() { - if (_currPointIndex == 0 && _stepError == 0) { - _yMoveTotalSteps = 0; - sendMessage(this, 0x1019, 0); - sendMessage(_parentScene, 0x2005, 0); - } else { - NPoint prevPt; - NPoint currPt; - if (_stepError == 0) { - prevPt = pathPoint(_currPointIndex - 1); - currPt = pathPoint(_currPointIndex); - } else { - prevPt = pathPoint(_currPointIndex); - currPt = pathPoint(_currPointIndex + 1); - } - if (ABS(prevPt.y - currPt.y) <= ABS(prevPt.x - currPt.x) && - ((_currMoveDirection == 2 && prevPt.x < currPt.x) || - (_currMoveDirection == 4 && prevPt.x >= currPt.x))) { - if (_currMoveDirection == 2) - _currMoveDirection = 4; - else if (_currMoveDirection == 4) - _currMoveDirection = 2; - if (_isIdle) - stTurnCarMoveToPrevPoint(); - else - stBrakeMoveToPrevPoint(); - } else { - if (_steps == 0) { - gotoNextState(); - _isIdle = false; - startAnimation(0x9966B138, 0, -1); - SetMessageHandler(&AsCommonCar::hmAnimation); - SetUpdateHandler(&AsCommonCar::update); - NextState(&AsCommonCar::stUpdateMoveDirection); - } - _isBraking = false; - SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint); - _lastDistance = 640; - } - } -} - -void AsCommonCar::stBrakeMoveToPrevPoint() { - FinalizeState(NULL); - _isBusy = true; - _isBraking = true; - startAnimation(0x192ADD30, 0, -1); - SetUpdateHandler(&AsCommonCar::update); - SetMessageHandler(&AsCommonCar::hmAnimation); - NextState(&AsCommonCar::stTurnCarMoveToPrevPoint); -} - -void AsCommonCar::evTurnCarDone() { - _isBusy = false; - setDoDeltaX(2); - _newMoveDirection = 0; - stUpdateMoveDirection(); -} - -void AsCommonCar::suMoveToNextPoint() { - int16 newX = _x, newY = _y; - - if (_currPointIndex >= (int)_pathPoints->size()) { - _yMoveTotalSteps = 0; - sendMessage(this, 0x1019, 0); - sendMessage(_parentScene, 0x2006, 0); - return; - } - - if (_isBraking) { - if (_steps <= 0) { - sendMessage(this, 0x1019, 0); - return; - } else - _steps--; - } else if (_steps < 11) - _steps++; - - bool firstTime = true; - _ySteps = _steps; - int stepsCtr = _steps; - - while (stepsCtr > 0) { - NPoint pt1; - NPoint pt2 = pathPoint(_currPointIndex); - if (_currPointIndex + 1 >= (int)_pathPoints->size()) - pt1 = pathPoint(0); - else - pt1 = pathPoint(_currPointIndex + 1); - int16 deltaX = ABS(pt1.x - pt2.x); - int16 deltaY = ABS(pt1.y - pt2.y); - if (deltaX >= deltaY) { - _newMoveDirection = 2; - if (pt1.x < pt2.x) - _newMoveDirection = 4; - if (stepsCtr + _stepError >= deltaX) { - stepsCtr -= deltaX; - stepsCtr += _stepError; - _stepError = 0; - _currPointIndex++; - if (_currPointIndex == (int)_pathPoints->size() - 1) - stepsCtr = 0; - newX = pathPoint(_currPointIndex).x; - newY = pathPoint(_currPointIndex).y; - } else { - _stepError += stepsCtr; - if (pt1.x >= pt2.x) - newX += stepsCtr; - else - newX -= stepsCtr; - if (pt1.y >= pt2.y) - newY = pt2.y + (deltaY * _stepError) / deltaX; - else - newY = pt2.y - (deltaY * _stepError) / deltaX; - stepsCtr = 0; - } - } else { - _newMoveDirection = 3; - if (pt1.y < pt2.y) - _newMoveDirection = 1; - if (firstTime) { - if (pt1.y >= pt2.y) - stepsCtr += 7; - else { - stepsCtr -= 4; - if (stepsCtr < 0) - stepsCtr = 0; - } - _ySteps = stepsCtr; - } - if (stepsCtr + _stepError >= deltaY) { - stepsCtr -= deltaY; - stepsCtr += _stepError; - _stepError = 0; - _currPointIndex++; - if (_currPointIndex == (int)_pathPoints->size() - 1) - stepsCtr = 0; - newX = pathPoint(_currPointIndex).x; - newY = pathPoint(_currPointIndex).y; - } else { - _stepError += stepsCtr; - if (pt1.x >= pt2.x) - newX = pt2.x + (deltaX * _stepError) / deltaY; - else - newX = pt2.x - (deltaX * _stepError) / deltaY; - if (pt1.y >= pt2.y) - newY += stepsCtr; - else - newY -= stepsCtr; - stepsCtr = 0; - } - } - firstTime = false; - } - - if (_yMoveTotalSteps != 0) { - _x = newX; - _y = newY; - _yMoveTotalSteps -= _ySteps; - if (_yMoveTotalSteps <= 0) { - _isBraking = true; - _yMoveTotalSteps = 0; - } - } else { - int distance = calcDistance(_destX, _destY, _x, _y); - _x = newX; - _y = newY; - if (newX > 20 && newX < 620 && newY > 20 && newY < 460) { - _exitDirection = 0; - _inMainArea = true; - } else if (_inMainArea) { - _destX = pathPoint(_pathPoints->size() - 1).x; - _destY = pathPoint(_pathPoints->size() - 1).y; - _inMainArea = false; - if (_x <= 20) - _exitDirection = 1; - else if (_x >= 620) - _exitDirection = 3; - else if (_y <= 20) - _exitDirection = 2; - else if (_y >= 460) - _exitDirection = 4; - if (_exitDirection != 0 && _isBraking) { - _isBraking = false; - _steps = 11; - } - } - if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) || - (_exitDirection == 0 && _lastDistance + 20 < distance)) - _isBraking = true; - if (distance < _lastDistance) - _lastDistance = distance; - if (_currPointIndex == (int)_pathPoints->size() - 1) { - _isBraking = true; - _yMoveTotalSteps = 0; - sendMessage(this, 0x1019, 0); - sendMessage(_parentScene, 0x2006, 0); - } - } - -} - -void AsCommonCar::suMoveToPrevPoint() { - int16 newX = _x, newY = _y; - - if (_currPointIndex == 0 && _stepError == 0) { - _yMoveTotalSteps = 0; - sendMessage(this, 0x1019, 0); - sendMessage(_parentScene, 0x2005, 0); - return; - } - - if (_isBraking) { - if (_steps <= 0) { - sendMessage(this, 0x1019, 0); - return; - } else - _steps--; - } else if (_steps < 11) - _steps++; - - bool firstTime = true; - _ySteps = _steps; - int stepsCtr = _steps; - - while (stepsCtr > 0) { - if (_stepError == 0) - _currPointIndex--; - NPoint pt1; - NPoint pt2 = pathPoint(_currPointIndex); - if (_currPointIndex + 1 >= (int)_pathPoints->size()) - pt1 = pathPoint(0); - else - pt1 = pathPoint(_currPointIndex + 1); - int16 deltaX = ABS(pt1.x - pt2.x); - int16 deltaY = ABS(pt1.y - pt2.y); - if (deltaX >= deltaY) { - _newMoveDirection = 4; - if (pt1.x < pt2.x) - _newMoveDirection = 2; - if (_stepError == 0) - _stepError = deltaX; - if (stepsCtr > _stepError) { - stepsCtr -= _stepError; - _stepError = 0; - if (_currPointIndex == 0) - stepsCtr = 0; - newX = pathPoint(_currPointIndex).x; - newY = pathPoint(_currPointIndex).y; - } else { - _stepError -= stepsCtr; - if (pt1.x >= pt2.x) - newX -= stepsCtr; - else - newX += stepsCtr; - if (pt1.y >= pt2.y) - newY = pt2.y + (deltaY * _stepError) / deltaX; - else - newY = pt2.y - (deltaY * _stepError) / deltaX; - stepsCtr = 0; - } - } else { - _newMoveDirection = 1; - if (pt1.y < pt2.y) - _newMoveDirection = 3; - if (firstTime) { - if (pt1.y >= pt2.y) { - stepsCtr -= 4; - if (stepsCtr < 0) - stepsCtr = 0; - } else { - stepsCtr += 7; - } - _ySteps = stepsCtr; - } - if (_stepError == 0) - _stepError = deltaY; - if (stepsCtr > _stepError) { - stepsCtr -= _stepError; - _stepError = 0; - if (_currPointIndex == 0) - stepsCtr = 0; - newX = pathPoint(_currPointIndex).x; - newY = pathPoint(_currPointIndex).y; - } else { - _stepError -= stepsCtr; - if (pt1.x >= pt2.x) - newX = pt2.x + (deltaX * _stepError) / deltaY; - else - newX = pt2.x - (deltaX * _stepError) / deltaY; - if (pt1.y >= pt2.y) - newY -= stepsCtr; - else - newY += stepsCtr; - stepsCtr = 0; - } - } - firstTime = false; - } - - if (_yMoveTotalSteps != 0) { - _x = newX; - _y = newY; - _yMoveTotalSteps -= _ySteps; - if (_yMoveTotalSteps <= 0) { - _isBraking = true; - _yMoveTotalSteps = 0; - } - } else { - int distance = calcDistance(_destX, _destY, _x, _y); - _x = newX; - _y = newY; - if (newX > 20 && newX < 620 && newY > 20 && newY < 460) { - _exitDirection = 0; - _inMainArea = true; - } else if (_inMainArea) { - _destX = pathPoint(0).x; - _destY = pathPoint(0).y; - _inMainArea = false; - if (_x <= 20) - _exitDirection = 1; - else if (_x >= 620) - _exitDirection = 3; - else if (_y <= 20) - _exitDirection = 2; - else if (_y >= 460) - _exitDirection = 4; - if (_exitDirection != 0 && _isBraking) { - _isBraking = false; - _steps = 11; - } - } - if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) || - (_exitDirection == 0 && _lastDistance + 20 < distance)) - _isBraking = true; - if (distance < _lastDistance) - _lastDistance = distance; - if (_currPointIndex == 0 && _stepError == 0) { - _isBraking = true; - _yMoveTotalSteps = 0; - sendMessage(this, 0x1019, 0); - sendMessage(_parentScene, 0x2005, 0); - } - } - -} - -void AsCommonCar::updateSound() { - int maxSoundCounter = 0; - _soundCounter++; - if (_steps != 0 && !_isIdle) { - if (_currMoveDirection == 1) - maxSoundCounter = 18 - _steps; - else if (_currMoveDirection == 3) { - maxSoundCounter = 5 - _steps; - if (maxSoundCounter < 1) - maxSoundCounter = 1; - } else - maxSoundCounter = 14 - _steps; - } else - maxSoundCounter = 21; - if (_soundCounter >= maxSoundCounter) { - sendMessage(_parentScene, 0x200D, 0); - _soundCounter = 0; - } -} - -AsCommonIdleCarLower::AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y) - : AnimatedSprite(vm, 0x1209E09F, 1100, x, y) { - - setDoDeltaX(1); - startAnimation(0x1209E09F, 1, -1); - _newStickFrameIndex = 1; -} - -AsCommonIdleCarFull::AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y) - : AnimatedSprite(vm, 0x1209E09F, 100, x, y) { - - setDoDeltaX(1); - _newStickFrameIndex = 0; -} - -AsCommonCarConnector::AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar) - : AnimatedSprite(vm, 1100), _asCar(asCar) { - - createSurface1(0x60281C10, 150); - startAnimation(0x60281C10, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - SetUpdateHandler(&AsCommonCarConnector::update); -} - -void AsCommonCarConnector::update() { - _x = _asCar->getX(); - _y = _asCar->getY(); - AnimatedSprite::update(); -} - -void Tracks::findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance, - DataResource &dataResource) { - const uint trackCount = size(); - minMatchTrackIndex = -1; - minMatchDistance = 640; - for (uint trackIndex = 0; trackIndex < trackCount; trackIndex++) { - NPointArray *pointList = dataResource.getPointArray((*this)[trackIndex]->trackPointsName); - for (uint pointIndex = 0; pointIndex < pointList->size(); pointIndex++) { - NPoint testPt = (*pointList)[pointIndex]; - int distance = calcDistance(testPt.x, testPt.y, pt.x, pt.y); - if (distance < minMatchDistance) { - minMatchTrackIndex = trackIndex; - minMatchDistance = distance; - } - } - } -} - -Scene1608::Scene1608(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _asCar(NULL), _countdown1(0) { - - setGlobalVar(V_CAR_DELTA_X, 1); - - SetMessageHandler(&Scene1608::hmLowerFloor); - - _asKey = insertSprite(this, 1, 1100, 198, 220); - addCollisionSprite(_asKey); - - if (which < 0) { - // Restoring game - if (_vm->gameState().which == 1) - // Klaymen is in the car - which = 1; - else { - // Klaymen is standing around - setRectList(0x004B47D0); - insertKlaymen(380, 438); - _kmScene1608 = _klaymen; - _klaymenInCar = false; - _sprite1 = insertStaticSprite(0x7D0404E8, 1100); - setMessageList(0x004B46A8); - setBackground(0x10080E01); - setPalette(0x10080E01); - _asTape = insertSprite(this, 13, 1100, 412, 443, 0x9148A011); - addCollisionSprite(_asTape); - _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); - SetUpdateHandler(&Scene1608::upLowerFloor); - insertScreenMouse(0x80E05108); - insertStaticSprite(0x4B18F868, 1200); - } - } else if (which == 0) { - // Klaymen entering from the left - _vm->gameState().which = 0; - setRectList(0x004B47D0); - insertKlaymen(0, 438); - _kmScene1608 = _klaymen; - _klaymenInCar = false; - setMessageList(0x004B46B0); - setBackground(0x10080E01); - setPalette(0x10080E01); - _asTape = insertSprite(this, 13, 1100, 412, 443, 0x9148A011); - addCollisionSprite(_asTape); - insertScreenMouse(0x80E05108); - _sprite1 = insertStaticSprite(0x7D0404E8, 1100); - _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); - SetUpdateHandler(&Scene1608::upLowerFloor); - insertStaticSprite(0x4B18F868, 1200); - } else if (which == 2) { - // Klaymen returning from looking through the upper window - _vm->gameState().which = 1; - _dataResource.load(0x003C0492); - _roomPathPoints = _dataResource.getPointArray(calcHash("meArchroArchRoomPath")); - setBackground(0x98001604); - setPalette(0x98001604); - _palette->addPalette("paPodRed", 65, 31, 65); - insertScreenMouse(0x01600988); - _sprite2 = insertStaticSprite(0x491F38A8, 1100); - _asCar = createSprite(this, 375, 227); // Create but don't add to the sprite list yet - _asIdleCarLower = insertSprite(375, 227); - _asIdleCarFull = insertSprite(375, 227); - _asCar->setVisible(false); - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { - insertKlaymen(373, 220); - _klaymen->setDoDeltaX(1); - } else - insertKlaymen(283, 220); - _kmScene1608 = _klaymen; - setMessageList(0x004B47A8); - SetMessageHandler(&Scene1608::hmUpperFloor); - SetUpdateHandler(&Scene1608::upUpperFloor); - _asCar->setPathPoints(_roomPathPoints); - sendMessage(_asCar, 0x2002, _roomPathPoints->size() - 1); - _sprite3 = insertStaticSprite(0xB47026B0, 1100); - _clipRect1.set(_sprite3->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2()); - _clipRect3.set(_sprite2->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2()); - _clipRect2 = _clipRect1; - _clipRect2.y2 = 215; - _klaymen->setClipRect(_clipRect1); - _asCar->setClipRect(_clipRect1); - _asIdleCarLower->setClipRect(_clipRect1); - _asIdleCarFull->setClipRect(_clipRect1); - _asTape = insertSprite(this, 13, 1100, 412, 443, 0x9148A011); - addCollisionSprite(_asTape); - insertSprite(_asCar)->setClipRect(_clipRect1); - _klaymenInCar = false; - _carClipFlag = false; - _carStatus = 0; - setRectList(0x004B4810); - } - - // NOTE: Not in the else because 'which' is set to 1 in the true branch - if (which == 1) { - // Klaymen riding the car - _vm->gameState().which = 1; - _dataResource.load(0x003C0492); - _roomPathPoints = _dataResource.getPointArray(calcHash("meArchroArchRoomPath")); - setBackground(0x98001604); - setPalette(0x98001604); - _palette->addPalette("paPodRed", 65, 31, 65); - insertScreenMouse(0x01600988); - _asCar = insertSprite(this, 375, 227); - _asIdleCarLower = insertSprite(375, 227); - _asIdleCarFull = insertSprite(375, 227); - _sprite2 = insertStaticSprite(0x491F38A8, 1100); - _kmScene1608 = createSprite(this, 439, 220); - sendMessage(_kmScene1608, 0x2032, 1); - _kmScene1608->setDoDeltaX(1); - SetMessageHandler(&Scene1608::hmRidingCar); - SetUpdateHandler(&Scene1608::upRidingCar); - _asIdleCarLower->setVisible(false); - _asIdleCarFull->setVisible(false); - _asCar->setPathPoints(_roomPathPoints); - sendMessage(_asCar, 0x2002, 0); - sendMessage(_asCar, 0x2008, 90); - _sprite3 = insertStaticSprite(0xB47026B0, 1100); - _clipRect1.set(_sprite3->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2()); - _clipRect3.set(_sprite2->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2()); - _clipRect2 = _clipRect1; - _clipRect2.y2 = 215; - _kmScene1608->setClipRect(_clipRect1); - _asCar->setClipRect(_clipRect1); - _asIdleCarLower->setClipRect(_clipRect1); - _asIdleCarFull->setClipRect(_clipRect1); - _asTape = insertSprite(this, 13, 1100, 412, 443, 0x9148A011); - // ... addCollisionSprite(_asTape); - insertSprite(_asCar)->setClipRect(_clipRect1); - _klaymenInCar = true; - _carClipFlag = true; - _carStatus = 0; - } - - _palette->addPalette("paKlayRed", 0, 64, 0); - -} - -Scene1608::~Scene1608() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _kmScene1608->isDoDeltaX() ? 1 : 0); - if (_klaymenInCar) - delete _kmScene1608; - else - delete _asCar; -} - -void Scene1608::upLowerFloor() { - Scene::update(); - if (_countdown1 != 0 && (--_countdown1 == 0)) - leaveScene(0); -} - -void Scene1608::upUpperFloor() { - Scene::update(); - if (_carStatus == 1) { - removeSurface(_klaymen->getSurface()); - removeEntity(_klaymen); - addSprite(_asCar); - _klaymenInCar = true; - clearRectList(); - SetUpdateHandler(&Scene1608::upCarAtHome); - SetMessageHandler(&Scene1608::hmCarAtHome); - _asIdleCarLower->setVisible(false); - _asIdleCarFull->setVisible(false); - _asCar->setVisible(true); - sendMessage(_asCar, 0x2009, 0); - _asCar->handleUpdate(); - _klaymen = NULL; - _carStatus = 0; - } - updateKlaymenCliprect(); -} - -void Scene1608::upCarAtHome() { - Scene::update(); - if (_mouseClicked) { - if (_mouseClickPos.x <= 329 && _asCar->getX() == 375 && _asCar->getY() == 227) { - sendMessage(_asCar, 0x200A, 0); - SetUpdateHandler(&Scene1608::upGettingOutOfCar); - } else { - sendPointMessage(_asCar, 0x2004, _mouseClickPos); - SetMessageHandler(&Scene1608::hmRidingCar); - SetUpdateHandler(&Scene1608::upRidingCar); - } - _mouseClicked = false; - } - updateKlaymenCliprect(); -} - -void Scene1608::upGettingOutOfCar() { - Scene::update(); - if (_carStatus == 2) { - _klaymen = _kmScene1608; - removeSurface(_asCar->getSurface()); - removeEntity(_asCar); - addSprite(_klaymen); - _klaymenInCar = false; - SetMessageHandler(&Scene1608::hmUpperFloor); - SetUpdateHandler(&Scene1608::upUpperFloor); - setRectList(0x004B4810); - _asIdleCarLower->setVisible(true); - _asIdleCarFull->setVisible(true); - _asCar->setVisible(false); - setMessageList(0x004B4748); - processMessageList(); - _klaymen->handleUpdate(); - _carStatus = 0; - } - updateKlaymenCliprect(); -} - -void Scene1608::upRidingCar() { - Scene::update(); - if (_mouseClicked) { - sendPointMessage(_asCar, 0x2004, _mouseClickPos); - _mouseClicked = false; - } - if (_asCar->getX() < 300) { - if (_carClipFlag) { - _carClipFlag = false; - _asCar->setClipRect(_clipRect1); - if (!_asCar->isDoDeltaX()) - sendMessage(_asCar, 0x200E, 0); - } - } else if (!_carClipFlag) { - _carClipFlag = true; - _asCar->setClipRect(_clipRect3); - } -} - -uint32 Scene1608::hmLowerFloor(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x20250B1A) { - clearRectList(); - _klaymen->setVisible(false); - showMouse(false); - _sprite1->setVisible(false); - //sendMessage(_asDoor, 0x4809, 0); // Play sound? - _countdown1 = 28; - } - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - case 0x4826: - if (sender == _asTape) { - sendEntityMessage(_kmScene1608, 0x1014, _asTape); - setMessageList(0x004B4770); - } else if (sender == _asKey) - setMessageList(0x004B46C8); - break; - } - return 0; -} - -uint32 Scene1608::hmUpperFloor(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x60842040) - _carStatus = 1; - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - case 0x4826: - if (sender == _asKey) { - sendEntityMessage(_kmScene1608, 0x1014, _asKey); - setMessageList(0x004B4760); - } - break; - } - return 0; -} - -uint32 Scene1608::hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2005: - leaveScene(1); - break; - case 0x2006: - SetMessageHandler(&Scene1608::hmCarAtHome); - SetUpdateHandler(&Scene1608::upCarAtHome); - sendMessage(_asCar, 0x200F, 1); - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - } - return 0; -} - -uint32 Scene1608::hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x200A: - _carStatus = 2; - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - } - return 0; -} - -void Scene1608::updateKlaymenCliprect() { - if (_kmScene1608->getX() <= 375) - _kmScene1608->setClipRect(_clipRect1); - else - _kmScene1608->setClipRect(_clipRect2); -} - -Scene1609::Scene1609(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule), _countdown1(1), _currentSymbolIndex(0), _symbolPosition(0), _changeCurrentSymbol(true), _isSolved(false) { - - _vm->gameModule()->initCodeSymbolsPuzzle(); - _noisySymbolIndex = getGlobalVar(V_NOISY_SYMBOL_INDEX); - - SetMessageHandler(&Scene1609::handleMessage); - SetUpdateHandler(&Scene1609::update); - - setBackground(0x92124A14); - setPalette(0x92124A14); - insertPuzzleMouse(0x24A10929, 20, 620); - - for (int symbolPosition = 0; symbolPosition < 12; symbolPosition++) - _asSymbols[symbolPosition] = insertSprite(symbolPosition, false); - - _ssButton = insertSprite(this, true); - addCollisionSprite(_ssButton); - loadSound(0, 0x68E25540); - -} - -void Scene1609::update() { - if (!_isSolved && _countdown1 != 0 && (--_countdown1 == 0)) { - if (_changeCurrentSymbol) { - _currentSymbolIndex++; - if (_currentSymbolIndex >= 12) - _currentSymbolIndex = 0; - _asSymbols[_symbolPosition]->change(_currentSymbolIndex + 12, _currentSymbolIndex == (int)getSubVar(VA_CODE_SYMBOLS, _noisySymbolIndex)); - _changeCurrentSymbol = false; - _countdown1 = 36; - } else { - _asSymbols[_symbolPosition]->hide(); - _changeCurrentSymbol = true; - _countdown1 = 12; - } - } - if (_isSolved && !isSoundPlaying(0)) - leaveScene(1); - Scene::update(); -} - -uint32 Scene1609::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) - leaveScene(0); - break; - case 0x2000: - if (!_isSolved) { - if (_changeCurrentSymbol) - _asSymbols[_symbolPosition]->change(_currentSymbolIndex + 12, false); - _asSymbols[_symbolPosition]->stopSymbolSound(); - _symbolPosition++; - if (_symbolPosition >= 12) { - if (testVars()) { - playSound(0); - setGlobalVar(V_CODE_SYMBOLS_SOLVED, 1); - _isSolved = true; - } else { - _symbolPosition = 0; - for (int i = 0; i < 12; i++) - _asSymbols[i]->hide(); - } - } - _changeCurrentSymbol = true; - _countdown1 = 1; - } - break; - } - return 0; -} - -bool Scene1609::testVars() { - int cmpSymbolIndex = 0; - - // Find the position of the first symbol - while ((int)getSubVar(VA_CODE_SYMBOLS, cmpSymbolIndex) != _asSymbols[0]->getSymbolIndex()) - cmpSymbolIndex++; - - // Check if the entered symbols match - for (int enteredSymbolIndex = 0; enteredSymbolIndex < 12; enteredSymbolIndex++) { - if ((int)getSubVar(VA_CODE_SYMBOLS, cmpSymbolIndex) != _asSymbols[enteredSymbolIndex]->getSymbolIndex()) - return false; - cmpSymbolIndex++; - if (cmpSymbolIndex >= 12) - cmpSymbolIndex = 0; - } - - return true; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module1600.h b/engines/neverhood/module1600.h deleted file mode 100644 index 0743767244..0000000000 --- a/engines/neverhood/module1600.h +++ /dev/null @@ -1,183 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE1600_H -#define NEVERHOOD_MODULE1600_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/module3000.h" - -namespace Neverhood { - -// Module1600 - -class Module1600 : public Module { -public: - Module1600(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module1600(); -protected: - int _sceneNum; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -class AsCommonCar : public AnimatedSprite { -public: - AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y); - ~AsCommonCar(); - void setPathPoints(NPointArray *pathPoints); -protected: - Scene *_parentScene; - NPointArray *_pathPoints; - int _newMoveDirection; - int _currMoveDirection; - int _exitDirection; - int _currPointIndex; - bool _hasAgainDestPoint; - NPoint _againDestPoint; - bool _hasAgainDestPointIndex; - int _againDestPointIndex; - bool _inMainArea; - bool _isBraking; - bool _isBusy; - bool _isIdle; - bool _isMoving; - bool _rectFlag; - int _idleCounter; - int _idleCounterMax; - int _steps; - int _stepError; - int _lastDistance; - int _yMoveTotalSteps; - int _ySteps; - int _newDeltaXType; - int _soundCounter; - int _turnMoveStatus; - int16 _destX, _destY; - NPoint pathPoint(uint index) { return (*_pathPoints)[index]; } - void update(); - void upIdle(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmLeaveCar(int messageNum, const MessageParam ¶m, Entity *sender); - void stCarAtHome(); - void updateTurnMovement(); - void updateMovement(); - void stEnterCar(); - void stLeaveCar(); - void stLeanForwardIdle(); - void evIdleDone(); - void stIdleBlink(); - void stUpdateMoveDirection(); - void stTurnCar(); - void moveToNextPoint(); - void stBrakeMoveToNextPoint(); - void stTurnCarMoveToNextPoint(); - void moveToPrevPoint(); - void stBrakeMoveToPrevPoint(); - void stTurnCarMoveToPrevPoint(); - void evTurnCarDone(); - void suMoveToNextPoint(); - void suMoveToPrevPoint(); - void updateSound(); -}; - -class AsCommonIdleCarLower : public AnimatedSprite { -public: - AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y); -}; - -class AsCommonIdleCarFull : public AnimatedSprite { -public: - AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y); -}; - -class AsCommonCarConnector : public AnimatedSprite { -public: - AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar); -protected: - AsCommonCar *_asCar; - void update(); -}; - -class Tracks : public Common::Array { -public: - void findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance, - DataResource &dataResource); -}; - -class Scene1608 : public Scene { -public: - Scene1608(NeverhoodEngine *vm, Module *parentModule, int which); - ~Scene1608(); -protected: - AsCommonCar *_asCar; - Sprite *_asKey; - Sprite *_asIdleCarLower; - Sprite *_asIdleCarFull; - Sprite *_sprite1; - Sprite *_sprite2; - Sprite *_sprite3; - Sprite *_asTape; - Klaymen *_kmScene1608; - NRect _clipRect1; - NRect _clipRect2; - NRect _clipRect3; - int _carStatus; - bool _carClipFlag; - bool _klaymenInCar; - int _countdown1; - NPointArray *_roomPathPoints; - void upLowerFloor(); - void upUpperFloor(); - void upCarAtHome(); - void upGettingOutOfCar(); - void upRidingCar(); - uint32 hmLowerFloor(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmUpperFloor(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender); - void updateKlaymenCliprect(); -}; - -class Scene1609 : public Scene { -public: - Scene1609(NeverhoodEngine *vm, Module *parentModule); -protected: - Sprite *_ssButton; - AsScene3011Symbol *_asSymbols[12]; - int _currentSymbolIndex; - int _noisySymbolIndex; - int _symbolPosition; - int _countdown1; - bool _changeCurrentSymbol; - bool _isSolved; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - bool testVars(); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE1600_H */ diff --git a/engines/neverhood/module1700.cpp b/engines/neverhood/module1700.cpp deleted file mode 100644 index 183b0b8e75..0000000000 --- a/engines/neverhood/module1700.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* 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/module1700.h" -#include "neverhood/gamemodule.h" - -namespace Neverhood { - -static const uint32 kModule1700SoundList[] = { - 0xB288D450, - 0x90804450, - 0x99801500, - 0xB288D455, - 0x93825040, - 0 -}; - -Module1700::Module1700(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - _vm->_soundMan->addMusic(0x04212331, 0x31114225); - _vm->_soundMan->addSoundList(0x04212331, kModule1700SoundList); - _vm->_soundMan->setSoundListParams(kModule1700SoundList, true, 50, 600, 5, 150); - _vm->_soundMan->playTwoSounds(0x04212331, 0x41861371, 0x43A2507F, 0); - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else if (which == 0) - createScene(0, -1); - else if (which == 1) - createScene(4, 1); - else - createScene(4, 3); - -} - -Module1700::~Module1700() { - _vm->_soundMan->deleteGroup(0x04212331); -} - -void Module1700::createScene(int sceneNum, int which) { - debug("Module1700::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _vm->_soundMan->setSoundListParams(kModule1700SoundList, false, 0, 0, 0, 0); - createSmackerScene(0x3028A005, true, true, false); - break; - case 1: - _vm->gameState().sceneNum = 1; - createNavigationScene(0x004AE8B8, which); - break; - case 2: - _vm->gameState().sceneNum = 2; - createNavigationScene(0x004AE8E8, which); - break; - case 3: - _vm->gameState().sceneNum = 3; - _vm->_soundMan->setSoundListParams(kModule1700SoundList, false, 0, 0, 0, 0); - createSmackerScene(0x01190041, true, true, false); - break; - case 4: - _vm->gameState().sceneNum = 4; - _vm->_soundMan->setSoundListParams(kModule1700SoundList, false, 0, 0, 0, 0); - _vm->_soundMan->startMusic(0x31114225, 0, 2); - _childObject = new Scene1705(_vm, this, which); - break; - } - SetUpdateHandler(&Module1700::updateScene); - _childObject->handleUpdate(); -} - -void Module1700::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - _vm->_soundMan->setSoundListParams(kModule1700SoundList, true, 0, 0, 0, 0); - createScene(1, 0); - break; - case 1: - if (_moduleResult == 0) - createScene(2, 0); - else if (_moduleResult == 1) - createScene(1, 1); - break; - case 2: - if (_moduleResult == 0) - createScene(3, -1); - else if (_moduleResult == 1) - createScene(1, 1); - else if (_moduleResult == 2) { - if (!isSoundPlaying(0)) { - setSoundVolume(0, 60); - playSound(0, 0x58B45E58); - } - createScene(2, 2); - } - break; - case 3: - createScene(4, 0); - break; - case 4: - leaveModule(1); - break; - } - } -} - -// Scene1705 - -static const uint32 kScene1705FileHashes[] = { - 0x910EA801, 0x920EA801, 0x940EA801, - 0x980EA801, 0x800EA801, 0xB00EA801, - 0xD00EA801, 0x100EA801, 0x900EA800, - 0xD10EA801, 0x110EA801, 0x910EA800 -}; - -SsScene1705WallSymbol::SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex) - : StaticSprite(vm, fileHash, 100) { - - _x = _spriteResource.getPosition().x + symbolIndex * 30; - _y = _spriteResource.getPosition().y + 160; - updatePosition(); -} - -SsScene1705Tape::SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash) - : StaticSprite(vm, fileHash, surfacePriority, x - 24, y - 4), _parentScene(parentScene), _tapeIndex(tapeIndex) { - - if (!getSubVar(VA_HAS_TAPE, _tapeIndex) && !getSubVar(VA_IS_TAPE_INSERTED, _tapeIndex)) { - SetMessageHandler(&SsScene1705Tape::handleMessage); - } else { - setVisible(false); - SetMessageHandler(NULL); - } - _collisionBoundsOffset = _drawOffset; - _collisionBoundsOffset.x -= 4; - _collisionBoundsOffset.y -= 8; - _collisionBoundsOffset.width += 8; - _collisionBoundsOffset.height += 16; - Sprite::updateBounds(); -} - -uint32 SsScene1705Tape::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x4806: - setSubVar(VA_HAS_TAPE, _tapeIndex, 1); - setVisible(false); - SetMessageHandler(NULL); - break; - } - return messageResult; -} - -Scene1705::Scene1705(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _paletteArea(1) { - - Sprite *tempSprite; - - setGlobalVar(V_FELL_DOWN_HOLE, 1); - _vm->gameModule()->initCannonSymbolsPuzzle(); - - SetMessageHandler(&Scene1705::handleMessage); - SetUpdateHandler(&Scene1705::update); - - setHitRects(0x004B69D8); - setBackground(0x03118226); - setPalette(0x03118226); - _palette->addBasePalette(0x91D3A391, 0, 64, 0); - _palette->copyBasePalette(0, 256, 0); - addEntity(_palette); - insertScreenMouse(0x18222039); - - insertSprite(kScene1705FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_2, 0)], 0); - insertSprite(kScene1705FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_2, 1)], 1); - insertSprite(kScene1705FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_2, 2)], 2); - _sprite = insertStaticSprite(0x31313A22, 1100); - _ssTape = insertSprite(this, 15, 1100, 238, 439, 0x02363852); - addCollisionSprite(_ssTape); - - if (which < 0) { - // Restoring game - insertKlaymen(231, 434); - setMessageList(0x004B69E8); - sendMessage(this, 0x2000, 0); - _klaymen->setClipRect(0, 0, _sprite->getDrawRect().x2(), 480); - } else if (which == 1) { - // Klaymen teleporting in - insertKlaymen(431, 434); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B6A08, false); - sendMessage(this, 0x2000, 1); - _klaymen->setClipRect(0, 0, _sprite->getDrawRect().x2(), 480); - } else if (which == 2) { - // Klaymen teleporting out - insertKlaymen(431, 434); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B6AA0, false); - sendMessage(this, 0x2000, 1); - _klaymen->setClipRect(0, 0, _sprite->getDrawRect().x2(), 480); - } else if (which == 3) { - // Klaymen returning from teleporter console - insertKlaymen(431, 434); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B6A18, false); - sendMessage(this, 0x2000, 1); - _klaymen->setClipRect(0, 0, _sprite->getDrawRect().x2(), 480); - } else { - // Klaymen falling through the hole - insertKlaymen(231, 74); - sendMessage(_klaymen, 0x2000, 0); - setMessageList(0x004B69F0); - sendMessage(this, 0x2000, 0); - tempSprite = insertStaticSprite(0x30303822, 1100); - _klaymen->setClipRect(0, tempSprite->getDrawRect().y, _sprite->getDrawRect().x2(), 480); - } - -} - -void Scene1705::update() { - Scene::update(); - if (_klaymen->getX() < 224 && _paletteArea != 0) { - _palette->addBasePalette(0xF2210C15, 0, 64, 0); - _palette->startFadeToPalette(12); - _paletteArea = 0; - } else if (_klaymen->getX() >= 224 && _paletteArea == 0) { - _palette->addBasePalette(0x91D3A391, 0, 64, 0); - _palette->startFadeToPalette(12); - _paletteArea = 1; - } -} - -uint32 Scene1705::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - if (param.asInteger()) { - setRectList(0x004B6B40); - _klaymen->setKlaymenIdleTable3(); - } else { - setRectList(0x004B6B30); - _klaymen->setKlaymenIdleTable1(); - } - break; - case 0x4826: - if (sender == _ssTape && _klaymen->getX() <= 318) { - sendEntityMessage(_klaymen, 0x1014, sender); - setMessageList(0x004B6AC0); - } - break; - } - return 0; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module1700.h b/engines/neverhood/module1700.h deleted file mode 100644 index 26e1a5e0b0..0000000000 --- a/engines/neverhood/module1700.h +++ /dev/null @@ -1,72 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE1700_H -#define NEVERHOOD_MODULE1700_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/smackerscene.h" - -namespace Neverhood { - -class Module1700 : public Module { -public: - Module1700(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module1700(); -protected: - int _sceneNum; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -// Scene1705 - -class SsScene1705WallSymbol : public StaticSprite { -public: - SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex); -}; - -class SsScene1705Tape : public StaticSprite { -public: - SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash); -protected: - Scene *_parentScene; - uint32 _tapeIndex; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene1705 : public Scene { -public: - Scene1705(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_sprite; - Sprite *_ssTape; - int _paletteArea; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE1700_H */ diff --git a/engines/neverhood/module1800.cpp b/engines/neverhood/module1800.cpp deleted file mode 100644 index 99b51295b7..0000000000 --- a/engines/neverhood/module1800.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* 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/module1800.h" -#include "neverhood/navigationscene.h" -#include "neverhood/menumodule.h" - -namespace Neverhood { - -static const uint32 kModule1800SoundList[] = { - 0x16805548, - 0x16805048, - 0xD0E14441, - 0x90E090C2, - 0x90E1D0C2, - 0x90E2D0C2, - 0 -}; - -Module1800::Module1800(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - _vm->_soundMan->addSoundList(0x04A14718, kModule1800SoundList); - _vm->_soundMan->setSoundListParams(kModule1800SoundList, true, 50, 600, 10, 150); - _vm->_soundMan->playTwoSounds(0x04A14718, 0x8A382B55, 0x0C242F1D, 0); - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else if (which == 2) - createScene(5, 0); - else if (which == 3) - createScene(0, 0); - else - createScene(3, 1); - -} - -Module1800::~Module1800() { - _vm->_soundMan->deleteGroup(0x04A14718); -} - -void Module1800::createScene(int sceneNum, int which) { - static const byte kNavigationTypes00[] = {1, 0, 2, 0}; - static const byte kNavigationTypes01[] = {5}; - debug("Module1800::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - createNavigationScene(0x004AFD38, which, kNavigationTypes00); - break; - case 1: - _vm->gameState().sceneNum = 1; - createNavigationScene(0x004AFD98, which, kNavigationTypes01); - break; - case 2: - _vm->gameState().sceneNum = 2; - createSmackerScene(0x006C0085, true, true, false); - break; - case 3: - _vm->gameState().sceneNum = 3; - createNavigationScene(0x004AFDB0, which); - break; - case 4: - _vm->gameState().sceneNum = 4; - createNavigationScene(0x004AFDE0, which); - break; - case 5: - _vm->gameState().sceneNum = 5; - createNavigationScene(0x004AFE40, which); - break; - case 6: - _vm->gameState().sceneNum = 6; - _vm->_soundMan->deleteGroup(0x04A14718); - createSmackerScene(0x08D84010, true, true, false); - break; - case 7: - _vm->gameState().sceneNum = 7; - _vm->_soundMan->setSoundListParams(kModule1800SoundList, false, 0, 0, 0, 0); - createSmackerScene(0x0168B121, true, true, false); - break; - case 8: - _vm->gameState().sceneNum = 8; - _childObject = new CreditsScene(_vm, this, false); - break; - case 1009: - _vm->gameState().sceneNum = 3; - // NOTE: Newly introduced sceneNum 1009 (was duplicate 3 with own update handler) - createSmackerScene(0x0A840C01, true, true, false); - break; - } - SetUpdateHandler(&Module1800::updateScene); - _childObject->handleUpdate(); -} - -void Module1800::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 1) - createScene(4, 0); - else if (_moduleResult == 2) - createScene(1, -1); - else if (_moduleResult == 3) - createScene(3, 0); - break; - case 1: - if (_navigationAreaType == 3) - createScene(7, -1); - else - createScene(2, -1); - break; - case 2: - createScene(0, 2); - break; - case 3: - if (_moduleResult == 0) - createScene(1009, -1); - else if (_moduleResult == 1) - createScene(0, 1); - break; - case 4: - if (_moduleResult == 0) - createScene(6, -1); - else if (_moduleResult == 1) - createScene(5, 0); - else if (_moduleResult == 2) - createScene(0, 3); - else if (_moduleResult == 3) - createScene(4, 3); - break; - case 5: - if (_moduleResult == 0) - leaveModule(2); - else if (_moduleResult == 1) - createScene(4, 3); - break; - case 6: - createScene(8, -1); - break; - case 7: - leaveModule(3); - break; - case 8: - // NOTE: After Klaymen jumped into the hole and died... - leaveModule(1); - break; - case 1009: - leaveModule(0); - break; - } - } else { - switch (_sceneNum) { - case 0: - if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 2) - _vm->_soundMan->setTwoSoundsPlayFlag(false); - break; - } - } -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module1800.h b/engines/neverhood/module1800.h deleted file mode 100644 index 3c1d02e09c..0000000000 --- a/engines/neverhood/module1800.h +++ /dev/null @@ -1,46 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE1800_H -#define NEVERHOOD_MODULE1800_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" - -namespace Neverhood { - -// Module1800 - -class Module1800 : public Module { -public: - Module1800(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module1800(); -protected: - int _sceneNum; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE1800_H */ diff --git a/engines/neverhood/module1900.cpp b/engines/neverhood/module1900.cpp deleted file mode 100644 index 348306f39b..0000000000 --- a/engines/neverhood/module1900.cpp +++ /dev/null @@ -1,650 +0,0 @@ -/* 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/module1900.h" -#include "neverhood/gamemodule.h" - -namespace Neverhood { - -static const uint32 kModule1900SoundList[] = { - 0xB4005E60, - 0x91835066, - 0x90E14440, - 0 -}; - -Module1900::Module1900(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - // NOTE: The original has a Scene1908 here as well but it's not used here but in another module... - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else - createScene(0, 0); - - _vm->_soundMan->addSoundList(0x04E1C09C, kModule1900SoundList); - _vm->_soundMan->setSoundListParams(kModule1900SoundList, true, 50, 600, 5, 150); - -} - -Module1900::~Module1900() { - _vm->_soundMan->deleteGroup(0x04E1C09C); -} - -void Module1900::createScene(int sceneNum, int which) { - debug("Module1900::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _childObject = new Scene1901(_vm, this, which); - break; - case 6: - _vm->gameState().sceneNum = 6; - _childObject = new Scene1907(_vm, this); - break; - } - SetUpdateHandler(&Module1900::updateScene); - _childObject->handleUpdate(); -} - -void Module1900::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 1) - createScene(6, 0); - else - leaveModule(0); - break; - case 6: - createScene(0, 1); - break; - } - } -} - -// Scene1901 - -Scene1901::Scene1901(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - Sprite *tempSprite; - - setRectList(0x004B34C8); - - setBackground(0x01303227); - setPalette(0x01303227); - insertScreenMouse(0x0322301B); - - insertStaticSprite(0x42213133, 1100); - - if (!getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) - insertStaticSprite(0x40A40168, 100); - else if (getGlobalVar(V_STAIRS_DOWN)) { - insertStaticSprite(0x124404C4, 100); - setGlobalVar(V_STAIRS_DOWN_ONCE, 1); - } else - insertStaticSprite(0x02840064, 100); - - if (which < 0) { - // Restoring game - insertKlaymen(120, 380); - setMessageList(0x004B3408); - } else if (which == 1) { - // Klaymen returning from the puzzle - insertKlaymen(372, 380); - setMessageList(0x004B3410); - } else { - // Klaymen entering from the left - insertKlaymen(0, 380); - setMessageList(0x004B3400); - } - - tempSprite = insertStaticSprite(0x4830A402, 1100); - _klaymen->setClipRect(tempSprite->getDrawRect().x, 0, 640, 480); - -} - -static const NPoint kAsScene1907SymbolGroundPositions[] = { - {160, 310}, { 90, 340}, {210, 335}, - {210, 380}, {310, 340}, {290, 400}, - {400, 375}, {370, 435}, {475, 415} -}; - -static const NPoint kAsScene1907SymbolPluggedInPositions[] = { - {275, 125}, {244, 125}, {238, 131}, - {221, 135}, {199, 136}, {168, 149}, - {145, 152}, {123, 154}, {103, 157} -}; - -static const NPoint kAsScene1907SymbolGroundHitPositions[] = { - {275, 299}, {244, 299}, {238, 305}, - {221, 309}, {199, 310}, {168, 323}, - {145, 326}, {123, 328}, {103, 331} -}; - -static const NPoint kAsScene1907SymbolPluggedInDownPositions[] = { - {275, 136}, {244, 156}, {238, 183}, - {221, 207}, {199, 228}, {168, 262}, - {145, 285}, {123, 307}, {103, 331} -}; - -static const uint32 kAsScene1907SymbolFileHashes[] = { - 0x006A1034, 0x006A1010, 0x006A1814, - 0x006A1016, 0x006A0014, 0x002A1014, - 0x00EA1014, 0x206A1014, 0x046A1414 -}; - -bool AsScene1907Symbol::_plugInFailed = false; -int AsScene1907Symbol::_plugInTryCount = 0; - -AsScene1907Symbol::AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex) - : AnimatedSprite(vm, 1000 - positionIndex), _parentScene(parentScene), _elementIndex(elementIndex), _isMoving(false) { - - _plugInFailed = false; - _plugInTryCount = 0; - - if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) { - _isPluggedIn = true; - _currPositionIndex = elementIndex; - if (!getGlobalVar(V_STAIRS_DOWN)) { - _x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x; - _y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y; - } else { - _x = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].x; - _y = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].y; - } - createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex); - startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - } else { - _isPluggedIn = false; - _currPositionIndex = positionIndex; - loadSound(0, 0x74231924); - loadSound(1, 0x36691914); - loadSound(2, 0x5421D806); - _parentScene->setPositionFree(_currPositionIndex, false); - _x = kAsScene1907SymbolGroundPositions[_currPositionIndex].x; - _y = kAsScene1907SymbolGroundPositions[_currPositionIndex].y; - createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex); - startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1); - _newStickFrameIndex = 0; - } - _collisionBoundsOffset.set(0, 0, 80, 80); - Sprite::updateBounds(); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1907Symbol::handleMessage); - -} - -void AsScene1907Symbol::update() { - updateAnim(); - handleSpriteUpdate(); - updatePosition(); - if (_plugInFailed && _plugInTryCount == 0) - _plugInFailed = false; -} - -uint32 AsScene1907Symbol::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (!_isPluggedIn && !_plugInFailed) { - tryToPlugIn(); - messageResult = 1; - } else - messageResult = 0; - break; - } - return messageResult; -} - -uint32 AsScene1907Symbol::hmTryToPlugIn(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1907Symbol::suTryToPlugIn() { - _currStep++; - _x -= _deltaX; - _y -= _deltaY; - if (_currStep == 16) { - _x -= _smallDeltaX; - _y -= _smallDeltaY; - SetSpriteUpdate(NULL); - } -} - -void AsScene1907Symbol::suFallOff() { - if (_fallOffDelay != 0) { - _fallOffDelay--; - } else { - _y += _yAccel; - _yAccel += 8; - if (_y >= kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) { - _y = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y; - stFallOffHitGround(); - } - } -} - -void AsScene1907Symbol::suFallOffHitGround() { - - if (_x == _someX - _xBreak) - _x -= _smallDeltaX; - else - _x -= _deltaX; - - if (_y == kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) { - _y -= _someY; - } - - if (_currStep < 8) { - _y -= _yAccel; - _yAccel -= 4; - if (_yAccel < 0) - _yAccel = 0; - } else if (_currStep < 15) { - _y += _yAccel; - _yAccel += 4; - } else { - _y = kAsScene1907SymbolGroundPositions[_newPositionIndex].y; - cbFallOffHitGroundEvent(); - } - - _currStep++; -} - -void AsScene1907Symbol::suMoveDown() { - _y += _yIncr; - if (_yIncr < 11) - _yIncr++; - if (_y >= kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y) { - _y = kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y; - _isMoving = false; - SetSpriteUpdate(NULL); - } -} - -void AsScene1907Symbol::suMoveUp() { - _y -= _yIncr; - if (getGlobalVar(V_WALL_BROKEN)) { - if (_y - (9 + (_elementIndex > 5 ? 31 : 0)) < kAsScene1907SymbolPluggedInPositions[_elementIndex].y) - _yIncr--; - else - _yIncr++; - } else - _yIncr = 2; - if (_yIncr > 9) - _yIncr = 9; - else if (_yIncr < 1) - _yIncr = 1; - if (_y < kAsScene1907SymbolPluggedInPositions[_elementIndex].y) { - _y = kAsScene1907SymbolPluggedInPositions[_elementIndex].y; - _isMoving = false; - SetSpriteUpdate(NULL); - } -} - -void AsScene1907Symbol::tryToPlugIn() { - _isPluggedIn = true; - _plugInTryCount++; - _newPositionIndex = _parentScene->getNextPosition(); - _parentScene->setPositionFree(_currPositionIndex, true); - sendMessage(_parentScene, 0x1022, 1100 + _newPositionIndex); - startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1); - SetUpdateHandler(&AsScene1907Symbol::update); - SetMessageHandler(&AsScene1907Symbol::hmTryToPlugIn); - SetSpriteUpdate(&AsScene1907Symbol::suTryToPlugIn); - _currStep = 0; - _deltaX = (_x - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x) / 16; - _smallDeltaX = _x - _deltaX * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x; - _deltaY = (_y - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y) / 16; - _smallDeltaY = _y - _deltaY * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y; - if (_elementIndex == _newPositionIndex) { - NextState(&AsScene1907Symbol::stPlugIn); - } else { - _plugInFailed = true; - NextState(&AsScene1907Symbol::stPlugInFail); - } -} - -void AsScene1907Symbol::fallOff(int newPositionIndex, int fallOffDelay) { - _isPluggedIn = false; - _newPositionIndex = newPositionIndex; - _fallOffDelay = fallOffDelay; - _parentScene->setPositionFree(_newPositionIndex, false); - _x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x; - _y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y; - _someX = _x; - _someY = _y; - startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, 0); - _playBackwards = true; - _newStickFrameIndex = STICK_LAST_FRAME; - _currStep = 0; - _yAccel = 1; - SetUpdateHandler(&AsScene1907Symbol::update); - SetMessageHandler(&AsScene1907Symbol::handleMessage); - SetSpriteUpdate(&AsScene1907Symbol::suFallOff); -} - -void AsScene1907Symbol::stFallOffHitGround() { - playSound(1); - sendMessage(_parentScene, 0x1022, 1000 + _newPositionIndex); - Entity::_priority = 1000 - _newPositionIndex; - _parentScene->removeCollisionSprite(this); - _parentScene->addCollisionSprite(this); - SetSpriteUpdate(&AsScene1907Symbol::suFallOffHitGround); - NextState(&AsScene1907Symbol::cbFallOffHitGroundEvent); - _newStickFrameIndex = 0; - _currStep = 0; - _yAccel = 30; - _deltaX = (_x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x) / 15; - _xBreak = _deltaX * 15; - _smallDeltaX = _x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x - _xBreak; - _someY = 0; - if (kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y > kAsScene1907SymbolGroundPositions[_newPositionIndex].y) - _someY = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y - kAsScene1907SymbolGroundPositions[_newPositionIndex].y; -} - -void AsScene1907Symbol::cbFallOffHitGroundEvent() { - _currPositionIndex = _newPositionIndex; - if (_plugInTryCount > 0) - _plugInTryCount--; - startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1); - _newStickFrameIndex = 0; - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1907Symbol::handleMessage); - SetSpriteUpdate(NULL); - updateBounds(); - playSound(2); -} - -void AsScene1907Symbol::stPlugIn() { - playSound(0); - _currPositionIndex = _newPositionIndex; - stopAnimation(); - SetMessageHandler(&AsScene1907Symbol::handleMessage); - SetSpriteUpdate(NULL); - if (_elementIndex == 8) - sendMessage(_parentScene, 0x2001, 0); -} - -void AsScene1907Symbol::stPlugInFail() { - _currPositionIndex = _newPositionIndex; - stopAnimation(); - _parentScene->plugInFailed(); -} - -void AsScene1907Symbol::moveUp() { - startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1); - stopAnimation(); - SetMessageHandler(&AsScene1907Symbol::handleMessage); - SetSpriteUpdate(&AsScene1907Symbol::suMoveUp); - _yIncr = 1; - _isMoving = true; -} - -void AsScene1907Symbol::moveDown() { - startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1); - stopAnimation(); - SetMessageHandler(&AsScene1907Symbol::handleMessage); - SetSpriteUpdate(&AsScene1907Symbol::suMoveDown); - _yIncr = 4; - _isMoving = true; -} - -SsScene1907UpDownButton::SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol) - : StaticSprite(vm, 1400), _parentScene(parentScene), _asScene1907Symbol(asScene1907Symbol), - _countdown1(0) { - - loadSprite(0x64516424, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 1400); - setVisible(false); - loadSound(0, 0x44061000); - SetUpdateHandler(&SsScene1907UpDownButton::update); - SetMessageHandler(&SsScene1907UpDownButton::handleMessage); - if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) { - if (getGlobalVar(V_STAIRS_DOWN)) - setToDownPosition(); - else - setToUpPosition(); - } -} - -void SsScene1907UpDownButton::update() { - updatePosition(); - if (_countdown1 != 0 && (--_countdown1 == 0)) { - setVisible(false); - sendMessage(_parentScene, 0x2000, 0); - } -} - -uint32 SsScene1907UpDownButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_countdown1 == 0 && !_asScene1907Symbol->isMoving() && getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) { - setVisible(true); - _countdown1 = 4; - updatePosition(); - playSound(0); - } - messageResult = 1; - } - return messageResult; -} - -void SsScene1907UpDownButton::setToUpPosition() { - _y = _spriteResource.getPosition().y; - updateBounds(); - updatePosition(); -} - -void SsScene1907UpDownButton::setToDownPosition() { - _y = _spriteResource.getPosition().y + 174; - updateBounds(); - updatePosition(); -} - -AsScene1907WaterHint::AsScene1907WaterHint(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1400) { - - createSurface1(0x110A1061, 1500); - _x = 320; - _y = 240; - startAnimation(0x110A1061, 0, -1); - _newStickFrameIndex = 0; - setVisible(false); - _needRefresh = true; - AnimatedSprite::updatePosition(); - SetUpdateHandler(&AsScene1907WaterHint::update); - SetMessageHandler(&Sprite::handleMessage); -} - -void AsScene1907WaterHint::update() { - updateAnim(); - updatePosition(); -} - -uint32 AsScene1907WaterHint::hmShowing(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1907WaterHint::show() { - setVisible(true); - startAnimation(0x110A1061, 0, -1); - SetMessageHandler(&AsScene1907WaterHint::hmShowing); - NextState(&AsScene1907WaterHint::hide); -} - -void AsScene1907WaterHint::hide() { - stopAnimation(); - setVisible(false); - SetMessageHandler(&Sprite::handleMessage); -} - -Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule), _currMovingSymbolIndex(0), _pluggedInCount(0), - _moveDownCountdown(0), _moveUpCountdown(0), _countdown3(0), _hasPlugInFailed(false) { - - setBackground(0x20628E05); - setPalette(0x20628E05); - - for (int i = 0; i < 9; i++) - _positionFree[i] = true; - - for (int i = 0; i < 9; i++) { - _asSymbols[i] = insertSprite(this, i, getRandomPositionIndex()); - addCollisionSprite(_asSymbols[i]); - } - - _ssUpDownButton = insertSprite(this, _asSymbols[8]); - addCollisionSprite(_ssUpDownButton); - - _asWaterHint = insertSprite(); - - insertPuzzleMouse(0x28E0120E, 20, 620); - - SetMessageHandler(&Scene1907::handleMessage); - SetUpdateHandler(&Scene1907::update); - - if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) - _pluggedInCount = 9; - - loadSound(0, 0x72004A10); - loadSound(1, 0x22082A12); - loadSound(2, 0x21100A10); - loadSound(3, 0x68E25540); - -} - -void Scene1907::update() { - Scene::update(); - - if (_hasPlugInFailed) { - int fallOffDelay = 0; - _hasPlugInFailed = false; - for (int i = 0; i < 9; i++) { - AsScene1907Symbol *asSymbol = _asSymbols[8 - i]; - if (asSymbol->isPluggedIn()) { - asSymbol->fallOff(getRandomPositionIndex(), fallOffDelay); - fallOffDelay += _vm->_rnd->getRandomNumber(10 - 1) + 4; - } - } - } - - if (_moveDownCountdown != 0 && (--_moveDownCountdown == 0)) { - _asSymbols[_currMovingSymbolIndex]->moveDown(); - if (_currMovingSymbolIndex > 0) { - _moveDownCountdown = 2; - _currMovingSymbolIndex--; - } - } - - if (_moveUpCountdown != 0 && (--_moveUpCountdown == 0)) { - _moveDownCountdown = 0; - for (int i = 0; i < 9; i++) - _asSymbols[i]->moveUp(); - } - - if (_countdown3 != 0 && (--_countdown3 == 0)) { - _asWaterHint->show(); - _moveUpCountdown = 4; - } - -} - -uint32 Scene1907::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && - !_hasPlugInFailed && _moveDownCountdown == 0 && _moveUpCountdown == 0 && _countdown3 == 0) { - leaveScene(0); - } - break; - case 0x2000: - if (getGlobalVar(V_STAIRS_DOWN)) { - playSound(0); - for (int i = 0; i < 9; i++) - _asSymbols[i]->moveUp(); - _ssUpDownButton->setToUpPosition(); - setGlobalVar(V_STAIRS_DOWN, 0); - } else { - if (!getGlobalVar(V_WALL_BROKEN)) { - playSound(2); - _countdown3 = 5; - } else { - playSound(1); - _ssUpDownButton->setToDownPosition(); - setGlobalVar(V_STAIRS_DOWN, 1); - } - _moveDownCountdown = 1; - _currMovingSymbolIndex = 8; - } - break; - case 0x2001: - playSound(3); - setGlobalVar(V_STAIRS_PUZZLE_SOLVED, 1); - break; - } - return 0; -} - -void Scene1907::plugInFailed() { - _pluggedInCount = 0; - _hasPlugInFailed = true; -} - -int Scene1907::getRandomPositionIndex() { - bool found = false; - int index = 0; - // Check if any position is free - for (int i = 0; i < 9; i++) - if (_positionFree[i]) - found = true; - if (found) { - // Get a random free position - found = false; - while (!found) { - index = _vm->_rnd->getRandomNumber(9 - 1); - if (_positionFree[index]) - found = true; - } - } - return index; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module1900.h b/engines/neverhood/module1900.h deleted file mode 100644 index 72dbf63a51..0000000000 --- a/engines/neverhood/module1900.h +++ /dev/null @@ -1,143 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE1900_H -#define NEVERHOOD_MODULE1900_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/module1200.h" - -namespace Neverhood { - -class Module1900 : public Module { -public: - Module1900(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module1900(); -protected: - int _sceneNum; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void createScene(int sceneNum, int which); - void updateScene(); -}; - -// Scene1901 - -class Scene1901 : public Scene { -public: - Scene1901(NeverhoodEngine *vm, Module *parentModule, int which); -}; - -// Scene1907 - -class Scene1907; - -class AsScene1907Symbol : public AnimatedSprite { -public: - AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex); - void moveUp(); - void moveDown(); - void fallOff(int newPositionIndex, int fallOffDelay); - bool isPluggedIn() { return _isPluggedIn; } - bool isMoving() { return _isMoving; } -protected: - Scene1907 *_parentScene; - int _elementIndex; - int _currPositionIndex; - int _newPositionIndex; - bool _isPluggedIn; - bool _isMoving; - int _someX, _someY; - int _xBreak; - int _currStep; - int _yAccel; - int _yIncr; - int _fallOffDelay; - int _deltaX, _smallDeltaX; - int _deltaY, _smallDeltaY; - // Dumb, change if possible - static bool _plugInFailed; - static int _plugInTryCount; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmTryToPlugIn(int messageNum, const MessageParam ¶m, Entity *sender); - void suTryToPlugIn(); - void suFallOff(); - void suFallOffHitGround(); - void suMoveDown(); - void suMoveUp(); - void tryToPlugIn(); - void stFallOffHitGround(); - void cbFallOffHitGroundEvent(); - void stPlugIn(); - void stPlugInFail(); -}; - -class AsScene1907WaterHint : public AnimatedSprite { -public: - AsScene1907WaterHint(NeverhoodEngine *vm); - void show(); -protected: - void update(); - uint32 hmShowing(int messageNum, const MessageParam ¶m, Entity *sender); - void hide(); -}; - -class SsScene1907UpDownButton : public StaticSprite { -public: - SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol); - void setToUpPosition(); - void setToDownPosition(); -protected: - Scene1907 *_parentScene; - AsScene1907Symbol *_asScene1907Symbol; - int _countdown1; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene1907 : public Scene { -public: - Scene1907(NeverhoodEngine *vm, Module *parentModule); - void plugInFailed(); - void setPositionFree(int index, bool value) { _positionFree[index] = value; } - int getNextPosition() { return _pluggedInCount++; } -protected: - AsScene1907Symbol *_asSymbols[9]; - SsScene1907UpDownButton *_ssUpDownButton; - AsScene1907WaterHint *_asWaterHint; - int _currMovingSymbolIndex; - int _pluggedInCount; - int _moveDownCountdown; - int _moveUpCountdown; - int _countdown3; - bool _hasPlugInFailed; - bool _positionFree[9]; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - int getRandomPositionIndex(); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE1900_H */ diff --git a/engines/neverhood/module2000.cpp b/engines/neverhood/module2000.cpp deleted file mode 100644 index 71bcdc7e58..0000000000 --- a/engines/neverhood/module2000.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* 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/module2000.h" -#include "neverhood/gamemodule.h" -#include "neverhood/navigationscene.h" - -namespace Neverhood { - -Module2000::Module2000(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else if (which == 0) - createScene(0, 1); - else if (which == 1) - createScene(0, 3); - -} - -Module2000::~Module2000() { - _vm->_soundMan->deleteGroup(0x81293110); -} - -void Module2000::createScene(int sceneNum, int which) { - debug("Module2000::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _childObject = new Scene2001(_vm, this, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - createNavigationScene(getGlobalVar(V_WORLDS_JOINED) ? 0x004B7B48 : 0x004B7B00, which); - break; - case 2: - _vm->gameState().sceneNum = 2; - setGlobalVar(V_WORLDS_JOINED, 1); - setSubVar(V_TELEPORTER_DEST_AVAILABLE, 1, 1); - createSmackerScene(0x204B2031, true, true, false); - break; - } - SetUpdateHandler(&Module2000::updateScene); - _childObject->handleUpdate(); -} - -void Module2000::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 1) - leaveModule(0); - else - createScene(1, 0); - break; - case 1: - if (_moduleResult == 0) { - if (getGlobalVar(V_WORLDS_JOINED)) - createScene(1, 0); - else - createScene(2, -1); - } else if (_moduleResult == 1) - createScene(1, 1); - else if (_moduleResult == 2) - createScene(0, 0); - break; - case 2: - createScene(1, 0); - break; - } - } -} - -// Scene2001 - -Scene2001::Scene2001(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - Sprite *tempSprite; - - SetMessageHandler(&Scene2001::handleMessage); - - setBackground(0xA6417244); - setPalette(0xA6417244); - insertScreenMouse(0x17240A6C); - - tempSprite = insertStaticSprite(0x0D641724, 1100); - - if (which < 0) { - // Restoring game - insertKlaymen(300, 345); - setMessageList(0x004B3538); - sendMessage(this, 0x2000, 0); - } else if (which == 1) { - // Klaymen teleporting in - insertKlaymen(116, 345); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B3540, false); - sendMessage(this, 0x2000, 1); - } else if (which == 2) { - // Klaymen teleporting out - insertKlaymen(116, 345); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B35F0, false); - sendMessage(this, 0x2000, 1); - } else if (which == 3) { - // Klaymen returning from teleporter console - insertKlaymen(116, 345); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B3550, false); - sendMessage(this, 0x2000, 1); - } else { - // Klaymen standing around - insertKlaymen(390, 345); - setMessageList(0x004B3530); - sendMessage(this, 0x2000, 0); - _klaymen->setDoDeltaX(1); - } - - _klaymen->setClipRect(tempSprite->getDrawRect().x, 0, 640, 480); - -} - -uint32 Scene2001::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - if (param.asInteger()) { - setRectList(0x004B3680); - _klaymen->setKlaymenIdleTable3(); - } else { - setRectList(0x004B3670); - _klaymen->setKlaymenIdleTable1(); - } - } - return 0; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module2000.h b/engines/neverhood/module2000.h deleted file mode 100644 index 9859c73006..0000000000 --- a/engines/neverhood/module2000.h +++ /dev/null @@ -1,55 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE2000_H -#define NEVERHOOD_MODULE2000_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/module1200.h" - -namespace Neverhood { - -class Module2000 : public Module { -public: - Module2000(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module2000(); -protected: - int _sceneNum; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void createScene(int sceneNum, int which); - void updateScene(); -}; - -// Scene2001 - -class Scene2001 : public Scene { -public: - Scene2001(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE2000_H */ diff --git a/engines/neverhood/module2100.cpp b/engines/neverhood/module2100.cpp deleted file mode 100644 index cd7a3d5e24..0000000000 --- a/engines/neverhood/module2100.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* 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/module2100.h" -#include "neverhood/gamemodule.h" -#include "neverhood/module1200.h" - -namespace Neverhood { - -Module2100::Module2100(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - _vm->_soundMan->addMusic(0x10A10C14, 0x11482B95); - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else if (which == 1) - createScene(0, 0); - else if (which == 2) - createScene(0, 3); - else - createScene(0, 1); - -} - -Module2100::~Module2100() { - _vm->_soundMan->deleteMusicGroup(0x10A10C14); -} - -void Module2100::createScene(int sceneNum, int which) { - debug("Module2100::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _vm->_soundMan->startMusic(0x11482B95, 0, 1); - _childObject = new Scene2101(_vm, this, which); - break; - } - SetUpdateHandler(&Module2100::updateScene); - _childObject->handleUpdate(); -} - -void Module2100::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 1) { - setGlobalVar(V_DOOR_PASSED, 1); - leaveModule(0); - } else - leaveModule(1); - break; - } - } -} - -// Scene2101 - -AsScene2101Door::AsScene2101Door(NeverhoodEngine *vm, bool isOpen) - : AnimatedSprite(vm, 1100) { - - createSurface(100, 328, 347); - _x = 320; - _y = 240; - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2101Door::handleMessage); - if (isOpen) { - startAnimation(0x0C202B9C, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - } else - setVisible(false); -} - -uint32 AsScene2101Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - case 0x4808: - stOpenDoor(); - break; - case 0x4809: - stCloseDoor(); - break; - } - return messageResult; -} - -void AsScene2101Door::stOpenDoor() { - startAnimation(0x0C202B9C, 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - setVisible(true); - playSound(0, calcHash("fxDoorOpen32")); -} - -void AsScene2101Door::stCloseDoor() { - startAnimation(0xC222A8D4, 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - setVisible(true); - playSound(0, calcHash("fxDoorClose32")); - NextState(&AsScene2101Door::stCloseDoorDone); -} - -void AsScene2101Door::stCloseDoorDone() { - stopAnimation(); - setVisible(false); -} - -AsScene2101HitByDoorEffect::AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen) - : AnimatedSprite(vm, 1400), _klaymen(klaymen) { - - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2101HitByDoorEffect::handleMessage); - createSurface(1200, 88, 165); - setVisible(false); -} - -uint32 AsScene2101HitByDoorEffect::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2001: - _x = _klaymen->getX(); - _y = _klaymen->getY() - 132; - startAnimation(0x0422255A, 0, -1); - setVisible(true); - break; - case 0x3002: - stopAnimation(); - setVisible(false); - break; - } - return messageResult; -} - -SsCommonFloorButton::SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash) - : StaticSprite(vm, 1100), _parentScene(parentScene), _countdown(0), - _fileHash1(fileHash1), _fileHash2(fileHash2), _soundFileHash(soundFileHash) { - - SetUpdateHandler(&SsCommonFloorButton::update); - SetMessageHandler(&SsCommonFloorButton::handleMessage); - if (_soundFileHash == 0) - _soundFileHash = 0x44141000; - createSurface(1010, 61, 30); - if (_fileHash1) - loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition); - else - setVisible(false); -} - -void SsCommonFloorButton::update() { - if (_countdown != 0 && (--_countdown == 0)) { - sendMessage(_parentScene, 0x1022, 1010); - if (_fileHash1) - loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition); - else - setVisible(false); - } -} - -uint32 SsCommonFloorButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x480B: - sendMessage(_parentScene, 0x480B, 0); - setVisible(true); - sendMessage(_parentScene, 0x1022, 990); - loadSprite(_fileHash2, kSLFDefDrawOffset | kSLFDefPosition); - _countdown = 16; - playSound(0, _soundFileHash); - break; - } - return messageResult; -} - -Scene2101::Scene2101(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - Sprite *tempSprite; - - SetMessageHandler(&Scene2101::handleMessage); - SetUpdateHandler(&Scene2101::update); - - setBackground(0x44242305); - setPalette(0x44242305); - insertScreenMouse(0x4230144A); - - insertStaticSprite(0x00502330, 1100); - tempSprite = insertStaticSprite(0x78492010, 1100); - _ssFloorButton = insertSprite(this, 0x72427010, 0x32423010, 200, 0); - _asTape1 = insertSprite(this, 18, 1100, 412, 443, 0x9148A011); - addCollisionSprite(_asTape1); - _asTape2 = insertSprite(this, 11, 1100, 441, 443, 0x9148A011); - addCollisionSprite(_asTape2); - - if (which < 0) { - insertKlaymen(380, 438); - setMessageList(0x004B8E48); - sendMessage(this, 0x2000, 0); - _asDoor = insertSprite(false); - _doorStatus = 1; - _countdown1 = 0; - } else if (which == 1) { - // Klaymen entering from the right - insertKlaymen(640, 438); - setMessageList(0x004B8E50); - sendMessage(this, 0x2000, 0); - _asDoor = insertSprite(true); - _doorStatus = 2; - _countdown1 = 48; - } else if (which == 2) { - // Klaymen teleporting out - insertKlaymen(115, 438); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B8F58); - sendMessage(this, 0x2000, 1); - _asDoor = insertSprite(false); - _doorStatus = 1; - _countdown1 = 0; - } else if (which == 3) { - // Klaymen returning from the teleporter console - insertKlaymen(115, 438); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B8EB0); - sendMessage(this, 0x2000, 1); - _asDoor = insertSprite(false); - _doorStatus = 1; - _countdown1 = 0; - } else { - // Klaymen teleporting in - insertKlaymen(115, 438); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004B8EA0); - sendMessage(this, 0x2000, 1); - _asDoor = insertSprite(false); - _doorStatus = 1; - _countdown1 = 0; - } - - _asHitByDoorEffect = insertSprite(_klaymen); - _klaymen->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480); - -} - -void Scene2101::update() { - if (_countdown1 != 0) { - if (_doorStatus == 2) { - if (--_countdown1 == 0) { - sendMessage(_asDoor, 0x4809, 0); - _doorStatus = 1; - } - } else { - if (_klaymen->getX() > 575) - _canAcceptInput = false; - if (--_countdown1 == 0) { - if (_klaymen->getX() < 480) { - sendMessage(_asDoor, 0x4809, 0); - _doorStatus = 1; - } else if (_klaymen->getX() >= 480 && _klaymen->getX() <= 575) { - _klaymen->setDoDeltaX(0); - setMessageList2(0x004B8F48); - sendMessage(_asDoor, 0x4809, 0); - sendMessage(_asHitByDoorEffect, 0x2001, 0); - _doorStatus = 1; - } - } - } - } else if (_doorStatus == 1 && _messageValue >= 0 && _klaymen->getX() > 470 && !isMessageList2(0x004B8F48)) - setMessageList2(0x004B8F50); - Scene::update(); -} - -uint32 Scene2101::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x02144CB1) - sendEntityMessage(_klaymen, 0x1014, _ssFloorButton); - else if (param.asInteger() == 0x21E64A00) { - if (_doorStatus == 0) - setMessageList(0x004B8E80); - else - setMessageList(0x004B8EC8); - } else if (param.asInteger() == 0x41442820) - cancelMessageList(); - break; - case 0x2000: - if (param.asInteger() != 0) { - setRectList(0x004B9008); - _klaymen->setKlaymenIdleTable3(); - } else { - setRectList(0x004B8FF8); - _klaymen->setKlaymenIdleTable1(); - } - break; - case 0x480B: - if (sender == _ssFloorButton && _doorStatus == 1) { - sendMessage(_asDoor, 0x4808, 0); - _doorStatus = 0; - _countdown1 = 90; - } - break; - case 0x4826: - if (sender == _asTape1 || sender == _asTape2) { - if (_klaymen->getX() >= 228 && _klaymen->getX() <= 500) { - sendEntityMessage(_klaymen, 0x1014, sender); - setMessageList(0x004B8F78); - } else if (_klaymen->getX() < 228) - setMessageList2(0x004B8F00); - } - break; - } - return 0; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module2100.h b/engines/neverhood/module2100.h deleted file mode 100644 index c2e7d09ff4..0000000000 --- a/engines/neverhood/module2100.h +++ /dev/null @@ -1,92 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE2100_H -#define NEVERHOOD_MODULE2100_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" - -namespace Neverhood { - -class Module2100 : public Module { -public: - Module2100(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module2100(); -protected: - int _sceneNum; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void createScene(int sceneNum, int which); - void updateScene(); -}; - -// Scene1901 - -class AsScene2101Door : public AnimatedSprite { -public: - AsScene2101Door(NeverhoodEngine *vm, bool isOpen); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stOpenDoor(); - void stCloseDoor(); - void stCloseDoorDone(); -}; - -class AsScene2101HitByDoorEffect : public AnimatedSprite { -public: - AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen); -protected: - Sprite *_klaymen; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsCommonFloorButton : public StaticSprite { -public: - SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash); -protected: - Scene *_parentScene; - uint32 _soundFileHash; - uint32 _fileHash1, _fileHash2; - int16 _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2101 : public Scene { -public: - Scene2101(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_ssFloorButton; - Sprite *_asTape1; - Sprite *_asTape2; - Sprite *_asDoor; - Sprite *_asHitByDoorEffect; - int _countdown1; - int _doorStatus; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE2100_H */ diff --git a/engines/neverhood/module2200.cpp b/engines/neverhood/module2200.cpp deleted file mode 100644 index ddcfb3685c..0000000000 --- a/engines/neverhood/module2200.cpp +++ /dev/null @@ -1,2564 +0,0 @@ -/* 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/module2200.h" -#include "neverhood/module1000.h" -#include "neverhood/module1200.h" -#include "neverhood/gamemodule.h" -#include "neverhood/diskplayerscene.h" - -namespace Neverhood { - -Module2200::Module2200(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - debug("Create Module2200(%d)", which); - - _vm->_soundMan->addMusic(0x11391412, 0x601C908C); - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else - createScene(0, 0); - -} - -Module2200::~Module2200() { - _vm->_soundMan->deleteGroup(0x11391412); -} - -void Module2200::createScene(int sceneNum, int which) { - debug("Module2200::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _childObject = new Scene2201(_vm, this, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - _vm->_soundMan->startMusic(0x601C908C, 0, 2); - _childObject = new Scene2202(_vm, this, which); - break; - case 2: - _vm->gameState().sceneNum = 2; - _vm->_soundMan->startMusic(0x601C908C, 0, 2); - _childObject = new Scene2203(_vm, this, which); - break; - case 3: - _vm->gameState().sceneNum = 3; - _vm->_soundMan->stopMusic(0x601C908C, 0, 2); - _childObject = new DiskplayerScene(_vm, this, 3); - break; - case 4: - _vm->gameState().sceneNum = 4; - _vm->_soundMan->stopMusic(0x601C908C, 0, 2); - _childObject = new Scene2205(_vm, this, which); - break; - case 5: - _vm->gameState().sceneNum = 5; - _vm->_soundMan->stopMusic(0x601C908C, 0, 2); - _childObject = new Scene2206(_vm, this, which); - break; - case 6: - _vm->gameState().sceneNum = 6; - _childObject = new Scene2207(_vm, this); - break; - case 7: - if (which >= 0) - _vm->gameState().which = _vm->gameState().sceneNum; - _vm->gameState().sceneNum = 7; - _childObject = new Scene2208(_vm, this, which); - break; - case 8: - _vm->gameState().sceneNum = 8; - _childObject = new Scene2208(_vm, this, which); - break; - case 9: - _vm->gameState().sceneNum = 9; - createHallOfRecordsScene(which, 0x004B7180); - break; - case 10: - _vm->gameState().sceneNum = 10; - createHallOfRecordsScene(which, 0x004B7198); - break; - case 11: - _vm->gameState().sceneNum = 11; - createHallOfRecordsScene(which, 0x004B71B0); - break; - case 12: - _vm->gameState().sceneNum = 12; - createHallOfRecordsScene(which, 0x004B71C8); - break; - case 13: - _vm->gameState().sceneNum = 13; - createHallOfRecordsScene(which, 0x004B71E0); - break; - case 14: - _vm->gameState().sceneNum = 14; - createHallOfRecordsScene(which, 0x004B71F8); - break; - case 15: - _vm->gameState().sceneNum = 15; - createHallOfRecordsScene(which, 0x004B7210); - break; - case 16: - _vm->gameState().sceneNum = 16; - createHallOfRecordsScene(which, 0x004B7228); - break; - case 17: - _vm->gameState().sceneNum = 17; - createHallOfRecordsScene(which, 0x004B7240); - break; - case 18: - _vm->gameState().sceneNum = 18; - createHallOfRecordsScene(which, 0x004B7258); - break; - case 19: - _vm->gameState().sceneNum = 19; - createHallOfRecordsScene(which, 0x004B7270); - break; - case 20: - _vm->gameState().sceneNum = 20; - createHallOfRecordsScene(which, 0x004B7288); - break; - case 21: - _vm->gameState().sceneNum = 21; - createHallOfRecordsScene(which, 0x004B72A0); - break; - case 22: - _vm->gameState().sceneNum = 22; - createHallOfRecordsScene(which, 0x004B72B8); - break; - case 23: - _vm->gameState().sceneNum = 23; - createHallOfRecordsScene(which, 0x004B72D0); - break; - case 24: - _vm->gameState().sceneNum = 24; - createHallOfRecordsScene(which, 0x004B72E8); - break; - case 25: - _vm->gameState().sceneNum = 25; - createHallOfRecordsScene(which, 0x004B7300); - break; - case 26: - _vm->gameState().sceneNum = 26; - createHallOfRecordsScene(which, 0x004B7318); - break; - case 27: - _vm->gameState().sceneNum = 27; - createHallOfRecordsScene(which, 0x004B7330); - break; - case 28: - _vm->gameState().sceneNum = 28; - createHallOfRecordsScene(which, 0x004B7348); - break; - case 29: - _vm->gameState().sceneNum = 29; - createHallOfRecordsScene(which, 0x004B7360); - break; - case 30: - _vm->gameState().sceneNum = 30; - createHallOfRecordsScene(which, 0x004B7378); - break; - case 31: - _vm->gameState().sceneNum = 31; - createHallOfRecordsScene(which, 0x004B7390); - break; - case 32: - _vm->gameState().sceneNum = 32; - createHallOfRecordsScene(which, 0x004B73A8); - break; - case 33: - _vm->gameState().sceneNum = 33; - createHallOfRecordsScene(which, 0x004B73C0); - break; - case 34: - _vm->gameState().sceneNum = 34; - createHallOfRecordsScene(which, 0x004B73D8); - break; - case 35: - _vm->gameState().sceneNum = 35; - createHallOfRecordsScene(which, 0x004B73F0); - break; - case 36: - _vm->gameState().sceneNum = 36; - createHallOfRecordsScene(which, 0x004B7408); - break; - case 37: - _vm->gameState().sceneNum = 37; - createHallOfRecordsScene(which, 0x004B7420); - break; - case 38: - _vm->gameState().sceneNum = 38; - createHallOfRecordsScene(which, 0x004B7438); - break; - case 39: - _vm->gameState().sceneNum = 39; - createHallOfRecordsScene(which, 0x004B7450); - break; - case 40: - _vm->gameState().sceneNum = 40; - createHallOfRecordsScene(which, 0x004B7468); - break; - case 41: - _vm->gameState().sceneNum = 41; - _childObject = new Scene2242(_vm, this, which); - break; - case 42: - _vm->gameState().sceneNum = 42; - createHallOfRecordsScene(which, 0x004B7480); - break; - case 43: - _vm->gameState().sceneNum = 43; - createHallOfRecordsScene(which, 0x004B7498); - break; - case 44: - _vm->gameState().sceneNum = 44; - createHallOfRecordsScene(which, 0x004B74B0); - break; - case 45: - _vm->gameState().sceneNum = 45; - createHallOfRecordsScene(which, 0x004B74C8); - break; - case 46: - _vm->gameState().sceneNum = 46; - _childObject = new Scene2247(_vm, this, which); - break; - case 47: - _vm->gameState().sceneNum = 47; - if (!getGlobalVar(V_WORLDS_JOINED)) { - if (getGlobalVar(V_LIGHTS_ON)) - createStaticScene(0x83110287, 0x10283839); - else - createStaticScene(0x83412B9D, 0x12B9983C); - } else { - if (getGlobalVar(V_LIGHTS_ON)) - createStaticScene(0x48632087, 0x3208348E); - else - createStaticScene(0x08C74886, 0x74882084); - } - break; - } - SetUpdateHandler(&Module2200::updateScene); - _childObject->handleUpdate(); -} - -#define HallOfRecordsSceneLink(nextSceneNum, prevSceneNum) \ - if (_moduleResult == 1) createScene(nextSceneNum, 0); else if (_moduleResult == 2) createScene(7, 0); else createScene(prevSceneNum, 1) - -void Module2200::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 1) - createScene(2, 0); - else if (_moduleResult == 2) - createScene(1, 0); - else - leaveModule(0); - break; - case 1: - createScene(0, 2); - break; - case 2: - if (_moduleResult == 1) - createScene(4, 0); - else if (_moduleResult == 2) - createScene(3, 0); - else - createScene(0, 1); - break; - case 3: - createScene(2, 2); - break; - case 4: - if (_moduleResult == 1) - createScene(5, 0); - else if (_moduleResult == 2) - createScene(4, 2); - else - createScene(2, 1); - break; - case 5: - if (_moduleResult == 1) - createScene(46, 0); - else if (_moduleResult == 2) - createScene(6, 0); - else if (_moduleResult == 3) - createScene(8, 0); - else - createScene(4, 1); - break; - case 6: - createScene(5, 2); - break; - case 7: - createScene(_vm->gameState().which, 2); - break; - case 8: - createScene(5, 3); - break; - case 9: - HallOfRecordsSceneLink(10, 46); - break; - case 10: - HallOfRecordsSceneLink(11, 9); - break; - case 11: - HallOfRecordsSceneLink(12, 10); - break; - case 12: - HallOfRecordsSceneLink(13, 11); - break; - case 13: - HallOfRecordsSceneLink(14, 12); - break; - case 14: - HallOfRecordsSceneLink(15, 13); - break; - case 15: - HallOfRecordsSceneLink(16, 14); - break; - case 16: - HallOfRecordsSceneLink(17, 15); - break; - case 17: - HallOfRecordsSceneLink(18, 16); - break; - case 18: - HallOfRecordsSceneLink(19, 17); - break; - case 19: - HallOfRecordsSceneLink(20, 18); - break; - case 20: - HallOfRecordsSceneLink(21, 19); - break; - case 21: - HallOfRecordsSceneLink(22, 20); - break; - case 22: - HallOfRecordsSceneLink(23, 21); - break; - case 23: - HallOfRecordsSceneLink(24, 22); - break; - case 24: - HallOfRecordsSceneLink(25, 23); - break; - case 25: - HallOfRecordsSceneLink(26, 24); - break; - case 26: - HallOfRecordsSceneLink(27, 25); - break; - case 27: - HallOfRecordsSceneLink(28, 26); - break; - case 28: - HallOfRecordsSceneLink(29, 27); - break; - case 29: - HallOfRecordsSceneLink(30, 28); - break; - case 30: - HallOfRecordsSceneLink(31, 29); - break; - case 31: - HallOfRecordsSceneLink(32, 30); - break; - case 32: - HallOfRecordsSceneLink(33, 31); - break; - case 33: - HallOfRecordsSceneLink(34, 32); - break; - case 34: - HallOfRecordsSceneLink(42, 33); - break; - case 35: - HallOfRecordsSceneLink(36, 45); - break; - case 36: - HallOfRecordsSceneLink(37, 35); - break; - case 37: - HallOfRecordsSceneLink(38, 36); - break; - case 38: - HallOfRecordsSceneLink(39, 37); - break; - case 39: - HallOfRecordsSceneLink(40, 38); - break; - case 40: - HallOfRecordsSceneLink(41, 39); - break; - case 41: - HallOfRecordsSceneLink(47, 40); - break; - case 42: - HallOfRecordsSceneLink(43, 34); - break; - case 43: - HallOfRecordsSceneLink(44, 42); - break; - case 44: - HallOfRecordsSceneLink(45, 43); - break; - case 45: - HallOfRecordsSceneLink(35, 44); - break; - case 46: - HallOfRecordsSceneLink(9, 5); - break; - case 47: - createScene(41, 1); - break; - } - } -} - -#undef HallOfRecordsSceneLink - -void Module2200::createHallOfRecordsScene(int which, uint32 hallOfRecordsInfoId) { - _childObject = new HallOfRecordsScene(_vm, this, which, hallOfRecordsInfoId); -} - -// Scene2201 - -AsScene2201CeilingFan::AsScene2201CeilingFan(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100) { - - _x = 403; - _y = 259; - createSurface(100, 233, 96); - startAnimation(0x8600866, 0, -1); - SetUpdateHandler(&AnimatedSprite::update); -} - -AsScene2201Door::AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen) - : AnimatedSprite(vm, 1100), _klaymen(klaymen), _ssDoorLight(ssDoorLight), _countdown(0), _isOpen(isOpen) { - - _x = 408; - _y = 290; - createSurface(900, 63, 266); - SetUpdateHandler(&AsScene2201Door::update); - SetMessageHandler(&AsScene2201Door::handleMessage); - if (_isOpen) { - startAnimation(0xE2CB0412, -1, -1); - _countdown = 48; - _newStickFrameIndex = STICK_LAST_FRAME; - } else { - startAnimation(0xE2CB0412, 0, -1); - _newStickFrameIndex = 0; - _ssDoorLight->setVisible(false); - } -} - -void AsScene2201Door::update() { - if (_countdown != 0 && _isOpen && (--_countdown == 0)) - stCloseDoor(); - AnimatedSprite::update(); -} - -uint32 AsScene2201Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x11001090) { - if (_isOpen) - _ssDoorLight->setVisible(true); - } else if (param.asInteger() == 0x11283090) { - if (!_isOpen) - _ssDoorLight->setVisible(false); - } - break; - case 0x2000: - if (_isOpen) - _countdown = 144; - messageResult = _isOpen ? 1 : 0; - break; - case 0x3002: - gotoNextState(); - break; - case 0x4808: - _countdown = 144; - if (!_isOpen) - stOpenDoor(); - break; - } - return messageResult; -} - -void AsScene2201Door::stOpenDoor() { - _isOpen = true; - startAnimation(0xE2CB0412, 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - playSound(0, calcHash("fxDoorOpen33")); -} - -void AsScene2201Door::stCloseDoor() { - _isOpen = false; - startAnimation(0xE2CB0412, -1, -1); - _playBackwards = true; - _newStickFrameIndex = 0; - playSound(0, calcHash("fxDoorClose33")); -} - -SsScene2201PuzzleCube::SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex) - : StaticSprite(vm, 900) { - - createSurface(100, 16, 16); - loadSprite(kSsScene2201PuzzleCubeFileHashes[cubeIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 0, - kSsScene2201PuzzleCubePoints[positionIndex].x, kSsScene2201PuzzleCubePoints[positionIndex].y); -} - -Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _isSoundPlaying(false) { - - Sprite *tempSprite; - - _vm->gameModule()->initCubeSymbolsPuzzle(); - - SetMessageHandler(&Scene2201::handleMessage); - SetUpdateHandler(&Scene2201::update); - - loadDataResource(0x04104242); - loadHitRectList(); - setBackground(0x40008208); - setPalette(0x40008208); - insertScreenMouse(0x0820C408); - - _asTape = insertSprite(this, 7, 1100, 459, 432, 0x9148A011); - addCollisionSprite(_asTape); - _ssDoorButton = insertSprite(this, 0xE4A43E29, 0xE4A43E29, 100, 0); - - for (uint32 cubeIndex = 0; cubeIndex < 9; cubeIndex++) - if ((int16)getSubVar(VA_CUBE_POSITIONS, cubeIndex) >= 0) - insertSprite(cubeIndex, (int16)getSubVar(VA_CUBE_POSITIONS, cubeIndex)); - - _clipRects[0].y1 = 0; - _clipRects[0].x2 = 640; - _clipRects[1].x2 = 640; - _clipRects[1].y2 = 480; - - if (!getGlobalVar(V_TILE_PUZZLE_SOLVED)) - insertStaticSprite(0x00026027, 900); - - tempSprite = insertStaticSprite(0x030326A0, 1100); - _clipRects[0].x1 = tempSprite->getDrawRect().x; - insertStaticSprite(0x811DA061, 1100); - tempSprite = insertStaticSprite(0x11180022, 1100); - _clipRects[1].x1 = tempSprite->getDrawRect().x; - tempSprite = insertStaticSprite(0x0D411130, 1100); - _clipRects[0].y2 = tempSprite->getDrawRect().y2(); - _clipRects[1].y1 = tempSprite->getDrawRect().y2(); - _ssDoorLight = insertStaticSprite(0xA4062212, 900); - - if (which < 0) { - // Restoring game - insertKlaymen(300, 427, _clipRects, 2); - setMessageList(0x004B8118); - _asDoor = insertSprite(_klaymen, _ssDoorLight, false); - } else if (which == 1) { - // Klaymen entering from the back - insertKlaymen(412, 393, _clipRects, 2); - setMessageList(0x004B8130); - _asDoor = insertSprite(_klaymen, _ssDoorLight, false); - } else if (which == 2) { - // Klaymen returning from the puzzle - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { - insertKlaymen(379, 427, _clipRects, 2); - _klaymen->setDoDeltaX(1); - } else - insertKlaymen(261, 427, _clipRects, 2); - setMessageList(0x004B8178); - _asDoor = insertSprite(_klaymen, _ssDoorLight, false); - } else { - // Klaymen entering from the left - NPoint pt = _dataResource.getPoint(0x0304D8DC); - insertKlaymen(pt.x, pt.y, _clipRects, 2); - setMessageList(0x004B8120); - _asDoor = insertSprite(_klaymen, _ssDoorLight, true); - } - - insertSprite(); - - _vm->_soundMan->addSound(0x04106220, 0x81212040); - -} - -Scene2201::~Scene2201() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); - _vm->_soundMan->deleteSoundGroup(0x04106220); -} - -void Scene2201::update() { - Scene::update(); - if (!_isSoundPlaying) { - _vm->_soundMan->playSoundLooping(0x81212040); - _isSoundPlaying = true; - } -} - -uint32 Scene2201::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x402064D8) - sendEntityMessage(_klaymen, 0x1014, _ssDoorButton); - else if (param.asInteger() == 0x35803198) { - if (sendMessage(_asDoor, 0x2000, 0)) - setMessageList(0x004B81A0); - else - setMessageList(0x004B81B8); - } else if (param.asInteger() == 0x51445010) { - if (getGlobalVar(V_TILE_PUZZLE_SOLVED)) - setMessageList(0x004B8108); - else - setMessageList(0x004B8150); - } else if (param.asInteger() == 0x1D203082) - setMessageList(0x004B8180); - else if (param.asInteger() == 0x00049091) { - if (getGlobalVar(V_TILE_PUZZLE_SOLVED)) - setMessageList(0x004B8138); - else - setMessageList(0x004B8108); - } - break; - case 0x480B: - if (sender == _ssDoorButton) - sendMessage(_asDoor, 0x4808, 0); - break; - case 0x4826: - if (sender == _asTape) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004B81C8); - } - break; - } - return 0; -} - -static const NPoint kSsScene2202PuzzleCubePoints[] = { - {196, 105}, {323, 102}, {445, 106}, - {192, 216}, {319, 220}, {446, 216}, - {188, 320}, {319, 319}, {443, 322} -}; - -static const uint32 kSsScene2202PuzzleCubeFileHashes1[] = { - 0xA500800C, 0x2182910C, 0x2323980C, - 0x23049084, 0x21008080, 0x2303900C, - 0x6120980C, 0x2504D808 -}; - -static const uint32 kSsScene2202PuzzleCubeFileHashes2[] = { - 0x0AAD8080, 0x0A290291, 0x0A2BA398, - 0x822B8490, 0x86298080, 0x0A2B8390, - 0x0A69A098, 0x0E2D84D8 -}; - -SsScene2202PuzzleCube::SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol) - : StaticSprite(vm, 900), _parentScene(parentScene), _cubeSymbol(cubeSymbol), _cubePosition(cubePosition), _isMoving(false) { - - int surfacePriority; - - SetUpdateHandler(&SsScene2202PuzzleCube::update); - SetMessageHandler(&SsScene2202PuzzleCube::handleMessage); - if (_cubePosition >= 0 && _cubePosition <= 2) - surfacePriority = 100; - else if (_cubePosition >= 3 && _cubePosition <= 5) - surfacePriority = 300; - else - surfacePriority = 500; - loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset | kSLFSetPosition | kSLFDefCollisionBoundsOffset, 0, - kSsScene2202PuzzleCubePoints[_cubePosition].x, kSsScene2202PuzzleCubePoints[_cubePosition].y); - loadSound(0, 0x40958621); - loadSound(1, 0x51108241); -} - -void SsScene2202PuzzleCube::update() { - handleSpriteUpdate(); - updatePosition(); -} - -uint32 SsScene2202PuzzleCube::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (!_isMoving && !getGlobalVar(V_TILE_PUZZLE_SOLVED)) - sendMessage(_parentScene, 0x2000, _cubePosition); - messageResult = 1; - break; - case 0x2001: - _isMoving = true; - moveCube(param.asInteger()); - break; - } - return messageResult; -} - -void SsScene2202PuzzleCube::suMoveCubeX() { - - bool done = false; - - if (_counterDirection) { - if (_counter > 2) - _counter -= 2; - } else { - if (_counter < 20) - _counter += 2; - } - - for (int16 i = 0; i < _counter; i++) { - _x += _xIncr; - _errValue += _yDelta; - if (_errValue >= _xDelta) { - _errValue -= _xDelta; - _y += _yIncr; - } - if (_x == _newX && _y == _newY) { - done = true; - break; - } - if (_x == _xFlagPos) - _counterDirection = true; - } - - if (done) - stopMoving(); - - updateBounds(); - -} - -void SsScene2202PuzzleCube::suMoveCubeY() { - - bool done = false; - - if (_counterDirection) { - if (_counter > 2) - _counter -= 2; - } else { - if (_counter < 20) - _counter += 2; - } - - for (int16 i = 0; i < _counter; i++) { - _y += _yIncr; - _errValue += _xDelta; - if (_errValue >= _yDelta) { - _errValue -= _yDelta; - _x += _xIncr; - } - if (_x == _newX && _y == _newY) { - done = true; - break; - } - if (_x == _xFlagPos) - _counterDirection = true; - } - - if (done) - stopMoving(); - - updateBounds(); - -} - -void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) { - - loadSprite(kSsScene2202PuzzleCubeFileHashes1[_cubeSymbol], kSLFCenteredDrawOffset); - - setSubVar(VA_CUBE_POSITIONS, _cubePosition, (uint32)-1); - setSubVar(VA_CUBE_POSITIONS, newCubePosition, (uint32)_cubeSymbol); - - _cubePosition = newCubePosition; - _errValue = 0; - _counterDirection = false; - _counter = 0; - _newX = kSsScene2202PuzzleCubePoints[newCubePosition].x; - _newY = kSsScene2202PuzzleCubePoints[newCubePosition].y; - - if (_x == _newX && _y == _newY) - return; - - if (_x <= _newX) { - if (_y <= _newY) { - _xDelta = _newX - _x; - _yDelta = _newY - _y; - _xIncr = 1; - _yIncr = 1; - } else { - _xDelta = _newX - _x; - _yDelta = _y - _newY; - _xIncr = 1; - _yIncr = -1; - } - } else { - if (_y <= _newY) { - _xDelta = _x - _newX; - _yDelta = _newY - _y; - _xIncr = -1; - _yIncr = 1; - } else { - _xDelta = _x - _newX; - _yDelta = _y - _newY; - _xIncr = -1; - _yIncr = -1; - } - } - - if (_xDelta > _yDelta) { - SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeX); - if (_xIncr > 0) { - if (_newX - _x >= 180) - _xFlagPos = _newX - 90; - else - _xFlagPos = _x + _newX / 2; - } else { - if (_x - _newX >= 180) - _xFlagPos = _x + 90; - else - _xFlagPos = _x / 2 + _newX; - } - playSound(0); - } else { - SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeY); - if (_yIncr > 0) { - if (_newY - _y >= 180) - _xFlagPos = _newY - 90; - else - _xFlagPos = _y + _newY / 2; - } else { - if (_y - _newY >= 180) - _xFlagPos = _y + 90; - else - _xFlagPos = _y / 2 + _newY; - } - playSound(1); - } - -} - -void SsScene2202PuzzleCube::stopMoving() { - loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset); - SetSpriteUpdate(NULL); - _isMoving = false; - sendMessage(_parentScene, 0x2002, _cubePosition); -} - -Scene2202::Scene2202(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _isSolved(false), _leaveScene(false), _isCubeMoving(false), - _ssMovingCube(NULL), _ssDoneMovingCube(NULL) { - - _vm->gameModule()->initCubeSymbolsPuzzle(); - - SetMessageHandler(&Scene2202::handleMessage); - SetUpdateHandler(&Scene2202::update); - - setBackground(0x08100A0C); - setPalette(0x08100A0C); - addEntity(_palette); - insertPuzzleMouse(0x00A08089, 20, 620); - - for (uint32 cubePosition = 0; cubePosition < 9; cubePosition++) { - int16 cubeSymbol = (int16)getSubVar(VA_CUBE_POSITIONS, cubePosition); - if (cubeSymbol >= 0) { - Sprite *puzzleCubeSprite = insertSprite(this, cubePosition, cubeSymbol); - addCollisionSprite(puzzleCubeSprite); - } - } - - insertStaticSprite(0x55C043B8, 200); - insertStaticSprite(0x85500158, 400); - insertStaticSprite(0x25547028, 600); - - loadSound(0, 0x68E25540); - loadSound(1, 0x40400457); - - _vm->_soundMan->addSound(0x60400854, 0x8101A241); - _vm->_soundMan->playSoundLooping(0x8101A241); - -} - -Scene2202::~Scene2202() { - _vm->_soundMan->deleteSoundGroup(0x60400854); -} - -void Scene2202::update() { - Scene::update(); - - if (_leaveScene && !isSoundPlaying(1)) - leaveScene(0); - - if (_isSolved && !isSoundPlaying(0)) { - playSound(1); - _isSolved = false; - _leaveScene = true; - } - - if (_ssMovingCube && !_isCubeMoving) { - int16 freeCubePosition = getFreeCubePosition(_movingCubePosition); - if (freeCubePosition != -1) { - setSurfacePriority(_ssMovingCube->getSurface(), 700); - sendMessage(_ssMovingCube, 0x2001, freeCubePosition); - _ssMovingCube = NULL; - _isCubeMoving = true; - } - } - - if (_ssDoneMovingCube) { - setSurfacePriority(_ssDoneMovingCube->getSurface(), _surfacePriority); - _ssDoneMovingCube = NULL; - if (testIsSolved()) { - playSound(0); - setGlobalVar(V_TILE_PUZZLE_SOLVED, 1); - _isSolved = true; - } - } - -} - -uint32 Scene2202::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) - leaveScene(0); - break; - case 0x2000: - _movingCubePosition = (int16)param.asInteger(); - _ssMovingCube = (Sprite*)sender; - break; - case 0x2002: - _isCubeMoving = false; - _ssDoneMovingCube = (Sprite*)sender; - if (param.asInteger() <= 2) - _surfacePriority = 100; - else if (param.asInteger() >= 3 && param.asInteger() <= 5) - _surfacePriority = 300; - else - _surfacePriority = 500; - break; - } - return 0; -} - -int16 Scene2202::getFreeCubePosition(int16 cubePosition) { - if (cubePosition >= 3 && (int16)getSubVar(VA_CUBE_POSITIONS, cubePosition - 3) == -1) - return cubePosition - 3; - else if (cubePosition <= 5 && (int16)getSubVar(VA_CUBE_POSITIONS, cubePosition + 3) == -1) - return cubePosition + 3; - else if (cubePosition != 0 && cubePosition != 3 && cubePosition != 6 && (int16)getSubVar(VA_CUBE_POSITIONS, cubePosition - 1) == -1) - return cubePosition - 1; - else if (cubePosition != 2 && cubePosition != 5 && cubePosition != 8 && (int16)getSubVar(VA_CUBE_POSITIONS, cubePosition + 1) == -1) - return cubePosition + 1; - else - return -1; -} - -bool Scene2202::testIsSolved() { - return - getSubVar(VA_CUBE_POSITIONS, 0) == 0 && - getSubVar(VA_CUBE_POSITIONS, 2) == 2 && - getSubVar(VA_CUBE_POSITIONS, 3) == 3 && - getSubVar(VA_CUBE_POSITIONS, 4) == 4 && - getSubVar(VA_CUBE_POSITIONS, 5) == 5 && - getSubVar(VA_CUBE_POSITIONS, 6) == 6 && - getSubVar(VA_CUBE_POSITIONS, 8) == 7; -} - -static const uint32 kAsCommonKeyFileHashes[] = { - 0x2450D850, 0x0C9CE8D0, 0x2C58A152 -}; - -AsCommonKey::AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y) - : AnimatedSprite(vm, kAsCommonKeyFileHashes[keyIndex], surfacePriority, x, y), _parentScene(parentScene), _keyIndex(keyIndex) { - - if (!getSubVar(VA_HAS_KEY, _keyIndex) && !getSubVar(VA_IS_KEY_INSERTED, _keyIndex)) { - SetMessageHandler(&AsCommonKey::handleMessage); - } else { - // If Klaymen already has the key or it's already inserted then don't show it - setVisible(false); - SetMessageHandler(NULL); - } -} - -uint32 AsCommonKey::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x4806: - setSubVar(VA_HAS_KEY, _keyIndex, 1); - setVisible(false); - SetMessageHandler(NULL); - } - return messageResult; -} - -static const uint32 kAsScene2203DoorFileHashes[] = { - 0x7868AE10, 0x1A488110 -}; - -AsScene2203Door::AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _doorIndex(doorIndex) { - - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2203Door::handleMessage); - _x = 320; - _y = 240; - createSurface1(kAsScene2203DoorFileHashes[_doorIndex], 900); - if (getGlobalVar(V_LARGE_DOOR_NUMBER) == _doorIndex) { - startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - } else { - startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 0, -1); - _newStickFrameIndex = 0; - } -} - -uint32 AsScene2203Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER)) - sendMessage(_parentScene, 0x2002, 0); - else - sendMessage(_parentScene, 0x2001, 0); - messageResult = 1; - break; - case 0x2000: - _otherDoor = (Sprite*)param.asEntity(); - break; - case 0x3002: - if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER)) - sendMessage(_parentScene, 0x4808, 0); - stopAnimation(); - break; - case 0x4808: - setGlobalVar(V_LARGE_DOOR_NUMBER, _doorIndex); - sendMessage(_otherDoor, 0x4809, 0); - openDoor(); - break; - case 0x4809: - closeDoor(); - sendMessage(_parentScene, 0x2003, 0); - break; - } - return messageResult; -} - -void AsScene2203Door::openDoor() { - playSound(0, 0x341014C4); - startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 1, -1); -} - -void AsScene2203Door::closeDoor() { - startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1); - _playBackwards = true; - _newStickFrameIndex = 0; -} - -Scene2203::Scene2203(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) - setGlobalVar(V_KEY3_LOCATION, 1); - - SetMessageHandler(&Scene2203::handleMessage); - - setBackground(0x82C80334); - setPalette(0x82C80334); - insertScreenMouse(0x80330824); - setHitRects(0x004B8320); - setRectList(0x004B8420); - - if (getGlobalVar(V_KEY3_LOCATION) == 1) { - _asKey = insertSprite(this, 2, 1100, 282, 432); - addCollisionSprite(_asKey); - } - - _asTape = insertSprite(this, 1, 1100, 435, 432, 0x9148A011); - addCollisionSprite(_asTape); - _asLeftDoor = insertSprite(this, 0); - _asRightDoor = insertSprite(this, 1); - _ssSmallLeftDoor = insertStaticSprite(0x542CC072, 1100); - _ssSmallRightDoor = insertStaticSprite(0x0A2C0432, 1100); - _leftDoorClipRect.set(_ssSmallLeftDoor->getDrawRect().x, 0, 640, 480); - _rightDoorClipRect.set(0, 0, _ssSmallRightDoor->getDrawRect().x2(), 480); - sendEntityMessage(_asLeftDoor, 0x2000, _asRightDoor); - sendEntityMessage(_asRightDoor, 0x2000, _asLeftDoor); - addCollisionSprite(_asLeftDoor); - addCollisionSprite(_asRightDoor); - - if (which < 0) { - // Restoring game - insertKlaymen(200, 427); - setMessageList(0x004B8340); - } else if (which == 1) { - // Klaymen entering from the right - insertKlaymen(640, 427); - setMessageList(0x004B8350); - } else if (which == 2) { - // Klaymen returning from the displayer - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { - insertKlaymen(362, 427); - _klaymen->setDoDeltaX(1); - } else - insertKlaymen(202, 427); - setMessageList(0x004B8358); - } else { - // Klaymen entering from the left - insertKlaymen(0, 427); - setMessageList(0x004B8348); - } - - if (getGlobalVar(V_LARGE_DOOR_NUMBER)) { - _ssSmallLeftDoor->setVisible(false); - _klaymen->setClipRect(_rightDoorClipRect); - } else { - _ssSmallRightDoor->setVisible(false); - _klaymen->setClipRect(_leftDoorClipRect); - } - -} - -Scene2203::~Scene2203() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); -} - -uint32 Scene2203::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2001: - sendEntityMessage(_klaymen, 0x1014, sender); - if (sender == _asLeftDoor) - setMessageList2(0x004B83B0); - else - setMessageList2(0x004B83C8); - break; - case 0x2002: - if (sender == _asLeftDoor) - setMessageList2(0x004B8370); - else - setMessageList2(0x004B8360); - break; - case 0x2003: - if (sender == _asLeftDoor) - _ssSmallLeftDoor->setVisible(false); - else - _ssSmallRightDoor->setVisible(false); - break; - case 0x4808: - if (sender == _asLeftDoor) { - _ssSmallLeftDoor->setVisible(true); - _klaymen->setClipRect(_leftDoorClipRect); - } else { - _ssSmallRightDoor->setVisible(true); - _klaymen->setClipRect(_rightDoorClipRect); - } - break; - case 0x4826: - if (sender == _asTape) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004B83E0); - } else if (sender == _asKey) { - sendEntityMessage(_klaymen, 0x1014, _asKey); - setMessageList(0x004B83F0); - } - break; - } - return messageResult; -} - -SsScene2205DoorFrame::SsScene2205DoorFrame(NeverhoodEngine *vm) - : StaticSprite(vm, 900) { - - SetMessageHandler(&SsScene2205DoorFrame::handleMessage); - createSurface(1100, 45, 206); - loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition); -} - -uint32 SsScene2205DoorFrame::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition); - break; - } - return messageResult; -} - -Scene2205::Scene2205(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - SetMessageHandler(&Scene2205::handleMessage); - SetUpdateHandler(&Scene2205::update); - - setHitRects(0x004B0620); - if (getGlobalVar(V_LIGHTS_ON)) { - _isLightOn = true; - setBackground(0x0008028D); - setPalette(0x0008028D); - addEntity(_palette); - insertScreenMouse(0x80289008); - _ssLightSwitch = insertSprite(this, 0x2D339030, 0x2D309030, 100, 0); - } else { - _isLightOn = false; - setBackground(0xD00A028D); - setPalette(0xD00A028D); - addEntity(_palette); - insertScreenMouse(0xA0289D08); - _ssLightSwitch = insertSprite(this, 0x2D339030, 0xDAC86E84, 100, 0); - } - _palette->addBasePalette(0xD00A028D, 0, 256, 0); - _ssDoorFrame = insertSprite(); - - if (which < 0) { - // Restoring game - insertKlaymen(320, 417); - setMessageList(0x004B0658); - if (!getGlobalVar(V_LIGHTS_ON)) - _palette->addPalette(0x68033B1C, 0, 65, 0); - _isKlaymenInLight = false; - } else if (which == 1) { - // Klaymen entering from the right - insertKlaymen(640, 417); - setMessageList(0x004B0648); - if (!getGlobalVar(V_LIGHTS_ON)) - _palette->addPalette(0x68033B1C, 0, 65, 0); - _isKlaymenInLight = false; - } else { - // Klaymen entering from the left - insertKlaymen(0, 417); - setMessageList(0x004B0640); - _isKlaymenInLight = true; - } - - _klaymen->setClipRect(_ssDoorFrame->getDrawRect().x, 0, 640, 480); - _klaymen->setSoundFlag(true); - - loadDataResource(0x00144822); - -} - -void Scene2205::update() { - Scene::update(); - if (!_isLightOn && getGlobalVar(V_LIGHTS_ON)) { - _palette->addPalette(0x0008028D, 0, 256, 0); - changeBackground(0x0008028D); - _ssLightSwitch->setFileHashes(0x2D339030, 0x2D309030); - sendMessage(_ssDoorFrame, 0x2000, 0); - changeMouseCursor(0x80289008); - _isLightOn = true; - } else if (_isLightOn && !getGlobalVar(V_LIGHTS_ON)) { - _palette->addPalette(0xD00A028D, 0, 256, 0); - changeBackground(0xD00A028D); - _ssLightSwitch->setFileHashes(0x2D339030, 0xDAC86E84); - sendMessage(_ssDoorFrame, 0x2000, 0); - changeMouseCursor(0xA0289D08); - _isKlaymenInLight = true; - if (_klaymen->getX() > 85) { - _palette->addPalette(0x68033B1C, 0, 65, 0); - _isKlaymenInLight = false; - } - _isLightOn = false; - } - if (!getGlobalVar(V_LIGHTS_ON)) { - if (_isKlaymenInLight && _klaymen->getX() > 85) { - _palette->addBasePalette(0x68033B1C, 0, 65, 0); - _palette->startFadeToPalette(12); - _isKlaymenInLight = false; - } else if (!_isKlaymenInLight && _klaymen->getX() <= 85) { - _palette->addBasePalette(0xD00A028D, 0, 65, 0); - _palette->startFadeToPalette(12); - _isKlaymenInLight = true; - } - } -} - -uint32 Scene2205::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x6449569A) - setMessageList(0x004B0690); - else if (param.asInteger() == 0x2841369C) - setMessageList(0x004B0630); - else if (param.asInteger() == 0x402064D8) - sendEntityMessage(_klaymen, 0x1014, _ssLightSwitch); - break; - case 0x480B: - setGlobalVar(V_LIGHTS_ON, getGlobalVar(V_LIGHTS_ON) ? 0 : 1); - break; - } - return 0; -} - -static const int16 kScene2206XPositions[] = { - 384, 480, 572 -}; - -static const uint32 kScene2206MessageIds1[] = { - 0x004B8998, 0x004B89B8, 0x004B89D8 -}; - -static const uint32 kScene2206MessageIds2[] = { - 0x004B89F8, 0x004B8A20, 0x004B8A48 -}; - -static const int16 kAsScene2206DoorSpikesXDeltasOpen[] = { - -24, -28, -18, 6, 9, -8 -}; - -static const int16 kAsScene2206DoorSpikesXDeltasClose[] = { - -8, 7, 11, 26, 13, 14 -}; - -AsScene2206DoorSpikes::AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash) - : StaticSprite(vm, fileHash, 200) { - - if (getGlobalVar(V_SPIKES_RETRACTED)) - _x -= 63; - SetUpdateHandler(&AsScene2206DoorSpikes::update); - SetMessageHandler(&AsScene2206DoorSpikes::handleMessage); - SetSpriteUpdate(NULL); -} - -void AsScene2206DoorSpikes::update() { - handleSpriteUpdate(); - updatePosition(); -} - -uint32 AsScene2206DoorSpikes::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4808: - _deltaIndex = 0; - playSound(0, 0x032746E0); - SetMessageHandler(NULL); - SetSpriteUpdate(&AsScene2206DoorSpikes::suOpen); - break; - case 0x4809: - _deltaIndex = 0; - playSound(0, 0x002642C0); - SetMessageHandler(NULL); - SetSpriteUpdate(&AsScene2206DoorSpikes::suClose); - break; - } - return messageResult; -} - -void AsScene2206DoorSpikes::suOpen() { - if (_deltaIndex < 6) { - _x += kAsScene2206DoorSpikesXDeltasOpen[_deltaIndex]; - _deltaIndex++; - } else { - SetMessageHandler(&AsScene2206DoorSpikes::handleMessage); - SetSpriteUpdate(NULL); - } -} - -void AsScene2206DoorSpikes::suClose() { - if (_deltaIndex < 6) { - _x += kAsScene2206DoorSpikesXDeltasClose[_deltaIndex]; - _deltaIndex++; - } else { - SetMessageHandler(&AsScene2206DoorSpikes::handleMessage); - SetSpriteUpdate(NULL); - } -} - -AsScene2206Platform::AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash) - : StaticSprite(vm, fileHash, 50) { - - SetUpdateHandler(&AsScene2206Platform::update); - SetMessageHandler(&AsScene2206Platform::handleMessage); - SetSpriteUpdate(NULL); -} - -void AsScene2206Platform::update() { - handleSpriteUpdate(); - updatePosition(); -} - -uint32 AsScene2206Platform::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4803: - _yDelta = 0; - SetMessageHandler(NULL); - SetSpriteUpdate(&AsScene2206Platform::suMoveDown); - break; - } - return messageResult; -} - -void AsScene2206Platform::suMoveDown() { - _yDelta++; - _y += _yDelta; -} - -SsScene2206TestTube::SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash) - : StaticSprite(vm, fileHash, surfacePriority), _parentScene(parentScene) { - - if (getGlobalVar(V_HAS_TEST_TUBE)) { - setVisible(false); - SetMessageHandler(NULL); - } else - SetMessageHandler(&SsScene2206TestTube::handleMessage); - _collisionBoundsOffset = _drawOffset; - updateBounds(); -} - -uint32 SsScene2206TestTube::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x4806: - setGlobalVar(V_HAS_TEST_TUBE, 1); - setVisible(false); - SetMessageHandler(NULL); - break; - } - return messageResult; -} - -Scene2206::Scene2206(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - uint32 fileHash; - - SetUpdateHandler(&Scene::update); - SetMessageHandler(&Scene2206::handleMessage); - - if (getGlobalVar(V_LIGHTS_ON)) { - fileHash = 0x41983216; - _sprite1 = insertStaticSprite(0x2201266A, 100); - _sprite2 = insertStaticSprite(0x3406A333, 300); - _sprite3 = insertStaticSprite(0x24A223A2, 100); - _asDoorSpikes = insertSprite(0x26133023); - _asDoorSpikes->setClipRect(_sprite2->getDrawRect().x, 0, 640, 480); - setRectList(0x004B8AF8); - _ssButton = insertSprite(this, 0x0E038022, 100, 0); - insertScreenMouse(0x83212411); - _ssTestTube = insertSprite(this, 1100, /*464, 433, */0x5E00E262); - _asPlatform = insertSprite(0x085E25E0); - } else { - fileHash = 0xE0102A45; - _sprite1 = insertStaticSprite(0x1C1106B8, 100); - _sprite2 = insertStaticSprite(0x020462E0, 300); - _sprite3 = insertStaticSprite(0x900626A2, 100); - _asDoorSpikes = insertSprite(0x544822A8); - _asDoorSpikes->setClipRect(_sprite2->getDrawRect().x, 0, 640, 480); - setRectList(0x004B8B58); - _ssButton = insertSprite(this, 0x16882608, 100, 0); - insertScreenMouse(0x02A41E09); - _ssTestTube = insertSprite(this, 1100, /*464, 433, */0x52032563); - _asPlatform = insertSprite(0x317831A0); - } - - _asPlatform->setClipRect(_sprite2->getDrawRect().x, 0, _sprite3->getDrawRect().x2(), _sprite1->getDrawRect().y2()); - setBackground(fileHash); - setPalette(fileHash); - addEntity(_palette); - _palette->addBasePalette(fileHash, 0, 256, 0); - if (!getGlobalVar(V_LIGHTS_ON)) - _palette->addPalette(0x0263D144, 0, 65, 0); - addCollisionSprite(_ssTestTube); - - if (which < 0) { - // Restoring game - insertKlaymen(200, 430); - setMessageList(0x004B88A8); - } else if (which == 1) { - // Klaymen entering from the right - insertKlaymen(640, 430); - setMessageList(0x004B88B8); - } else if (which == 2) { - // Klaymen entering from the back - insertKlaymen(205, 396); - setMessageList(0x004B88C8); - _palette->addPalette(getGlobalVar(V_LIGHTS_ON) ? 0xB103B604 : 0x0263D144, 0, 65, 0); - klaymenBehindSpikes(); - playSound(0, 0x53B8284A); - } else if (which == 3) { - // Klaymen entering from reading a text column - insertKlaymen(kScene2206XPositions[getGlobalVar(V_CLICKED_COLUMN_INDEX)], 430); - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) - _klaymen->setDoDeltaX(1); - setMessageList(0x004B8A70); - } else { - // Klaymen entering from the left - insertKlaymen(0, 430); - setMessageList(0x004B88B0); - } - - _klaymen->setSoundFlag(true); - _klaymen->setKlaymenIdleTable2(); - -} - -Scene2206::~Scene2206() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); -} - -uint32 Scene2206::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x800C6694) - readClickedColumn(); - else if (param.asInteger() == 0x402064D8) - sendEntityMessage(_klaymen, 0x1014, _ssButton); - else if (param.asInteger() == 0x11C40840) { - if (getGlobalVar(V_SPIKES_RETRACTED)) - setMessageList(0x004B8948); - else - setMessageList(0x004B8970); - } - break; - case 0x4803: - sendMessage(_asPlatform, 0x4803, 0); - break; - case 0x480B: - if (sender == _ssButton) { - setGlobalVar(V_SPIKES_RETRACTED, getGlobalVar(V_SPIKES_RETRACTED) ? 0 : 1); - if (getGlobalVar(V_SPIKES_RETRACTED)) - sendMessage(_asDoorSpikes, 0x4808, 0); - else - sendMessage(_asDoorSpikes, 0x4809, 0); - } - break; - case 0x4826: - sendEntityMessage(_klaymen, 0x1014, _ssTestTube); - setMessageList(0x004B8988); - break; - case 0x482A: - klaymenBehindSpikes(); - break; - case 0x482B: - klaymenInFrontSpikes(); - break; - } - return messageResult; -} - -void Scene2206::klaymenInFrontSpikes() { - if (getGlobalVar(V_LIGHTS_ON)) { - _palette->addBasePalette(0x41983216, 0, 65, 0); - _palette->startFadeToPalette(12); - } - setSurfacePriority(_sprite1->getSurface(), 100); - setSurfacePriority(_sprite2->getSurface(), 300); - setSurfacePriority(_sprite3->getSurface(), 100); - setSurfacePriority(_asDoorSpikes->getSurface(), 200); - _klaymen->setClipRect(0, 0, 640, 480); -} - -void Scene2206::klaymenBehindSpikes() { - if (!getGlobalVar(V_LIGHTS_ON)) { - _palette->addBasePalette(0xB103B604, 0, 65, 0); - _palette->startFadeToPalette(12); - } - setSurfacePriority(_sprite1->getSurface(), 1100); - setSurfacePriority(_sprite2->getSurface(), 1300); - setSurfacePriority(_sprite3->getSurface(), 1100); - setSurfacePriority(_asDoorSpikes->getSurface(), 1200); - _klaymen->setClipRect(_sprite2->getDrawRect().x, 0, _sprite3->getDrawRect().x2(), _sprite1->getDrawRect().y2()); -} - -void Scene2206::readClickedColumn() { - setGlobalVar(V_CLICKED_COLUMN_INDEX, (_mouseClickPos.x - 354) / 96); - if (getGlobalVar(V_CLICKED_COLUMN_INDEX) > 2) - setGlobalVar(V_CLICKED_COLUMN_INDEX, 2); - setGlobalVar(V_CLICKED_COLUMN_ROW, (_mouseClickPos.y - 183) / 7); - setGlobalVar(V_COLUMN_TEXT_NAME, calcHash("stLineagex")); - setGlobalVar(V_COLUMN_BACK_NAME, 0); - if (ABS(kScene2206XPositions[getGlobalVar(V_CLICKED_COLUMN_INDEX)] - _klaymen->getX()) >= 144) - setMessageList2(kScene2206MessageIds1[getGlobalVar(V_CLICKED_COLUMN_INDEX)]); - else - setMessageList2(kScene2206MessageIds2[getGlobalVar(V_CLICKED_COLUMN_INDEX)]); -} - -static const uint32 kScene2207FileHashes[] = { - 0x33B1E12E, 0x33D1E12E, 0x3311E12E, - 0x3291E12E, 0x3191E12E, 0x3791E12E, - 0x3B91E12E, 0x2391E12E, 0x1391E12E, - 0x3BB1E12E, 0x23B1E12E, 0x13B1E12E -}; - -AsScene2207Elevator::AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 900), _parentScene(parentScene), _pointIndex(0), _destPointIndex(0), _destPointIndexDelta(0) { - - NPoint pt; - - _dataResource.load(0x00524846); - _pointArray = _dataResource.getPointArray(0x005B02B7); - pt = _dataResource.getPoint(0x403A82B1); - _x = pt.x; - _y = pt.y; - createSurface(1100, 129, 103); - startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, 0, 0); - _newStickFrameIndex = 0; - SetUpdateHandler(&AsScene2207Elevator::update); - SetMessageHandler(&AsScene2207Elevator::handleMessage); - SetSpriteUpdate(&AsScene2207Elevator::suSetPosition); -} - -AsScene2207Elevator::~AsScene2207Elevator() { - _vm->_soundMan->deleteSoundGroup(0x02700413); -} - -void AsScene2207Elevator::update() { - - if (_destPointIndex + _destPointIndexDelta > _pointIndex) { - _pointIndex++; - startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex); - _newStickFrameIndex = _pointIndex; - if (_destPointIndex + _destPointIndexDelta == _pointIndex) { - if (_destPointIndexDelta != 0) - _destPointIndexDelta = 0; - else { - _vm->_soundMan->deleteSound(0xD3B02847); - playSound(0, 0x53B8284A); - } - } - } - - if (_destPointIndex + _destPointIndexDelta < _pointIndex) { - _pointIndex--; - if (_pointIndex == 0) - sendMessage(_parentScene, 0x2003, 0); - startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex); - _newStickFrameIndex = _pointIndex; - if (_destPointIndex + _destPointIndexDelta == _pointIndex) { - if (_destPointIndexDelta != 0) - _destPointIndexDelta = 0; - else { - _vm->_soundMan->deleteSound(0xD3B02847); - playSound(0, 0x53B8284A); - } - } - } - - if (_pointIndex > 20 && _surface->getPriority() != 900) - sendMessage(_parentScene, 0x2002, 900); - else if (_pointIndex < 20 && _surface->getPriority() != 1100) - sendMessage(_parentScene, 0x2002, 1100); - - AnimatedSprite::update(); - - if (_destPointIndex + _destPointIndexDelta == _pointIndex && _isMoving) { - sendMessage(_parentScene, 0x2004, 0); - _isMoving = false; - } - -} - -void AsScene2207Elevator::suSetPosition() { - _x = (*_pointArray)[_pointIndex].x; - _y = (*_pointArray)[_pointIndex].y - 60; - updateBounds(); -} - -uint32 AsScene2207Elevator::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - moveToY(param.asInteger()); - break; - } - return messageResult; -} - -void AsScene2207Elevator::moveToY(int16 y) { - int16 minDistance = 480; - - if (!_pointArray || _pointArray->size() == 0) - return; - - for (uint i = 0; i < _pointArray->size(); i++) { - int16 distance = ABS(y - (*_pointArray)[i].y); - if (distance < minDistance) { - minDistance = distance; - _destPointIndex = i; - } - } - - if (_destPointIndex != _pointIndex) { - if (_destPointIndex == 0 || _destPointIndex == (int)_pointArray->size() - 1) - _destPointIndexDelta = 0; - else if (_destPointIndex < _pointIndex) - _destPointIndexDelta = -2; - else - _destPointIndexDelta = 2; - _vm->_soundMan->addSound(0x02700413, 0xD3B02847); - _vm->_soundMan->playSoundLooping(0xD3B02847); - } - - _isMoving = true; - -} - -AsScene2207Lever::AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX) - : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - - _x = x; - _y = y; - createSurface(1010, 71, 73); - setDoDeltaX(doDeltaX); - startAnimation(0x80880090, 0, -1); - _newStickFrameIndex = 0; - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2207Lever::handleMessage); -} - -uint32 AsScene2207Lever::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x3002: - gotoNextState(); - stopAnimation(); - break; - case 0x4807: - stLeverUp(); - break; - case 0x480F: - stLeverDown(); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -void AsScene2207Lever::stLeverDown() { - startAnimation(0x80880090, 1, -1); - playSound(0, 0x40581882); - FinalizeState(&AsScene2207Lever::stLeverDownEvent); -} - -void AsScene2207Lever::stLeverDownEvent() { - sendMessage(_parentScene, 0x480F, 0); -} - -void AsScene2207Lever::stLeverUp() { - startAnimation(0x80880090, 6, -1); - _playBackwards = true; - playSound(0, 0x40581882); - FinalizeState(&AsScene2207Lever::stLeverUpEvent); -} - -void AsScene2207Lever::stLeverUpEvent() { - sendMessage(_parentScene, 0x4807, 0); -} - -AsScene2207WallRobotAnimation::AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 1200), _idle(true) { - - _x = 309; - _y = 320; - createSurface1(0xCCFD6090, 100); - startAnimation(0xCCFD6090, 0, -1); - _newStickFrameIndex = 0; - loadSound(1, 0x40330872); - loadSound(2, 0x72A2914A); - loadSound(3, 0xD4226080); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2207WallRobotAnimation::handleMessage); -} - -AsScene2207WallRobotAnimation::~AsScene2207WallRobotAnimation() { - _vm->_soundMan->deleteSoundGroup(0x80D00820); -} - -uint32 AsScene2207WallRobotAnimation::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (!_idle) { - if (param.asInteger() == 0x3423093) { - _vm->_soundMan->addSound(0x80D00820, 0x12121943); - _vm->_soundMan->playSoundLooping(0x12121943); - } else if (param.asInteger() == 0x834AB011) { - stopSound(0); - stopSound(1); - stopSound(2); - stopSound(3); - _vm->_soundMan->deleteSound(0x12121943); - } else if (param.asInteger() == 0x3A980501) - playSound(1); - else if (param.asInteger() == 0x2A2AD498) - playSound(2); - else if (param.asInteger() == 0xC4980008) - playSound(3); - else if (param.asInteger() == 0x06B84228) - playSound(0, 0xE0702146); - } - break; - case 0x2006: - stStartAnimation(); - break; - case 0x2007: - stStopAnimation(); - break; - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene2207WallRobotAnimation::stStartAnimation() { - if (!_idle) { - NextState(NULL); - } else { - startAnimation(0xCCFD6090, 0, -1); - _idle = false; - setVisible(true); - } -} - -void AsScene2207WallRobotAnimation::stStopAnimation() { - NextState(&AsScene2207WallRobotAnimation::cbStopAnimation); -} - -void AsScene2207WallRobotAnimation::cbStopAnimation() { - stopAnimation(); - stopSound(0); - stopSound(1); - stopSound(2); - stopSound(3); - _vm->_soundMan->deleteSound(0x12121943); - _idle = true; - setVisible(false); -} - -AsScene2207WallCannonAnimation::AsScene2207WallCannonAnimation(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1200), _idle(true) { - - _x = 309; - _y = 320; - createSurface1(0x8CAA0099, 100); - startAnimation(0x8CAA0099, 0, -1); - _newStickFrameIndex = 0; - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2207WallCannonAnimation::handleMessage); -} - -uint32 AsScene2207WallCannonAnimation::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2006: - stStartAnimation(); - break; - case 0x2007: - stStopAnimation(); - break; - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene2207WallCannonAnimation::stStartAnimation() { - if (!_idle) { - NextState(NULL); - } else { - setVisible(true); - startAnimation(0x8CAA0099, 0, -1); - _idle = false; - } -} - -void AsScene2207WallCannonAnimation::stStopAnimation() { - NextState(&AsScene2207WallCannonAnimation::cbStopAnimation); -} - -void AsScene2207WallCannonAnimation::cbStopAnimation() { - stopAnimation(); - setVisible(false); - _idle = true; -} - -SsScene2207Symbol::SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index) - : StaticSprite(vm, fileHash, 100) { - - _x = 330; - _y = 246 + index * 50; - updatePosition(); -} - -Scene2207::Scene2207(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule), _klaymenAtElevator(true), _elevatorSurfacePriority(0) { - - _vm->gameModule()->initCannonSymbolsPuzzle(); - - if (!getSubVar(VA_IS_PUZZLE_INIT, 0x88460852)) - setSubVar(VA_IS_PUZZLE_INIT, 0x88460852, 1); - - SetMessageHandler(&Scene2207::handleMessage); - SetUpdateHandler(&Scene2207::update); - - insertKlaymen(0, 0); - _klaymen->setRepl(64, 0); - setMessageList(0x004B38E8); - _asElevator = insertSprite(this); - - if (getGlobalVar(V_LIGHTS_ON)) { - setBackground(0x88C00241); - setPalette(0x88C00241); - insertScreenMouse(0x00245884); - _ssMaskPart1 = insertStaticSprite(0xE20A28A0, 1200); - _ssMaskPart2 = insertStaticSprite(0x688F62A5, 1100); - _ssMaskPart3 = insertStaticSprite(0x0043B038, 1100); - _asTape = insertSprite(this, 4, 1100, 277, 428, 0x9148A011); - addCollisionSprite(_asTape); - _asLever = insertSprite(this, 527, 333, 0); - addCollisionSprite(_asLever); - _asWallRobotAnimation = insertSprite(this); - _asWallCannonAnimation = insertSprite(); - _asWallRobotAnimation->setVisible(false); - _asWallCannonAnimation->setVisible(false); - _ssButton = insertSprite(this, 0x2C4061C4, 100, 0); - _asLever->setClipRect(0, 0, _ssMaskPart3->getDrawRect().x2(), 480); - _klaymen->setClipRect(0, _ssMaskPart1->getDrawRect().y, 640, _ssMaskPart2->getDrawRect().y2()); - _asElevator->setClipRect(0, _ssMaskPart1->getDrawRect().y, 640, _ssMaskPart2->getDrawRect().y2()); - } else { - setGlobalVar(V_SEEN_SYMBOLS_NO_LIGHT, 1); - setBackground(0x05C02A55); - setPalette(0x05C02A55); - insertScreenMouse(0x02A51054); - _ssMaskPart1 = insertStaticSprite(0x980E46A4, 1200); - insertSprite(kScene2207FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_1, 0)], 0); - insertSprite(kScene2207FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_1, 1)], 1); - insertSprite(kScene2207FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_1, 2)], 2); - _asTape = NULL; - _asLever = NULL; - _asWallRobotAnimation = NULL; - _asWallCannonAnimation = NULL; - _ssButton = NULL; - _klaymen->setClipRect(0, _ssMaskPart1->getDrawRect().y, 640, 480); - _asElevator->setClipRect(0, _ssMaskPart1->getDrawRect().y, 640, 480); - } - - _dataResource.load(0x00524846); - setRectList(0x004B38B8); - - sendEntityMessage(_klaymen, 0x1014, _asElevator); - sendMessage(_klaymen, 0x2001, 0); - sendMessage(_asElevator, 0x2000, 480); - - loadSound(1, calcHash("fxFogHornSoft")); - -} - -void Scene2207::update() { - Scene::update(); - if (_elevatorSurfacePriority != 0) { - setSurfacePriority(_asElevator->getSurface(), _elevatorSurfacePriority); - _elevatorSurfacePriority = 0; - } - if (_klaymen->getY() == 423) - _klaymenAtElevator = _klaymen->getX() > 459 && _klaymen->getX() < 525; -} - -uint32 Scene2207::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x0014F275) { - if (_klaymenAtElevator) { - sendMessage(_asElevator, 0x2000, _mouseClickPos.y); - sendEntityMessage(_klaymen, 0x1014, _asElevator); - sendMessage(_klaymen, 0x2001, 0); - } else - cancelMessageList(); - } else if (param.asInteger() == 0x34569073) { - if (_klaymenAtElevator) { - _isKlaymenBusy = true; - sendMessage(_asElevator, 0x2000, 0); - sendEntityMessage(_klaymen, 0x1014, _asElevator); - sendMessage(_klaymen, 0x2001, 0); - } else - cancelMessageList(); - } else if (param.asInteger() == 0x4054C877) { - if (_klaymenAtElevator) { - sendMessage(_asElevator, 0x2000, 480); - sendEntityMessage(_klaymen, 0x1014, _asElevator); - sendMessage(_klaymen, 0x2001, 0); - } else - cancelMessageList(); - } else if (param.asInteger() == 0x0CBC6211) { - sendEntityMessage(_klaymen, 0x1014, _asElevator); - sendMessage(_klaymen, 0x2001, 0); - setRectList(0x004B38B8); - } else if (param.asInteger() == 0x402064D8) - sendEntityMessage(_klaymen, 0x1014, _ssButton); - else if (param.asInteger() == 0x231DA241) { - if (_ssButton) - setMessageList(0x004B38F0); - else - setMessageList(0x004B37D8); - } - break; - case 0x2002: - _elevatorSurfacePriority = param.asInteger(); - break; - case 0x2003: - _isKlaymenBusy = false; - break; - case 0x4807: - sendMessage(_asWallRobotAnimation, 0x2007, 0); - sendMessage(_asWallCannonAnimation, 0x2007, 0); - break; - case 0x480B: - if (sender == _ssButton) { - if (getSubVar(VA_LOCKS_DISABLED, 0x40119852)) { - setSubVar(VA_LOCKS_DISABLED, 0x40119852, 0); - playSound(0, calcHash("fx3LocksDisable")); - } else { - setSubVar(VA_LOCKS_DISABLED, 0x40119852, 1); - playSound(1); - } - } - break; - case 0x480F: - sendMessage(_asWallRobotAnimation, 0x2006, 0); - sendMessage(_asWallCannonAnimation, 0x2006, 0); - _asWallRobotAnimation->setVisible(true); - _asWallCannonAnimation->setVisible(true); - break; - case 0x4826: - if (sender == _asTape) { - if (_klaymen->getY() == 423) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004B3958); - } - } else if (_klaymenAtElevator) { - SetMessageHandler(&Scene2207::handleMessage2); - sendMessage(_asElevator, 0x2000, 347); - sendEntityMessage(_klaymen, 0x1014, _asElevator); - sendMessage(_klaymen, 0x2001, 0); - } - break; - } - return messageResult; -} - -uint32 Scene2207::handleMessage2(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2002: - _elevatorSurfacePriority = param.asInteger(); - break; - case 0x2004: - SetMessageHandler(&Scene2207::handleMessage); - sendMessage(_klaymen, 0x2005, 0); - sendEntityMessage(_klaymen, 0x1014, _asLever); - setMessageList(0x004B3920); - setRectList(0x004B3948); - break; - } - return messageResult; -} - -static const uint32 kScene2208FileHashes1[] = { - 0x041023CB, 0x041020CB, 0x041026CB, 0x04102ACB, - 0x041032CB, 0x041002CB -}; - -static const uint32 kScene2208FileHashes2[] = { - 0x091206C9, 0x091406C9, 0x091806C9, 0x090006C9, - 0x093006C9, 0x095006C9 -}; - -Scene2208::Scene2208(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _textResource(vm) { - - SpriteResource spriteResource(_vm); - const char *textStart, *textEnd; - - if (!getGlobalVar(V_COLUMN_TEXT_NAME)) - setGlobalVar(V_COLUMN_TEXT_NAME, calcHash("stLineagex")); - - _textResource.load(getGlobalVar(V_COLUMN_TEXT_NAME)); - - textStart = _textResource.getString(getGlobalVar(V_CLICKED_COLUMN_INDEX), textEnd); - while (textStart < textEnd) { - _strings.push_back(textStart); - textStart += strlen(textStart) + 1; - } - - _maxRowIndex = 8 + 10 * (3 - (getGlobalVar(V_COLUMN_TEXT_NAME) == calcHash("stLineagex") ? 1 : 0)); - - _background = new Background(_vm, 0); - _background->createSurface(0, 640, 528); - _background->getSpriteResource().getPosition().y = 480; - addBackground(_background); - setPalette(0x08100289); - addEntity(_palette); - insertPuzzleMouse(0x0028D089, 40, 600); - - _fontSurface = FontSurface::createFontSurface(_vm, 0x0800090C); - - _backgroundSurface = new BaseSurface(_vm, 0, 640, 480); - spriteResource.load(0x08100289, true); - _backgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0); - - _topBackgroundSurface = new BaseSurface(_vm, 0, 640, 192); - spriteResource.load(!getGlobalVar(V_COLUMN_BACK_NAME) - ? kScene2208FileHashes1[getGlobalVar(V_CLICKED_COLUMN_INDEX) % 6] - : getGlobalVar(V_COLUMN_BACK_NAME), true); - _topBackgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0); - - _bottomBackgroundSurface = new BaseSurface(_vm, 0, 640, 192); - spriteResource.load(kScene2208FileHashes2[getGlobalVar(V_CLICKED_COLUMN_INDEX) % 6], true); - _bottomBackgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0); - - SetUpdateHandler(&Scene2208::update); - SetMessageHandler(&Scene2208::handleMessage); - - _visibleRowsCount = 10; - _newRowIndex = (int16)getGlobalVar(V_CLICKED_COLUMN_ROW); - if (_newRowIndex + _visibleRowsCount > _maxRowIndex) - _newRowIndex = _maxRowIndex - _visibleRowsCount; - if (_newRowIndex < 6) - _newRowIndex = 0; - _rowScrollY = 0; - _backgroundScrollY = 48 * _newRowIndex; - _currRowIndex = _newRowIndex; - - for (int16 rowIndex = 0; rowIndex < _visibleRowsCount; rowIndex++) - drawRow(_newRowIndex + rowIndex); - - _background->getSurface()->getSysRect().y = _backgroundScrollY; - -} - -Scene2208::~Scene2208() { - delete _fontSurface; - delete _backgroundSurface; - delete _topBackgroundSurface; - delete _bottomBackgroundSurface; -} - -void Scene2208::update() { - - int16 mouseY = _vm->getMouseY(); - - if (mouseY < 48) { - if (_currRowIndex > 0) - _newRowIndex = _currRowIndex - 1; - } else if (mouseY > 432) { - if (_currRowIndex < _maxRowIndex - _visibleRowsCount) - _newRowIndex = _currRowIndex + 1; - } else { - if (_currRowIndex > _newRowIndex) - _newRowIndex = _currRowIndex; - } - - if (_currRowIndex < _newRowIndex) { - if (_rowScrollY == 0) - drawRow(_currRowIndex + _visibleRowsCount); - _backgroundScrollY += 4; - _rowScrollY += 4; - if (_rowScrollY == 48) { - _rowScrollY = 0; - _currRowIndex++; - } - _background->getSurface()->getSysRect().y = _backgroundScrollY; - } else if (_currRowIndex > _newRowIndex || _rowScrollY > 0) { - if (_rowScrollY == 0) { - drawRow(_currRowIndex - 1); - _currRowIndex--; - } - _backgroundScrollY -= 4; - if (_rowScrollY == 0) - _rowScrollY = 48; - _rowScrollY -= 4; - _background->getSurface()->getSysRect().y = _backgroundScrollY; - } - - Scene::update(); - -} - -uint32 Scene2208::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 40 || param.asPoint().x >= 600) - leaveScene(0); - break; - } - return messageResult; -} - -void Scene2208::drawRow(int16 rowIndex) { - NDrawRect sourceRect; - int16 y = (rowIndex * 48) % 528; - if (rowIndex < 4) { - sourceRect.x = 0; - sourceRect.y = y; - sourceRect.width = 640; - sourceRect.height = 48; - _background->getSurface()->copyFrom(_topBackgroundSurface->getSurface(), 0, y, sourceRect); - } else if (rowIndex > _maxRowIndex - 5) { - sourceRect.x = 0; - sourceRect.y = (rowIndex - _maxRowIndex + 4) * 48; - sourceRect.width = 640; - sourceRect.height = 48; - _background->getSurface()->copyFrom(_bottomBackgroundSurface->getSurface(), 0, y, sourceRect); - } else { - rowIndex -= 4; - sourceRect.x = 0; - sourceRect.y = (rowIndex * 48) % 480; - sourceRect.width = 640; - sourceRect.height = 48; - _background->getSurface()->copyFrom(_backgroundSurface->getSurface(), 0, y, sourceRect); - if (rowIndex < (int)_strings.size()) { - const char *text = _strings[rowIndex]; - _fontSurface->drawString(_background->getSurface(), 95, y, (const byte*)text); - } - } -} - -static const int16 kScene2242XPositions[] = { - 68, 158 -}; - -static const uint32 kScene2242MessageListIds2[] = { - 0x004B3CB8, 0x004B3CD8 -}; - -static const uint32 kScene2242MessageListIds1[] = { - 0x004B3CF8, 0x004B3D20 -}; - -Scene2242::Scene2242(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _isKlaymenInLight(false) { - - SetMessageHandler(&Scene2242::handleMessage); - SetUpdateHandler(&Scene2242::update); - - if (getGlobalVar(V_LIGHTS_ON)) { - setBackground(0x11840E24); - setPalette(0x11840E24); - insertScreenMouse(0x40E20110); - setRectList(0x004B3DC8); - } else { - setBackground(0x25848E24); - setPalette(0x25848E24); - addEntity(_palette); - _palette->copyBasePalette(0, 256, 0); - _palette->addPalette(0x68033B1C, 0, 65, 0); - insertScreenMouse(0x48E20250); - setRectList(0x004B3E18); - } - - _asTape = insertSprite(this, 10, 1100, 464, 435, 0x9148A011); - addCollisionSprite(_asTape); - - if (which < 0) { - // Restoring game - insertKlaymen(200, 430); - setMessageList(0x004B3C18); - } else if (which == 1) { - // Klaymen entering from looking through the window - insertKlaymen(530, 430); - setMessageList(0x004B3D60); - } else if (which == 2) { - // Klaymen returning from reading a text column - insertKlaymen(kScene2242XPositions[!getGlobalVar(V_CLICKED_COLUMN_INDEX) ? 0 : 1], 430); - setMessageList(0x004B3D48); - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) - _klaymen->setDoDeltaX(1); - } else { - // Klaymen entering from the left - insertKlaymen(0, 430); - setMessageList(0x004B3C20); - } - - _klaymen->setSoundFlag(true); - -} - -Scene2242::~Scene2242() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); -} - -void Scene2242::update() { - if (!getGlobalVar(V_LIGHTS_ON)) { - if (_isKlaymenInLight && _klaymen->getX() < 440) { - _palette->addBasePalette(0x68033B1C, 0, 65, 0); - _palette->startFadeToPalette(12); - _isKlaymenInLight = false; - } else if (!_isKlaymenInLight && _klaymen->getX() >= 440) { - _palette->addBasePalette(0x25848E24, 0, 65, 0); - _palette->startFadeToPalette(12); - _isKlaymenInLight = true; - } - } - Scene::update(); -} - -uint32 Scene2242::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x800C6694) - readClickedColumn(); - break; - case 0x4826: - if (sender == _asTape) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004B3D50); - } - break; - } - return messageResult; -} - -void Scene2242::readClickedColumn() { - int index; - if (_mouseClickPos.x < 108) { - setGlobalVar(V_COLUMN_TEXT_NAME, 0x04290188); - setGlobalVar(V_CLICKED_COLUMN_INDEX, 42); - setGlobalVar(V_COLUMN_BACK_NAME, calcHash("bgRecPanelStart1")); - index = 0; - } else { - setGlobalVar(V_COLUMN_TEXT_NAME, 0x04290188); - setGlobalVar(V_CLICKED_COLUMN_INDEX, 43); - setGlobalVar(V_COLUMN_BACK_NAME, calcHash("bgRecPanelStart2")); - index = 1; - } - setGlobalVar(V_CLICKED_COLUMN_ROW, (_mouseClickPos.y - 100) / 7); - if (ABS(_klaymen->getX() - kScene2242XPositions[index]) < 133) - setMessageList2(kScene2242MessageListIds1[index]); - else - setMessageList2(kScene2242MessageListIds2[index]); -} - -static const int16 kHallOfRecordsKlaymenXPos[] = { - 68, 157, 246, 335, - 424, 513, 602 -}; - -static const uint32 kHallOfRecordsSceneMessageListIds2[] = { - 0x004B2978, 0x004B2998, 0x004B29B8, 0x004B29D8, - 0x004B29F8, 0x004B2A18, 0x004B2A38 -}; - -static const uint32 kHallOfRecordsSceneMessageListIds1[] = { - 0x004B2A58, 0x004B2A80, 0x004B2AA8, 0x004B2AD0, - 0x004B2AF8, 0x004B2B20, 0x004B2B48 -}; - -HallOfRecordsScene::HallOfRecordsScene(NeverhoodEngine *vm, Module *parentModule, int which, uint32 hallOfRecordsInfoId) - : Scene(vm, parentModule) { - - _hallOfRecordsInfo = _vm->_staticData->getHallOfRecordsInfoItem(hallOfRecordsInfoId); - - SetMessageHandler(&HallOfRecordsScene::handleMessage); - SetUpdateHandler(&Scene::update); - - if (!getGlobalVar(V_LIGHTS_ON) && _hallOfRecordsInfo->bgFilename2) { - setRectList(0x004B2BF8); - setBackground(_hallOfRecordsInfo->bgFilename2); - setPalette(_hallOfRecordsInfo->bgFilename2); - insertScreenMouse(0x14320138); - } else { - setRectList(0x004B2BB8); - setBackground(_hallOfRecordsInfo->bgFilename1); - setPalette(_hallOfRecordsInfo->bgFilename1); - insertScreenMouse(0x63A40028); - } - - if (which < 0) { - // Restoring game - insertKlaymen(200, 430); - setMessageList(0x004B2900); - } else if (which == 1) { - // Klaymen entering from the right - insertKlaymen(640, 430); - setMessageList(0x004B2910); - } else if (which == 2) { - // Klaymen returning from reading a text column - insertKlaymen(kHallOfRecordsKlaymenXPos[getGlobalVar(V_CLICKED_COLUMN_INDEX) - _hallOfRecordsInfo->xPosIndex], 430); - setMessageList(0x004B2B70); - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) - _klaymen->setDoDeltaX(1); - } else { - // Klaymen entering from the left - insertKlaymen(0, 430); - setMessageList(0x004B2908); - } - - _klaymen->setSoundFlag(true); - _klaymen->setKlaymenIdleTable2(); - -} - -HallOfRecordsScene::~HallOfRecordsScene() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); -} - -uint32 HallOfRecordsScene::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x800C6694) - readClickedColumn(); - break; - } - return messageResult; -} - -void HallOfRecordsScene::readClickedColumn() { - int16 index = (_mouseClickPos.x - 23) / 89; - if (index >= _hallOfRecordsInfo->count) - setMessageList2(0x004B2920); - else { - setGlobalVar(V_CLICKED_COLUMN_INDEX, _hallOfRecordsInfo->xPosIndex + index); - setGlobalVar(V_CLICKED_COLUMN_ROW, (_mouseClickPos.y - 100) / 7); - setGlobalVar(V_COLUMN_TEXT_NAME, _hallOfRecordsInfo->txFilename); - if (index == 0 && _hallOfRecordsInfo->bgFilename3) - setGlobalVar(V_COLUMN_BACK_NAME, _hallOfRecordsInfo->bgFilename3); - else - setGlobalVar(V_COLUMN_BACK_NAME, 0); - if (ABS(_klaymen->getX() - kHallOfRecordsKlaymenXPos[index]) < 133) - setMessageList2(kHallOfRecordsSceneMessageListIds1[index]); - else - setMessageList2(kHallOfRecordsSceneMessageListIds2[index]); - } -} - -static const int16 kScene2247XPositions[] = { - 513, 602 -}; - -static const uint32 kScene2247MessageListIds2[] = { - 0x004B54A0, 0x004B54C0 -}; - -static const uint32 kScene2247MessageListIds1[] = { - 0x004B54E0, 0x004B5508 -}; - -Scene2247::Scene2247(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - SetMessageHandler(&Scene2247::handleMessage); - SetUpdateHandler(&Scene::update); - - if (getGlobalVar(V_LIGHTS_ON)) { - setRectList(0x004B5588); - setBackground(0x40339414); - setPalette(0x40339414); - insertScreenMouse(0x3941040B); - } else { - setRectList(0x004B55C8); - setBackground(0x071963E5); - setPalette(0x071963E5); - insertScreenMouse(0x14320138); - } - - if (which < 0) { - // Restoring game - insertKlaymen(200, 430); - setMessageList(0x004B5428); - } else if (which == 1) { - // Klaymen entering from the right - insertKlaymen(640, 430); - setMessageList(0x004B5438); - } else if (which == 2) { - // Klaymen returning from reading a text column - insertKlaymen(kScene2247XPositions[getGlobalVar(V_COLUMN_TEXT_NAME) == 0x0008E486 ? 0 : 1], 430); - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) - _klaymen->setDoDeltaX(1); - setMessageList(0x004B5530); - } else { - // Klaymen entering from the left - insertKlaymen(0, 430); - setMessageList(0x004B5430); - } - - _klaymen->setSoundFlag(true); - -} - -Scene2247::~Scene2247() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); -} - -uint32 Scene2247::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x800C6694) - readClickedColumn(); - break; - } - return messageResult; -} - -void Scene2247::readClickedColumn() { - int index; - if (_mouseClickPos.x < 553) { - setGlobalVar(V_COLUMN_TEXT_NAME, 0x0008E486); - setGlobalVar(V_COLUMN_BACK_NAME, calcHash("bgFatherHeader")); - index = 0; - } else { - setGlobalVar(V_COLUMN_TEXT_NAME, 0x03086004); - setGlobalVar(V_COLUMN_BACK_NAME, calcHash("bgQuaterHeader")); - index = 1; - } - setGlobalVar(V_CLICKED_COLUMN_INDEX, 0); - setGlobalVar(V_CLICKED_COLUMN_ROW, (_mouseClickPos.y - 100) / 7); - if (ABS(_klaymen->getX() - kScene2247XPositions[index]) < 133) - setMessageList2(kScene2247MessageListIds1[index]); - else - setMessageList2(kScene2247MessageListIds2[index]); -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module2200.h b/engines/neverhood/module2200.h deleted file mode 100644 index f198871613..0000000000 --- a/engines/neverhood/module2200.h +++ /dev/null @@ -1,375 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE2200_H -#define NEVERHOOD_MODULE2200_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/module1000.h" -#include "neverhood/graphics.h" - -namespace Neverhood { - -// Module2200 - -class Module2200 : public Module { -public: - Module2200(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module2200(); -protected: - int _sceneNum; - void createScene(int sceneNum, int which); - void updateScene(); - void createHallOfRecordsScene(int which, uint32 hallOfRecordsInfoId); -}; - -// Scene2201 - -static const NPoint kSsScene2201PuzzleCubePoints[] = { - {305, 305}, {321, 305}, {336, 305}, {305, 319}, - {321, 319}, {336, 319}, {305, 332}, {321, 332}, - {336, 333} -}; - -static const uint32 kSsScene2201PuzzleCubeFileHashes[] = { - 0x88134A44, 0xAA124340, 0xB8124602, 0xA902464C, - 0x890A4244, 0xA8124642, 0xB812C204, 0x381A4A4C -}; - -class AsScene2201CeilingFan : public AnimatedSprite { -public: - AsScene2201CeilingFan(NeverhoodEngine *vm); -}; - -class AsScene2201Door : public AnimatedSprite { -public: - AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen); -protected: - Klaymen *_klaymen; - Sprite *_ssDoorLight; - bool _isOpen; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stOpenDoor(); - void stCloseDoor(); -}; - -class SsScene2201PuzzleCube : public StaticSprite { -public: - SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex); -}; - -class Scene2201 : public Scene { -public: - Scene2201(NeverhoodEngine *vm, Module *parentModule, int which); - ~Scene2201(); -protected: - NRect _clipRects[2]; - Sprite *_ssDoorLight; - Sprite *_asDoor; - Sprite *_ssDoorButton; - Sprite *_asTape; - bool _isSoundPlaying; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsScene2202PuzzleCube : public StaticSprite { -public: - SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol); -protected: - Scene *_parentScene; - int16 _cubeSymbol; - int16 _cubePosition; - int16 _newX, _newY; - int16 _xDelta, _yDelta; - int16 _xIncr; - int16 _yIncr; - int16 _errValue; - int16 _counter; - int16 _xFlagPos; - bool _counterDirection; - bool _isMoving; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suMoveCubeX(); - void suMoveCubeY(); - void moveCube(int16 newCubePosition); - void stopMoving(); -}; - -class Scene2202 : public Scene { -public: - Scene2202(NeverhoodEngine *vm, Module *parentModule, int which); - ~Scene2202(); -protected: - Sprite *_ssMovingCube; - Sprite *_ssDoneMovingCube; - bool _isCubeMoving; - int16 _movingCubePosition; - int _surfacePriority; - bool _leaveScene; - bool _isSolved; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - int16 getFreeCubePosition(int16 index); - bool testIsSolved(); -}; - -class AsCommonKey : public AnimatedSprite { -public: - AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y); -protected: - Scene *_parentScene; - int _keyIndex; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2203Door : public AnimatedSprite { -public: - AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex); -protected: - Scene *_parentScene; - Sprite *_otherDoor; - uint _doorIndex; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void openDoor(); - void closeDoor(); -}; - -class Scene2203 : public Scene { -public: - Scene2203(NeverhoodEngine *vm, Module *parentModule, int which); - ~Scene2203(); -protected: - Sprite *_asLeftDoor; - Sprite *_asRightDoor; - Sprite *_ssSmallLeftDoor; - Sprite *_ssSmallRightDoor; - Sprite *_asTape; - Sprite *_asKey; - NRect _leftDoorClipRect; - NRect _rightDoorClipRect; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsScene2205DoorFrame : public StaticSprite { -public: - SsScene2205DoorFrame(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2205 : public Scene { -public: - Scene2205(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - SsCommonPressButton *_ssLightSwitch; - Sprite *_ssDoorFrame; - bool _isKlaymenInLight; - bool _isLightOn; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2206DoorSpikes : public StaticSprite { -public: - AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash); -protected: - int _deltaIndex; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suOpen(); - void suClose(); -}; - -class AsScene2206Platform : public StaticSprite { -public: - AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash); -protected: - int16 _yDelta; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suMoveDown(); -}; - -class SsScene2206TestTube : public StaticSprite { -public: - SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2206 : public Scene { -public: - Scene2206(NeverhoodEngine *vm, Module *parentModule, int which); - ~Scene2206(); -protected: - Sprite *_sprite1; - Sprite *_sprite2; - Sprite *_sprite3; - Sprite *_asDoorSpikes; - Sprite *_ssButton; - Sprite *_asPlatform; - Sprite *_ssTestTube; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void klaymenInFrontSpikes(); - void klaymenBehindSpikes(); - void readClickedColumn(); -}; - -class AsScene2207Elevator : public AnimatedSprite { -public: - AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene); - ~AsScene2207Elevator(); -protected: - Scene *_parentScene; - NPointArray *_pointArray; - int16 _pointIndex; - int16 _destPointIndex, _destPointIndexDelta; - bool _isMoving; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suSetPosition(); - void moveToY(int16 y); -}; - -class AsScene2207Lever : public AnimatedSprite { -public: - AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stLeverDown(); - void stLeverDownEvent(); - void stLeverUp(); - void stLeverUpEvent(); -}; - -class AsScene2207WallRobotAnimation : public AnimatedSprite { -public: - AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene); - ~AsScene2207WallRobotAnimation(); -protected: - bool _idle; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stStartAnimation(); - void stStopAnimation(); - void cbStopAnimation(); -}; - -class AsScene2207WallCannonAnimation : public AnimatedSprite { -public: - AsScene2207WallCannonAnimation(NeverhoodEngine *vm); -protected: - bool _idle; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stStartAnimation(); - void stStopAnimation(); - void cbStopAnimation(); -}; - -class SsScene2207Symbol : public StaticSprite { -public: - SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index); -}; - -class Scene2207 : public Scene { -public: - Scene2207(NeverhoodEngine *vm, Module *parentModule); -protected: - Sprite *_asElevator; - Sprite *_ssMaskPart1; - Sprite *_ssMaskPart2; - Sprite *_ssMaskPart3; - Sprite *_asTape; - Sprite *_asLever; - Sprite *_asWallRobotAnimation; - Sprite *_asWallCannonAnimation; - Sprite *_ssButton; - int _elevatorSurfacePriority; - bool _klaymenAtElevator; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 handleMessage2(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2208 : public Scene { -public: - Scene2208(NeverhoodEngine *vm, Module *parentModule, int which); - ~Scene2208(); -protected: - FontSurface *_fontSurface; - BaseSurface *_backgroundSurface; - BaseSurface *_topBackgroundSurface; - BaseSurface *_bottomBackgroundSurface; - TextResource _textResource; - int16 _backgroundScrollY; - int16 _newRowIndex; - int16 _currRowIndex; - int16 _rowScrollY; - int16 _maxRowIndex; - int16 _visibleRowsCount; - Common::Array _strings; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void drawRow(int16 rowIndex); -}; - -class Scene2242 : public Scene { -public: - Scene2242(NeverhoodEngine *vm, Module *parentModule, int which); - ~Scene2242(); -protected: - Sprite *_asTape; - bool _isKlaymenInLight; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void readClickedColumn(); -}; - -class HallOfRecordsScene : public Scene { -public: - HallOfRecordsScene(NeverhoodEngine *vm, Module *parentModule, int which, uint32 hallOfRecordsInfoId); - ~HallOfRecordsScene(); -protected: - HallOfRecordsInfo *_hallOfRecordsInfo; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void readClickedColumn(); -}; - -class Scene2247 : public Scene { -public: - Scene2247(NeverhoodEngine *vm, Module *parentModule, int which); - ~Scene2247(); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void readClickedColumn(); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE2200_H */ diff --git a/engines/neverhood/module2300.cpp b/engines/neverhood/module2300.cpp deleted file mode 100644 index bf0e866b2f..0000000000 --- a/engines/neverhood/module2300.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* 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/module2300.h" -#include "neverhood/navigationscene.h" - -namespace Neverhood { - -static const uint32 kModule2300SoundList[] = { - 0x90805C50, 0x90804450, 0xB4005E60, 0x91835066, - 0x90E14440, 0x90F0D1C3, 0 -}; - -Module2300::Module2300(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule), _soundVolume(0) { - - _vm->_soundMan->addSoundList(0x1A214010, kModule2300SoundList); - _vm->_soundMan->setSoundListParams(kModule2300SoundList, true, 50, 600, 10, 150); - - _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; - - if (_isWallBroken) { - _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); - _vm->_soundMan->playSoundLooping(0x90F0D1C3); - } else { - _vm->_soundMan->setSoundParams(0x90F0D1C3, false, 0, 0, 0, 0); - } - - _vm->_soundMan->playTwoSounds(0x1A214010, 0x48498E46, 0x50399F64, 0); - _vm->_soundMan->playTwoSounds(0x1A214010, 0x41861371, 0x43A2507F, 0); - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else if (which == 1) - createScene(2, 0); - else if (which == 2) - createScene(3, 0); - else if (which == 3) - createScene(4, -1); - else if (which == 4) - createScene(1, 3); - else - createScene(0, 1); - -} - -Module2300::~Module2300() { - _vm->_soundMan->deleteGroup(0x1A214010); -} - -void Module2300::createScene(int sceneNum, int which) { - debug("Module2300::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - createNavigationScene(0x004B67B8, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - createNavigationScene(0x004B67E8, which); - if (_isWallBroken) { - _soundVolume = 15; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, 15); - } - break; - case 2: - _vm->gameState().sceneNum = 2; - createNavigationScene(0x004B6878, which); - break; - case 3: - _vm->gameState().sceneNum = 3; - if (getGlobalVar(V_WALL_BROKEN)) - createNavigationScene(0x004B68F0, which); - else { - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); - createNavigationScene(0x004B68A8, which); - if (_isWallBroken) { - _soundVolume = 87; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, 87); - } - } - break; - case 4: - _vm->gameState().sceneNum = 4; - _vm->_soundMan->setTwoSoundsPlayFlag(true); - createSmackerScene(0x20080A0B, true, true, false); - break; - case 9999: - createDemoScene(); - break; - } - SetUpdateHandler(&Module2300::updateScene); - _childObject->handleUpdate(); -} - -void Module2300::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 1) - createScene(1, 4); - else - leaveModule(0); - break; - case 1: - if (_moduleResult == 1) - createScene(0, 0); - else if (_vm->isDemo()) - createScene(9999, 0); - else if (_moduleResult == 2) - createScene(2, 1); - else if (_moduleResult == 3) - createScene(1, 3); - else if (_moduleResult == 4) - createScene(3, 1); - else if (_moduleResult == 5) - leaveModule(3); - else - leaveModule(4); - break; - case 2: - if (_moduleResult == 1) - leaveModule(1); - else - createScene(1, 5); - break; - case 3: - if (_moduleResult == 1) - leaveModule(2); - else - createScene(1, 1); - break; - case 4: - _vm->_soundMan->setTwoSoundsPlayFlag(false); - createScene(1, 2); - break; - case 9999: - createScene(1, -1); - break; - } - } else { - switch (_sceneNum) { - case 1: - if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 4 && - navigationScene()->getFrameNumber() % 2) { - _soundVolume++; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); - } - if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 0 && - navigationScene()->getFrameNumber() == 50) { - _vm->_soundMan->playTwoSounds(0x1A214010, 0x48498E46, 0x50399F64, 0); - _vm->_soundMan->setSoundVolume(0x48498E46, 70); - _vm->_soundMan->setSoundVolume(0x50399F64, 70); - } - break; - case 3: - if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getFrameNumber() % 2) { - _soundVolume--; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); - } - break; - } - } -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module2300.h b/engines/neverhood/module2300.h deleted file mode 100644 index 64f6c6d937..0000000000 --- a/engines/neverhood/module2300.h +++ /dev/null @@ -1,48 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE2300_H -#define NEVERHOOD_MODULE2300_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" - -namespace Neverhood { - -// Module2300 - -class Module2300 : public Module { -public: - Module2300(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module2300(); -protected: - int _sceneNum; - bool _isWallBroken; - int _soundVolume; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE2300_H */ diff --git a/engines/neverhood/module2400.cpp b/engines/neverhood/module2400.cpp deleted file mode 100644 index 369132187d..0000000000 --- a/engines/neverhood/module2400.cpp +++ /dev/null @@ -1,992 +0,0 @@ -/* 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/module2400.h" - -namespace Neverhood { - -Module2400::Module2400(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - _vm->_soundMan->addMusic(0x202D1010, 0xB110382D); - - if (which < 0) - createScene(_vm->gameState().sceneNum, _vm->gameState().which); - else - createScene(0, 0); - -} - -Module2400::~Module2400() { - _vm->_soundMan->deleteMusicGroup(0x202D1010); -} - -void Module2400::createScene(int sceneNum, int which) { - debug("Module2400::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _vm->_soundMan->stopMusic(0xB110382D, 0, 0); - _childObject = new Scene2401(_vm, this, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - _vm->_soundMan->startMusic(0xB110382D, 0, 2); - _childObject = new Scene2402(_vm, this, which); - break; - case 2: - _vm->gameState().sceneNum = 2; - _vm->_soundMan->startMusic(0xB110382D, 0, 0); - _childObject = new Scene2403(_vm, this, which); - break; - case 4: - _vm->gameState().sceneNum = 4; - _vm->_soundMan->stopMusic(0xB110382D, 0, 2); - _childObject = new DiskplayerScene(_vm, this, 0); - break; - case 5: - _vm->gameState().sceneNum = 5; - _vm->_soundMan->startMusic(0xB110382D, 0, 2); - _childObject = new Scene2406(_vm, this, which); - break; - case 6: - _vm->gameState().sceneNum = 6; - _vm->_soundMan->stopMusic(0xB110382D, 0, 2); - createSmackerScene(0x20D80001, true, true, false); - break; - case 7: - _vm->gameState().sceneNum = 7; - createStaticScene(0x81523218, 0x2321C81D); - break; - case 8: - _vm->gameState().sceneNum = 8; - createStaticScene(0x08100210, 0x00214089); - break; - case 9: - _vm->gameState().sceneNum = 9; - createStaticScene(0x8C020505, 0x205018C8); - break; - } - SetUpdateHandler(&Module2400::updateScene); - _childObject->handleUpdate(); -} - -void Module2400::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 1) - createScene(1, 0); - else - leaveModule(0); - break; - case 1: - if (_moduleResult == 1) - createScene(5, 0); - else if (_moduleResult == 2) - createScene(7, -1); - else - createScene(0, 1); - break; - case 2: - if (_moduleResult == 1) - createScene(9, -1); - else if (_moduleResult == 2) - createScene(6, -1); - else - createScene(5, 1); - break; - case 4: - createScene(5, 2); - break; - case 5: - if (_moduleResult == 1) - createScene(2, 0); - else if (_moduleResult == 2) - createScene(4, 0); - else if (_moduleResult == 3) - createScene(8, -1); - else - createScene(1, 1); - break; - case 6: - createScene(2, 2); - break; - case 7: - createScene(1, 2); - break; - case 8: - createScene(5, 3); - break; - case 9: - createScene(2, 1); - break; - } - } -} - -static const NPoint kScene2401Points[] = { - {384, 389}, {406, 389}, {429, 389}, - {453, 389}, {477, 389} -}; - -static const uint32 kScene2401FileHashes1[] = { - 0x02842920, 0x02882920, 0x02902920, - 0x02A02920, 0x02C02920, 0x02002920, - 0x03802920, 0x00802920, 0x06802920, - 0x03842920 -}; - -static const uint32 kScene2401FileHashes2[] = { - 0xD0910020, 0xD0910038, 0xD0910008, - 0xD0910068, 0xD09100A8, 0 -}; - -static const uint32 kScene2401FileHashes3[] = { - 0xD0910020, 0xD0910038, 0xD0910008, - 0xD0910068, 0xD09100A8, 0 -}; - -static const NRect kScene2401Rects[] = { - NRect(369, 331, 394, 389), - NRect(395, 331, 419, 389), - NRect(420, 331, 441, 389), - NRect(442, 331, 464, 389), - NRect(465, 331, 491, 389) -}; - -static const uint32 kAsScene2401WaterSpitFileHashes2[] = { - 0x5C044690, 0x5C644690, 0x5CA44690, - 0x5D244690, 0x5E244690 -}; - -static const uint32 kAsScene2401WaterSpitFileHashes1[] = { - 0xF4418408, 0xF4418808, 0xF4419008, - 0xF441A008, 0xCD4F8411 -}; - -AsScene2401WaterSpit::AsScene2401WaterSpit(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1200) { - - _x = 240; - _y = 447; - createSurface(100, 146, 74); - setVisible(false); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2401WaterSpit::handleMessage); - SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); -} - -uint32 AsScene2401WaterSpit::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x120A0013) - playSound(0, kAsScene2401WaterSpitFileHashes1[_soundIndex]); - break; - case 0x2000: - _x = 240; - _y = 447; - _soundIndex = getSubVar(VA_CURR_WATER_PIPES_LEVEL, param.asInteger()); - startAnimation(kAsScene2401WaterSpitFileHashes2[param.asInteger()], 0, -1); - setVisible(true); - playSound(0, 0x48640244); - break; - case 0x3002: - stopAnimation(); - setVisible(false); - break; - } - return messageResult; -} - -AsScene2401FlowingWater::AsScene2401FlowingWater(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1200), _isWaterFlowing(false) { - - _x = 88; - _y = 421; - createSurface1(0x10203116, 100); - setVisible(false); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2401FlowingWater::handleMessage); -} - -AsScene2401FlowingWater::~AsScene2401FlowingWater() { - _vm->_soundMan->deleteSoundGroup(0x40F11C09); -} - -uint32 AsScene2401FlowingWater::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (_isWaterFlowing && param.asInteger() == 0x02421405) - startAnimationByHash(0x10203116, 0x01084280, 0); - break; - case 0x2002: - if (!_isWaterFlowing) { - _vm->_soundMan->addSound(0x40F11C09, 0x980C1420); - _vm->_soundMan->playSoundLooping(0x980C1420); - startAnimation(0x10203116, 0, -1); - setVisible(true); - _isWaterFlowing = true; - } - break; - case 0x2003: - _vm->_soundMan->deleteSound(0x980C1420); - _isWaterFlowing = false; - break; - case 0x3002: - stopAnimation(); - setVisible(false); - break; - } - return messageResult; -} - -AsScene2401WaterFlushing::AsScene2401WaterFlushing(NeverhoodEngine *vm, int16 x, int16 y) - : AnimatedSprite(vm, 1200), _countdown(0), _flushLoopCount(0) { - - _x = x; - _y = y; - createSurface1(0xB8596884, 100); - setVisible(false); - SetUpdateHandler(&AsScene2401WaterFlushing::update); - SetMessageHandler(&AsScene2401WaterFlushing::handleMessage); -} - -void AsScene2401WaterFlushing::update() { - if (_countdown != 0 && (--_countdown) == 0) { - setDoDeltaX(_vm->_rnd->getRandomNumber(1)); - startAnimation(0xB8596884, 0, -1); - setVisible(true); - } - AnimatedSprite::update(); -} - -uint32 AsScene2401WaterFlushing::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (_flushLoopCount > 0 && param.asInteger() == 0x02421405) { - startAnimationByHash(0xB8596884, 0x01084280, 0); - _flushLoopCount--; - } - break; - case 0x2002: - if (param.asInteger() > 0) { - _flushLoopCount = param.asInteger() - 1; - _countdown = _vm->_rnd->getRandomNumber(3) + 1; - } - break; - case 0x3002: - stopAnimation(); - setVisible(false); - break; - } - return messageResult; -} - -AsScene2401Door::AsScene2401Door(NeverhoodEngine *vm, bool isOpen) - : AnimatedSprite(vm, 1100), _countdown(0), _isOpen(isOpen) { - - _x = 320; - _y = 240; - createSurface1(0x44687810, 100); - _newStickFrameIndex = STICK_LAST_FRAME; - if (_isOpen) { - stopAnimation(); - setVisible(false); - _countdown = 48; - } else { - startAnimation(0x44687810, 0, -1); - _newStickFrameIndex = 0; - } - SetUpdateHandler(&AsScene2401Door::update); - SetMessageHandler(&AsScene2401Door::handleMessage); -} - -void AsScene2401Door::update() { - if (_isOpen && _countdown != 0 && (--_countdown) == 0) { - _isOpen = false; - setVisible(true); - startAnimation(0x44687810, -1, -1); - _newStickFrameIndex = 0; - _playBackwards = true; - playSound(0, calcHash("fxDoorClose38")); - } - AnimatedSprite::update(); -} - -uint32 AsScene2401Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2004: - if (_isOpen) - _countdown = 168; - messageResult = _isOpen ? 1 : 0; - break; - case 0x3002: - gotoNextState(); - break; - case 0x4808: - if (!_isOpen) { - _countdown = 168; - _isOpen = true; - setVisible(true); - startAnimation(0x44687810, 0, -1); - playSound(0, calcHash("fxDoorOpen38")); - NextState(&AsScene2401Door::stDoorOpenFinished); - } - break; - } - return messageResult; -} - -void AsScene2401Door::stDoorOpenFinished() { - stopAnimation(); - setVisible(false); -} - -Scene2401::Scene2401(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _countdown1(0), _countdown2(0), _unkFlag(false), - _soundToggle(false), _asWaterSpitIndex(0) { - - _vm->gameModule()->initWaterPipesPuzzle(); - - SetMessageHandler(&Scene2401::handleMessage); - SetUpdateHandler(&Scene2401::update); - - setRectList(0x004B3140); - setBackground(0x8C030206); - setPalette(0x8C030206); - addEntity(_palette); - _palette->addBasePalette(0x8C030206, 0, 256, 0); - _palette->addPalette(0x91D3A391, 0, 65, 0); - insertScreenMouse(0x302028C8); - - _sprite1 = insertStaticSprite(0x2E068A23, 200); - insertStaticSprite(0x401410A6, 200); - _asFlowingWater = insertSprite(); - insertStaticSprite(0x90C0A4B4, 200); - _ssButton = insertSprite(this, 0x0092916A, 100, 0); - _ssFloorButton = insertSprite(this, 0x28001120, 0x00911068, 100, 0); - - for (uint i = 0; i < 5; i++) - _asWaterFlushing[i] = insertSprite(kScene2401Points[i].x, kScene2401Points[i].y); - - for (uint i = 0; i < 10; i++) { - _ssWaterPipes[i] = insertStaticSprite(kScene2401FileHashes1[i], 300); - _ssWaterPipes[i]->setVisible(false); - } - - _asWaterSpit[0] = insertSprite(); - _asWaterSpit[1] = insertSprite(); - - if (which < 0) { - // Restoring game - insertKlaymen(200, 447); - setMessageList(0x004B2F70); - _asDoor = insertSprite(false); - } else if (which == 1) { - // Klaymen entering from the back - insertKlaymen(280, 413); - setMessageList(0x004B2F80); - _palette->addBasePalette(0xB103B604, 0, 65, 0); - _palette->addPalette(0xB103B604, 0, 65, 0); - _asDoor = insertSprite(true); - } else { - // Klaymen entering from the left - insertKlaymen(-20, 447); - setMessageList(0x004B2F78); - _asDoor = insertSprite(false); - } - -} - -void Scene2401::update() { - - if (_countdown1 != 0 && (--_countdown1) == 0) { - if (_pipeStatus > 0 && _pipeStatus <= 10) - _ssWaterPipes[_pipeStatus - 1]->setVisible(false); - if (_pipeStatus >= 10) { - bool puzzleSolved = true, waterInside = false; - for (uint pipeIndex = 0; pipeIndex < 5; pipeIndex++) { - if (getSubVar(VA_CURR_WATER_PIPES_LEVEL, pipeIndex) != getSubVar(VA_GOOD_WATER_PIPES_LEVEL, pipeIndex)) - puzzleSolved = false; - if (getSubVar(VA_CURR_WATER_PIPES_LEVEL, pipeIndex) != 0) - waterInside = true; - } - if (puzzleSolved) { - setGlobalVar(V_NOTES_DOOR_UNLOCKED, 1); - setGlobalVar(V_NOTES_PUZZLE_SOLVED, 1); - sendMessage(_asDoor, 0x4808, 0); - } else if (waterInside) { - playPipeSound(0xD0431020); - for (uint i = 0; i < 5; i++) { - sendMessage(_asWaterFlushing[i], 0x2002, getSubVar(VA_CURR_WATER_PIPES_LEVEL, i)); - setSubVar(VA_CURR_WATER_PIPES_LEVEL, i, 0); - } - } - } else if (_pipeStatus >= 5) { - _ssWaterPipes[_pipeStatus]->setVisible(true); - _countdown1 = 8; - playPipeSound(kScene2401FileHashes3[getSubVar(VA_CURR_WATER_PIPES_LEVEL, _pipeStatus - 5)]); - } else { - _ssWaterPipes[_pipeStatus]->setVisible(true); - _countdown1 = _pipeStatus == 4 ? 16 : 8; - playPipeSound(kScene2401FileHashes3[getSubVar(VA_GOOD_WATER_PIPES_LEVEL, _pipeStatus)]); - } - _pipeStatus++; - } - - if (_countdown2 != 0 && (--_countdown2) == 0) - sendMessage(_asFlowingWater, 0x2003, 0); - - Scene::update(); - -} - -uint32 Scene2401::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x402064D8) - sendEntityMessage(_klaymen, 0x1014, _ssButton); - else if (param.asInteger() == 0x02144CB1) - sendEntityMessage(_klaymen, 0x1014, _ssFloorButton); - else if (param.asInteger() == 0x11C40840) { - if (getGlobalVar(V_NOTES_DOOR_UNLOCKED) && sendMessage(_asDoor, 0x2004, 0)) - setMessageList(0x004B3090); - else - setMessageList(0x004B30B0); - } else if (param.asInteger() == 0x412722C0) { - if (_countdown2 > 0 && getGlobalVar(V_HAS_TEST_TUBE)) { - _countdown2 = 144; - setMessageList(0x004B3020); - } else - setMessageList(0x004B3050); - } else if (param.asInteger() == 0x21142050) { - if (_unkFlag && _countdown1 == 0 && !getGlobalVar(V_NOTES_PUZZLE_SOLVED)) - setMessageList(0x004B2FA8); - else - setMessageList(0x004B2FC8); - } else if (param.asInteger() == 0x87441031) - setSurfacePriority(_sprite1->getSurface(), 1100); - else if (param.asInteger() == 0x80C40322) { - setSurfacePriority(_sprite1->getSurface(), 200); - cancelMessageList(); - _unkFlag = true; - } else if (param.asInteger() == 0x09C4B40A && _countdown2 > 12) - _countdown2 = 12; - break; - case 0x2000: - messageResult = 0; - for (uint32 i = 0; i < 5; i++) - if (kScene2401Rects[i].contains(_mouseClickPos.x, _mouseClickPos.y)) { - messageResult = i; - break; - } - break; - case 0x2001: - sendMessage(_asWaterSpit[_asWaterSpitIndex], 0x2000, param.asInteger()); - _asWaterSpitIndex = (_asWaterSpitIndex + 1) & 1; - incSubVar(VA_CURR_WATER_PIPES_LEVEL, param.asInteger(), 1); - if (getSubVar(VA_CURR_WATER_PIPES_LEVEL, param.asInteger()) >= 5) - setSubVar(VA_CURR_WATER_PIPES_LEVEL, param.asInteger(), 4); - break; - case 0x480B: - if (sender == _ssButton) { - _pipeStatus = 0; - _countdown1 = 8; - } else if (sender == _ssFloorButton && getGlobalVar(V_WATER_RUNNING)) { - _countdown2 = 144; - sendMessage(_asFlowingWater, 0x2002, 0); - playSound(0, 0xE1130324); - } - break; - case 0x482A: - _palette->addBasePalette(0xB103B604, 0, 65, 0); - _palette->startFadeToPalette(12); - break; - case 0x482B: - _palette->addBasePalette(0x91D3A391, 0, 65, 0); - _palette->startFadeToPalette(12); - break; - } - return messageResult; -} - -void Scene2401::playPipeSound(uint32 fileHash) { - playSound(_soundToggle ? 0 : 1, fileHash); - _soundToggle = !_soundToggle; -} - -static const uint32 kScene2402FileHashes[] = { - 0xD0910020, 0xD0910038, 0xD0910008, - 0xD0910068, 0xD09100A8 -}; - -AsScene2402Door::AsScene2402Door(NeverhoodEngine *vm, Scene *parentScene, bool isOpen) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _isOpen(isOpen), _countdown(0) { - - _x = 320; - _y = 240; - createSurface1(0x80495831, 100); - if (_isOpen) { - startAnimation(0x80495831, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - _countdown = 48; - } else { - stopAnimation(); - setVisible(false); - } - SetUpdateHandler(&AsScene2402Door::update); - SetMessageHandler(&AsScene2402Door::handleMessage); -} - -void AsScene2402Door::update() { - if (_isOpen && _countdown != 0 && (--_countdown) == 0) { - _isOpen = false; - setVisible(true); - startAnimation(0x80495831, -1, -1); - _playBackwards = true; - playSound(0, calcHash("fxDoorClose38")); - NextState(&AsScene2402Door::stDoorClosingFinished); - } - AnimatedSprite::update(); -} - -uint32 AsScene2402Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - if (_isOpen) - _countdown = 144; - messageResult = _isOpen ? 1 : 0; - break; - case 0x3002: - gotoNextState(); - break; - case 0x4808: - _countdown = 144; - _isOpen = true; - setVisible(true); - startAnimation(0x80495831, 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - playSound(0, calcHash("fxDoorOpen38")); - break; - } - return messageResult; -} - -void AsScene2402Door::stDoorClosingFinished() { - sendMessage(_parentScene, 0x2001, 0); - setVisible(false); -} - -AsScene2402TV::AsScene2402TV(NeverhoodEngine *vm, Klaymen *klaymen) - : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown1(0), _countdown2(0) { - - _x = 260; - _y = 210; - createSurface(100, 127, 90); - setDoDeltaX(1); - SetMessageHandler(&Sprite::handleMessage); - if (!getGlobalVar(V_TV_JOKE_TOLD)) { - loadSound(0, 0x58208810); - _countdown1 = 48; - startAnimation(0x4919397A, 0, -1); - _newStickFrameIndex = 0; - SetUpdateHandler(&AsScene2402TV::upWait); - } else { - int16 frameIndex; - if (_klaymen->getX() > 320) - _currFrameIndex = 29; - frameIndex = CLIP((_klaymen->getX() - _x + 150) / 10, 0, 29); - startAnimation(0x050A0103, frameIndex, -1); - _newStickFrameIndex = frameIndex; - _countdown1 = 0; - SetUpdateHandler(&AsScene2402TV::upFocusKlaymen); - } -} - -AsScene2402TV::~AsScene2402TV() { - _vm->_soundMan->deleteSoundGroup(0x01520123); -} - -void AsScene2402TV::upWait() { - if (_countdown1 != 0 && (--_countdown1) == 0) { - startAnimation(0x4919397A, 0, -1); - SetMessageHandler(&AsScene2402TV::hmJoke); - NextState(&AsScene2402TV::stJokeFinished); - } - AnimatedSprite::update(); -} - -void AsScene2402TV::upFocusKlaymen() { - int16 frameIndex = CLIP((_klaymen->getX() - _x + 150) / 10, 0, 29); - if (frameIndex != _currFrameIndex) { - if (frameIndex > _currFrameIndex) - _currFrameIndex++; - else if (frameIndex < _currFrameIndex) - _currFrameIndex--; - startAnimation(0x050A0103, _currFrameIndex, -1); - _newStickFrameIndex = _currFrameIndex; - if (_countdown2 == 0) { - _vm->_soundMan->addSound(0x01520123, 0xC42D4528); - _vm->_soundMan->playSoundLooping(0xC42D4528); - } - _countdown2 = 5; - } else if (_countdown2 != 0 && (--_countdown2 == 0)) - _vm->_soundMan->deleteSound(0xC42D4528); - AnimatedSprite::update(); -} - -void AsScene2402TV::stJokeFinished() { - setGlobalVar(V_TV_JOKE_TOLD, 1); - startAnimation(0x050A0103, 0, -1); - _newStickFrameIndex = 0; - SetUpdateHandler(&AsScene2402TV::upFocusKlaymen); -} - -uint32 AsScene2402TV::hmJoke(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x431EA0B0) - playSound(0); - break; - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -Scene2402::Scene2402(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _countdown(0), _soundToggle(false) { - - Sprite *tempSprite; - - SetMessageHandler(&Scene2402::handleMessage); - SetUpdateHandler(&Scene2402::update); - - setRectList(0x004AF900); - setBackground(0x81660220); - setPalette(0x81660220); - insertScreenMouse(0x6022481E); - _asTape = insertSprite(this, 9, 1100, 286, 409, 0x9148A011); - addCollisionSprite(_asTape); - _ssButton = insertSprite(this, 0x15288120, 100, 0); - - if (which < 0) { - // Restoring game - insertKlaymen(198, 404); - setMessageList(0x004AF7C8); - } else if (which == 1) { - // Klaymen entering from the right - insertKlaymen(660, 404); - setMessageList(0x004AF7D8); - } else if (which == 2) { - // Klaymen returning from looking through the window - insertKlaymen(409, 404); - _klaymen->setDoDeltaX(getGlobalVar(V_KLAYMEN_IS_DELTA_X) ? 1 : 0); - setMessageList(0x004AF888); - } else { - // Klaymen entering from the left - insertKlaymen(0, 404); - setMessageList(0x004AF7D0); - } - - tempSprite = insertStaticSprite(0x081A60A8, 1100); - _ssDoorFrame = (StaticSprite*)insertStaticSprite(0x406C0AE0, 1100); - _klaymen->setClipRect(_ssDoorFrame->getDrawRect().x, 0, 639, tempSprite->getDrawRect().y2()); - _asDoor = insertSprite(this, which == 0); - insertSprite(_klaymen); - insertStaticSprite(0x3A01A020, 200); - -} - -Scene2402::~Scene2402() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); -} - -void Scene2402::update() { - if (_countdown != 0 && (--_countdown) == 0) { - if (_pipeStatus >= 10) { - sendMessage(_asDoor, 0x4808, 0); - _ssDoorFrame->loadSprite(0x00B415E0, kSLFDefDrawOffset | kSLFDefPosition); - } else if (_pipeStatus >= 5) { - _countdown = 8; - playPipeSound(kScene2402FileHashes[getSubVar(VA_CURR_WATER_PIPES_LEVEL, _pipeStatus - 5)]); - } else { - _countdown = _pipeStatus == 4 ? 16 : 8; - playPipeSound(kScene2402FileHashes[getSubVar(VA_GOOD_WATER_PIPES_LEVEL, _pipeStatus)]); - } - _pipeStatus++; - } - Scene::update(); -} - -uint32 Scene2402::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x402064D8) - sendEntityMessage(_klaymen, 0x1014, _ssButton); - else if (param.asInteger() == 0x01C66840) { - if (sendMessage(_asDoor, 0x2000, 0)) - setMessageList(0x004AF800); - else - setMessageList(0x004AF818); - } - break; - case 0x2001: - _ssDoorFrame->loadSprite(0x406C0AE0, kSLFDefDrawOffset | kSLFDefPosition); - break; - case 0x480B: - if (sender == _ssButton) { - _pipeStatus = 0; - _countdown = 8; - } - break; - case 0x4826: - if (sender == _asTape) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004AF890); - } - break; - } - return messageResult; -} - -void Scene2402::playPipeSound(uint32 fileHash) { - playSound(_soundToggle ? 0 : 1, fileHash); - _soundToggle = !_soundToggle; -} - -Scene2403::Scene2403(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - Sprite *tempSprite1, *tempSprite2, *tempSprite3; - - SetMessageHandler(&Scene2403::handleMessage); - setBackground(0x0C05060C); - setPalette(0x0C05060C); - _palette->addPalette(0x414364B0, 0, 65, 0); - insertScreenMouse(0x506080C8); - _asTape = insertSprite(this, 2, 1100, 480, 454, 0x9148A011); - addCollisionSprite(_asTape); - _asLightCord = insertSprite(this, 0xA1095A10, 0x836D3813, 368, 200); - _asLightCord->setClipRect(0, 25, 640, 480); - - if (which < 0) { - // Restoring game - _isClimbingLadder = false; - insertKlaymen(220, 449); - setMessageList(0x004B5C98); - setRectList(0x004B5E18); - } else if (which == 1) { - // Klaymen returning from looking through the window - _isClimbingLadder = false; - insertKlaymen(433, 449); - setMessageList(0x004B5D70); - setRectList(0x004B5E18); - } else if (which == 2) { - // Klaymen standing around after the critter video - _isClimbingLadder = false; - insertKlaymen(440, 449); - _klaymen->setDoDeltaX(1); - setMessageList(0x004B5C98); - setRectList(0x004B5E18); - } else { - // Klaymen coming up from ladder - _isClimbingLadder = true; - insertKlaymen(122, 599); - setMessageList(0x004B5CA0); - setRectList(0x004B5E28); - } - - _ssButton = insertSprite(this, 0x3130B0EB, 100, 0); - tempSprite1 = insertStaticSprite(0x20C24220, 1100); - tempSprite2 = insertStaticSprite(0x03080900, 1300); - tempSprite3 = insertSprite(_klaymen); - tempSprite3->setClipRect(tempSprite1->getDrawRect().x, 0, 640, tempSprite2->getDrawRect().y2()); - _klaymen->setClipRect(tempSprite1->getDrawRect().x, 0, 640, tempSprite2->getDrawRect().y2()); - loadSound(1, calcHash("fxFogHornSoft")); -} - -uint32 Scene2403::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x040424D0) - sendEntityMessage(_klaymen, 0x1014, _ssButton); - else if (param.asInteger() == 0x180CE614) - sendEntityMessage(_klaymen, 0x1014, _asLightCord); - break; - case 0x2000: - _isClimbingLadder = true; - setRectList(0x004B5E28); - break; - case 0x2001: - _isClimbingLadder = false; - setRectList(0x004B5E18); - break; - case 0x480B: - if (sender == _ssButton) { - if (getSubVar(VA_LOCKS_DISABLED, 0x304008D2)) { - setSubVar(VA_LOCKS_DISABLED, 0x304008D2, 0); - playSound(0, calcHash("fx3LocksDisable")); - } else { - setSubVar(VA_LOCKS_DISABLED, 0x304008D2, 1); - playSound(1); - } - } - break; - case 0x480F: - if (sender == _asLightCord) - leaveScene(2); - break; - case 0x4826: - if (sender == _asTape && !_isClimbingLadder) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004B5D98); - } - break; - } - return messageResult; -} - -Scene2406::Scene2406(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - Sprite *tempSprite1, *tempSprite2; - - if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) - setGlobalVar(V_KEY3_LOCATION, 2); - - SetMessageHandler(&Scene2406::handleMessage); - - setRectList(0x004B78C8); - insertScreenMouse(0xB03001A8); - - if (getGlobalVar(V_KEY3_LOCATION) == 2) { - _asKey = insertSprite(this, 2, 1100, 560, 409); - addCollisionSprite(_asKey); - } - - _asTape = insertSprite(this, 5, 1100, 456, 409, 0x9148A011); - addCollisionSprite(_asTape); - tempSprite2 = insertStaticSprite(0x19625293, 1100); - _clipRects[0].x1 = 0; - _clipRects[0].y1 = 0; - _clipRects[0].x2 = tempSprite2->getDrawRect().x2(); - _clipRects[0].y2 = 480; - - if (getGlobalVar(V_SPIKES_RETRACTED)) { - setBackground(0x1A0B0304); - setPalette(0x1A0B0304); - tempSprite1 = insertStaticSprite(0x32923922, 1100); - } else { - setBackground(0x0A038595); - setPalette(0x0A038595); - tempSprite1 = insertStaticSprite(0x1712112A, 1100); - } - - tempSprite2 = insertStaticSprite(0x22300924, 1300); - _clipRects[1].x1 = tempSprite1->getDrawRect().x; - _clipRects[1].y1 = tempSprite2->getDrawRect().y; - _clipRects[1].x2 = 640; - _clipRects[1].y2 = 480; - - if (which < 0) { - // Restoring game - _isClimbingLadder = false; - insertKlaymen(307, 404, _clipRects, 2); - setMessageList(0x004B76C8); - setRectList(0x004B78C8); - } else if (which == 1) { - // Klaymen coming down the ladder - _isClimbingLadder = true; - insertKlaymen(253, -16, _clipRects, 2); - setMessageList(0x004B76D8); - setRectList(0x004B78D8); - } else if (which == 2) { - // Klaymen returning from the diskplayer - _isClimbingLadder = false; - insertKlaymen(480, 404, _clipRects, 2); - setMessageList(0x004B77C0); - setRectList(0x004B78C8); - } else if (which == 3) { - // Klaymen returning from looking through the window - _isClimbingLadder = false; - insertKlaymen(387, 404, _clipRects, 2); - setMessageList(0x004B7810); - setRectList(0x004B78C8); - } else { - // Klaymen entering from the left - _isClimbingLadder = false; - insertKlaymen(0, 404, _clipRects, 2); - setMessageList(0x004B76D0); - setRectList(0x004B78C8); - } - - tempSprite2 = insertSprite(_klaymen); - tempSprite2->setClipRect(_clipRects[1]); - -} - -uint32 Scene2406::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x41062804) { - if (getGlobalVar(V_SPIKES_RETRACTED)) - setMessageList(0x004B7758); - else - setMessageList(0x004B7738); - } - break; - case 0x2000: - _isClimbingLadder = true; - setRectList(0x004B78D8); - break; - case 0x2001: - _isClimbingLadder = false; - setRectList(0x004B78C8); - break; - case 0x4826: - if (sender == _asTape && !_isClimbingLadder) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004B77C8); - } else if (sender == _asKey && !_isClimbingLadder) { - sendEntityMessage(_klaymen, 0x1014, _asKey); - setMessageList(0x004B77D8); - } - break; - } - return messageResult; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module2400.h b/engines/neverhood/module2400.h deleted file mode 100644 index 38664658ce..0000000000 --- a/engines/neverhood/module2400.h +++ /dev/null @@ -1,182 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE2400_H -#define NEVERHOOD_MODULE2400_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/gamemodule.h" -#include "neverhood/module1000.h" -#include "neverhood/module1100.h" -#include "neverhood/module1200.h" -#include "neverhood/module2100.h" -#include "neverhood/module2200.h" -#include "neverhood/module2800.h" -#include "neverhood/diskplayerscene.h" - -namespace Neverhood { - -// Module2400 - -class Module2400 : public Module { -public: - Module2400(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module2400(); -protected: - int _sceneNum; - void createScene(int sceneNum, int which); - void updateScene(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2401WaterSpit : public AnimatedSprite { -public: - AsScene2401WaterSpit(NeverhoodEngine *vm); -protected: - int _soundIndex; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2401FlowingWater : public AnimatedSprite { -public: - AsScene2401FlowingWater(NeverhoodEngine *vm); - virtual ~AsScene2401FlowingWater(); -protected: - bool _isWaterFlowing; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2401WaterFlushing : public AnimatedSprite { -public: - AsScene2401WaterFlushing(NeverhoodEngine *vm, int16 x, int16 y); -protected: - int _countdown; - int _flushLoopCount; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2401Door : public AnimatedSprite { -public: - AsScene2401Door(NeverhoodEngine *vm, bool isOpen); -protected: - int _countdown; - bool _isOpen; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stDoorOpenFinished(); -}; - -class Scene2401 : public Scene { -public: - Scene2401(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_sprite1; - Sprite *_asFlowingWater; - Sprite *_ssButton; - Sprite *_ssFloorButton; - Sprite *_asWaterSpit[2]; - Sprite *_ssWaterPipes[10]; - Sprite *_asWaterFlushing[5]; - Sprite *_asDoor; - bool _soundToggle; - bool _unkFlag; - int _countdown1; - int _countdown2; - int _pipeStatus; - int _asWaterSpitIndex; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void playPipeSound(uint32 fileHash); -}; - -class AsScene2402Door : public AnimatedSprite { -public: - AsScene2402Door(NeverhoodEngine *vm, Scene *parentScene, bool isOpen); -protected: - Scene *_parentScene; - int _countdown; - bool _isOpen; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stDoorClosingFinished(); -}; - -class AsScene2402TV : public AnimatedSprite { -public: - AsScene2402TV(NeverhoodEngine *vm, Klaymen *klaymen); - virtual ~AsScene2402TV(); -protected: - Klaymen *_klaymen; - int _countdown1; - int _countdown2; - void upWait(); - void upFocusKlaymen(); - void stJokeFinished(); - uint32 hmJoke(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2402 : public Scene { -public: - Scene2402(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Scene2402(); -protected: - Sprite *_asDoor; - Sprite *_ssButton; - Sprite *_asTape; - StaticSprite *_ssDoorFrame; - int _pipeStatus; - int _countdown; - bool _soundToggle; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void playPipeSound(uint32 fileHash); -}; - -class Scene2403 : public Scene { -public: - Scene2403(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_ssButton; - Sprite *_asTape; - Sprite *_asKey; - Sprite *_asLightCord; - bool _isClimbingLadder; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2406 : public Scene { -public: - Scene2406(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_asTape; - Sprite *_asKey; - NRect _clipRects[2]; - bool _isClimbingLadder; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE2400_H */ diff --git a/engines/neverhood/module2500.cpp b/engines/neverhood/module2500.cpp deleted file mode 100644 index 1623e4ca90..0000000000 --- a/engines/neverhood/module2500.cpp +++ /dev/null @@ -1,546 +0,0 @@ -/* 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/module2500.h" -#include "neverhood/module1600.h" - -namespace Neverhood { - -static const uint32 kScene2505StaticSprites[] = { - 0x4000A226, 0 -}; - -static const NRect kScene2505ClipRect = NRect(0, 0, 564, 480); - -static const uint32 kScene2506StaticSprites[] = { - 0x4027AF02, 0 -}; - -static const NRect kScene2506ClipRect = NRect(0, 0, 640, 441); - -static const uint32 kScene2508StaticSprites1[] = { - 0x2F08E610, 0xD844E6A0, 0 -}; - -static const NRect kScene2508ClipRect1 = NRect(0, 0, 594, 448); - -static const uint32 kScene2508StaticSprites2[] = { - 0x2F08E610, 0 -}; - -static const NRect kScene2508ClipRect2 = NRect(0, 0, 594, 448); - -Module2500::Module2500(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule), _soundIndex(0) { - - _vm->_soundMan->addMusic(0x29220120, 0x05343184); - _vm->_soundMan->startMusic(0x05343184, 0, 0); - SetMessageHandler(&Module2500::handleMessage); - - if (which < 0) - createScene(_vm->gameState().sceneNum, _vm->gameState().which); - else - createScene(0, 0); - - loadSound(0, 0x00880CCC); - loadSound(1, 0x00880CC0); - loadSound(2, 0x00880CCC); - loadSound(3, 0x00880CC0); - -} - -Module2500::~Module2500() { - _vm->_soundMan->deleteMusicGroup(0x29220120); -} - -void Module2500::createScene(int sceneNum, int which) { - debug("Module2500::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _childObject = new Scene2501(_vm, this, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - _vm->gameState().which = which; - createScene2704(which, 0x004B01B8, 220); - break; - case 2: - _vm->gameState().sceneNum = 2; - _vm->gameState().which = which; - if (getGlobalVar(V_WORLDS_JOINED)) - createScene2704(which, 0x004B01E0, 150); - else - createScene2704(which, 0x004B0208, 150); - break; - case 3: - _vm->gameState().sceneNum = 3; - _childObject = new Scene2504(_vm, this, which); - break; - case 4: - _vm->gameState().sceneNum = 4; - _vm->gameState().which = which; - createScene2704(which, 0x004B0230, 150, kScene2505StaticSprites, &kScene2505ClipRect); - break; - case 5: - setGlobalVar(V_CAR_DELTA_X, 1); - _vm->gameState().sceneNum = 5; - _vm->gameState().which = which; - createScene2704(which, 0x004B0268, 150, kScene2506StaticSprites, &kScene2506ClipRect); - break; - case 6: - _vm->gameState().sceneNum = 6; - _vm->gameState().which = which; - createScene2704(which, 0x004B02A0, 150); - break; - case 7: - _vm->gameState().sceneNum = 7; - _vm->gameState().which = which; - if (getGlobalVar(V_ENTRANCE_OPEN)) - createScene2704(which, 0x004B02C8, 150, kScene2508StaticSprites1, &kScene2508ClipRect1); - else - createScene2704(which, 0x004B02C8, 150, kScene2508StaticSprites2, &kScene2508ClipRect2); - break; - case 8: - _vm->gameState().sceneNum = 8; - _childObject = new Scene1608(_vm, this, which); - break; - case 9: - _vm->gameState().sceneNum = 9; - if (getGlobalVar(V_ENTRANCE_OPEN)) - createStaticScene(0xC62A0645, 0xA0641C6A); - else - createStaticScene(0x7A343546, 0x435427AB); - break; - } - SetUpdateHandler(&Module2500::updateScene); - _childObject->handleUpdate(); -} - -void Module2500::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 1) - createScene(2, 0); - else if (_moduleResult == 2) - createScene(1, 0); - else - leaveModule(0); - break; - case 1: - if (_moduleResult == 1) - createScene(3, -1); - else - createScene(0, 2); - break; - case 2: - if (_moduleResult == 1) - createScene(4, 0); - else - createScene(0, 1); - break; - case 3: - createScene(1, 1); - break; - case 4: - if (_moduleResult == 1) - createScene(5, 0); - else - createScene(2, 1); - break; - case 5: - if (_moduleResult == 1) - createScene(6, 0); - else - createScene(4, 1); - break; - case 6: - if (_moduleResult == 1) - createScene(7, 0); - else - createScene(5, 1); - break; - case 7: - if (_moduleResult == 1) - createScene(8, 1); - else - createScene(6, 1); - break; - case 8: - if (_moduleResult == 2) - createScene(9, -1); - else - createScene(7, 1); - break; - case 9: - createScene(8, 2); - break; - } - } -} - -uint32 Module2500::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Module::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x200D: - playSound(_soundIndex); - _soundIndex++; - if (_soundIndex >= 4) - _soundIndex = 0; - break; - } - return messageResult; -} - -void Module2500::createScene2704(int which, uint32 sceneInfoId, int16 value, const uint32 *staticSprites, const NRect *clipRect) { - _childObject = new Scene2704(_vm, this, which, sceneInfoId, value, staticSprites, clipRect); -} - -Scene2501::Scene2501(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B2628)); - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B264C)); - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B2670)); - - setGlobalVar(V_CAR_DELTA_X, 1); - SetUpdateHandler(&Scene2501::update); - setBackground(0x1B8E8115); - setPalette(0x1B8E8115); - _palette->addPalette(0x00128842, 65, 31, 65); - _palette->addPalette("paKlayRed", 0, 64, 0); - insertScreenMouse(0xE81111B0); - - _ssTrackShadowBackground = createSprite(0x99BE9015); // Don't add this to the sprite list - addEntity(_ssTrackShadowBackground); - _asCar = createSprite(this, 211, 400); // Create but don't add to the sprite list yet - _asIdleCarLower = insertSprite(211, 400); - _asIdleCarFull = insertSprite(211, 400); - insertStaticSprite(0xC42AC521, 1500); - - if (which < 0) { - // Restoring game - insertKlaymen(162, 393); - _kmScene2501 = _klaymen; - _klaymenInCar = false; - setMessageList(0x004B2538); - setRectList(0x004B2608); - SetMessageHandler(&Scene2501::handleMessage); - SetUpdateHandler(&Scene2501::update); - sendMessage(_asCar, 0x2009, 0); - _asCar->setVisible(false); - _currTrackIndex = 0; - } else if (which == 1 || which == 2) { - // 1: Klaymen entering riding the car on the left track - // 2: Klaymen entering riding the car on the bottom track - addSprite(_asCar); - _kmScene2501 = (Klaymen*)new KmScene2501(_vm, this, 275, 393); - _klaymenInCar = true; - sendMessage(_kmScene2501, 0x2000, 1); - _kmScene2501->setDoDeltaX(1); - SetMessageHandler(&Scene2501::hmRidingCar); - SetUpdateHandler(&Scene2501::upRidingCar); - _asIdleCarLower->setVisible(false); - _asIdleCarFull->setVisible(false); - _currTrackIndex = which; - } else { - // Klaymen entering the car - insertKlaymen(162, 393); - _kmScene2501 = _klaymen; - _klaymenInCar = false; - setMessageList(0x004B2538); - setRectList(0x004B2608); - SetMessageHandler(&Scene2501::handleMessage); - SetUpdateHandler(&Scene2501::update); - sendMessage(_asCar, 0x2009, 0); - _asCar->setVisible(false); - _currTrackIndex = 0; - } - - _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - insertSprite(_asCar); - - _newTrackIndex = -1; - _dataResource.load(calcHash("Ashooded")); - - _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); - _asCar->setPathPoints(_trackPoints); - - if (which >= 0 && _tracks[_currTrackIndex]->which2 == which) { - NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1]; - sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); - if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480) - sendMessage(_asCar, 0x2007, 150); - } else { - NPoint testPoint = (*_trackPoints)[0]; - sendMessage(_asCar, 0x2002, 0); - if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480) - sendMessage(_asCar, 0x2008, 150); - } - - _carStatus = 0; - -} - -Scene2501::~Scene2501() { - // Free sprites not currently in the sprite list - if (_klaymenInCar) - delete _kmScene2501; - else - delete _asCar; -} - -void Scene2501::update() { - Scene::update(); - if (_carStatus == 1) { - removeSprite(_klaymen); - addSprite(_asCar); - clearRectList(); - _klaymenInCar = true; - SetMessageHandler(&Scene2501::hmCarAtHome); - SetUpdateHandler(&Scene2501::upCarAtHome); - _asIdleCarLower->setVisible(false); - _asIdleCarFull->setVisible(false); - _asCar->setVisible(true); - sendMessage(_asCar, 0x2009, 0); - _asCar->handleUpdate(); - _klaymen = NULL; - _carStatus = 0; - } - updateKlaymenClipRect(); -} - -void Scene2501::upCarAtHome() { - Scene::update(); - if (_mouseClicked) { - if (_mouseClickPos.x <= 210 && _asCar->getX() == 211 && _asCar->getY() == 400) { - sendMessage(_asCar, 0x200A, 0); - SetUpdateHandler(&Scene2501::upGettingOutOfCar); - } else { - moveCarToPoint(_mouseClickPos); - SetMessageHandler(&Scene2501::hmRidingCar); - SetUpdateHandler(&Scene2501::upRidingCar); - } - _mouseClicked = false; - } - updateKlaymenClipRect(); -} - -void Scene2501::upGettingOutOfCar() { - Scene::update(); - if (_carStatus == 2) { - _klaymen = _kmScene2501; - removeSprite(_asCar); - addSprite(_klaymen); - _klaymenInCar = false; - SetMessageHandler(&Scene2501::handleMessage); - SetUpdateHandler(&Scene2501::update); - setRectList(0x004B2608); - _asIdleCarLower->setVisible(true); - _asIdleCarFull->setVisible(true); - _asCar->setVisible(false); - setMessageList(0x004B2570); - processMessageList(); - _klaymen->handleUpdate(); - _carStatus = 0; - } - updateKlaymenClipRect(); -} - -void Scene2501::upRidingCar() { - Scene::update(); - if (_mouseClicked) { - moveCarToPoint(_mouseClickPos); - _mouseClicked = false; - } -} - -uint32 Scene2501::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x60842040) - _carStatus = 1; - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - } - return messageResult; -} - -uint32 Scene2501::hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2005: - if (_tracks[_currTrackIndex]->which1 < 0 && _newTrackIndex >= 0) - changeTrack(); - else if (_tracks[_currTrackIndex]->which1 == 0) { - SetMessageHandler(&Scene2501::hmCarAtHome); - SetUpdateHandler(&Scene2501::upCarAtHome); - sendMessage(_asCar, 0x200F, 1); - } else if (_tracks[_currTrackIndex]->which1 > 0) - leaveScene(_tracks[_currTrackIndex]->which1); - break; - case 0x2006: - if (_tracks[_currTrackIndex]->which2 < 0 && _newTrackIndex >= 0) - changeTrack(); - else if (_tracks[_currTrackIndex]->which2 == 0) { - SetMessageHandler(&Scene2501::hmCarAtHome); - SetUpdateHandler(&Scene2501::upCarAtHome); - sendMessage(_asCar, 0x200F, 1); - } else if (_tracks[_currTrackIndex]->which2 > 0) - leaveScene(_tracks[_currTrackIndex]->which2); - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - } - return messageResult; -} - -uint32 Scene2501::hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x200A: - _carStatus = 2; - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - } - return messageResult; -} - -void Scene2501::moveCarToPoint(NPoint &pt) { - int minMatchTrackIndex, minMatchDistance; - _tracks.findTrackPoint(pt, minMatchTrackIndex, minMatchDistance, _dataResource); - if (minMatchTrackIndex >= 0 && minMatchTrackIndex != _currTrackIndex) { - _newTrackIndex = minMatchTrackIndex; - _clickPoint = pt; - if (_currTrackIndex == 0) - sendMessage(_asCar, 0x2003, _trackPoints->size() - 1); - else - sendMessage(_asCar, 0x2003, 0); - } else { - _newTrackIndex = -1; - sendMessage(_asCar, 0x2004, pt); - } -} - -void Scene2501::changeTrack() { - _currTrackIndex = _newTrackIndex; - _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); - _asCar->setPathPoints(_trackPoints); - if (_currTrackIndex == 0) - sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); - else - sendMessage(_asCar, 0x2002, 0); - sendPointMessage(_asCar, 0x2004, _clickPoint); - _newTrackIndex = -1; -} - -void Scene2501::updateKlaymenClipRect() { - if (_kmScene2501->getX() <= 211) - _kmScene2501->setClipRect(0, 0, 640, 480); - else - _kmScene2501->setClipRect(0, 0, 640, 388); -} - -SsScene2504Button::SsScene2504Button(NeverhoodEngine *vm) - : StaticSprite(vm, 1400), _countdown(0), _isSoundPlaying(false) { - - loadSprite(0x070220D9, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); - setVisible(false); - loadSound(0, 0x4600204C); - loadSound(1, 0x408C0034); - loadSound(2, 0x44043000); - loadSound(3, 0x44045000); - SetMessageHandler(&SsScene2504Button::handleMessage); - SetUpdateHandler(&SsScene2504Button::update); -} - -void SsScene2504Button::update() { - updatePosition(); - if (_isSoundPlaying && !isSoundPlaying(0) && !isSoundPlaying(1)) { - playSound(3); - setVisible(false); - _isSoundPlaying = false; - } - if (_countdown != 0 && (--_countdown) == 0) { - if (getSubVar(VA_LOCKS_DISABLED, 0x01180951)) - playSound(0); - else - playSound(1); - _isSoundPlaying = true; - } -} - -uint32 SsScene2504Button::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_countdown == 0 && !_isSoundPlaying) { - setVisible(true); - _countdown = 2; - if (getSubVar(VA_LOCKS_DISABLED, 0x01180951)) - setSubVar(VA_LOCKS_DISABLED, 0x01180951, 0); - else - setSubVar(VA_LOCKS_DISABLED, 0x01180951, 1); - playSound(2); - } - messageResult = 1; - break; - } - return messageResult; -} - -Scene2504::Scene2504(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - Sprite *ssButton; - - setBackground(0x90791B80); - setPalette(0x90791B80); - ssButton = insertSprite(); - addCollisionSprite(ssButton); - insertPuzzleMouse(0x91B8490F, 20, 620); - SetMessageHandler(&Scene2504::handleMessage); - SetUpdateHandler(&Scene::update); -} - -uint32 Scene2504::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) - leaveScene(0); - break; - } - return messageResult; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module2500.h b/engines/neverhood/module2500.h deleted file mode 100644 index 10301b089d..0000000000 --- a/engines/neverhood/module2500.h +++ /dev/null @@ -1,101 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE2500_H -#define NEVERHOOD_MODULE2500_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/module1000.h" -#include "neverhood/module1600.h" -#include "neverhood/module2700.h" - -namespace Neverhood { - -// Module2500 - -class Module2500 : public Module { -public: - Module2500(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module2500(); -protected: - int _sceneNum; - int _soundIndex; - void createScene(int sceneNum, int which); - void updateScene(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void createScene2704(int which, uint32 sceneInfoId, int16 value, const uint32 *staticSprites = NULL, const NRect *clipRect = NULL); -}; - -class Scene2501 : public Scene { -public: - Scene2501(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Scene2501(); -protected: - AsCommonCar *_asCar; - Sprite *_ssTrackShadowBackground; - Sprite *_asCarShadow; - Sprite *_asCarConnectorShadow; - Sprite *_asCarTrackShadow; - Sprite *_asIdleCarLower; - Sprite *_asIdleCarFull; - Klaymen *_kmScene2501; - Tracks _tracks; - NPointArray *_trackPoints; - int _currTrackIndex; - NPoint _clickPoint; - int _newTrackIndex; - int _carStatus; - bool _klaymenInCar; - void update(); - void upCarAtHome(); - void upGettingOutOfCar(); - void upRidingCar(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender); - void moveCarToPoint(NPoint &pt); - void changeTrack(); - void updateKlaymenClipRect(); -}; - -class SsScene2504Button : public StaticSprite { -public: - SsScene2504Button(NeverhoodEngine *vm); -protected: - int _countdown; - bool _isSoundPlaying; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2504 : public Scene { -public: - Scene2504(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE2500_H */ diff --git a/engines/neverhood/module2600.cpp b/engines/neverhood/module2600.cpp deleted file mode 100644 index 04a91475a1..0000000000 --- a/engines/neverhood/module2600.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* 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/module2600.h" - -namespace Neverhood { - -static const uint32 kModule2600SoundList[] = { - 0xB288D450, - 0x90804450, - 0x99801500, - 0xB288D455, - 0x93825040, - 0 -}; - -Module2600::Module2600(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - if (which < 0) - createScene(_vm->gameState().sceneNum, -1); - else if (which == 1) - createScene(4, 1); - else - createScene(0, 1); - - _vm->_soundMan->addSoundList(0x40271018, kModule2600SoundList); - _vm->_soundMan->setSoundListParams(kModule2600SoundList, true, 50, 600, 5, 150); - _vm->_soundMan->playTwoSounds(0x40271018, 0x41861371, 0x43A2507F, 0); - -} - -Module2600::~Module2600() { - _vm->_soundMan->deleteGroup(0x40271018); -} - -void Module2600::createScene(int sceneNum, int which) { - debug("Module2600::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - createNavigationScene(0x004B8608, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - createNavigationScene(0x004B8638, which); - break; - case 2: - _vm->gameState().sceneNum = 2; - createNavigationScene(0x004B86C8, which); - break; - case 3: - _vm->gameState().sceneNum = 3; - if (getGlobalVar(V_CREATURE_ANGRY)) - createNavigationScene(0x004B8758, which); - else - createNavigationScene(0x004B86F8, which); - break; - case 4: - _vm->gameState().sceneNum = 4; - createNavigationScene(0x004B87B8, which); - break; - case 6: - _vm->gameState().sceneNum = 6; - createNavigationScene(0x004B8698, which); - break; - case 7: - _vm->gameState().sceneNum = 7; - _vm->_soundMan->deleteGroup(0x40271018); - createSmackerScene(0x30090001, true, true, false); - break; - case 8: - _vm->gameState().sceneNum = 8; - _childObject = new Scene2609(_vm, this, which); - break; - case 1002: - _vm->gameState().sceneNum = 2; - if (getGlobalVar(V_FRUIT_COUNTING_INDEX) == 1) - createSmackerScene(0x018C0404, true, true, false); - else if (getGlobalVar(V_FRUIT_COUNTING_INDEX) == 2) - createSmackerScene(0x018C0407, true, true, false); - else - createSmackerScene(0x818C0405, true, true, false); - if (getGlobalVar(V_FRUIT_COUNTING_INDEX) >= 2) - setGlobalVar(V_FRUIT_COUNTING_INDEX, 0); - else - incGlobalVar(V_FRUIT_COUNTING_INDEX, +1); - break; - case 1003: - _vm->gameState().sceneNum = 3; - createSmackerScene(0x001C0007, true, true, false); - break; - case 1006: - _vm->gameState().sceneNum = 6; - if (getGlobalVar(V_WATER_RUNNING)) - createSmackerScene(0x049A1181, true, true, false); - else - createSmackerScene(0x04981181, true, true, false); - break; - case 1008: - _vm->gameState().sceneNum = 8; - if (getGlobalVar(V_WATER_RUNNING)) - createSmackerScene(0x42B80941, true, true, false); - else - createSmackerScene(0x42980941, true, true, false); - break; - case 9999: - createDemoScene(); - break; - } - SetUpdateHandler(&Module2600::updateScene); - _childObject->handleUpdate(); -} - -void Module2600::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == 1) - createScene(1, 3); - else - leaveModule(0); - break; - case 1: - if (_moduleResult == 0) - createScene(6, 0); - else if (_moduleResult == 1) - createScene(0, 0); - else if (_moduleResult == 2) - createScene(2, 1); - else if (_moduleResult == 3) - createScene(3, 0); - break; - case 2: - if (_moduleResult == 0) - createScene(1, 0); - else if (_moduleResult == 1) { - if (_vm->isDemo()) - createScene(9999, -1); - else - createScene(1002, -1); - } - break; - case 3: - if (_moduleResult == 0) { - if (getGlobalVar(V_CREATURE_ANGRY)) - createScene(4, 0); - else - createScene(1003, -1); - } else if (_moduleResult == 2) - createScene(1, 1); - else if (_moduleResult == 3) { - if (getGlobalVar(V_CREATURE_ANGRY)) - createScene(4, 0); - else { - setGlobalVar(V_CREATURE_ANGRY, 1); - createScene(7, -1); - } - } - break; - case 4: - if (_moduleResult == 0) - leaveModule(1); - else - createScene(3, 1); - break; - case 6: - if (_moduleResult == 0) { - if (_vm->isDemo()) - createScene(9999, -1); - else - createScene(1006, -1); - } - else if (_moduleResult == 1) - createScene(1, 2); - break; - case 7: - leaveModule(0); - break; - case 8: - createScene(1008, -1); - break; - case 1002: - createScene(2, 1); - break; - case 1003: - createScene(3, 0); - break; - case 1006: - createScene(8, -1); - break; - case 1008: - createScene(6, 0); - break; - case 9999: - createScene(_vm->gameState().sceneNum, -1); - break; - } - } -} - -SsScene2609Button::SsScene2609Button(NeverhoodEngine *vm, Scene *parentScene) - : StaticSprite(vm, 1400), _parentScene(parentScene), _countdown(0) { - - SetUpdateHandler(&SsScene2609Button::update); - SetMessageHandler(&SsScene2609Button::handleMessage); - - loadSprite(0x825A6923, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); - if (!getGlobalVar(V_WATER_RUNNING)) - setVisible(false); - loadSound(0, 0x10267160); - loadSound(1, 0x7027FD64); - loadSound(2, 0x44043000); - loadSound(3, 0x44045000); -} - -void SsScene2609Button::update() { - updatePosition(); - if (_countdown != 0 && (--_countdown == 0)) { - if (getGlobalVar(V_WATER_RUNNING)) { - setGlobalVar(V_WATER_RUNNING, 0); - sendMessage(_parentScene, 0x2001, 0); - } else { - setGlobalVar(V_WATER_RUNNING, 1); - sendMessage(_parentScene, 0x2002, 0); - } - } -} - -uint32 SsScene2609Button::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_countdown == 0) { - sendMessage(_parentScene, 0x2000, 0); - if (getGlobalVar(V_WATER_RUNNING)) { - setVisible(false); - playSound(3); - playSound(1); - _countdown = 12; - } else { - setVisible(true); - playSound(2); - playSound(0); - _countdown = 96; - } - } - messageResult = 1; - break; - } - return messageResult; -} - -AsScene2609Water::AsScene2609Water(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1000) { - - _x = 240; - _y = 420; - setDoDeltaX(1); - createSurface1(0x9C210C90, 1200); - setClipRect(260, 260, 400, 368); - _vm->_soundMan->addSound(0x08526C36, 0xDC2769B0); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2609Water::handleMessage); - if (getGlobalVar(V_WATER_RUNNING)) - sendMessage(this, 0x2002, 0); -} - -AsScene2609Water::~AsScene2609Water() { - _vm->_soundMan->deleteSoundGroup(0x08526C36); -} - -uint32 AsScene2609Water::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2001: - stopAnimation(); - setVisible(false); - _vm->_soundMan->stopSound(0xDC2769B0); - break; - case 0x2002: - startAnimation(0x9C210C90, 0, -1); - setVisible(true); - _vm->_soundMan->playSoundLooping(0xDC2769B0); - break; - } - return messageResult; -} - -Scene2609::Scene2609(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _isBusy(false) { - - SetUpdateHandler(&Scene::update); - SetMessageHandler(&Scene2609::handleMessage); - - setBackground(0x51409A16); - setPalette(0x51409A16); - _asWater = insertSprite(); - _ssButton = insertSprite(this); - addCollisionSprite(_ssButton); - insertPuzzleMouse(0x09A1251C, 20, 620); - insertStaticSprite(0x02138002, 1200); - insertStaticSprite(0x825E2827, 1200); -} - -uint32 Scene2609::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && !_isBusy) - leaveScene(0); - break; - case 0x2000: - _isBusy = true; - break; - case 0x2001: - _isBusy = false; - sendMessage(_asWater, 0x2001, 0); - break; - case 0x2002: - _isBusy = false; - sendMessage(_asWater, 0x2002, 0); - break; - } - return 0; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module2600.h b/engines/neverhood/module2600.h deleted file mode 100644 index 8f2f3779fe..0000000000 --- a/engines/neverhood/module2600.h +++ /dev/null @@ -1,74 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE2600_H -#define NEVERHOOD_MODULE2600_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" - -namespace Neverhood { - -// Module2600 - -class Module2600 : public Module { -public: - Module2600(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module2600(); -protected: - int _sceneNum; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -class SsScene2609Button : public StaticSprite { -public: - SsScene2609Button(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2609Water : public AnimatedSprite { -public: - AsScene2609Water(NeverhoodEngine *vm); - virtual ~AsScene2609Water(); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2609 : public Scene { -public: - Scene2609(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - bool _isBusy; - Sprite *_asWater; - Sprite *_ssButton; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE2600_H */ diff --git a/engines/neverhood/module2700.cpp b/engines/neverhood/module2700.cpp deleted file mode 100644 index 53e73af179..0000000000 --- a/engines/neverhood/module2700.cpp +++ /dev/null @@ -1,1211 +0,0 @@ -/* 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/module2700.h" -#include "neverhood/gamemodule.h" -#include "neverhood/module1000.h" - -namespace Neverhood { - -static const NRect kScene2710ClipRect = NRect(0, 0, 626, 480); - -static const uint32 kScene2710StaticSprites[] = { - 0x0D2016C0, - 0 -}; - -static const NRect kScene2711ClipRect = NRect(0, 0, 521, 480); - -static const uint32 kScene2711FileHashes1[] = { - 0, - 0x100801A1, - 0x201081A0, - 0x006800A4, - 0x40390120, - 0x000001B1, - 0x001000A1, - 0 -}; - -static const uint32 kScene2711FileHashes2[] = { - 0, - 0x40403308, - 0x71403168, - 0x80423928, - 0x224131A8, - 0x50401328, - 0x70423328, - 0 -}; - -static const uint32 kScene2711FileHashes3[] = { - 0, - 0x1088A021, - 0x108120E5, - 0x18A02321, - 0x148221A9, - 0x10082061, - 0x188820E1, - 0 -}; - -static const NRect kScene2724ClipRect = NRect(0, 141, 640, 480); - -static const uint32 kScene2724StaticSprites[] = { - 0xC20D00A5, - 0 -}; - -static const NRect kScene2725ClipRect = NRect(0, 0, 640, 413); - -static const uint32 kScene2725StaticSprites[] = { - 0xC20E00A5, - 0 -}; - -Module2700::Module2700(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule), _soundIndex(0), _raidoMusicInitialized(false) { - - _vm->_soundMan->addMusic(0x42212411, 0x04020210); - _vm->_soundMan->startMusic(0x04020210, 24, 2); - SetMessageHandler(&Module2700::handleMessage); - - if (which < 0) { - which = _vm->gameState().which; - // Scenes 0, 30 and 31 are "normal" scenes, whereas the other scenes are tracks. - // "gameState().which" indicates which track the car is at. - if (_vm->gameState().sceneNum == 0 || _vm->gameState().sceneNum == 30 || _vm->gameState().sceneNum == 31) - which = -1; - createScene(_vm->gameState().sceneNum, which); - } else - createScene(0, 0); - - loadSound(0, 0x00880CCC); - loadSound(1, 0x00880CC0); - loadSound(2, 0x00880CCC); - loadSound(3, 0x00880CC0); - -} - -Module2700::~Module2700() { - _vm->_soundMan->deleteGroup(0x42212411); -} - -void Module2700::createScene(int sceneNum, int which) { - debug("Module2700::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _vm->gameState().which = which; - _childObject = new Scene2701(_vm, this, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - _vm->gameState().which = which; - _childObject = new Scene2702(_vm, this, which); - break; - case 2: - _vm->gameState().sceneNum = 2; - _vm->gameState().which = which; - if (which == 6 || which == 7) - createScene2703(which, 0x004B1710); - else if (which == 4 || which == 5) - createScene2703(which, 0x004B1738); - else if (which == 2 || which == 3) - createScene2703(which, 0x004B1760); - else - createScene2703(which, 0x004B1788); - break; - case 3: - _vm->gameState().sceneNum = 3; - _vm->gameState().which = which; - createScene2704(which, 0x004B17B0, 150); - break; - case 4: - _vm->gameState().sceneNum = 4; - _vm->gameState().which = which; - createScene2704(which, 0x004B17D8, 150); - break; - case 5: - _vm->gameState().sceneNum = 5; - _vm->gameState().which = which; - if (which >= 4) - _childObject = new Scene2706(_vm, this, which); - else if (which == 2 || which == 3) - createScene2704(which, 0x004B1828, 150); - else - createScene2704(which, 0x004B1800, 150); - break; - case 6: - _vm->gameState().sceneNum = 6; - _vm->gameState().which = which; - createScene2704(which, 0x004B1850, 150); - break; - case 7: - _vm->gameState().sceneNum = 7; - _vm->gameState().which = which; - if (which == 2 || which == 3) - createScene2704(which, 0x004B1878, 150); - else - createScene2704(which, 0x004B18A0, 150); - break; - case 8: - _vm->gameState().sceneNum = 8; - _vm->gameState().which = which; - if (which == 2 || which == 3) - createScene2704(which, 0x004B18C8, 150); - else - createScene2704(which, 0x004B18F0, 150); - break; - case 9: - _vm->gameState().sceneNum = 9; - _vm->gameState().which = which; - createScene2704(which, 0x004B1918, 150, kScene2710StaticSprites, &kScene2710ClipRect); - break; - case 10: - _vm->gameState().sceneNum = 10; - _vm->gameState().which = which; - _vm->gameModule()->initTestTubes2Puzzle(); - _scene2711StaticSprites[0] = kScene2711FileHashes1[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2)]; - _scene2711StaticSprites[1] = kScene2711FileHashes2[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1)]; - _scene2711StaticSprites[2] = kScene2711FileHashes3[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0)]; - _scene2711StaticSprites[3] = 0x0261282E; - _scene2711StaticSprites[4] = 0x9608E5A0; - _scene2711StaticSprites[5] = 0; - createScene2704(which, 0x004B1950, 150, _scene2711StaticSprites, &kScene2711ClipRect); - break; - case 11: - _vm->gameState().sceneNum = 11; - _vm->gameState().which = which; - createScene2704(which, 0x004B19E0, 150); - break; - case 12: - _vm->gameState().sceneNum = 12; - _vm->gameState().which = which; - createScene2704(which, 0x004B1A08, 150); - break; - case 13: - _vm->gameState().sceneNum = 13; - _vm->gameState().which = which; - createScene2704(which, 0x004B1A30, 150); - break; - case 14: - _vm->gameState().sceneNum = 14; - _vm->gameState().which = which; - if (which == 4 || which == 5) - createScene2704(which, 0x004B1A58, 150); - else if (which == 2 || which == 3) - createScene2704(which, 0x004B1A80, 150); - else - createScene2704(which, 0x004B1AA8, 150); - break; - case 15: - _vm->gameState().sceneNum = 15; - _vm->gameState().which = which; - if (which == 4 || which == 5) - createScene2704(which, 0x004B1AD0, 150); - else if (which == 2 || which == 3) - createScene2704(which, 0x004B1AF8, 150); - else - createScene2704(which, 0x004B1B20, 150); - break; - case 16: - _vm->gameState().sceneNum = 16; - _vm->gameState().which = which; - if (which == 4 || which == 5) - createScene2704(which, 0x004B1B48, 150); - else if (which == 2 || which == 3) - createScene2704(which, 0x004B1B70, 150); - else - createScene2704(which, 0x004B1B98, 150); - break; - case 17: - _vm->gameState().sceneNum = 17; - _vm->gameState().which = which; - if (which == 4 || which == 5) - createScene2704(which, 0x004B1BC0, 150); - else if (which == 2 || which == 3) - createScene2704(which, 0x004B1BE8, 150); - else - createScene2704(which, 0x004B1C10, 150); - break; - case 18: - _vm->gameState().sceneNum = 18; - _vm->gameState().which = which; - if (which == 2 || which == 3) - createScene2704(which, 0x004B1C38, 150); - else - createScene2704(which, 0x004B1C60, 150); - break; - case 19: - _vm->gameState().sceneNum = 19; - _vm->gameState().which = which; - if (which == 2 || which == 3) - createScene2704(which, 0x004B1CB0, 150); - else - createScene2704(which, 0x004B1C88, 150); - break; - case 20: - _vm->gameState().sceneNum = 20; - _vm->gameState().which = which; - if (which == 2 || which == 3) - createScene2704(which, 0x004B1CD8, 150); - else - createScene2704(which, 0x004B1D00, 150); - break; - case 21: - _vm->gameState().sceneNum = 21; - _vm->gameState().which = which; - createScene2704(which, 0x004B1D28, 150); - break; - case 22: - _vm->gameState().sceneNum = 22; - _vm->gameState().which = which; - createScene2704(which, 0x004B1D50, 150); - break; - case 23: - _vm->gameState().sceneNum = 23; - _vm->gameState().which = which; - createScene2704(which, 0x004B1D78, 150, kScene2724StaticSprites, &kScene2724ClipRect); - break; - case 24: - _vm->gameState().sceneNum = 24; - _vm->gameState().which = which; - createScene2704(which, 0x004B1DB0, 150, kScene2725StaticSprites, &kScene2725ClipRect); - break; - case 25: - _vm->gameState().sceneNum = 25; - _vm->gameState().which = which; - createScene2704(which, 0x004B1DE8, 150); - break; - case 26: - _vm->gameState().sceneNum = 26; - _vm->gameState().which = which; - createScene2704(which, 0x004B1E10, 150); - break; - case 27: - _vm->gameState().sceneNum = 27; - _vm->gameState().which = which; - createScene2704(which, 0x004B1E38, 150); - break; - case 28: - _vm->gameState().sceneNum = 28; - _vm->gameState().which = which; - createScene2704(which, 0x004B1E60, 150); - break; - case 30: - _vm->gameState().sceneNum = 30; - createStaticScene(0x09507248, 0x0724C09D); - break; - case 31: - _vm->gameState().sceneNum = 31; - _childObject = new Scene2732(_vm, this); - break; - } - SetUpdateHandler(&Module2700::updateScene); - _childObject->handleUpdate(); -} - -#define SceneLinkIf(moduleResult, sceneNum, which) \ - if (_moduleResult == moduleResult) { createScene(sceneNum, which); break; } - -void Module2700::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - SceneLinkIf(1, 1, 0); - leaveModule(0); - break; - case 1: - SceneLinkIf(1, 14, 1); - SceneLinkIf(2, 2, 2); - SceneLinkIf(3, 14, 3); - SceneLinkIf(4, 2, 6); - SceneLinkIf(5, 2, 4); - createScene(0, 1); - break; - case 2: - SceneLinkIf(1, 5, 0); - SceneLinkIf(2, 1, 2); - SceneLinkIf(3, 5, 2); - SceneLinkIf(4, 1, 5); - SceneLinkIf(5, 5, 4); - SceneLinkIf(6, 1, 4); - SceneLinkIf(7, 11, 0); - createScene(3, 0); - break; - case 3: - createScene(2, 0); - break; - case 4: - SceneLinkIf(1, 7, 2); - createScene(5, 5); - break; - case 5: - SceneLinkIf(1, 6, 0); - SceneLinkIf(2, 2, 3); - SceneLinkIf(3, 8, 2); - SceneLinkIf(4, 2, 5); - SceneLinkIf(5, 4, 0); - SceneLinkIf(6, 7, 0); - createScene(2, 1); - break; - case 6: - SceneLinkIf(1, 8, 0); - createScene(5, 1); - break; - case 7: - SceneLinkIf(1, 8, 3); - SceneLinkIf(2, 4, 1); - SceneLinkIf(3, 9, 0); - createScene(5, 6); - break; - case 8: - SceneLinkIf(1, 10, 0); - SceneLinkIf(2, 5, 3); - SceneLinkIf(3, 7, 1); - createScene(6, 1); - break; - case 9: - SceneLinkIf(1, 10, 1); - createScene(7, 3); - break; - case 10: - SceneLinkIf(1, 9, 1); - createScene(8, 1); - break; - case 11: - SceneLinkIf(1, 12, 0); - createScene(2, 7); - break; - case 12: - SceneLinkIf(1, 13, 0); - createScene(11, 1); - break; - case 13: - SceneLinkIf(1, 30, 0); - createScene(12, 1); - break; - case 14: - SceneLinkIf(1, 1, 1); - SceneLinkIf(2, 15, 3); - SceneLinkIf(3, 1, 3); - SceneLinkIf(4, 15, 5); - SceneLinkIf(5, 22, 0); - createScene(15, 1); - break; - case 15: - SceneLinkIf(1, 14, 0); - SceneLinkIf(2, 16, 3); - SceneLinkIf(3, 14, 2); - SceneLinkIf(4, 16, 5); - SceneLinkIf(5, 14, 4); - createScene(16, 1); - break; - case 16: - SceneLinkIf(1, 15, 0); - SceneLinkIf(2, 17, 3); - SceneLinkIf(3, 15, 2); - SceneLinkIf(4, 17, 5); - SceneLinkIf(5, 15, 4); - createScene(17, 1); - break; - case 17: - SceneLinkIf(1, 16, 0); - SceneLinkIf(2, 18, 3); - SceneLinkIf(3, 16, 2); - SceneLinkIf(4, 20, 1); - SceneLinkIf(5, 16, 4); - createScene(18, 1); - break; - case 18: - SceneLinkIf(1, 17, 0); - SceneLinkIf(2, 19, 2); - SceneLinkIf(3, 17, 2); - createScene(19, 0); - break; - case 19: - SceneLinkIf(1, 20, 2); - SceneLinkIf(2, 18, 2); - SceneLinkIf(3, 20, 0); - createScene(18, 0); - break; - case 20: - SceneLinkIf(1, 17, 4); - SceneLinkIf(2, 19, 1); - SceneLinkIf(3, 21, 0); - createScene(19, 3); - break; - case 21: - _vm->_soundMan->deleteMusic(_musicFileHash); - _vm->_soundMan->startMusic(0x04020210, 0, 2); - _vm->_soundMan->deleteSoundGroup(0x42212411); - createScene(20, 3); - break; - case 22: - SceneLinkIf(1, 23, 0); - createScene(14, 5); - break; - case 23: - SceneLinkIf(1, 24, 0); - createScene(22, 1); - break; - case 24: - SceneLinkIf(1, 25, 0); - createScene(23, 1); - break; - case 25: - SceneLinkIf(1, 26, 0); - createScene(24, 1); - break; - case 26: - SceneLinkIf(1, 27, 0); - createScene(25, 1); - break; - case 27: - SceneLinkIf(1, 28, 0); - createScene(26, 1); - break; - case 28: - SceneLinkIf(1, 31, 0); - createScene(27, 1); - break; - case 30: - createScene(13, 1); - break; - case 31: - createScene(28, 1); - break; - } - } else { - switch (_sceneNum) { - case 21: - if (!_raidoMusicInitialized) { - _vm->_soundMan->stopMusic(0x04020210, 0, 1); - _vm->gameModule()->initRadioPuzzle(); - _musicFileHash = getGlobalVar(V_GOOD_RADIO_MUSIC_NAME); - _vm->_soundMan->addMusic(0x42212411, _musicFileHash); - _vm->_soundMan->startMusic(_musicFileHash, 0, 2); - _vm->_soundMan->addSound(0x42212411, 0x44014282); - _vm->_soundMan->setSoundParams(0x44014282, true, 120, 360, 72, 0); - _raidoMusicInitialized = true; - } - break; - } - } -} - -uint32 Module2700::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Module::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x200D: - playSound(_soundIndex); - _soundIndex++; - if (_soundIndex >= 4) - _soundIndex = 0; - break; - } - return messageResult; -} - -void Module2700::createScene2703(int which, uint32 trackInfoId) { - _childObject = new Scene2703(_vm, this, which, trackInfoId); -} - -void Module2700::createScene2704(int which, uint32 trackInfoId, int16 value, const uint32 *staticSprites, const NRect *clipRect) { - _childObject = new Scene2704(_vm, this, which, trackInfoId, value, staticSprites, clipRect); -} - -static const NPoint kCarShadowOffsets[] = { - {-63, 3}, {-48, 40}, {-33, 58}, - { 0, 65}, { 40, 53}, { 56, 27}, - { 63, 0}, {-30, 26}, { 0, 30}, - { 26, 25} -}; - -SsCommonTrackShadowBackground::SsCommonTrackShadowBackground(NeverhoodEngine *vm, uint32 fileHash) - : StaticSprite(vm, 0) { - - loadSprite(fileHash, kSLFDefDrawOffset | kSLFDefPosition, 0); -} - -AsCommonCarShadow::AsCommonCarShadow(NeverhoodEngine *vm, AnimatedSprite *asCar, BaseSurface *shadowSurface, uint index) - : AnimatedSprite(vm, 1100), _asCar(asCar), _index(index), _animFileHash(0) { - - SetUpdateHandler(&AsCommonCarShadow::update); - createShadowSurface(shadowSurface, 211, 147, 100); - updateShadow(); -} - -void AsCommonCarShadow::update() { - updateShadow(); - AnimatedSprite::update(); -} - -void AsCommonCarShadow::updateShadow() { - if (_asCar->getFrameIndex() != _currFrameIndex || _asCar->getCurrAnimFileHash() != _animFileHash) { - uint32 fileHash = _asCar->getCurrAnimFileHash(); - if (fileHash == 0x35698F78 || fileHash == 0x192ADD30 || fileHash == 0x9C220DA4 || - fileHash == 0x9966B138 || fileHash == 0xB579A77C || fileHash == 0xA86A9538 || - fileHash == 0xD4220027 || fileHash == 0xD00A1364 || fileHash == 0xD4AA03A4 || - fileHash == 0xF46A0324) { - startAnimation(fileHash, _asCar->getFrameIndex(), -1); - _newStickFrameIndex = _asCar->getFrameIndex(); - } - _animFileHash = fileHash; - } - _x = _asCar->getX() + kCarShadowOffsets[_index].x; - _y = _asCar->getY() + kCarShadowOffsets[_index].y; - if (!_asCar->getVisible()) { - startAnimation(0x1209E09F, 0, -1); - _newStickFrameIndex = 0; - } - setDoDeltaX(_asCar->isDoDeltaX() ? 1 : 0); -} - -AsCommonCarConnectorShadow::AsCommonCarConnectorShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, uint index) - : AnimatedSprite(vm, 1100), _asCar(asCar), _index(index) { - - SetUpdateHandler(&AsCommonCarConnectorShadow::update); - createShadowSurface1(shadowSurface, 0x60281C10, 150); - startAnimation(0x60281C10, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; -} - -void AsCommonCarConnectorShadow::update() { - _x = _asCar->getX() + kCarShadowOffsets[_index].x; - _y = _asCar->getY() + kCarShadowOffsets[_index].y; - AnimatedSprite::update(); -} - -AsCommonCarTrackShadow::AsCommonCarTrackShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, int16 frameIndex) - : AnimatedSprite(vm, 1100), _asCar(asCar) { - - SetUpdateHandler(&AsCommonCarTrackShadow::update); - createShadowSurface1(shadowSurface, 0x0759129C, 100); - startAnimation(0x0759129C, frameIndex, -1); - _newStickFrameIndex = frameIndex; -} - -void AsCommonCarTrackShadow::update() { - _x = _asCar->getX(); - _y = _asCar->getY(); - AnimatedSprite::update(); -} - -Scene2701::Scene2701(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - Sprite *tempSprite; - - NRect clipRect; - TrackInfo *tracks = _vm->_staticData->getTrackInfo(0x004B2240); - setGlobalVar(V_CAR_DELTA_X, 1); - - setBackground(tracks->bgFilename); - setPalette(tracks->bgFilename); - _palette->addPalette(calcHash("paPodFloor"), 65, 31, 65); - _palette->addPalette(calcHash("paKlayFloor"), 0, 65, 0); - insertScreenMouse(0x08B08180); - - tempSprite = insertStaticSprite(0x1E086325, 1200); - clipRect.set(0, 0, 640, tempSprite->getDrawRect().y2()); - - if (tracks->bgShadowFilename) { - _ssTrackShadowBackground = createSprite(tracks->bgShadowFilename); - addEntity(_ssTrackShadowBackground); - _asCar = insertSprite(this, 320, 240); - _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - } else { - _ssTrackShadowBackground = NULL; - _asCar = insertSprite(this, 320, 240); - } - - _asCarConnector = insertSprite(_asCar); - _which1 = tracks->which1; - _which2 = tracks->which2; - _dataResource.load(tracks->dataResourceFilename); - _trackPoints = _dataResource.getPointArray(tracks->trackPointsName); - _asCar->setPathPoints(_trackPoints); - - if (which == _which2) { - NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1]; - sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); - if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480) - sendMessage(_asCar, 0x2007, 150); - } else { - NPoint testPoint = (*_trackPoints)[0]; - sendMessage(_asCar, 0x2002, 0); - if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480) - sendMessage(_asCar, 0x2008, 150); - } - - _asCar->setClipRect(clipRect); - _asCarConnector->setClipRect(clipRect); - - if (which == 1) { - SetMessageHandler(&Scene2701::hmRidingCar); - } else { - sendMessage(_asCar, 0x2009, 0); - SetMessageHandler(&Scene2701::hmCarAtHome); - } - -} - -uint32 Scene2701::hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - sendPointMessage(_asCar, 0x2004, param.asPoint()); - break; - case 0x2005: - if (_which1 >= 0) - SetMessageHandler(&Scene2701::hmCarAtHome); - break; - case 0x2006: - if (_which2 >= 0) - leaveScene(_which2); - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - } - return 0; -} - -uint32 Scene2701::hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x >= 385) - leaveScene(0); - else { - sendPointMessage(_asCar, 0x2004, param.asPoint()); - SetMessageHandler(&Scene2701::hmRidingCar); - } - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - } - return 0; -} - -Scene2702::Scene2702(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _isInLight(true), _newTrackIndex(-1) { - - SetMessageHandler(&Scene2702::handleMessage); - SetUpdateHandler(&Scene2702::update); - - setBackground(0x18808B00); - setPalette(0x18808B00); - _palette->addPalette(calcHash("paPodFloor"), 65, 31, 65); - _palette->addPalette(calcHash("paKlayFloor"), 0, 65, 0); - addEntity(_palette); - insertScreenMouse(0x08B04180); - - _ssTrackShadowBackground = createSprite(0x12002035); - addEntity(_ssTrackShadowBackground); - _asCar = insertSprite(this, 320, 240); - _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - insertSprite(_asCar); - _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _dataResource.load(0x04310014); - - if (which == 1) { - _isUpperTrack = false; - _currTrackIndex = 1; - } else if (which == 2) { - _isUpperTrack = false; - _currTrackIndex = 2; - _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); - _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); - _isInLight = false; - } else if (which == 3) { - _isUpperTrack = true; - _currTrackIndex = 0; - } else if (which == 4) { - _isUpperTrack = true; - _currTrackIndex = 2; - _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); - _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); - _isInLight = false; - } else if (which == 5) { - _isUpperTrack = true; - _currTrackIndex = 1; - _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); - _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); - _isInLight = false; - } else { - _isUpperTrack = false; - _currTrackIndex = 0; - } - - if (_isUpperTrack) { - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5F68)); - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5F8C)); - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FB0)); - } else { - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FD8)); - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FFC)); - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B6020)); - } - - _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); - _asCar->setPathPoints(_trackPoints); - - if (which == _tracks[_currTrackIndex]->which2) { - sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); - sendMessage(_asCar, 0x2007, 150); - } else { - sendMessage(_asCar, 0x2002, 0); - sendMessage(_asCar, 0x2008, 150); - } - - _palette->copyBasePalette(0, 256, 0); - -} - -void Scene2702::update() { - Scene::update(); - if (_isInLight && _asCar->getX() > 422) { - _palette->addBasePalette(calcHash("paPodShade"), 65, 31, 65); - _palette->addBasePalette(calcHash("paKlayShade"), 0, 65, 0); - _palette->startFadeToPalette(12); - _isInLight = false; - } else if (!_isInLight && _asCar->getX() <= 422) { - _palette->addBasePalette(calcHash("paPodFloor"), 65, 31, 65); - _palette->addBasePalette(calcHash("paKlayFloor"), 0, 65, 0); - _palette->startFadeToPalette(12); - _isInLight = true; - } -} - -uint32 Scene2702::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - moveCarToPoint(param.asPoint()); - break; - case 0x2005: - if (_newTrackIndex >= 0) { - if (_tracks[_currTrackIndex]->which1 < 0) - changeTrack(); - } else if (_tracks[_currTrackIndex]->which1 >= 0) - leaveScene(_tracks[_currTrackIndex]->which1); - break; - case 0x2006: - if (_newTrackIndex >= 0) { - if (_tracks[_currTrackIndex]->which2 < 0) - changeTrack(); - } else if (_tracks[_currTrackIndex]->which2 >= 0) - leaveScene(_tracks[_currTrackIndex]->which2); - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - } - return 0; -} - -void Scene2702::moveCarToPoint(NPoint pt) { - int minMatchTrackIndex, minMatchDistance; - _tracks.findTrackPoint(pt, minMatchTrackIndex, minMatchDistance, _dataResource); - if (minMatchTrackIndex >= 0 && minMatchTrackIndex != _currTrackIndex) { - _newTrackIndex = minMatchTrackIndex; - _newTrackDestX = pt.x; - if (_isUpperTrack) { - if (_currTrackIndex == 0) - sendMessage(_asCar, 0x2003, _trackPoints->size() - 1); - else - sendMessage(_asCar, 0x2003, 0); - } else if (_currTrackIndex == 2) - sendMessage(_asCar, 0x2003, 0); - else - sendMessage(_asCar, 0x2003, _trackPoints->size() - 1); - } else { - _newTrackIndex = -1; - sendMessage(_asCar, 0x2004, pt.x); - } -} - -void Scene2702::changeTrack() { - _currTrackIndex = _newTrackIndex; - _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); - _asCar->setPathPoints(_trackPoints); - if (_isUpperTrack) { - if (_currTrackIndex == 0) - sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); - else - sendMessage(_asCar, 0x2002, 0); - } else if (_currTrackIndex == 2) - sendMessage(_asCar, 0x2002, 0); - else - sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); - sendMessage(_asCar, 0x2004, _newTrackDestX); - _newTrackIndex = -1; -} - -Scene2703::Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint32 trackInfoId) - : Scene(vm, parentModule) { - - TrackInfo *tracks = _vm->_staticData->getTrackInfo(trackInfoId); - - SetMessageHandler(&Scene2703::handleMessage); - SetUpdateHandler(&Scene2703::update); - - setBackground(tracks->bgFilename); - setPalette(tracks->bgFilename); - _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); - _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); - addEntity(_palette); - insertScreenMouse(tracks->mouseCursorFilename); - - _palStatus = 2; - - if (tracks->bgShadowFilename) { - _ssTrackShadowBackground = createSprite(tracks->bgShadowFilename); - addEntity(_ssTrackShadowBackground); - _asCar = insertSprite(this, 320, 240); - _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - } else { - _ssTrackShadowBackground = NULL; - _asCarShadow = NULL; - _asCar = insertSprite(this, 320, 240); - } - - _asCarConnector = insertSprite(_asCar); - _which1 = tracks->which1; - _which2 = tracks->which2; - _dataResource.load(tracks->dataResourceFilename); - _trackPoints = _dataResource.getPointArray(tracks->trackPointsName); - _asCar->setPathPoints(_trackPoints); - - if (which == _which2) { - NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1]; - sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); - if (testPoint.x > 0 && testPoint.x < 640 && testPoint.y > 0 && testPoint.y < 480) - sendMessage(_asCar, 0x2009, 0); - else - sendMessage(_asCar, 0x2007, 150); - } else { - NPoint testPoint = (*_trackPoints)[0]; - sendMessage(_asCar, 0x2002, 0); - if (testPoint.x > 0 && testPoint.x < 640 && testPoint.y > 0 && testPoint.y < 480) - sendMessage(_asCar, 0x2009, 0); - else - sendMessage(_asCar, 0x2008, 150); - } - - if (which == 0) { - _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); - _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); - _palStatus = 1; - } else if (which == 2 || which == 4 || which == 6) { - _palette->addPalette(calcHash("paPodBlack"), 65, 31, 65); - _palette->addPalette(calcHash("paKlayBlack"), 0, 65, 0); - _palStatus = 0; - } - - _palette->copyBasePalette(0, 256, 0); - -} - -void Scene2703::update() { - Scene::update(); - if (_mouseClicked) { - sendPointMessage(_asCar, 0x2004, _mouseClickPos); - _mouseClicked = false; - } - if (_asCar->getX() > 469) { - if (_palStatus != 2) { - _palette->addBasePalette(calcHash("paPodShade"), 65, 31, 65); - _palette->addBasePalette(calcHash("paKlayShade"), 0, 65, 0); - _palette->startFadeToPalette(12); - _palStatus = 2; - } - } else if (_asCar->getX() > 181) { - if (_palStatus != 1) { - _palette->addBasePalette(calcHash("paPodShade"), 65, 31, 65); - _palette->addBasePalette(calcHash("paKlayShade"), 0, 65, 0); - _palette->startFadeToPalette(12); - _palStatus = 1; - } - } else if (_palStatus != 0) { - _palette->addBasePalette(calcHash("paPodBlack"), 65, 31, 65); - _palette->addBasePalette(calcHash("paKlayBlack"), 0, 65, 0); - _palette->startFadeToPalette(12); - _palStatus = 0; - } -} - -uint32 Scene2703::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2005: - if (_which1 >= 0) - leaveScene(_which1); - break; - case 0x2006: - if (_which2 >= 0) - leaveScene(_which2); - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - } - return 0; -} - -Scene2704::Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint32 trackInfoId, int16 value, - const uint32 *staticSprites, const NRect *clipRect) - : Scene(vm, parentModule) { - - TrackInfo *tracks = _vm->_staticData->getTrackInfo(trackInfoId); - - SetMessageHandler(&Scene2704::handleMessage); - SetUpdateHandler(&Scene2704::update); - - setBackground(tracks->bgFilename); - setPalette(tracks->bgFilename); - - if (tracks->exPaletteFilename1) - _palette->addPalette(tracks->exPaletteFilename1, 0, 65, 0); - - if (tracks->exPaletteFilename2) - _palette->addPalette(tracks->exPaletteFilename2, 65, 31, 65); - - while (staticSprites && *staticSprites) - insertStaticSprite(*staticSprites++, 1100); - - insertScreenMouse(tracks->mouseCursorFilename); - - if (tracks->bgShadowFilename) { - _ssTrackShadowBackground = createSprite(tracks->bgShadowFilename); - addEntity(_ssTrackShadowBackground); - _asCar = insertSprite(this, 320, 240); - _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - } else { - _ssTrackShadowBackground = NULL; - _asCarShadow = NULL; - _asCar = insertSprite(this, 320, 240); - } - - _asCarConnector = insertSprite(_asCar); - _which1 = tracks->which1; - _which2 = tracks->which2; - _dataResource.load(tracks->dataResourceFilename); - _trackPoints = _dataResource.getPointArray(tracks->trackPointsName); - _asCar->setPathPoints(_trackPoints); - - if (which == _which2) { - NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1]; - sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); - if (testPoint.x > 0 && testPoint.x < 640 && testPoint.y > 0 && testPoint.y < 480) - sendMessage(_asCar, 0x2009, 0); - else - sendMessage(_asCar, 0x2007, 0); - } else { - NPoint testPoint = (*_trackPoints)[0]; - sendMessage(_asCar, 0x2002, 0); - if (testPoint.x > 0 && testPoint.x < 640 && testPoint.y > 0 && testPoint.y < 480) - sendMessage(_asCar, 0x2009, 0); - else - sendMessage(_asCar, 0x2008, 0); - } - - if (clipRect) { - _asCar->getClipRect() = *clipRect; - if (_asCarShadow) - _asCarShadow->getClipRect() = *clipRect; - if (_asCarTrackShadow) - _asCarTrackShadow->getClipRect() = *clipRect; - if (_asCarConnectorShadow) - _asCarConnectorShadow->getClipRect() = *clipRect; - if (_asCarConnector) - _asCarConnector->getClipRect() = *clipRect; - } - -} - -void Scene2704::update() { - Scene::update(); - if (_mouseClicked) { - sendPointMessage(_asCar, 0x2004, _mouseClickPos); - _mouseClicked = false; - } -} - -uint32 Scene2704::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2005: - if (_which1 >= 0) - leaveScene(_which1); - break; - case 0x2006: - if (_which2 >= 0) - leaveScene(_which2); - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - } - return 0; -} - -Scene2706::Scene2706(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _newTrackIndex(-1) { - - SetMessageHandler(&Scene2706::handleMessage); - - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22A0)); - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22C4)); - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22E8)); - - setBackground(0x18808B88); - setPalette(0x18808B88); - - _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); - _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); - - insertScreenMouse(0x08B8C180); - - _ssTrackShadowBackground = createSprite(0x18808B88); - addEntity(_ssTrackShadowBackground); - - _asCar = insertSprite(this, 320, 240); - _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _asCarConnector = insertSprite(_asCar); - _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); - - _dataResource.load(0x06000162); - - if (which == 5) - _currTrackIndex = 2; - else if (which == 6) - _currTrackIndex = 1; - else - _currTrackIndex = 0; - - _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); - _asCar->setPathPoints(_trackPoints); - - if (which == _tracks[_currTrackIndex]->which2) { - sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); - if (which == 5) - sendMessage(_asCar, 0x2007, 50); - else - sendMessage(_asCar, 0x2007, 150); - } else { - sendMessage(_asCar, 0x2002, 0); - if (which == 5) - sendMessage(_asCar, 0x2008, 50); - else - sendMessage(_asCar, 0x2008, 150); - } - -} - -uint32 Scene2706::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - moveCarToPoint(param.asPoint()); - break; - case 0x2005: - if (_newTrackIndex >= 0) { - if (_tracks[_currTrackIndex]->which1 < 0) - changeTrack(); - } else if (_tracks[_currTrackIndex]->which1 >= 0) - leaveScene(_tracks[_currTrackIndex]->which1); - break; - case 0x2006: - if (_newTrackIndex >= 0) { - if (_tracks[_currTrackIndex]->which2 < 0) - changeTrack(); - } else if (_tracks[_currTrackIndex]->which2 >= 0) - leaveScene(_tracks[_currTrackIndex]->which2); - break; - case 0x200D: - sendMessage(_parentModule, 0x200D, 0); - break; - } - return 0; -} - -void Scene2706::moveCarToPoint(NPoint pt) { - int minMatchTrackIndex, minMatchDistance; - _tracks.findTrackPoint(pt, minMatchTrackIndex, minMatchDistance, _dataResource); - if (minMatchTrackIndex >= 0 && minMatchTrackIndex != _currTrackIndex) { - _newTrackIndex = minMatchTrackIndex; - _newTrackDestX = pt.x; - if (_currTrackIndex == 0) - sendMessage(_asCar, 0x2003, _trackPoints->size() - 1); - else - sendMessage(_asCar, 0x2003, 0); - } else { - _newTrackIndex = -1; - sendMessage(_asCar, 0x2004, pt.x); - } -} - -void Scene2706::changeTrack() { - _currTrackIndex = _newTrackIndex; - _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); - _asCar->setPathPoints(_trackPoints); - if (_currTrackIndex == 0) - sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); - else - sendMessage(_asCar, 0x2002, 0); - sendMessage(_asCar, 0x2004, _newTrackDestX); - _newTrackIndex = -1; -} - -Scene2732::Scene2732(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule) { - - Sprite *tempSprite; - - setBackground(0x0220C041); - setPalette(0x0220C041); - insertScreenMouse(0x0C04502A); - setRectList(0x004AE360); - - insertKlaymen(108, 331); - setMessageList(0x004AE328); - - tempSprite = insertStaticSprite(0x50C22C48, 1100); - _klaymen->setClipRect(tempSprite->getDrawRect().x, 0, 640, 480); - -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module2700.h b/engines/neverhood/module2700.h deleted file mode 100644 index 5861c2e4b5..0000000000 --- a/engines/neverhood/module2700.h +++ /dev/null @@ -1,182 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE2700_H -#define NEVERHOOD_MODULE2700_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/module1600.h" - -namespace Neverhood { - -// Module2700 - -class Module2700 : public Module { -public: - Module2700(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module2700(); -protected: - int _sceneNum; - int _soundIndex; - bool _raidoMusicInitialized; - uint32 _scene2711StaticSprites[6]; - uint32 _musicFileHash; - void createScene(int sceneNum, int which); - void updateScene(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void createScene2703(int which, uint32 trackInfoId); - void createScene2704(int which, uint32 trackInfoId, int16 value, const uint32 *staticSprites = NULL, const NRect *clipRect = NULL); -}; - -class SsCommonTrackShadowBackground : public StaticSprite { -public: - SsCommonTrackShadowBackground(NeverhoodEngine *vm, uint32 fileHash); -}; - -class AsCommonCarShadow : public AnimatedSprite { -public: - AsCommonCarShadow(NeverhoodEngine *vm, AnimatedSprite *asCar, BaseSurface *shadowSurface, uint index); -protected: - uint _index; - AnimatedSprite *_asCar; - uint32 _animFileHash; - void update(); - void updateShadow(); -}; - -class AsCommonCarConnectorShadow : public AnimatedSprite { -public: - AsCommonCarConnectorShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, uint index); -protected: - uint _index; - Sprite *_asCar; - void update(); -}; - -class AsCommonCarTrackShadow : public AnimatedSprite { -public: - AsCommonCarTrackShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, int16 frameIndex); -protected: - Sprite *_asCar; - void update(); -}; - -class Scene2701 : public Scene { -public: - Scene2701(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - AsCommonCar *_asCar; - Sprite *_ssTrackShadowBackground; - Sprite *_asCarShadow; - Sprite *_asCarTrackShadow; - Sprite *_asCarConnectorShadow; - Sprite *_asCarConnector; - int _which1, _which2; - NPointArray *_trackPoints; - uint32 hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2702 : public Scene { -public: - Scene2702(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - AsCommonCar *_asCar; - Sprite *_ssTrackShadowBackground; - Sprite *_asCarShadow; - Sprite *_asCarTrackShadow; - Sprite *_asCarConnectorShadow; - int16 _newTrackDestX; - bool _isInLight; - int _currTrackIndex, _newTrackIndex; - bool _isUpperTrack; - Tracks _tracks; - NPointArray *_trackPoints; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void moveCarToPoint(NPoint pt); - void changeTrack(); -}; - -class Scene2703 : public Scene { -public: - Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint32 trackInfoId); -protected: - AsCommonCar *_asCar; - Sprite *_ssTrackShadowBackground; - Sprite *_asCarShadow; - Sprite *_asCarConnector; - Sprite *_asCarTrackShadow; - Sprite *_asCarConnectorShadow; - int _palStatus; - int _which1, _which2; - NPointArray *_trackPoints; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2704 : public Scene { -public: - Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint32 trackInfoId, int16 value, - const uint32 *staticSprites = NULL, const NRect *clipRect = NULL); -protected: - AsCommonCar *_asCar; - Sprite *_ssTrackShadowBackground; - Sprite *_asCarShadow; - Sprite *_asCarConnector; - Sprite *_asCarTrackShadow; - Sprite *_asCarConnectorShadow; - int _which1, _which2; - NPointArray *_trackPoints; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2706 : public Scene { -public: - Scene2706(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - AsCommonCar *_asCar; - Sprite *_ssTrackShadowBackground; - Sprite *_asCarShadow; - Sprite *_asCarConnector; - Sprite *_asCarTrackShadow; - Sprite *_asCarConnectorShadow; - int16 _newTrackDestX; - int _currTrackIndex, _newTrackIndex; - Tracks _tracks; - NPointArray *_trackPoints; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void moveCarToPoint(NPoint pt); - void changeTrack(); -}; - -class Scene2732 : public Scene { -public: - Scene2732(NeverhoodEngine *vm, Module *parentModule); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE2700_H */ diff --git a/engines/neverhood/module2800.cpp b/engines/neverhood/module2800.cpp deleted file mode 100644 index d81445cf50..0000000000 --- a/engines/neverhood/module2800.cpp +++ /dev/null @@ -1,3205 +0,0 @@ -/* 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/module2800.h" -#include "neverhood/gamemodule.h" -#include "neverhood/module1000.h" -#include "neverhood/module1200.h" -#include "neverhood/module1700.h" -#include "neverhood/module2200.h" -#include "neverhood/diskplayerscene.h" - -namespace Neverhood { - -Module2800::Module2800(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule), _musicResource(NULL) { - - _currentMusicFileHash = 0; - _vm->_soundMan->addMusic(0x64210814, 0xD2FA4D14); - setGlobalVar(V_RADIO_MOVE_DISH_VIDEO, 1); - - if (which < 0) { - createScene(_vm->gameState().sceneNum, which); - } else if (which == 2) { - createScene(4, 3); - } else if (which == 1) { - createScene(4, 1); - } else { - createScene(0, 0); - } - -} - -Module2800::~Module2800() { - if (_musicResource) { - _musicResource->unload(); - delete _musicResource; - } - _vm->_soundMan->deleteGroup(0x64210814); -} - -void Module2800::createScene(int sceneNum, int which) { - debug("Module2800::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _vm->_soundMan->stopMusic(0xD2FA4D14, 0, 0); - _childObject = new Scene2801(_vm, this, which); - break; - case 1: - _vm->gameState().sceneNum = 1; - _vm->_soundMan->stopMusic(0xD2FA4D14, 0, 0); - if (getGlobalVar(V_RADIO_ENABLED)) - _childObject = new Scene2802(_vm, this, which); - else - createStaticScene(0x000C6444, 0xC6440008); - break; - case 2: - _vm->gameState().sceneNum = 2; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - if (getGlobalVar(V_KLAYMEN_SMALL)) - _childObject = new Scene2803Small(_vm, this, which); - else - _childObject = new Scene2803(_vm, this, which); - break; - case 3: - _vm->gameState().sceneNum = 3; - _childObject = new Scene2804(_vm, this, which); - break; - case 4: - _vm->gameState().sceneNum = 4; - _vm->_soundMan->stopMusic(0xD2FA4D14, 0, 2); - _childObject = new Scene2805(_vm, this, which); - break; - case 5: - _vm->gameState().sceneNum = 5; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - _childObject = new Scene2806(_vm, this, which); - break; - case 6: - _vm->gameState().sceneNum = 6; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - _childObject = new Scene2807(_vm, this, which); - break; - case 7: - _vm->gameState().sceneNum = 7; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - _childObject = new Scene2808(_vm, this, 0); - break; - case 8: - _vm->gameState().sceneNum = 8; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - _childObject = new Scene2809(_vm, this, which); - break; - case 9: - _vm->gameState().sceneNum = 9; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - _childObject = new Scene2810(_vm, this, which); - break; - case 10: - _vm->gameState().sceneNum = 10; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - _childObject = new Scene2808(_vm, this, 1); - break; - case 11: - _vm->gameState().sceneNum = 11; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - _childObject = new Scene2812(_vm, this, which); - break; - case 12: - _vm->gameState().sceneNum = 12; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0x0000A245, 0x0A241008); - break; - case 13: - _vm->gameState().sceneNum = 13; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0x81C60635, 0x60631814); - break; - case 14: - _vm->gameState().sceneNum = 14; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0xCA811204, 0x11200CA0); - break; - case 15: - _vm->gameState().sceneNum = 15; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0x2D438A00, 0x38A042DC); - break; - case 16: - _vm->gameState().sceneNum = 16; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0x0A806204, 0x062000A0); - break; - case 17: - _vm->gameState().sceneNum = 17; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0x010F9284, 0xF9280018); - break; - case 18: - _vm->gameState().sceneNum = 18; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0x0100022B, 0x0022F018); - break; - case 19: - _vm->gameState().sceneNum = 19; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0x10866205, 0x66201100); - break; - case 20: - _vm->gameState().sceneNum = 20; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0x01C58000, 0x58004014); - break; - case 21: - _vm->gameState().sceneNum = 21; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - _childObject = new Scene2822(_vm, this, which); - break; - case 22: - _vm->gameState().sceneNum = 22; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0x9408121E, 0x8121A948); - break; - case 23: - _vm->gameState().sceneNum = 23; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0x048C0600, 0xC0604040); - break; - case 24: - _vm->gameState().sceneNum = 24; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - createStaticScene(0x04270A94, 0x70A9004A); - break; - case 25: - _vm->gameState().sceneNum = 25; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - if (getGlobalVar(V_SHRINK_LIGHTS_ON)) - createStaticScene(0x01600204, 0x0020001E); - else - createStaticScene(0x08611204, 0x1120008E); - break; - case 26: - _vm->gameState().sceneNum = 26; - _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); - _childObject = new DiskplayerScene(_vm, this, 4); - break; - case 1001: - _vm->_soundMan->stopMusic(0xD2FA4D14, 0, 0); - createSmackerScene(0x00800801, true, true, false); - break; - } - SetUpdateHandler(&Module2800::updateScene); - _childObject->handleUpdate(); -} - -void Module2800::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult != 2) { - if (_musicResource) { - _musicResource->unload(); - delete _musicResource; - _musicResource = NULL; - } - _currentMusicFileHash = 0; - } - if (_moduleResult == 1) { - createScene(2, 0); - } else if (_moduleResult == 2) { - createScene(1, 0); - } else { - leaveModule(0); - } - break; - case 1: - if (_moduleResult == 0) { - createScene(0, 2); - } else { - createScene(1001, -1); - } - break; - case 2: - if (_moduleResult == 1) - createScene(3, 0); - else if (_moduleResult == 2) - createScene(5, 0); - else if (_moduleResult == 3) - createScene(6, 0); - else if (_moduleResult == 4) - createScene(9, 0); - else if (_moduleResult == 5) - createScene(25, 0); - else - createScene(0, 1); - break; - case 3: - createScene(2, 1); - break; - case 4: - if (_moduleResult == 1) { - leaveModule(1); - } else { - createScene(11, 1); - } - break; - case 5: - if (_moduleResult == 1) { - createScene(7, 0); - } else { - createScene(2, 2); - } - break; - case 6: - createScene(2, 3); - break; - case 7: - createScene(5, _moduleResult); - break; - case 8: - if (_moduleResult == 1) - createScene(10, 0); - else - createScene(9, 4); - break; - case 9: - if (_moduleResult == 1) - createScene(11, 0); - else if (_moduleResult == 2) - createScene(2, 0); - else if (_moduleResult == 3) - createScene(24, 0); - else if (_moduleResult == 4) - createScene(8, 0); - else if (_moduleResult == 6) - createScene(2, 6); - else if (_moduleResult == 11) - createScene(12, 0); - else if (_moduleResult == 12) - createScene(13, 0); - else if (_moduleResult == 13) - createScene(14, 0); - else if (_moduleResult == 14) - createScene(15, 0); - else if (_moduleResult == 15) - createScene(16, 0); - else if (_moduleResult == 16) - createScene(17, 0); - else if (_moduleResult == 17) - createScene(18, 0); - else if (_moduleResult == 18) - createScene(19, 0); - else if (_moduleResult == 19) - createScene(20, 0); - else if (_moduleResult == 20) - createScene(21, 0); - else if (_moduleResult == 21) - createScene(22, 0); - else if (_moduleResult == 22) - createScene(23, 0); - else - createScene(2, 4); - break; - case 10: - createScene(8, _moduleResult); - break; - case 11: - if (_moduleResult == 1) - createScene(4, 0); - else if (_moduleResult == 2) - createScene(26, 0); - else if (_moduleResult == 3) - createScene(9, 5); - else - createScene(9, 1); - break; - case 12: - createScene(9, 11); - break; - case 13: - createScene(9, 12); - break; - case 14: - createScene(9, 13); - break; - case 15: - createScene(9, 14); - break; - case 16: - createScene(9, 15); - break; - case 17: - createScene(9, 16); - break; - case 18: - createScene(9, 17); - break; - case 19: - createScene(9, 18); - break; - case 20: - createScene(9, 19); - break; - case 21: - createScene(9, 20); - break; - case 22: - createScene(9, 21); - break; - case 23: - createScene(9, 22); - break; - case 24: - createScene(9, 3); - break; - case 25: - createScene(2, 5); - break; - case 26: - createScene(11, 2); - break; - case 1001: - createScene(1, -1); - break; - } - } else { - switch (_sceneNum) { - case 0: - updateMusic(true); - break; - case 1: - updateMusic(false); - break; - } - } -} - -void Module2800::updateMusic(bool halfVolume) { - - uint32 newMusicFileHash = _vm->_gameModule->getCurrRadioMusicFileHash(); - - if (!_musicResource) - _musicResource = new MusicResource(_vm); - - if (newMusicFileHash != _currentMusicFileHash) { - _currentMusicFileHash = newMusicFileHash; - if (_currentMusicFileHash != 0) { - _musicResource->load(_currentMusicFileHash); - _musicResource->setVolume(halfVolume ? 60 : 100); - _musicResource->play(0); - } else { - _musicResource->stop(0); - } - } else if (_currentMusicFileHash != 0) { - if (!_musicResource->isPlaying()) { - _musicResource->setVolume(halfVolume ? 60 : 100); - _musicResource->play(0); - } else { - _musicResource->setVolume(halfVolume ? 60 : 100); - } - } else { - _musicResource->stop(0); - } - -} - -Scene2801::Scene2801(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - Sprite *_sprite1; - Sprite *_sprite2; - - _vm->gameModule()->initRadioPuzzle(); - - SetMessageHandler(&Scene2801::handleMessage); - SetUpdateHandler(&Scene::update); - - // Display the disabled radio; only possible when the left door is open - if (!getGlobalVar(V_RADIO_ENABLED)) - insertStaticSprite(0x0001264C, 100); - - if (which < 0) { - insertKlaymen(194, 430); - setMessageList(0x004B6BB8); - } else if (which == 1) { - insertKlaymen(443, 398); - setMessageList(0x004B6BC0); - } else if (which == 2) { - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { - insertKlaymen(312, 432); - _klaymen->setDoDeltaX(1); - } else { - insertKlaymen(194, 432); - } - setMessageList(0x004B6C10); - } else { - insertKlaymen(0, 432); - setMessageList(0x004B6BB0); - } - - if (getGlobalVar(V_RADIO_ROOM_LEFT_DOOR)) { - setRectList(0x004B6CE0); - setBackground(0x01400666); - setPalette(0x01400666); - _paletteHash = 0x15021024; - _palette->addBasePalette(0x01400666, 0, 256, 0); - _sprite1 = insertStaticSprite(0x100CA0A8, 1100); - _sprite2 = insertStaticSprite(0x287C21A4, 1100); - _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite2->getDrawRect().x2(), 480); - insertScreenMouse(0x0066201C); - _asTape = insertSprite(this, 8, 1100, 302, 437, 0x9148A011); - addCollisionSprite(_asTape); - } else if (getGlobalVar(V_RADIO_ROOM_RIGHT_DOOR)) { - setRectList(0x004B6CD0); - setBackground(0x11E00684); - setPalette(0x11E00684); - _paletteHash = 0x15021024; - _palette->addBasePalette(0x11E00684, 0, 256, 0); - _sprite2 = insertStaticSprite(0x061601C8, 1100); - _klaymen->setClipRect(0, 0, _sprite2->getDrawRect().x2(), 480); - insertScreenMouse(0x00680116); - _asTape = insertSprite(this, 8, 1100, 302, 437, 0x01142428); - addCollisionSprite(_asTape); - } else { - setRectList(0x004B6CF0); - setBackground(0x030006E6); - setPalette(0x030006E6); - _paletteHash = 0x15021024; - _palette->addBasePalette(0x030006E6, 0, 256, 0); - _sprite2 = insertStaticSprite(0x273801CE, 1100); - _klaymen->setClipRect(0, 0, _sprite2->getDrawRect().x2(), 480); - insertScreenMouse(0x006E2038); - _asTape = insertSprite(this, 8, 1100, 302, 437, 0x9148A011); - addCollisionSprite(_asTape); - } - - addEntity(_palette); - - if (which == 1) { - _palette->addPalette(0xB103B604, 0, 65, 0); - _palette->addBasePalette(0xB103B604, 0, 65, 0); - } else { - _palette->addPalette(_paletteHash, 0, 65, 0); - _palette->addBasePalette(_paletteHash, 0, 65, 0); - } - -} - -Scene2801::~Scene2801() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); -} - -uint32 Scene2801::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4826: - if (sender == _asTape) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004B6C40); - } - break; - case 0x482A: - _palette->addBasePalette(0xB103B604, 0, 65, 0); - _palette->startFadeToPalette(12); - break; - case 0x482B: - _palette->addBasePalette(_paletteHash, 0, 65, 0); - _palette->startFadeToPalette(12); - break; - } - return messageResult; -} - -Scene2802::Scene2802(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _currTuneStatus(0), _countdown1(0), _countdown2(0) { - - SetMessageHandler(&Scene2802::handleMessage); - SetUpdateHandler(&Scene2802::update); - insertPuzzleMouse(0x008810A8, 20, 620); - _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, 0x8284C100, true, true, true)); - _currRadioMusicIndex = getGlobalVar(V_CURR_RADIO_MUSIC_INDEX); - // Need to go to the first frame first to load up the palette - _smackerPlayer->gotoFrame(0); - // Now we can actually set the current radio frame - _smackerPlayer->gotoFrame(_currRadioMusicIndex); - _vm->_soundMan->addSound(0x04360A18, 0x422630C2); - _vm->_soundMan->addSound(0x04360A18, 0x00632252); - _vm->_soundMan->addSound(0x04360A18, 0x00372241); - _vm->_soundMan->setSoundVolume(0x00372241, 60); - changeTuneStatus(0, 0); - _vm->_soundMan->playSoundLooping(0x00372241); -} - -Scene2802::~Scene2802() { - _vm->_soundMan->deleteSoundGroup(0x04360A18); - if (_currRadioMusicIndex == 0) { - setGlobalVar(V_RADIO_ROOM_LEFT_DOOR, 1); - setGlobalVar(V_RADIO_ROOM_RIGHT_DOOR, 0); - } else if (_currRadioMusicIndex == getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX)) { - setGlobalVar(V_RADIO_ROOM_LEFT_DOOR, 0); - setGlobalVar(V_RADIO_ROOM_RIGHT_DOOR, 1); - } else { - setGlobalVar(V_RADIO_ROOM_LEFT_DOOR, 0); - setGlobalVar(V_RADIO_ROOM_RIGHT_DOOR, 0); - } - setGlobalVar(V_CURR_RADIO_MUSIC_INDEX, _currRadioMusicIndex); -} - -void Scene2802::update() { - int prevTuneStatus = _currTuneStatus; - uint prevRadioMusicIndex = _currRadioMusicIndex; - - Scene::update(); - if (_countdown1 > 0) - --_countdown1; - else if (_currTuneStatus == 1) - _currTuneStatus = 3; - else if (_currTuneStatus == 4) - _currTuneStatus = 6; - - switch (_currTuneStatus) { - case 2: - if (_currRadioMusicIndex < 90) - incRadioMusicIndex(+1); - _currTuneStatus = 0; - break; - case 3: - if (_countdown2 > 0) - --_countdown2; - else if (_currRadioMusicIndex < 90) { - incRadioMusicIndex(+1); - _countdown2 = 1; - } else - _currTuneStatus = 0; - break; - case 5: - if (_currRadioMusicIndex > 0) - incRadioMusicIndex(-1); - _currTuneStatus = 0; - break; - case 6: - if (_countdown2 > 0) - --_countdown2; - else if (_currRadioMusicIndex > 0) { - incRadioMusicIndex(-1); - _countdown2 = 1; - } else - _currTuneStatus = 0; - break; - - } - - if (prevRadioMusicIndex != _currRadioMusicIndex) - _smackerPlayer->gotoFrame(_currRadioMusicIndex); - - if (prevTuneStatus != _currTuneStatus) - changeTuneStatus(prevTuneStatus, _currTuneStatus); - - //DEBUG>>> - //debug("_currRadioMusicIndex = %d; V_GOOD_RADIO_MUSIC_INDEX = %d", _currRadioMusicIndex, getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX)); - //DEBUG<<< - - if (getGlobalVar(V_RADIO_MOVE_DISH_VIDEO) && prevTuneStatus != _currTuneStatus && _currRadioMusicIndex != 0) { - setGlobalVar(V_RADIO_MOVE_DISH_VIDEO, 0); - leaveScene(1); - } - -} - -uint32 Scene2802::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - int prevTuneStatus = _currTuneStatus; - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { - leaveScene(0); - } else if (_currTuneStatus == 0) { - if (param.asPoint().x > 180 && param.asPoint().x < 300 && - param.asPoint().y > 130 && param.asPoint().y < 310) { - _currTuneStatus = 4; - } else if (param.asPoint().x > 300 && param.asPoint().x < 400 && - param.asPoint().y > 130 && param.asPoint().y < 310) { - _currTuneStatus = 1; - } - if (_currTuneStatus == 1 || _currTuneStatus == 4) { - _countdown1 = 8; - changeTuneStatus(0, _currTuneStatus); - } - } - break; - case 0x0002: - if (_countdown1 == 0) - _currTuneStatus = 0; - else { - if (_currTuneStatus == 1) - _currTuneStatus = 2; - else if (_currTuneStatus == 4) - _currTuneStatus = 5; - else - _currTuneStatus = 0; - _countdown1 = 0; - } - if (prevTuneStatus != _currTuneStatus) - changeTuneStatus(prevTuneStatus, _currTuneStatus); - break; - } - return 0; -} - -void Scene2802::incRadioMusicIndex(int delta) { - _currRadioMusicIndex += delta; - setGlobalVar(V_CURR_RADIO_MUSIC_INDEX, _currRadioMusicIndex); -} - -void Scene2802::changeTuneStatus(int prevTuneStatus, int newTuneStatus) { - - if (prevTuneStatus == 3 || prevTuneStatus == 6) { - _vm->_soundMan->stopSound(0x422630C2); - _vm->_soundMan->stopSound(0x00632252); - } - - if (newTuneStatus == 0) { - if (_vm->_gameModule->getCurrRadioMusicFileHash() != 0) - _vm->_soundMan->stopSound(0x00632252); - else - _vm->_soundMan->playSoundLooping(0x00632252); - } else if (newTuneStatus == 3 || newTuneStatus == 6) { - _vm->_soundMan->playSoundLooping(0x422630C2); - _vm->_soundMan->playSoundLooping(0x00632252); - } - -} - -AsScene2803LightCord::AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _fileHash1(fileHash1), _fileHash2(fileHash2), - _isPulled(false), _isBusy(false) { - - createSurface(1010, 28, 379); - SetUpdateHandler(&AnimatedSprite::update); - SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); - _x = x; - _y = y; - stIdle(); -} - -uint32 AsScene2803LightCord::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (!_isBusy && param.asInteger() == calcHash("ClickSwitch")) { - sendMessage(_parentScene, 0x480F, 0); - playSound(0, 0x4E1CA4A0); - } - break; - case 0x480F: - stPulled(); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -uint32 AsScene2803LightCord::hmPulled(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene2803LightCord::stPulled() { - _isBusy = false; - _isPulled = true; - startAnimation(_fileHash2, 0, -1); - SetMessageHandler(&AsScene2803LightCord::hmPulled); - NextState(&AsScene2803LightCord::stIdle); -} - -void AsScene2803LightCord::stIdle() { - _isPulled = false; - startAnimation(_fileHash1, 0, -1); - SetMessageHandler(&AsScene2803LightCord::handleMessage); -} - -void AsScene2803LightCord::setFileHashes(uint32 fileHash1, uint32 fileHash2) { - _fileHash1 = fileHash1; - _fileHash2 = fileHash2; - if (_isPulled) { - startAnimation(_fileHash2, _currFrameIndex, -1); - _isBusy = true; - } else { - startAnimation(_fileHash1, 0, -1); - } -} - -AsScene2803TestTubeOne::AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2) - : AnimatedSprite(vm, 1200), _fileHash1(fileHash1), _fileHash2(fileHash2) { - - createSurface1(fileHash1, 100); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2803TestTubeOne::handleMessage); - _x = 529; - _y = 326; -} - -uint32 AsScene2803TestTubeOne::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - if (param.asInteger()) - startAnimation(_fileHash2, 0, -1); - else - startAnimation(_fileHash1, 0, -1); - break; - } - return messageResult; -} - -AsScene2803Rope::AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x) - : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - - createSurface(990, 68, 476); - SetUpdateHandler(&AnimatedSprite::update); - SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); - SetMessageHandler(&AsScene2803Rope::handleMessage); - startAnimation(0x9D098C23, 35, 53); - NextState(&AsScene2803Rope::stReleased); - _x = x; - _y = -276; -} - -uint32 AsScene2803Rope::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - startAnimation(0x9D098C23, 50, -1); - SetMessageHandler(&AsScene2803Rope::hmReleased); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -uint32 AsScene2803Rope::hmReleased(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -void AsScene2803Rope::stReleased() { - startAnimation(0x8258A030, 0, 1); - NextState(&AsScene2803Rope::stHide); -} - -void AsScene2803Rope::stHide() { - stopAnimation(); - setVisible(false); -} - -Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _paletteArea(0) { - - static const uint32 kScene2803FileHashes1[] = { - 0, - 0x081000F1, - 0x08100171, - 0x08100271 - }; - - static const uint32 kScene2803FileHashes2[] = { - 0, - 0x286800D4, - 0x286806D4, - 0x28680AD4 - }; - - setGlobalVar(V_BEEN_SHRINKING_ROOM, 1); - _vm->gameModule()->initTestTubes1Puzzle(); - - SetMessageHandler(&Scene2803::handleMessage); - - loadDataResource(0x00900849); - - _background = new Background(_vm, 0); - _background->createSurface(0, 640, 480); - addBackground(_background); - - setPalette(0x412A423E); - addEntity(_palette); - - insertScreenMouse(0xA423A41A); - - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 0) { - _asTestTubeOne = (StaticSprite*)insertStaticSprite(0x66121222, 100); - } else { - _asTestTubeOne = (StaticSprite*)insertSprite( - kScene2803FileHashes1[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)], - kScene2803FileHashes2[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)]); - } - - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) - _asTestTubeTwo = (StaticSprite*)insertStaticSprite(0x64330236, 100); - - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) - _asTestTubeThree = (StaticSprite*)insertStaticSprite(0x2E4A22A2, 100); - - _asLightCord = insertSprite(this, 0x8FAD5932, 0x276E1A3D, 578, 200); - _sprite3 = (StaticSprite*)insertStaticSprite(0xA40EF2FB, 1100); - _sprite4 = (StaticSprite*)insertStaticSprite(0x0C03AA23, 1100); - _sprite5 = (StaticSprite*)insertStaticSprite(0x2A822E2E, 1100); - _sprite6 = (StaticSprite*)insertStaticSprite(0x2603A202, 1100); - _sprite7 = (StaticSprite*)insertStaticSprite(0x24320220, 1100); - _sprite8 = (StaticSprite*)insertStaticSprite(0x3C42022F, 1100); - _sprite9 = (StaticSprite*)insertStaticSprite(0x341A0237, 1100); - _sprite10 = insertStaticSprite(0x855820A3, 1200); - - _clipRectsFloor[0].x1 = 0; - _clipRectsFloor[0].y1 = 0; - _clipRectsFloor[0].x2 = 640; - _clipRectsFloor[0].y2 = _sprite8->getDrawRect().y2(); - - _clipRectsFloor[1].x1 = _sprite8->getDrawRect().x2(); - _clipRectsFloor[1].y1 = _sprite8->getDrawRect().y2(); - _clipRectsFloor[1].x2 = 640; - _clipRectsFloor[1].y2 = 480; - - _clipRectsStairs[0].x1 = _sprite5->getDrawRect().x; - _clipRectsStairs[0].y1 = 0; - _clipRectsStairs[0].x2 = _sprite5->getDrawRect().x2(); - _clipRectsStairs[0].y2 = _sprite5->getDrawRect().y2(); - - _clipRectsStairs[1].x1 = _sprite6->getDrawRect().x; - _clipRectsStairs[1].y1 = 0; - _clipRectsStairs[1].x2 = _sprite3->getDrawRect().x; - _clipRectsStairs[1].y2 = _sprite6->getDrawRect().y2(); - - _clipRectsStairs[2].x1 = _sprite3->getDrawRect().x; - _clipRectsStairs[2].y1 = 0; - _clipRectsStairs[2].x2 = _sprite4->getDrawRect().x2(); - _clipRectsStairs[2].y2 = 480; - - if (which < 0) { - insertKlaymen(302, 445, _clipRectsFloor, 2); - setMessageList(0x004B79F0); - klaymenFloor(); - } else if (which == 1) { - insertKlaymen(200, 445, _clipRectsFloor, 2); - setMessageList(0x004B79C8); - klaymenFloor(); - } else if (which == 3) { - NPoint pt = _dataResource.getPoint(0xC2A08694); - insertKlaymen(pt.x, pt.y, _clipRectsStairs, 3); - setMessageList(0x004B7A00); - klaymenStairs(); - } else if (which == 5) { - insertKlaymen(253, 298, _clipRectsStairs, 3); - setMessageList(0x004B7A00); - klaymenStairs(); - } else if (which == 6) { - _asRope = insertSprite(this, 384); - _asRope->setClipRect(0, 25, 640, 480); - insertKlaymen(384, 0, _clipRectsFloor, 2); - sendEntityMessage(_klaymen, 0x1014, _asRope); - _klaymen->setClipRect(0, 25, 640, 480); - setMessageList(0x004B7A78); - klaymenFloor(); - } else if (which == 2) { - insertKlaymen(400, 445, _clipRectsFloor, 2); - setMessageList(0x004B79F8); - klaymenFloor(); - } else { - insertKlaymen(50, 231, _clipRectsStairs, 3); - setMessageList(0x004B79C0); - klaymenStairs(); - } - - changeBackground(); - -} - -void Scene2803::upKlaymenStairs() { - if (_klaymen->getX() < 350) { - setPaletteArea0(); - } else { - setPaletteArea1(); - } - Scene::update(); -} - -uint32 Scene2803::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x480F: - toggleBackground(); - // NOTE Intentional fall-through - case 0x100D: - if (param.asInteger() == 0x84251F82) - setMessageList(0x004B7A50); - else if (param.asInteger() == 0x4254A2D2) - setMessageList(0x004B7A58); - else if (param.asInteger() == 0xE90A40A0) - setMessageList(0x004B7A08); - else if (param.asInteger() == 0x482D1210) - setMessageList(0x004B7A30); - else if (param.asInteger() == 0x802402B2) { - sendEntityMessage(_klaymen, 0x1014, _asLightCord); - setMessageList(0x004B7A68); - } else if (param.asInteger() == 0x9626F390) - setMessageList(0x004B7A88); - break; - case 0x482A: - klaymenStairs(); - setPaletteArea1(); - break; - case 0x482B: - klaymenFloor(); - setPaletteArea0(); - break; - } - return messageResult; -} - -void Scene2803::klaymenStairs() { - SetUpdateHandler(&Scene2803::upKlaymenStairs); - _klaymen->getSurface()->setClipRects(_clipRectsStairs, 3); - sendMessage(_klaymen, 0x482C, 0xE5A48297); - _sprite3->setVisible(true); - _sprite4->setVisible(true); - _sprite5->setVisible(true); - _sprite6->setVisible(true); - _sprite7->setVisible(true); - _sprite8->setVisible(false); - _sprite9->setVisible(false); -} - -void Scene2803::klaymenFloor() { - SetUpdateHandler(&Scene::update); - _klaymen->getSurface()->setClipRects(_clipRectsFloor, 2); - sendMessage(_klaymen, 0x482C, 0); - _sprite3->setVisible(false); - _sprite4->setVisible(false); - _sprite5->setVisible(false); - _sprite6->setVisible(false); - _sprite7->setVisible(false); - _sprite8->setVisible(true); - _sprite9->setVisible(true); -} - -void Scene2803::toggleBackground() { - setGlobalVar(V_SHRINK_LIGHTS_ON, getGlobalVar(V_SHRINK_LIGHTS_ON) ? 0 : 1); - changeBackground(); -} - -void Scene2803::changeBackground() { - if (getGlobalVar(V_SHRINK_LIGHTS_ON)) { - _asLightCord->setFileHashes(0x8FAD5932, 0x276E1A3D); - _background->load(0x412A423E); - _palette->addPalette(0x412A423E, 0, 256, 0); - _palette->addBasePalette(0x412A423E, 0, 256, 0); - _sprite3->loadSprite(0xA40EF2FB); - _sprite4->loadSprite(0x0C03AA23); - _sprite5->loadSprite(0x2A822E2E); - _sprite6->loadSprite(0x2603A202); - _sprite7->loadSprite(0x24320220); - _mouseCursor->load(0xA423A41A); - _mouseCursor->updateCursor(); - _sprite8->loadSprite(0x3C42022F); - _sprite9->loadSprite(0x341A0237); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 0) - _asTestTubeOne->loadSprite(0x66121222); - else - sendMessage(_asTestTubeOne, 0x2000, 0); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) - _asTestTubeTwo->loadSprite(0x64330236); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) - _asTestTubeThree->loadSprite(0x2E4A22A2); - _sprite10->setVisible(true); - } else { - _asLightCord->setFileHashes(0xAFAD591A, 0x276E321D); - _background->load(0x29800A01); - _palette->addPalette(0x29800A01, 0, 256, 0); - _palette->addBasePalette(0x29800A01, 0, 256, 0); - _sprite3->loadSprite(0x234340A0); - _sprite4->loadSprite(0x16202200); - _sprite5->loadSprite(0x1030169A); - _sprite6->loadSprite(0x1600A6A8); - _sprite7->loadSprite(0xD0802EA0); - _mouseCursor->load(0x00A05290); - _mouseCursor->updateCursor(); - _sprite8->loadSprite(0x108012C1); - _sprite9->loadSprite(0x708072E0); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) != 0) - sendMessage(_asTestTubeOne, 0x2000, 1); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) - _asTestTubeTwo->loadSprite(0xD48077A0); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) - _asTestTubeThree->loadSprite(0x30022689); - _sprite10->setVisible(false); - } - updatePaletteArea(); -} - -void Scene2803::setPaletteArea0() { - if (_paletteArea != 0) { - _paletteArea = 0; - updatePaletteArea(); - } -} - -void Scene2803::setPaletteArea1() { - if (_paletteArea != 1) { - _paletteArea = 1; - updatePaletteArea(); - } -} - -void Scene2803::updatePaletteArea() { - uint32 fadePaletteHash; - if (getGlobalVar(V_SHRINK_LIGHTS_ON)) - fadePaletteHash = (_paletteArea == 1) ? 0xB103B604 : 0x412A423E; - else - fadePaletteHash = (_paletteArea == 1) ? 0x0263D144 : 0x29800A01; - _palette->addBasePalette(fadePaletteHash, 0, 64, 0); - _palette->startFadeToPalette(12); -} - -Scene2803Small::Scene2803Small(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _paletteArea(0) { - - static const uint32 kScene2803SmallFileHashes1[] = { - 0, 0x081000F1, 0x08100171, 0x08100271 - }; - - static const uint32 kScene2803SmallFileHashes2[] = { - 0, 0x286800D4, 0x286806D4, 0x28680AD4 - }; - - SetMessageHandler(&Scene2803Small::handleMessage); - - loadDataResource(0x81120132); - insertScreenMouse(0x00A05290); - - insertSprite(this, 0xAFAD591A, 0x276E321D, 578, 200); - - if (getGlobalVar(V_SHRINK_LIGHTS_ON)) { - setBackground(0x412A423E); - setPalette(0x412A423E); - _palette->addBasePalette(0x412A423E, 0, 256, 0); - addEntity(_palette); - _sprite1 = insertStaticSprite(0x0C03AA23, 1100); - _sprite2 = insertStaticSprite(0x24320220, 1100); - _sprite3 = insertStaticSprite(0x1A032204, 1100); - _sprite4 = insertStaticSprite(0x18032204, 1100); - _sprite5 = insertStaticSprite(0x34422912, 1100); - _sprite6 = insertStaticSprite(0x3C42022F, 1100); - _sprite7 = insertStaticSprite(0x341A0237, 1100); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 0) - insertStaticSprite(0x66121222, 100); - else - insertSprite(kScene2803SmallFileHashes1[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)], 100, 529, 326); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) - insertStaticSprite(0x64330236, 100); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) - insertStaticSprite(0x2E4A22A2, 100); - } else { - setBackground(0x29800A01); - setPalette(0x29800A01); - _palette->addBasePalette(0x29800A01, 0, 256, 0); - addEntity(_palette); - _sprite1 = insertStaticSprite(0x16202200, 1100); - _sprite2 = insertStaticSprite(0xD0802EA0, 1100); - _sprite3 = insertStaticSprite(0x780C2E30, 1100); - _sprite4 = insertStaticSprite(0x700C2E30, 1100); - _sprite5 = insertStaticSprite(0x102CE6E1, 900); - _sprite6 = insertStaticSprite(0x108012C1, 1100); - _sprite7 = insertStaticSprite(0x708072E0, 1100); - insertStaticSprite(0x90582EA4, 100); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) != 0) - insertSprite(kScene2803SmallFileHashes2[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)], 100, 529, 326); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) - insertStaticSprite(0xD48077A0, 100); - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) - insertStaticSprite(0x30022689, 100); - } - - _sprite6->setVisible(false); - _sprite7->setVisible(false); - - if (which < 0) { - insertKlaymen(479, 435); - klaymenFloor(); - setMessageList(0x004B60D8); - } else if (which == 3) { - NPoint pt = _dataResource.getPoint(0x096520ED); - insertKlaymen(pt.x, pt.y); - klaymenSlope(); - setMessageList(0x004B6100); - _klaymen->setRepl(64, 0); - } else if (which == 4) { - NPoint pt = _dataResource.getPoint(0x20C6238D); - insertKlaymen(pt.x, pt.y); - klaymenSlope(); - setMessageList(0x004B60F8); - _klaymen->setRepl(64, 0); - } else if (which == 5) { - NPoint pt = _dataResource.getPoint(0x2146690D); - insertKlaymen(pt.x, pt.y); - klaymenSlope(); - setMessageList(0x004B6100); - _klaymen->setRepl(64, 0); - } else if (which == 2) { - NPoint pt = _dataResource.getPoint(0x104C03ED); - insertKlaymen(pt.x, pt.y); - klaymenFloor(); - setMessageList(0x004B6138); - } else { - insertKlaymen(135, 444); - klaymenFloor(); - setMessageList(0x004B60E0, false); - _sprite6->setVisible(true); - _sprite7->setVisible(true); - } - -} - -uint32 Scene2803Small::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0xB4E4884C) { - setMessageList(0x004B6180); - } else if (param.asInteger() == 0xB1FDAB2E) { - NPoint pt = _dataResource.getPoint(0x0D84A1AD); - _klaymen->setX(pt.x); - _klaymen->setY(pt.y); - _klaymen->updateBounds(); - klaymenFloor(); - _klaymen->setClipRect(517, 401, 536, 480); - setMessageList(0x004B6198); - } else if (param.asInteger() == 0xB00C7C48) { - setMessageList(0x004B6108); - } else if (param.asInteger() == 0x61F64346) { - setMessageList(0x004B6150); - } else if (param.asInteger() == 0xAC69A28D) { - setMessageList(0x004B6168); - } else if (param.asInteger() == 0x00086212) { - _klaymen->setClipRect(0, 0, 560, 315); - _klaymen->setX(560); - _klaymen->setY(315); - _klaymen->updateBounds(); - klaymenSlope(); - setMessageList(0x004B61A0); - } else if (param.asInteger() == 0x002CAA68) { - setMessageList(0x004B61A8); - } - break; - case 0x482A: - if (_klaymen->getX() < 200) { - setPaletteArea3(); - } else if (_klaymen->getX() < 500) { - setSurfacePriority(_sprite5->getSurface(), 1100); - sendMessage(_klaymen, 0x482C, 0); - setPaletteArea2(); - } else { - _klaymen->setClipRect(517, 401, 536, 480); - setPaletteArea2(); - } - break; - case 0x482B: - _sprite6->setVisible(false); - _sprite7->setVisible(false); - _klaymen->setClipRect(0, 0, 640, 480); - setSurfacePriority(_sprite5->getSurface(), 900); - sendMessage(_klaymen, 0x482C, 0x2086222D); - break; - } - return 0; -} - -void Scene2803Small::upKlaymenSlope() { - if (_klaymen->getX() < 388) { - _klaymen->setClipRect(_sprite3->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); - setPaletteArea0(); - } else if (_klaymen->getX() < 500) { - _klaymen->setClipRect(0, 0, _sprite1->getDrawRect().x2(), _sprite1->getDrawRect().y2()); - setPaletteArea1(); - } - Scene::update(); -} - -void Scene2803Small::upKlaymenFloor() { - if (_klaymen->getX() > 194 && _klaymen->getX() < 273) - setPaletteArea2(); - else if (_klaymen->getX() > 155 && _klaymen->getX() < 300) - setPaletteArea0(); - Scene::update(); -} - -void Scene2803Small::klaymenSlope() { - SetUpdateHandler(&Scene2803Small::upKlaymenSlope); - sendMessage(_klaymen, 0x482C, 0x23C630D9); - _klaymen->setClipRect(0, 0, _sprite1->getDrawRect().x2(), _sprite1->getDrawRect().y2()); - _klaymen->setRepl(64, 0); - _sprite1->setVisible(true); -} - -void Scene2803Small::klaymenFloor() { - SetUpdateHandler(&Scene2803Small::upKlaymenFloor); - sendMessage(_klaymen, 0x482C, 0x2086222D); - _klaymen->setClipRect(0, 0, 640, 480); - _klaymen->clearRepl(); - _sprite1->setVisible(false); -} - -void Scene2803Small::setPaletteArea0() { - if (_paletteArea != 0) { - _paletteArea = 0; - updatePaletteArea(false); - } -} - -void Scene2803Small::setPaletteArea1() { - if (_paletteArea != 1) { - _paletteArea = 1; - updatePaletteArea(false); - } -} - -void Scene2803Small::setPaletteArea2() { - if (_paletteArea != 2) { - _paletteArea = 2; - updatePaletteArea(false); - } -} - -void Scene2803Small::setPaletteArea3() { - if (_paletteArea != 3) { - _paletteArea = 3; - updatePaletteArea(true); - } -} - -void Scene2803Small::updatePaletteArea(bool instantly) { - if (getGlobalVar(V_SHRINK_LIGHTS_ON)) { - switch (_paletteArea) { - case 1: - _palette->addBasePalette(0x0A938204, 0, 64, 0); - break; - case 2: - _palette->addBasePalette(0xB103B604, 0, 64, 0); - break; - case 3: - _palette->fillBaseBlack(0, 64); - break; - default: - _palette->addBasePalette(0x412A423E, 0, 64, 0); - break; - } - } else { - switch (_paletteArea) { - case 2: - _palette->addBasePalette(0x0263D144, 0, 64, 0); - break; - case 3: - _palette->fillBaseBlack(0, 64); - break; - default: - _palette->addBasePalette(0x29800A01, 0, 64, 0); - break; - } - } - _palette->startFadeToPalette(instantly ? 0 : 12); -} - -SsScene2804RedButton::SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene) - : StaticSprite(vm, 900), _countdown(0), _parentScene(parentScene) { - - loadSprite(getGlobalVar(V_SHRINK_LIGHTS_ON) ? 0x51A10202 : 0x11814A21, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); - setVisible(false); - SetUpdateHandler(&SsScene2804RedButton::update); - SetMessageHandler(&SsScene2804RedButton::handleMessage); - loadSound(0, 0x44241240); -} - -void SsScene2804RedButton::update() { - updatePosition(); - if (_countdown != 0 && (--_countdown) == 0) { - setVisible(false); - } -} - -uint32 SsScene2804RedButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_countdown == 0 && !_parentScene->isWorking()) { - playSound(0); - setVisible(true); - _countdown = 4; - sendMessage(_parentScene, 0x2000, 0); - } - messageResult = 1; - break; - } - return messageResult; -} - -SsScene2804LightCoil::SsScene2804LightCoil(NeverhoodEngine *vm) - : StaticSprite(vm, 900) { - - loadSprite(0x8889B008, kSLFDefDrawOffset | kSLFDefPosition, 400); - setVisible(false); - SetMessageHandler(&SsScene2804LightCoil::handleMessage); -} - -uint32 SsScene2804LightCoil::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2002: - setVisible(true); - updatePosition(); - messageResult = 1; - break; - case 0x2003: - setVisible(false); - updatePosition(); - messageResult = 1; - break; - } - return messageResult; -} - -SsScene2804LightTarget::SsScene2804LightTarget(NeverhoodEngine *vm) - : StaticSprite(vm, 900) { - - loadSprite(0x06092132, kSLFDefDrawOffset | kSLFDefPosition, 400); - setVisible(false); - SetMessageHandler(&SsScene2804LightTarget::handleMessage); -} - -uint32 SsScene2804LightTarget::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2004: - setVisible(true); - updatePosition(); - messageResult = 1; - break; - case 0x2005: - setVisible(false); - updatePosition(); - messageResult = 1; - break; - } - return messageResult; -} - -SsScene2804Flash::SsScene2804Flash(NeverhoodEngine *vm) - : StaticSprite(vm, 900) { - - loadSprite(0x211003A0, kSLFDefDrawOffset | kSLFDefPosition, 400); - setVisible(false); - loadSound(0, 0xCB36BA54); -} - -void SsScene2804Flash::show() { - setVisible(true); - updatePosition(); - playSound(0); -} - -SsScene2804BeamCoilBody::SsScene2804BeamCoilBody(NeverhoodEngine *vm) - : StaticSprite(vm, 900) { - - loadSprite(0x9A816000, kSLFDefDrawOffset | kSLFDefPosition, 400); - setVisible(false); -} - -AsScene2804CrystalWaves::AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex) - : AnimatedSprite(vm, 1100), _crystalIndex(crystalIndex) { - - static const NPoint kAsScene2804CrystalWavesPoints[] = { - {323, 245}, - {387, 76}, - {454, 260}, - {527, 70} - }; - - _x = kAsScene2804CrystalWavesPoints[crystalIndex].x; - _y = kAsScene2804CrystalWavesPoints[crystalIndex].y; - createSurface1(0x840C41F0, 1200); - if (crystalIndex & 1) - setDoDeltaY(1); - setVisible(false); - _needRefresh = true; - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&Sprite::handleMessage); -} - -void AsScene2804CrystalWaves::show() { - setVisible(true); - startAnimation(0x840C41F0, 0, -1); -} - -void AsScene2804CrystalWaves::hide() { - setVisible(false); - stopAnimation(); -} - -static const int16 kAsScene2804CrystalFrameNums[] = { - 0, 6, 2, 8, 1, 10, 0, 0 -}; - -static const uint32 kAsScene2804CrystalFileHashes[] = { - 0x000540B0, - 0x001280D0, - 0x003D0010, - 0x00620190, - 0x00DC0290 -}; - -AsScene2804Crystal::AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex) - : AnimatedSprite(vm, 1100), _asCrystalWaves(asCrystalWaves), _crystalIndex(crystalIndex), _isShowing(false) { - - static const NPoint kAsScene2804CrystalPoints[] = { - {204, 196}, - {272, 316}, - {334, 206}, - {410, 334}, - {470, 180} - }; - - _colorNum = (int16)getSubVar(VA_CURR_CRYSTAL_COLORS, crystalIndex); - _isLightOn = getGlobalVar(V_SHRINK_LIGHTS_ON) != 0; - if (_isLightOn) { - _x = kAsScene2804CrystalPoints[crystalIndex].x; - _y = kAsScene2804CrystalPoints[crystalIndex].y; - createSurface1(0x108DFB12, 1200); - startAnimation(0x108DFB12, kAsScene2804CrystalFrameNums[_colorNum], -1); - _needRefresh = true; - _newStickFrameIndex = kAsScene2804CrystalFrameNums[_colorNum]; - } else { - _x = 320; - _y = 240; - createSurface1(kAsScene2804CrystalFileHashes[crystalIndex], 1200); - startAnimation(kAsScene2804CrystalFileHashes[crystalIndex], _colorNum, -1); - setVisible(false); - _needRefresh = true; - _newStickFrameIndex = _colorNum; - } - loadSound(0, 0x725294D4); - SetUpdateHandler(&AnimatedSprite::update); -} - -void AsScene2804Crystal::show() { - if (!_isLightOn) { - setVisible(true); - _isShowing = true; - if (_asCrystalWaves) - _asCrystalWaves->show(); - playSound(0); - } -} - -void AsScene2804Crystal::hide() { - if (!_isLightOn) { - setVisible(false); - _isShowing = false; - if (_asCrystalWaves) - _asCrystalWaves->hide(); - } -} - -void AsScene2804Crystal::activate() { - if (!_isShowing) { - int16 frameNum = kAsScene2804CrystalFrameNums[_colorNum]; - _colorNum++; - if (_colorNum >= 6) - _colorNum = 0; - if (_isLightOn) { - startAnimation(0x108DFB12, frameNum, kAsScene2804CrystalFrameNums[_colorNum]); - _playBackwards = kAsScene2804CrystalFrameNums[_colorNum] < _colorNum; - _newStickFrameIndex = kAsScene2804CrystalFrameNums[_colorNum]; - } else { - startAnimation(kAsScene2804CrystalFileHashes[_crystalIndex], _colorNum, -1); - _newStickFrameIndex = _colorNum; - } - setSubVar(VA_CURR_CRYSTAL_COLORS, _crystalIndex, _colorNum); - } -} - -SsScene2804CrystalButton::SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex) - : StaticSprite(vm, 900), _countdown(0), _parentScene(parentScene), _asCrystal(asCrystal), _crystalIndex(crystalIndex) { - - static const uint32 kSsScene2804CrystalButtonFileHashes1[] = { - 0x911101B0, - 0x22226001, - 0x4444A362, - 0x888925A4, - 0x11122829 - }; - - static const uint32 kSsScene2804CrystalButtonFileHashes2[] = { - 0xB500A1A0, - 0x6A012021, - 0xD4022322, - 0xA8042525, - 0x5008292B - }; - - loadSprite(getGlobalVar(V_SHRINK_LIGHTS_ON) ? kSsScene2804CrystalButtonFileHashes1[crystalIndex] : kSsScene2804CrystalButtonFileHashes2[crystalIndex], - kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); - setVisible(false); - loadSound(0, 0x44045140); - SetUpdateHandler(&SsScene2804CrystalButton::update); - SetMessageHandler(&SsScene2804CrystalButton::handleMessage); -} - -void SsScene2804CrystalButton::update() { - updatePosition(); - if (_countdown != 0 && (--_countdown) == 0) { - setVisible(false); - } -} - -uint32 SsScene2804CrystalButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_countdown == 0 && !_parentScene->isWorking()) { - playSound(0); - setVisible(true); - _countdown = 4; - _asCrystal->activate(); - } - messageResult = 1; - break; - } - return messageResult; -} - -AsScene2804BeamCoil::AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody) - : AnimatedSprite(vm, 1400), _parentScene(parentScene), _ssBeamCoilBody(ssBeamCoilBody), _countdown(0) { - - createSurface1(0x00494891, 1000); - _x = 125; - _y = 184; - setVisible(false); - _needRefresh = true; - AnimatedSprite::updatePosition(); - loadSound(0, 0x6352F051); - _vm->_soundMan->addSound(0xC5EA0B28, 0xEF56B094); - SetUpdateHandler(&AsScene2804BeamCoil::update); - SetMessageHandler(&AsScene2804BeamCoil::handleMessage); -} - -AsScene2804BeamCoil::~AsScene2804BeamCoil() { - _vm->_soundMan->deleteSoundGroup(0xC5EA0B28); -} - -void AsScene2804BeamCoil::update() { - updateAnim(); - updatePosition(); - if (_countdown != 0 && (--_countdown) == 0) { - sendMessage(_parentScene, 0x2001, 0); - } -} - -uint32 AsScene2804BeamCoil::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2002: - show(); - _countdown = 92; - messageResult = 1; - break; - case 0x2003: - hide(); - messageResult = 1; - break; - } - return messageResult; -} - -void AsScene2804BeamCoil::show() { - _ssBeamCoilBody->setVisible(true); - setVisible(true); - startAnimation(0x00494891, 0, -1); - playSound(0); - SetMessageHandler(&AsScene2804BeamCoil::hmBeaming); - NextState(&AsScene2804BeamCoil::stBeaming); -} - -void AsScene2804BeamCoil::hide() { - stopAnimation(); - SetMessageHandler(&AsScene2804BeamCoil::handleMessage); - setVisible(false); - _ssBeamCoilBody->setVisible(false); - _vm->_soundMan->stopSound(0xEF56B094); -} - -void AsScene2804BeamCoil::stBeaming() { - startAnimation(0x00494891, 93, -1); - NextState(&AsScene2804BeamCoil::stBeaming); - _vm->_soundMan->playSoundLooping(0xEF56B094); -} - -uint32 AsScene2804BeamCoil::hmBeaming(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -AsScene2804BeamTarget::AsScene2804BeamTarget(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1400) { - - createSurface1(0x03842000, 1000); - _x = 475; - _y = 278; - setVisible(false); - _needRefresh = true; - updatePosition(); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2804BeamTarget::handleMessage); -} - -uint32 AsScene2804BeamTarget::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2004: - setVisible(true); - startAnimation(0x03842000, 0, -1); - messageResult = 1; - break; - case 0x2005: - setVisible(false); - stopAnimation(); - messageResult = 1; - break; - } - return messageResult; -} - -Scene2804::Scene2804(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _countdown1(0), _countdown2(0), _countdown3(0), - _beamStatus(0), _isSolved(false), _isWorking(false) { - - _vm->gameModule()->initCrystalColorsPuzzle(); - - SetMessageHandler(&Scene2804::handleMessage); - SetUpdateHandler(&Scene2804::update); - - if (getGlobalVar(V_SHRINK_LIGHTS_ON)) { - setBackground(0xA1D03005); - setPalette(0xA1D03005); - addEntity(_palette); - insertPuzzleMouse(0x03001A15, 20, 620); - _asCoil = insertSprite(); - _asTarget = insertSprite(); - } else { - SsScene2804BeamCoilBody *ssBeamCoilBody; - setBackground(0x01C01414); - setPalette(0x01C01414); - addEntity(_palette); - insertPuzzleMouse(0x01410014, 20, 620); - ssBeamCoilBody = insertSprite(); - _asCoil = insertSprite(this, ssBeamCoilBody); - _asTarget = insertSprite(); - _ssFlash = insertSprite(); - } - - _ssRedButton = insertSprite(this); - addCollisionSprite(_ssRedButton); - - for (uint crystalIndex = 0; crystalIndex < 5; crystalIndex++) { - AsScene2804CrystalWaves *asCrystalWaves = NULL; - if (crystalIndex < 4 && getGlobalVar(V_SHRINK_LIGHTS_ON) == 0) - asCrystalWaves = insertSprite(crystalIndex); - _asCrystals[crystalIndex] = insertSprite(asCrystalWaves, crystalIndex); - _ssCrystalButtons[crystalIndex] = insertSprite(this, _asCrystals[crystalIndex], crystalIndex); - addCollisionSprite(_ssCrystalButtons[crystalIndex]); - } - -} - -uint32 Scene2804::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { - leaveScene(0); - } - break; - case 0x2000: - _isWorking = true; - sendMessage(_asCoil, 0x2002, 0); - if (getGlobalVar(V_SHRINK_LIGHTS_ON)) { - sendMessage(_asTarget, 0x2004, 0); - _countdown2 = 48; - } - break; - case 0x2001: - _countdown3 = 2; - _isSolved = true; - _beamStatus = 0; - for (uint index = 0; index < 5; index++) - if (_asCrystals[index]->getColorNum() != (int16)getSubVar(VA_GOOD_CRYSTAL_COLORS, index)) - _isSolved = false; - _countdown2 = 48; - break; - } - return 0; -} - -void Scene2804::update() { - - Scene::update(); - - if (_countdown1 != 0 && (--_countdown1) == 0) { - leaveScene(0); - } - - if (_countdown2 != 0 && (--_countdown2) == 0) { - _isWorking = false; - sendMessage(_asCoil, 0x2003, 0); - sendMessage(_asTarget, 0x2005, 0); - for (uint index = 0; index < 5; index++) - _asCrystals[index]->hide(); - } - - if (_countdown3 != 0 && (--_countdown3) == 0) { - if (_beamStatus == 5) { - sendMessage(_asTarget, 0x2004, 0); - if (_isSolved) { - _palette->fillBaseWhite(0, 256); - _palette->startFadeToPalette(18); - setGlobalVar(V_KLAYMEN_SMALL, 1); - _countdown1 = 48; - } - } else if (_beamStatus == 6) { - if (_isSolved) - _ssFlash->show(); - } else { - _asCrystals[_beamStatus]->show(); - } - _beamStatus++; - if (_beamStatus < 6) - _countdown3 = 2; - else if (_beamStatus < 7) - _countdown3 = 4; - } - -} - -Scene2805::Scene2805(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - SetMessageHandler(&Scene2805::handleMessage); - - setBackground(0x08021E04); - setPalette(0x08021E04); - _palette->addPalette(0x8A6B1F91, 0, 65, 0); - insertScreenMouse(0x21E00088); - - _sprite1 = insertStaticSprite(0x008261E7, 1100); - _sprite2 = insertStaticSprite(0x020CE421, 1100); - - if (which < 0) { - insertKlaymen(380, 338); - setMessageList(0x004AE1C8); - sendMessage(this, 0x2000, 0); - } else if (which == 1) { - insertKlaymen(493, 338); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004AE1D0, false); - sendMessage(this, 0x2000, 1); - } else if (which == 2) { - insertKlaymen(493, 338); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004AE288, false); - sendMessage(this, 0x2000, 1); - } else if (which == 3) { - insertKlaymen(493, 338); - sendMessage(_klaymen, 0x2000, 1); - setMessageList(0x004AE1E0, false); - sendMessage(this, 0x2000, 1); - } else { - insertKlaymen(340, 338); - setMessageList(0x004AE1C0); - sendMessage(this, 0x2000, 0); - } - - _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite2->getDrawRect().x2(), 480); - -} - -uint32 Scene2805::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - if (param.asInteger()) { - setRectList(0x004AE318); - _klaymen->setKlaymenIdleTable3(); - } else { - setRectList(0x004AE308); - _klaymen->setKlaymenIdleTable1(); - } - break; - } - return 0; -} - -AsScene2806Spew::AsScene2806Spew(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1200) { - - createSurface1(0x04211490, 1200); - _x = 378; - _y = 423; - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2806Spew::handleMessage); - setDoDeltaX(1); - setVisible(false); -} - -uint32 AsScene2806Spew::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - playSound(0, 0x48640244); - startAnimation(0x04211490, 0, -1); - setVisible(true); - break; - case 0x3002: - stopAnimation(); - setVisible(false); - break; - } - return messageResult; -} - -Scene2806::Scene2806(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - Sprite *tempSprite; - - which = 3; - - SetMessageHandler(&Scene2806::handleMessage); - SetUpdateHandler(&Scene2806::update); - - loadDataResource(0x98182003); - loadHitRectList(); - - _pointList = _dataResource.getPointArray(0x3606A422); - - insertScreenMouse(0x22114C13); - setBackground(0xC1B22110); - setPalette(0xC1B22110); - - _sprite1 = insertStaticSprite(0xA21F82CB, 1100); - _clipRects[0].x1 = _sprite1->getDrawRect().x; - _clipRects[0].y1 = _sprite1->getDrawRect().y; - _clipRects[0].x2 = _sprite1->getDrawRect().x2(); - _clipRects[0].y2 = _sprite1->getDrawRect().y2(); - - _sprite2 = insertStaticSprite(0x92035301, 1100); - _clipRects[1].y2 = _sprite2->getDrawRect().y2(); - - _sprite3 = insertStaticSprite(0x3182220E, 1100); - - _sprite4 = insertStaticSprite(0x72090342, 1100); - _clipRects[1].x1 = _sprite4->getDrawRect().x; - _clipRects[1].y1 = _sprite4->getDrawRect().y; - - tempSprite = insertStaticSprite(0xD2012C02, 1100); - _clipRects[2].x1 = tempSprite->getDrawRect().x; - _clipRects[2].y2 = tempSprite->getDrawRect().y2(); - _clipRects[3].y1 = tempSprite->getDrawRect().y2(); - _clipRects[1].x2 = tempSprite->getDrawRect().x; - - tempSprite = insertStaticSprite(0x72875F42, 1100); - _clipRects[3].x1 = tempSprite->getDrawRect().x; - - insertStaticSprite(0x0201410A, 1100); - insertStaticSprite(0x72875F42, 1100); - - _asSpew = insertSprite(); - - _clipRects[2].y1 = 0; - _clipRects[3].y2 = 480; - _clipRects[2].x2 = 640; - _clipRects[3].x2 = 640; - - if (which < 0) { - insertKlaymen(441, 423, false, _clipRects, 4); - setMessageList(0x004AF098); - } else if (which == 1) { - insertKlaymen(378, 423, false, _clipRects, 4); - setMessageList(0x004AF098); - } else if (which == 2) { - insertKlaymen(378, 423, false, _clipRects, 4); - setMessageList(0x004AF0C8, false); - } else if (which == 3) { - insertKlaymen(378, 423, true, _clipRects, 4); - setMessageList(0x004AF0A0, false); - setGlobalVar(V_KLAYMEN_SMALL, 0); - } else { - insertKlaymen(670, 423, false, _clipRects, 4); - setMessageList(0x004AF090); - } - - _pointIndex = -1; - findClosestPoint(); - -} - -uint32 Scene2806::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x44262B12) { - setMessageList(0x004AF0E0); - } - break; - case 0x2000: - sendMessage(_asSpew, 0x2000, 0); - break; - } - return 0; -} - -void Scene2806::update() { - Scene::update(); - findClosestPoint(); -} - -void Scene2806::findClosestPoint() { - - static const uint32 kScene2806PaletteFileHashes[] = { - 0x48052508, - 0x01139404, - 0x01138C04, - 0x01138004, - 0x01138604, - 0x086B8890 - }; - - int16 x = MIN(_klaymen->getX(), 639); - int index = 1; - - while (index < (int)_pointList->size() && (*_pointList)[index].x < x) - ++index; - --index; - - if (_pointIndex != index) { - _pointIndex = index; - _palette->addPalette(kScene2806PaletteFileHashes[index], 0, 64, 0); - } - -} - -Scene2807::Scene2807(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - SetMessageHandler(&Scene2807::handleMessage); - - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 1) { - insertStaticSprite(0x103021E2, 300); - } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 2) { - insertStaticSprite(0x103022E2, 300); - } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 3) { - insertStaticSprite(0x103024E2, 300); - } - - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 1) { - insertStaticSprite(0x4800A52A, 200); - } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 2) { - insertStaticSprite(0x4800A62A, 200); - } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) { - insertStaticSprite(0x4800A02A, 200); - } - - if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 1) { - insertStaticSprite(0x31203430, 100); - } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 2) { - insertStaticSprite(0x31203400, 100); - } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) { - insertStaticSprite(0x31203460, 100); - } - - setBackground(0x3E049A95); - setPalette(0x3E049A95); - insertPuzzleMouse(0x49A913E8, 20, 620); - -} - -uint32 Scene2807::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { - leaveScene(0); - } - break; - } - return 0; -} - -static const uint32 kScene2808FileHashes1[] = { - 0x90B0392, - 0x90B0192 -}; - -static const uint32 kScene2808FileHashes2[] = { - 0xB0396098, - 0xB0196098 -}; - -static const uint32 kClass428FileHashes[] = { - 0x140022CA, - 0x4C30A602, - 0xB1633402, - 0x12982135, - 0x0540B728, - 0x002A81E3, - 0x08982841, - 0x10982841, - 0x20982841, - 0x40982841, - 0x80982841, - 0x40800711 -}; - -static const int kClass428Countdowns1[] = { - 18, 16, 10, 0 -}; - -static const int kClass428Countdowns2[] = { - 9, 9, 8, 8, 5, 5, 0, 0 -}; - -static const uint32 kClass490FileHashes[] = { - 0x08100071, - 0x24084215, - 0x18980A10 -}; - -static const int16 kClass490FrameIndices1[] = { - 0, 8, 15, 19 -}; - -static const int16 kClass490FrameIndices2[] = { - 0, 4, 8, 11, 15, 17, 19, 0 -}; - -SsScene2808Dispenser::SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex) - : StaticSprite(vm, 900), _parentScene(parentScene), _countdown(0), _testTubeSetNum(testTubeSetNum), - _testTubeIndex(testTubeIndex) { - - loadSprite(kClass428FileHashes[testTubeSetNum * 3 + testTubeIndex], kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 1500); - setVisible(false); - SetUpdateHandler(&SsScene2808Dispenser::update); - SetMessageHandler(&SsScene2808Dispenser::handleMessage); -} - -void SsScene2808Dispenser::update() { - updatePosition(); - if (_countdown != 0 && (--_countdown) == 0) { - setVisible(false); - } -} - -uint32 SsScene2808Dispenser::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x2000, _testTubeIndex); - messageResult = 1; - break; - } - return messageResult; -} - -void SsScene2808Dispenser::startCountdown(int index) { - setVisible(true); - updatePosition(); - if (_testTubeSetNum == 0) { - _countdown = kClass428Countdowns1[index]; - } else { - _countdown = kClass428Countdowns2[index]; - } -} - -AsScene2808TestTube::AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser) - : AnimatedSprite(vm, 1100), _testTubeSetNum(testTubeSetNum), _testTubeIndex(testTubeIndex), _ssDispenser(ssDispenser), _fillLevel(0) { - - if (testTubeSetNum == 0) { - _x = 504; - _y = 278; - } else { - setDoDeltaX(1); - _x = 136; - _y = 278; - } - - createSurface1(kClass490FileHashes[testTubeIndex], 1100); - - if (testTubeSetNum == 0) { - loadSound(0, 0x30809E2D); - loadSound(1, 0x72811E2D); - loadSound(2, 0x78B01625); - } else { - loadSound(3, 0x70A41E0C); - loadSound(4, 0x50205E2D); - loadSound(5, 0xF8621E2D); - loadSound(6, 0xF1A03C2D); - loadSound(7, 0x70A43D2D); - loadSound(8, 0xF0601E2D); - } - - startAnimation(kClass490FileHashes[testTubeIndex], 0, -1); - _newStickFrameIndex = 0; - - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2808TestTube::handleMessage); - - if (_fillLevel == 0) - setVisible(false); - -} - -uint32 AsScene2808TestTube::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - fill(); - messageResult = 1; - break; - } - return messageResult; -} - -void AsScene2808TestTube::fill() { - if ((int)_fillLevel < _testTubeSetNum * 3 + 3) { - if (_testTubeSetNum == 0) { - playSound(_fillLevel); - setVisible(true); - startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices1[_fillLevel], kClass490FrameIndices1[_fillLevel + 1]); - _newStickFrameIndex = kClass490FrameIndices1[_fillLevel + 1]; - } else { - playSound(3 + _fillLevel); - setVisible(true); - startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices2[_fillLevel], kClass490FrameIndices2[_fillLevel + 1]); - _newStickFrameIndex = kClass490FrameIndices2[_fillLevel + 1]; - } - _ssDispenser->startCountdown(_fillLevel); - _fillLevel++; - } -} - -void AsScene2808TestTube::flush() { - if (_fillLevel != 0) { - if (_testTubeSetNum == 0) { - startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices1[_fillLevel], -1); - } else { - startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices2[_fillLevel], -1); - } - _newStickFrameIndex = 0; - _playBackwards = true; - setVisible(true); - } -} - -AsScene2808Handle::AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum) - : AnimatedSprite(vm, 1300), _parentScene(parentScene), _testTubeSetNum(testTubeSetNum), _isActivated(false) { - - loadSound(0, 0xE18D1F30); - _x = 320; - _y = 240; - if (_testTubeSetNum == 1) - setDoDeltaX(1); - createSurface1(0x040900D0, 1300); - startAnimation(0x040900D0, 0, -1); - _needRefresh = true; - _newStickFrameIndex = 0; - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2808Handle::handleMessage); - AnimatedSprite::updatePosition(); -} - -uint32 AsScene2808Handle::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (!_isActivated) { - sendMessage(_parentScene, 0x2001, 0); - playSound(0); - activate(); - } - messageResult = 1; - break; - } - return messageResult; -} - -uint32 AsScene2808Handle::hmActivating(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene2808Handle::activate() { - startAnimation(0x040900D0, 0, -1); - SetMessageHandler(&AsScene2808Handle::hmActivating); - NextState(&AsScene2808Handle::stActivated); - _isActivated = true; - _newStickFrameIndex = -1; -} - -void AsScene2808Handle::stActivated() { - stopAnimation(); - sendMessage(_parentScene, 0x2002, 0); -} - -AsScene2808Flow::AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _testTubeSetNum(testTubeSetNum) { - - if (testTubeSetNum == 0) { - _x = 312; - _y = 444; - } else { - _x = 328; - _y = 444; - } - createSurface1(0xB8414818, 1200); - startAnimation(0xB8414818, 0, -1); - setVisible(false); - _newStickFrameIndex = 0; - _needRefresh = true; - loadSound(0, 0x6389B652); - SetUpdateHandler(&AnimatedSprite::update); - AnimatedSprite::updatePosition(); -} - -uint32 AsScene2808Flow::hmFlowing(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene2808Flow::start() { - startAnimation(0xB8414818, 0, -1); - setVisible(true); - SetMessageHandler(&AsScene2808Flow::hmFlowing); - NextState(&AsScene2808Flow::stKeepFlowing); - playSound(0); -} - -void AsScene2808Flow::stKeepFlowing() { - startAnimation(0xB8414818, 1, -1); - NextState(&AsScene2808Flow::stKeepFlowing); -} - -AsScene2808LightEffect::AsScene2808LightEffect(NeverhoodEngine *vm, int testTubeSetNum) - : AnimatedSprite(vm, 800), _countdown(1) { - - _x = 320; - _y = 240; - if (testTubeSetNum == 1) - setDoDeltaX(1); - createSurface1(0x804C2404, 800); - SetUpdateHandler(&AsScene2808LightEffect::update); - _needRefresh = true; - AnimatedSprite::updatePosition(); -} - -void AsScene2808LightEffect::update() { - if (_countdown != 0 && (--_countdown) == 0) { - int16 frameIndex = _vm->_rnd->getRandomNumber(3 - 1); - startAnimation(0x804C2404, frameIndex, frameIndex); - updateAnim(); - updatePosition(); - _countdown = _vm->_rnd->getRandomNumber(3 - 1) + 1; - } -} - -Scene2808::Scene2808(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _countdown(0), _testTubeSetNum(which), _leaveResult(0), _isFlowing(false) { - - Sprite *asHandle; - - if (which == 0) - _vm->gameModule()->initTestTubes1Puzzle(); - else - _vm->gameModule()->initTestTubes2Puzzle(); - - SetMessageHandler(&Scene2808::handleMessage); - SetUpdateHandler(&Scene2808::update); - - setBackground(kScene2808FileHashes1[which]); - setPalette(kScene2808FileHashes1[which]); - - asHandle = insertSprite(this, which); - addCollisionSprite(asHandle); - - _asFlow = insertSprite(this, which); - insertSprite(which); - - for (int testTubeIndex = 0; testTubeIndex < 3; testTubeIndex++) { - SsScene2808Dispenser *ssDispenser = insertSprite(this, which, testTubeIndex); - addCollisionSprite(ssDispenser); - _asTestTubes[testTubeIndex] = insertSprite(which, testTubeIndex, ssDispenser); - addCollisionSprite(_asTestTubes[testTubeIndex]); - } - - insertScreenMouse(kScene2808FileHashes2[which]); - -} - -uint32 Scene2808::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && !isAnyTestTubeFilled()) { - leaveScene(1); - } - break; - case 0x2000: - if (!_isFlowing) - _asTestTubes[param.asInteger()]->fill(); - break; - case 0x2001: - _isFlowing = true; - break; - case 0x2002: - if (isAnyTestTubeFilled()) { - _leaveResult = 3; - if (!isMixtureGood()) - _leaveResult = 2; - _asFlow->start(); - for (int i = 0; i < 3; i++) - _asTestTubes[i]->flush(); - _mouseCursor->setVisible(false); - _countdown = 16; - } else { - leaveScene(1); - } - break; - } - return 0; -} - -void Scene2808::update() { - - // DEBUG>>> Show correct values - #if 1 - debug("---------------"); - if (_testTubeSetNum == 0) - debug("%03d %03d %03d", getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2)); - else - debug("%03d %03d %03d", getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2)); - debug("%03d %03d %03d", _asTestTubes[0]->getFillLevel(), _asTestTubes[1]->getFillLevel(), _asTestTubes[2]->getFillLevel()); - #endif - // DEBUG<<< - - Scene::update(); - if (_countdown != 0 && (--_countdown) == 0) { - leaveScene(_leaveResult); - } -} - -bool Scene2808::isMixtureGood() { - if (_testTubeSetNum == 0) { - return - _asTestTubes[0]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) && - _asTestTubes[1]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) && - _asTestTubes[2]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2); - } else { - return - _asTestTubes[0]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0) && - _asTestTubes[1]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1) && - _asTestTubes[2]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2); - } -} - -bool Scene2808::isAnyTestTubeFilled() { - return - _asTestTubes[0]->getFillLevel() > 0 || - _asTestTubes[1]->getFillLevel() > 0 || - _asTestTubes[2]->getFillLevel() > 0; -} - -AsScene2809Spew::AsScene2809Spew(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1200) { - - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2809Spew::handleMessage); - createSurface1(0x04211490, 1200); - _x = 262; - _y = 423; - setDoDeltaX(0); - setVisible(false); -} - -uint32 AsScene2809Spew::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - playSound(0, 0x48640244); - startAnimation(0x04211490, 0, -1); - setVisible(true); - break; - case 0x3002: - stopAnimation(); - setVisible(false); - break; - } - return messageResult; -} - -Scene2809::Scene2809(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - Sprite *tempSprite; - - SetMessageHandler(&Scene2809::handleMessage); - SetUpdateHandler(&Scene2809::update); - - loadDataResource(0x1830009A); - loadHitRectList(); - - _pointList = _dataResource.getPointArray(0x064A310E); - - setBackground(0xB22116C5); - setPalette(0xB22116C5); - insertScreenMouse(0x116C1B2A); - - _sprite1 = insertStaticSprite(0x1FA2EB82, 1100); - - _clipRects[0].x1 = _sprite1->getDrawRect().x; - _clipRects[0].y1 = _sprite1->getDrawRect().y; - _clipRects[0].x2 = _sprite1->getDrawRect().x2(); - _clipRects[0].y2 = _sprite1->getDrawRect().y2(); - - _sprite2 = insertStaticSprite(0x037321B2, 1100); - _clipRects[1].y2 = _sprite2->getDrawRect().y2(); - - _sprite3 = insertStaticSprite(0x82022E11, 1100); - - _sprite4 = insertStaticSprite(0x09236252, 1100); - _clipRects[1].x2 = _sprite4->getDrawRect().x2(); - _clipRects[1].y1 = _sprite4->getDrawRect().y; - - tempSprite = insertStaticSprite(0x010C22F2, 1100); - _clipRects[2].x2 = tempSprite->getDrawRect().x2(); - _clipRects[2].y2 = tempSprite->getDrawRect().y2(); - _clipRects[3].y1 = tempSprite->getDrawRect().y2(); - _clipRects[1].x1 = tempSprite->getDrawRect().x2(); - - tempSprite = insertStaticSprite(0x877F6252, 1100); - _clipRects[3].x2 = tempSprite->getDrawRect().x2(); - - insertStaticSprite(0x01612A22, 1100); - insertStaticSprite(0x877F6252, 1100); - - _asSpew = insertSprite(); - _clipRects[2].y1 = 0; - _clipRects[3].y2 = 480; - _clipRects[2].x1 = 0; - _clipRects[3].x1 = 0; - - if (which < 0) { - insertKlaymen(226, 423, false, _clipRects, 4); - setMessageList(0x004B5B90); - } else if (which == 1) { - insertKlaymen(262, 423, false, _clipRects, 4); - setMessageList(0x004B5B90); - } else if (which == 2) { - insertKlaymen(262, 423, false, _clipRects, 4); - setMessageList(0x004B5BD0); - } else if (which == 3) { - insertKlaymen(262, 423, true, _clipRects, 4); - setMessageList(0x004B5BA8, false); - setGlobalVar(V_KLAYMEN_SMALL, 0); - } else { - insertKlaymen(-30, 423, false, _clipRects, 4); - setMessageList(0x004B5B88); - } - - _pointIndex = -1; - findClosestPoint(); - -} - -void Scene2809::update() { - Scene::update(); - findClosestPoint(); -} - -uint32 Scene2809::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x160DA937) { - setMessageList(0x004B5B98); - } - break; - case 0x2000: - sendMessage(_asSpew, 0x2000, 0); - break; - } - return 0; -} - -void Scene2809::findClosestPoint() { - - static const uint32 kScene2809PaletteFileHashes[] = { - 0x04260848, - 0x12970401, - 0x128F0401, - 0x12830401, - 0x12850401, - 0x6A8B9008 - }; - - int16 x = MAX(_klaymen->getX(), 2); - int index = 1; - - while (index < (int)_pointList->size() && (*_pointList)[index].x >= x) - ++index; - --index; - - if (_pointIndex != index) { - _pointIndex = index; - _palette->addPalette(kScene2809PaletteFileHashes[index], 0, 64, 0); - } - -} - -AsScene2810Rope::AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x) - : AnimatedSprite(vm, 1100) { - - createSurface(990, 68, 476); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2810Rope::handleMessage); - SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); - _x = x; - _y = -276; - startAnimation(0x9D098C23, 35, 53); -} - -uint32 AsScene2810Rope::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - startAnimation(0x9D098C23, 35, 53); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -Scene2810::Scene2810(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule) { - - Sprite *tempSprite; - - SetMessageHandler(&Scene2810::handleMessage); - - setBackground(0x26508804); - setPalette(0x26508804); - insertScreenMouse(0x0880026D); - - _sprite6 = insertStaticSprite(0x03615227, 1100); - _sprite5 = insertStaticSprite(0xE059A224, 1100); - - _clipRects[0].x1 = 0; - _clipRects[0].y1 = 0; - _clipRects[0].x2 = 640; - _clipRects[0].y2 = 400; - _clipRects[1].x1 = _sprite5->getDrawRect().x; - _clipRects[1].y1 = 400; - _clipRects[1].x2 = _sprite6->getDrawRect().x2(); - _clipRects[1].y2 = 480; - - if (getGlobalVar(V_KLAYMEN_SMALL)) { - _asTape = insertSprite(this, 0, 900, 245, 429, 0x9148A011); - addCollisionSprite(_asTape); - } else { - _asTape = insertSprite(this, 0, 1100, 245, 429, 0x9148A011); - addCollisionSprite(_asTape); - } - - _sprite1 = insertStaticSprite(0x430001C4, 1200); - - if (getGlobalVar(V_LADDER_DOWN)) { - setGlobalVar(V_BEEN_STATUE_ROOM, 1); - if (getGlobalVar(V_KLAYMEN_SMALL)) { - _sprite4 = insertStaticSprite(0x82653808, 100); - } else { - _sprite4 = insertStaticSprite(0x82653808, 1100); - } - _sprite4->setClipRect(0, _sprite1->getDrawRect().y, 640, 480); - } - - if (which < 0) { - if (getGlobalVar(V_KLAYMEN_SMALL)) { - insertKlaymen(240, 448); - _klaymen->setClipRect(_sprite5->getDrawRect().x, 0, 640, 480); - setMessageList(0x004AE438); - setRectList(0x004AE810); - _isRopingDown = false; - removeCollisionSprite(_asTape); - } else { - insertKlaymen(300, 424, _clipRects, 2); - setMessageList(0x004AE438); - if (getGlobalVar(V_LADDER_DOWN)) - loadDataResource(0x84130112); - else - loadDataResource(0x84500132); - tempSprite = insertSprite(_klaymen); - tempSprite->setClipRect(0, _sprite1->getDrawRect().y, 640, 480); - _clipRects[0].y1 = _sprite1->getDrawRect().y; - _isRopingDown = false; - } - } else if (which == 1) { - insertKlaymen(186, 64, _clipRects, 2); - setMessageList(0x004AE440); - loadDataResource(0x84130112); - tempSprite = insertSprite(_klaymen); - tempSprite->setClipRect(0, _sprite1->getDrawRect().y, 640, 480); - _isRopingDown = true; - _clipRects[0].y1 = _sprite1->getDrawRect().y; - } else if (which == 5) { - insertStaticSprite(0xC3007EA0, 100); - _sprite2 = insertStaticSprite(0x02780936, 1100); - _sprite3 = insertStaticSprite(0x1CA02160, 1100); - _asRope = insertSprite(this, 384); - insertKlaymen(384, 0, _clipRects, 0); - sendEntityMessage(_klaymen, 0x1014, _asRope); - setMessageList(0x004AE738); - _klaymen->setClipRect(0, _sprite2->getDrawRect().y, 640, _sprite3->getDrawRect().y2()); - _asRope->setClipRect(0, _sprite2->getDrawRect().y, 640, _sprite3->getDrawRect().y2()); - _vm->_soundMan->addSound(0x84400112, 0xC874EE6C); - _vm->_soundMan->playSoundLooping(0xC874EE6C); - _vm->_soundMan->setSoundVolume(0xC874EE6C, 50); - _isRopingDown = false; - } else if ((which >= 11 && which <= 14) || (which >= 19 && which <= 22) || which == 3) { - if (getGlobalVar(V_KLAYMEN_SMALL)) { - insertKlaymen((int16)getGlobalVar(V_KLAYMEN_SAVED_X), 448); - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) - _klaymen->setDoDeltaX(1); - _klaymen->setClipRect(_sprite5->getDrawRect().x, 0, 640, 480); - setMessageList(0x004AE6D8); - setRectList(0x004AE810); - _isRopingDown = false; - removeCollisionSprite(_asTape); - } else { - insertKlaymenLadder(); - if (getGlobalVar(V_LADDER_DOWN_ACTION)) { - setMessageList(0x004AE6E8); - setGlobalVar(V_LADDER_DOWN_ACTION, 0); - _isRopingDown = false; - } else { - setMessageList(0x004AE6D8); - _isRopingDown = false; - } - } - } else if (which >= 15 && which <= 18) { - insertKlaymenLadder(); - setMessageList(0x004AE6E0); - _isRopingDown = false; - } else if (which == 4) { - if (getGlobalVar(V_KLAYMEN_SMALL)) { - insertKlaymen(473, 448); - _klaymen->setClipRect(_sprite5->getDrawRect().x, 0, 640, 480); - setMessageList(0x004AE428); - setRectList(0x004AE810); - _isRopingDown = false; - removeCollisionSprite(_asTape); - } else { - insertKlaymen(450, 424, _clipRects, 2); - setMessageList(0x004AE418); - if (getGlobalVar(V_LADDER_DOWN)) - loadDataResource(0x84130112); - else - loadDataResource(0x84500132); - tempSprite = insertSprite(_klaymen); - tempSprite->setClipRect(0, _sprite1->getDrawRect().y, 640, 480); - _clipRects[0].y1 = _sprite1->getDrawRect().y; - _isRopingDown = false; - } - } else { - insertKlaymen(120, 448); - _klaymen->setClipRect(_sprite5->getDrawRect().x, 0, 640, 480); - setMessageList(0x004AE410); - setRectList(0x004AE810); - _isRopingDown = false; - removeCollisionSprite(_asTape); - } - -} - -Scene2810::~Scene2810() { - setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); - setGlobalVar(V_KLAYMEN_SAVED_X, _klaymen->getX()); - _vm->_soundMan->deleteSoundGroup(0x84400112); -} - -void Scene2810::insertKlaymenLadder() { - Sprite *tempSprite; - - if (getGlobalVar(V_LADDER_DOWN_ACTION)) { - insertKlaymen(430, 424, _clipRects, 2); - _klaymen->setDoDeltaX(1); - } else { - insertKlaymen((int16)getGlobalVar(V_KLAYMEN_SAVED_X), 424, _clipRects, 2); - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) - _klaymen->setDoDeltaX(1); - } - if (getGlobalVar(V_LADDER_DOWN)) - loadDataResource(0x84130112); - else - loadDataResource(0x84500132); - tempSprite = insertSprite(_klaymen); - tempSprite->setClipRect(0, _sprite1->getDrawRect().y, 640, 480); - _clipRects[0].y1 = _sprite1->getDrawRect().y; -} - -uint32 Scene2810::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0xE574F14C) - setMessageList(0x004AE458); - else if (param.asInteger() == 0x7214A05C || param.asInteger() == 0x2905E574) - setMessageList(0x004AE4A8); - else if (param.asInteger() == 0x7274E24C || param.asInteger() == 0x2D24E572) - setMessageList(0x004AE4D0); - else if (param.asInteger() == 0x4A07A040 || param.asInteger() == 0x190426F5) - setMessageList(0x004AE4F8); - else if (param.asInteger() == 0x6604200C || param.asInteger() == 0x2100E435) - setMessageList(0x004AE520); - else if (param.asInteger() == 0xE216A05C || param.asInteger() == 0x0905EC74) - setMessageList(0x004AE548); - else if (param.asInteger() == 0x721DA05C || param.asInteger() == 0xB905E574) - setMessageList(0x004AE570); - else if (param.asInteger() == 0x6214E09C || param.asInteger() == 0x2D09E474) - setMessageList(0x004AE598); - else if (param.asInteger() == 0x6276A04C || param.asInteger() == 0x0904E472) - setMessageList(0x004AE5C0); - else if (param.asInteger() == 0x6E14A00C || param.asInteger() == 0x2900E4B4) - setMessageList(0x004AE5E8); - else if (param.asInteger() == 0x6014A04D || param.asInteger() == 0x2904F454) - setMessageList(0x004AE610); - else if (param.asInteger() == 0x6215A3C4 || param.asInteger() == 0x393C6474) - setMessageList(0x004AE638); - else if (param.asInteger() == 0x6A54E24D || param.asInteger() == 0x2D24F4F0) - setMessageList(0x004AE660); - else if (param.asInteger() == 0x2064294C || param.asInteger() == 0x2194E053) - setMessageList(0x004AE688); - break; - case 0x2000: - setRectList(0x004AE800); - _isRopingDown = true; - break; - case 0x2001: - if (getGlobalVar(V_LADDER_DOWN)) - loadDataResource(0x84130112); - else - loadDataResource(0x84500132); - _isRopingDown = false; - break; - case 0x4826: - if (sender == _asTape && getGlobalVar(V_KLAYMEN_SMALL) == 0 && !_isRopingDown) { - sendEntityMessage(_klaymen, 0x1014, _asTape); - setMessageList(0x004AE750); - } - break; - } - return messageResult; -} - -AsScene2812Winch::AsScene2812Winch(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100) { - - createSurface1(0x20DA08A0, 1200); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2812Winch::handleMessage); - setVisible(false); - _x = 280; - _y = 184; -} - -AsScene2812Winch::~AsScene2812Winch() { - _vm->_soundMan->deleteSoundGroup(0x00B000E2); -} - -uint32 AsScene2812Winch::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - startAnimation(0x20DA08A0, 0, -1); - setVisible(true); - _vm->_soundMan->addSound(0x00B000E2, 0xC874EE6C); - _vm->_soundMan->playSoundLooping(0xC874EE6C); - break; - case 0x3002: - startAnimation(0x20DA08A0, 7, -1); - break; - } - return messageResult; -} - -AsScene2812Rope::AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - - createSurface(990, 68, 476); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene2812Rope::handleMessage); - SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); - startAnimation(0xAE080551, 0, -1); - _x = 334; - _y = 201; -} - -uint32 AsScene2812Rope::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4806: - setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0); - stRopingDown(); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -uint32 AsScene2812Rope::hmRopingDown(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene2812Rope::stRopingDown() { - sendMessage(_parentScene, 0x4806, 0); - startAnimation(0x9D098C23, 0, -1); - SetMessageHandler(&AsScene2812Rope::hmRopingDown); -} - -AsScene2812TrapDoor::AsScene2812TrapDoor(NeverhoodEngine *vm) - : AnimatedSprite(vm, 0x805D0029, 100, 320, 240) { - - SetMessageHandler(&AsScene2812TrapDoor::handleMessage); - _newStickFrameIndex = 0; -} - -uint32 AsScene2812TrapDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2000: - startAnimation(0x805D0029, 0, -1); - playSound(0, 0xEA005F40); - _newStickFrameIndex = STICK_LAST_FRAME; - break; - } - return messageResult; -} - -Scene2812::Scene2812(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _paletteArea(0) { - - if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) - setGlobalVar(V_KEY3_LOCATION, 3); - - SetMessageHandler(&Scene2812::handleMessage); - SetUpdateHandler(&Scene2812::update); - - setRectList(0x004AF700); - - setBackground(0x03600606); - setPalette(0x03600606); - addEntity(_palette); - _palette->addBasePalette(0x03600606, 0, 256, 0); - - _sprite1 = insertStaticSprite(0x0C06C860, 1100); - insertScreenMouse(0x0060203E); - - if (getGlobalVar(V_KEY3_LOCATION) == 3) { - _asKey = insertSprite(this, 2, 1100, 474, 437); - addCollisionSprite(_asKey); - } - - _ssTape = insertSprite(this, 6, 1100, 513, 437, 0xA1361863); - addCollisionSprite(_ssTape); - - _asWinch = insertSprite(); - _asTrapDoor = insertSprite(); - _asRope = insertSprite(this); - - _sprite2 = insertStaticSprite(0x08478078, 1100); - _sprite3 = insertStaticSprite(0x2203B821, 1100); - _sprite4 = insertStaticSprite(0x08592134, 1100); - - if (which < 0) { - _isRopingDown = false; - insertKlaymen(272, 432); - setMessageList(0x004AF560); - _sprite1->setVisible(false); - _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); - } else if (which == 1) { - _isRopingDown = false; - insertKlaymen(338, 398); - setMessageList(0x004AF588); - setPaletteArea1(true); - _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite1->getDrawRect().x2(), _sprite3->getDrawRect().y2()); - } else if (which == 2) { - _isRopingDown = false; - if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { - insertKlaymen(554, 432); - _klaymen->setDoDeltaX(1); - } else { - insertKlaymen(394, 432); - } - setMessageList(0x004AF5F0); - _sprite1->setVisible(false); - _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); - } else { - _isRopingDown = true; - insertKlaymen(150, 582); - setMessageList(0x004AF568); - setPaletteArea2(true); - _sprite1->setVisible(false); - _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); - } - - _asRope->setClipRect(0, _sprite2->getDrawRect().y, 640, _sprite3->getDrawRect().y2()); - -} - -void Scene2812::update() { - if (_klaymen->getX() < 220) - setPaletteArea2(false); - else if (_klaymen->getX() < 240) - setPaletteArea0(false); - Scene::update(); -} - -uint32 Scene2812::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x0004269B) - sendEntityMessage(_klaymen, 0x1014, _asRope); - break; - case 0x2001: - _isRopingDown = true; - setRectList(0x004AF710); - _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite4->getDrawRect().y2()); - break; - case 0x2002: - _isRopingDown = false; - setRectList(0x004AF700); - _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); - break; - case 0x4806: - sendMessage(_asWinch, 0x2000, 0); - sendMessage(_asTrapDoor, 0x2000, 0); - break; - case 0x4826: - if (sender == _ssTape && !_isRopingDown) { - sendEntityMessage(_klaymen, 0x1014, _ssTape); - setMessageList(0x004AF658); - } else if (sender == _asKey && !_isRopingDown) { - sendEntityMessage(_klaymen, 0x1014, _asKey); - setMessageList(0x004AF668); - } - break; - case 0x482A: - setPaletteArea1(false); - _sprite1->setVisible(true); - _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite1->getDrawRect().x2(), _sprite3->getDrawRect().y2()); - break; - case 0x482B: - setPaletteArea0(false); - _sprite1->setVisible(false); - _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); - break; - } - return messageResult; -} - -void Scene2812::setPaletteArea0(bool instantly) { - if (_paletteArea != 0) { - _paletteArea = 0; - updatePaletteArea(instantly); - } -} - -void Scene2812::setPaletteArea1(bool instantly) { - if (_paletteArea != 1) { - _paletteArea = 1; - updatePaletteArea(instantly); - } -} - -void Scene2812::setPaletteArea2(bool instantly) { - if (_paletteArea != 2) { - _paletteArea = 2; - updatePaletteArea(instantly); - } -} - -void Scene2812::updatePaletteArea(bool instantly) { - if (_paletteArea == 0) - _palette->addBasePalette(0x05D30F11, 0, 64, 0); - else if (_paletteArea == 1) - _palette->addBasePalette(0x92CA2C9B, 0, 64, 0); - else if (_paletteArea == 2) - _palette->addBasePalette(0x381F92C5, 0, 64, 0); - _palette->startFadeToPalette(instantly ? 0 : 12); -} - -Scene2822::Scene2822(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _countdown(0), _scrollIndex(0) { - - SetMessageHandler(&Scene2822::handleMessage); - SetUpdateHandler(&Scene2822::update); - _background = new Background(_vm, 0xD542022E, 0, 0); - addBackground(_background); - _background->getSurface()->getDrawRect().y = -10; - setPalette(0xD542022E); - insertPuzzleMouse(0x0028D089, 20, 620); - _ssButton = insertStaticSprite(0x1A4D4120, 1100); - _ssButton->setVisible(false); - loadSound(2, 0x19044E72); -} - -void Scene2822::update() { - - static const int16 kScene2822BackgroundYPositions[] = { - 0, -20, -5, -15, -8, -12, -9, -11, -10, 0 - }; - - Scene::update(); - - if (_countdown != 0) { - if ((--_countdown) == 0) { - if (_countdownStatus == 0) { - _ssButton->setVisible(false); - _countdownStatus = 1; - _countdown = 48; - } else if (_countdownStatus == 1) { - playSound(0, 0x1384CB60); - _countdownStatus = 2; - _countdown = 12; - } else if (_countdownStatus == 2 && getGlobalVar(V_LADDER_DOWN_ACTION)) { - leaveScene(0); - } - } else if (_countdownStatus == 2 && getGlobalVar(V_LADDER_DOWN_ACTION)) { - if (_scrollIndex < 9) { - _background->getSurface()->getDrawRect().y = kScene2822BackgroundYPositions[_scrollIndex]; - _scrollIndex++; - } else { - _background->getSurface()->getDrawRect().y = -10; - } - } - } - -} - -uint32 Scene2822::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { - leaveScene(0); - } else if (param.asPoint().x >= 257 && param.asPoint().y >= 235 && - param.asPoint().x <= 293 && param.asPoint().y <= 273) { - _ssButton->setVisible(true); - _countdownStatus = 0; - _countdown = 12; - playSound(1, 0x44061000); - if (getGlobalVar(V_LADDER_DOWN) == 0) { - setGlobalVar(V_LADDER_DOWN, 1); - setGlobalVar(V_LADDER_DOWN_ACTION, 1); - SetMessageHandler(NULL); - playSound(2); - _mouseCursor->setVisible(false); - } - } - break; - } - return messageResult; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module2800.h b/engines/neverhood/module2800.h deleted file mode 100644 index 970de3cbdf..0000000000 --- a/engines/neverhood/module2800.h +++ /dev/null @@ -1,505 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE2800_H -#define NEVERHOOD_MODULE2800_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" - -namespace Neverhood { - -// Module2800 - -class Module2800 : public Module { -public: - Module2800(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module2800(); -protected: - int _sceneNum; - uint32 _currentMusicFileHash; - MusicResource *_musicResource; - void createScene(int sceneNum, int which); - void updateScene(); - void updateMusic(bool halfVolume); -}; - -class Scene2801 : public Scene { -public: - Scene2801(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Scene2801(); -protected: - Sprite *_asTape; - uint32 _paletteHash; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2802 : public Scene { -public: - Scene2802(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Scene2802(); -protected: - SmackerPlayer *_smackerPlayer; - uint _currRadioMusicIndex; - int _currTuneStatus; - int _countdown1; - int _countdown2; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void incRadioMusicIndex(int delta); - void changeTuneStatus(int prevTuneStatus, int newTuneStatus); -}; - -class AsScene2803LightCord : public AnimatedSprite { -public: - AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y); - void stPulled(); - void stIdle(); - void setFileHashes(uint32 fileHash1, uint32 fileHash2); -protected: - Scene *_parentScene; - uint32 _fileHash1, _fileHash2; - bool _isPulled, _isBusy; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmPulled(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2803TestTubeOne : public AnimatedSprite { -public: - AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2); -protected: - uint32 _fileHash1, _fileHash2; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2803Rope : public AnimatedSprite { -public: - AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmReleased(int messageNum, const MessageParam ¶m, Entity *sender); - void stReleased(); - void stHide(); -}; - -class Scene2803 : public Scene { -public: - Scene2803(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - StaticSprite *_asTestTubeOne; - StaticSprite *_asTestTubeTwo; - StaticSprite *_asTestTubeThree; - Sprite *_asRope; - AsScene2803LightCord *_asLightCord; - StaticSprite *_sprite3; - StaticSprite *_sprite4; - StaticSprite *_sprite5; - StaticSprite *_sprite6; - StaticSprite *_sprite7; - StaticSprite *_sprite8; - StaticSprite *_sprite9; - Sprite *_sprite10; - NRect _clipRectsFloor[2]; - NRect _clipRectsStairs[3]; - int _paletteArea; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void upKlaymenStairs(); - void klaymenStairs(); - void klaymenFloor(); - void toggleBackground(); - void changeBackground(); - void setPaletteArea0(); - void setPaletteArea1(); - void updatePaletteArea(); -}; - -class Scene2803Small : public Scene { -public: - Scene2803Small(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - int _paletteArea; - Sprite *_sprite1; - Sprite *_sprite2; - Sprite *_sprite3; - Sprite *_sprite4; - Sprite *_sprite5; - Sprite *_sprite6; - Sprite *_sprite7; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void upKlaymenSlope(); - void upKlaymenFloor(); - void klaymenSlope(); - void klaymenFloor(); - void setPaletteArea0(); - void setPaletteArea1(); - void setPaletteArea2(); - void setPaletteArea3(); - void updatePaletteArea(bool instantly); -}; - -class Scene2804; - -class SsScene2804RedButton : public StaticSprite { -public: - SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene); -protected: - Scene2804 *_parentScene; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsScene2804LightCoil : public StaticSprite { -public: - SsScene2804LightCoil(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsScene2804BeamCoilBody : public StaticSprite { -public: - SsScene2804BeamCoilBody(NeverhoodEngine *vm); -}; - -class SsScene2804LightTarget : public StaticSprite { -public: - SsScene2804LightTarget(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsScene2804Flash : public StaticSprite { -public: - SsScene2804Flash(NeverhoodEngine *vm); - void show(); -}; - -class AsScene2804CrystalWaves : public AnimatedSprite { -public: - AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex); - void show(); - void hide(); -protected: - uint _crystalIndex; -}; - -class AsScene2804Crystal : public AnimatedSprite { -public: - AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex); - void show(); - void hide(); - void activate(); - int16 getColorNum() const { return _colorNum; } -protected: - AsScene2804CrystalWaves *_asCrystalWaves; - uint _crystalIndex; - int16 _colorNum; - bool _isLightOn; - bool _isShowing; -}; - -class SsScene2804CrystalButton : public StaticSprite { -public: - SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex); -protected: - Scene2804 *_parentScene; - AsScene2804Crystal *_asCrystal; - uint _crystalIndex; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2804BeamCoil : public AnimatedSprite { -public: - AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody); - virtual ~AsScene2804BeamCoil(); -protected: - Scene *_parentScene; - SsScene2804BeamCoilBody *_ssBeamCoilBody; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void show(); - void hide(); - void stBeaming(); - uint32 hmBeaming(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2804BeamTarget : public AnimatedSprite { -public: - AsScene2804BeamTarget(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2804 : public Scene { -public: - Scene2804(NeverhoodEngine *vm, Module *parentModule, int which); - bool isWorking() const { return _isWorking; } -protected: - int _countdown1; - int _countdown2; - int _countdown3; - int _beamStatus; - bool _isSolved; - bool _isWorking; - Sprite *_ssRedButton; - Sprite *_asCoil; - Sprite *_asTarget; - SsScene2804Flash *_ssFlash; - AsScene2804Crystal *_asCrystals[5]; - Sprite *_ssCrystalButtons[5]; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2805 : public Scene { -public: - Scene2805(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_sprite1; - Sprite *_sprite2; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2806Spew : public AnimatedSprite { -public: - AsScene2806Spew(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2806 : public Scene { -public: - Scene2806(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - NPointArray *_pointList; - int _pointIndex; - NRect _clipRects[4]; - Sprite *_sprite1; - Sprite *_sprite2; - Sprite *_sprite3; - Sprite *_sprite4; - Sprite *_asSpew; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void update(); - void findClosestPoint(); -}; - -class Scene2807 : public Scene { -public: - Scene2807(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsScene2808Dispenser : public StaticSprite { -public: - SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex); - void startCountdown(int index); -protected: - Scene *_parentScene; - int _countdown; - int _testTubeSetNum, _testTubeIndex; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2808TestTube : public AnimatedSprite { -public: - AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser); - void fill(); - void flush(); - uint32 getFillLevel() const { return _fillLevel; } -protected: - SsScene2808Dispenser *_ssDispenser; - int _testTubeSetNum; - uint32 _fillLevel; - int _testTubeIndex; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2808Handle : public AnimatedSprite { -public: - AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum); - void activate(); - void stActivated(); -protected: - Scene *_parentScene; - int _testTubeSetNum; - bool _isActivated; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmActivating(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2808Flow : public AnimatedSprite { -public: - AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum); - void start(); - void stKeepFlowing(); -protected: - Scene *_parentScene; - int _testTubeSetNum; - uint32 hmFlowing(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2808LightEffect : public AnimatedSprite { -public: - AsScene2808LightEffect(NeverhoodEngine *vm, int which); -protected: - int _countdown; - void update(); -}; - -class Scene2808 : public Scene { -public: - Scene2808(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - int _countdown; - int _testTubeSetNum; - AsScene2808Flow *_asFlow; - int _leaveResult; - bool _isFlowing; - AsScene2808TestTube *_asTestTubes[3]; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void update(); - bool isMixtureGood(); - bool isAnyTestTubeFilled(); -}; - -class AsScene2809Spew : public AnimatedSprite { -public: - AsScene2809Spew(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2809 : public Scene { -public: - Scene2809(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - NPointArray *_pointList; - int _pointIndex; - NRect _clipRects[4]; - Sprite *_sprite1; - Sprite *_sprite2; - Sprite *_sprite3; - Sprite *_sprite4; - Sprite *_asSpew; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void findClosestPoint(); -}; - -class AsScene2810Rope : public AnimatedSprite { -public: - AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2810 : public Scene { -public: - Scene2810(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Scene2810(); -protected: - Sprite *_sprite1; - Sprite *_sprite2; - Sprite *_sprite3; - Sprite *_asRope; - Sprite *_sprite4; - Sprite *_asTape; - Sprite *_sprite5; - Sprite *_sprite6; - bool _isRopingDown; - NRect _clipRects[2]; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void insertKlaymenLadder(); -}; - -class AsScene2812Winch : public AnimatedSprite { -public: - AsScene2812Winch(NeverhoodEngine *vm); - virtual ~AsScene2812Winch(); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene2812Rope : public AnimatedSprite { -public: - AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmRopingDown(int messageNum, const MessageParam ¶m, Entity *sender); - void stRopingDown(); -}; - -class AsScene2812TrapDoor : public AnimatedSprite { -public: - AsScene2812TrapDoor(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2812 : public Scene { -public: - Scene2812(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_asWinch; - Sprite *_asTrapDoor; - Sprite *_asRope; - Sprite *_sprite3; - Sprite *_sprite2; - Sprite *_sprite4; - Sprite *_ssTape; - Sprite *_asKey; - Sprite *_sprite1; - bool _isRopingDown; - int _paletteArea; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void setPaletteArea0(bool instantly); - void setPaletteArea1(bool instantly); - void setPaletteArea2(bool instantly); - void updatePaletteArea(bool instantly); -}; - -class Scene2822 : public Scene { -public: - Scene2822(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_ssButton; - int _scrollIndex; - int _countdown; - int _countdownStatus; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE2800_H */ diff --git a/engines/neverhood/module2900.cpp b/engines/neverhood/module2900.cpp deleted file mode 100644 index 1e14d37fd5..0000000000 --- a/engines/neverhood/module2900.cpp +++ /dev/null @@ -1,439 +0,0 @@ -/* 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/module2900.h" -#include "neverhood/gamemodule.h" -#include "neverhood/module1100.h" -#include "neverhood/module1300.h" -#include "neverhood/module1700.h" -#include "neverhood/module2000.h" -#include "neverhood/module2100.h" -#include "neverhood/module2800.h" - -namespace Neverhood { - -Module2900::Module2900(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { - - if (which >= 0) - setGlobalVar(V_TELEPORTER_WHICH, which); - - createScene(0, 0); - -} - -void Module2900::createScene(int sceneNum, int which) { - debug("Module2900::createScene(%d, %d)", sceneNum, which); - _sceneNum = sceneNum; - switch (_sceneNum) { - case 0: - _vm->gameState().sceneNum = 0; - _childObject = new Scene2901(_vm, this, getGlobalVar(V_TELEPORTER_WHICH)); - break; - case 1: - _vm->gameState().sceneNum = 0; - _childObject = new Scene2805(_vm, this, which); - break; - case 2: - _vm->gameState().sceneNum = 0; - _childObject = new Scene2101(_vm, this, which); - break; - case 3: - _vm->gameState().sceneNum = 0; - _childObject = new Scene1306(_vm, this, which); - break; - case 4: - _vm->gameState().sceneNum = 0; - _childObject = new Scene1705(_vm, this, which); - break; - case 5: - _vm->gameState().sceneNum = 0; - _childObject = new Scene1109(_vm, this, which); - break; - case 6: - _vm->gameState().sceneNum = 0; - _childObject = new Scene2001(_vm, this, which); - break; - } - SetUpdateHandler(&Module2900::updateScene); - _childObject->handleUpdate(); -} - -void Module2900::updateScene() { - if (!updateChild()) { - switch (_sceneNum) { - case 0: - if (_moduleResult == (uint32)-1) { - leaveModule((uint32)-1); - } else { - _teleporterModuleResult = _moduleResult; - switch (getGlobalVar(V_TELEPORTER_WHICH)) { - case 0: - createScene(3, 4); - break; - case 1: - createScene(2, 2); - break; - case 2: - createScene(5, 2); - break; - case 3: - createScene(4, 2); - break; - case 4: - createScene(6, 2); - break; - case 5: - createScene(1, 2); - break; - default: - leaveModule(_moduleResult); - break; - } - } - break; - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - leaveModule(_teleporterModuleResult); - break; - } - } -} - -static const uint32 kScene2901FileHashes1[] = { - 0x023023B4, - 0x36204507, - 0x046CF08E, - 0x9313A237, - 0xA651F246, - 0x02108034 -}; - -static const uint32 kScene2901FileHashes2[] = { - 0x023B002B, - 0x0450336A, - 0xCF08A04E, - 0x3A233939, - 0x1F242A6D, - 0x08030029 -}; - -static const uint32 kSsScene2901LocationButtonFileHashes[] = { - 0x2311326A, - 0x212323AC, - 0x10098138, - 0x25213167, - 0x1119A363, - 0x94452612, - 0x39464212, - 0x01860450, - 0x53002104, - 0x58E68412, - 0x18600300, - 0xB650A890, - 0x2452A7C4, - 0xA0232748, - 0x08862B02, - 0x2491E648, - 0x0010EB46, - 0x214C8A11, - 0x16A31921, - 0x0AC33A00, - 0x238028AA, - 0x26737A21, - 0x063039A8, - 0x51286C60, - 0x464006B4, - 0x42242538, - 0x20716010, - 0x4A2000AE, - 0x225124A6, - 0x28E82E45, - 0x58652C04, - 0xC82210A4, - 0x62A84060, - 0xC0693CB4, - 0x22212C64, - 0x5034EA71 -}; - -static const NPoint kSsScene2901LocationButtonPoints[] = { - {525, 120}, {576, 149}, {587, 205}, - {538, 232}, {484, 205}, {479, 153} -}; - -static const uint32 kSsScene2901LocationButtonLightFileHashes1[] = { - 0x03136246, - 0x2106216E, - 0x4025A13A, - 0x21816927, - 0x110B2202, - 0xCC0522B2, - 0x3CC24258, - 0x59C600F0, - 0x534A2480, - 0x50E61019, - 0x34400150, - 0x225BA090, - 0xB059AFC4, - 0xE093A741, - 0x0086BF09, - 0x3281E760, - 0xA048AB42, - 0x20649C01, - 0x14611904, - 0x26E33850, - 0x23A52A68, - 0xA2733024, - 0x10203880, - 0x1B2DE860, - 0x0644A6EC, - 0x426E20BC, - 0x80292014, - 0x4360B02E, - 0x22742664, - 0x98682705, - 0x0925B82C, - 0x5C2918A4, - 0xD2284920, - 0x41083CA6, - 0x6824A864, - 0x50266B10 -}; - -static const uint32 kSsScene2901LocationButtonLightFileHashes2[] = { - 0x43C46D4C, - 0x43C4AD4C, - 0x43C52D4C, - 0x43C62D4C, - 0x43C02D4C, - 0x43CC2D4C -}; - -static const uint32 kSsScene2901BrokenButtonFileHashes[] = { - 0x3081BD3A, - 0xD3443003, - 0x0786A320, - 0xE3A22029, - 0x61611814, - 0x425848E2 -}; - -static const uint32 kSsScene2901BigButtonFileHashes[] = { - 0x010D7748, - 0x9D02019A, - 0x351A2F43, - 0x448138E5, - 0x02788CF0, - 0x71718024 -}; - -SsScene2901LocationButton::SsScene2901LocationButton(NeverhoodEngine *vm, Scene *parentScene, int which, uint index) - : StaticSprite(vm, 900), _parentScene(parentScene), _index(index), _countdown1(0) { - - const NPoint &pt = kSsScene2901LocationButtonPoints[_index]; - - loadSprite(kSsScene2901LocationButtonFileHashes[which * 6 + index], kSLFDefDrawOffset | kSLFDefPosition, 800); - _collisionBounds.set(pt.x - 25, pt.y - 25, pt.x + 25, pt.y + 25); - setVisible(false); - loadSound(0, 0x440430C0); - SetUpdateHandler(&SsScene2901LocationButton::update); - SetMessageHandler(&SsScene2901LocationButton::handleMessage); -} - -void SsScene2901LocationButton::update() { - updatePosition(); - if (_countdown1 != 0 && (--_countdown1) == 0) { - setVisible(false); - } -} - -uint32 SsScene2901LocationButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_countdown1 == 0) { - playSound(0); - setVisible(true); - _countdown1 = 4; - sendMessage(_parentScene, 0x2001, _index); - } - messageResult = 1; - break; - } - return messageResult; -} - -SsScene2901LocationButtonLight::SsScene2901LocationButtonLight(NeverhoodEngine *vm, int which, uint index) - : StaticSprite(vm, 900), _index(index) { - - loadSprite(kSsScene2901LocationButtonLightFileHashes1[which * 6 + index], kSLFDefDrawOffset | kSLFDefPosition, 900); - setVisible(false); - loadSound(0, kSsScene2901LocationButtonLightFileHashes2[_index]); -} - -void SsScene2901LocationButtonLight::show() { - playSound(0); - setVisible(true); - updatePosition(); -} - -void SsScene2901LocationButtonLight::hide() { - setVisible(false); - updatePosition(); -} - -SsScene2901BrokenButton::SsScene2901BrokenButton(NeverhoodEngine *vm, int which) - : StaticSprite(vm, 900) { - - loadSprite(kSsScene2901BrokenButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 900); -} - -SsScene2901BigButton::SsScene2901BigButton(NeverhoodEngine *vm, Scene *parentScene, int which) - : StaticSprite(vm, 900), _parentScene(parentScene), _which(which), _countdown1(0) { - - loadSprite(kSsScene2901BigButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 400); - _collisionBounds.set(62, 94, 322, 350); - setVisible(false); - loadSound(0, 0xF3D420C8); - SetUpdateHandler(&SsScene2901BigButton::update); - SetMessageHandler(&SsScene2901BigButton::handleMessage); -} - -void SsScene2901BigButton::update() { - updatePosition(); - if (_countdown1 != 0 && (--_countdown1) == 0) { - setVisible(false); - sendMessage(_parentScene, 0x2000, 0); - } -} - -uint32 SsScene2901BigButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_countdown1 == 0) { - playSound(0); - setVisible(true); - _countdown1 = 4; - } - messageResult = 1; - break; - } - return messageResult; -} - -Scene2901::Scene2901(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _currLocationButtonNum(which), _selectedButtonNum(which), - _currWhirlButtonNum(0), _prevWhirlButtonNum(0), _countdown1(1), _skipCountdown(0), _blinkOn(0) { - - _isButton2Broken = getGlobalVar(V_ENTRANCE_OPEN) != 0; - - setSubVar(V_TELEPORTER_DEST_AVAILABLE, which, 1); - setSubVar(V_TELEPORTER_DEST_AVAILABLE, 5, 1); - setSubVar(V_TELEPORTER_DEST_AVAILABLE, 4, 1); - - if (_currLocationButtonNum == 3) - setSubVar(V_TELEPORTER_DEST_AVAILABLE, 2, 1); - - setBackground(kScene2901FileHashes1[_currLocationButtonNum]); - setPalette(kScene2901FileHashes1[_currLocationButtonNum]); - - for (uint i = 0; i < 6; ++i) { - if (i != 2 || !_isButton2Broken) { - _ssLocationButtons[i] = insertSprite(this, _currLocationButtonNum, i); - addCollisionSprite(_ssLocationButtons[i]); - _ssLocationButtonLights[i] = insertSprite(_currLocationButtonNum, i); - } - } - - if (_isButton2Broken) - insertSprite(_currLocationButtonNum); - - _ssBigButton = insertSprite(this, _currLocationButtonNum); - addCollisionSprite(_ssBigButton); - - insertPuzzleMouse(kScene2901FileHashes2[_currLocationButtonNum], 20, 620); - - SetUpdateHandler(&Scene2901::update); - SetMessageHandler(&Scene2901::handleMessage); - -} - -void Scene2901::update() { - Scene::update(); - if (_countdown1 != 0 && (--_countdown1) == 0) { - if (_currLocationButtonNum == _selectedButtonNum) { - _ssLocationButtonLights[_currWhirlButtonNum]->hide(); - ++_currWhirlButtonNum; - while (!getSubVar(V_TELEPORTER_DEST_AVAILABLE, _currWhirlButtonNum) || (_currWhirlButtonNum == 2 && _isButton2Broken) || _currLocationButtonNum == _currWhirlButtonNum) { - ++_currWhirlButtonNum; - if (_currWhirlButtonNum >= 6) - _currWhirlButtonNum = 0; - } - if (_currWhirlButtonNum != _prevWhirlButtonNum || _skipCountdown == 0) { - _ssLocationButtonLights[_currWhirlButtonNum]->show(); - _skipCountdown = 4; - } - _countdown1 = 2; - --_skipCountdown; - _prevWhirlButtonNum = _currWhirlButtonNum; - } else if (_blinkOn) { - _blinkOn = false; - _ssLocationButtonLights[_selectedButtonNum]->hide(); - _countdown1 = 16; - } else { - _blinkOn = true; - _ssLocationButtonLights[_selectedButtonNum]->show(); - _countdown1 = 4; - } - } -} - -uint32 Scene2901::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) - leaveScene((uint32)-1); - break; - case 0x2000: - if (_currLocationButtonNum != _selectedButtonNum) - leaveScene(_selectedButtonNum); - break; - case 0x2001: - if (_currLocationButtonNum == _selectedButtonNum) - _selectedButtonNum = _currWhirlButtonNum; - _ssLocationButtonLights[_selectedButtonNum]->hide(); - _selectedButtonNum = param.asInteger(); - if (!getSubVar(V_TELEPORTER_DEST_AVAILABLE, _selectedButtonNum)) - _selectedButtonNum = _currLocationButtonNum; - break; - } - return 0; -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module2900.h b/engines/neverhood/module2900.h deleted file mode 100644 index 19514399e5..0000000000 --- a/engines/neverhood/module2900.h +++ /dev/null @@ -1,102 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE2900_H -#define NEVERHOOD_MODULE2900_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" - -namespace Neverhood { - -// Module2900 - -class Module2900 : public Module { -public: - Module2900(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - int _sceneNum; - int _teleporterModuleResult; - void createScene(int sceneNum, int which); - void updateScene(); - void updateMusic(bool halfVolume); -}; - -class SsScene2901LocationButton : public StaticSprite { -public: - SsScene2901LocationButton(NeverhoodEngine *vm, Scene *parentScene, int which, uint index); -protected: - Scene *_parentScene; - uint _index; - int _countdown1; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsScene2901LocationButtonLight : public StaticSprite { -public: - SsScene2901LocationButtonLight(NeverhoodEngine *vm, int which, uint index); - void show(); - void hide(); -protected: - uint _index; -}; - -class SsScene2901BrokenButton : public StaticSprite { -public: - SsScene2901BrokenButton(NeverhoodEngine *vm, int which); -}; - -class SsScene2901BigButton : public StaticSprite { -public: - SsScene2901BigButton(NeverhoodEngine *vm, Scene *parentScene, int which); -protected: - Scene *_parentScene; - int _which; - int _countdown1; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene2901 : public Scene { -public: - Scene2901(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_ssLocationButtons[6]; - SsScene2901LocationButtonLight *_ssLocationButtonLights[6]; - Sprite *_ssBigButton; - int _currWhirlButtonNum; - int _prevWhirlButtonNum; - int _countdown1; - int _currLocationButtonNum; - int _selectedButtonNum; - int _skipCountdown; - int _blinkOn; - bool _isButton2Broken; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE2900_H */ diff --git a/engines/neverhood/module3000.cpp b/engines/neverhood/module3000.cpp deleted file mode 100644 index d08ff9d6ae..0000000000 --- a/engines/neverhood/module3000.cpp +++ /dev/null @@ -1,1548 +0,0 @@ -/* 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/module3000.h" -#include "neverhood/gamemodule.h" -#include "neverhood/navigationscene.h" - -namespace Neverhood { - -static const uint32 kModule3000SoundList[] = { - 0x92025040, - 0x90035066, - 0x90815450, - 0x99801500, - 0x90E14440, - 0x16805048, - 0x90F0D1C3, - 0 -}; - -Module3000::Module3000(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule), _soundVolume(0) { - - _vm->_soundMan->addSoundList(0x81293110, kModule3000SoundList); - _vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 50, 600, 5, 150); - _vm->_soundMan->setSoundParams(0x90F0D1C3, false, 20000, 30000, 20000, 30000); - _vm->_soundMan->playTwoSounds(0x81293110, 0x48498E46, 0x50399F64, 0); - _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); - _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); - - _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; - - if (_isWallBroken) { - _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); - _vm->_soundMan->playSoundLooping(0x90F0D1C3); - } - - if (which < 0) { - createScene(_vm->gameState().sceneNum, -1); - } else if (which == 0) { - createScene(1, 0); - } else if (which == 1) { - createScene(4, 2); - } else if (which == 2) { - createScene(4, 1); - } else if (which == 3) { - createScene(5, 1); - } - -} - -Module3000::~Module3000() { - _vm->_soundMan->deleteGroup(0x81293110); -} - -void Module3000::createScene(int sceneNum, int which) { - static const byte kNavigationTypes05[] = {3, 0}; - static const byte kNavigationTypes06[] = {5}; - debug("Module3000::createScene(%d, %d)", sceneNum, which); - _vm->gameState().sceneNum = sceneNum; - switch (_vm->gameState().sceneNum) { - case 1: - if (!getGlobalVar(V_BOLT_DOOR_OPEN)) { - createNavigationScene(0x004B7C80, which); - } else if (getGlobalVar(V_WALL_BROKEN)) { - createNavigationScene(0x004B7CE0, which); - } else { - createNavigationScene(0x004B7CB0, which); - } - break; - case 2: - _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); - if (_isWallBroken) { - _soundVolume = 90; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, 90); - } - if (getGlobalVar(V_WALL_BROKEN)) { - createNavigationScene(0x004B7D58, which); - } else { - createNavigationScene(0x004B7D10, which); - } - break; - case 3: - if (getGlobalVar(V_STAIRS_DOWN)) - createNavigationScene(0x004B7E60, which); - else if (getGlobalVar(V_WALL_BROKEN)) - createNavigationScene(0x004B7DA0, which); - else - createNavigationScene(0x004B7E00, which); - break; - case 4: - if (getGlobalVar(V_STAIRS_DOWN)) - createNavigationScene(0x004B7F20, which); - else - createNavigationScene(0x004B7EC0, which); - break; - case 5: - createNavigationScene(0x004B7F80, which, kNavigationTypes05); - break; - case 6: - createNavigationScene(0x004B7FB0, which, kNavigationTypes06); - break; - case 7: - _vm->_soundMan->setSoundListParams(kModule3000SoundList, false, 0, 0, 0, 0); - if (!getSubVar(VA_IS_PUZZLE_INIT, 0x089809C2)) { - setSubVar(VA_IS_PUZZLE_INIT, 0x089809C2, 1); - createSmackerScene(0x90022001, true, true, false); - } else - createSmackerScene(0x98022001, true, true, false); - break; - case 8: - _childObject = new Scene3009(_vm, this, which); - break; - case 9: - _childObject = new Scene3010(_vm, this, 0); - break; - case 10: - _childObject = new Scene3011(_vm, this, 0); - break; - case 11: - _vm->_soundMan->setSoundListParams(kModule3000SoundList, false, 0, 0, 0, 0); - if (!getSubVar(VA_IS_PUZZLE_INIT, 0x10130993)) { - setSubVar(VA_IS_PUZZLE_INIT, 0x10130993, 1); - createSmackerScene(0x31093019, true, true, false); - } else - createSmackerScene(0x20093019, true, true, false); - break; - case 12: - _childObject = new Scene3010(_vm, this, 1); - break; - // NOTE: Newly introduced sceneNums - case 1001: - if (!getGlobalVar(V_BOLT_DOOR_OPEN)) - if (getGlobalVar(V_WALL_BROKEN)) - createSmackerScene(0x00940021, true, true, false); - else - createSmackerScene(0x01140021, true, true, false); - else - if (getGlobalVar(V_WALL_BROKEN)) - createSmackerScene(0x001011B1, true, true, false); - else - createSmackerScene(0x001021B1, true, true, false); - setGlobalVar(V_BOLT_DOOR_OPEN, getGlobalVar(V_BOLT_DOOR_OPEN) ? 0 : 1); - break; - case 1006: - createSmackerScene(0x080810C5, true, true, false); - break; - case 1008: - createSmackerScene(getGlobalVar(V_CANNON_SMACKER_NAME), true, true, false); - break; - } - SetUpdateHandler(&Module3000::updateScene); - _childObject->handleUpdate(); -} - -void Module3000::updateScene() { - if (!updateChild()) { - switch (_vm->gameState().sceneNum) { - case 1: - if (!getGlobalVar(V_BOLT_DOOR_OPEN)) { - if (_moduleResult == 0) - createScene(9, -1); - else if (_moduleResult == 1) - leaveModule(0); - } else { - if (_moduleResult == 0) - if (_navigationAreaType == 2) - createScene(2, 0); - else - createScene(1001, -1); - else if (_moduleResult == 1) - leaveModule(0); - } - break; - case 2: - _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); - if (_isWallBroken) { - _soundVolume = 0; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); - } - if (_moduleResult == 0) { - createScene(3, 0); - } else if (_moduleResult == 1) { - setGlobalVar(V_BOLT_DOOR_OPEN, 0); - createScene(1, 1); - } - break; - case 3: - if (_moduleResult == 1) - createScene(4, 0); - else if (_moduleResult == 3) - createScene(10, -1); - else if (getGlobalVar(V_STAIRS_DOWN)) - createScene(5, 0); - else - createScene(2, 1); - break; - case 4: - if (_moduleResult == 0) - leaveModule(1); - else if (_moduleResult == 1) - createScene(7, -1); - else if (_moduleResult == 2) - createScene(3, 3); - break; - case 5: - if (_moduleResult == 0) - createScene(6, 0); - else if (_moduleResult == 1) - createScene(3, 0); - break; - case 6: - if (_navigationAreaType == 4) - createScene(11, -1); - else - createScene(1006, -1); - break; - case 7: - createScene(8, -1); - break; - case 8: - _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; - if (_moduleResult != 1) { - _vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 0, 0, 0, 0); - createScene(4, 1); - } else if (getGlobalVar(V_CANNON_SMACKER_NAME)) { - createScene(1008, -1); - } else { - _vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 0, 0, 0, 0); - createScene(4, 1); - } - break; - case 9: - if (_moduleResult == 0 || _moduleResult == 2) - createScene(1, 0); - else if (_moduleResult == 1) - createScene(1001, -1); - break; - case 10: - createScene(3, 3); - break; - case 11: - leaveModule(3); - break; - case 12: - createScene(1, 0); - break; - case 1001: - if (getGlobalVar(V_BOLT_DOOR_OPEN)) - createScene(1, 0); - else - createScene(12, -1); - break; - case 1006: - createScene(5, 0); - break; - case 1008: - createScene(8, -1); - break; - } - } else { - switch (_vm->gameState().sceneNum) { - case 1: - if (navigationScene()->isWalkingForward()) { - uint32 frameNumber = navigationScene()->getFrameNumber(); - int navigationIndex = navigationScene()->getNavigationIndex(); - if (navigationIndex == 1) { - if (frameNumber == 0) { - _vm->_soundMan->playTwoSounds(0x81293110, 0x48498E46, 0x50399F64, 0); - _vm->_soundMan->setSoundVolume(0x48498E46, 70); - _vm->_soundMan->setSoundVolume(0x50399F64, 70); - } else if (frameNumber == 100) { - _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); - } - } else if (navigationIndex == 0) { - if (frameNumber == 0) { - _vm->_soundMan->playTwoSounds(0x81293110, 0x48498E46, 0x50399F64, 0); - _vm->_soundMan->setSoundVolume(0x48498E46, 70); - _vm->_soundMan->setSoundVolume(0x50399F64, 70); - } else if (frameNumber == 10) { - _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); - } - if (_isWallBroken && _soundVolume < 90 && frameNumber % 2) { - if (frameNumber == 0) - _soundVolume = 40; - else - _soundVolume++; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); - } - } - } - break; - case 2: - if (navigationScene()->isWalkingForward()) { - uint32 frameNumber = navigationScene()->getFrameNumber(); - int navigationIndex = navigationScene()->getNavigationIndex(); - if (_isWallBroken && _soundVolume > 1 && frameNumber % 2) { - _soundVolume--; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); - } - if (navigationIndex == 0) { - if (frameNumber == 35) { - _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); - } - } else if (navigationIndex == 1) { - if (frameNumber == 55) { - _vm->_soundMan->playTwoSounds(0x81293110, 0x48498E46, 0x50399F64, 0); - _vm->_soundMan->setSoundVolume(0x48498E46, 70); - _vm->_soundMan->setSoundVolume(0x50399F64, 70); - } - } - } - break; - case 3: - if (navigationScene()->isWalkingForward()) { - uint32 frameNumber = navigationScene()->getFrameNumber(); - int navigationIndex = navigationScene()->getNavigationIndex(); - if (navigationIndex == 2) { - if (frameNumber == 40) { - _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); - } - if (_isWallBroken && _soundVolume < 90 && frameNumber % 2) { - if (frameNumber == 0) - _soundVolume = 40; - else - _soundVolume++; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); - } - } - } - break; - case 5: - if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 0) { - _vm->_soundMan->setTwoSoundsPlayFlag(false); - } - break; - } - } -} - -// Scene3009 - -enum { - kCTSNull = 0, - kCTSBreakWall = 1, - kCTSWall = 2, - kCTSEmptyness = 3, - kCTSFireRobotNoTarget = 4, - kCTSFireRobotIsTarget = 5, - kCTSFireNoRobot = 6, - kCTSRaiseCannon = 7, - kCTSRightRobotNoTarget = 8, - kCTSRightRobotIsTarget = 9, - kCTSRightNoRobot = 10, - kCTSLeftRobotNoTarget = 11, - kCTSLeftRobotIsTarget = 12, - kCTSLeftNoRobot = 13, - kCTSLowerCannon = 14, - kCTSCount = 14 -}; - -static const uint32 kScene3009CannonScopeVideos[] = { - 0x1010000D, - 0x340A0049, - 0x340A0049, - 0x0282081D, - 0x0082080D, - 0x0882080D, - 0x0882080D, - 0x0282081D, - 0x004B000B, - 0x014B000B, - 0x044B000B, - 0x0282081D, - 0x0282081D, - 0x0282081D, - 0x340A0049 -}; - -static const uint32 kScene3009CannonActionVideos[] = { - 0x00000000, - 0x8004001B, // 1 Fire cannon at wall, it breaks (lowered) - 0x0004001A, // 2 Fire cannon at wall, nothing happens (lowered) - 0x1048404B, // 3 Fire cannon at emptyness (raised) - 0x50200109, // 4 Fire cannon, robot missed (raised) - 0x12032109, // 5 Fire cannon, robot hit (raised) - 0x10201109, // 6 Fire cannon, no robot (raised) - 0x000A2030, // 7 Raise the cannon - 0x000A0028, // 8 - 0x000A0028, // 9 - 0x000A0028, // 10 - 0x040A1069, // 11 - 0x040A1069, // 12 - 0x040A1069, // 13 - 0x240A1101 // 14 Lower the cannon -}; - -static const uint32 kSsScene3009SymbolEdgesFileHashes[] = { - 0x618827A0, - 0xB1A92322 -}; - -static const uint32 kSsScene3009TargetLineFileHashes[] = { - 0x4011018C, - 0x15086623 -}; - -static const NPoint kAsScene3009SymbolPoints[] = { - {289, 338}, - {285, 375}, - {284, 419}, - {456, 372}, - {498, 372}, - {541, 372} -}; - -static const uint32 kAsScene3009SymbolFileHashes[] = { - 0x24542582, - 0x1CD61D96 -}; - -static const uint32 kSsScene3009SymbolArrowFileHashes1[] = { - 0x24016060, - 0x21216221, - 0x486160A0, - 0x42216422, - 0x90A16120, - 0x84216824, - 0x08017029, - 0x08217029, - 0x10014032, - 0x10214032, - 0x20012004, - 0x20212004 -}; - -static const uint32 kSsScene3009SymbolArrowFileHashes2[] = { - 0x40092024, - 0x01636002, - 0x8071E028, - 0x02A56064, - 0x00806031, - 0x052960A8, - 0x0A116130, - 0x0A316130, - 0x14216200, - 0x14016200, - 0x28416460, - 0x28616460 -}; - -SsScene3009FireCannonButton::SsScene3009FireCannonButton(NeverhoodEngine *vm, Scene3009 *parentScene) - : StaticSprite(vm, 1400), _parentScene(parentScene), _isClicked(false) { - - loadSprite(0x120B24B0, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); - setVisible(false); - SetUpdateHandler(&SsScene3009FireCannonButton::update); - SetMessageHandler(&SsScene3009FireCannonButton::handleMessage); - loadSound(0, 0x3901B44F); -} - -void SsScene3009FireCannonButton::update() { - updatePosition(); - if (_isClicked && !isSoundPlaying(0)) { - sendMessage(_parentScene, 0x2000, 0); - setVisible(false); - } -} - -uint32 SsScene3009FireCannonButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (!_isClicked && !_parentScene->isTurning()) { - _isClicked = true; - setVisible(true); - playSound(0); - } - messageResult = 1; - break; - } - return messageResult; -} - -SsScene3009SymbolEdges::SsScene3009SymbolEdges(NeverhoodEngine *vm, int index) - : StaticSprite(vm, 1400), _blinkCountdown(0) { - - loadSprite(kSsScene3009SymbolEdgesFileHashes[index], kSLFDefDrawOffset | kSLFDefPosition, 600); - if (getGlobalVar(V_ROBOT_HIT)) - hide(); - else - startBlinking(); - SetUpdateHandler(&SsScene3009SymbolEdges::update); -} - -void SsScene3009SymbolEdges::update() { - if (_blinkCountdown != 0 && (--_blinkCountdown == 0)) { - if (_blinkToggle) { - setVisible(true); - } else { - setVisible(false); - } - updatePosition(); - _blinkCountdown = 3; - _blinkToggle = !_blinkToggle; - } -} - -void SsScene3009SymbolEdges::show() { - setVisible(true); - updatePosition(); - _blinkCountdown = 0; -} - -void SsScene3009SymbolEdges::hide() { - setVisible(false); - updatePosition(); - _blinkCountdown = 0; -} - -void SsScene3009SymbolEdges::startBlinking() { - setVisible(true); - updatePosition(); - _blinkCountdown = 3; - _blinkToggle = true; -} - -SsScene3009TargetLine::SsScene3009TargetLine(NeverhoodEngine *vm, int index) - : StaticSprite(vm, 1400) { - - loadSprite(kSsScene3009TargetLineFileHashes[index], kSLFDefDrawOffset | kSLFDefPosition, 600); - setVisible(false); -} - -void SsScene3009TargetLine::show() { - setVisible(true); - updatePosition(); -} - -SsScene3009SymbolArrow::SsScene3009SymbolArrow(NeverhoodEngine *vm, Sprite *asSymbol, int index) - : StaticSprite(vm, 1400), _asSymbol(asSymbol), _index(index), _enabled(true), _countdown(0) { - - _incrDecr = _index % 2; - - createSurface(1200, 33, 31); - loadSprite(kSsScene3009SymbolArrowFileHashes2[_index], kSLFDefPosition); - _drawOffset.set(0, 0, 33, 31); - _collisionBoundsOffset = _drawOffset; - updateBounds(); - _needRefresh = true; - - SetUpdateHandler(&SsScene3009SymbolArrow::update); - SetMessageHandler(&SsScene3009SymbolArrow::handleMessage); - loadSound(0, 0x2C852206); -} - -void SsScene3009SymbolArrow::hide() { - _enabled = false; - setVisible(false); -} - -void SsScene3009SymbolArrow::update() { - updatePosition(); - if (_countdown != 0 && (--_countdown == 0)) { - loadSprite(kSsScene3009SymbolArrowFileHashes2[_index], kSLFDefDrawOffset); - } -} - -uint32 SsScene3009SymbolArrow::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_enabled && _countdown == 0) { - _countdown = 2; - loadSprite(kSsScene3009SymbolArrowFileHashes1[_index], kSLFDefDrawOffset); - playSound(0); - sendMessage(_asSymbol, 0x2005, _incrDecr); - } - messageResult = 1; - break; - } - return messageResult; -} - -AsScene3009VerticalIndicator::AsScene3009VerticalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, int index) - : AnimatedSprite(vm, 1000), _parentScene(parentScene), _enabled(false) { - - _x = 300; - _y = getGlobalVar(V_CANNON_RAISED) ? 52 : 266; - createSurface1(0xC2463913, 1200); - _needRefresh = true; - updatePosition(); - setVisible(false); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene3009VerticalIndicator::handleMessage); -} - -void AsScene3009VerticalIndicator::show() { - startAnimation(0xC2463913, 0, -1); - setVisible(true); - updatePosition(); - _enabled = true; -} - -uint32 AsScene3009VerticalIndicator::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_enabled) { - sendMessage(_parentScene, 0x2002, 0); - } - messageResult = 1; - break; - } - return messageResult; -} - -AsScene3009HorizontalIndicator::AsScene3009HorizontalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, uint32 cannonTargetStatus) - : AnimatedSprite(vm, 1000), _parentScene(parentScene), _enabled(false) { - - _x = getGlobalVar(V_CANNON_TURNED) ? 533 : 92; - _y = 150; - createSurface1(0xC0C12954, 1200); - _needRefresh = true; - updatePosition(); - setVisible(false); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene3009HorizontalIndicator::handleMessage); - if (cannonTargetStatus == kCTSRightRobotNoTarget || cannonTargetStatus == kCTSRightRobotIsTarget || cannonTargetStatus == kCTSRightNoRobot) { - SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveRight); - _x = 280; - } -} - -uint32 AsScene3009HorizontalIndicator::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_enabled) { - sendMessage(_parentScene, 0x2004, 0); - } - messageResult = 1; - break; - } - return messageResult; -} - -void AsScene3009HorizontalIndicator::suMoveLeft() { - _x -= 6; - if (_x < 92) { - SetSpriteUpdate(NULL); - _x = 92; - } -} - -void AsScene3009HorizontalIndicator::suMoveRight() { - _x += 6; - if (_x > 533) { - SetSpriteUpdate(NULL); - _x = 533; - } -} - -void AsScene3009HorizontalIndicator::show() { - startAnimation(0xC0C12954, 0, -1); - setVisible(true); - updatePosition(); - _enabled = true; -} - -void AsScene3009HorizontalIndicator::stMoveLeft() { - _x = 533; - SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveLeft); -} - -void AsScene3009HorizontalIndicator::stMoveRight() { - _x = 330; - SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveRight); -} - -AsScene3009Symbol::AsScene3009Symbol(NeverhoodEngine *vm, Scene3009 *parentScene, int symbolPosition) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _symbolPosition(symbolPosition) { - - _symbolIndex = getSubVar(VA_CURR_CANNON_SYMBOLS, _symbolPosition); - - _x = kAsScene3009SymbolPoints[_symbolPosition].x; - _y = kAsScene3009SymbolPoints[_symbolPosition].y; - createSurface1(kAsScene3009SymbolFileHashes[_symbolPosition / 3], 1200); - startAnimation(kAsScene3009SymbolFileHashes[_symbolPosition / 3], _symbolIndex, -1); - _newStickFrameIndex = _symbolIndex; - _needRefresh = true; - updatePosition(); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene3009Symbol::handleMessage); - _ssArrowPrev = _parentScene->insertSprite(this, _symbolPosition * 2 + 0); - _parentScene->addCollisionSprite(_ssArrowPrev); - _ssArrowNext = _parentScene->insertSprite(this, _symbolPosition * 2 + 1); - _parentScene->addCollisionSprite(_ssArrowNext); -} - -uint32 AsScene3009Symbol::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2005: - if (param.asInteger()) { - if (_symbolIndex == 11) - _symbolIndex = 0; - else - _symbolIndex++; - } else { - if (_symbolIndex == 0) - _symbolIndex = 11; - else - _symbolIndex--; - } - startAnimation(kAsScene3009SymbolFileHashes[_symbolPosition / 3], _symbolIndex, -1); - _newStickFrameIndex = _symbolIndex; - setSubVar(VA_CURR_CANNON_SYMBOLS, _symbolPosition, _symbolIndex); - if (_symbolPosition / 3 == 0) { - sendMessage(_parentScene, 0x2001, 0); - } else { - sendMessage(_parentScene, 0x2003, 0); - } - messageResult = 1; - break; - } - return messageResult; -} - -void AsScene3009Symbol::hide() { - _ssArrowPrev->hide(); - _ssArrowNext->hide(); -} - -Scene3009::Scene3009(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _keepVideo(false), _moveCannonLeftFirst(false), - _isTurning(false), _lockSymbolsPart1Countdown(1), _lockSymbolsPart2Countdown(1) { - - _cannonTargetStatus = getGlobalVar(V_CANNON_TARGET_STATUS); - - _vm->gameModule()->initCannonSymbolsPuzzle(); - - setGlobalVar(V_CANNON_SMACKER_NAME, 0); - - _vm->_screen->clear(); - - setBackground(0xD000420C); - setPalette(0xD000420C); - insertPuzzleMouse(0x04208D08, 20, 620); - - _ssFireCannonButton = insertSprite(this); - addCollisionSprite(_ssFireCannonButton); - - _asVerticalIndicator = insertSprite(this, _cannonTargetStatus); - addCollisionSprite(_asVerticalIndicator); - - _asHorizontalIndicator = insertSprite(this, _cannonTargetStatus); - addCollisionSprite(_asHorizontalIndicator); - - if (_cannonTargetStatus != kCTSNull && _cannonTargetStatus != kCTSRightRobotNoTarget && _cannonTargetStatus != kCTSRightRobotIsTarget && _cannonTargetStatus != kCTSRightNoRobot) { - _keepVideo = true; - } else { - _keepVideo = false; - if (_cannonTargetStatus != kCTSNull) { - _asHorizontalIndicator->stMoveRight(); - _isTurning = true; - } - } - - _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, kScene3009CannonScopeVideos[_cannonTargetStatus], false, _keepVideo)); - _smackerPlayer->setDrawPos(89, 37); - _palette->usePalette(); // Use it again since the SmackerPlayer overrides the usage - - insertStaticSprite(0x8540252C, 400); - - for (int i = 0; i < 2; i++) { - _ssSymbolEdges[i] = insertSprite(i); - _ssTargetLines[i] = insertSprite(i); - } - - for (int symbolPosition = 0; symbolPosition < 6; symbolPosition++) { - _asSymbols[symbolPosition] = insertSprite(this, symbolPosition); - if (symbolPosition < 3) - _correctSymbols[symbolPosition] = getSubVar(VA_GOOD_CANNON_SYMBOLS_1, symbolPosition); - else - _correctSymbols[symbolPosition] = getSubVar(VA_GOOD_CANNON_SYMBOLS_2, symbolPosition - 3); - } - - SetMessageHandler(&Scene3009::handleMessage); - SetUpdateHandler(&Scene3009::update); - - // DEBUG Enable to set the correct code -#if 0 - for (int i = 0; i < 6; i++) - setSubVar(VA_CURR_CANNON_SYMBOLS, i, _correctSymbols[i]); - sendMessage(this, 0x2003, 0); -#endif - -} - -void Scene3009::update() { - Scene::update(); - - if (!_keepVideo && _smackerPlayer->isDone() && _cannonTargetStatus <= kCTSCount) { - switch (_cannonTargetStatus) { - case kCTSNull: - case kCTSLowerCannon: - _smackerPlayer->open(0x340A0049, true); - _palette->usePalette(); - _keepVideo = true; - break; - case kCTSRightRobotNoTarget: - _smackerPlayer->open(0x0082080D, true); - _palette->usePalette(); - _keepVideo = true; - _isTurning = false; - break; - case kCTSRightRobotIsTarget: - _smackerPlayer->open(0x0282080D, true); - _palette->usePalette(); - _keepVideo = true; - _isTurning = false; - break; - case kCTSRightNoRobot: - _smackerPlayer->open(0x0882080D, true); - _palette->usePalette(); - _keepVideo = true; - _isTurning = false; - break; - case kCTSLeftRobotNoTarget: - case kCTSLeftRobotIsTarget: - case kCTSLeftNoRobot: - if (_moveCannonLeftFirst) { - if (_cannonTargetStatus == kCTSLeftRobotNoTarget) - _smackerPlayer->open(0x110A000F, false); - else if (_cannonTargetStatus == kCTSLeftRobotIsTarget) - _smackerPlayer->open(0x500B004F, false); - else if (_cannonTargetStatus == kCTSLeftNoRobot) - _smackerPlayer->open(0x100B010E, false); - _palette->usePalette(); - _moveCannonLeftFirst = false; - _asHorizontalIndicator->stMoveLeft(); - } else { - playActionVideo(); - } - break; - } - } - - if (_lockSymbolsPart1Countdown != 0 && (--_lockSymbolsPart1Countdown == 0) && isSymbolsPart1Solved()) { - for (int i = 0; i < 3; i++) - _asSymbols[i]->hide(); - if (!getGlobalVar(V_ROBOT_HIT) || getGlobalVar(V_CANNON_RAISED) || getGlobalVar(V_CANNON_TURNED)) { - _ssSymbolEdges[0]->show(); - _ssTargetLines[0]->show(); - _asVerticalIndicator->show(); - } - } - - if (_lockSymbolsPart2Countdown != 0 && (--_lockSymbolsPart2Countdown == 0) && isSymbolsPart2Solved()) { - for (int i = 3; i < 6; i++) - _asSymbols[i]->hide(); - if (!getGlobalVar(V_ROBOT_HIT) || getGlobalVar(V_CANNON_RAISED) || getGlobalVar(V_CANNON_TURNED)) { - _ssSymbolEdges[1]->show(); - _ssTargetLines[1]->show(); - _asHorizontalIndicator->show(); - } - } - -} - -uint32 Scene3009::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && !getGlobalVar(V_CANNON_RAISED)) { - setGlobalVar(V_CANNON_TARGET_STATUS, 0); - leaveScene(0); - } - break; - case 0x2000: - if (!getGlobalVar(V_CANNON_RAISED)) { - if (!getGlobalVar(V_WALL_BROKEN)) { - _cannonTargetStatus = kCTSBreakWall; - setGlobalVar(V_WALL_BROKEN, 1); - } else { - _cannonTargetStatus = kCTSWall; - } - } else if (!getGlobalVar(V_CANNON_TURNED)) { - _cannonTargetStatus = kCTSEmptyness; - } else if (!getGlobalVar(V_ROBOT_TARGET)) { - _cannonTargetStatus = kCTSFireRobotNoTarget; - } else if (!getGlobalVar(V_ROBOT_HIT)) { - setGlobalVar(V_ROBOT_HIT, 1); - _cannonTargetStatus = kCTSFireRobotIsTarget; - } else { - _cannonTargetStatus = kCTSFireNoRobot; - } - playActionVideo(); - break; - case 0x2001: - _lockSymbolsPart1Countdown = 24; - break; - case 0x2002: - // Raise/lower the cannon - if (!getGlobalVar(V_CANNON_TURNED) && !_isTurning) { - if (getGlobalVar(V_CANNON_RAISED)) { - _cannonTargetStatus = kCTSLowerCannon; - setGlobalVar(V_CANNON_RAISED, 0); - } else { - _cannonTargetStatus = kCTSRaiseCannon; - setGlobalVar(V_CANNON_RAISED, 1); - } - playActionVideo(); - } - break; - case 0x2003: - _lockSymbolsPart2Countdown = 24; - break; - case 0x2004: - // Turn the cannon if it's raised - if (getGlobalVar(V_CANNON_RAISED)) { - if (!getGlobalVar(V_CANNON_TURNED)) { - // Cannon is at the left position - if (!getGlobalVar(V_ROBOT_TARGET)) { - _cannonTargetStatus = kCTSRightRobotNoTarget; - } else if (!getGlobalVar(V_ROBOT_HIT)) { - _cannonTargetStatus = kCTSRightRobotIsTarget; - } else { - _cannonTargetStatus = kCTSRightNoRobot; - } - setGlobalVar(V_CANNON_TURNED, 1); - _isTurning = true; - playActionVideo(); - } else { - // Cannon is at the right position - if (!getGlobalVar(V_ROBOT_TARGET)) { - _cannonTargetStatus = kCTSLeftRobotNoTarget; - _smackerPlayer->open(0x108A000F, false); - } else if (!getGlobalVar(V_ROBOT_HIT)) { - _cannonTargetStatus = kCTSLeftRobotIsTarget; - _smackerPlayer->open(0x500B002F, false); - } else { - _cannonTargetStatus = kCTSLeftNoRobot; - _smackerPlayer->open(0x100B008E, false); - } - _palette->usePalette(); - _moveCannonLeftFirst = true; - _isTurning = true; - _keepVideo = false; - setGlobalVar(V_CANNON_TURNED, 0); - } - } - break; - } - return 0; -} - -void Scene3009::playActionVideo() { - setGlobalVar(V_CANNON_TARGET_STATUS, _cannonTargetStatus); - setGlobalVar(V_CANNON_SMACKER_NAME, kScene3009CannonActionVideos[_cannonTargetStatus]); - leaveScene(1); -} - -bool Scene3009::isSymbolsPart1Solved() { - for (int i = 0; i < 3; i++) - if (_correctSymbols[i] != getSubVar(VA_CURR_CANNON_SYMBOLS, i)) - return false; - return true; -} - -bool Scene3009::isSymbolsPart2Solved() { - for (int i = 3; i < 6; i++) - if (_correctSymbols[i] != getSubVar(VA_CURR_CANNON_SYMBOLS, i)) - return false; - return true; -} - -bool Scene3009::isTurning() { - return _isTurning; -} - -// Scene3010 - -static const uint32 kScene3010ButtonNameHashes[] = { - 0x304008D2, - 0x40119852, - 0x01180951 -}; - -static const uint32 kScene3010DeadBoltButtonFileHashes1[] = { - 0x301024C2, - 0x20280580, - 0x30200452 -}; - -static const uint32 kScene3010DeadBoltButtonFileHashes2[] = { - 0x50C025A8, - 0x1020A0A0, - 0x5000A7E8 -}; - -static const NPoint kAsScene3010DeadBoltPoints[] = { - {550, 307}, - {564, 415}, - {560, 514} -}; - -static const uint32 kAsScene3010DeadBoltFileHashes2[] = { - 0x181A0042, - 0x580A08F2, - 0x18420076 -}; - -static const uint32 kAsScene3010DeadBoltFileHashes1[] = { - 0x300E105A, - 0x804E0052, - 0x040E485A -}; - -SsScene3010DeadBoltButton::SsScene3010DeadBoltButton(NeverhoodEngine *vm, Scene *parentScene, int buttonIndex, int initCountdown, bool initDisabled) - : StaticSprite(vm, 900), _parentScene(parentScene), _buttonLocked(false), _countdown1(0), _countdown2(0), _buttonIndex(buttonIndex) { - - _buttonEnabled = getSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[_buttonIndex]) != 0; - createSurface(400, 88, 95); - setSprite(kScene3010DeadBoltButtonFileHashes2[_buttonIndex]); - if (initDisabled) - disableButton(); - else if (_buttonEnabled) - _countdown1 = initCountdown * 12 + 1; - loadSound(0, 0xF4217243); - loadSound(1, 0x44049000); - loadSound(2, 0x6408107E); - SetUpdateHandler(&SsScene3010DeadBoltButton::update); - SetMessageHandler(&SsScene3010DeadBoltButton::handleMessage); -} - -void SsScene3010DeadBoltButton::update() { - - if (_countdown1 != 0 && (--_countdown1 == 0)) { - playSound(0); - setVisible(false); - setSprite(kScene3010DeadBoltButtonFileHashes1[_buttonIndex]); - } - - if (_countdown2 != 0 && (--_countdown2 == 0)) { - setVisible(true); - setSprite(kScene3010DeadBoltButtonFileHashes2[_buttonIndex]); - } - -} - -uint32 SsScene3010DeadBoltButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (!_buttonLocked && _countdown1 == 0) { - if (_buttonEnabled) { - playSound(1); - playSound(2); - setVisible(true); - _buttonLocked = true; - sendMessage(_parentScene, 0x2000, _buttonIndex); - } else { - sendMessage(_parentScene, 0x2002, _buttonIndex); - } - _needRefresh = true; - updatePosition(); - } - messageResult = 1; - break; - } - return messageResult; -} - -void SsScene3010DeadBoltButton::disableButton() { - _buttonLocked = true; - setSprite(kScene3010DeadBoltButtonFileHashes1[_buttonIndex]); - setVisible(true); -} - -void SsScene3010DeadBoltButton::setSprite(uint32 fileHash) { - loadSprite(fileHash, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset); -} - -void SsScene3010DeadBoltButton::setCountdown(int count) { - _countdown2 = count * 18 + 1; -} - -AsScene3010DeadBolt::AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene, int boltIndex, bool initUnlocked) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _boltIndex(boltIndex), _soundToggle(true), - _unlocked(false), _locked(false), _countdown(0) { - - _x = kAsScene3010DeadBoltPoints[_boltIndex].x; - _y = kAsScene3010DeadBoltPoints[_boltIndex].y; - - if (getSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[_boltIndex])) { - createSurface1(kAsScene3010DeadBoltFileHashes1[_boltIndex], 1200); - startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1); - loadSound(0, 0x46005BC4); - } else { - createSurface1(kAsScene3010DeadBoltFileHashes2[_boltIndex], 1200); - startAnimation(kAsScene3010DeadBoltFileHashes2[_boltIndex], 0, -1); - loadSound(0, 0x420073DC); - loadSound(1, 0x420073DC); - } - - setVisible(false); - stIdle(); - if (initUnlocked) - unlock(true); - - _needRefresh = true; - AnimatedSprite::updatePosition(); - -} - -void AsScene3010DeadBolt::update() { - updateAnim(); - updatePosition(); - if (_countdown != 0 && (--_countdown == 0)) { - stDisabled(); - } -} - -uint32 AsScene3010DeadBolt::hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene3010DeadBolt::stIdle() { - stopAnimation(); - SetUpdateHandler(&AsScene3010DeadBolt::update); - SetMessageHandler(&Sprite::handleMessage); - _locked = false; -} - -void AsScene3010DeadBolt::unlock(bool skipAnim) { - if (!_unlocked) { - setVisible(true); - if (skipAnim) { - startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], -1, 0); - _newStickFrameIndex = STICK_LAST_FRAME; - } else { - startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1); - SetMessageHandler(&AsScene3010DeadBolt::hmAnimation); - FinalizeState(&AsScene3010DeadBolt::stIdleMessage); - NextState(&AsScene3010DeadBolt::stIdle); - playSound(0); - } - _unlocked = true; - loadSound(2, 0x4010C345); - } -} - -void AsScene3010DeadBolt::stIdleMessage() { - stopAnimation(); - SetMessageHandler(&Sprite::handleMessage); - sendMessage(_parentScene, 0x2001, _boltIndex); -} - -void AsScene3010DeadBolt::lock() { - if (!_locked) { - _locked = true; - setVisible(true); - startAnimation(kAsScene3010DeadBoltFileHashes2[_boltIndex], 0, -1); - SetMessageHandler(&AsScene3010DeadBolt::hmAnimation); - FinalizeState(&AsScene3010DeadBolt::stDisabledMessage); - NextState(&AsScene3010DeadBolt::stIdle); - if (_soundToggle) { - playSound(0); - } else { - playSound(1); - } - _soundToggle = !_soundToggle; - } -} - -void AsScene3010DeadBolt::setCountdown(int count) { - _countdown = count * 18 + 1; -} - -void AsScene3010DeadBolt::stDisabled() { - setVisible(true); - startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1); - SetMessageHandler(&AsScene3010DeadBolt::hmAnimation); - FinalizeState(&AsScene3010DeadBolt::stDisabledMessage); - NextState(&AsScene3010DeadBolt::stIdle); - _playBackwards = true; - playSound(2); -} - -void AsScene3010DeadBolt::stDisabledMessage() { - setVisible(false); - sendMessage(_parentScene, 0x2003, _boltIndex); -} - -Scene3010::Scene3010(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _countdown(0), _doorUnlocked(false), _checkUnlocked(false) { - - int initCountdown = 0; - - // DEBUG Enable to activate all buttons -#if 0 - setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[0], 1); - setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[1], 1); - setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[2], 1); -#endif - - setBackground(0x80802626); - setPalette(0x80802626); - - for (int i = 0; i < 3; i++) { - _asDeadBolts[i] = insertSprite(this, i, which == 1);//CHECKME - _ssDeadBoltButtons[i] = insertSprite(this, i, initCountdown, which == 1);//CHECKME - addCollisionSprite(_ssDeadBoltButtons[i]); - if (getSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[i])) - initCountdown++; - _boltUnlocking[i] = false; - _boltUnlocked[i] = false; - } - - if (which == 0) { - insertPuzzleMouse(0x02622800, 20, 620); - } - - loadSound(0, 0x68E25540); - - SetMessageHandler(&Scene3010::handleMessage); - SetUpdateHandler(&Scene3010::update); - - if (which == 1) { - _checkUnlocked = true; - for (int i = 0; i < 3; i++) { - _boltUnlocked[i] = true; - _ssDeadBoltButtons[i]->setCountdown(i + 1); - _asDeadBolts[i]->setCountdown(i + 1); - } - } - -} - -void Scene3010::update() { - Scene::update(); - if (_checkUnlocked && !_boltUnlocked[0] && !_boltUnlocked[1] && !_boltUnlocked[2]) { - _countdown = 24; - _checkUnlocked = false; - } - if (_countdown != 0 && (--_countdown == 0)) { - leaveScene(_doorUnlocked ? 1 : 0); - } -} - -uint32 Scene3010::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && _countdown == 0 && !_checkUnlocked) { - if (!_boltUnlocking[0] && !_boltUnlocking[1] && !_boltUnlocking[2]) { - showMouse(false); - if (!_boltUnlocked[0] && !_boltUnlocked[1] && !_boltUnlocked[2]) { - _countdown = 1; - } else { - _checkUnlocked = true; - for (int i = 0; i < 3; i++) { - _ssDeadBoltButtons[i]->setCountdown(i); - if (_boltUnlocked[i]) { - _asDeadBolts[i]->setCountdown(i); - } - } - } - } - } - break; - case 0x2000: - if (!_boltUnlocked[param.asInteger()] && !_checkUnlocked && _countdown == 0) { - _asDeadBolts[param.asInteger()]->unlock(false); - _boltUnlocking[param.asInteger()] = true; - } - break; - case 0x2001: - _boltUnlocked[param.asInteger()] = true; - _boltUnlocking[param.asInteger()] = false; - if (_boltUnlocked[0] && _boltUnlocked[1] && _boltUnlocked[2]) { - if (!getGlobalVar(V_BOLT_DOOR_UNLOCKED)) { - setGlobalVar(V_BOLT_DOOR_UNLOCKED, 1); - playSound(0); - _countdown = 60; - } else { - _countdown = 48; - } - _doorUnlocked = true; - } - break; - case 0x2002: - if (!_checkUnlocked && _countdown == 0) { - _asDeadBolts[param.asInteger()]->lock(); - } - break; - case 0x2003: - _boltUnlocked[param.asInteger()] = false; - break; - } - return 0; -} - -// Scene3011 - -static const uint32 kAsScene3011SymbolFileHashes[] = { - 0x00C88050, - 0x01488050, - 0x02488050, - 0x04488050, - 0x08488050, - 0x10488050, - 0x20488050, - 0x40488050, - 0x80488050, - 0x00488051, - 0x00488052, - 0x00488054, - 0x008B0000, - 0x008D0000, - 0x00810000, - 0x00990000, - 0x00A90000, - 0x00C90000, - 0x00090000, - 0x01890000, - 0x02890000, - 0x04890000, - 0x08890000, - 0x10890000 -}; - -SsScene3011Button::SsScene3011Button(NeverhoodEngine *vm, Scene *parentScene, bool flag) - : StaticSprite(vm, 1400), _parentScene(parentScene), _countdown(0) { - - loadSprite(flag ? 0x11282020 : 0x994D0433, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); - setVisible(false); - loadSound(0, 0x44061000); - SetUpdateHandler(&SsScene3011Button::update); - SetMessageHandler(&SsScene3011Button::handleMessage); -} - -void SsScene3011Button::update() { - updatePosition(); - if (_countdown != 0 && (--_countdown == 0)) { - setVisible(false); - } -} - -uint32 SsScene3011Button::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = 0; - StaticSprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_countdown == 0) { - setVisible(true); - _countdown = 4; - sendMessage(_parentScene, 0x2000, 0); - playSound(0); - } - messageResult = 1; - break; - } - return messageResult; -} - -AsScene3011Symbol::AsScene3011Symbol(NeverhoodEngine *vm, int symbolIndex, bool largeSymbol) - : AnimatedSprite(vm, 1000), _symbolIndex(symbolIndex), _largeSymbol(largeSymbol), _isNoisy(false) { - - if (_largeSymbol) { - _x = 310; - _y = 200; - createSurface1(kAsScene3011SymbolFileHashes[_symbolIndex], 1200); - loadSound(0, 0x6052C60F); - loadSound(1, 0x6890433B); - } else { - _symbolIndex = 12; - _x = symbolIndex * 39 + 96; - _y = 225; - createSurface(1200, 41, 48); - loadSound(0, 0x64428609); - loadSound(1, 0x7080023B); - } - setVisible(false); - _needRefresh = true; - SetUpdateHandler(&AnimatedSprite::update); -} - -void AsScene3011Symbol::show(bool isNoisy) { - _isNoisy = isNoisy; - startAnimation(kAsScene3011SymbolFileHashes[_symbolIndex], 0, -1); - setVisible(true); - if (_isNoisy) { - playSound(1); - } else { - playSound(0); - } -} - -void AsScene3011Symbol::hide() { - stopAnimation(); - setVisible(false); -} - -void AsScene3011Symbol::stopSymbolSound() { - if (_isNoisy) { - stopSound(1); - } else { - stopSound(0); - } -} - -void AsScene3011Symbol::change(int symbolIndex, bool isNoisy) { - _symbolIndex = symbolIndex; - _isNoisy = isNoisy; - startAnimation(kAsScene3011SymbolFileHashes[_symbolIndex], 0, -1); - setVisible(true); - if (_isNoisy) { - playSound(1); - } else { - playSound(0); - } -} - -Scene3011::Scene3011(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _updateStatus(0), _buttonClicked(false), _currentSymbolIndex(0), _countdown(0) { - - _vm->gameModule()->initCodeSymbolsPuzzle(); - _noisySymbolIndex = getGlobalVar(V_NOISY_SYMBOL_INDEX); - - SetMessageHandler(&Scene3011::handleMessage); - SetUpdateHandler(&Scene3011::update); - - setBackground(0x92124A04); - setPalette(0xA4070114); - addEntity(_palette); - - insertPuzzleMouse(0x24A00929, 20, 620); - - for (int symbolIndex = 0; symbolIndex < 12; symbolIndex++) - _asSymbols[symbolIndex] = insertSprite(symbolIndex, true); - - _ssButton = insertSprite(this, true); - addCollisionSprite(_ssButton); - -} - -void Scene3011::update() { - Scene::update(); - - if (_countdown != 0 && (--_countdown == 0)) { - switch (_updateStatus) { - case 0: - if (_buttonClicked) { - if (_noisySymbolIndex == _currentSymbolIndex) { - do { - _noisyRandomSymbolIndex = _vm->_rnd->getRandomNumber(12 - 1); - } while (_noisySymbolIndex == _noisyRandomSymbolIndex); - _asSymbols[getSubVar(VA_CODE_SYMBOLS, _noisyRandomSymbolIndex)]->show(true); - } else { - _asSymbols[getSubVar(VA_CODE_SYMBOLS, _currentSymbolIndex)]->show(false); - } - _updateStatus = 1; - _countdown = 24; - fadeIn(); - _buttonClicked = false; - } - break; - case 1: - _updateStatus = 2; - _countdown = 24; - break; - case 2: - fadeOut(); - _updateStatus = 3; - _countdown = 24; - break; - case 3: - _updateStatus = 0; - _countdown = 1; - if (_noisySymbolIndex == _currentSymbolIndex) { - _asSymbols[getSubVar(VA_CODE_SYMBOLS, _noisyRandomSymbolIndex)]->hide(); - } else { - _asSymbols[getSubVar(VA_CODE_SYMBOLS, _currentSymbolIndex)]->hide(); - } - _currentSymbolIndex++; - if (_currentSymbolIndex >= 12) - _currentSymbolIndex = 0; - break; - } - } -} - -uint32 Scene3011::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - Scene::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { - leaveScene(0); - } - break; - case 0x2000: - _buttonClicked = true; - if (_countdown == 0) - _countdown = 1; - break; - } - return 0; -} - -void Scene3011::fadeIn() { - _palette->addBasePalette(0x92124A04, 0, 256, 0); - _palette->startFadeToPalette(24); -} - -void Scene3011::fadeOut() { - _palette->addBasePalette(0xA4070114, 0, 256, 0); - _palette->startFadeToPalette(24); -} - -} // End of namespace Neverhood diff --git a/engines/neverhood/module3000.h b/engines/neverhood/module3000.h deleted file mode 100644 index 0fd1a1ed70..0000000000 --- a/engines/neverhood/module3000.h +++ /dev/null @@ -1,255 +0,0 @@ -/* 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. - * - */ - -#ifndef NEVERHOOD_MODULE3000_H -#define NEVERHOOD_MODULE3000_H - -#include "neverhood/neverhood.h" -#include "neverhood/module.h" -#include "neverhood/scene.h" -#include "neverhood/module1200.h" - -namespace Neverhood { - -class Module3000 : public Module { -public: - Module3000(NeverhoodEngine *vm, Module *parentModule, int which); - virtual ~Module3000(); -protected: - int _soundVolume; - bool _isWallBroken; - void createScene(int sceneNum, int which); - void updateScene(); -}; - -// Scene3009 - -class Scene3009; - -class SsScene3009FireCannonButton : public StaticSprite { -public: - SsScene3009FireCannonButton(NeverhoodEngine *vm, Scene3009 *parentScene); -protected: - Scene3009 *_parentScene; - bool _isClicked; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsScene3009SymbolEdges : public StaticSprite { -public: - SsScene3009SymbolEdges(NeverhoodEngine *vm, int index); - void show(); - void hide(); - void startBlinking(); -protected: - int _blinkCountdown; - bool _blinkToggle; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class SsScene3009TargetLine : public StaticSprite { -public: - SsScene3009TargetLine(NeverhoodEngine *vm, int index); - void show(); -}; - -class SsScene3009SymbolArrow : public StaticSprite { -public: - SsScene3009SymbolArrow(NeverhoodEngine *vm, Sprite *asSymbol, int index); - void hide(); -protected: - Sprite *_asSymbol; - int _index; - int _incrDecr; - bool _enabled; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene3009VerticalIndicator : public AnimatedSprite { -public: - AsScene3009VerticalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, int index); - void show(); -protected: - Scene3009 *_parentScene; - bool _enabled; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene3009HorizontalIndicator : public AnimatedSprite { -public: - AsScene3009HorizontalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, uint32 cannonTargetStatus); - void show(); - void stMoveLeft(); - void stMoveRight(); -protected: - Scene3009 *_parentScene; - bool _enabled; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suMoveLeft(); - void suMoveRight(); -}; - -class AsScene3009Symbol : public AnimatedSprite { -public: - AsScene3009Symbol(NeverhoodEngine *vm, Scene3009 *parentScene, int symbolPosition); - void hide(); -protected: - Scene3009 *_parentScene; - int _symbolPosition; - uint32 _symbolIndex; - SsScene3009SymbolArrow *_ssArrowPrev; - SsScene3009SymbolArrow *_ssArrowNext; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class Scene3009 : public Scene { -public: - Scene3009(NeverhoodEngine *vm, Module *parentModule, int which); - bool isTurning(); -protected: - int _lockSymbolsPart1Countdown; - int _lockSymbolsPart2Countdown; - SmackerPlayer *_smackerPlayer; - Sprite *_ssFireCannonButton; - SsScene3009SymbolEdges *_ssSymbolEdges[2]; - SsScene3009TargetLine *_ssTargetLines[2]; - AsScene3009VerticalIndicator *_asVerticalIndicator; - AsScene3009HorizontalIndicator *_asHorizontalIndicator; - AsScene3009Symbol *_asSymbols[6]; - uint32 _cannonTargetStatus; - uint32 _correctSymbols[6]; - bool _keepVideo; - bool _moveCannonLeftFirst; - bool _isTurning; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void playActionVideo(); - bool isSymbolsPart1Solved(); - bool isSymbolsPart2Solved(); -}; - -// Scene3010 - -class SsScene3010DeadBoltButton : public StaticSprite { -public: - SsScene3010DeadBoltButton(NeverhoodEngine *vm, Scene *parentScene, int buttonIndex, int initCountdown, bool initDisabled); - void setCountdown(int count); -protected: - Scene *_parentScene; - int _buttonIndex; - bool _buttonEnabled; - bool _buttonLocked; - int _countdown1; - int _countdown2; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void disableButton(); - void setSprite(uint32 fileHash); -}; - -class AsScene3010DeadBolt : public AnimatedSprite { -public: - AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene, int boltIndex, bool initUnlocked); - void setCountdown(int count); - void lock(); - void unlock(bool skipAnim); -protected: - Scene *_parentScene; - int _boltIndex; - int _countdown; - bool _soundToggle; - bool _unlocked; - bool _locked; - void update(); - uint32 hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender); - void stIdle(); - void stIdleMessage(); - void stDisabled(); - void stDisabledMessage(); -}; - -class Scene3010 : public Scene { -public: - Scene3010(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - int _countdown; - bool _doorUnlocked; - bool _checkUnlocked; - SsScene3010DeadBoltButton *_ssDeadBoltButtons[3]; - AsScene3010DeadBolt *_asDeadBolts[3]; - bool _boltUnlocked[3]; - bool _boltUnlocking[3]; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -// Scene3011 - -class SsScene3011Button : public StaticSprite { -public: - SsScene3011Button(NeverhoodEngine *vm, Scene *parentScene, bool flag); -protected: - Scene *_parentScene; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - -class AsScene3011Symbol : public AnimatedSprite { -public: - AsScene3011Symbol(NeverhoodEngine *vm, int symbolIndex, bool largeSymbol); - void show(bool isNoisy); - void hide(); - void stopSymbolSound(); - void change(int symbolIndex, bool isNoisy); - int getSymbolIndex() { return _largeSymbol ? _symbolIndex : _symbolIndex - 12; } -protected: - bool _largeSymbol; - bool _isNoisy; - int _symbolIndex; -}; - -class Scene3011 : public Scene { -public: - Scene3011(NeverhoodEngine *vm, Module *parentModule, int which); -protected: - Sprite *_ssButton; - AsScene3011Symbol *_asSymbols[12]; - int _updateStatus; - bool _buttonClicked; - int _countdown; - int _noisySymbolIndex; - int _currentSymbolIndex; - int _noisyRandomSymbolIndex; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void fadeIn(); - void fadeOut(); -}; - -} // End of namespace Neverhood - -#endif /* NEVERHOOD_MODULE3000_H */ diff --git a/engines/neverhood/modules/module1000.cpp b/engines/neverhood/modules/module1000.cpp new file mode 100644 index 0000000000..ef2872ba2e --- /dev/null +++ b/engines/neverhood/modules/module1000.cpp @@ -0,0 +1,1699 @@ +/* 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/modules/module1000.h" + +namespace Neverhood { + +Module1000::Module1000(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + debug("Create Module1000(%d)", which); + + _musicFileHash = getGlobalVar(V_ENTRANCE_OPEN) ? 0x81106480 : 0x00103144; + + _vm->_soundMan->addMusic(0x03294419, 0x061880C6); + _vm->_soundMan->addMusic(0x03294419, _musicFileHash); + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else if (which == 0) + createScene(0, 0); + else if (which == 1) + createScene(1, 1); + +} + +Module1000::~Module1000() { + _vm->_soundMan->deleteMusicGroup(0x03294419); +} + +void Module1000::createScene(int sceneNum, int which) { + debug("Module1000::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _vm->_soundMan->startMusic(0x061880C6, 0, 0); + _childObject = new Scene1001(_vm, this, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + _vm->_soundMan->startMusic(0x061880C6, 0, 0); + _childObject = new Scene1002(_vm, this, which); + break; + case 2: + _vm->gameState().sceneNum = 2; + _vm->_soundMan->startMusic(0x061880C6, 0, 0); + createStaticScene(0xC084110C, 0x41108C00); + break; + case 3: + _vm->gameState().sceneNum = 3; + _vm->_soundMan->stopMusic(0x061880C6, 0, 2); + _childObject = new Scene1004(_vm, this, which); + break; + case 4: + _vm->gameState().sceneNum = 4; + _vm->_soundMan->stopMusic(0x061880C6, 0, 0); + _vm->_soundMan->startMusic(_musicFileHash, 0, 0); + _childObject = new Scene1005(_vm, this, which); + break; + } + SetUpdateHandler(&Module1000::updateScene); + _childObject->handleUpdate(); +} + +void Module1000::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 2) + createScene(2, 0); + else + createScene(1, 0); + break; + case 1: + if (_moduleResult == 1) + leaveModule(0); + else if (_moduleResult == 2) { + if (_vm->isDemo()) + // Demo version returns to the same scene + createScene(1, 2); + else + createScene(3, 0); + } else + createScene(0, 1); + break; + case 2: + createScene(0, 2); + break; + case 3: + if (_moduleResult == 1) + createScene(4, 0); + else + createScene(1, 2); + break; + case 4: + _vm->_soundMan->stopMusic(_musicFileHash, 0, 1); + createScene(3, 1); + break; + } + } +} + +// Scene1001 + +AsScene1001Door::AsScene1001Door(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100) { + + createSurface(800, 137, 242); + _x = 726; + _y = 440; + stShowIdleDoor(); + loadSound(1, 0xED403E03); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1001Door::handleMessage); +} + +uint32 AsScene1001Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + hammerHitsDoor(); + break; + case 0x3002: + gotoNextState(); + break; + } + return 0; +} + +void AsScene1001Door::hammerHitsDoor() { + switch (getGlobalVar(V_DOOR_STATUS)) { + case 0: + case 1: + playSound(0, 0x65482F03); + startAnimation(0x624C0498, 1, 3); + NextState(&AsScene1001Door::stShowIdleDoor); + break; + case 2: + playSound(1); + startAnimation(0x624C0498, 6, 6); + NextState(&AsScene1001Door::stBustedDoorMove); + break; + default: + // Nothing + break; + } + incGlobalVar(V_DOOR_STATUS, 1); +} + +void AsScene1001Door::stShowIdleDoor() { + switch (getGlobalVar(V_DOOR_STATUS)) { + case 1: + startAnimation(0x624C0498, 4, -1); + _newStickFrameIndex = 4; + break; + case 2: + startAnimation(0x624C0498, 1, -1); + _newStickFrameIndex = 1; + break; + case 3: + stopAnimation(); + setVisible(false); + break; + default: + startAnimation(0x624C0498, 0, -1); + _newStickFrameIndex = 0; + break; + } +} + +void AsScene1001Door::stBustedDoorMove() { + setGlobalVar(V_DOOR_BUSTED, 1); + startAnimation(0x624C0498, 6, 6); + NextState(&AsScene1001Door::stBustedDoorGone); + _x = 30; +} + +void AsScene1001Door::stBustedDoorGone() { + playSound(0); + stopAnimation(); + setVisible(false); +} + +AsScene1001Hammer::AsScene1001Hammer(NeverhoodEngine *vm, Sprite *asDoor) + : AnimatedSprite(vm, 1100), _asDoor(asDoor) { + + _x = 547; + _y = 206; + createSurface(900, 177, 192); + startAnimation(0x022C90D4, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1001Hammer::handleMessage); +} + +uint32 AsScene1001Hammer::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x00352100) + sendMessage(_asDoor, 0x2000, 0); + else if (param.asInteger() == 0x0A1A0109) + playSound(0, 0x66410886); + break; + case 0x2000: + startAnimation(0x022C90D4, 1, -1); + playSound(0, 0xE741020A); + _newStickFrameIndex = STICK_LAST_FRAME; + break; + } + return 0; +} + +AsScene1001Window::AsScene1001Window(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1200) { + + _x = 320; + _y = 240; + createSurface(100, 66, 129); + startAnimation(0xC68C2299, 0, -1); + _newStickFrameIndex = 0; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1001Window::handleMessage); +} + +uint32 AsScene1001Window::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x0E0A1410) + playSound(0, 0x60803F10); + break; + case 0x2001: + startAnimation(0xC68C2299, 0, -1); + break; + case 0x3002: + SetMessageHandler(NULL); + setGlobalVar(V_WINDOW_OPEN, 1); + setVisible(false); + break; + } + return 0; +} + +AsScene1001Lever::AsScene1001Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int deltaXType) + : AnimatedSprite(vm, 1100), _parentScene(parentScene) { + + createSurface(1010, 71, 73); + setDoDeltaX(deltaXType); + startAnimation(0x04A98C36, 0, -1); + _newStickFrameIndex = 0; + _x = x; + _y = y; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1001Lever::handleMessage); +} + +uint32 AsScene1001Lever::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x00C0C444) + sendMessage(_parentScene, 0x480F, 0); + else if (param.asInteger() == 0xC41A02C0) + playSound(0, 0x40581882); + break; + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x3002: + startAnimation(0x04A98C36, 0, -1); + _newStickFrameIndex = 0; + break; + case 0x480F: + startAnimation(0x04A98C36, 0, -1); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +SsCommonButtonSprite::SsCommonButtonSprite(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, int surfacePriority, uint32 soundFileHash) + : StaticSprite(vm, fileHash, surfacePriority), _parentScene(parentScene), _countdown(0) { + + _priority = 1100; + _soundFileHash = soundFileHash ? soundFileHash : 0x44141000; + setVisible(false); + SetUpdateHandler(&SsCommonButtonSprite::update); + SetMessageHandler(&SsCommonButtonSprite::handleMessage); +} + +void SsCommonButtonSprite::update() { + if (_countdown != 0 && (--_countdown) == 0) + setVisible(false); +} + +uint32 SsCommonButtonSprite::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x480B: + sendMessage(_parentScene, 0x480B, 0); + setVisible(true); + _countdown = 8; + playSound(0, _soundFileHash); + break; + } + return messageResult; +} + +Scene1001::Scene1001(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _asDoor(NULL), _asWindow(NULL) { + + Sprite *tempSprite; + + SetMessageHandler(&Scene1001::handleMessage); + + setHitRects(0x004B4860); + setBackground(0x4086520E); + setPalette(0x4086520E); + insertScreenMouse(0x6520A400); + + if (which < 0) { + // Restoring game + setRectList(0x004B49F0); + insertKlaymen(200, 433); + setMessageList(0x004B4888); + } else if (which == 1) { + // Klaymen entering from the right + setRectList(0x004B49F0); + insertKlaymen(640, 433); + setMessageList(0x004B4898); + } else if (which == 2) { + // Klaymen returning from looking through the window + setRectList(0x004B49F0); + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { + insertKlaymen(390, 433); + _klaymen->setDoDeltaX(1); + } else { + insertKlaymen(300, 433); + } + setMessageList(0x004B4970); + } else { + // Klaymen sleeping + setRectList(0x004B4A00); + insertKlaymen(200, 433); + setMessageList(0x004B4890); + } + + tempSprite = insertStaticSprite(0x2080A3A8, 1300); + + _klaymen->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480); + + if (!getGlobalVar(V_DOOR_BUSTED)) { + _asDoor = insertSprite(); + _asDoor->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480); + } + + _asLever = insertSprite(this, 150, 433, 1); + + insertStaticSprite(0x809861A6, 950); + insertStaticSprite(0x89C03848, 1100); + + _ssButton = insertSprite(this, 0x15288120, 100, 0); + + if (!getGlobalVar(V_WINDOW_OPEN)) { + tempSprite = insertStaticSprite(0x8C066150, 200); + _asWindow = insertSprite(); + _asWindow->setClipRect(tempSprite->getDrawRect()); + } + + _asHammer = insertSprite(_asDoor); + +} + +Scene1001::~Scene1001() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX()); +} + +uint32 Scene1001::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x00342624) { + sendEntityMessage(_klaymen, 0x1014, _asLever); + setMessageList2(0x004B4910); + messageResult = 1; + } else if (param.asInteger() == 0x21E64A00) { + if (getGlobalVar(V_DOOR_BUSTED)) { + setMessageList(0x004B48A8); + } else { + setMessageList(0x004B48C8); + } + messageResult = 1; + } else if (param.asInteger() == 0x040424D0) { + sendEntityMessage(_klaymen, 0x1014, _ssButton); + } else if (param.asInteger() == 0x80006358) { + if (getGlobalVar(V_WINDOW_OPEN)) { + setMessageList(0x004B4938); + } else { + setMessageList(0x004B4960); + } + } + break; + case 0x2002: + setRectList(0x004B49F0); + break; + case 0x480B: + sendMessage(_asWindow, 0x2001, 0); + break; + case 0x480F: + sendMessage(_asHammer, 0x2000, 0); + break; + } + return messageResult; +} + +// Scene1002 + +AsScene1002Ring::AsScene1002Ring(NeverhoodEngine *vm, Scene *parentScene, bool isSpecial, int16 x, int16 y, int16 clipY1, bool isRingLow) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _isSpecial(isSpecial) { + + SetUpdateHandler(&AsScene1002Ring::update); + + if (_isSpecial) { + createSurface(990, 68, 314); + if (isRingLow) { + startAnimation(0x04103090, 0, -1); + SetMessageHandler(&AsScene1002Ring::hmRingHangingLow); + } else { + startAnimation(0xA85C4011, _vm->_rnd->getRandomNumber(15), -1); + SetMessageHandler(&AsScene1002Ring::hmRingIdle); + } + } else { + createSurface(990, 68, 138); + startAnimation(0xA85C4011, _vm->_rnd->getRandomNumber(15), -1); + SetMessageHandler(&AsScene1002Ring::hmRingIdle); + } + + setClipRect(0, clipY1, 640, 480); + + _x = x; + _y = y; + + setDoDeltaX(_vm->_rnd->getRandomNumber(1)); + +} + +void AsScene1002Ring::update() { + updateAnim(); + updatePosition(); +} + +uint32 AsScene1002Ring::hmRingIdle(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4806: + setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0); + sendMessage(_parentScene, 0x4806, 0); + SetMessageHandler(&AsScene1002Ring::hmRingPulled1); + startAnimation(_isSpecial ? 0x87502558 : 0x80DD4010, 0, -1); + break; + case 0x480F: + setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0); + sendMessage(_parentScene, 0x480F, 0); + SetMessageHandler(&AsScene1002Ring::hmRingPulled2); + startAnimation(0x861A2020, 0, -1); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +uint32 AsScene1002Ring::hmRingPulled1(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + startAnimation(_isSpecial ? 0x78D0A812 : 0xB85D2A10, 0, -1); + SetMessageHandler(&AsScene1002Ring::hmRingHangingLow); + break; + case 0x4807: + sendMessage(_parentScene, 0x4807, 0); + setDoDeltaX(_vm->_rnd->getRandomNumber(1)); + startAnimation(0x8258A030, 0, -1); + SetMessageHandler(&AsScene1002Ring::hmRingReleased); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +uint32 AsScene1002Ring::hmRingPulled2(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + startAnimation(0x04103090, 0, -1); + SetMessageHandler(&AsScene1002Ring::hmRingHangingLow); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +uint32 AsScene1002Ring::hmRingHangingLow(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4807: + sendMessage(_parentScene, 0x4807, 0); + setDoDeltaX(_vm->_rnd->getRandomNumber(1)); + startAnimation(0x8258A030, 0, -1); + SetMessageHandler(&AsScene1002Ring::hmRingReleased); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +uint32 AsScene1002Ring::hmRingReleased(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = hmRingIdle(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x05410F72) + playSound(0, 0x21EE40A9); + break; + case 0x3002: + startAnimation(0xA85C4011, 0, -1); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +AsScene1002Door::AsScene1002Door(NeverhoodEngine *vm, NRect &clipRect) + : StaticSprite(vm, 1200) { + + loadSprite(0x1052370F, kSLFDefDrawOffset | kSLFSetPosition, 800, 526, getGlobalVar(V_FLYTRAP_RING_DOOR) ? 49 : 239); + setClipRect(clipRect); + SetUpdateHandler(&AsScene1002Door::update); + SetMessageHandler(&AsScene1002Door::handleMessage); + SetSpriteUpdate(NULL); +} + +void AsScene1002Door::update() { + handleSpriteUpdate(); + updatePosition(); +} + +uint32 AsScene1002Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4808: + setGlobalVar(V_FLYTRAP_RING_DOOR, 1); + SetSpriteUpdate(&AsScene1002Door::suOpenDoor); + break; + case 0x4809: + setGlobalVar(V_FLYTRAP_RING_DOOR, 0); + SetSpriteUpdate(&AsScene1002Door::suCloseDoor); + break; + } + return messageResult; +} + +void AsScene1002Door::suOpenDoor() { + if (_y > 49) { + _y -= 8; + if (_y < 49) { + SetSpriteUpdate(NULL); + _y = 49; + } + _needRefresh = true; + } +} + +void AsScene1002Door::suCloseDoor() { + if (_y < 239) { + _y += 8; + if (_y > 239) { + SetSpriteUpdate(NULL); + _y = 239; + } + _needRefresh = true; + } +} + +AsScene1002BoxingGloveHitEffect::AsScene1002BoxingGloveHitEffect(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1400) { + + createSurface(1025, 88, 165); + setVisible(false); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1002BoxingGloveHitEffect::handleMessage); +} + +uint32 AsScene1002BoxingGloveHitEffect::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2004: + _x = ((Sprite*)sender)->getX() - 98; + _y = ((Sprite*)sender)->getY() - 111; + startAnimation(0x0422255A, 0, -1); + setVisible(true); + break; + case 0x3002: + stopAnimation(); + setVisible(false); + break; + } + return messageResult; +} + +AsScene1002DoorSpy::AsScene1002DoorSpy(NeverhoodEngine *vm, NRect &clipRect, Scene *parentScene, Sprite *asDoor, Sprite *asScene1002BoxingGloveHitEffect) + : AnimatedSprite(vm, 1300), _clipRect(clipRect), _parentScene(parentScene), _asDoor(asDoor), _asBoxingGloveHitEffect(asScene1002BoxingGloveHitEffect) { + + createSurface(800, 136, 147); + setClipRect(clipRect); + suDoorSpy(); + loadSound(0, 0xC0C40298); + startAnimation(0x586C1D48, 0, 0); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1002DoorSpy::handleMessage); + SetSpriteUpdate(&AsScene1002DoorSpy::suDoorSpy); +} + +uint32 AsScene1002DoorSpy::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0xA61CA1C2) + sendMessage(_asBoxingGloveHitEffect, 0x2004, 0); + else if (param.asInteger() == 0x14CE0620) + playSound(0); + break; + case 0x2003: + stDoorSpyBoxingGlove(); + break; + } + return messageResult; +} + +uint32 AsScene1002DoorSpy::hmDoorSpyAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1002DoorSpy::suDoorSpy() { + _x = _asDoor->getX() + 34; + _y = _asDoor->getY() + 175; +} + +void AsScene1002DoorSpy::stDoorSpyIdle() { + setClipRect(_clipRect); + _parentScene->setSurfacePriority(getSurface(), 800); + startAnimation(0x586C1D48, 0, 0); + SetMessageHandler(&AsScene1002DoorSpy::handleMessage); +} + +void AsScene1002DoorSpy::stDoorSpyBoxingGlove() { + setClipRect(0, 0, 640, 480); + _parentScene->setSurfacePriority(getSurface(), 1200); + startAnimation(0x586C1D48, 1, -1); + SetMessageHandler(&AsScene1002DoorSpy::hmDoorSpyAnimation); + NextState(&AsScene1002DoorSpy::stDoorSpyIdle); +} + +SsCommonPressButton::SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash) + : StaticSprite(vm, 1100), _parentScene(parentScene), _status(0) { + + _soundFileHash = soundFileHash != 0 ? soundFileHash : 0x44141000; + _fileHashes[0] = fileHash1; + _fileHashes[1] = fileHash2; + createSurface(surfacePriority, 40, 40); + loadSprite(fileHash1, kSLFDefDrawOffset | kSLFDefPosition); + setVisible(false); + SetUpdateHandler(&SsCommonPressButton::update); + SetMessageHandler(&SsCommonPressButton::handleMessage); +} + +void SsCommonPressButton::setFileHashes(uint32 fileHash1, uint32 fileHash2) { + _fileHashes[0] = fileHash1; + _fileHashes[1] = fileHash2; + loadSprite(_status == 2 ? fileHash2 : fileHash1, kSLFDefDrawOffset | kSLFDefPosition); +} + +void SsCommonPressButton::update() { + if (_countdown != 0 && (--_countdown) == 0) { + if (_status == 1) { + _status = 2; + loadSprite(_fileHashes[1], kSLFDefDrawOffset | kSLFDefPosition); + _countdown = 4; + } else if (_status == 2) { + _status = 3; + loadSprite(_fileHashes[0], kSLFDefDrawOffset | kSLFDefPosition); + _countdown = 4; + } else if (_status == 3) { + _status = 0; + setVisible(false); + } + } +} + +uint32 SsCommonPressButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x480B: + sendMessage(_parentScene, 0x480B, 0); + _status = 1; + _countdown = 4; + setVisible(true); + playSound(0, _soundFileHash); + break; + } + return messageResult; +} + +AsScene1002VenusFlyTrap::AsScene1002VenusFlyTrap(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, bool isSecond) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _klaymen(klaymen), _isSecond(isSecond), _countdown(0) { + + createSurface(995, 175, 195); + if (!_isSecond) { + if (getGlobalVar(V_FLYTRAP_RING_DOOR)) { + setDoDeltaX(1); + _x = 366; + _y = 435; + stRingGrabbed(); + } else { + _x = 174 + getGlobalVar(V_FLYTRAP_POSITION_1) * 32; + _y = 435; + stIdle(); + } + } else { + _x = 186 + getGlobalVar(V_FLYTRAP_POSITION_2) * 32; + _y = 364; + if (getGlobalVar(V_FLYTRAP_RING_BRIDGE) || getGlobalVar(V_FLYTRAP_RING_FENCE)) { + stRingGrabbed(); + } else { + stIdle(); + } + } + _flags = 4; + SetUpdateHandler(&AsScene1002VenusFlyTrap::update); + SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage); + SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); +} + +void AsScene1002VenusFlyTrap::update() { + if (_countdown != 0 && (--_countdown == 0)) + gotoNextState(); + AnimatedSprite::update(); +} + +void AsScene1002VenusFlyTrap::upIdle() { + if (_countdown == 0 && _klaymen->getX() - 20 > _x) + setDoDeltaX(1); + else if (_klaymen->getX() + 20 < _x) + setDoDeltaX(0); + update(); +} + +uint32 AsScene1002VenusFlyTrap::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x000890C4) + playSound(0, 0xC21190D8); + else if (param.asInteger() == 0x522200A0) + playSound(0, 0x931080C8); + break; + case 0x1011: + if (_isSecond) { + if (_x >= 154 && _x <= 346) { + sendMessage(_parentScene, 0x2000, 0); + messageResult = 1; + } + } else { + if (_x >= 174 && _x <= 430) { + sendMessage(_parentScene, 0x2000, 0); + messageResult = 1; + } + } + break; + case 0x480B: + setDoDeltaX(param.asInteger() != 0 ? 1 : 0); + if (!_isSecond) { + if (getGlobalVar(V_FLYTRAP_RING_DOOR)) + stRelease(); + else + stWalk(); + } else { + if (getGlobalVar(V_FLYTRAP_RING_BRIDGE) || getGlobalVar(V_FLYTRAP_RING_FENCE)) + stRelease(); + else + stWalk(); + } + break; + case 0x480C: + if (_isSecond) { + if (_x >= 154 && _x <= 346) + messageResult = 1; + else + messageResult = 0; + } else { + if (_x >= 174 && _x <= 430) + messageResult = 1; + else + messageResult = 0; + } + break; + case 0x480E: + if (param.asInteger() == 1) + stGrabRing(); + break; + case 0x4810: + swallowKlaymen(); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 995); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1015); + break; + } + return messageResult; +} + +uint32 AsScene1002VenusFlyTrap::hmAnimationSimple(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +uint32 AsScene1002VenusFlyTrap::hmAnimationExt(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x000890C4) + playSound(0, 0xC21190D8); + else if (param.asInteger() == 0x41881801) { + if (_isSecond) { + if (_x > 330) + sendMessage(_klaymen, 0x4811, 2); + else + sendMessage(_klaymen, 0x4811, 0); + } else { + sendMessage(_klaymen, 0x4811, 0); + } + } else if (param.asInteger() == 0x522200A0) + playSound(0, 0x931080C8); + break; + case 0x3002: + gotoNextState(); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 995); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1015); + break; + } + return messageResult; +} + +void AsScene1002VenusFlyTrap::stWalkBack() { + setDoDeltaX(2); + startAnimation(0xC4080034, 0, -1); + SetUpdateHandler(&AsScene1002VenusFlyTrap::update); + SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt); + NextState(&AsScene1002VenusFlyTrap::stIdle); +} + +void AsScene1002VenusFlyTrap::stWalk() { + startAnimation(0xC4080034, 0, -1); + SetUpdateHandler(&AsScene1002VenusFlyTrap::update); + SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple); + NextState(&AsScene1002VenusFlyTrap::stIdle); +} + +void AsScene1002VenusFlyTrap::stRelease() { + sendMessage(_parentScene, 0x4807, 0); + startAnimation(0x82292851, 0, -1); + SetUpdateHandler(&AsScene1002VenusFlyTrap::update); + SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple); + NextState(&AsScene1002VenusFlyTrap::stIdle); +} + +void AsScene1002VenusFlyTrap::stGrabRing() { + setDoDeltaX(1); + startAnimation(0x86A82A11, 0, -1); + SetUpdateHandler(&AsScene1002VenusFlyTrap::update); + SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple); + NextState(&AsScene1002VenusFlyTrap::stRingGrabbed); +} + +void AsScene1002VenusFlyTrap::stRingGrabbed() { + startAnimation(0xB5A86034, 0, -1); + SetUpdateHandler(&AsScene1002VenusFlyTrap::update); + SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage); +} + +void AsScene1002VenusFlyTrap::stKlaymenInside() { + startAnimation(0x31303094, 0, -1); + SetUpdateHandler(&AsScene1002VenusFlyTrap::update); + SetMessageHandler(NULL); + NextState(&AsScene1002VenusFlyTrap::stKlaymenInsideMoving); + _countdown = 24; +} + +void AsScene1002VenusFlyTrap::stIdle() { + startAnimation(0xC8204250, 0, -1); + SetUpdateHandler(&AsScene1002VenusFlyTrap::upIdle); + SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage); + if (_isSecond) { + if (_x >= 154 && _x <= 346) + setGlobalVar(V_FLYTRAP_POSITION_2, (_x - 186) / 32); + else { + NextState(&AsScene1002VenusFlyTrap::stWalkBack); + _countdown = 12; + } + } else { + if (_x >= 174 && _x <= 430) + setGlobalVar(V_FLYTRAP_POSITION_1, (_x - 174) / 32); + else { + NextState(&AsScene1002VenusFlyTrap::stWalkBack); + _countdown = 12; + } + } +} + +void AsScene1002VenusFlyTrap::stKlaymenInsideMoving() { + startAnimation(0x152920C4, 0, -1); + SetUpdateHandler(&AsScene1002VenusFlyTrap::update); + SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt); + NextState(&AsScene1002VenusFlyTrap::stSpitOutKlaymen); +} + +void AsScene1002VenusFlyTrap::stSpitOutKlaymen() { + startAnimation(0x84001117, 0, -1); + SetUpdateHandler(&AsScene1002VenusFlyTrap::update); + SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt); + NextState(&AsScene1002VenusFlyTrap::stIdle); +} + +void AsScene1002VenusFlyTrap::swallowKlaymen() { + if (_x - 15 < _klaymen->getX() && _x + 15 > _klaymen->getX()) { + if (_isSecond) + setDoDeltaX(_x > 265 && _x < 330 ? 1 : 0); + else + setDoDeltaX(_x > 320 ? 1 : 0); + sendMessage(_klaymen, 0x2001, 0); + startAnimation(0x8C2C80D4, 0, -1); + SetUpdateHandler(&AsScene1002VenusFlyTrap::update); + SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt); + NextState(&AsScene1002VenusFlyTrap::stKlaymenInside); + } +} + +AsScene1002OutsideDoorBackground::AsScene1002OutsideDoorBackground(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1200), _countdown(0) { + + createSurface(850, 186, 212); + _x = 320; + _y = 240; + if (getGlobalVar(V_FLYTRAP_RING_DOOR)) { + startAnimation(0x004A4495, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + } else + setVisible(false); + SetUpdateHandler(&AsScene1002OutsideDoorBackground::update); + SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage); +} + +void AsScene1002OutsideDoorBackground::update() { + if (_countdown != 0 && (--_countdown == 0)) { + if (_isDoorClosed) + stCloseDoor(); + else + stOpenDoor(); + } + AnimatedSprite::update(); +} + +uint32 AsScene1002OutsideDoorBackground::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageResult) { + case 0x4808: + _isDoorClosed = false; + _countdown = 2; + break; + case 0x4809: + _isDoorClosed = true; + _countdown = 2; + break; + } + return messageResult; +} + +uint32 AsScene1002OutsideDoorBackground::hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage(messageNum, param, sender); + switch (messageResult) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1002OutsideDoorBackground::stOpenDoor() { + startAnimation(0x004A4495, 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + setVisible(true); + SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage); +} + +void AsScene1002OutsideDoorBackground::stCloseDoor() { + startAnimation(0x004A4495, -1, -1); + _playBackwards = true; + setVisible(true); + SetMessageHandler(&AsScene1002OutsideDoorBackground::hmAnimation); + NextState(&AsScene1002OutsideDoorBackground::stDoorClosed); +} + +void AsScene1002OutsideDoorBackground::stDoorClosed() { + setVisible(false); + stopAnimation(); +} + +AsScene1002KlaymenLadderHands::AsScene1002KlaymenLadderHands(NeverhoodEngine *vm, Klaymen *klaymen) + : AnimatedSprite(vm, 1200), _klaymen(klaymen) { + + createSurface(1200, 40, 163); + setVisible(false); + SetUpdateHandler(&AsScene1002KlaymenLadderHands::update); + SetMessageHandler(&Sprite::handleMessage); +} + +void AsScene1002KlaymenLadderHands::update() { + if (_klaymen->getCurrAnimFileHash() == 0x3A292504) { + startAnimation(0xBA280522, _klaymen->getFrameIndex(), -1); + _newStickFrameIndex = _klaymen->getFrameIndex(); + setVisible(true); + _x = _klaymen->getX(); + _y = _klaymen->getY(); + setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0); + } else if (_klaymen->getCurrAnimFileHash() == 0x122D1505) { + startAnimation(0x1319150C, _klaymen->getFrameIndex(), -1); + _newStickFrameIndex = _klaymen->getFrameIndex(); + setVisible(true); + _x = _klaymen->getX(); + _y = _klaymen->getY(); + setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0); + } else + setVisible(false); + AnimatedSprite::update(); +} + +AsScene1002KlaymenPeekHand::AsScene1002KlaymenPeekHand(NeverhoodEngine *vm, Scene *parentScene, Klaymen *klaymen) + : AnimatedSprite(vm, 1200), _parentScene(parentScene), _klaymen(klaymen), + _isClipRectSaved(false) { + + createSurface(1000, 33, 41); + setVisible(false); + SetUpdateHandler(&AsScene1002KlaymenPeekHand::update); + SetMessageHandler(&AsScene1002KlaymenPeekHand::handleMessage); +} + +void AsScene1002KlaymenPeekHand::update() { + if (_klaymen->getCurrAnimFileHash() == 0xAC20C012 && _klaymen->getFrameIndex() < 50) { + startAnimation(0x9820C913, _klaymen->getFrameIndex(), -1); + _newStickFrameIndex = _klaymen->getFrameIndex(); + setVisible(true); + _x = _klaymen->getX(); + _y = _klaymen->getY(); + setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0); + } else + setVisible(false); + AnimatedSprite::update(); +} + +uint32 AsScene1002KlaymenPeekHand::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x4AB28209) { + sendMessage(_parentScene, 0x1022, 1200); + _isClipRectSaved = true; + _savedClipRect = _surface->getClipRect(); + setClipRect(0, 0, 640, 480); + } else if (param.asInteger() == 0x88001184) { + sendMessage(_parentScene, 0x1022, 1000); + if (_isClipRectSaved) + setClipRect(_savedClipRect); + } + break; + } + return messageResult; +} + +Scene1002::Scene1002(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _isKlaymenFloor(false), _isClimbingLadder(false) { + + NRect tempClipRect; + Sprite *tempSprite; + + SetUpdateHandler(&Scene1002::update); + SetMessageHandler(&Scene1002::handleMessage); + + setHitRects(0x004B4138); + setBackground(0x12C23307); + setPalette(0x12C23307); + + insertStaticSprite(0x06149428, 1100); + insertStaticSprite(0x312C8774, 1100); + + _ssLadderArch = insertStaticSprite(0x152C1313, 1015); + _ssLadderArchPart1 = insertStaticSprite(0x060000A0, 1200); + _ssLadderArchPart2 = insertStaticSprite(0xB2A423B0, 1100); + _ssLadderArchPart3 = insertStaticSprite(0x316E0772, 1100); + + _ssCeiling = insertStaticSprite(0x316C4BB4, 1015); + + if (which < 0) { + // Restoring game + if (_vm->_gameState.which == 0) { + // Klaymen on top + insertKlaymen(90, 226); + _asKlaymenLadderHands = insertSprite(_klaymen); + setMessageList(0x004B4270); + _klaymen->setClipRect(31, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart3->getDrawRect().y2()); + _asKlaymenLadderHands->getSurface()->getClipRect() = _klaymen->getSurface()->getClipRect(); + _klaymen->setRepl(64, 0); + } else { + // Klaymen on the floor + insertKlaymen(379, 435); + _asKlaymenLadderHands = insertSprite(_klaymen); + setMessageList(0x004B4270); + _klaymen->setClipRect(_ssLadderArch->getDrawRect().x, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart1->getDrawRect().y2()); + _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); + } + } else if (which == 1) { + // Klaymen entering from the right + insertKlaymen(650, 435); + _asKlaymenLadderHands = insertSprite(_klaymen); + setMessageList(0x004B4478); + _klaymen->setClipRect(_ssLadderArch->getDrawRect().x, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart1->getDrawRect().y2()); + _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); + _vm->_gameState.which = 1; + } else if (which == 2) { + // Klaymen coming up the ladder + insertKlaymen(68, 645); + _asKlaymenLadderHands = insertSprite(_klaymen); + setMessageList(0x004B4298); + _klaymen->setClipRect(_ssLadderArch->getDrawRect().x, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart1->getDrawRect().y2()); + _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); + _vm->_gameState.which = 1; + sendMessage(_klaymen, 0x4820, 0); + } else { + // Klaymen entering from the left, peeking + insertKlaymen(90, 226); + _asKlaymenLadderHands = insertSprite(_klaymen); + setMessageList(0x004B4470); + _klaymen->setClipRect(31, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart3->getDrawRect().y2()); + _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); + _asKlaymenPeekHand = insertSprite(this, _klaymen); + _asKlaymenPeekHand->setClipRect(_klaymen->getClipRect()); + _klaymen->setRepl(64, 0); + _vm->_gameState.which = 0; + } + + insertScreenMouse(0x23303124); + + tempSprite = insertStaticSprite(0xB3242310, 825); + tempClipRect.set(tempSprite->getDrawRect().x, tempSprite->getDrawRect().y, + _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart2->getDrawRect().y2()); + + _asRing1 = insertSprite(this, false, 258, 191, _ssCeiling->getDrawRect().y, false); + _asRing2 = insertSprite(this, false, 297, 189, _ssCeiling->getDrawRect().y, false); + _asRing3 = insertSprite(this, true, 370, 201, _ssCeiling->getDrawRect().y, getGlobalVar(V_FLYTRAP_RING_DOOR)); + _asRing4 = insertSprite(this, false, 334, 191, _ssCeiling->getDrawRect().y, false); + _asRing5 = insertSprite(this, false, 425, 184, _ssCeiling->getDrawRect().y, false); + + _asDoor = insertSprite(tempClipRect); + tempSprite = insertSprite(); + _asDoorSpy = insertSprite(tempClipRect, this, _asDoor, tempSprite); + _ssPressButton = insertSprite(this, 0x00412692, 0x140B60BE, 800, 0); + _asVenusFlyTrap = insertSprite(this, _klaymen, false); + addCollisionSprite(_asVenusFlyTrap); + + sendEntityMessage(_klaymen, 0x2007, _asVenusFlyTrap); + + _asOutsideDoorBackground = insertSprite(); + + setRectList(0x004B43A0); + + loadSound(1, 0x60755842); + loadSound(2, 0x616D5821); + +} + +Scene1002::~Scene1002() { +} + +void Scene1002::update() { + Scene::update(); + if (!_isKlaymenFloor && _klaymen->getY() > 230) { + _klaymen->setClipRect(_ssLadderArch->getDrawRect().x, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart1->getDrawRect().y2()); + _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); + deleteSprite(&_ssLadderArchPart3); + _klaymen->clearRepl(); + _isKlaymenFloor = true; + _vm->_gameState.which = 1; + } +} + +uint32 Scene1002::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0xE6EE60E1) { + if (getGlobalVar(V_FLYTRAP_RING_DOOR)) + setMessageList(0x004B4428); + else + setMessageList(0x004B4448); + messageResult = 1; + } else if (param.asInteger() == 0x4A845A00) + sendEntityMessage(_klaymen, 0x1014, _asRing1); + else if (param.asInteger() == 0x43807801) + sendEntityMessage(_klaymen, 0x1014, _asRing2); + else if (param.asInteger() == 0x46C26A01) { + if (getGlobalVar(V_FLYTRAP_RING_DOOR)) { + setMessageList(0x004B44B8); + } else { + sendEntityMessage(_klaymen, 0x1014, _asRing3); + if (_asVenusFlyTrap->getX() - 10 < 366 && _asVenusFlyTrap->getX() + 10 > 366) { + setGlobalVar(V_FLYTRAP_RING_EATEN, 1); + setMessageList(0x004B44A8); + } else { + setMessageList(0x004B44A0); + } + } + messageResult = 1; + } else if (param.asInteger() == 0x468C7B11) + sendEntityMessage(_klaymen, 0x1014, _asRing4); + else if (param.asInteger() == 0x42845B19) + sendEntityMessage(_klaymen, 0x1014, _asRing5); + else if (param.asInteger() == 0xC0A07458) + sendEntityMessage(_klaymen, 0x1014, _ssPressButton); + break; + case 0x1024: + sendMessage(_parentModule, 0x1024, param.asInteger()); + break; + case 0x2000: + if (_isClimbingLadder) { + setMessageList2(0x004B43D0); + } else { + if (_klaymen->getY() > 420) { + sendEntityMessage(_klaymen, 0x1014, _asVenusFlyTrap); + setMessageList2(0x004B4480); + } else if (_klaymen->getY() > 227) { + setMessageList2(0x004B41E0); + } else { + setMessageList2(0x004B4148); + } + } + break; + case 0x2002: + _messageList = NULL; + break; + case 0x2005: + _isClimbingLadder = true; + setRectList(0x004B4418); + break; + case 0x2006: + _isClimbingLadder = false; + setRectList(0x004B43A0); + break; + case 0x4806: + if (sender == _asRing1) { + setGlobalVar(V_RADIO_ENABLED, 0); + playSound(0, 0x665198C0); + } else if (sender == _asRing2) { + setGlobalVar(V_RADIO_ENABLED, 0); + playSound(0, 0xE2D389C0); + } else if (sender == _asRing3) { + setGlobalVar(V_RADIO_ENABLED, 0); + playSound(1); + sendMessage(_asDoor, 0x4808, 0); + sendMessage(_asOutsideDoorBackground, 0x4808, 0); + } else if (sender == _asRing4) { + setGlobalVar(V_RADIO_ENABLED, 0); + playSound(0, 0xE0558848); + } else if (sender == _asRing5) { + setGlobalVar(V_RADIO_ENABLED, 1); + playSound(0, 0x44014282); + } + break; + case 0x4807: + if (sender == _asRing3) { + playSound(2); + sendMessage(_asDoor, 0x4809, 0); + sendMessage(_asOutsideDoorBackground, 0x4809, 0); + } else if (sender == _asVenusFlyTrap) { + if (getGlobalVar(V_FLYTRAP_RING_DOOR)) { + sendMessage(_asRing3, 0x4807, 0); + } + } + break; + case 0x480B: + sendEntityMessage(_klaymen, 0x1014, _asDoorSpy); + break; + case 0x480F: + setGlobalVar(V_RADIO_ENABLED, 0); + playSound(1); + sendMessage(_asDoor, 0x4808, 0); + sendMessage(_asOutsideDoorBackground, 0x4808, 0); + break; + case 0x8000: + setSpriteSurfacePriority(_ssCeiling, 995); + setSpriteSurfacePriority(_ssLadderArch, 995); + break; + case 0x8001: + setSpriteSurfacePriority(_ssCeiling, 1015); + setSpriteSurfacePriority(_ssLadderArch, 1015); + break; + } + return messageResult; +} + +// StaticScene + +StaticScene::StaticScene(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 cursorFileHash) + : Scene(vm, parentModule) { + + SetMessageHandler(&StaticScene::handleMessage); + + setBackground(backgroundFileHash); + setPalette(backgroundFileHash); + insertPuzzleMouse(cursorFileHash, 20, 620); +} + +uint32 StaticScene::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) + leaveScene(0); + break; + } + return 0; +} + +// Scene1004 + +AsScene1004TrashCan::AsScene1004TrashCan(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100) { + + _x = 330; + _y = 327; + createSurface(800, 56, 50); + setVisible(false); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1004TrashCan::handleMessage); +} + +uint32 AsScene1004TrashCan::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x225A8587) + playSound(0, 0x109AFC4C); + break; + case 0x2002: + startAnimation(0xEB312C11, 0, -1); + setVisible(true); + break; + case 0x3002: + stopAnimation(); + setVisible(false); + break; + } + return 0; +} + +Scene1004::Scene1004(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _paletteAreaStatus(-1) { + + Sprite *tempSprite; + + SetUpdateHandler(&Scene1004::update); + SetMessageHandler(&Scene1004::handleMessage); + + setBackground(0x50C03005); + + if (getGlobalVar(V_ENTRANCE_OPEN)) { + setPalette(0xA30BA329); + _palette->addBasePalette(0xA30BA329, 0, 256, 0); + } else { + setPalette(0x50C03005); + _palette->addBasePalette(0x50C03005, 0, 256, 0); + } + addEntity(_palette); + + insertScreenMouse(0x03001504); + + if (which < 0) { + // Restoring game + setRectList(0x004B7C70); + insertKlaymen(330, 327); + setMessageList(0x004B7C18); + } else if (which == 1) { + // Klaymen returning from reading a note + setRectList(0x004B7C70); + insertKlaymen(330, 327); + setMessageList(0x004B7C08); + } else { + // Klaymen coming down the ladder + loadDataResource(0x01900A04); + insertKlaymen(_dataResource.getPoint(0x80052A29).x, 27); + setMessageList(0x004B7BF0); + } + + updatePaletteArea(); + + _asKlaymenLadderHands = insertSprite(_klaymen); + + insertStaticSprite(0x800034A0, 1100); + insertStaticSprite(0x64402020, 1100); + insertStaticSprite(0x3060222E, 1300); + tempSprite = insertStaticSprite(0x0E002004, 1300); + + _klaymen->setClipRect(0, tempSprite->getDrawRect().y, 640, 480); + _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); + + _asTrashCan = insertSprite(); + +} + +void Scene1004::update() { + Scene::update(); + updatePaletteArea(); +} + +uint32 Scene1004::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x926500A1) { + setMessageList(0x004B7C20); + messageResult = 1; + } + break; + case 0x2000: + loadDataResource(0x01900A04); + break; + case 0x2001: + setRectList(0x004B7C70); + break; + case 0x2002: + sendMessage(_asTrashCan, 0x2002, 0); + break; + } + return messageResult; +} + +void Scene1004::updatePaletteArea() { + if (_klaymen->getY() < 150) { + if (_paletteAreaStatus != 0) { + _paletteAreaStatus = 0; + _palette->addBasePalette(0x406B0D10, 0, 64, 0); + _palette->startFadeToPalette(12); + } + } else { + if (_paletteAreaStatus != 1) { + _paletteAreaStatus = 1; + _palette->addBasePalette(0x24332243, 0, 64, 0); + _palette->startFadeToPalette(12); + } + } +} + +// Scene1005 + +Scene1005::Scene1005(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + SetMessageHandler(&Scene1005::handleMessage); + + if (getGlobalVar(V_ENTRANCE_OPEN)) { + setBackground(0x2800E011); + setPalette(0x2800E011); + insertStaticSprite(0x492D5AD7, 100); + insertPuzzleMouse(0x0E015288, 20, 620); + } else { + setBackground(0x8870A546); + setPalette(0x8870A546); + insertStaticSprite(0x40D1E0A9, 100); + insertStaticSprite(0x149C00A6, 100); + insertPuzzleMouse(0x0A54288F, 20, 620); + } + + drawTextToBackground(); + +} + +uint32 Scene1005::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) + leaveScene(0); + break; + } + return 0; +} + +void Scene1005::drawTextToBackground() { + TextResource textResource(_vm); + const char *textStart, *textEnd; + int16 y = 36; + uint32 textIndex = getTextIndex(); + FontSurface *fontSurface = FontSurface::createFontSurface(_vm, getGlobalVar(V_ENTRANCE_OPEN) ? 0x283CE401 : 0xC6604282); + textResource.load(0x80283101); + textStart = textResource.getString(textIndex, textEnd); + while (textStart < textEnd) { + fontSurface->drawString(_background->getSurface(), 188, y, (const byte*)textStart); + y += 36; + textStart += strlen(textStart) + 1; + } + delete fontSurface; +} + +uint32 Scene1005::getTextIndex() { + uint32 textIndex; + textIndex = getTextIndex1(); + if (getGlobalVar(V_ENTRANCE_OPEN)) { + textIndex = getTextIndex2(); + } + if (getGlobalVar(V_TEXT_FLAG1) && getGlobalVar(V_TEXT_INDEX) == textIndex) { + textIndex = getTextIndex3(); + } else { + setGlobalVar(V_TEXT_FLAG1, 1); + setGlobalVar(V_TEXT_INDEX, textIndex); + } + return textIndex; +} + +uint32 Scene1005::getTextIndex1() { + uint32 textIndex; + if (getGlobalVar(V_WORLDS_JOINED)) { + if (!getGlobalVar(V_DOOR_PASSED)) + textIndex = 18; + else if (!getGlobalVar(V_ROBOT_TARGET)) + textIndex = 19; + else if (getGlobalVar(V_ROBOT_HIT)) { + if (!getGlobalVar(V_ENTRANCE_OPEN)) + textIndex = 23; + else if (!getSubVar(VA_HAS_KEY, 0) && !getSubVar(VA_IS_KEY_INSERTED, 0)) + textIndex = 24; + else if (!getGlobalVar(V_HAS_FINAL_KEY)) + textIndex = 26; + else if (!getSubVar(VA_HAS_KEY, 1) && !getSubVar(VA_IS_KEY_INSERTED, 1)) + textIndex = 27; + else if (!getGlobalVar(V_HAS_FINAL_KEY)) + textIndex = 28; + else + textIndex = 29; + } else if (!getGlobalVar(V_FELL_DOWN_HOLE)) + textIndex = 20; + else if (!getGlobalVar(V_SEEN_SYMBOLS_NO_LIGHT)) + textIndex = 21; + else + textIndex = 22; + } else if (getGlobalVar(V_BOLT_DOOR_UNLOCKED)) { + if (!getGlobalVar(V_WALL_BROKEN)) + textIndex = 12; + else if (!getGlobalVar(V_STAIRS_DOWN_ONCE)) + textIndex = 13; + else if (!getGlobalVar(V_RADIO_ENABLED)) + textIndex = 50; + else if (!getGlobalVar(V_UNUSED)) + textIndex = 14; + else if (!getGlobalVar(V_BEEN_SHRINKING_ROOM)) + textIndex = 15; + else if (!getGlobalVar(V_BEEN_STATUE_ROOM)) + textIndex = 16; + else + textIndex = 17; + } else if (!getGlobalVar(V_FLYTRAP_RING_EATEN)) { + textIndex = 0; + } else if (getGlobalVar(V_CREATURE_EXPLODED)) { + if (!getGlobalVar(V_TILE_PUZZLE_SOLVED)) + textIndex = 4; + else if (!getGlobalVar(V_HAS_TEST_TUBE)) + textIndex = 5; + else if (!getSubVar(VA_LOCKS_DISABLED, 0x40119852)) + textIndex = 6; + else if (!getGlobalVar(V_WATER_RUNNING)) + textIndex = 7; + else if (!getGlobalVar(V_NOTES_PUZZLE_SOLVED)) + textIndex = 8; + else if (!getSubVar(VA_LOCKS_DISABLED, 0x304008D2)) + textIndex = 9; + else if (!getSubVar(VA_LOCKS_DISABLED, 0x01180951)) + textIndex = 10; + else + textIndex = 11; + } else if (!getGlobalVar(V_CREATURE_ANGRY)) { + textIndex = 1; + } else if (getGlobalVar(V_TNT_DUMMY_BUILT)) { + textIndex = 3; + } else { + textIndex = 2; + } + return textIndex; +} + +uint32 Scene1005::getTextIndex2() { + uint32 textIndex = getGlobalVar(V_TEXT_COUNTING_INDEX1); + if (textIndex + 1 >= 10) { + setGlobalVar(V_TEXT_COUNTING_INDEX1, 0); + textIndex = 0; + } else { + setGlobalVar(V_TEXT_COUNTING_INDEX1, textIndex + 1); + } + return textIndex + 40; +} + +uint32 Scene1005::getTextIndex3() { + uint32 textIndex = getGlobalVar(V_TEXT_COUNTING_INDEX2); + if (textIndex + 1 >= 10) { + setGlobalVar(V_TEXT_COUNTING_INDEX2, 0); + textIndex = 0; + } else { + setGlobalVar(V_TEXT_COUNTING_INDEX2, textIndex + 1); + } + return textIndex + 30; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1000.h b/engines/neverhood/modules/module1000.h new file mode 100644 index 0000000000..9977590a6a --- /dev/null +++ b/engines/neverhood/modules/module1000.h @@ -0,0 +1,300 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE1000_H +#define NEVERHOOD_MODULES_MODULE1000_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +// Module1000 + +class Module1000 : public Module { +public: + Module1000(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1000(); +protected: + int _sceneNum; + uint32 _musicFileHash; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +// Scene1001 + +class AsScene1001Door : public AnimatedSprite { +public: + AsScene1001Door(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void hammerHitsDoor(); + void stShowIdleDoor(); + void stBustedDoorMove(); + void stBustedDoorGone(); +}; + +class AsScene1001Hammer : public AnimatedSprite { +public: + AsScene1001Hammer(NeverhoodEngine *vm, Sprite *asDoor); +protected: + Sprite *_asDoor; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1001Window : public AnimatedSprite { +public: + AsScene1001Window(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1001Lever : public AnimatedSprite { +public: + AsScene1001Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int deltaXType); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsCommonButtonSprite : public StaticSprite { +public: + SsCommonButtonSprite(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, int surfacePriority, uint32 soundFileHash); +protected: + Scene *_parentScene; + uint32 _soundFileHash; + int16 _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1001 : public Scene { +public: + Scene1001(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene1001(); +protected: + Sprite *_asHammer; + Sprite *_asDoor; + Sprite *_asWindow; + Sprite *_asLever; + Sprite *_ssButton; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +// TODO: Move this to some common file since it's used several times + +class StaticScene : public Scene { +public: + StaticScene(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 cursorFileHash); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +// Scene1002 + +class AsScene1002Ring : public AnimatedSprite { +public: + AsScene1002Ring(NeverhoodEngine *vm, Scene *parentScene, bool isSpecial, int16 x, int16 y, int16 clipY1, bool isRingLow); +protected: + Scene *_parentScene; + bool _isSpecial; + void update(); + uint32 hmRingIdle(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmRingPulled1(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmRingPulled2(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmRingHangingLow(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmRingReleased(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1002Door : public StaticSprite { +public: + AsScene1002Door(NeverhoodEngine *vm, NRect &clipRect); +protected: + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suOpenDoor(); + void suCloseDoor(); +}; + +class AsScene1002BoxingGloveHitEffect : public AnimatedSprite { +public: + AsScene1002BoxingGloveHitEffect(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1002DoorSpy : public AnimatedSprite { +public: + AsScene1002DoorSpy(NeverhoodEngine *vm, NRect &clipRect, Scene *parentScene, Sprite *asDoor, Sprite *asScene1002BoxingGloveHitEffect); +protected: + Scene *_parentScene; + Sprite *_asDoor; + Sprite *_asBoxingGloveHitEffect; + NRect _clipRect; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmDoorSpyAnimation(int messageNum, const MessageParam ¶m, Entity *sender); + void suDoorSpy(); + void stDoorSpyIdle(); + void stDoorSpyBoxingGlove(); +}; + +class SsCommonPressButton : public StaticSprite { +public: + SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash); + void setFileHashes(uint32 fileHash1, uint32 fileHash2); +protected: + Scene *_parentScene; + uint32 _soundFileHash; + uint32 _fileHashes[2]; + int _status; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1002VenusFlyTrap : public AnimatedSprite { +public: + AsScene1002VenusFlyTrap(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, bool isSecond); +protected: + Scene *_parentScene; + Sprite *_klaymen; + int _countdown; + bool _isSecond; + void update(); + void upIdle(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmAnimationSimple(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmAnimationExt(int messageNum, const MessageParam ¶m, Entity *sender); + void stWalkBack(); + void stWalk(); + void stRelease(); + void stGrabRing(); + void stRingGrabbed(); + void stKlaymenInside(); + void stIdle(); + void stKlaymenInsideMoving(); + void stSpitOutKlaymen(); + void swallowKlaymen(); +}; + +class AsScene1002OutsideDoorBackground : public AnimatedSprite { +public: + AsScene1002OutsideDoorBackground(NeverhoodEngine *vm); +protected: + int _countdown; + bool _isDoorClosed; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender); + void stOpenDoor(); + void stCloseDoor(); + void stDoorClosed(); +}; + +class AsScene1002KlaymenLadderHands : public AnimatedSprite { +public: + AsScene1002KlaymenLadderHands(NeverhoodEngine *vm, Klaymen *klaymen); +protected: + Klaymen *_klaymen; + void update(); +}; + +class AsScene1002KlaymenPeekHand : public AnimatedSprite { +public: + AsScene1002KlaymenPeekHand(NeverhoodEngine *vm, Scene *parentScene, Klaymen *klaymen); +protected: + Scene *_parentScene; + Klaymen *_klaymen; + bool _isClipRectSaved; + NRect _savedClipRect; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1002 : public Scene { +public: + Scene1002(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene1002(); +protected: + Sprite *_asRing1; + Sprite *_asRing2; + Sprite *_asRing3; + Sprite *_asRing4; + Sprite *_asRing5; + Sprite *_asDoor; + Sprite *_asDoorSpy; + Sprite *_asVenusFlyTrap; + Sprite *_ssLadderArch; + Sprite *_ssLadderArchPart1; + Sprite *_ssLadderArchPart2; + Sprite *_ssLadderArchPart3; + Sprite *_ssCeiling; + Sprite *_asKlaymenLadderHands; + Sprite *_asKlaymenPeekHand; + Sprite *_asOutsideDoorBackground; + Sprite *_ssPressButton; + bool _isKlaymenFloor; + bool _isClimbingLadder; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +// Scene1004 + +class AsScene1004TrashCan : public AnimatedSprite { +public: + AsScene1004TrashCan(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1004 : public Scene { +public: + Scene1004(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_asKlaymenLadderHands; + Sprite *_asTrashCan; + int _paletteAreaStatus; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void updatePaletteArea(); +}; + +// Scene1005 + +class Scene1005 : public Scene { +public: + Scene1005(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void drawTextToBackground(); + uint32 getTextIndex(); + uint32 getTextIndex1(); + uint32 getTextIndex2(); + uint32 getTextIndex3(); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1000_H */ diff --git a/engines/neverhood/modules/module1100.cpp b/engines/neverhood/modules/module1100.cpp new file mode 100644 index 0000000000..5a5e52e5b0 --- /dev/null +++ b/engines/neverhood/modules/module1100.cpp @@ -0,0 +1,707 @@ +/* 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/modules/module1100.h" +#include "neverhood/gamemodule.h" +#include "neverhood/navigationscene.h" + +namespace Neverhood { + +static const uint32 kModule1100SoundList[] = { + 0x90805C50, + 0xB288D450, + 0x98C05840, + 0x98A01500, + 0xB4005E50, + 0x92025040, + 0x90035066, + 0x74E01054, + 0 +}; + +Module1100::Module1100(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + if (which < 0) { + createScene(_vm->gameState().sceneNum, -1); + } else if (which == 1) { + createScene(8, 1); + } else { + createScene(8, 3); + } + + _vm->_soundMan->addSoundList(0x0002C818, kModule1100SoundList); + _vm->_soundMan->setSoundListParams(kModule1100SoundList, true, 50, 600, 20, 250); + _vm->_soundMan->setSoundParams(0x74E01054, false, 100, 200, 10, 20); + _vm->_soundMan->setSoundVolume(0x74E01054, 60); + _vm->_soundMan->playTwoSounds(0x0002C818, 0x41861371, 0x43A2507F, 0); + +} + +Module1100::~Module1100() { + _vm->_soundMan->deleteGroup(0x0002C818); +} + +void Module1100::createScene(int sceneNum, int which) { + static const uint32 kSmackerFileHashList06[] = {0x10880805, 0x1088081D, 0}; + static const uint32 kSmackerFileHashList07[] = {0x00290321, 0x01881000, 0}; + debug("Module1100::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _countdown = 65; + createNavigationScene(0x004B8430, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + _countdown = 50; + createNavigationScene(0x004B8460, which); + break; + case 2: + _vm->gameState().sceneNum = 2; + if (getGlobalVar(V_ROBOT_TARGET)) { + createNavigationScene(0x004B84F0, which); + } else { + createNavigationScene(0x004B8490, which); + } + break; + case 3: + _vm->gameState().sceneNum = 3; + if (getGlobalVar(V_ROBOT_TARGET)) { + createNavigationScene(0x004B8580, which); + } else { + createNavigationScene(0x004B8550, which); + } + break; + case 4: + _vm->gameState().sceneNum = 4; + _childObject = new Scene1105(_vm, this); + break; + case 5: + _vm->gameState().sceneNum = 5; + if (getGlobalVar(V_ROBOT_TARGET)) + createSmackerScene(0x04180001, true, false, false); + else + createSmackerScene(0x04180007, true, false, false); + break; + case 6: + _vm->gameState().sceneNum = 6; + _vm->_soundMan->deleteSoundGroup(0x0002C818); + createSmackerScene(kSmackerFileHashList06, true, true, false); + break; + case 7: + _vm->gameState().sceneNum = 7; + _vm->_soundMan->setSoundParams(0x74E01054, false, 0, 0, 0, 0); + createSmackerScene(kSmackerFileHashList07, true, true, false); + break; + case 8: + _vm->gameState().sceneNum = 8; + _childObject = new Scene1109(_vm, this, which); + break; + case 1002: + _vm->gameState().sceneNum = 2; + _countdown = 40; + _vm->_soundMan->setTwoSoundsPlayFlag(true); + createSmackerScene(0x00012211, true, true, false); + break; + } + SetUpdateHandler(&Module1100::updateScene); + _childObject->handleUpdate(); +} + +void Module1100::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + _countdown = 0; + _vm->_soundMan->playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64, 0); + _vm->_soundMan->setSoundVolume(0x48498E46, 65); + _vm->_soundMan->setSoundVolume(0x50399F64, 65); + if (_moduleResult == 0) + createScene(1, 0); + else if (_moduleResult == 1) + createScene(8, 0); + break; + case 1: + _vm->_soundMan->playTwoSounds(0x0002C818, 0x41861371, 0x43A2507F, 0); + if (getGlobalVar(V_ROBOT_HIT)) { + if (_moduleResult == 0) + createScene(6, -1); + else if (_moduleResult == 1) + createScene(0, 1); + } else { + if (_moduleResult == 0) + createScene(2, 0); + else if (_moduleResult == 1) + createScene(0, 1); + } + break; + case 2: + _vm->_soundMan->setSoundParams(0x74E01054, false, 0, 0, 0, 0); + if (_navigationAreaType == 3) + createScene(7, -1); + else if (_moduleResult == 1) + createScene(3, 0); + else if (_moduleResult == 2) + createScene(1002, -1); + break; + case 3: + if (_moduleResult == 0) + createScene(4, 0); + else if (_moduleResult == 1) + createScene(2, 3); + break; + case 4: + if (_moduleResult == 0) + createScene(3, 0); + else if (_moduleResult == 1) + createScene(5, -1); + break; + case 5: + _vm->_soundMan->setTwoSoundsPlayFlag(false); + if (getGlobalVar(V_ROBOT_TARGET)) + createScene(3, 0); + else + createScene(4, 0); + break; + case 6: + _vm->_soundMan->setTwoSoundsPlayFlag(false); + leaveModule(1); + break; + case 7: + _vm->_soundMan->setTwoSoundsPlayFlag(false); + createScene(2, 2); + break; + case 8: + if (_moduleResult == 0) + createScene(0, 0); + else if (_moduleResult == 1) + leaveModule(0); + break; + case 1002: + _vm->_soundMan->setTwoSoundsPlayFlag(false); + _countdown = 0; + _vm->_soundMan->playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64, 0); + createScene(1, 1); + break; + } + } else { + switch (_sceneNum) { + case 0: + if (navigationScene()->isWalkingForward() && _countdown != 0 && (--_countdown == 0)) { + _vm->_soundMan->playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64, 0); + _vm->_soundMan->setSoundVolume(0x48498E46, 65); + _vm->_soundMan->setSoundVolume(0x50399F64, 65); + } + break; + case 1: + if (navigationScene()->isWalkingForward() && _countdown != 0 && (--_countdown == 0)) + _vm->_soundMan->playTwoSounds(0x0002C818, 0x41861371, 0x43A2507F, 0); + break; + case 2: + _vm->_soundMan->setSoundParams(0x74E01054, !navigationScene()->isWalkingForward(), 0, 0, 0, 0); + break; + case 5: + case 6: + case 7: + case 1002: + if (_countdown != 0 && (--_countdown == 0)) { + _vm->_soundMan->playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64, 0); + _vm->_soundMan->setSoundVolume(0x48498E46, 65); + _vm->_soundMan->setSoundVolume(0x50399F64, 65); + } + break; + } + } +} + +static const uint32 kScene1105FileHashes[] = { + 0x00028006, + 0x0100A425, + 0x63090415, + 0x082100C4, + 0x0068C607, + 0x00018344, + 0x442090E4, + 0x0400E004, + 0x5020A054, + 0xB14A891E +}; + +static const uint32 kScene1105BackgroundFileHashes[] = { + 0x20018662, + 0x20014202, + 0x20012202, + 0x20010002 // CHECKME: This used ?? +}; + +static const uint32 kSsScene1105SymbolDieFileHashes[] = { + 0, + 0x90898414, + 0x91098414, + 0x92098414, + 0x94098414, + 0x98098414, + 0x80098414, + 0xB0098414, + 0xD0098414, + 0x10098414 +}; + +SsScene1105Button::SsScene1105Button(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, NRect &collisionBounds) + : StaticSprite(vm, fileHash, 200), _parentScene(parentScene), _countdown(0) { + + _collisionBounds = collisionBounds; + SetMessageHandler(&SsScene1105Button::handleMessage); + SetUpdateHandler(&SsScene1105Button::update); + setVisible(false); +} + +void SsScene1105Button::update() { + if (_countdown != 0 && (--_countdown == 0)) { + sendMessage(_parentScene, 0x4807, 0); + setVisible(false); + } +} + +uint32 SsScene1105Button::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown == 0) { + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + } + break; + case 0x480B: + _countdown = 8; + setVisible(true); + playSound(0, 0x44141000); + break; + } + return messageResult; +} + +SsScene1105Symbol::SsScene1105Symbol(NeverhoodEngine *vm, uint32 fileHash, int16 x, int16 y) + : StaticSprite(vm, 0) { + + loadSprite(fileHash, kSLFCenteredDrawOffset | kSLFSetPosition, 200, x, y); +} + +void SsScene1105Symbol::hide() { + setVisible(false); + _needRefresh = true; + updatePosition(); +} + +SsScene1105SymbolDie::SsScene1105SymbolDie(NeverhoodEngine *vm, uint dieIndex, int16 x, int16 y) + : StaticSprite(vm, 1100), _dieIndex(dieIndex) { + + _x = x; + _y = y; + createSurface(200, 50, 50); + loadSymbolSprite(); + SetMessageHandler(&SsScene1105SymbolDie::handleMessage); +} + +uint32 SsScene1105SymbolDie::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + loadSymbolSprite(); + break; + } + return messageResult; +} + +void SsScene1105SymbolDie::loadSymbolSprite() { + loadSprite(kSsScene1105SymbolDieFileHashes[getSubVar(VA_CURR_DICE_NUMBERS, _dieIndex)], kSLFCenteredDrawOffset); +} + +void SsScene1105SymbolDie::hide() { + setVisible(false); + _needRefresh = true; + updatePosition(); +} + +AsScene1105TeddyBear::AsScene1105TeddyBear(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1100), _parentScene(parentScene) { + + createSurface(100, 556, 328); + _x = 320; + _y = 240; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1105TeddyBear::handleMessage); + startAnimation(0x65084002, 0, -1); + _newStickFrameIndex = 0; + setVisible(false); + _needRefresh = true; + updatePosition(); + loadSound(0, 0xCE840261); + loadSound(1, 0xCCA41A62); +} + +uint32 AsScene1105TeddyBear::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2002: + if (getGlobalVar(V_ROBOT_TARGET)) { + startAnimation(0x6B0C0432, 0, -1); + playSound(0); + } else { + startAnimation(0x65084002, 0, -1); + playSound(1); + } + break; + case 0x3002: + sendMessage(_parentScene, 0x2003, 0); + stopAnimation(); + break; + } + return messageResult; +} + +void AsScene1105TeddyBear::show() { + setVisible(true); + _needRefresh = true; + updatePosition(); +} + +void AsScene1105TeddyBear::hide() { + setVisible(false); + _needRefresh = true; + updatePosition(); +} + +SsScene1105OpenButton::SsScene1105OpenButton(NeverhoodEngine *vm, Scene *parentScene) + : StaticSprite(vm, 900), _parentScene(parentScene), _countdown(0), _isClicked(false) { + + loadSprite(0x8228A46C, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); + setVisible(false); + loadSound(0, 0x44045140); + SetUpdateHandler(&SsScene1105OpenButton::update); + SetMessageHandler(&SsScene1105OpenButton::handleMessage); +} + +void SsScene1105OpenButton::update() { + updatePosition(); + if (_countdown != 0 && (--_countdown == 0)) { + setVisible(false); + sendMessage(_parentScene, 0x2001, 0); + } +} + +uint32 SsScene1105OpenButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown == 0 && !_isClicked) { + playSound(0); + setVisible(true); + _isClicked = true; + _countdown = 4; + } + messageResult = 1; + break; + } + return messageResult; +} + +Scene1105::Scene1105(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule), _countdown(0), _isPanelOpen(false), _isActionButtonClicked(false), _doMoveTeddy(false), + _isClosePanelDone(false), _leaveResult(0), _backgroundIndex(0) { + + Sprite *ssOpenButton; + + _vm->gameModule()->initMemoryPuzzle(); + + SetUpdateHandler(&Scene1105::update); + SetMessageHandler(&Scene1105::handleMessage); + + setBackground(0x20010002); + setPalette(0x20010002); + + _asTeddyBear = insertSprite(this); + ssOpenButton = insertSprite(this); + addCollisionSprite(ssOpenButton); + insertPuzzleMouse(0x10006208, 20, 620); + + loadSound(0, 0x48442057); + loadSound(1, 0xC025014F); + loadSound(2, 0x68E25540); + +} + +uint32 Scene1105::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { + if (!_isActionButtonClicked && _backgroundIndex == 0) { + if (_isPanelOpen) { + _isPanelOpen = false; + _backgroundIndex = 15; + SetUpdateHandler(&Scene1105::upClosePanel); + } else + _isPanelOpen = true; + _leaveResult = 0; + } + } + break; + case 0x2001: + showMouse(false); + _backgroundIndex = 24; + SetUpdateHandler(&Scene1105::upOpenPanel); + break; + case 0x2003: + _backgroundIndex = 24; + _leaveResult = 1; + SetUpdateHandler(&Scene1105::upClosePanel); + break; + case 0x4807: + if (sender == _ssActionButton) { + if (getSubVar(VA_GOOD_DICE_NUMBERS, 0) == getSubVar(VA_CURR_DICE_NUMBERS, 0) && + getSubVar(VA_GOOD_DICE_NUMBERS, 1) == getSubVar(VA_CURR_DICE_NUMBERS, 1) && + getSubVar(VA_GOOD_DICE_NUMBERS, 2) == getSubVar(VA_CURR_DICE_NUMBERS, 2)) { + setGlobalVar(V_ROBOT_TARGET, 1); + playSound(2); + _doMoveTeddy = true; + } else { + sendMessage(_asTeddyBear, 0x2002, 0); + } + showMouse(false); + _isActionButtonClicked = true; + } + break; + case 0x4826: + if (_isPanelOpen) { + if (sender == _ssActionButton) { + sendMessage(_ssActionButton, 0x480B, 0); + _isPanelOpen = false; + } else if (!getGlobalVar(V_ROBOT_TARGET)) { + if (sender == _ssSymbol1UpButton) { + if (getSubVar(VA_CURR_DICE_NUMBERS, 0) < 9) { + incSubVar(VA_CURR_DICE_NUMBERS, 0, +1); + sendMessage(_ssSymbol1UpButton, 0x480B, 0); + sendMessage(_ssSymbolDice[0], 0x2000, 0); + } + } else if (sender == _ssSymbol1DownButton) { + if (getSubVar(VA_CURR_DICE_NUMBERS, 0) > 1) { + incSubVar(VA_CURR_DICE_NUMBERS, 0, -1); + sendMessage(_ssSymbol1DownButton, 0x480B, 0); + sendMessage(_ssSymbolDice[0], 0x2000, 0); + } + } else if (sender == _ssSymbol2UpButton) { + if (getSubVar(VA_CURR_DICE_NUMBERS, 1) < 9) { + incSubVar(VA_CURR_DICE_NUMBERS, 1, +1); + sendMessage(_ssSymbol2UpButton, 0x480B, 0); + sendMessage(_ssSymbolDice[1], 0x2000, 0); + } + } else if (sender == _ssSymbol2DownButton) { + if (getSubVar(VA_CURR_DICE_NUMBERS, 1) > 1) { + incSubVar(VA_CURR_DICE_NUMBERS, 1, -1); + sendMessage(_ssSymbol2DownButton, 0x480B, 0); + sendMessage(_ssSymbolDice[1], 0x2000, 0); + } + } else if (sender == _ssSymbol3UpButton) { + if (getSubVar(VA_CURR_DICE_NUMBERS, 2) < 9) { + incSubVar(VA_CURR_DICE_NUMBERS, 2, +1); + sendMessage(_ssSymbol3UpButton, 0x480B, 0); + sendMessage(_ssSymbolDice[2], 0x2000, 0); + } + } else if (sender == _ssSymbol3DownButton) { + if (getSubVar(VA_CURR_DICE_NUMBERS, 2) > 1) { + incSubVar(VA_CURR_DICE_NUMBERS, 2, -1); + sendMessage(_ssSymbol3DownButton, 0x480B, 0); + sendMessage(_ssSymbolDice[2], 0x2000, 0); + } + } + } + } + break; + } + return messageResult; +} + +void Scene1105::createObjects() { + _ssSymbols[0] = insertSprite(kScene1105FileHashes[getSubVar(VA_DICE_MEMORY_SYMBOLS, 0)], 161, 304); + _ssSymbols[1] = insertSprite(kScene1105FileHashes[getSubVar(VA_DICE_MEMORY_SYMBOLS, 1)], 294, 304); + _ssSymbols[2] = insertSprite(kScene1105FileHashes[getSubVar(VA_DICE_MEMORY_SYMBOLS, 2)], 440, 304); + + _ssSymbolDice[0] = insertSprite(0, 206, 304); + _ssSymbolDice[1] = insertSprite(1, 339, 304); + _ssSymbolDice[2] = insertSprite(2, 485, 304); + + _ssSymbol1UpButton = insertSprite(this, 0x08002860, NRect(146, 362, 192, 403)); + addCollisionSprite(_ssSymbol1UpButton); + _ssSymbol1DownButton = insertSprite(this, 0x42012460, NRect(147, 404, 191, 442)); + addCollisionSprite(_ssSymbol1DownButton); + _ssSymbol2UpButton = insertSprite(this, 0x100030A0, NRect(308, 361, 355, 402)); + addCollisionSprite(_ssSymbol2UpButton); + _ssSymbol2DownButton = insertSprite(this, 0x840228A0, NRect(306, 406, 352, 445)); + addCollisionSprite(_ssSymbol2DownButton); + _ssSymbol3UpButton = insertSprite(this, 0x20000120, NRect(476, 358, 509, 394)); + addCollisionSprite(_ssSymbol3UpButton); + _ssSymbol3DownButton = insertSprite(this, 0x08043121, NRect(463, 401, 508, 438)); + addCollisionSprite(_ssSymbol3DownButton); + _ssActionButton = insertSprite(this, 0x8248AD35, NRect(280, 170, 354, 245)); + addCollisionSprite(_ssActionButton); + + _isPanelOpen = true; + + _asTeddyBear->show(); + + insertPuzzleMouse(0x18666208, 20, 620); + +} + +void Scene1105::upOpenPanel() { + Scene::update(); + if (_backgroundIndex != 0) { + _backgroundIndex--; + if (_backgroundIndex < 6 && _backgroundIndex % 2 == 0) { + uint32 backgroundFileHash = kScene1105BackgroundFileHashes[_backgroundIndex / 2]; + changeBackground(backgroundFileHash); + _palette->addPalette(backgroundFileHash, 0, 256, 0); + } + if (_backgroundIndex == 10) + playSound(0); + if (_backgroundIndex == 0) { + SetUpdateHandler(&Scene1105::update); + _countdown = 2; + } + } +} + +void Scene1105::upClosePanel() { + Scene::update(); + if (_backgroundIndex != 0) { + _backgroundIndex--; + if (_backgroundIndex == 14) { + showMouse(false); + _ssSymbols[0]->hide(); + _ssSymbols[1]->hide(); + _ssSymbols[2]->hide(); + _ssSymbolDice[0]->hide(); + _ssSymbolDice[1]->hide(); + _ssSymbolDice[2]->hide(); + } + if (_backgroundIndex < 6 && _backgroundIndex % 2 == 0) { + uint32 backgroundFileHash = kScene1105BackgroundFileHashes[3 - _backgroundIndex / 2]; // CHECKME + if (_backgroundIndex == 4) { + playSound(1); + _asTeddyBear->hide(); + } + changeBackground(backgroundFileHash); + _palette->addPalette(backgroundFileHash, 0, 256, 0); + } + if (_backgroundIndex == 0) { + SetUpdateHandler(&Scene1105::update); + _isClosePanelDone = true; + } + } +} + +void Scene1105::update() { + + // DEBUG: Show the correct code + debug("(%d, %d) (%d, %d) (%d, %d)", + getSubVar(VA_GOOD_DICE_NUMBERS, 0), getSubVar(VA_CURR_DICE_NUMBERS, 0), + getSubVar(VA_GOOD_DICE_NUMBERS, 1), getSubVar(VA_CURR_DICE_NUMBERS, 1), + getSubVar(VA_GOOD_DICE_NUMBERS, 2), getSubVar(VA_CURR_DICE_NUMBERS, 2)); + + Scene::update(); + if (_countdown != 0 && (--_countdown == 0)) + createObjects(); + if (_isClosePanelDone && !isSoundPlaying(1)) + leaveScene(_leaveResult); + if (_doMoveTeddy && !isSoundPlaying(2)) { + sendMessage(_asTeddyBear, 0x2002, 0); + _doMoveTeddy = false; + } +} + +Scene1109::Scene1109(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + SetMessageHandler(&Scene1109::handleMessage); + + setBackground(0x8449E02F); + setPalette(0x8449E02F); + insertScreenMouse(0x9E02B84C); + + _sprite1 = insertStaticSprite(0x600CEF01, 1100); + + if (which < 0) { + // Restoring game + insertKlaymen(140, 436); + setMessageList(0x004B6260); + sendMessage(this, 0x2000, 0); + } else if (which == 1) { + // Klaymen teleporting in + insertKlaymen(450, 436); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B6268, false); + sendMessage(this, 0x2000, 1); + } else if (which == 2) { + // Klaymen teleporting out + insertKlaymen(450, 436); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B6318, false); + sendMessage(this, 0x2000, 1); + } else if (which == 3) { + // Klaymen returning from teleporter console + insertKlaymen(450, 436); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B6278, false); + sendMessage(this, 0x2000, 1); + } else { + // Klaymen entering from the left + insertKlaymen(0, 436); + setMessageList(0x004B6258); + sendMessage(this, 0x2000, 0); + } + + _klaymen->setClipRect(0, 0, _sprite1->getDrawRect().x2(), 480); + +} + +uint32 Scene1109::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + if (param.asInteger()) { + setRectList(0x004B63A8); + _klaymen->setKlaymenIdleTable3(); + } else { + setRectList(0x004B6398); + _klaymen->setKlaymenIdleTable1(); + } + break; + } + return 0; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1100.h b/engines/neverhood/modules/module1100.h new file mode 100644 index 0000000000..373f6b703f --- /dev/null +++ b/engines/neverhood/modules/module1100.h @@ -0,0 +1,130 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE1100_H +#define NEVERHOOD_MODULES_MODULE1100_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +// Module1100 + +class Module1100 : public Module { +public: + Module1100(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1100(); +protected: + int _sceneNum; + int _countdown; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +class SsScene1105Button : public StaticSprite { +public: + SsScene1105Button(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, NRect &collisionBounds); +protected: + Scene *_parentScene; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene1105Symbol : public StaticSprite { +public: + SsScene1105Symbol(NeverhoodEngine *vm, uint32 fileHash, int16 x, int16 y); + void hide(); +}; + +class SsScene1105SymbolDie : public StaticSprite { +public: + SsScene1105SymbolDie(NeverhoodEngine *vm, uint dieIndex, int16 x, int16 y); + void hide(); +protected: + uint _dieIndex; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void loadSymbolSprite(); +}; + +class AsScene1105TeddyBear : public AnimatedSprite { +public: + AsScene1105TeddyBear(NeverhoodEngine *vm, Scene *parentScene); + void show(); + void hide(); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene1105OpenButton : public StaticSprite { +public: + SsScene1105OpenButton(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + int _countdown; + bool _isClicked; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1105 : public Scene { +public: + Scene1105(NeverhoodEngine *vm, Module *parentModule); +protected: + int _countdown; + int _backgroundIndex; + bool _isPanelOpen; + bool _isActionButtonClicked; + bool _doMoveTeddy; + bool _isClosePanelDone; + int _leaveResult; + AsScene1105TeddyBear *_asTeddyBear; + SsScene1105Symbol *_ssSymbols[3]; + SsScene1105SymbolDie *_ssSymbolDice[3]; + Sprite *_ssSymbol1UpButton; + Sprite *_ssSymbol1DownButton; + Sprite *_ssSymbol2UpButton; + Sprite *_ssSymbol2DownButton; + Sprite *_ssSymbol3UpButton; + Sprite *_ssSymbol3DownButton; + Sprite *_ssActionButton; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void createObjects(); + void upOpenPanel(); + void upClosePanel(); + void update(); +}; + +class Scene1109 : public Scene { +public: + Scene1109(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_sprite1; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1100_H */ diff --git a/engines/neverhood/modules/module1200.cpp b/engines/neverhood/modules/module1200.cpp new file mode 100644 index 0000000000..3be3635645 --- /dev/null +++ b/engines/neverhood/modules/module1200.cpp @@ -0,0 +1,1102 @@ +/* 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/modules/module1200.h" + +namespace Neverhood { + +Module1200::Module1200(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + SetMessageHandler(&Module1200::handleMessage); + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else if (which == 1) + createScene(0, 2); + else + createScene(0, 0); + + _vm->_soundMan->addMusic(0x00478311, 0x62222CAE); + _vm->_soundMan->startMusic(0x62222CAE, 0, 0); +} + +Module1200::~Module1200() { + _vm->_soundMan->deleteMusicGroup(0x00478311); +} + +void Module1200::createScene(int sceneNum, int which) { + debug("Module1200::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _childObject = new Scene1201(_vm, this, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + _childObject = new Scene1202(_vm, this); + break; + case 2: + _vm->gameState().sceneNum = 2; + _vm->_soundMan->stopMusic(0x62222CAE, 0, 0); + createSmackerScene(0x31890001, true, true, false); + setGlobalVar(V_SEEN_CREATURE_EXPLODE_VID, 1); + break; + } + SetUpdateHandler(&Module1200::updateScene); + _childObject->handleUpdate(); +} + +void Module1200::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 1) + createScene(1, 0); + else if (_moduleResult == 2) { + if (getGlobalVar(V_CREATURE_EXPLODED) && !getGlobalVar(V_SEEN_CREATURE_EXPLODE_VID)) + createScene(2, -1); + else + leaveModule(1); + } else + leaveModule(0); + break; + case 1: + createScene(0, 1); + break; + case 2: + _vm->_soundMan->startMusic(0x62222CAE, 0, 0); + createScene(0, 3); + break; + } + } +} + +// Scene1201 + +static const uint32 kScene1201InitArray[] = { + 1, 0, 2, 4, 5, 3, 6, 7, 8, 10, 9, 11, 13, 14, 12, 16, 17, 15 +}; + +static const NPoint kScene1201PointArray[] = { + {218, 193}, {410, 225}, {368, 277}, + {194, 227}, {366, 174}, {458, 224}, + {242, 228}, {512, 228}, {458, 277}, + {217, 233}, {458, 173}, {410, 276}, + {203, 280}, {371, 226}, {508, 279}, + {230, 273}, {410, 171}, {493, 174} +}; + +static const uint32 kScene1201TntFileHashList1[] = { + 0x2098212D, 0x1600437E, 0x1600437E, + 0x00A840E3, 0x1A1830F6, 0x1A1830F6, + 0x00212062, 0x384010B6, 0x384010B6, + 0x07A01080, 0xD80C2837, 0xD80C2837, + 0x03A22092, 0xD8802CB6, 0xD8802CB6, + 0x03A93831, 0xDA460476, 0xDA460476 +}; + +static const uint32 kScene1201TntFileHashList2[] = { + 0x3040C676, 0x10914448, 0x10914448, + 0x3448A066, 0x1288C049, 0x1288C049, + 0x78C0E026, 0x3098D05A, 0x3098D05A, + 0x304890E6, 0x1284E048, 0x1284E048, + 0xB140A1E6, 0x5088A068, 0x5088A068, + 0x74C4C866, 0x3192C059, 0x3192C059 +}; + +SsScene1201Tnt::SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 pointIndex, int16 clipY2) + : StaticSprite(vm, 900) { + + int16 x = kScene1201PointArray[pointIndex].x; + int16 y = kScene1201PointArray[pointIndex].y; + if (x < 300) + loadSprite(kScene1201TntFileHashList1[elemIndex], kSLFDefDrawOffset | kSLFDefPosition, 50); + else + loadSprite(kScene1201TntFileHashList2[elemIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 50, x, y); + setClipRect(0, 0, 640, clipY2); +} + +AsScene1201Tape::AsScene1201Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 nameHash, int surfacePriority, int16 x, int16 y, uint32 fileHash) + : AnimatedSprite(vm, fileHash, surfacePriority, x, y), _parentScene(parentScene), _nameHash(nameHash) { + + if (!getSubVar(VA_HAS_TAPE, _nameHash) && !getSubVar(VA_IS_TAPE_INSERTED, _nameHash)) { + SetMessageHandler(&AsScene1201Tape::handleMessage); + } else { + setVisible(false); + SetMessageHandler(NULL); + } +} + +uint32 AsScene1201Tape::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x4806: + setSubVar(VA_HAS_TAPE, _nameHash, 1); + setVisible(false); + SetMessageHandler(NULL); + break; + } + return messageResult; +} + +AsScene1201TntManRope::AsScene1201TntManRope(NeverhoodEngine *vm, bool isDummyHanging) + : AnimatedSprite(vm, 1200) { + + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1201TntManRope::handleMessage); + createSurface(10, 34, 149); + _x = 202; + _y = -32; + if (isDummyHanging) { + startAnimation(0x928F0C10, 15, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + } else { + startAnimation(0x928F0C10, 0, -1); + _newStickFrameIndex = 0; + } +} + +uint32 AsScene1201TntManRope::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x02060018) + playSound(0, 0x47900E06); + break; + case 0x2006: + startAnimation(0x928F0C10, 1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + break; + } + return messageResult; +} + +AsScene1201RightDoor::AsScene1201RightDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen) + : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown(0) { + + createSurface1(0xD088AC30, 100); + _x = 320; + _y = 240; + SetUpdateHandler(&AsScene1201RightDoor::update); + SetMessageHandler(&AsScene1201RightDoor::handleMessage); + _newStickFrameIndex = STICK_LAST_FRAME; + if (isOpen) { + startAnimation(0xD088AC30, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + _countdown = 25; + } else { + stopAnimation(); + setVisible(false); + } +} + +void AsScene1201RightDoor::update() { + if (_countdown != 0 && (--_countdown == 0)) + stCloseDoor(); + AnimatedSprite::update(); +} + +uint32 AsScene1201RightDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + case 0x4829: + stOpenDoor(); + break; + } + return messageResult; +} + +void AsScene1201RightDoor::stOpenDoor() { + startAnimation(0xD088AC30, 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + setVisible(true); + playSound(0, calcHash("fxDoorOpen20")); +} + +void AsScene1201RightDoor::stCloseDoor() { + startAnimation(0xD088AC30, -1, -1); + _playBackwards = true; + setVisible(true); + playSound(0, calcHash("fxDoorClose20")); + NextState(&AsScene1201RightDoor::stCloseDoorDone); +} + +void AsScene1201RightDoor::stCloseDoorDone() { + stopAnimation(); + setVisible(false); +} + +AsScene1201KlaymenHead::AsScene1201KlaymenHead(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1200) { + + createSurface(1200, 69, 98); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1201KlaymenHead::handleMessage); + SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); + setVisible(false); +} + +uint32 AsScene1201KlaymenHead::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2006: + _x = 436; + _y = 339; + startAnimation(0xA060C599, 0, -1); + setVisible(true); + break; + case 0x3002: + stopAnimation(); + setVisible(false); + gotoNextState(); + break; + } + return messageResult; +} + +AsScene1201TntMan::AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sprite *asTntManRope, bool isComingDown) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _asTntManRope(asTntManRope), + _isMoving(false) { + + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1201TntMan::handleMessage); + createSurface(990, 106, 181); + _x = 201; + if (isComingDown) { + _y = 297; + stComingDown(); + } else { + _y = 334; + stStanding(); + } +} + +AsScene1201TntMan::~AsScene1201TntMan() { + _vm->_soundMan->deleteSoundGroup(0x01D00560); +} + +uint32 AsScene1201TntMan::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x092870C0) + sendMessage(_asTntManRope, 0x2006, 0); + else if (param.asInteger() == 0x11CA0144) + playSound(0, 0x51800A04); + break; + case 0x1011: + sendMessage(_parentScene, 0x2002, 0); + messageResult = 1; + break; + case 0x480B: + if (!_isMoving) { + _sprite = (Sprite*)sender; + stMoving(); + } + break; + } + return messageResult; + +} + +uint32 AsScene1201TntMan::hmComingDown(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = AsScene1201TntMan::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1201TntMan::suMoving() { + _x = _sprite->getX() + 100; +} + +void AsScene1201TntMan::stStanding() { + startAnimation(0x654913D0, 0, -1); + SetMessageHandler(&AsScene1201TntMan::handleMessage); + SetSpriteUpdate(NULL); +} + +void AsScene1201TntMan::stComingDown() { + startAnimation(0x356803D0, 0, -1); + SetMessageHandler(&AsScene1201TntMan::hmComingDown); + SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); + NextState(&AsScene1201TntMan::stStanding); +} + +void AsScene1201TntMan::stMoving() { + _vm->_soundMan->addSound(0x01D00560, 0x4B044624); + _vm->_soundMan->playSoundLooping(0x4B044624); + _isMoving = true; + startAnimation(0x85084190, 0, -1); + SetMessageHandler(&AsScene1201TntMan::handleMessage); + SetSpriteUpdate(&AsScene1201TntMan::suMoving); + _newStickFrameIndex = STICK_LAST_FRAME; +} + +AsScene1201TntManFlame::AsScene1201TntManFlame(NeverhoodEngine *vm, Sprite *asTntMan) + : AnimatedSprite(vm, 1200), _asTntMan(asTntMan) { + + createSurface1(0x828C0411, 995); + SetUpdateHandler(&AsScene1201TntManFlame::update); + SetMessageHandler(&Sprite::handleMessage); + SetSpriteUpdate(&AsScene1201TntManFlame::suUpdate); + startAnimation(0x828C0411, 0, -1); + setVisible(false); +} + +AsScene1201TntManFlame::~AsScene1201TntManFlame() { + _vm->_soundMan->deleteSoundGroup(0x041080A4); +} + +void AsScene1201TntManFlame::update() { + AnimatedSprite::update(); + if (getGlobalVar(V_TNT_DUMMY_FUSE_LIT)) { + setVisible(true); + SetUpdateHandler(&AnimatedSprite::update); + _vm->_soundMan->addSound(0x041080A4, 0x460A1050); + _vm->_soundMan->playSoundLooping(0x460A1050); + } +} + +void AsScene1201TntManFlame::suUpdate() { + _x = _asTntMan->getX() - 18; + _y = _asTntMan->getY() - 158; +} + +AsScene1201Match::AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _countdown(0) { + + createSurface(1100, 57, 60); + SetUpdateHandler(&AsScene1201Match::update); + SetMessageHandler(&AsScene1201Match::hmOnDoorFrameAboutToMove); + SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); + switch (getGlobalVar(V_MATCH_STATUS)) { + case 0: + _x = 521; + _y = 112; + _status = 0; + stIdleOnDoorFrame(); + break; + case 1: + _x = 521; + _y = 112; + _status = 2; + stOnDoorFrameAboutToMove(); + loadSound(0, 0xD00230CD); + break; + case 2: + setDoDeltaX(1); + _x = 403; + _y = 337; + _status = 0; + stIdleOnFloor(); + break; + } +} + +void AsScene1201Match::update() { + if (_countdown != 0 && (--_countdown == 0)) + gotoNextState(); + updateAnim(); + handleSpriteUpdate(); + updatePosition(); +} + +uint32 AsScene1201Match::hmOnDoorFrameAboutToMove(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x86668011) + playSound(0); + break; + } + return messageResult; +} + +uint32 AsScene1201Match::hmOnDoorFrameMoving(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = hmOnDoorFrameAboutToMove(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +uint32 AsScene1201Match::hmIdle(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = hmOnDoorFrameAboutToMove(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x2001, 0); + messageResult = 1; + break; + case 0x4806: + setVisible(false); + setGlobalVar(V_MATCH_STATUS, 3); + break; + } + return messageResult; +} + +void AsScene1201Match::stOnDoorFrameMoving() { + startAnimation(0x00842374, 0, -1); + SetMessageHandler(&AsScene1201Match::hmOnDoorFrameMoving); + if (_status == 0) { + NextState(&AsScene1201Match::stFallingFromDoorFrame); + } else { + NextState(&AsScene1201Match::stOnDoorFrameAboutToMove); + } +} + +void AsScene1201Match::stFallingFromDoorFrame() { + setGlobalVar(V_MATCH_STATUS, 2); + _x -= 199; + _y += 119; + startAnimation(0x018D0240, 0, -1); + SetMessageHandler(&AsScene1201Match::hmOnDoorFrameMoving); + NextState(&AsScene1201Match::stIdleOnFloor); +} + +void AsScene1201Match::stOnDoorFrameAboutToMove() { + startAnimation(0x00842374, 0, -1); + SetMessageHandler(&AsScene1201Match::hmOnDoorFrameAboutToMove); + _newStickFrameIndex = 0; + if (_status != 0) { + _countdown = 36; + _status--; + NextState(&AsScene1201Match::stOnDoorFrameMoving); + } +} + +void AsScene1201Match::stIdleOnDoorFrame() { + startAnimation(0x00842374, 0, -1); + SetMessageHandler(&AsScene1201Match::hmIdle); + _newStickFrameIndex = 0; +} + +void AsScene1201Match::stIdleOnFloor() { + setDoDeltaX(1); + _x = 403; + _y = 337; + startAnimation(0x00842374, 0, -1); + SetMessageHandler(&AsScene1201Match::hmIdle); + _newStickFrameIndex = 0; +} + +AsScene1201Creature::AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen) + : AnimatedSprite(vm, 900), _parentScene(parentScene), _klaymen(klaymen), _klaymenTooClose(false) { + + // NOTE: _countdown2 and _countdown3 were unused/without effect and thus removed + + createSurface(1100, 203, 199); + SetUpdateHandler(&AsScene1201Creature::update); + SetMessageHandler(&AsScene1201Creature::hmWaiting); + _x = 540; + _y = 320; + stWaiting(); +} + +void AsScene1201Creature::update() { + bool oldKlaymenTooClose = _klaymenTooClose; + _klaymenTooClose = _klaymen->getX() >= 385; + if (_klaymenTooClose != oldKlaymenTooClose) + stWaiting(); + if (_countdown != 0 && (--_countdown == 0)) + gotoNextState(); + updateAnim(); + handleSpriteUpdate(); + updatePosition(); +} + +uint32 AsScene1201Creature::hmWaiting(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x02060018) + playSound(0, 0xCD298116); + break; + case 0x2004: + GotoState(&AsScene1201Creature::stStartReachForTntDummy); + break; + case 0x2006: + GotoState(&AsScene1201Creature::stPincerSnapKlaymen); + break; + } + return messageResult; +} + +uint32 AsScene1201Creature::hmPincerSnap(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = hmWaiting(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +uint32 AsScene1201Creature::hmPincerSnapKlaymen(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x02060018) { + playSound(0, 0xCD298116); + sendMessage(_parentScene, 0x4814, 0); + sendMessage(_klaymen, 0x4814, 0); + } + break; + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1201Creature::stWaiting() { + startAnimation(0x08081513, 0, -1); + SetMessageHandler(&AsScene1201Creature::hmWaiting); + NextState(&AsScene1201Creature::stPincerSnap); + _countdown = 36; +} + +void AsScene1201Creature::stPincerSnap() { + if (!_klaymenTooClose) { + startAnimation(0xCA287133, 0, -1); + SetMessageHandler(&AsScene1201Creature::hmPincerSnap); + NextState(&AsScene1201Creature::stWaiting); + } +} + +void AsScene1201Creature::stStartReachForTntDummy() { + startAnimation(0x08081513, 0, -1); + SetMessageHandler(&AsScene1201Creature::hmWaiting); + NextState(&AsScene1201Creature::stReachForTntDummy); + _countdown = 48; +} + +void AsScene1201Creature::stReachForTntDummy() { + startAnimation(0x5A201453, 0, -1); + SetMessageHandler(&AsScene1201Creature::hmWaiting); + _countdown = 0; +} + +void AsScene1201Creature::stPincerSnapKlaymen() { + startAnimation(0xCA287133, 0, -1); + SetMessageHandler(&AsScene1201Creature::hmPincerSnapKlaymen); + NextState(&AsScene1201Creature::stWaiting); + _countdown = 0; +} + +AsScene1201LeftDoor::AsScene1201LeftDoor(NeverhoodEngine *vm, Sprite *klaymen) + : AnimatedSprite(vm, 1100), _klaymen(klaymen) { + + _x = 320; + _y = 240; + createSurface(800, 55, 199); + if (_klaymen->getX() < 100) { + startAnimation(0x508A111B, 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + playSound(0, calcHash("fxDoorOpen03")); + } else { + startAnimation(0x508A111B, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + } + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1201LeftDoor::handleMessage); +} + +uint32 AsScene1201LeftDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4809: + stCloseDoor(); + break; + } + return messageResult; +} + +void AsScene1201LeftDoor::stCloseDoor() { + startAnimation(0x508A111B, -1, -1); + _playBackwards = true; + _newStickFrameIndex = 0; +} + +Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _creatureExploded(false), _asMatch(NULL), _asTntMan(NULL), + _asCreature(NULL), _asTntManRope(NULL), _asLeftDoor(NULL), _asRightDoor(NULL), _asTape(NULL) { + + int16 topY1, topY2, topY3, topY4; + int16 x1, x2; + Sprite *tempSprite; + + SetUpdateHandler(&Scene1201::update); + SetMessageHandler(&Scene1201::handleMessage); + + setHitRects(0x004AEBD0); + + if (!getSubVar(VA_IS_PUZZLE_INIT, 0xE8058B52)) { + setSubVar(VA_IS_PUZZLE_INIT, 0xE8058B52, 1); + for (uint32 index = 0; index < 18; index++) + setSubVar(VA_TNT_POSITIONS, index, kScene1201InitArray[index]); + } + + insertScreenMouse(0x9A2C0409); + + _asTape = insertSprite(this, 3, 1100, 243, 340, 0x9148A011); + addCollisionSprite(_asTape); + + tempSprite = insertStaticSprite(0x03C82530, 100); + topY1 = tempSprite->getY() + tempSprite->getDrawRect().height; + + tempSprite = insertStaticSprite(0x88182069, 200); + topY2 = tempSprite->getY() + tempSprite->getDrawRect().height; + + tempSprite = insertStaticSprite(0x476014E0, 300); + topY3 = tempSprite->getY() + tempSprite->getDrawRect().height; + + tempSprite = insertStaticSprite(0x04063110, 500); + topY4 = tempSprite->getY() + 1; + + _asTntManRope = insertSprite(getGlobalVar(V_TNT_DUMMY_BUILT) && which != 1); + _asTntManRope->setClipRect(0, topY4, 640, 480); + + insertStaticSprite(0x400B04B0, 1200); + + tempSprite = insertStaticSprite(0x40295462, 1200); + x1 = tempSprite->getX(); + + tempSprite = insertStaticSprite(0xA29223FA, 1200); + x2 = tempSprite->getX() + tempSprite->getDrawRect().width; + + _asKlaymenHead = insertSprite(); + + if (which < 0) { + // Restoring game + insertKlaymen(364, 333); + setMessageList(0x004AEC08); + } else if (which == 3) { + // Klaymen standing after the weasel exploded + insertKlaymen(400, 329); + setMessageList(0x004AEC08); + } else if (which == 2) { + // Klaymen entering from the right + if (getGlobalVar(V_CREATURE_ANGRY) && !getGlobalVar(V_CREATURE_EXPLODED)) { + insertKlaymen(374, 333); + setMessageList(0x004AEC08); + } else { + insertKlaymen(640, 329); + setMessageList(0x004AEC20); + } + } else if (which == 1) { + // Klaymen returning from the TNT console + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { + insertKlaymen(364, 333); + _klaymen->setDoDeltaX(1); + } else { + insertKlaymen(246, 333); + } + setMessageList(0x004AEC30); + } else { + // Klaymen entering from the left + insertKlaymen(0, 336); + setMessageList(0x004AEC10); + } + + _klaymen->setClipRect(x1, 0, x2, 480); + _klaymen->setRepl(64, 0); + + if (getGlobalVar(V_CREATURE_ANGRY) && !getGlobalVar(V_CREATURE_EXPLODED)) { + setBackground(0x4019A2C4); + setPalette(0x4019A2C4); + _asRightDoor = NULL; + } else { + setBackground(0x40206EC5); + setPalette(0x40206EC5); + _asRightDoor = insertSprite(_klaymen, which == 2); + } + + if (getGlobalVar(V_TNT_DUMMY_BUILT)) { + insertStaticSprite(0x10002ED8, 500); + if (!getGlobalVar(V_CREATURE_EXPLODED)) { + _asTntMan = insertSprite(this, _asTntManRope, which == 1); + _asTntMan->setClipRect(x1, 0, x2, 480); + _asTntMan->setRepl(64, 0); + addCollisionSprite(_asTntMan); + tempSprite = insertSprite(_asTntMan); + tempSprite->setClipRect(x1, 0, x2, 480); + } + + uint32 tntIndex = 1; + while (tntIndex < 18) { + uint32 elemIndex = getSubVar(VA_TNT_POSITIONS, tntIndex); + int16 clipY2; + if (kScene1201PointArray[elemIndex].y < 175) + clipY2 = topY1; + else if (kScene1201PointArray[elemIndex].y < 230) + clipY2 = topY2; + else + clipY2 = topY3; + insertSprite(tntIndex, getSubVar(VA_TNT_POSITIONS, tntIndex), clipY2); + elemIndex = getSubVar(VA_TNT_POSITIONS, tntIndex + 1); + if (kScene1201PointArray[elemIndex].y < 175) + clipY2 = topY1; + else if (kScene1201PointArray[elemIndex].y < 230) + clipY2 = topY2; + else + clipY2 = topY3; + insertSprite(tntIndex + 1, getSubVar(VA_TNT_POSITIONS, tntIndex + 1), clipY2); + tntIndex += 3; + } + + if (getGlobalVar(V_CREATURE_ANGRY) && !getGlobalVar(V_CREATURE_EXPLODED)) { + setRectList(0x004AEE58); + } else { + setRectList(0x004AEDC8); + } + + } else { + + insertStaticSprite(0x8E8A1981, 900); + + uint32 tntIndex = 0; + while (tntIndex < 18) { + uint32 elemIndex = getSubVar(VA_TNT_POSITIONS, tntIndex); + int16 clipY2; + if (kScene1201PointArray[elemIndex].x < 300) { + clipY2 = 480; + } else { + if (kScene1201PointArray[elemIndex].y < 175) + clipY2 = topY1; + else if (kScene1201PointArray[elemIndex].y < 230) + clipY2 = topY2; + else + clipY2 = topY3; + } + insertSprite(tntIndex, getSubVar(VA_TNT_POSITIONS, tntIndex), clipY2); + tntIndex++; + } + + if (getGlobalVar(V_CREATURE_ANGRY) && !getGlobalVar(V_CREATURE_EXPLODED)) + setRectList(0x004AEE18); + else + setRectList(0x004AED88); + + } + + tempSprite = insertStaticSprite(0x63D400BC, 900); + + _asLeftDoor = insertSprite(_klaymen); + _asLeftDoor->setClipRect(x1, tempSprite->getDrawRect().y, tempSprite->getDrawRect().x2(), 480); + + if (getGlobalVar(V_CREATURE_ANGRY) && getGlobalVar(V_MATCH_STATUS) == 0) + setGlobalVar(V_MATCH_STATUS, 1); + + _asMatch = NULL; + + if (getGlobalVar(V_MATCH_STATUS) < 3) { + _asMatch = insertSprite(this); + addCollisionSprite(_asMatch); + } + + if (getGlobalVar(V_CREATURE_ANGRY) && getGlobalVar(V_CREATURE_EXPLODED) == 0) { + _asCreature = insertSprite(this, _klaymen); + _asCreature->setClipRect(x1, 0, x2, 480); + } + +} + +Scene1201::~Scene1201() { + if (_creatureExploded) + setGlobalVar(V_CREATURE_EXPLODED, 1); + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); +} + +void Scene1201::update() { + Scene::update(); + if (_asMatch && getGlobalVar(V_MATCH_STATUS) == 3) + deleteSprite(&_asMatch); +} + +uint32 Scene1201::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x07053000) { + _creatureExploded = true; + sendMessage(_asCreature, 0x2004, 0); + } else if (param.asInteger() == 0x140E5744) + sendMessage(_asCreature, 0x2005, 0); + else if (param.asInteger() == 0x40253C40) { + _canAcceptInput = false; + sendMessage(_asCreature, 0x2006, 0); + } else if (param.asInteger() == 0x090EB048) { + if (_klaymen->getX() < 572) + setMessageList2(0x004AEC90); + else + setMessageList2(0x004AEC20); + } + break; + case 0x2001: + if (getGlobalVar(V_MATCH_STATUS) == 0) + setMessageList2(0x004AECB0); + else { + sendEntityMessage(_klaymen, 0x1014, _asMatch); + setMessageList2(0x004AECC0); + } + break; + case 0x2002: + if (getGlobalVar(V_TNT_DUMMY_FUSE_LIT)) { + // Move the TNT dummy if the fuse is burning + sendEntityMessage(_klaymen, 0x1014, _asTntMan); + setMessageList2(0x004AECF0, false); + } else if (getGlobalVar(V_MATCH_STATUS) == 3) { + // Light the TNT dummy if we have the match + sendEntityMessage(_klaymen, 0x1014, _asTntMan); + if (_klaymen->getX() > _asTntMan->getX()) + setMessageList(0x004AECD0); + else + setMessageList(0x004AECE0); + } + break; + case 0x4814: + cancelMessageList(); + break; + case 0x4826: + if (sender == _asTape) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004AED38); + } + break; + case 0x4829: + sendMessage(_asRightDoor, 0x4829, 0); + break; + case 0x8000: + sendMessage(_asKlaymenHead, 0x2006, 0); + break; + } + return messageResult; +} + +// Scene1202 + +static const uint32 kScene1202Table[] = { + 1, 2, 0, 4, 5, 3, 7, 8, 6, 10, 11, 9, 13, 14, 12, 16, 17, 15 +}; + +static const NPoint kScene1202Points[] = { + {203, 140}, {316, 212}, {277, 264}, + {176, 196}, {275, 159}, {366, 212}, + {230, 195}, {412, 212}, {368, 263}, + {204, 192}, {365, 164}, {316, 262}, + {191, 255}, {280, 213}, {406, 266}, + {214, 254}, {316, 158}, {402, 161} +}; + +static const uint32 kScene1202FileHashes[] = { + 0x1AC00B8, 0x1AC14B8, 0x1AC14B8, + 0x1AC30B8, 0x1AC14B8, 0x1AC14B8, + 0x1AC00B8, 0x1AC14B8, 0x1AC14B8, + 0x1AC90B8, 0x1AC18B8, 0x1AC18B8, + 0x1AC30B8, 0x1AC14B8, 0x1AC14B8, + 0x1AC50B8, 0x1AC14B8, 0x1AC14B8 +}; + +AsScene1202TntItem::AsScene1202TntItem(NeverhoodEngine *vm, Scene *parentScene, int itemIndex) + : AnimatedSprite(vm, 900), _parentScene(parentScene), _itemIndex(itemIndex) { + + int positionIndex; + + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1202TntItem::hmShowIdle); + positionIndex = getSubVar(VA_TNT_POSITIONS, _itemIndex); + createSurface(900, 37, 67); + _x = kScene1202Points[positionIndex].x; + _y = kScene1202Points[positionIndex].y; + stShowIdle(); +} + +uint32 AsScene1202TntItem::hmShowIdle(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x2000, _itemIndex); + messageResult = 1; + break; + case 0x2001: + _newPosition = (int)param.asInteger(); + stChangePositionFadeOut(); + break; + } + return messageResult; +} + +uint32 AsScene1202TntItem::hmChangePosition(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1202TntItem::stShowIdle() { + startAnimation(kScene1202FileHashes[_itemIndex], 0, -1); + SetMessageHandler(&AsScene1202TntItem::hmShowIdle); + _newStickFrameIndex = 0; +} + +void AsScene1202TntItem::stChangePositionFadeOut() { + startAnimation(kScene1202FileHashes[_itemIndex], 0, -1); + SetMessageHandler(&AsScene1202TntItem::hmChangePosition); + NextState(&AsScene1202TntItem::stChangePositionFadeIn); +} + +void AsScene1202TntItem::stChangePositionFadeIn() { + _x = kScene1202Points[_newPosition].x; + _y = kScene1202Points[_newPosition].y; + startAnimation(kScene1202FileHashes[_itemIndex], 6, -1); + _playBackwards = true; + SetMessageHandler(&AsScene1202TntItem::hmChangePosition); + NextState(&AsScene1202TntItem::stChangePositionDone); +} + +void AsScene1202TntItem::stChangePositionDone() { + sendMessage(_parentScene, 0x2002, _itemIndex); + stShowIdle(); +} + +Scene1202::Scene1202(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule), _paletteResource(vm), + _soundToggle(true), _isPuzzleSolved(false), _counter(0), _clickedIndex(-1) { + + SetMessageHandler(&Scene1202::handleMessage); + SetUpdateHandler(&Scene1202::update); + + setBackground(0x60210ED5); + setPalette(0x60210ED5); + addEntity(_palette); + + _paletteResource.load(0x60250EB5); + _paletteResource.copyPalette(_paletteData); + + insertPuzzleMouse(0x10ED160A, 20, 620); + + for (int tntIndex = 0; tntIndex < 18; tntIndex++) { + _asTntItems[tntIndex] = insertSprite(this, tntIndex); + addCollisionSprite(_asTntItems[tntIndex]); + } + + insertStaticSprite(0x8E8419C1, 1100); + + if (getGlobalVar(V_TNT_DUMMY_BUILT)) + SetMessageHandler(&Scene1202::hmSolved); + + playSound(0, 0x40106542); + loadSound(1, 0x40005446); + loadSound(2, 0x40005446); // Same sound as slot 1 + loadSound(3, 0x68E25540); + +} + +Scene1202::~Scene1202() { + if (isSolved()) + setGlobalVar(V_TNT_DUMMY_BUILT, 1); +} + +void Scene1202::update() { + Scene::update(); + if (_isPuzzleSolved) { + if (!isSoundPlaying(3)) + leaveScene(0); + } else if (_counter == 0 && isSolved()) { + _clickedIndex = 0; + SetMessageHandler(&Scene1202::hmSolved); + setGlobalVar(V_TNT_DUMMY_BUILT, 1); + _palette->copyToBasePalette(_paletteData); + _palette->startFadeToPalette(24); + playSound(3); + _isPuzzleSolved = true; + } else if (_clickedIndex >= 0 && _counter == 0) { + // Swap TNT positions + int destIndex = kScene1202Table[_clickedIndex]; + sendMessage(_asTntItems[_clickedIndex], 0x2001, getSubVar(VA_TNT_POSITIONS, destIndex)); + sendMessage(_asTntItems[destIndex], 0x2001, getSubVar(VA_TNT_POSITIONS, _clickedIndex)); + int temp = getSubVar(VA_TNT_POSITIONS, destIndex); + setSubVar(VA_TNT_POSITIONS, destIndex, getSubVar(VA_TNT_POSITIONS, _clickedIndex)); + setSubVar(VA_TNT_POSITIONS, _clickedIndex, temp); + _counter = 2; + _clickedIndex = -1; + playSound(_soundToggle ? 1 : 2); + _soundToggle = !_soundToggle; + } +} + +uint32 Scene1202::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && !_isPuzzleSolved) + leaveScene(0); + break; + case 0x2000: + _clickedIndex = (int)param.asInteger(); + break; + case 0x2002: + _counter--; + break; + } + return messageResult; +} + +uint32 Scene1202::hmSolved(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) + leaveScene(0); + break; + } + return 0; +} + +bool Scene1202::isSolved() { + return + getSubVar(VA_TNT_POSITIONS, 0) == 0 && getSubVar(VA_TNT_POSITIONS, 3) == 3 && + getSubVar(VA_TNT_POSITIONS, 6) == 6 && getSubVar(VA_TNT_POSITIONS, 9) == 9 && + getSubVar(VA_TNT_POSITIONS, 12) == 12 && getSubVar(VA_TNT_POSITIONS, 15) == 15; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1200.h b/engines/neverhood/modules/module1200.h new file mode 100644 index 0000000000..c97dc98986 --- /dev/null +++ b/engines/neverhood/modules/module1200.h @@ -0,0 +1,216 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE1200_H +#define NEVERHOOD_MODULES_MODULE1200_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +// Module1200 + +class Module1200 : public Module { +public: + Module1200(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1200(); +protected: + int _sceneNum; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +// Scene1201 + +class AsScene1201Tape : public AnimatedSprite { +public: + AsScene1201Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 nameHash, int surfacePriority, int16 x, int16 y, uint32 fileHash); +protected: + Scene *_parentScene; + uint32 _nameHash; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1201TntManRope : public AnimatedSprite { +public: + AsScene1201TntManRope(NeverhoodEngine *vm, bool isDummyHanging); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1201RightDoor : public AnimatedSprite { +public: + AsScene1201RightDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen); +protected: + Sprite *_klaymen; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stOpenDoor(); + void stCloseDoor(); + void stCloseDoorDone(); +}; + +class AsScene1201KlaymenHead : public AnimatedSprite { +public: + AsScene1201KlaymenHead(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1201TntMan : public AnimatedSprite { +public: + AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sprite *asTntManRope, bool isDown); + virtual ~AsScene1201TntMan(); +protected: + Scene *_parentScene; + Sprite *_asTntManRope; + Sprite *_sprite; + bool _isMoving; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmComingDown(int messageNum, const MessageParam ¶m, Entity *sender); + void suMoving(); + void stStanding(); + void stComingDown(); + void stMoving(); +}; + +class AsScene1201TntManFlame : public AnimatedSprite { +public: + AsScene1201TntManFlame(NeverhoodEngine *vm, Sprite *asTntMan); + ~AsScene1201TntManFlame(); +protected: + Sprite *_asTntMan; + void update(); + void suUpdate(); +}; + +class AsScene1201Match : public AnimatedSprite { +public: + AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + int _countdown; + int _status; + void update(); + uint32 hmOnDoorFrameAboutToMove(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmOnDoorFrameMoving(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmIdle(int messageNum, const MessageParam ¶m, Entity *sender); + void stOnDoorFrameMoving(); + void stFallingFromDoorFrame(); + void stOnDoorFrameAboutToMove(); + void stIdleOnDoorFrame(); + void stIdleOnFloor(); +}; + +class AsScene1201Creature : public AnimatedSprite { +public: + AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen); +protected: + Scene *_parentScene; + Sprite *_klaymen; + int _countdown; + bool _klaymenTooClose; + void update(); + uint32 hmWaiting(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmPincerSnap(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmPincerSnapKlaymen(int messageNum, const MessageParam ¶m, Entity *sender); + void stWaiting(); + void stPincerSnap(); + void stStartReachForTntDummy(); + void stReachForTntDummy(); + void stPincerSnapKlaymen(); +}; + +class AsScene1201LeftDoor : public AnimatedSprite { +public: + AsScene1201LeftDoor(NeverhoodEngine *vm, Sprite *klaymen); +protected: + Sprite *_klaymen; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stCloseDoor(); +}; + +class SsScene1201Tnt : public StaticSprite { +public: + SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 pointIndex, int16 clipY2); +protected: + uint32 _elemIndex; +}; + +class Scene1201 : public Scene { +public: + Scene1201(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene1201(); +protected: + Sprite *_asMatch; + AsScene1201TntMan *_asTntMan; + Sprite *_asCreature; + Sprite *_asTntManRope; + Sprite *_asLeftDoor; + Sprite *_asRightDoor; + Sprite *_asTape; + Sprite *_asKlaymenHead; + bool _creatureExploded; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +// Scene1202 + +class AsScene1202TntItem : public AnimatedSprite { +public: + AsScene1202TntItem(NeverhoodEngine *vm, Scene *parentScene, int index); +protected: + Scene *_parentScene; + int _itemIndex, _newPosition; + uint32 hmShowIdle(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmChangePosition(int messageNum, const MessageParam ¶m, Entity *sender); + void stShowIdle(); + void stChangePositionFadeOut(); + void stChangePositionFadeIn(); + void stChangePositionDone(); +}; + +class Scene1202 : public Scene { +public: + Scene1202(NeverhoodEngine *vm, Module *parentModule); + virtual ~Scene1202(); +protected: + PaletteResource _paletteResource; + Sprite *_asTntItems[18]; + int _counter; + int _clickedIndex; + byte _paletteData[1024]; + bool _isPuzzleSolved; + bool _soundToggle; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmSolved(int messageNum, const MessageParam ¶m, Entity *sender); + bool isSolved(); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1200_H */ diff --git a/engines/neverhood/modules/module1300.cpp b/engines/neverhood/modules/module1300.cpp new file mode 100644 index 0000000000..8dbfcf616c --- /dev/null +++ b/engines/neverhood/modules/module1300.cpp @@ -0,0 +1,1835 @@ +/* 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/modules/module1300.h" +#include "neverhood/modules/module1000.h" +#include "neverhood/modules/module1200.h" +#include "neverhood/modules/module1400.h" +#include "neverhood/modules/module2200.h" +#include "neverhood/gamemodule.h" +#include "neverhood/diskplayerscene.h" +#include "neverhood/menumodule.h" +#include "neverhood/navigationscene.h" +#include "neverhood/smackerscene.h" + +namespace Neverhood { + +static const uint32 kModule1300SoundList[] = { + 0x16805648, + 0x16805C48, + 0xB4964448, + 0x96A05481, + 0xD0E14441, + 0x90815450, + 0 +}; + +Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + _vm->_soundMan->addMusic(0x61C090, 0x00203197); + _vm->_soundMan->addSoundList(0x61C090, kModule1300SoundList); + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 50, 600, 20, 150); + _vm->_soundMan->playTwoSounds(0x61C090, 0x48498E46, 0x50399F64, 0); + _vm->_soundMan->setSoundVolume(0x48498E46, 70); + _vm->_soundMan->setSoundVolume(0x50399F64, 70); + + if (which < 0) { + if (_vm->gameState().sceneNum >= 1 && _vm->gameState().sceneNum <= 17) + createScene(_vm->gameState().sceneNum, -1); + else + createScene(11, 0); + } else { + switch (which) { + case 0: + createScene(11, 0); + break; + case 1: + createScene(13, 0); + break; + case 2: + createScene(14, 0); + break; + case 3: + createScene(15, 0); + break; + case 4: + createScene(7, 0); + break; + case 5: + createScene(5, 1); + break; + case 6: + createScene(5, 5); + break; + case 7: + createScene(3, 0); + break; + case 8: + createScene(1, 0); + break; + case 9: + createScene(2, 0); + break; + case 10: + createScene(6, 0); + break; + case 11: + createScene(4, 0); + break; + default: + createScene(12, 0); + break; + } + } + +} + +Module1300::~Module1300() { + _vm->_soundMan->deleteGroup(0x61C090); +} + +void Module1300::createScene(int sceneNum, int which) { + debug("Module1300::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 1: + _vm->gameState().sceneNum = 1; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->startMusic(0x00203197, 0, 2); + _childObject = new Scene1302(_vm, this, which); + break; + case 2: + _vm->gameState().sceneNum = 2; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + _childObject = new Scene1303(_vm, this); + break; + case 3: + _vm->gameState().sceneNum = 3; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + _childObject = new Scene1304(_vm, this, which); + break; + case 4: + _vm->gameState().sceneNum = 4; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->startMusic(0x00203197, 0, 2); + _childObject = new Scene1305(_vm, this, which); + break; + case 5: + _vm->gameState().sceneNum = 5; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->startMusic(0x00203197, 0, 2); + _childObject = new Scene1306(_vm, this, which); + break; + case 6: + _vm->gameState().sceneNum = 6; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->startMusic(0x00203197, 0, 2); + _childObject = new Scene1307(_vm, this); + break; + case 7: + _vm->gameState().sceneNum = 7; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->startMusic(0x00203197, 0, 2); + _childObject = new Scene1308(_vm, this, which); + break; + case 8: + _vm->gameState().sceneNum = 8; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + _childObject = new DiskplayerScene(_vm, this, 1); + break; + case 9: + _vm->gameState().sceneNum = 9; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + createSmackerScene(0x20082818, true, true, false); + break; + case 10: + _vm->gameState().sceneNum = 10; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + createSmackerScene(0x20082828, true, true, false); + break; + case 11: + _vm->gameState().sceneNum = 11; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + createNavigationScene(0x004B27A8, which); + break; + case 12: + _vm->gameState().sceneNum = 12; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + createNavigationScene(0x004B2718, which); + break; + case 13: + _vm->gameState().sceneNum = 13; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + createNavigationScene(0x004B27D8, which); + break; + case 14: + _vm->gameState().sceneNum = 14; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + createNavigationScene(0x004B2808, which); + break; + case 15: + _vm->gameState().sceneNum = 15; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + createNavigationScene(0x004B2838, which); + break; + case 16: + _vm->gameState().sceneNum = 16; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + _childObject = new Scene1317(_vm, this); + break; + case 17: + _vm->gameState().sceneNum = 17; + _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->stopMusic(0x00203197, 0, 2); + _childObject = new CreditsScene(_vm, this, false); + break; + } + SetUpdateHandler(&Module1300::updateScene); + _childObject->handleUpdate(); +} + +void Module1300::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 1: + if (_moduleResult == 1) + createScene(4, 0); + else + createScene(7, 1); + break; + case 2: + createScene(5, 3); + break; + case 3: + createScene(15, 0); + break; + case 4: + createScene(16, -1); + break; + case 5: + if (_moduleResult == 2) + createScene(8, 0); + else if (_moduleResult == 3) + createScene(2, 0); + else if (_moduleResult == 0) + leaveModule(0); + else if (_moduleResult == 1) + createScene(10, -1); + break; + case 6: + createScene(7, 2); + break; + case 7: + if (_moduleResult == 0) + createScene(13, 0); + else if (_moduleResult == 1) + createScene(1, 0); + else if (_moduleResult == 2) + createScene(6, 0); + break; + case 8: + createScene(5, 2); + break; + case 9: + createScene(5, 0); + break; + case 10: + createScene(14, 0); + break; + case 11: + if (_moduleResult == 0) + createScene(12, 0); + else if (_moduleResult == 1) + createScene(11, 1); + break; + case 12: + if (_moduleResult == 0) + createScene(14, 1); + else if (_moduleResult == 1) + createScene(15, 1); + else if (_moduleResult == 3) + createScene(11, 1); + else if (_moduleResult == 5) + createScene(13, 1); + break; + case 13: + if (_moduleResult == 0) + createScene(12, 2); + else if (_moduleResult == 1) + createScene(7, 0); + break; + case 14: + if (_moduleResult == 0) + createScene(12, 3); + else if (_moduleResult == 1) + createScene(9, -1); + break; + case 15: + if (_moduleResult == 0) + createScene(12, 4); + else if (_moduleResult == 1) + createScene(3, 0); + break; + case 16: + createScene(17, -1); + break; + case 17: + leaveModule(1); + break; + } + } +} + +AsScene1302Bridge::AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1100), _parentScene(parentScene) { + + _x = 320; + _y = 240; + createSurface1(0x88148150, 500); + if (!getGlobalVar(V_FLYTRAP_RING_BRIDGE)) { + startAnimation(0x88148150, 0, -1); + _newStickFrameIndex = 0; + } else { + startAnimation(0x88148150, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + } + loadSound(0, 0x68895082); + loadSound(1, 0x689BD0C1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1302Bridge::handleMessage); +} + +uint32 AsScene1302Bridge::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + case 0x4808: + stLowerBridge(); + break; + case 0x4809: + stRaiseBridge(); + break; + } + return messageResult; +} + +void AsScene1302Bridge::stLowerBridge() { + startAnimation(0x88148150, 0, -1); + playSound(1); + NextState(&AsScene1302Bridge::cbLowerBridgeEvent); +} + +void AsScene1302Bridge::stRaiseBridge() { + startAnimation(0x88148150, 7, -1); + _playBackwards = true; + _newStickFrameIndex = 0; + playSound(0); +} + +void AsScene1302Bridge::cbLowerBridgeEvent() { + sendMessage(_parentScene, 0x2032, 0); + startAnimation(0x88148150, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; +} + +SsScene1302Fence::SsScene1302Fence(NeverhoodEngine *vm) + : StaticSprite(vm, 0x11122122, 200) { + + _firstY = _y; + if (getGlobalVar(V_FLYTRAP_RING_FENCE)) + _y += 152; + loadSound(0, 0x7A00400C); + loadSound(1, 0x78184098); + SetUpdateHandler(&SsScene1302Fence::update); + SetMessageHandler(&SsScene1302Fence::handleMessage); + SetSpriteUpdate(NULL); +} + +void SsScene1302Fence::update() { + handleSpriteUpdate(); + updatePosition(); +} + +uint32 SsScene1302Fence::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4808: + playSound(0); + SetMessageHandler(NULL); + SetSpriteUpdate(&SsScene1302Fence::suMoveDown); + break; + case 0x4809: + playSound(1); + SetMessageHandler(NULL); + SetSpriteUpdate(&SsScene1302Fence::suMoveUp); + break; + } + return messageResult; +} + +void SsScene1302Fence::suMoveDown() { + if (_y < _firstY + 152) + _y += 8; + else { + SetMessageHandler(&SsScene1302Fence::handleMessage); + SetSpriteUpdate(NULL); + } +} + +void SsScene1302Fence::suMoveUp() { + if (_y > _firstY) + _y -= 8; + else { + SetMessageHandler(&SsScene1302Fence::handleMessage); + SetSpriteUpdate(NULL); + } +} + +Scene1302::Scene1302(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + SetMessageHandler(&Scene1302::handleMessage); + + setHitRects(0x004B0858); + setRectList(0x004B0A38); + setBackground(0x420643C4); + setPalette(0x420643C4); + insertScreenMouse(0x643C0428); + + _class595 = insertStaticSprite(0xB0420130, 1015); + _sprite1 = insertStaticSprite(0x942FC224, 300); + _sprite2 = insertStaticSprite(0x70430830, 1200); + _sprite2->setVisible(false); + _sprite3 = insertStaticSprite(0x16E01E20, 1100); + _asRing1 = insertSprite(this, false, 218, 122, _class595->getDrawRect().y, false); + _asRing2 = insertSprite(this, true, 218 + 32, 132, _class595->getDrawRect().y, getGlobalVar(V_FLYTRAP_RING_BRIDGE)); + _asRing3 = insertSprite(this, false, 218 + 32 + 32, 122, _class595->getDrawRect().y, false); + _asRing4 = insertSprite(this, true, 218 + 32 + 32 + 32, 132, _class595->getDrawRect().y, getGlobalVar(V_FLYTRAP_RING_FENCE)); + _asRing5 = insertSprite(this, false, 218 + 32 + 32 + 32 + 32, 115, _class595->getDrawRect().y, false); + _asBridge = insertSprite(this); + _ssFence = insertSprite(); + _ssFence->setClipRect(0, 0, 640, _sprite1->getDrawRect().y2()); + + if (which < 0) { + // Restoring game + insertKlaymen(380, 364); + setMessageList(0x004B0868); + } else { + // Klaymen entering from back + insertKlaymen(293, 330); + setMessageList(0x004B0870); + } + + _klaymen->setClipRect(0, 0, _sprite3->getDrawRect().x2(), 480); + + _asVenusFlyTrap = insertSprite(this, _klaymen, true); + addCollisionSprite(_asVenusFlyTrap); + + sendEntityMessage(_klaymen, 0x2007, _asVenusFlyTrap); + +} + +uint32 Scene1302::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x4A845A00) + sendEntityMessage(_klaymen, 0x1014, _asRing1); + else if (param.asInteger() == 0x43807801) { + if (!getGlobalVar(V_FLYTRAP_RING_BRIDGE)) { + sendEntityMessage(_klaymen, 0x1014, _asRing2); + if (_asVenusFlyTrap->getX() - 10 < 218 + 32 && _asVenusFlyTrap->getX() + 10 > 218 + 32) + setMessageList(0x004B0940); + else + setMessageList(0x004B0938); + } else + setMessageList(0x004B0950); + messageResult = 1; + } else if (param.asInteger() == 0x46C26A01) + sendEntityMessage(_klaymen, 0x1014, _asRing3); + else if (param.asInteger() == 0x468C7B11) { + if (!getGlobalVar(V_FLYTRAP_RING_FENCE)) { + sendEntityMessage(_klaymen, 0x1014, _asRing4); + if (_asVenusFlyTrap->getX() - 10 < 218 + 32 + 32 + 32 && _asVenusFlyTrap->getX() + 10 > 218 + 32 + 32 + 32) + setMessageList(0x004B0940); + else + setMessageList(0x004B0938); + } else + setMessageList(0x004B0950); + messageResult = 1; + } else if (param.asInteger() == 0x42845B19) + sendEntityMessage(_klaymen, 0x1014, _asRing5); + else if (param.asInteger() == 0x430A6060) { + if (getGlobalVar(V_FLYTRAP_RING_BRIDGE)) + setMessageList2(0x004B0910); + else + cancelMessageList(); + } else if (param.asInteger() == 0x012E2070) { + if (getGlobalVar(V_FLYTRAP_RING_BRIDGE)) + setMessageList2(0x004B0968); + else + cancelMessageList(); + } else if (param.asInteger() == 0x11C40840) { + if (_asVenusFlyTrap->getX() >= 260 && _asVenusFlyTrap->getX() <= 342) + setMessageList(0x004B0878); + else + setMessageList(0x004B0978); + } + break; + case 0x2000: + if (_klaymen->getY() > 360) { + sendEntityMessage(_klaymen, 0x1014, _asVenusFlyTrap); + setMessageList2(0x004B08F0); + } else + setMessageList2(0x004B0920); + break; + case 0x2002: + if (_klaymen->getX() > 545) + leaveScene(1); + break; + case 0x2032: + _sprite2->setVisible(true); + break; + case 0x4806: + sendMessage(_parentModule, 0x1024, 2); + if (sender == _asRing1) + playSound(0, 0x665198C0); + else if (sender == _asRing2) { + sendMessage(_asBridge, 0x4808, 0); + setGlobalVar(V_FLYTRAP_RING_BRIDGE, 1); + } else if (sender == _asRing3) + playSound(0, 0xE2D389C0); + else if (sender == _asRing4) { + sendMessage(_ssFence, 0x4808, 0); + setGlobalVar(V_FLYTRAP_RING_FENCE, 1); + } else if (sender == _asRing5) + playSound(0, 0x40428A09); + break; + case 0x4807: + if (sender == _asRing2) { + sendMessage(_asBridge, 0x4809, 0); + setGlobalVar(V_FLYTRAP_RING_BRIDGE, 0); + _sprite2->setVisible(false); + } else if (sender == _asRing4) { + sendMessage(_ssFence, 0x4809, 0); + setGlobalVar(V_FLYTRAP_RING_FENCE, 0); + } else if (sender == _asVenusFlyTrap) { + if (getGlobalVar(V_FLYTRAP_RING_BRIDGE)) + sendMessage(_asRing2, 0x4807, 0); + else + sendMessage(_asRing4, 0x4807, 0); + } + break; + case 0x480F: + if (sender == _asRing2) { + playSound(0, 0x60755842); + sendMessage(_asBridge, 0x4808, 0); + setGlobalVar(V_FLYTRAP_RING_BRIDGE, 1); + } else if (sender == _asRing4) { + playSound(0, 0x60755842); + sendMessage(_ssFence, 0x4808, 0); + setGlobalVar(V_FLYTRAP_RING_FENCE, 1); + } + break; + case 0x482A: + sendMessage(_asVenusFlyTrap, 0x482B, 0); + break; + case 0x482B: + sendMessage(_asVenusFlyTrap, 0x482A, 0); + break; + case 0x8000: + setSpriteSurfacePriority(_class595, 995); + break; + case 0x8001: + setSpriteSurfacePriority(_class595, 1015); + break; + } + return messageResult; +} + +AsScene1303Balloon::AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1100), _parentScene(parentScene) { + + createSurface(200, 128, 315); + _x = 289; + _y = 390; + startAnimation(0x800278D2, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1303Balloon::handleMessage); + SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); +} + +uint32 AsScene1303Balloon::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x2000: + stPopBalloon(); + break; + } + return messageResult; +} + +uint32 AsScene1303Balloon::hmBalloonPopped(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x020B0003) + playSound(0, 0x742B0055); + break; + case 0x3002: + playSound(0, 0x470007EE); + stopAnimation(); + setVisible(false); + SetMessageHandler(NULL); + break; + } + return messageResult; +} + +void AsScene1303Balloon::stPopBalloon() { + startAnimation(0xAC004CD0, 0, -1); + SetMessageHandler(&AsScene1303Balloon::hmBalloonPopped); +} + +Scene1303::Scene1303(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule) { + + SetMessageHandler(&Scene1303::handleMessage); + + setRectList(0x004AF9E8); + setBackground(0x01581A9C); + setPalette(0x01581A9C); + insertScreenMouse(0x81A9801D); + + if (!getGlobalVar(V_BALLOON_POPPED)) { + _asBalloon = insertSprite(this); + addCollisionSprite(_asBalloon); + } + + _sprite1 = insertStaticSprite(0xA014216B, 1100); + + insertKlaymen(207, 332); + setMessageList(0x004AF9A0); + + _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); + +} + +uint32 Scene1303::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + setGlobalVar(V_BALLOON_POPPED, 1); + sendMessage(_asBalloon, 0x2000, 0); + break; + case 0x4826: + if (sender == _asBalloon && getGlobalVar(V_HAS_NEEDLE)) + setMessageList(0x004AF9B8); + break; + } + return 0; +} + +AsScene1304Needle::AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y) + : AnimatedSprite(vm, 0x548E9411, surfacePriority, x, y), _parentScene(parentScene) { + + // NOTE: Skipped check if Klaymen already has the needle since that's done in the scene itself + SetMessageHandler(&AsScene1304Needle::handleMessage); +} + +uint32 AsScene1304Needle::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x4806: + setGlobalVar(V_HAS_NEEDLE, 1); + setVisible(false); + SetMessageHandler(NULL); + break; + } + return messageResult; +} + +Scene1304::Scene1304(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _asNeedle(NULL) { + + SetMessageHandler(&Scene1304::handleMessage); + + setRectList(0x004B91A8); + setBackground(0x062C0214); + setPalette(0x062C0214); + insertScreenMouse(0xC021006A); + + if (getGlobalVar(V_BALLOON_POPPED)) { + _asKey = insertSprite(this, 0, 1100, 278, 347); + addCollisionSprite(_asKey); + } else { + _asKey = insertSprite(0x80106018, 100, 279, 48); + } + + if (!getGlobalVar(V_HAS_NEEDLE)) { + _asNeedle = insertSprite(this, 1100, 278, 347); + addCollisionSprite(_asNeedle); + } + + _sprite1 = insertStaticSprite(0x0562E621, 1100); + insertStaticSprite(0x012AE033, 1100); + insertStaticSprite(0x090AF033, 1100); + + if (which < 0) { + // Restoring game + insertKlaymen(217, 347); + setMessageList(0x004B90E8); + } else { + // Klaymen entering from the left + insertKlaymen(100, 347); + setMessageList(0x004B90F0); + } + + _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); + +} + +uint32 Scene1304::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x415634A4) { + if (getGlobalVar(V_BALLOON_POPPED)) + cancelMessageList(); + else + setMessageList(0x004B9158); + } + break; + case 0x4826: + if (sender == _asNeedle) { + sendEntityMessage(_klaymen, 0x1014, _asNeedle); + setMessageList(0x004B9130); + } else if (sender == _asKey) { + sendEntityMessage(_klaymen, 0x1014, _asKey); + setMessageList(0x004B9140); + } + break; + } + return 0; +} + +Scene1305::Scene1305(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + SetMessageHandler(&Scene1305::handleMessage); + + setRectList(0x004B6E98); + setBackground(0x28801B64); + setPalette(0x28801B64); + insertScreenMouse(0x01B60280); + + if (which < 0) { + // Restoring game + insertKlaymen(212, 441); + setMessageList(0x004B6E40); + } else { + // Klaymen enters falling + insertKlaymen(212, 441); + setMessageList(0x004B6E48); + } + +} + +uint32 Scene1305::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + return Scene::handleMessage(messageNum, param, sender); +} + +AsScene1306Elevator::AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _asElevatorDoor(asElevatorDoor), _isUp(false), _isDown(true), + _countdown(0) { + + _x = 320; + _y = 240; + createSurface1(0x043B0270, 100); + startAnimation(0x043B0270, 0, -1); + _newStickFrameIndex = 0; + loadSound(0, 0x1C100E83); + loadSound(1, 0x1C08CEC5); + loadSound(2, 0x5D011E87); + SetMessageHandler(&AsScene1306Elevator::handleMessage); +} + +void AsScene1306Elevator::update() { + if (_isUp && _countdown != 0 && (--_countdown == 0)) + stGoingDown(); + AnimatedSprite::update(); + if (_currFrameIndex == 7) { + playSound(1); + _asElevatorDoor->setVisible(false); + } +} + +void AsScene1306Elevator::upGoingDown() { + AnimatedSprite::update(); + if (_currFrameIndex == 5) + _asElevatorDoor->setVisible(true); +} + +uint32 AsScene1306Elevator::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2001: + if (_isUp) + _countdown = 144; + messageResult = _isUp ? 1 : 0; + break; + case 0x3002: + gotoNextState(); + break; + case 0x4808: + if (_isDown) + stGoingUp(); + break; + } + return messageResult; +} + +void AsScene1306Elevator::stGoingUp() { + setVisible(true); + _isDown = false; + startAnimation(0x043B0270, 0, -1); + playSound(0); + SetUpdateHandler(&AsScene1306Elevator::update); + NextState(&AsScene1306Elevator::cbGoingUpEvent); +} + +void AsScene1306Elevator::cbGoingUpEvent() { + sendMessage(_parentScene, 0x4808, 0); + _isUp = true; + _countdown = 144; + stopAnimation(); + setVisible(false); + SetUpdateHandler(&AsScene1306Elevator::update); +} + +void AsScene1306Elevator::stGoingDown() { + _isUp = false; + setVisible(true); + startAnimation(0x043B0270, -1, -1); + _playBackwards = true; + playSound(1); + SetUpdateHandler(&AsScene1306Elevator::upGoingDown); + NextState(&AsScene1306Elevator::cbGoingDownEvent); +} + +void AsScene1306Elevator::cbGoingDownEvent() { + _isDown = true; + sendMessage(_parentScene, 0x4809, 0); + stopAnimation(); + SetUpdateHandler(&AsScene1306Elevator::update); +} + +Scene1306::Scene1306(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) + setGlobalVar(V_KEY3_LOCATION, 4); + + SetMessageHandler(&Scene1306::handleMessage); + + setBackground(0x05303114); + setPalette(0x05303114); + insertScreenMouse(0x0311005B); + + if (getGlobalVar(V_KEY3_LOCATION) == 4) { + _asKey = insertSprite(this, 2, 1100, 435, 445); + addCollisionSprite(_asKey); + } + + _ssButton = insertSprite(this, 0x404A36A0, 100, 0x440C1000); + _asTape = insertSprite(this, 19, 1100, 359, 445, 0x9148A011); + _asElevatorDoor = insertSprite(0x043B0270, 90, 320, 240); + _asElevatorDoor->startAnimation(0x043B0270, 6, -1); + _asElevatorDoor->setNewHashListIndex(6); + _asElevator = insertSprite(this, _asElevatorDoor); + _sprite1 = insertStaticSprite(0x036A1EE0, 80); + insertStaticSprite(0x00042313, 1100); + + if (which < 0) { + // Resoring game + insertKlaymen(380, 440); + setMessageList(0x004AFAD0); + sendMessage(this, 0x2000, 0); + addCollisionSprite(_asTape); + } else if (which == 1) { + // Klaymen teleporting in + insertKlaymen(136, 440); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004AFAF0); + sendMessage(this, 0x2000, 1); + addCollisionSprite(_asTape); + } else if (which == 2) { + // Klaymen returning from diskplayer + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { + insertKlaymen(515, 440); + _klaymen->setDoDeltaX(1); + } else { + insertKlaymen(355, 440); + } + setMessageList(0x004AFBC8); + sendMessage(this, 0x2000, 0); + addCollisionSprite(_asTape); + } else if (which == 3) { + // Klaymen returning from window + insertKlaymen(534, 440); + setMessageList(0x004AFC30); + sendMessage(this, 0x2000, 0); + addCollisionSprite(_asTape); + } else if (which == 4) { + // Klaymen teleporting out + insertKlaymen(136, 440); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004AFC38); + sendMessage(this, 0x2000, 1); + addCollisionSprite(_asTape); + } else if (which == 5) { + // Klaymen returning from teleporter + insertKlaymen(136, 440); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004AFB00); + sendMessage(this, 0x2000, 1); + addCollisionSprite(_asTape); + } else { + // Klaymen coming up in elevator + insertKlaymen(286, 408); + setSurfacePriority(_asElevator->getSurface(), 1100); + setSurfacePriority(_asElevatorDoor->getSurface(), 1090); + setSurfacePriority(_sprite1->getSurface(), 1080); + sendMessage(this, 0x2000, 0); + SetMessageHandler(&Scene1306::handleMessage416EB0); + clearRectList(); + sendMessage(_asElevator, 0x4808, 0); + } + +} + +Scene1306::~Scene1306() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); +} + +uint32 Scene1306::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x402064D8) + sendEntityMessage(_klaymen, 0x1014, _ssButton); + else if (param.asInteger() == 0x01C66840) { + if (sendMessage(_asElevator, 0x2001, 0) != 0) + setMessageList(0x004AFBD8); + else + setMessageList(0x004AFAE0); + } else if (param.asInteger() == 0x8E646E00) { + setMessageList(0x004AFAD8); + clearRectList(); + SetMessageHandler(&Scene1306::handleMessage416EB0); + } + break; + case 0x2000: + if (param.asInteger() != 0) { + setRectList(0x004AFD28); + _klaymen->setKlaymenIdleTable3(); + } else { + setRectList(0x004AFD18); + _klaymen->setKlaymenIdleTable1(); + } + break; + case 0x480B: + if (sender == _ssButton) + sendMessage(_asElevator, 0x4808, 0); + break; + case 0x4826: + if (sender == _asKey) { + if (_klaymen->getX() >= 249) { + sendEntityMessage(_klaymen, 0x1014, _asKey); + setMessageList(0x004AFC58); + } + } else if (sender == _asTape) { + if (_klaymen->getX() >= 249) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004AFC68); + } + } + break; + case 0x482A: + setSurfacePriority(_asElevator->getSurface(), 1100); + setSurfacePriority(_asElevatorDoor->getSurface(), 1090); + setSurfacePriority(_sprite1->getSurface(), 1080); + break; + case 0x482B: + setSurfacePriority(_asElevator->getSurface(), 100); + setSurfacePriority(_asElevatorDoor->getSurface(), 90); + setSurfacePriority(_sprite1->getSurface(), 80); + sendMessage(this, 0x2000, 0); + addCollisionSprite(_asTape); + break; + } + return 0; +} + +uint32 Scene1306::handleMessage416EB0(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4808: + setMessageList(0x004AFBD0); + SetMessageHandler(&Scene1306::handleMessage); + break; + case 0x4809: + leaveScene(1); + break; + case 0x482A: + setSurfacePriority(_asElevator->getSurface(), 1100); + setSurfacePriority(_asElevatorDoor->getSurface(), 1090); + setSurfacePriority(_sprite1->getSurface(), 1080); + break; + case 0x482B: + setSurfacePriority(_asElevator->getSurface(), 100); + setSurfacePriority(_asElevatorDoor->getSurface(), 90); + setSurfacePriority(_sprite1->getSurface(), 80); + sendMessage(this, 0x2000, 0); + addCollisionSprite(_asTape); + break; + } + return 0; +} + +static const uint32 kAsScene1307KeyResourceList1[] = { + 0x0438069C, 0x45B0023C, 0x05700217 +}; + +static const uint32 kAsScene1307KeyResourceList2[] = { + 0x04441334, 0x061433F0, 0x06019390 +}; + +static const uint32 kAsScene1307KeyResourceList3[] = { + 0x11A80030, 0x178812B1, 0x1488121C +}; + +static const uint32 *kAsScene1307KeyResourceLists[] = { + kAsScene1307KeyResourceList1, + kAsScene1307KeyResourceList2, + kAsScene1307KeyResourceList3 +}; + +static const int kAsScene1307KeySurfacePriorities[] = { + 700, 500, 300, 100 +}; + +const uint kAsScene1307KeyPointsCount = 12; + +static const NPoint kAsScene1307KeyPoints[] = { + {-2, 0}, {-5, 0}, { 5, 0}, + {12, 0}, {17, 0}, {25, 0}, + {16, -2}, {10, -6}, { 0, -7}, + {-7, -3}, {-3, 4}, { 2, 2} +}; + +const uint kAsScene1307KeyFrameIndicesCount = 20; + +static const int16 kAsScene1307KeyFrameIndices[] = { + 1, 4, 8, 11, 15, 16, 17, 17, 17, 16, + 15, 14, 12, 10, 9, 7, 5, 3, 2, 1 +}; + +const int kAsScene1307KeyDivValue = 200; +const int16 kAsScene1307KeyXDelta = 70; +const int16 kAsScene1307KeyYDelta = -12; + +AsScene1307Key::AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _keyIndex(keyIndex), _clipRects(clipRects), + _isClickable(true) { + + NPoint pt; + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + + _dataResource.load(0x22102142); + _pointList = _dataResource.getPointArray(0xAC849240); + pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; + _x = pt.x; + _y = pt.y; + createSurface(kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4], 190, 148); + startAnimation(fileHashes[0], 0, -1); + loadSound(0, 0xDC4A1280); + loadSound(1, 0xCC021233); + loadSound(2, 0xC4C23844); + loadSound(3, 0xC4523208); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1307Key::handleMessage); +} + +uint32 AsScene1307Key::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_isClickable) { + sendMessage(_parentScene, 0x4826, 0); + stRemoveKey(); + messageResult = 1; + } + break; + case 0x2000: + _isClickable = param.asInteger() != 0; + break; + case 0x2001: + setSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex, param.asInteger()); + stMoveKey(); + break; + case 0x2003: + playSound(3); + stUnlock(); + break; + case 0x2004: + playSound(2); + stInsert(); + break; + } + return messageResult; +} + +void AsScene1307Key::suRemoveKey() { + if (_pointIndex < kAsScene1307KeyPointsCount) { + _x += kAsScene1307KeyPoints[_pointIndex].x; + _y += kAsScene1307KeyPoints[_pointIndex].y; + updateBounds(); + _pointIndex++; + } else { + SetSpriteUpdate(NULL); + } +} + +void AsScene1307Key::suInsertKey() { + if (_pointIndex < kAsScene1307KeyPointsCount) { + _x -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].x; + _y -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].y; + updateBounds(); + _pointIndex++; + if (_pointIndex == 7) + playSound(0); + } else { + SetSpriteUpdate(NULL); + sendMessage(_parentScene, 0x2002, 0); + } +} + +void AsScene1307Key::suMoveKey() { + if (_pointIndex < kAsScene1307KeyFrameIndicesCount) { + _frameIndex += kAsScene1307KeyFrameIndices[_pointIndex]; + _x = _prevX + (_deltaX * _frameIndex) / kAsScene1307KeyDivValue; + _y = _prevY + (_deltaY * _frameIndex) / kAsScene1307KeyDivValue; + updateBounds(); + _pointIndex++; + } else { + NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; + _x = pt.x + kAsScene1307KeyXDelta; + _y = pt.y + kAsScene1307KeyYDelta; + stInsertKey(); + } +} + +void AsScene1307Key::stRemoveKey() { + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + _pointIndex = 0; + startAnimation(fileHashes[0], 0, -1); + playSound(1); + SetSpriteUpdate(&AsScene1307Key::suRemoveKey); +} + +void AsScene1307Key::stInsertKey() { + _pointIndex = 0; + sendMessage(_parentScene, 0x1022, kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]); + setClipRect(_clipRects[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]); + _newStickFrameIndex = STICK_LAST_FRAME; + SetSpriteUpdate(&AsScene1307Key::suInsertKey); +} + +void AsScene1307Key::stMoveKey() { + NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; + int16 newX = pt.x + kAsScene1307KeyXDelta; + int16 newY = pt.y + kAsScene1307KeyYDelta; + sendMessage(_parentScene, 0x1022, 1000); + setClipRect(0, 0, 640, 480); + _prevX = _x; + _prevY = _y; + if (newX == _x && newY == _y) { + stInsertKey(); + } else { + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + _pointIndex = 0; + _frameIndex = 0; + _deltaX = newX - _x; + _deltaY = newY - _y; + startAnimation(fileHashes[0], 0, -1); + SetSpriteUpdate(&AsScene1307Key::suMoveKey); + } +} + +void AsScene1307Key::stUnlock() { + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + startAnimation(fileHashes[1], 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; +} + +void AsScene1307Key::stInsert() { + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + startAnimation(fileHashes[2], 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; +} + +Scene1307::Scene1307(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule), _countdown(0), _asCurrKey(NULL), + _isInsertingKey(false), _doLeaveScene(false), _isPuzzleSolved(false) { + + Sprite *tempSprite; + + _vm->gameModule()->initKeySlotsPuzzle(); + + _dataResource.load(0x22102142); + _keyHolePoints = _dataResource.getPointArray(0xAC849240); + + for (uint i = 0; i < 16; i++) { + NPoint pt = (*_keyHolePoints)[i]; + _keyHoleRects[i].x1 = pt.x - 15; + _keyHoleRects[i].y1 = pt.y - 15; + _keyHoleRects[i].x2 = pt.x + 15; + _keyHoleRects[i].y2 = pt.y + 15; + } + + SetMessageHandler(&Scene1307::handleMessage); + SetUpdateHandler(&Scene1307::update); + + setBackground(0xA8006200); + setPalette(0xA8006200); + addEntity(_palette); + insertPuzzleMouse(0x06204A88, 20, 620); + + tempSprite = insertStaticSprite(0x00A3621C, 800); + _clipRects[0].set(tempSprite->getDrawRect().x, 0, 640, 480); + tempSprite = insertStaticSprite(0x00A3641C, 600); + _clipRects[1].set(tempSprite->getDrawRect().x, 0, 640, 480); + tempSprite = insertStaticSprite(0x00A3681C, 400); + _clipRects[2].set(tempSprite->getDrawRect().x, 0, 640, 480); + tempSprite = insertStaticSprite(0x00A3701C, 200); + _clipRects[3].set(tempSprite->getDrawRect().x, 0, 640, 480); + + for (uint keyIndex = 0; keyIndex < 3; keyIndex++) { + if (getSubVar(VA_IS_KEY_INSERTED, keyIndex)) { + _asKeys[keyIndex] = insertSprite(this, keyIndex, _clipRects); + addCollisionSprite(_asKeys[keyIndex]); + } else { + _asKeys[keyIndex] = NULL; + } + } + + loadSound(0, 0x68E25540); + +} + +void Scene1307::update() { + Scene::update(); + if (_countdown && (--_countdown == 0)) + _doLeaveScene = true; + else if (_countdown == 20) + _palette->startFadeToWhite(40); + if (_doLeaveScene && !isSoundPlaying(0)) { + leaveScene(1); + setGlobalVar(V_KEYDOOR_UNLOCKED, 1); + } +} + +uint32 Scene1307::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (!_isPuzzleSolved) { + if (param.asPoint().x > 20 && param.asPoint().x < 620) { + if (_asCurrKey && !_isInsertingKey) { + int16 mouseX = param.asPoint().x; + int16 mouseY = param.asPoint().y; + uint clickedKeyHoleIndex; + for (clickedKeyHoleIndex = 0; clickedKeyHoleIndex < 16; clickedKeyHoleIndex++) { + if (mouseX >= _keyHoleRects[clickedKeyHoleIndex].x1 && mouseX <= _keyHoleRects[clickedKeyHoleIndex].x2 && + mouseY >= _keyHoleRects[clickedKeyHoleIndex].y1 && mouseY <= _keyHoleRects[clickedKeyHoleIndex].y2) + break; + } + if (clickedKeyHoleIndex < 16) { + // Check if the clicked keyhole is already occupied with a key + bool occupied = false; + for (uint keyIndex = 0; keyIndex < 3 && !occupied; keyIndex++) { + if (getSubVar(VA_IS_KEY_INSERTED, keyIndex) && _asKeys[keyIndex] != _asCurrKey) { + if (getSubVar(VA_CURR_KEY_SLOT_NUMBERS, keyIndex) == clickedKeyHoleIndex) + occupied = true; + } + } + if (!occupied) { + // If the keyhole is free, insert the current key + sendMessage(_asCurrKey, 0x2001, clickedKeyHoleIndex); + _isInsertingKey = true; + _mouseClicked = false; + } + } + } + } else if (_countdown == 0 && !_asCurrKey && !_isInsertingKey) + leaveScene(0); + } + break; + case 0x2002: + // Check if all keys are in the correct keyholes + if (getSubVar(VA_IS_KEY_INSERTED, 0) && getSubVar(VA_CURR_KEY_SLOT_NUMBERS, 0) == getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 0) && + getSubVar(VA_IS_KEY_INSERTED, 1) && getSubVar(VA_CURR_KEY_SLOT_NUMBERS, 1) == getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 1) && + getSubVar(VA_IS_KEY_INSERTED, 2) && getSubVar(VA_CURR_KEY_SLOT_NUMBERS, 2) == getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 2)) { + // Play unlock animations for all keys + for (uint keyIndex = 0; keyIndex < 3; keyIndex++) { + if (_asKeys[keyIndex]) + sendMessage(_asKeys[keyIndex], 0x2003, 1); + } + playSound(0); + _isPuzzleSolved = true; + _countdown = 47; + } else { + for (uint keyIndex = 0; keyIndex < 3; keyIndex++) + if (getSubVar(VA_IS_KEY_INSERTED, keyIndex) && _asKeys[keyIndex]) + sendMessage(_asKeys[keyIndex], 0x2000, 1); + sendMessage(_asCurrKey, 0x2004, 1); + } + _asCurrKey = NULL; + _isInsertingKey = false; + break; + case 0x4826: + _asCurrKey = (Sprite*)sender; + for (uint keyIndex = 0; keyIndex < 3; keyIndex++) + if (getSubVar(VA_IS_KEY_INSERTED, keyIndex) && _asKeys[keyIndex]) + sendMessage(_asKeys[keyIndex], 0x2000, 0); + break; + } + return messageResult; +} + +static const uint32 kScene1308NumberFileHashes[] = { + 0x08006320, 0x10006320, 0x20006320, + 0x40006320, 0x80006320, 0x00006321, + 0x00006322, 0x00006324, 0x00006328, + 0x08306320, 0x10306320, 0x20306320, + 0x40306320, 0x80306320, 0x00306321, + 0x00306322 +}; + +AsScene1308JaggyDoor::AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 0xBA0AE050, 1100, 320, 240), _parentScene(parentScene) { + + setVisible(false); + stopAnimation(); + SetMessageHandler(&AsScene1308JaggyDoor::handleMessage); +} + +uint32 AsScene1308JaggyDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + case 0x4808: + stOpenDoor(); + break; + case 0x4809: + stCloseDoor(); + break; + } + return messageResult; +} + +void AsScene1308JaggyDoor::stOpenDoor() { + startAnimation(0xBA0AE050, 0, -1); + setVisible(true); + playSound(0, calcHash("fxDoorOpen38")); + NextState(&AsScene1308JaggyDoor::stOpenDoorDone); +} + +void AsScene1308JaggyDoor::stOpenDoorDone() { + sendMessage(_parentScene, 0x2000, 0); + stopAnimation(); + setVisible(false); +} + +void AsScene1308JaggyDoor::stCloseDoor() { + startAnimation(0xBA0AE050, -1, -1); + _playBackwards = true; + setVisible(true); + playSound(0, calcHash("fxDoorClose38")); + NextState(&AsScene1308JaggyDoor::stCloseDoorDone); +} + +void AsScene1308JaggyDoor::stCloseDoorDone() { + sendMessage(_parentScene, 0x2001, 0); + stopAnimation(); +} + +AsScene1308KeyboardDoor::AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 0xA08A0851, 1100, 320, 240), _parentScene(parentScene) { + + playSound(0, 0x51456049); + SetMessageHandler(&AsScene1308KeyboardDoor::handleMessage); + NextState(&AsScene1308KeyboardDoor::stFallingKeys); +} + +uint32 AsScene1308KeyboardDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1308KeyboardDoor::stFallingKeys() { + startAnimation(0x6238B191, 0, -1); + _x = 580; + _y = 383; + NextState(&AsScene1308KeyboardDoor::stFallingKeysDone); +} + +void AsScene1308KeyboardDoor::stFallingKeysDone() { + sendMessage(_parentScene, 0x2004, 0); + stopAnimation(); + setVisible(false); +} + +AsScene1308LightWallSymbols::AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 0x80180A10, 100, 320, 240), _parentScene(parentScene) { + + setVisible(false); + stopAnimation(); + Entity::_priority = 1200; + SetMessageHandler(&AsScene1308LightWallSymbols::handleMessage); +} + +uint32 AsScene1308LightWallSymbols::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2002: + stFadeIn(); + break; + case 0x2003: + stFadeOut(); + break; + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1308LightWallSymbols::stFadeIn() { + startAnimation(0x80180A10, 0, -1); + setVisible(true); + _newStickFrameIndex = STICK_LAST_FRAME; +} + +void AsScene1308LightWallSymbols::stFadeOut() { + startAnimation(0x80180A10, -1, -1); + _playBackwards = true; + NextState(&AsScene1308LightWallSymbols::stFadeOutDone); +} + +void AsScene1308LightWallSymbols::stFadeOutDone() { + sendMessage(_parentScene, 0x2003, 0); + stopAnimation(); + setVisible(false); +} + +SsScene1308Number::SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index) + : StaticSprite(vm, fileHash, 100) { + + setVisible(false); + _x = _spriteResource.getPosition().x + index * 20; + updatePosition(); +} + +AsScene1308Mouse::AsScene1308Mouse(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100) { + + _x = 286; + _y = 429; + createSurface1(0xA282C472, 100); + startAnimation(0xA282C472, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1308Mouse::handleMessage); +} + +uint32 AsScene1308Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x66382026) + playSound(0, 0x0CD84468); + else if (param.asInteger() == 0x6E28061C) + playSound(0, 0x78C8402C); + else if (param.asInteger() == 0x462F0410) + playSound(0, 0x60984E28); + break; + } + return messageResult; +} + +Scene1308::Scene1308(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _isProjecting(false), _asProjector(NULL) { + + _vm->gameModule()->initKeySlotsPuzzle(); + + SetMessageHandler(&Scene1308::handleMessage); + + setBackground(0x41024202); + setPalette(0x41024202); + insertScreenMouse(0x24206418); + + _asTape = insertSprite(this, 17, 1100, 502, 445, 0x9148A011); + addCollisionSprite(_asTape); + + if (getGlobalVar(V_MOUSE_SUCKED_IN)) { + insertSprite(); + insertSprite(0x461A1490, 200, 235, 429); + } + + _sprite1 = insertStaticSprite(0x0A042060, 1100); + _asJaggyDoor = insertSprite(this); + _asLightWallSymbols = insertSprite(this); + _ssNumber1 = insertSprite(kScene1308NumberFileHashes[getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 1)], 0); + _ssNumber2 = insertSprite(kScene1308NumberFileHashes[getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 0)], 1); + _ssNumber3 = insertSprite(kScene1308NumberFileHashes[getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 2)], 2); + _sprite2 = insertStaticSprite(0x40043120, 995); + _sprite3 = insertStaticSprite(0x43003100, 995); + _sprite4 = NULL; + + if (which < 0) { + // Restoring game + insertKlaymen(380, 440); + setMessageList(0x004B57C0); + if (getGlobalVar(V_KEYDOOR_UNLOCKED)) { + _sprite4 = insertStaticSprite(0x0101A624, 1100); + setRectList(0x004B5990); + } else { + _sprite5 = insertStaticSprite(0x080811A0, 100); + setRectList(0x004B5980); + } + } else if (which == 1) { + // Klaymen entering from the right + insertKlaymen(640, 440); + setMessageList(0x004B57C8); + if (getGlobalVar(V_KEYDOOR_UNLOCKED)) { + _sprite4 = insertStaticSprite(0x0101A624, 1100); + setRectList(0x004B5990); + } else { + _sprite5 = insertStaticSprite(0x080811A0, 100); + setRectList(0x004B5980); + } + } else if (which == 2) { + // Klaymen returning from keyslots panel + insertKlaymen(475, 440); + setMessageList(0x004B58B0); + if (getGlobalVar(V_KEYDOOR_UNLOCKED)) { + _sprite5 = insertSprite(this); + _sprite4 = insertStaticSprite(0x0101A624, 1100); + _sprite4->setVisible(false); + } else { + _sprite5 = insertStaticSprite(0x080811A0, 100); + setRectList(0x004B5980); + } + } else { + // Klaymen entering from the left + insertKlaymen(41, 440); + setMessageList(0x004B57D0); + sendMessage(_asJaggyDoor, 0x4808, 0); + _sprite1->setVisible(false); + if (getGlobalVar(V_KEYDOOR_UNLOCKED)) { + _sprite4 = insertStaticSprite(0x0101A624, 1100); + _klaymen->setVisible(false); + } else { + _sprite5 = insertStaticSprite(0x080811A0, 100); + _klaymen->setVisible(false); + } + } + + if (_sprite4) + _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite4->getDrawRect().x2(), 480); + else + _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); + + if (getGlobalVar(V_PROJECTOR_LOCATION) == 4) { + _asProjector = insertSprite(this, _klaymen, (Sprite*)NULL); + addCollisionSprite(_asProjector); + _asProjector->setClipRect(0, 0, 640, _sprite2->getDrawRect().y2()); + _asProjector->setRepl(64, 0); + } + +} + +uint32 Scene1308::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x88C11390) { + setRectList(0x004B59A0); + _isProjecting = true; + } else if (param.asInteger() == 0x08821382) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + if (getGlobalVar(V_KEYDOOR_UNLOCKED)) + setRectList(0x004B5990); + else + setRectList(0x004B5980); + _isProjecting = false; + } else if (param.asInteger() == 0x4AC68808) { + clearRectList(); + sendMessage(_asJaggyDoor, 0x4809, 0); + _sprite1->setVisible(false); + _klaymen->setVisible(false); + } + break; + case 0x1022: + if (sender == _asProjector) { + if (param.asInteger() >= 1000) + setSurfacePriority(_sprite3->getSurface(), 1100); + else + setSurfacePriority(_sprite3->getSurface(), 995); + } + break; + case 0x2000: + if (getGlobalVar(V_KEYDOOR_UNLOCKED)) + setRectList(0x004B5990); + else + setRectList(0x004B5980); + setMessageList(0x004B57E8, false); + _sprite1->setVisible(true); + _klaymen->setVisible(true); + break; + case 0x2001: + leaveScene(0); + break; + case 0x2003: + _ssNumber1->setVisible(false); + _ssNumber2->setVisible(false); + _ssNumber3->setVisible(false); + break; + case 0x2004: + _sprite4->setVisible(true); + setRectList(0x004B5990); + break; + case 0x4807: + sendMessage(_asLightWallSymbols, 0x2003, 0); + break; + case 0x480F: + sendMessage(_asLightWallSymbols, 0x2002, 0); + _ssNumber1->setVisible(true); + _ssNumber2->setVisible(true); + _ssNumber3->setVisible(true); + break; + case 0x4826: + if (sender == _asProjector) { + if (_isProjecting) + setMessageList2(0x004B5868); + else { + if (param.asInteger() == 1) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + setMessageList2(0x004B5848); + } else if (sendMessage(_asProjector, 0x480C, _klaymen->getX() <= _asProjector->getX() ? 0 : 1) != 0) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + setMessageList2(0x004B5830); + } else + setMessageList2(0x004B5800); + } + } else if (sender == _asTape) { + if (_isProjecting) + setMessageList2(0x004B5868); + else if (_messageListStatus != 2) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList2(0x004B58E0); + } + } + break; + } + return 0; +} + +Scene1317::Scene1317(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule) { + + SetMessageHandler(&Scene1317::handleMessage); + _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, 0x08982841, true, false)); + _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); + insertScreenMouse(0x08284011); + showMouse(false); + _smackerFileHash = 0; + _keepLastSmackerFrame = false; +} + +void Scene1317::update() { + if (_smackerFileHash) { + _smackerPlayer->open(_smackerFileHash, _keepLastSmackerFrame); + _smackerFileHash = 0; + } + Scene::update(); +} + +void Scene1317::upChooseKing() { + if (!_klaymenBlinks && _klaymenBlinkCountdown != 0 && (--_klaymenBlinkCountdown == 0)) + _klaymenBlinks = true; + + if (!_klaymenBlinks && _smackerPlayer->getFrameNumber() + 1 >= 2) { + _smackerPlayer->rewind(); + } else if (_klaymenBlinks && _smackerPlayer->getFrameNumber() + 1 >= 6) { + _smackerPlayer->rewind(); + _klaymenBlinks = false; + _klaymenBlinkCountdown = _vm->_rnd->getRandomNumber(30 - 1) + 15; + } + + if (!_klaymenBlinks && _decisionCountdown != 0 && (--_decisionCountdown == 0)) + stNoDecisionYet(); + + if (_smackerFileHash) { + _smackerPlayer->open(_smackerFileHash, _keepLastSmackerFrame); + _smackerFileHash = 0; + } + + Scene::update(); + +} + +uint32 Scene1317::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + stChooseKing(); + break; + } + return messageResult; +} + +uint32 Scene1317::hmChooseKing(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x >= 21 && param.asPoint().y >= 24 && + param.asPoint().x <= 261 && param.asPoint().y <= 280) { + stHoborgAsKing(); + } else if (param.asPoint().x >= 313 && param.asPoint().y >= 184 && + param.asPoint().x <= 399 && param.asPoint().y <= 379) { + stKlaymenAsKing(); + } else if (param.asPoint().x >= 347 && param.asPoint().y >= 380 && + param.asPoint().x <= 418 && param.asPoint().y <= 474) { + stKlaymenAsKing(); + } + break; + } + return messageResult; +} + +uint32 Scene1317::hmHoborgAsKing(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + stEndMovie(); + break; + } + return messageResult; +} + +uint32 Scene1317::hmEndMovie(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + leaveScene(0); + break; + } + return messageResult; +} + +void Scene1317::stChooseKing() { + showMouse(true); + _smackerFileHash = 0x10982841; + _keepLastSmackerFrame = true; + _decisionCountdown = 450; + _klaymenBlinks = false; + _klaymenBlinkCountdown = _vm->_rnd->getRandomNumber(30 - 1) + 15; + SetMessageHandler(&Scene1317::hmChooseKing); + SetUpdateHandler(&Scene1317::upChooseKing); +} + +void Scene1317::stNoDecisionYet() { + showMouse(false); + _smackerFileHash = 0x20982841; + _keepLastSmackerFrame = false; + SetMessageHandler(&Scene1317::handleMessage); + SetUpdateHandler(&Scene1317::update); +} + +void Scene1317::stHoborgAsKing() { + showMouse(false); + _smackerFileHash = 0x40982841; + _keepLastSmackerFrame = false; + SetMessageHandler(&Scene1317::hmHoborgAsKing); + SetUpdateHandler(&Scene1317::update); +} + +void Scene1317::stKlaymenAsKing() { + showMouse(false); + _smackerFileHash = 0x80982841; + _keepLastSmackerFrame = false; + SetMessageHandler(&Scene1317::hmEndMovie); + SetUpdateHandler(&Scene1317::update); +} + +void Scene1317::stEndMovie() { + showMouse(false); + _smackerFileHash = 0x40800711; + _keepLastSmackerFrame = false; + SetMessageHandler(&Scene1317::hmEndMovie); + SetUpdateHandler(&Scene1317::update); +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1300.h b/engines/neverhood/modules/module1300.h new file mode 100644 index 0000000000..501f76304f --- /dev/null +++ b/engines/neverhood/modules/module1300.h @@ -0,0 +1,295 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE1300_H +#define NEVERHOOD_MODULES_MODULE1300_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/smackerplayer.h" + +namespace Neverhood { + +// Module1300 + +class Module1300 : public Module { +public: + Module1300(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1300(); +protected: + int _sceneNum; + uint32 _musicFileHash; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +class AsScene1302Bridge : public AnimatedSprite { +public: + AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stLowerBridge(); + void stRaiseBridge(); + void cbLowerBridgeEvent(); +}; + +class SsScene1302Fence : public StaticSprite { +public: + SsScene1302Fence(NeverhoodEngine *vm); +protected: + int16 _firstY; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suMoveDown(); + void suMoveUp(); +}; + +class Scene1302 : public Scene { +public: + Scene1302(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_asVenusFlyTrap; + Sprite *_asBridge; + Sprite *_ssFence; + Sprite *_asRing1; + Sprite *_asRing2; + Sprite *_asRing3; + Sprite *_asRing4; + Sprite *_asRing5; + Sprite *_class595; + Sprite *_sprite1; + Sprite *_sprite2; + Sprite *_sprite3; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1303Balloon : public AnimatedSprite { +public: + AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmBalloonPopped(int messageNum, const MessageParam ¶m, Entity *sender); + void stPopBalloon(); +}; + +class Scene1303 : public Scene { +public: + Scene1303(NeverhoodEngine *vm, Module *parentModule); +protected: + Sprite *_sprite1; + Sprite *_asBalloon; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1304Needle : public AnimatedSprite { +public: + AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1304 : public Scene { +public: + Scene1304(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_sprite1; + Sprite *_asKey; + Sprite *_asNeedle; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1305 : public Scene { +public: + Scene1305(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1306Elevator : public AnimatedSprite { +public: + AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor); +protected: + Scene *_parentScene; + AnimatedSprite *_asElevatorDoor; + bool _isUp; + bool _isDown; + int _countdown; + void update(); + void upGoingDown(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stGoingUp(); + void cbGoingUpEvent(); + void stGoingDown(); + void cbGoingDownEvent(); +}; + +class Scene1306 : public Scene { +public: + Scene1306(NeverhoodEngine *vm, Module *parentModule, int which); + ~Scene1306(); +protected: + Sprite *_ssButton; + Sprite *_asTape; + AnimatedSprite *_asElevatorDoor; + Sprite *_asElevator; + Sprite *_sprite1; + Sprite *_asKey; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage416EB0(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1307Key : public AnimatedSprite { +public: + AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects); +protected: + Scene *_parentScene; + NPointArray *_pointList; + uint _pointIndex; + int _frameIndex; + uint _keyIndex; + NRect *_clipRects; + bool _isClickable; + int16 _prevX, _prevY; + int16 _deltaX, _deltaY; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suRemoveKey(); + void suInsertKey(); + void suMoveKey(); + void stRemoveKey(); + void stInsertKey(); + void stMoveKey(); + void stUnlock(); + void stInsert(); +}; + +class Scene1307 : public Scene { +public: + Scene1307(NeverhoodEngine *vm, Module *parentModule); +protected: + NPointArray *_keyHolePoints; + NRect _keyHoleRects[16]; + NRect _clipRects[4]; + Sprite *_asKeys[3]; + int _countdown; + Sprite *_asCurrKey; + bool _isInsertingKey; + bool _doLeaveScene; + bool _isPuzzleSolved; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1308JaggyDoor : public AnimatedSprite { +public: + AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stOpenDoor(); + void stOpenDoorDone(); + void stCloseDoor(); + void stCloseDoorDone(); +}; + +class AsScene1308KeyboardDoor : public AnimatedSprite { +public: + AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stFallingKeys(); + void stFallingKeysDone(); +}; + +class AsScene1308LightWallSymbols : public AnimatedSprite { +public: + AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stFadeIn(); + void stFadeOut(); + void stFadeOutDone(); +}; + +class SsScene1308Number : public StaticSprite { +public: + SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index); +}; + +class AsScene1308Mouse : public AnimatedSprite { +public: + AsScene1308Mouse(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1308 : public Scene { +public: + Scene1308(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_asTape; + Sprite *_asJaggyDoor; + Sprite *_asLightWallSymbols; + Sprite *_ssNumber1; + Sprite *_ssNumber2; + Sprite *_ssNumber3; + AnimatedSprite *_asProjector; + Sprite *_sprite1; + Sprite *_sprite2; + Sprite *_sprite3; + Sprite *_sprite4; + Sprite *_sprite5; + bool _isProjecting; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1317 : public Scene { +public: + Scene1317(NeverhoodEngine *vm, Module *parentModule); +protected: + SmackerPlayer *_smackerPlayer; + bool _klaymenBlinks; + int _klaymenBlinkCountdown; + int _decisionCountdown; + uint32 _smackerFileHash; + bool _keepLastSmackerFrame; + void update(); + void upChooseKing(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmChooseKing(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmHoborgAsKing(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmEndMovie(int messageNum, const MessageParam ¶m, Entity *sender); + void stChooseKing(); + void stNoDecisionYet(); + void stHoborgAsKing(); + void stKlaymenAsKing(); + void stEndMovie(); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1300_H */ diff --git a/engines/neverhood/modules/module1400.cpp b/engines/neverhood/modules/module1400.cpp new file mode 100644 index 0000000000..4f69637ee0 --- /dev/null +++ b/engines/neverhood/modules/module1400.cpp @@ -0,0 +1,1621 @@ +/* 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/modules/module1400.h" +#include "neverhood/modules/module1000.h" +#include "neverhood/modules/module2100.h" +#include "neverhood/modules/module2200.h" +#include "neverhood/diskplayerscene.h" +#include "neverhood/gamemodule.h" + +namespace Neverhood { + +Module1400::Module1400(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + _vm->_soundMan->addMusic(0x00AD0012, 0x06333232); + _vm->_soundMan->addMusic(0x00AD0012, 0x624A220E); + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else + createScene(0, 0); + +} + +Module1400::~Module1400() { + _vm->_soundMan->deleteMusicGroup(0x00AD0012); +} + +void Module1400::createScene(int sceneNum, int which) { + debug("Module1400::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _vm->_soundMan->startMusic(0x06333232, 0, 2); + _childObject = new Scene1401(_vm, this, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + _vm->_soundMan->stopMusic(0x06333232, 0, 2); + _vm->_soundMan->stopMusic(0x624A220E, 0, 2); + _childObject = new Scene1402(_vm, this, which); + break; + case 2: + _vm->gameState().sceneNum = 2; + _vm->_soundMan->stopMusic(0x06333232, 0, 2); + _vm->_soundMan->startMusic(0x624A220E, 0, 2); + _childObject = new Scene1403(_vm, this, which); + break; + case 3: + _vm->gameState().sceneNum = 3; + _vm->_soundMan->startMusic(0x06333232, 0, 2); + _childObject = new Scene1404(_vm, this, which); + break; + case 4: + _vm->gameState().sceneNum = 4; + _vm->_soundMan->startMusic(0x06333232, 0, 2); + _childObject = new Scene1405(_vm, this); + break; + case 5: + _vm->gameState().sceneNum = 5; + _vm->_soundMan->stopMusic(0x06333232, 0, 2); + _childObject = new DiskplayerScene(_vm, this, 2); + break; + case 6: + _vm->gameState().sceneNum = 6; + _vm->_soundMan->stopMusic(0x06333232, 0, 2); + _childObject = new Scene1407(_vm, this); + break; + } + SetUpdateHandler(&Module1400::updateScene); + _childObject->handleUpdate(); +} + +void Module1400::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 1) + createScene(1, 0); + else if (_moduleResult == 2) + createScene(3, 0); + else + leaveModule(0); + break; + case 1: + if (_moduleResult == 1) + createScene(2, 0); + else if (_moduleResult == 2) + createScene(6, -1); + else + createScene(0, 1); + break; + case 2: + createScene(1, 1); + break; + case 3: + if (_moduleResult == 1) + createScene(4, 0); + else if (_moduleResult == 2) + createScene(5, -1); + else + createScene(0, 2); + break; + case 4: + createScene(3, 1); + break; + case 5: + createScene(3, 2); + break; + case 6: + createScene(1, 2); + break; + } + } +} + +// Scene1401 + +AsScene1401Pipe::AsScene1401Pipe(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100), _countdown1(0), _countdown2(0) { + + createSurface(900, 152, 147); + _x = 454; + _y = 217; + startAnimation(0x4C210500, 0, -1); + SetUpdateHandler(&AsScene1401Pipe::update); + SetMessageHandler(&AsScene1401Pipe::handleMessage); +} + +AsScene1401Pipe::~AsScene1401Pipe() { + _vm->_soundMan->deleteSoundGroup(0x01104C08); +} + +void AsScene1401Pipe::update() { + AnimatedSprite::update(); + if (_countdown1 != 0 && (--_countdown1 == 0)) + stDoneSucking(); + if (_countdown2 != 0 && (--_countdown2 == 0)) { + _vm->_soundMan->addSound(0x01104C08, 0x4A116437); + _vm->_soundMan->playSoundLooping(0x4A116437); + } +} + +void AsScene1401Pipe::upSuckInProjector() { + AnimatedSprite::update(); + if (_countdown1 != 0) + _countdown1--; +} + +uint32 AsScene1401Pipe::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x0A8A1490) + playSound(1, 0x6AB6666F); + break; + case 0x2000: + _countdown1 = 70; + _countdown2 = 8; + stStartSucking(); + break; + case 0x483A: + stSuckInProjector(); + break; + } + return messageResult; +} + +uint32 AsScene1401Pipe::hmSuckInProjector(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + if (_countdown1 != 0) + stStartSucking(); + else + stDoneSucking(); + SetMessageHandler(&AsScene1401Pipe::handleMessage); + SetUpdateHandler(&AsScene1401Pipe::update); + break; + } + return messageResult; +} + +void AsScene1401Pipe::stStartSucking() { + startAnimation(0x4C240100, 0, -1); + playSound(0, 0x4A30063F); +} + +void AsScene1401Pipe::stDoneSucking() { + _vm->_soundMan->deleteSound(0x4A116437); + playSound(0, 0x4A120435); + startAnimation(0x4C210500, 0, -1); +} + +void AsScene1401Pipe::stSuckInProjector() { + startAnimation(0x6C210810, 0, -1); + SetUpdateHandler(&AsScene1401Pipe::upSuckInProjector); + SetMessageHandler(&AsScene1401Pipe::hmSuckInProjector); +} + +AsScene1401Mouse::AsScene1401Mouse(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100) { + + createSurface(100, 71, 41); + _x = 478; + _y = 433; + startAnimation(0xA282C472, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1401Mouse::handleMessage); +} + +uint32 AsScene1401Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x66382026) + playSound(0, 0x0CD84468); + else if (param.asInteger() == 0x6E28061C) + playSound(0, 0x78C8402C); + else if (param.asInteger() == 0x462F0410) + playSound(0, 0x60984E28); + break; + case 0x4839: + stSuckedIn(); + break; + } + return messageResult; +} + +void AsScene1401Mouse::suSuckedIn() { + AnimatedSprite::updateDeltaXY(); + if (_collisionBounds.y1 <= 150) { + playSound(0, 0x0E32247F); + stopAnimation(); + setVisible(false); + SetMessageHandler(NULL); + SetSpriteUpdate(NULL); + } +} + +void AsScene1401Mouse::stSuckedIn() { + startAnimation(0x34880040, 0, -1); + SetSpriteUpdate(&AsScene1401Mouse::suSuckedIn); +} + +AsScene1401Cheese::AsScene1401Cheese(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100) { + + createSurface(200, 152, 147); + _x = 427; + _y = 433; + startAnimation(0x461A1490, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1401Cheese::handleMessage); +} + +uint32 AsScene1401Cheese::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4839: + stSuckedIn(); + break; + } + return messageResult; +} + +void AsScene1401Cheese::suSuckedIn() { + AnimatedSprite::updateDeltaXY(); + if (_collisionBounds.y1 <= 150) { + playSound(0, 0x18020439); + stopAnimation(); + setVisible(false); + SetMessageHandler(NULL); + SetSpriteUpdate(NULL); + } +} + +void AsScene1401Cheese::stSuckedIn() { + startAnimation(0x103B8020, 0, -1); + SetSpriteUpdate(&AsScene1401Cheese::suSuckedIn); +} + +AsScene1401BackDoor::AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen) + : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown(0), _isOpen(isOpen) { + + _x = 320; + _y = 240; + createSurface1(0x04551900, 100); + if (isOpen) { + startAnimation(0x04551900, -1, -1); + _countdown = 48; + } else { + stopAnimation(); + setVisible(false); + } + _newStickFrameIndex = STICK_LAST_FRAME; + SetUpdateHandler(&AsScene1401BackDoor::update); + SetMessageHandler(&AsScene1401BackDoor::handleMessage); +} + +void AsScene1401BackDoor::update() { + if (_countdown != 0 && (--_countdown == 0)) + stCloseDoor(); + AnimatedSprite::update(); +} + + +uint32 AsScene1401BackDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2001: + if (_isOpen) + _countdown = 168; + messageResult = _isOpen ? 1 : 0; + break; + case 0x3002: + gotoNextState(); + break; + case 0x4808: + _countdown = 168; + if (!_isOpen) + stOpenDoor(); + break; + } + return messageResult; +} + +void AsScene1401BackDoor::stOpenDoor() { + _isOpen = true; + setVisible(true); + startAnimation(0x04551900, 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + playSound(0, calcHash("fxDoorOpen24")); +} + +void AsScene1401BackDoor::stCloseDoor() { + _isOpen = false; + setVisible(true); + startAnimation(0x04551900, -1, -1); + playSound(0, calcHash("fxDoorClose24")); + _playBackwards = true; + NextState(&AsScene1401BackDoor::stCloseDoorDone); +} + +void AsScene1401BackDoor::stCloseDoorDone() { + stopAnimation(); + setVisible(false); +} + +static const AsCommonProjectorItem kAsCommonProjectorItems[] = { + {{154, 453}, 4, 2, 0, 0, 1}, + {{104, 391}, 4, -1, -1, 1, 1}, + {{ 22, 447}, 6, -1, -1, 1, 1}, + {{112, 406}, 2, -1, -1, 1, 0}, + {{262, 433}, 1, 1, 0, 0, 0} +}; + +AsCommonProjector::AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _klaymen(klaymen), _asPipe(asPipe) { + + _asProjectorItem = &kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)]; + createSurface(990, 101, 182); + startAnimation(0x10E3042B, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsCommonProjector::handleMessage); + _x = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; + _lockedInSlot = true; + moveProjector(); + setDoDeltaX(1); + if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex) + stStayLockedInSlot(); + loadSound(2, 0xC8C2507C); +} + +AsCommonProjector::~AsCommonProjector() { + _vm->_soundMan->deleteSoundGroup(0x05331081); +} + +uint32 AsCommonProjector::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x4807: + setGlobalVar(V_PROJECTOR_SLOT, (_x - _asProjectorItem->point.x) / 108); + if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex) + stStartLockedInSlot(); + else + stIdle(); + break; + case 0x480B: + if (param.asInteger() != 1) { + if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount) + incGlobalVar(V_PROJECTOR_SLOT, 1); + } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0) + incGlobalVar(V_PROJECTOR_SLOT, -1); + stMoving(); + break; + case 0x480C: + // Check if the projector can be moved + if (param.asInteger() != 1) + messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0; + else + messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0; + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + case 0x4839: + stStartSuckedIn(); + break; + } + return messageResult; +} + +uint32 AsCommonProjector::hmLockedInSlot(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (param.asPoint().x - _x >= 17 && param.asPoint().x - _x <= 56 && + param.asPoint().y - _y >= -120 && param.asPoint().y - _y <= -82) { + sendMessage(_parentScene, 0x4826, 1); + } else + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x4807: + sendMessage(_parentScene, 0x4807, 0); + stStopProjecting(); + break; + case 0x480B: + if (param.asInteger() != 1) { + if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount) + incGlobalVar(V_PROJECTOR_SLOT, 1); + } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0) + incGlobalVar(V_PROJECTOR_SLOT, -1); + stTurnToFront(); + break; + case 0x480C: + // Check if the projector can be moved + if (param.asInteger() != 1) + messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0; + else + messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0; + break; + case 0x480F: + stStartProjecting(); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +uint32 AsCommonProjector::hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsCommonProjector::suMoving() { + if (_x <= _klaymen->getX()) + _x = _klaymen->getX() - 100; + else + _x = _klaymen->getX() + 100; + moveProjector(); + if (_beforeMoveX == _x) { + if (getGlobalVar(V_PROJECTOR_SLOT) == 0 && _asProjectorItem->leftBorderLeaves != 0) { + sendMessage(_parentScene, 0x1019, 0); + incGlobalVar(V_PROJECTOR_LOCATION, -1); + setGlobalVar(V_PROJECTOR_SLOT, kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)].maxSlotCount); + } else if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->maxSlotCount && _asProjectorItem->rightBorderLeaves != 0) { + sendMessage(_parentScene, 0x1019, 1); + incGlobalVar(V_PROJECTOR_LOCATION, +1); + setGlobalVar(V_PROJECTOR_SLOT, 0); + } + } + Sprite::updateBounds(); +} + +void AsCommonProjector::moveProjector() { + + bool nowLockedInSlot = false; + + _y = _asProjectorItem->point.y; + + if (_asProjectorItem->index1 != -1) { + int16 elX = _asProjectorItem->index1 * 108 + _asProjectorItem->point.x; + if (elX - 20 < _x && elX + 20 > _x) { + nowLockedInSlot = true; + _y = _asProjectorItem->point.y + 10; + } + } + + if (_asProjectorItem->lockSlotIndex != -1) { + int16 elX = _asProjectorItem->lockSlotIndex * 108 + _asProjectorItem->point.x; + if (elX - 20 < _x && elX + 20 > _x) { + nowLockedInSlot = true; + _y = _asProjectorItem->point.y + 10; + } + } + + if (_lockedInSlot && !nowLockedInSlot) + _lockedInSlot = false; + else if (!_lockedInSlot && nowLockedInSlot) { + playSound(1, 0x5440E474); + _lockedInSlot = true; + } + +} + +void AsCommonProjector::stSuckedIn() { + AnimatedSprite::updateDeltaXY(); + if (_collisionBounds.y1 <= 150) { + sendMessage(_asPipe, 0x483A, 0); + stopAnimation(); + setVisible(false); + SetMessageHandler(&Sprite::handleMessage); + SetSpriteUpdate(NULL); + } +} + +void AsCommonProjector::stIdle() { + startAnimation(0x10E3042B, 0, -1); + SetMessageHandler(&AsCommonProjector::handleMessage); + SetSpriteUpdate(NULL); +} + +void AsCommonProjector::stMoving() { + _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; + startAnimation(0x14A10137, 0, -1); + playSound(1, 0xEC008474); + SetMessageHandler(&AsCommonProjector::handleMessage); + SetSpriteUpdate(&AsCommonProjector::suMoving); +} + +void AsCommonProjector::stStartLockedInSlot() { + startAnimation(0x80C32213, 0, -1); + SetMessageHandler(&AsCommonProjector::hmAnimation); + SetSpriteUpdate(NULL); + NextState(&AsCommonProjector::stStayLockedInSlot); +} + +void AsCommonProjector::stStayLockedInSlot() { + startAnimation(0xD23B207F, 0, -1); + SetMessageHandler(&AsCommonProjector::hmLockedInSlot); + SetSpriteUpdate(NULL); +} + +void AsCommonProjector::stStartProjecting() { + startAnimation(0x50A80517, 0, -1); + setGlobalVar(V_PROJECTOR_ACTIVE, 1); + playSound(0, 0xCC4A8456); + _vm->_soundMan->addSound(0x05331081, 0xCE428854); + _vm->_soundMan->playSoundLooping(0xCE428854); + SetMessageHandler(&AsCommonProjector::hmAnimation); + SetSpriteUpdate(NULL); + NextState(&AsCommonProjector::stLockedInSlot); +} + +void AsCommonProjector::stLockedInSlot() { + sendMessage(_parentScene, 0x480F, 0); + startAnimation(0xD833207F, 0, -1); + SetMessageHandler(&AsCommonProjector::hmLockedInSlot); + SetSpriteUpdate(NULL); +} + +void AsCommonProjector::stStopProjecting() { + startAnimation(0x50A94417, 0, -1); + setGlobalVar(V_PROJECTOR_ACTIVE, 0); + playSound(0, 0xCC4A8456); + _vm->_soundMan->deleteSound(0xCE428854); + SetMessageHandler(&AsCommonProjector::hmAnimation); + SetSpriteUpdate(NULL); + NextState(&AsCommonProjector::stStayLockedInSlot); +} + +void AsCommonProjector::stTurnToFront() { + _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; + startAnimation(0x22CB4A33, 0, -1); + SetMessageHandler(&AsCommonProjector::hmAnimation); + SetSpriteUpdate(&AsCommonProjector::suMoving); + NextState(&AsCommonProjector::stMoving); +} + +void AsCommonProjector::stStartSuckedIn() { + setGlobalVar(V_PROJECTOR_LOCATION, 4); + setGlobalVar(V_PROJECTOR_SLOT, 0); + startAnimation(0x708D4712, 0, -1); + playSound(2); + SetMessageHandler(&Sprite::handleMessage); + SetSpriteUpdate(&AsCommonProjector::stSuckedIn); +} + +Scene1401::Scene1401(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _projectorBorderFlag(false), _ssFloorButton(NULL), _asProjector(NULL), + _asPipe(NULL), _asMouse(NULL), _asCheese(NULL), _asBackDoor(NULL), + _sprite1(NULL), _sprite2(NULL), _sprite3(NULL), _ssButton(NULL) { + + SetMessageHandler(&Scene1401::handleMessage); + SetUpdateHandler(&Scene1401::update); + + setRectList(0x004B6758); + setBackground(0x08221FA5); + setPalette(0x08221FA5); + insertScreenMouse(0x21FA108A); + + _ssFloorButton = insertSprite(this, 0x980F3124, 0x12192892, 100, 0); + _asPipe = insertSprite(); + + if (!getGlobalVar(V_MOUSE_SUCKED_IN)) { + _asMouse = insertSprite(); + _asCheese = insertSprite(); + } + + _sprite3 = insertStaticSprite(0xA82BA811, 1100); + insertStaticSprite(0x0A116C60, 1100); + _ssButton = insertSprite(this, 0xB84B1100, 100, 0); + _sprite1 = insertStaticSprite(0x38EA100C, 1005); + _sprite2 = insertStaticSprite(0x98D0223C, 1200); + _sprite2->setVisible(false); + + if (which < 0) { + // Restoring game + insertKlaymen(380, 447); + setMessageList(0x004B65C8); + _sprite1->setVisible(false); + } else if (which == 1) { + // Klaymen entering from the left + insertKlaymen(0, 447); + setMessageList(0x004B65D0); + _sprite1->setVisible(false); + } else if (which == 2) { + // Klaymen entering from the right + insertKlaymen(660, 447); + setMessageList(0x004B65D8); + _sprite1->setVisible(false); + } else { + // Klaymen entering from the back + insertKlaymen(290, 413); + setMessageList(0x004B65E8); + _sprite1->setVisible(false); + } + + if (getGlobalVar(V_PROJECTOR_LOCATION) == 2) { + _asProjector = insertSprite(this, _klaymen, _asPipe); + addCollisionSprite(_asProjector); + if (getGlobalVar(V_PROJECTOR_SLOT) == 6) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + _klaymen->setX(_asProjector->getX() + 100); + _klaymen->updateBounds(); + setMessageList(0x004B6670); + } else if (getGlobalVar(V_PROJECTOR_SLOT) == 0) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + _klaymen->setX(_asProjector->getX() - 100); + _klaymen->updateBounds(); + setMessageList(0x004B6670); + } + _asProjector->setClipRect(_sprite3->getDrawRect().x, _sprite2->getDrawRect().y, 640, 480); + } + + _klaymen->setClipRect(_sprite3->getDrawRect().x, 0, 640, 480); + + if (which == 0 && _asProjector) + sendMessage(_asProjector, 0x482B, 0); + + _asBackDoor = insertSprite(_klaymen, which == 0); + +} + +void Scene1401::update() { + Scene::update(); + if (_asProjector && !_projectorBorderFlag && _asProjector->getY() < 360) { + _sprite2->setVisible(true); + _projectorBorderFlag = true; + } else + _sprite2->setVisible(false); +} + +uint32 Scene1401::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x02144CB1) + sendEntityMessage(_klaymen, 0x1014, _ssFloorButton); + else if (param.asInteger() == 0x402064D8) + sendEntityMessage(_klaymen, 0x1014, _ssButton); + else if (param.asInteger() == 0x01C66840) { + if (sendMessage(_asBackDoor, 0x2001, 0) != 0) + setMessageList(0x004B6690); + else + setMessageList(0x004B66B0); + } + break; + case 0x1019: + if (param.asInteger() != 0) + leaveScene(2); + else + leaveScene(1); + break; + case 0x480B: + if (sender == _ssFloorButton) { + sendMessage(_asPipe, 0x2000, 0); + if (!getGlobalVar(V_MOUSE_SUCKED_IN)) { + sendMessage(_asMouse, 0x4839, 0); + sendMessage(_asCheese, 0x4839, 0); + setGlobalVar(V_MOUSE_SUCKED_IN, 1); + } + if (_asProjector && _asProjector->getX() > 404 && _asProjector->getX() < 504) + sendMessage(_asProjector , 0x4839, 0); + } else if (sender == _ssButton) + sendMessage(_asBackDoor, 0x4808, 0); + break; + case 0x4826: + if (sender == _asProjector) { + if (sendMessage(_asProjector, 0x480C, _klaymen->getX() > _asProjector->getX() ? 1 : 0) != 0) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + setMessageList2(0x004B6658); + } else + setMessageList2(0x004B65F0); + } + break; + case 0x482A: + _sprite1->setVisible(true); + if (_asProjector) + sendMessage(_asProjector, 0x482B, 0); + break; + case 0x482B: + _sprite1->setVisible(false); + if (_asProjector) + sendMessage(_asProjector, 0x482A, 0); + break; + } + return 0; +} + +// Scene1402 + +SsScene1402BridgePart::SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority) + : StaticSprite(vm, fileHash, surfacePriority) { + + SetFilterY(&Sprite::defFilterY); + SetUpdateHandler(&StaticSprite::updatePosition); +} + +AsScene1402PuzzleBox::AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status) + : AnimatedSprite(vm, 1100), _parentScene(parentScene) { + + createSurface(900, 347, 230); + + SetFilterY(&Sprite::defFilterY); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1402PuzzleBox::handleMessage); + _x = 279; + _y = 270; + if (status == 2) { + // Puzzle box after the puzzle was solved + startAnimation(0x20060259, 0, -1); + playSound(0, 0x419014AC); + loadSound(1, 0x61901C29); + NextState(&AsScene1402PuzzleBox::stMoveDownSolvedDone); + } else if (status == 1) { + // Puzzle box appears + startAnimation(0x210A0213, 0, -1); + playSound(0, 0x41809C6C); + NextState(&AsScene1402PuzzleBox::stMoveUpDone); + } else { + // Puzzle box is here + startAnimation(0x20060259, -1, -1); + loadSound(1, 0x61901C29); + _newStickFrameIndex = STICK_LAST_FRAME; + } +} + +uint32 AsScene1402PuzzleBox::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2002: + playSound(1); + startAnimation(0x20060259, -1, -1); + _playBackwards = true; + NextState(&AsScene1402PuzzleBox::stMoveDownDone); + break; + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1402PuzzleBox::stMoveUpDone() { + sendMessage(_parentScene, 0x2000, 0); + stopAnimation(); + setVisible(false); +} + +void AsScene1402PuzzleBox::stMoveDownDone() { + sendMessage(_parentScene, 0x2001, 0); + stopAnimation(); + setVisible(false); +} + +void AsScene1402PuzzleBox::stMoveDownSolvedDone() { + sendMessage(_parentScene, 0x2003, 0); + stopAnimation(); +} + +Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _isShaking(false), _asPuzzleBox(NULL), _asProjector(NULL) { + + SetMessageHandler(&Scene1402::handleMessage); + + _vm->_screen->setYOffset(0); + + setBackground(0x231482F0); + setBackgroundY(-10); + setPalette(0x231482F0); + _palette->addPalette(0x91D3A391, 0, 64, 0); + insertScreenMouse(0x482F4239); + + _ssBridgePart1 = insertSprite(0x15402D64, 1100); + _ssBridgePart2 = insertSprite(0x10A02120, 1100); + _ssBridgePart3 = insertSprite(0x60882BE0, 1100); + + if (getGlobalVar(V_MOUSE_PUZZLE_SOLVED)) + setRectList(0x004B0C48); + else + setRectList(0x004B0C98); + + if (which < 0) { + // Restoring game + insertKlaymen(377, 391); + setMessageList(0x004B0B48); + if (!getGlobalVar(V_MOUSE_PUZZLE_SOLVED)) + _asPuzzleBox = insertSprite(this, 0); + } else if (which == 1) { + // Klaymen entering from the left + insertKlaymen(42, 391); + setMessageList(0x004B0B50); + } else if (which == 2) { + // Klaymen returning from the puzzle box + insertKlaymen(377, 391); + setMessageList(0x004B0B60); + _klaymen->setDoDeltaX(1); + if (getGlobalVar(V_MOUSE_PUZZLE_SOLVED)) { + _asPuzzleBox = insertSprite(this, 1); + clearRectList(); + showMouse(false); + startShaking(); + } else + _asPuzzleBox = insertSprite(this, 0); + } else { + // Klaymen entering from the right + insertKlaymen(513, 391); + setMessageList(0x004B0B58); + if (!getGlobalVar(V_MOUSE_PUZZLE_SOLVED)) { + _asPuzzleBox = insertSprite(this, 2); + startShaking(); + } + } + + if (_asPuzzleBox) + _asPuzzleBox->setClipRect(0, 0, 640, _ssBridgePart3->getDrawRect().y2()); + + if (getGlobalVar(V_PROJECTOR_LOCATION) == 1) { + _asProjector = insertSprite(this, _klaymen, (Sprite*)NULL); + addCollisionSprite(_asProjector); + if (getGlobalVar(V_PROJECTOR_SLOT) == 4) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + _klaymen->setX(_asProjector->getX() + 100); + _klaymen->updateBounds(); + setMessageList(0x004B0BD0); + } else if (getGlobalVar(V_PROJECTOR_SLOT) == 0) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + _klaymen->setX(_asProjector->getX() - 100); + _klaymen->updateBounds(); + setMessageList(0x004B0BD0); + } + _asProjector->setClipRect(_ssBridgePart1->getDrawRect().x, 0, _ssBridgePart2->getDrawRect().x, _ssBridgePart3->getDrawRect().y2()); + } + + _klaymen->setClipRect(_ssBridgePart1->getDrawRect().x, 0, _ssBridgePart2->getDrawRect().x2(), _ssBridgePart3->getDrawRect().y2()); + +} + +void Scene1402::upShaking() { + if (_isShaking) { + setBackgroundY(_vm->_rnd->getRandomNumber(10 - 1) - 10); + _vm->_screen->setYOffset(-10 - getBackgroundY()); + } else { + setBackgroundY(-10); + _vm->_screen->setYOffset(0); + SetUpdateHandler(&Scene::update); + } + Scene::update(); + if (_asPuzzleBox) + _asPuzzleBox->setClipRect(0, 0, 640, _ssBridgePart3->getDrawRect().y2()); + _klaymen->setClipRect(_ssBridgePart1->getDrawRect().x, 0, _ssBridgePart2->getDrawRect().x2(), _ssBridgePart3->getDrawRect().y2()); +} + +uint32 Scene1402::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x00F43389) { + if (getGlobalVar(V_MOUSE_PUZZLE_SOLVED)) + leaveScene(0); + else { + clearRectList(); + _klaymen->setVisible(false); + showMouse(false); + sendMessage(_asPuzzleBox, 0x2002, 0); + startShaking(); + } + } + break; + case 0x1019: + if (param.asInteger()) + leaveScene(0); + else + leaveScene(1); + break; + case 0x2000: + stopShaking(); + showMouse(true); + setRectList(0x004B0C48); + break; + case 0x2001: + stopShaking(); + leaveScene(0); + break; + case 0x2003: + stopShaking(); + break; + case 0x4826: + if (sender == _asProjector) { + if (sendMessage(_asProjector, 0x480C, _klaymen->getX() > _asProjector->getX() ? 1 : 0) != 0) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + setMessageList2(0x004B0BB8); + } else + setMessageList2(0x004B0B68); + } + break; + } + return 0; +} + +void Scene1402::startShaking() { + _isShaking = true; + SetUpdateHandler(&Scene1402::upShaking); +} + +void Scene1402::stopShaking() { + _isShaking = false; +} + +// Scene1407 + +static const int16 kScene1407MouseFloorY[] = { + 106, 150, 191, 230, 267, 308, 350, 395 +}; + +static const struct { + int16 x; + int16 floorIndex; + int16 sectionIndex; + int16 nextHoleIndex; +} kScene1407MouseHoles[] = { + {125, 0, 0, 7}, + {452, 7, 21, 0}, + {337, 4, 11, 4}, + {286, 6, 17, 6}, + {348, 6, 17, 39}, + {536, 6, 18, 42}, + {111, 1, 3, 18}, + {203, 1, 3, 38}, + {270, 1, 3, 9}, + {197, 5, 14, 3}, + {252, 5, 14, 35}, + {297, 5, 14, 7}, + {359, 5, 14, 8}, + {422, 4, 12, 26}, + {467, 4, 12, 2}, + {539, 4, 12, 40}, + {111, 5, 13, 17}, + {211, 0, 1, 20}, + {258, 0, 1, 11}, + {322, 0, 1, 16}, + { 99, 6, 16, 31}, + {142, 6, 16, 27}, + {194, 6, 16, 12}, + {205, 2, 6, 45}, + {264, 2, 6, 10}, + { 98, 4, 10, 2}, + {152, 4, 10, 37}, + {199, 4, 10, 13}, + {258, 4, 10, 16}, + {100, 7, 19, 43}, + {168, 7, 19, 23}, + {123, 3, 8, 14}, + {181, 3, 8, 39}, + {230, 3, 8, 28}, + {292, 3, 8, 22}, + {358, 3, 8, 36}, + {505, 3, 9, 44}, + {400, 2, 7, 34}, + {454, 2, 7, 32}, + {532, 2, 7, 46}, + {484, 5, 15, 25}, + {529, 5, 15, 30}, + {251, 7, 20, 48}, + {303, 7, 20, 21}, + {360, 7, 20, 33}, + {503, 0, 2, 5}, + {459, 1, 4, 19}, + {530, 1, 4, 42}, + {111, 2, 5, 47}, + {442, 6, 18, 1} +}; + +static const struct { + int16 x1, x2; + int16 goodHoleIndex; +} kScene1407MouseSections[] = { + {100, 149, 0}, + {182, 351, 17}, + {430, 524, 45}, + { 89, 293, 7}, + {407, 555, 47}, + { 89, 132, 48}, + {178, 303, 23}, + {367, 551, 38}, + {105, 398, 31}, + {480, 537, 36}, + { 84, 275, 27}, + {318, 359, 2}, + {402, 560, 15}, + { 91, 132, 16}, + {179, 400, 10}, + {461, 552, 41}, + { 86, 218, 21}, + {267, 376, 4}, + {420, 560, 49}, + { 77, 188, 30}, + {237, 394, 44}, + {438, 515, 5} +}; + +AsScene1407Mouse::AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _currSectionIndex(0) { + + createSurface(100, 117, 45); + _x = 108; + _y = 106; + stIdleLookAtGoodHole(); + SetUpdateHandler(&AnimatedSprite::update); +} + +void AsScene1407Mouse::suWalkTo() { + int16 xdelta = _walkDestX - _x; + if (xdelta > _deltaX) + xdelta = _deltaX; + else if (xdelta < -_deltaX) + xdelta = -_deltaX; + _deltaX = 0; + if (_walkDestX == _x) + sendMessage(this, 0x1019, 0); + else { + _x += xdelta; + updateBounds(); + } +} + +void AsScene1407Mouse::upGoThroughHole() { + if (_countdown != 0 && (--_countdown == 0)) { + SetUpdateHandler(&AnimatedSprite::update); + gotoNextState(); + } + AnimatedSprite::update(); +} + +uint32 AsScene1407Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + { + int16 mouseX = param.asPoint().x; + int16 mouseY = param.asPoint().y; + int holeIndex; + for (holeIndex = 0; holeIndex < 50; holeIndex++) { + int16 holeX = kScene1407MouseHoles[holeIndex].x; + int16 holeY = kScene1407MouseFloorY[kScene1407MouseHoles[holeIndex].floorIndex]; + if (mouseX >= holeX - 14 && mouseX <= holeX + 14 && mouseY >= holeY - 36 && mouseY <= holeY) + break; + } + if (holeIndex < 50 && kScene1407MouseHoles[holeIndex].sectionIndex == _currSectionIndex) { + _nextHoleIndex = kScene1407MouseHoles[holeIndex].nextHoleIndex; + _walkDestX = kScene1407MouseHoles[holeIndex].x; + stWalkToHole(); + } else { + if (mouseX < kScene1407MouseSections[_currSectionIndex].x1) + _walkDestX = kScene1407MouseSections[_currSectionIndex].x1; + else if (mouseX > kScene1407MouseSections[_currSectionIndex].x2) + _walkDestX = kScene1407MouseSections[_currSectionIndex].x2; + else + _walkDestX = mouseX; + stWalkToDest(); + } + } + break; + case 0x1019: + gotoNextState(); + break; + case 0x2001: + { + // Reset the position + // Find the nearest hole and go through it, and exit at the first hole + int16 distance = 640; + int matchIndex = 50; + for (int index = 0; index < 50; index++) + if (kScene1407MouseHoles[index].sectionIndex == _currSectionIndex && + ABS(kScene1407MouseHoles[index].x - _x) < distance) { + matchIndex = index; + distance = ABS(kScene1407MouseHoles[index].x - _x); + } + if (matchIndex < 50) { + _nextHoleIndex = 0; + _walkDestX = kScene1407MouseHoles[matchIndex].x; + stWalkToHole(); + } + } + break; + } + return messageResult; +} + +void AsScene1407Mouse::stIdleLookAtGoodHole() { + setDoDeltaX(kScene1407MouseHoles[kScene1407MouseSections[_currSectionIndex].goodHoleIndex].x < _x ? 1 : 0); + startAnimation(0x72215194, 0, -1); + SetMessageHandler(&AsScene1407Mouse::handleMessage); + SetSpriteUpdate(NULL); +} + +void AsScene1407Mouse::stWalkToDest() { + if (_walkDestX != _x) { + setDoDeltaX(_walkDestX < _x ? 1 : 0); + startAnimation(0x22291510, 0, -1); + SetMessageHandler(&AsScene1407Mouse::handleMessage); + SetSpriteUpdate(&AsScene1407Mouse::suWalkTo); + NextState(&AsScene1407Mouse::stIdleLookAtGoodHole); + } +} + +void AsScene1407Mouse::stWalkToHole() { + setDoDeltaX(_walkDestX < _x ? 1 : 0); + startAnimation(0x22291510, 0, -1); + SetMessageHandler(&AsScene1407Mouse::handleMessage); + SetSpriteUpdate(&AsScene1407Mouse::suWalkTo); + NextState(&AsScene1407Mouse::stGoThroughHole); +} + +void AsScene1407Mouse::stGoThroughHole() { + startAnimation(0x72215194, 0, -1); + setVisible(false); + _countdown = 12; + SetUpdateHandler(&AsScene1407Mouse::upGoThroughHole); + SetMessageHandler(NULL); + SetSpriteUpdate(NULL); + NextState(&AsScene1407Mouse::stArriveAtHole); +} + +void AsScene1407Mouse::stArriveAtHole() { + _currSectionIndex = kScene1407MouseHoles[_nextHoleIndex].sectionIndex; + _x = kScene1407MouseHoles[_nextHoleIndex].x; + _y = kScene1407MouseFloorY[kScene1407MouseHoles[_nextHoleIndex].floorIndex]; + if (_nextHoleIndex == 1) { + sendMessage(_parentScene, 0x2000, 0); + _walkDestX = 512; + stWalkToDest(); + setVisible(true); + } else { + _walkDestX = _x + 14; + stWalkToDest(); + setVisible(true); + } +} + +Scene1407::Scene1407(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule), _puzzleSolvedCountdown(0), _resetButtonCountdown(0) { + + SetMessageHandler(&Scene1407::handleMessage); + SetUpdateHandler(&Scene1407::update); + + setBackground(0x00442225); + setPalette(0x00442225); + insertPuzzleMouse(0x4222100C, 20, 620); + + _asMouse = insertSprite(this); + _ssResetButton = insertStaticSprite(0x12006600, 100); + _ssResetButton->setVisible(false); + +} + +void Scene1407::update() { + Scene::update(); + if (_puzzleSolvedCountdown != 0 && (--_puzzleSolvedCountdown == 0)) + leaveScene(1); + else if (_resetButtonCountdown != 0 && (--_resetButtonCountdown == 0)) + _ssResetButton->setVisible(false); +} + +uint32 Scene1407::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (_puzzleSolvedCountdown == 0) { + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { + // Exit scene + leaveScene(0); + } else if (param.asPoint().x >= 75 && param.asPoint().x <= 104 && + param.asPoint().y >= 62 && param.asPoint().y <= 90) { + // The reset button was clicked + sendMessage(_asMouse, 0x2001, 0); + _ssResetButton->setVisible(true); + playSound(0, 0x44045000); + _resetButtonCountdown = 12; + } else { + // Handle the mouse + sendMessage(_asMouse, messageNum, param); + } + } + break; + case 0x2000: + // The mouse got the cheese (nomnom) + setGlobalVar(V_MOUSE_PUZZLE_SOLVED, 1); + playSound(0, 0x68E25540); + showMouse(false); + _puzzleSolvedCountdown = 72; + break; + } + return 0; +} + +// Scene1403 + +Scene1403::Scene1403(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _asProjector(NULL), _isProjecting(false) { + + SetMessageHandler(&Scene1403::handleMessage); + + setRectList(0x004B1FF8); + setBackground(0x2110A234); + setPalette(0x2110A234); + insertScreenMouse(0x0A230219); + + _sprite1 = insertStaticSprite(0x01102A33, 100); + _sprite1->setVisible(false); + _sprite2 = insertStaticSprite(0x04442520, 995); + _sprite3 = insertStaticSprite(0x08742271, 995); + _asTape1 = insertSprite(this, 12, 1100, 201, 468, 0x9148A011); + addCollisionSprite(_asTape1); + _asTape1->setRepl(64, 0); + _asTape2 = insertSprite(this, 16, 1100, 498, 468, 0x9048A093); + addCollisionSprite(_asTape2); + _asTape2->setRepl(64, 0); + + if (which < 0) { + // Restoring game + insertKlaymen(380, 463); + setMessageList(0x004B1F18); + } else { + // Klaymen entering from the right + insertKlaymen(640, 463); + setMessageList(0x004B1F20); + } + _klaymen->setRepl(64, 0); + + if (getGlobalVar(V_PROJECTOR_LOCATION) == 0) { + _asProjector = insertSprite(this, _klaymen, (Sprite*)NULL); + addCollisionSprite(_asProjector); + if (getGlobalVar(V_PROJECTOR_SLOT) == 4) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + _klaymen->setX(_asProjector->getX() + 100); + _klaymen->updateBounds(); + setMessageList(0x004B1F70); + } + _asProjector->setClipRect(0, 0, 640, _sprite2->getDrawRect().y2()); + _asProjector->setRepl(64, 0); + } + +} + +uint32 Scene1403::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x88C11390) { + setRectList(0x004B2008); + _isProjecting = true; + } else if (param.asInteger() == 0x08821382) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + setRectList(0x004B1FF8); + _isProjecting = false; + } + break; + case 0x1019: + leaveScene(0); + break; + case 0x1022: + if (sender == _asProjector) { + if (param.asInteger() >= 1000) + setSurfacePriority(_sprite3->getSurface(), 1100); + else + setSurfacePriority(_sprite3->getSurface(), 995); + } + break; + case 0x4807: + _sprite1->setVisible(false); + break; + case 0x480F: + _sprite1->setVisible(true); + break; + case 0x4826: + if (sender == _asProjector) { + if (_isProjecting) + setMessageList2(0x004B1FA8); + else if (param.asInteger() == 1) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + setMessageList2(0x004B1F88); + } else if (sendMessage(_asProjector, 0x480C, _klaymen->getX() > _asProjector->getX() ? 1 : 0) != 0) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + setMessageList2(0x004B1F58); + } else + setMessageList2(0x004B1F28); + } else if (sender == _asTape1 || sender == _asTape2) { + if (_isProjecting) + setMessageList2(0x004B1FA8); + else if (_messageListStatus != 2) { + sendEntityMessage(_klaymen, 0x1014, sender); + setMessageList2(0x004B1FB8); + } + } + break; + } + return 0; +} + +// Scene1404 + +Scene1404::Scene1404(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _asProjector(NULL), _asKey(NULL) { + + if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) + setGlobalVar(V_KEY3_LOCATION, 5); + + SetMessageHandler(&Scene1404::handleMessage); + + setRectList(0x004B8D80); + setBackground(0xAC0B006F); + setPalette(0xAC0B006F); + _palette->addPalette(0x00801510, 0, 65, 0); + insertScreenMouse(0xB006BAC8); + + if (getGlobalVar(V_KEY3_LOCATION) == 5) { + _asKey = insertSprite(this, 2, 1100, 267, 411); + addCollisionSprite(_asKey); + } + + _sprite1 = insertStaticSprite(0x1900A1F8, 1100); + _asTape = insertSprite(this, 14, 1100, 281, 411, 0x9148A011); + addCollisionSprite(_asTape); + + if (which < 0) { + // Restoring game + insertKlaymen(376, 406); + setMessageList(0x004B8C28); + } else if (which == 1) { + // Klaymen returning from the tiles puzzle + insertKlaymen(376, 406); + setMessageList(0x004B8C30); + } else if (which == 2) { + // Klaymen returning from the diskplayer + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { + insertKlaymen(347, 406); + _klaymen->setDoDeltaX(1); + } else { + insertKlaymen(187, 406); + } + setMessageList(0x004B8D28); + } else { + // Klaymen entering from the left + insertKlaymen(30, 406); + setMessageList(0x004B8C38); + } + + if (getGlobalVar(V_PROJECTOR_LOCATION) == 3) { + _asProjector = insertSprite(this, _klaymen, (Sprite*)NULL); + addCollisionSprite(_asProjector); + if (getGlobalVar(V_PROJECTOR_SLOT) == 0) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + _klaymen->setX(_asProjector->getX() - 100); + _klaymen->updateBounds(); + setMessageList(0x004B8CB8); + } + _asProjector->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); + } + + _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); + +} + +Scene1404::~Scene1404() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); +} + +uint32 Scene1404::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x410650C2) { + if (_asProjector && _asProjector->getX() == 220) + setMessageList(0x004B8C40); + else + setMessageList(0x004B8CE8); + } + break; + case 0x1019: + leaveScene(0); + break; + case 0x4826: + if (sender == _asProjector) { + if (sendMessage(_asProjector, 0x480C, _klaymen->getX() > _asProjector->getX() ? 1 : 0) != 0) { + sendEntityMessage(_klaymen, 0x1014, _asProjector); + setMessageList2(0x004B8CA0); + } else + setMessageList2(0x004B8C40); + } else if (sender == _asTape && _messageListStatus != 2) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004B8CD0); + } else if (sender == _asKey && _messageListStatus != 2) { + sendEntityMessage(_klaymen, 0x1014, _asKey); + setMessageList(0x004B8D18); + } + break; + } + return 0; +} + +// Scene1405 + +static const NPoint kAsScene1405TileItemPositions[] = { + {100, 80}, {162, 78}, {222, 76}, {292, 76}, + {356, 82}, {422, 84}, {488, 86}, {550, 90}, + {102, 134}, {164, 132}, {224, 136}, {294, 136}, + {360, 136}, {422, 138}, {484, 144}, {548, 146}, + { 98, 196}, {160, 200}, {228, 200}, {294, 202}, + {360, 198}, {424, 200}, {482, 202}, {548, 206}, + { 98, 260}, {160, 264}, {226, 260}, {296, 262}, + {358, 260}, {424, 262}, {486, 264}, {550, 266}, + { 94, 322}, {160, 316}, {226, 316}, {296, 320}, + {358, 322}, {422, 324}, {488, 322}, {550, 322}, + { 98, 380}, {160, 376}, {226, 376}, {294, 378}, + {356, 380}, {420, 380}, {490, 378}, {552, 376} +}; + +AsScene1405Tile::AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _tileIndex(tileIndex), _countdown(0), _isShowing(false) { + + loadSound(0, 0x05308101); + setSoundPan(0, (tileIndex % 8 * 4 + 4) * 25 / 8); + _x = kAsScene1405TileItemPositions[_tileIndex].x; + _y = kAsScene1405TileItemPositions[_tileIndex].y; + createSurface1(0x844B805C, 1100); + setVisible(false); + if (getSubVar(VA_IS_TILE_MATCH, _tileIndex)) + _countdown = _vm->_rnd->getRandomNumber(36 - 1) + 1; + startAnimation(0x844B805C, getSubVar(VA_TILE_SYMBOLS, _tileIndex), -1); + _newStickFrameIndex = (int16)getSubVar(VA_TILE_SYMBOLS, _tileIndex); + SetUpdateHandler(&AsScene1405Tile::update); + SetMessageHandler(&AsScene1405Tile::handleMessage); +} + +void AsScene1405Tile::update() { + updateAnim(); + updatePosition(); + if (_countdown != 0 && (--_countdown == 0)) + show(); +} + +uint32 AsScene1405Tile::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (getSubVar(VA_IS_TILE_MATCH, _tileIndex) == 0 && _parentScene->getCountdown() == 0) { + show(); + sendMessage(_parentScene, 0x2000, _tileIndex); + } + messageResult = 1; + break; + } + return messageResult; +} + +void AsScene1405Tile::show() { + if (!_isShowing) { + _isShowing = true; + playSound(0); + setVisible(true); + } +} + +void AsScene1405Tile::hide() { + if (_isShowing) { + _isShowing = false; + playSound(0); + setVisible(false); + } +} + +Scene1405::Scene1405(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule), _selectFirstTile(true), _tilesLeft(48), _countdown(0) { + + _vm->gameModule()->initMemoryPuzzle(); + + SetUpdateHandler(&Scene1405::update); + SetMessageHandler(&Scene1405::handleMessage); + + setBackground(0x0C0C007D); + setPalette(0x0C0C007D); + insertPuzzleMouse(0xC00790C8, 20, 620); + + for (uint32 tileIndex = 0; tileIndex < 48; tileIndex++) { + _tiles[tileIndex] = insertSprite(this, tileIndex); + addCollisionSprite(_tiles[tileIndex]); + if (getSubVar(VA_IS_TILE_MATCH, tileIndex)) + _tilesLeft--; + } + + loadSound(0, 0x68E25540); +} + +void Scene1405::update() { + Scene::update(); + if (_countdown != 0 && (--_countdown == 0)) { + _tilesLeft = 48; + _tiles[_firstTileIndex]->hide(); + _tiles[_secondTileIndex]->hide(); + for (uint32 i = 0; i < 48; i++) { + if (getSubVar(VA_IS_TILE_MATCH, i)) { + _tiles[i]->hide(); + setSubVar(VA_IS_TILE_MATCH, i, 0); + } + } + } +} + +uint32 Scene1405::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) + leaveScene(0); + break; + case 0x2000: + if (_selectFirstTile) { + _firstTileIndex = param.asInteger(); + _selectFirstTile = false; + } else { + _secondTileIndex = param.asInteger(); + if (_firstTileIndex != _secondTileIndex) { + _selectFirstTile = true; + if (getSubVar(VA_TILE_SYMBOLS, _secondTileIndex) == getSubVar(VA_TILE_SYMBOLS, _firstTileIndex)) { + setSubVar(VA_IS_TILE_MATCH, _firstTileIndex, 1); + setSubVar(VA_IS_TILE_MATCH, _secondTileIndex, 1); + _tilesLeft -= 2; + if (_tilesLeft == 0) + playSound(0); + } else + _countdown = 10; + } + } + break; + } + return 0; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1400.h b/engines/neverhood/modules/module1400.h new file mode 100644 index 0000000000..9a592c2952 --- /dev/null +++ b/engines/neverhood/modules/module1400.h @@ -0,0 +1,281 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE1400_H +#define NEVERHOOD_MODULES_MODULE1400_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/modules/module1200.h" + +namespace Neverhood { + +class Module1400 : public Module { +public: + Module1400(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1400(); +protected: + int _sceneNum; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +// Scene1401 + +class AsScene1401Pipe : public AnimatedSprite { +public: + AsScene1401Pipe(NeverhoodEngine *vm); + virtual ~AsScene1401Pipe(); +protected: + int _countdown1; + int _countdown2; + void update(); + void upSuckInProjector(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmSuckInProjector(int messageNum, const MessageParam ¶m, Entity *sender); + void stStartSucking(); + void stDoneSucking(); + void stSuckInProjector(); +}; + +class AsScene1401Mouse : public AnimatedSprite { +public: + AsScene1401Mouse(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suSuckedIn(); + void stSuckedIn(); +}; + +class AsScene1401Cheese : public AnimatedSprite { +public: + AsScene1401Cheese(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suSuckedIn(); + void stSuckedIn(); +}; + +class AsScene1401BackDoor : public AnimatedSprite { +public: + AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen); +protected: + Sprite *_klaymen; + int _countdown; + bool _isOpen; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stOpenDoor(); + void stCloseDoor(); + void stCloseDoorDone(); +}; + +struct AsCommonProjectorItem { + NPoint point; + int8 maxSlotCount; + int8 lockSlotIndex; + int8 index1; + int8 leftBorderLeaves; + int8 rightBorderLeaves; +}; + +class AsCommonProjector : public AnimatedSprite { +public: + AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe); + virtual ~AsCommonProjector(); +protected: + Scene *_parentScene; + Sprite *_klaymen; + Sprite *_asPipe; + const AsCommonProjectorItem *_asProjectorItem; + int16 _beforeMoveX; + bool _lockedInSlot; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmLockedInSlot(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender); + void suMoving(); + void moveProjector(); + void stSuckedIn(); + void stIdle(); + void stMoving(); + void stStartLockedInSlot(); + void stStayLockedInSlot(); + void stStartProjecting(); + void stLockedInSlot(); + void stStopProjecting(); + void stTurnToFront(); + void stStartSuckedIn(); +}; + +class Scene1401 : public Scene { +public: + Scene1401(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + bool _projectorBorderFlag; + Sprite *_ssFloorButton; + AsCommonProjector *_asProjector; + Sprite *_asPipe; + Sprite *_asMouse; + Sprite *_asCheese; + Sprite *_asBackDoor; + Sprite *_sprite1; + Sprite *_sprite2; + Sprite *_sprite3; + Sprite *_ssButton; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +// Scene1402 + +class SsScene1402BridgePart : public StaticSprite { +public: + SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority); +}; + +class AsScene1402PuzzleBox : public AnimatedSprite { +public: + AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stMoveUpDone(); + void stMoveDownDone(); + void stMoveDownSolvedDone(); +}; + +class Scene1402 : public Scene { +public: + Scene1402(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_ssBridgePart1; + Sprite *_ssBridgePart2; + Sprite *_ssBridgePart3; + Sprite *_asPuzzleBox; + AsCommonProjector *_asProjector; + bool _isShaking; + void upShaking(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void startShaking(); + void stopShaking(); +}; + +// Scene1407 + +class AsScene1407Mouse : public AnimatedSprite { +public: + AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + int16 _walkDestX; + int16 _currSectionIndex; + int16 _nextHoleIndex; + int _countdown; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suWalkTo(); + void upGoThroughHole(); + void stIdleLookAtGoodHole(); + void stWalkToDest(); + void stWalkToHole(); + void stGoThroughHole(); + void stArriveAtHole(); +}; + +class Scene1407 : public Scene { +public: + Scene1407(NeverhoodEngine *vm, Module *parentModule); +protected: + Sprite *_asMouse; + Sprite *_ssResetButton; + int _puzzleSolvedCountdown; + int _resetButtonCountdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +// Scene1403 + +class Scene1403 : public Scene { +public: + Scene1403(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_sprite1; + Sprite *_sprite2; + Sprite *_sprite3; + AsScene1201Tape *_asTape1; + AsScene1201Tape *_asTape2; + AsCommonProjector *_asProjector; + bool _isProjecting; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +// Scene1404 + +class Scene1404 : public Scene { +public: + Scene1404(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene1404(); +protected: + Sprite *_sprite1; + Sprite *_asTape; + AsCommonProjector *_asProjector; + Sprite *_asKey; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +// Scene1405 + +class Scene1405; + +class AsScene1405Tile : public AnimatedSprite { +public: + AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex); + void show(); + void hide(); +protected: + Scene1405 *_parentScene; + bool _isShowing; + uint32 _tileIndex; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1405 : public Scene { +public: + Scene1405(NeverhoodEngine *vm, Module *parentModule); + int getCountdown() const { return _countdown; } +protected: + bool _selectFirstTile; + int _firstTileIndex; + int _secondTileIndex; + int _tilesLeft; + int _countdown; + AsScene1405Tile *_tiles[48]; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1400_H */ diff --git a/engines/neverhood/modules/module1500.cpp b/engines/neverhood/modules/module1500.cpp new file mode 100644 index 0000000000..2a9597b1fd --- /dev/null +++ b/engines/neverhood/modules/module1500.cpp @@ -0,0 +1,134 @@ +/* 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/modules/module1500.h" + +namespace Neverhood { + +Module1500::Module1500(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else + createScene(3, -1); + +} + +void Module1500::createScene(int sceneNum, int which) { + debug("Module1500::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _childObject = new Scene1501(_vm, this, 0x8420221D, 0xA61024C4, 150, 48); + break; + case 1: + _vm->gameState().sceneNum = 1; + _childObject = new Scene1501(_vm, this, 0x30050A0A, 0x58B45E58, 110, 48); + break; + case 2: + _vm->gameState().sceneNum = 2; + sendMessage(_parentModule, 0x0800, 0); + createSmackerScene(0x001A0005, true, true, true); + break; + case 3: + _vm->gameState().sceneNum = 3; + _childObject = new Scene1501(_vm, this, 0x0CA04202, 0, 110, 48); + break; + } + SetUpdateHandler(&Module1500::updateScene); + _childObject->handleUpdate(); +} + +void Module1500::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + createScene(1, -1); + break; + case 1: + createScene(2, -1); + break; + case 3: + createScene(0, -1); + break; + default: + leaveModule(0); + break; + } + } +} + +// Scene1501 + +Scene1501::Scene1501(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 soundFileHash, int countdown2, int countdown3) + : Scene(vm, parentModule), _countdown3(countdown3), _countdown2(countdown2), _countdown1(0), _skip(false) { + + SetUpdateHandler(&Scene1501::update); + SetMessageHandler(&Scene1501::handleMessage); + + setBackground(backgroundFileHash); + setPalette(); + addEntity(_palette); + _palette->addBasePalette(backgroundFileHash, 0, 256, 0); + _palette->startFadeToPalette(12); + + if (soundFileHash != 0) + playSound(0, soundFileHash); + +} + +void Scene1501::update() { + Scene::update(); + if (_countdown1 != 0) { + _countdown1--; + if (_countdown1 == 0) { + _vm->_screen->clear(); + leaveScene(0); + } + } else if ((_countdown2 != 0 && (--_countdown2 == 0)) || (_countdown2 == 0 && !isSoundPlaying(0))) { + _countdown1 = 12; + _palette->startFadeToBlack(11); + } + + if (_countdown3 != 0) + _countdown3--; + + if (_countdown3 == 0 && _skip && _countdown1 == 0) { + _countdown1 = 12; + _palette->startFadeToBlack(11); + } + +} + +uint32 Scene1501::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0009: + _skip = true; + break; + } + return messageResult; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1500.h b/engines/neverhood/modules/module1500.h new file mode 100644 index 0000000000..f244948918 --- /dev/null +++ b/engines/neverhood/modules/module1500.h @@ -0,0 +1,58 @@ +/* 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. + * + */ + +// TODO: I couldn't come up with a better name than 'Module' so far + +#ifndef NEVERHOOD_MODULES_MODULE1500_H +#define NEVERHOOD_MODULES_MODULE1500_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/smackerscene.h" + +namespace Neverhood { + +class Module1500 : public Module { +public: + Module1500(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + int _sceneNum; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +class Scene1501 : public Scene { +public: + Scene1501(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 soundFileHash, int countdown2, int countdown3); +protected: + int _countdown1; + int _countdown2; + int _countdown3; + bool _skip; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1500_H */ diff --git a/engines/neverhood/modules/module1600.cpp b/engines/neverhood/modules/module1600.cpp new file mode 100644 index 0000000000..f7e3c37d84 --- /dev/null +++ b/engines/neverhood/modules/module1600.cpp @@ -0,0 +1,1412 @@ +/* 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/modules/module1600.h" +#include "neverhood/gamemodule.h" +#include "neverhood/modules/module1200.h" +#include "neverhood/modules/module2200.h" + +namespace Neverhood { + +static const uint32 kModule1600SoundList[] = { + 0x90805C50, 0x90804450, 0xB4005E60, + 0x91835066, 0x90E14440, 0 +}; + +Module1600::Module1600(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else if (which == 1) + createScene(4, 1); + else if (which == 2) + createScene(5, 0); + else if (which == 3) + createScene(6, 1); + else if (which == 4) + createScene(1, 0); + else + createScene(0, 0); + + _vm->_soundMan->addSoundList(0x1A008D8, kModule1600SoundList); + _vm->_soundMan->setSoundListParams(kModule1600SoundList, true, 50, 600, 5, 150); + _vm->_soundMan->playTwoSounds(0x1A008D8, 0x41861371, 0x43A2507F, 0); + +} + +Module1600::~Module1600() { + _vm->_soundMan->deleteGroup(0x1A008D8); +} + +void Module1600::createScene(int sceneNum, int which) { + debug("Module1600::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + createNavigationScene(0x004B39D0, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + createNavigationScene(0x004B3A30, which); + break; + case 2: + _vm->gameState().sceneNum = 2; + createNavigationScene(0x004B3A60, which); + break; + case 3: + _vm->gameState().sceneNum = 3; + createNavigationScene(0x004B3A90, which); + break; + case 4: + _vm->gameState().sceneNum = 4; + createNavigationScene(0x004B3B20, which); + break; + case 5: + _vm->gameState().sceneNum = 5; + createNavigationScene(0x004B3B50, which); + break; + case 6: + _vm->gameState().sceneNum = 6; + createNavigationScene(0x004B3B80, which); + break; + case 7: + _vm->gameState().sceneNum = 7; + _childObject = new Scene1608(_vm, this, which); + break; + case 8: + _vm->gameState().sceneNum = 8; + _childObject = new Scene1609(_vm, this); + break; + case 1001: + _vm->gameState().sceneNum = 1; + if (getGlobalVar(V_TALK_COUNTING_INDEX) == 1) + createSmackerScene(0x80050200, true, true, false); + else if (getGlobalVar(V_TALK_COUNTING_INDEX) == 2) + createSmackerScene(0x80090200, true, true, false); + else + createSmackerScene(0x80000200, true, true, false); + if (getGlobalVar(V_TALK_COUNTING_INDEX) >= 2) + setGlobalVar(V_TALK_COUNTING_INDEX, 0); + else + incGlobalVar(V_TALK_COUNTING_INDEX, +1); + break; + } + SetUpdateHandler(&Module1600::updateScene); + _childObject->handleUpdate(); +} + +void Module1600::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 0) + createScene(2, 0); + else if (_moduleResult == 1) + createScene(1, 0); + else if (_moduleResult == 2) + leaveModule(4); + break; + case 1: + if (_moduleResult == 0) + createScene(1001, -1); + else if (_moduleResult == 1) + createScene(0, 3); + break; + case 2: + if (_moduleResult == 0) + createScene(3, 0); + else if (_moduleResult == 1) + createScene(0, 2); + break; + case 3: + if (_moduleResult == 0) + createScene(5, 0); + else if (_moduleResult == 2) + createScene(6, 0); + else if (_moduleResult == 3) + createScene(2, 1); + else if (_moduleResult == 4) + createScene(4, 0); + break; + case 4: + if (_moduleResult == 0) + leaveModule(1); + else if (_moduleResult == 1) + createScene(3, 1); + break; + case 5: + if (_moduleResult == 0) + leaveModule(2); + else if (_moduleResult == 1) + createScene(3, 3); + break; + case 6: + if (_moduleResult == 0) + createScene(8, -1); + else if (_moduleResult == 1) + createScene(3, 5); + break; + case 7: + createScene(6, 1); + break; + case 8: + if (_moduleResult == 0) + createScene(6, 0); + else + createScene(7, 0); + break; + case 1001: + createScene(1, 0); + break; + } + } +} + +AsCommonCar::AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) + : AnimatedSprite(vm, 1000), _parentScene(parentScene) { + + createSurface(200, 556, 328); + _x = x; + _y = y; + + _inMainArea = false; + _exitDirection = 0; + _currPointIndex = 0; + _hasAgainDestPoint = false; + _stepError = 0; + _hasAgainDestPointIndex = false; + _steps = 0; + _isBraking = false; + _yMoveTotalSteps = 0; + _isBusy = false; + _isIdle = false; + _isMoving = true; + _rectFlag = false; + _newDeltaXType = -1; + _soundCounter = 0; + _pathPoints = NULL; + _currMoveDirection = 0; + + startAnimation(0xD4220027, 0, -1); + setDoDeltaX(getGlobalVar(V_CAR_DELTA_X)); + + SetUpdateHandler(&AsCommonCar::update); + SetMessageHandler(&AsCommonCar::handleMessage); + SetSpriteUpdate(NULL); +} + +AsCommonCar::~AsCommonCar() { + if (_finalizeStateCb == AnimationCallback(&AsCommonCar::evTurnCarDone)) + setGlobalVar(V_CAR_DELTA_X, !getGlobalVar(V_CAR_DELTA_X)); +} + +void AsCommonCar::setPathPoints(NPointArray *pathPoints) { + _pathPoints = pathPoints; +} + +void AsCommonCar::update() { + if (_newDeltaXType >= 0) { + setDoDeltaX(_newDeltaXType); + _newDeltaXType = -1; + } + AnimatedSprite::update(); + if (_hasAgainDestPoint && _yMoveTotalSteps == 0 && !_isBusy) { + _hasAgainDestPoint = false; + _hasAgainDestPointIndex = false; + sendPointMessage(this, 0x2004, _againDestPoint); + } else if (_hasAgainDestPointIndex && _yMoveTotalSteps == 0 && !_isBusy) { + _hasAgainDestPointIndex = false; + sendMessage(this, 0x2003, _againDestPointIndex); + } + updateMovement(); + updateSound(); +} + +void AsCommonCar::upIdle() { + update(); + if (++_idleCounter >= _idleCounterMax) + stIdleBlink(); + updateSound(); +} + +uint32 AsCommonCar::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1019: + SetSpriteUpdate(NULL); + break; + case 0x2002: + // Set the current position without moving + _currPointIndex = param.asInteger(); + _stepError = 0; + _x = pathPoint(_currPointIndex).x; + _y = pathPoint(_currPointIndex).y; + break; + case 0x2003: + // Move to a point by its index + { + int newPointIndex = param.asInteger(); + if (_yMoveTotalSteps <= 0 && !_isBusy) { + _destX = pathPoint(newPointIndex).x; + _destY = pathPoint(newPointIndex).y; + if (_currPointIndex < newPointIndex) { + moveToNextPoint(); + } else if (_currPointIndex == newPointIndex && _stepError == 0) { + if (_currPointIndex == 0) { + _yMoveTotalSteps = 0; + sendMessage(_parentScene, 0x2005, 0); + } else if (_currPointIndex == (int)_pathPoints->size()) { + _yMoveTotalSteps = 0; + sendMessage(_parentScene, 0x2006, 0); + } + } else { + moveToPrevPoint(); + } + } else { + _hasAgainDestPointIndex = true; + _againDestPointIndex = newPointIndex; + } + } + break; + case 0x2004: + // Move to the point closest to the parameter point + { + int minMatchIndex = -1; + int minMatchDistance, distance; + NPoint pt = param.asPoint(); + if (_yMoveTotalSteps <= 0 && !_isBusy) { + // Check if we're already exiting (or something) + if ((pt.x <= 20 && _exitDirection == 1) || + (pt.x >= 620 && _exitDirection == 3) || + (pt.y <= 20 && _exitDirection == 2) || + (pt.y >= 460 && _exitDirection == 4)) + break; + _destX = pt.x; + _destY = pt.y; + minMatchDistance = calcDistance(_destX, _destY, _x, _y) + 1; + for (int i = _currPointIndex + 1; i < (int)_pathPoints->size(); i++) { + distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y); + if (distance >= minMatchDistance) + break; + minMatchDistance = distance; + minMatchIndex = i; + } + for (int i = _currPointIndex; i >= 0; i--) { + distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y); + if (distance >= minMatchDistance) + break; + minMatchDistance = distance; + minMatchIndex = i; + } + if (minMatchIndex == -1) { + if (_currPointIndex == 0) + moveToPrevPoint(); + else + SetSpriteUpdate(NULL); + } else { + if (minMatchIndex > _currPointIndex) + moveToNextPoint(); + else + moveToPrevPoint(); + } + } else { + _hasAgainDestPoint = true; + _againDestPoint = pt; + } + } + break; + case 0x2007: + _yMoveTotalSteps = param.asInteger(); + _steps = 0; + _isBraking = false; + _lastDistance = 640; + SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint); + break; + case 0x2008: + _yMoveTotalSteps = param.asInteger(); + _steps = 0; + _isBraking = false; + _lastDistance = 640; + SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint); + break; + case 0x2009: + stEnterCar(); + break; + case 0x200A: + stLeaveCar(); + break; + case 0x200E: + stTurnCar(); + break; + case 0x200F: + stCarAtHome(); + _newDeltaXType = param.asInteger(); + break; + } + return messageResult; +} + +uint32 AsCommonCar::hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = AsCommonCar::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (_isBusy && param.asInteger() == 0x025424A2) + gotoNextState(); + break; + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +uint32 AsCommonCar::hmLeaveCar(int messageNum, const MessageParam ¶m, Entity *sender) { + switch (messageNum) { + case 0x2009: + stEnterCar(); + break; + case 0x3002: + sendMessage(_parentScene, 0x200A, 0); + SetMessageHandler(&AsCommonCar::handleMessage); + break; + } + return 0; +} + +void AsCommonCar::stCarAtHome() { + bool doDeltaX = _doDeltaX; + SetSpriteUpdate(NULL); + _hasAgainDestPoint = false; + _hasAgainDestPointIndex = false; + _isBraking = false; + _isBusy = false; + _isIdle = false; + _isMoving = false; + _rectFlag = false; + NextState(&AsCommonCar::stLeanForwardIdle); + startAnimation(0x35698F78, 0, -1); + setDoDeltaX(doDeltaX ? 1 : 0); + _currMoveDirection = 0; + _newMoveDirection = 0; + _steps = 0; + _idleCounter = 0; + _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24; + SetUpdateHandler(&AsCommonCar::upIdle); + SetMessageHandler(&AsCommonCar::handleMessage); + FinalizeState(&AsCommonCar::evIdleDone); +} + +void AsCommonCar::updateTurnMovement() { + if (_turnMoveStatus == 1) { + _lastDistance = 640; + _isIdle = false; + _isBraking = false; + SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint); + } else if (_turnMoveStatus == 2) { + _lastDistance = 640; + _isIdle = false; + _isBraking = false; + SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint); + } +} + +void AsCommonCar::updateMovement() { + if (_isBraking && !_isIdle && !_isBusy) { + gotoNextState(); + _isMoving = false; + _isIdle = true; + startAnimation(0x192ADD30, 0, -1); + SetUpdateHandler(&AsCommonCar::update); + SetMessageHandler(&AsCommonCar::hmAnimation); + NextState(&AsCommonCar::stLeanForwardIdle); + } else if (!_isBraking && _steps && _isIdle) { + gotoNextState(); + _isIdle = false; + startAnimation(0x9966B138, 0, -1); + SetUpdateHandler(&AsCommonCar::update); + SetMessageHandler(&AsCommonCar::hmAnimation); + NextState(&AsCommonCar::stUpdateMoveDirection); + } else if (_newMoveDirection != _currMoveDirection && _isMoving && !_isBusy) { + gotoNextState(); + _currMoveDirection = _newMoveDirection; + stUpdateMoveDirection(); + } +} + +void AsCommonCar::stEnterCar() { + startAnimation(0xA86A9538, 0, -1); + SetUpdateHandler(&AsCommonCar::update); + SetMessageHandler(&AsCommonCar::hmAnimation); + NextState(&AsCommonCar::stLeanForwardIdle); +} + +void AsCommonCar::stLeaveCar() { + startAnimation(0xA86A9538, -1, -1); + _playBackwards = true; + SetUpdateHandler(&AsCommonCar::update); + SetMessageHandler(&AsCommonCar::hmLeaveCar); +} + +void AsCommonCar::stLeanForwardIdle() { + startAnimation(0x35698F78, 0, -1); + _currMoveDirection = 0; + _newMoveDirection = 0; + _steps = 0; + _idleCounter = 0; + _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24; + SetUpdateHandler(&AsCommonCar::upIdle); + SetMessageHandler(&AsCommonCar::handleMessage); + FinalizeState(&AsCommonCar::evIdleDone); +} + +void AsCommonCar::evIdleDone() { + SetUpdateHandler(&AsCommonCar::update); +} + +void AsCommonCar::stIdleBlink() { + startAnimation(0xB579A77C, 0, -1); + _idleCounter = 0; + _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24; + SetUpdateHandler(&AsCommonCar::update); + SetMessageHandler(&AsCommonCar::hmAnimation); + NextState(&AsCommonCar::stLeanForwardIdle); +} + +void AsCommonCar::stUpdateMoveDirection() { + _isMoving = true; + if (_currMoveDirection == 1) + startAnimation(0xD4AA03A4, 0, -1); + else if (_currMoveDirection == 3) + startAnimation(0xD00A1364, 0, -1); + else if ((_currMoveDirection == 2 && _doDeltaX) || (_currMoveDirection == 4 && !_doDeltaX)) + stTurnCar(); + else + startAnimation(0xD4220027, 0, -1); + setGlobalVar(V_CAR_DELTA_X, _doDeltaX ? 1 : 0); +} + +void AsCommonCar::moveToNextPoint() { + if (_currPointIndex >= (int)_pathPoints->size() - 1) { + _yMoveTotalSteps = 0; + sendMessage(this, 0x1019, 0); + sendMessage(_parentScene, 0x2006, 0); + } else { + NPoint nextPt = pathPoint(_currPointIndex + 1); + NPoint currPt = pathPoint(_currPointIndex); + if (ABS(nextPt.y - currPt.y) <= ABS(nextPt.x - currPt.x) && + ((_currMoveDirection == 2 && nextPt.x < currPt.x) || + (_currMoveDirection == 4 && nextPt.x >= currPt.x))) { + if (_currMoveDirection == 2) + _currMoveDirection = 4; + else if (_currMoveDirection == 4) + _currMoveDirection = 2; + if (_isIdle) + stTurnCarMoveToNextPoint(); + else + stBrakeMoveToNextPoint(); + } else { + if (_steps == 0) { + gotoNextState(); + _isIdle = false; + startAnimation(0x9966B138, 0, -1); + SetMessageHandler(&AsCommonCar::hmAnimation); + SetUpdateHandler(&AsCommonCar::update); + NextState(&AsCommonCar::stUpdateMoveDirection); + } + _isBraking = false; + SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint); + _lastDistance = 640; + } + } +} + +void AsCommonCar::stBrakeMoveToNextPoint() { + gotoNextState(); + _isBusy = true; + _isBraking = true; + startAnimation(0x192ADD30, 0, -1); + SetUpdateHandler(&AsCommonCar::update); + SetMessageHandler(&AsCommonCar::hmAnimation); + NextState(&AsCommonCar::stTurnCarMoveToNextPoint); +} + +void AsCommonCar::stTurnCar() { + // Turn to left/right #1 + gotoNextState(); + _isBusy = true; + startAnimation(0xF46A0324, 0, -1); + SetUpdateHandler(&AsCommonCar::update); + SetMessageHandler(&AsCommonCar::hmAnimation); + FinalizeState(&AsCommonCar::evTurnCarDone); + _turnMoveStatus = 0; + updateTurnMovement(); +} + +void AsCommonCar::stTurnCarMoveToNextPoint() { + // Turn to left/right #2 + gotoNextState(); + _isBusy = true; + startAnimation(0xF46A0324, 0, -1); + SetUpdateHandler(&AsCommonCar::update); + SetMessageHandler(&AsCommonCar::hmAnimation); + FinalizeState(&AsCommonCar::evTurnCarDone); + _turnMoveStatus = 1; + updateTurnMovement(); +} + +void AsCommonCar::stTurnCarMoveToPrevPoint() { + // Turn to left/right #3 + FinalizeState(NULL); + _isBusy = true; + startAnimation(0xF46A0324, 0, -1); + SetUpdateHandler(&AsCommonCar::update); + SetMessageHandler(&AsCommonCar::hmAnimation); + FinalizeState(&AsCommonCar::evTurnCarDone); + _turnMoveStatus = 2; + updateTurnMovement(); +} + +void AsCommonCar::moveToPrevPoint() { + if (_currPointIndex == 0 && _stepError == 0) { + _yMoveTotalSteps = 0; + sendMessage(this, 0x1019, 0); + sendMessage(_parentScene, 0x2005, 0); + } else { + NPoint prevPt; + NPoint currPt; + if (_stepError == 0) { + prevPt = pathPoint(_currPointIndex - 1); + currPt = pathPoint(_currPointIndex); + } else { + prevPt = pathPoint(_currPointIndex); + currPt = pathPoint(_currPointIndex + 1); + } + if (ABS(prevPt.y - currPt.y) <= ABS(prevPt.x - currPt.x) && + ((_currMoveDirection == 2 && prevPt.x < currPt.x) || + (_currMoveDirection == 4 && prevPt.x >= currPt.x))) { + if (_currMoveDirection == 2) + _currMoveDirection = 4; + else if (_currMoveDirection == 4) + _currMoveDirection = 2; + if (_isIdle) + stTurnCarMoveToPrevPoint(); + else + stBrakeMoveToPrevPoint(); + } else { + if (_steps == 0) { + gotoNextState(); + _isIdle = false; + startAnimation(0x9966B138, 0, -1); + SetMessageHandler(&AsCommonCar::hmAnimation); + SetUpdateHandler(&AsCommonCar::update); + NextState(&AsCommonCar::stUpdateMoveDirection); + } + _isBraking = false; + SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint); + _lastDistance = 640; + } + } +} + +void AsCommonCar::stBrakeMoveToPrevPoint() { + FinalizeState(NULL); + _isBusy = true; + _isBraking = true; + startAnimation(0x192ADD30, 0, -1); + SetUpdateHandler(&AsCommonCar::update); + SetMessageHandler(&AsCommonCar::hmAnimation); + NextState(&AsCommonCar::stTurnCarMoveToPrevPoint); +} + +void AsCommonCar::evTurnCarDone() { + _isBusy = false; + setDoDeltaX(2); + _newMoveDirection = 0; + stUpdateMoveDirection(); +} + +void AsCommonCar::suMoveToNextPoint() { + int16 newX = _x, newY = _y; + + if (_currPointIndex >= (int)_pathPoints->size()) { + _yMoveTotalSteps = 0; + sendMessage(this, 0x1019, 0); + sendMessage(_parentScene, 0x2006, 0); + return; + } + + if (_isBraking) { + if (_steps <= 0) { + sendMessage(this, 0x1019, 0); + return; + } else + _steps--; + } else if (_steps < 11) + _steps++; + + bool firstTime = true; + _ySteps = _steps; + int stepsCtr = _steps; + + while (stepsCtr > 0) { + NPoint pt1; + NPoint pt2 = pathPoint(_currPointIndex); + if (_currPointIndex + 1 >= (int)_pathPoints->size()) + pt1 = pathPoint(0); + else + pt1 = pathPoint(_currPointIndex + 1); + int16 deltaX = ABS(pt1.x - pt2.x); + int16 deltaY = ABS(pt1.y - pt2.y); + if (deltaX >= deltaY) { + _newMoveDirection = 2; + if (pt1.x < pt2.x) + _newMoveDirection = 4; + if (stepsCtr + _stepError >= deltaX) { + stepsCtr -= deltaX; + stepsCtr += _stepError; + _stepError = 0; + _currPointIndex++; + if (_currPointIndex == (int)_pathPoints->size() - 1) + stepsCtr = 0; + newX = pathPoint(_currPointIndex).x; + newY = pathPoint(_currPointIndex).y; + } else { + _stepError += stepsCtr; + if (pt1.x >= pt2.x) + newX += stepsCtr; + else + newX -= stepsCtr; + if (pt1.y >= pt2.y) + newY = pt2.y + (deltaY * _stepError) / deltaX; + else + newY = pt2.y - (deltaY * _stepError) / deltaX; + stepsCtr = 0; + } + } else { + _newMoveDirection = 3; + if (pt1.y < pt2.y) + _newMoveDirection = 1; + if (firstTime) { + if (pt1.y >= pt2.y) + stepsCtr += 7; + else { + stepsCtr -= 4; + if (stepsCtr < 0) + stepsCtr = 0; + } + _ySteps = stepsCtr; + } + if (stepsCtr + _stepError >= deltaY) { + stepsCtr -= deltaY; + stepsCtr += _stepError; + _stepError = 0; + _currPointIndex++; + if (_currPointIndex == (int)_pathPoints->size() - 1) + stepsCtr = 0; + newX = pathPoint(_currPointIndex).x; + newY = pathPoint(_currPointIndex).y; + } else { + _stepError += stepsCtr; + if (pt1.x >= pt2.x) + newX = pt2.x + (deltaX * _stepError) / deltaY; + else + newX = pt2.x - (deltaX * _stepError) / deltaY; + if (pt1.y >= pt2.y) + newY += stepsCtr; + else + newY -= stepsCtr; + stepsCtr = 0; + } + } + firstTime = false; + } + + if (_yMoveTotalSteps != 0) { + _x = newX; + _y = newY; + _yMoveTotalSteps -= _ySteps; + if (_yMoveTotalSteps <= 0) { + _isBraking = true; + _yMoveTotalSteps = 0; + } + } else { + int distance = calcDistance(_destX, _destY, _x, _y); + _x = newX; + _y = newY; + if (newX > 20 && newX < 620 && newY > 20 && newY < 460) { + _exitDirection = 0; + _inMainArea = true; + } else if (_inMainArea) { + _destX = pathPoint(_pathPoints->size() - 1).x; + _destY = pathPoint(_pathPoints->size() - 1).y; + _inMainArea = false; + if (_x <= 20) + _exitDirection = 1; + else if (_x >= 620) + _exitDirection = 3; + else if (_y <= 20) + _exitDirection = 2; + else if (_y >= 460) + _exitDirection = 4; + if (_exitDirection != 0 && _isBraking) { + _isBraking = false; + _steps = 11; + } + } + if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) || + (_exitDirection == 0 && _lastDistance + 20 < distance)) + _isBraking = true; + if (distance < _lastDistance) + _lastDistance = distance; + if (_currPointIndex == (int)_pathPoints->size() - 1) { + _isBraking = true; + _yMoveTotalSteps = 0; + sendMessage(this, 0x1019, 0); + sendMessage(_parentScene, 0x2006, 0); + } + } + +} + +void AsCommonCar::suMoveToPrevPoint() { + int16 newX = _x, newY = _y; + + if (_currPointIndex == 0 && _stepError == 0) { + _yMoveTotalSteps = 0; + sendMessage(this, 0x1019, 0); + sendMessage(_parentScene, 0x2005, 0); + return; + } + + if (_isBraking) { + if (_steps <= 0) { + sendMessage(this, 0x1019, 0); + return; + } else + _steps--; + } else if (_steps < 11) + _steps++; + + bool firstTime = true; + _ySteps = _steps; + int stepsCtr = _steps; + + while (stepsCtr > 0) { + if (_stepError == 0) + _currPointIndex--; + NPoint pt1; + NPoint pt2 = pathPoint(_currPointIndex); + if (_currPointIndex + 1 >= (int)_pathPoints->size()) + pt1 = pathPoint(0); + else + pt1 = pathPoint(_currPointIndex + 1); + int16 deltaX = ABS(pt1.x - pt2.x); + int16 deltaY = ABS(pt1.y - pt2.y); + if (deltaX >= deltaY) { + _newMoveDirection = 4; + if (pt1.x < pt2.x) + _newMoveDirection = 2; + if (_stepError == 0) + _stepError = deltaX; + if (stepsCtr > _stepError) { + stepsCtr -= _stepError; + _stepError = 0; + if (_currPointIndex == 0) + stepsCtr = 0; + newX = pathPoint(_currPointIndex).x; + newY = pathPoint(_currPointIndex).y; + } else { + _stepError -= stepsCtr; + if (pt1.x >= pt2.x) + newX -= stepsCtr; + else + newX += stepsCtr; + if (pt1.y >= pt2.y) + newY = pt2.y + (deltaY * _stepError) / deltaX; + else + newY = pt2.y - (deltaY * _stepError) / deltaX; + stepsCtr = 0; + } + } else { + _newMoveDirection = 1; + if (pt1.y < pt2.y) + _newMoveDirection = 3; + if (firstTime) { + if (pt1.y >= pt2.y) { + stepsCtr -= 4; + if (stepsCtr < 0) + stepsCtr = 0; + } else { + stepsCtr += 7; + } + _ySteps = stepsCtr; + } + if (_stepError == 0) + _stepError = deltaY; + if (stepsCtr > _stepError) { + stepsCtr -= _stepError; + _stepError = 0; + if (_currPointIndex == 0) + stepsCtr = 0; + newX = pathPoint(_currPointIndex).x; + newY = pathPoint(_currPointIndex).y; + } else { + _stepError -= stepsCtr; + if (pt1.x >= pt2.x) + newX = pt2.x + (deltaX * _stepError) / deltaY; + else + newX = pt2.x - (deltaX * _stepError) / deltaY; + if (pt1.y >= pt2.y) + newY -= stepsCtr; + else + newY += stepsCtr; + stepsCtr = 0; + } + } + firstTime = false; + } + + if (_yMoveTotalSteps != 0) { + _x = newX; + _y = newY; + _yMoveTotalSteps -= _ySteps; + if (_yMoveTotalSteps <= 0) { + _isBraking = true; + _yMoveTotalSteps = 0; + } + } else { + int distance = calcDistance(_destX, _destY, _x, _y); + _x = newX; + _y = newY; + if (newX > 20 && newX < 620 && newY > 20 && newY < 460) { + _exitDirection = 0; + _inMainArea = true; + } else if (_inMainArea) { + _destX = pathPoint(0).x; + _destY = pathPoint(0).y; + _inMainArea = false; + if (_x <= 20) + _exitDirection = 1; + else if (_x >= 620) + _exitDirection = 3; + else if (_y <= 20) + _exitDirection = 2; + else if (_y >= 460) + _exitDirection = 4; + if (_exitDirection != 0 && _isBraking) { + _isBraking = false; + _steps = 11; + } + } + if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) || + (_exitDirection == 0 && _lastDistance + 20 < distance)) + _isBraking = true; + if (distance < _lastDistance) + _lastDistance = distance; + if (_currPointIndex == 0 && _stepError == 0) { + _isBraking = true; + _yMoveTotalSteps = 0; + sendMessage(this, 0x1019, 0); + sendMessage(_parentScene, 0x2005, 0); + } + } + +} + +void AsCommonCar::updateSound() { + int maxSoundCounter = 0; + _soundCounter++; + if (_steps != 0 && !_isIdle) { + if (_currMoveDirection == 1) + maxSoundCounter = 18 - _steps; + else if (_currMoveDirection == 3) { + maxSoundCounter = 5 - _steps; + if (maxSoundCounter < 1) + maxSoundCounter = 1; + } else + maxSoundCounter = 14 - _steps; + } else + maxSoundCounter = 21; + if (_soundCounter >= maxSoundCounter) { + sendMessage(_parentScene, 0x200D, 0); + _soundCounter = 0; + } +} + +AsCommonIdleCarLower::AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y) + : AnimatedSprite(vm, 0x1209E09F, 1100, x, y) { + + setDoDeltaX(1); + startAnimation(0x1209E09F, 1, -1); + _newStickFrameIndex = 1; +} + +AsCommonIdleCarFull::AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y) + : AnimatedSprite(vm, 0x1209E09F, 100, x, y) { + + setDoDeltaX(1); + _newStickFrameIndex = 0; +} + +AsCommonCarConnector::AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar) + : AnimatedSprite(vm, 1100), _asCar(asCar) { + + createSurface1(0x60281C10, 150); + startAnimation(0x60281C10, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + SetUpdateHandler(&AsCommonCarConnector::update); +} + +void AsCommonCarConnector::update() { + _x = _asCar->getX(); + _y = _asCar->getY(); + AnimatedSprite::update(); +} + +void Tracks::findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance, + DataResource &dataResource) { + const uint trackCount = size(); + minMatchTrackIndex = -1; + minMatchDistance = 640; + for (uint trackIndex = 0; trackIndex < trackCount; trackIndex++) { + NPointArray *pointList = dataResource.getPointArray((*this)[trackIndex]->trackPointsName); + for (uint pointIndex = 0; pointIndex < pointList->size(); pointIndex++) { + NPoint testPt = (*pointList)[pointIndex]; + int distance = calcDistance(testPt.x, testPt.y, pt.x, pt.y); + if (distance < minMatchDistance) { + minMatchTrackIndex = trackIndex; + minMatchDistance = distance; + } + } + } +} + +Scene1608::Scene1608(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _asCar(NULL), _countdown1(0) { + + setGlobalVar(V_CAR_DELTA_X, 1); + + SetMessageHandler(&Scene1608::hmLowerFloor); + + _asKey = insertSprite(this, 1, 1100, 198, 220); + addCollisionSprite(_asKey); + + if (which < 0) { + // Restoring game + if (_vm->gameState().which == 1) + // Klaymen is in the car + which = 1; + else { + // Klaymen is standing around + setRectList(0x004B47D0); + insertKlaymen(380, 438); + _kmScene1608 = _klaymen; + _klaymenInCar = false; + _sprite1 = insertStaticSprite(0x7D0404E8, 1100); + setMessageList(0x004B46A8); + setBackground(0x10080E01); + setPalette(0x10080E01); + _asTape = insertSprite(this, 13, 1100, 412, 443, 0x9148A011); + addCollisionSprite(_asTape); + _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); + SetUpdateHandler(&Scene1608::upLowerFloor); + insertScreenMouse(0x80E05108); + insertStaticSprite(0x4B18F868, 1200); + } + } else if (which == 0) { + // Klaymen entering from the left + _vm->gameState().which = 0; + setRectList(0x004B47D0); + insertKlaymen(0, 438); + _kmScene1608 = _klaymen; + _klaymenInCar = false; + setMessageList(0x004B46B0); + setBackground(0x10080E01); + setPalette(0x10080E01); + _asTape = insertSprite(this, 13, 1100, 412, 443, 0x9148A011); + addCollisionSprite(_asTape); + insertScreenMouse(0x80E05108); + _sprite1 = insertStaticSprite(0x7D0404E8, 1100); + _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480); + SetUpdateHandler(&Scene1608::upLowerFloor); + insertStaticSprite(0x4B18F868, 1200); + } else if (which == 2) { + // Klaymen returning from looking through the upper window + _vm->gameState().which = 1; + _dataResource.load(0x003C0492); + _roomPathPoints = _dataResource.getPointArray(calcHash("meArchroArchRoomPath")); + setBackground(0x98001604); + setPalette(0x98001604); + _palette->addPalette("paPodRed", 65, 31, 65); + insertScreenMouse(0x01600988); + _sprite2 = insertStaticSprite(0x491F38A8, 1100); + _asCar = createSprite(this, 375, 227); // Create but don't add to the sprite list yet + _asIdleCarLower = insertSprite(375, 227); + _asIdleCarFull = insertSprite(375, 227); + _asCar->setVisible(false); + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { + insertKlaymen(373, 220); + _klaymen->setDoDeltaX(1); + } else + insertKlaymen(283, 220); + _kmScene1608 = _klaymen; + setMessageList(0x004B47A8); + SetMessageHandler(&Scene1608::hmUpperFloor); + SetUpdateHandler(&Scene1608::upUpperFloor); + _asCar->setPathPoints(_roomPathPoints); + sendMessage(_asCar, 0x2002, _roomPathPoints->size() - 1); + _sprite3 = insertStaticSprite(0xB47026B0, 1100); + _clipRect1.set(_sprite3->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2()); + _clipRect3.set(_sprite2->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2()); + _clipRect2 = _clipRect1; + _clipRect2.y2 = 215; + _klaymen->setClipRect(_clipRect1); + _asCar->setClipRect(_clipRect1); + _asIdleCarLower->setClipRect(_clipRect1); + _asIdleCarFull->setClipRect(_clipRect1); + _asTape = insertSprite(this, 13, 1100, 412, 443, 0x9148A011); + addCollisionSprite(_asTape); + insertSprite(_asCar)->setClipRect(_clipRect1); + _klaymenInCar = false; + _carClipFlag = false; + _carStatus = 0; + setRectList(0x004B4810); + } + + // NOTE: Not in the else because 'which' is set to 1 in the true branch + if (which == 1) { + // Klaymen riding the car + _vm->gameState().which = 1; + _dataResource.load(0x003C0492); + _roomPathPoints = _dataResource.getPointArray(calcHash("meArchroArchRoomPath")); + setBackground(0x98001604); + setPalette(0x98001604); + _palette->addPalette("paPodRed", 65, 31, 65); + insertScreenMouse(0x01600988); + _asCar = insertSprite(this, 375, 227); + _asIdleCarLower = insertSprite(375, 227); + _asIdleCarFull = insertSprite(375, 227); + _sprite2 = insertStaticSprite(0x491F38A8, 1100); + _kmScene1608 = createSprite(this, 439, 220); + sendMessage(_kmScene1608, 0x2032, 1); + _kmScene1608->setDoDeltaX(1); + SetMessageHandler(&Scene1608::hmRidingCar); + SetUpdateHandler(&Scene1608::upRidingCar); + _asIdleCarLower->setVisible(false); + _asIdleCarFull->setVisible(false); + _asCar->setPathPoints(_roomPathPoints); + sendMessage(_asCar, 0x2002, 0); + sendMessage(_asCar, 0x2008, 90); + _sprite3 = insertStaticSprite(0xB47026B0, 1100); + _clipRect1.set(_sprite3->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2()); + _clipRect3.set(_sprite2->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2()); + _clipRect2 = _clipRect1; + _clipRect2.y2 = 215; + _kmScene1608->setClipRect(_clipRect1); + _asCar->setClipRect(_clipRect1); + _asIdleCarLower->setClipRect(_clipRect1); + _asIdleCarFull->setClipRect(_clipRect1); + _asTape = insertSprite(this, 13, 1100, 412, 443, 0x9148A011); + // ... addCollisionSprite(_asTape); + insertSprite(_asCar)->setClipRect(_clipRect1); + _klaymenInCar = true; + _carClipFlag = true; + _carStatus = 0; + } + + _palette->addPalette("paKlayRed", 0, 64, 0); + +} + +Scene1608::~Scene1608() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _kmScene1608->isDoDeltaX() ? 1 : 0); + if (_klaymenInCar) + delete _kmScene1608; + else + delete _asCar; +} + +void Scene1608::upLowerFloor() { + Scene::update(); + if (_countdown1 != 0 && (--_countdown1 == 0)) + leaveScene(0); +} + +void Scene1608::upUpperFloor() { + Scene::update(); + if (_carStatus == 1) { + removeSurface(_klaymen->getSurface()); + removeEntity(_klaymen); + addSprite(_asCar); + _klaymenInCar = true; + clearRectList(); + SetUpdateHandler(&Scene1608::upCarAtHome); + SetMessageHandler(&Scene1608::hmCarAtHome); + _asIdleCarLower->setVisible(false); + _asIdleCarFull->setVisible(false); + _asCar->setVisible(true); + sendMessage(_asCar, 0x2009, 0); + _asCar->handleUpdate(); + _klaymen = NULL; + _carStatus = 0; + } + updateKlaymenCliprect(); +} + +void Scene1608::upCarAtHome() { + Scene::update(); + if (_mouseClicked) { + if (_mouseClickPos.x <= 329 && _asCar->getX() == 375 && _asCar->getY() == 227) { + sendMessage(_asCar, 0x200A, 0); + SetUpdateHandler(&Scene1608::upGettingOutOfCar); + } else { + sendPointMessage(_asCar, 0x2004, _mouseClickPos); + SetMessageHandler(&Scene1608::hmRidingCar); + SetUpdateHandler(&Scene1608::upRidingCar); + } + _mouseClicked = false; + } + updateKlaymenCliprect(); +} + +void Scene1608::upGettingOutOfCar() { + Scene::update(); + if (_carStatus == 2) { + _klaymen = _kmScene1608; + removeSurface(_asCar->getSurface()); + removeEntity(_asCar); + addSprite(_klaymen); + _klaymenInCar = false; + SetMessageHandler(&Scene1608::hmUpperFloor); + SetUpdateHandler(&Scene1608::upUpperFloor); + setRectList(0x004B4810); + _asIdleCarLower->setVisible(true); + _asIdleCarFull->setVisible(true); + _asCar->setVisible(false); + setMessageList(0x004B4748); + processMessageList(); + _klaymen->handleUpdate(); + _carStatus = 0; + } + updateKlaymenCliprect(); +} + +void Scene1608::upRidingCar() { + Scene::update(); + if (_mouseClicked) { + sendPointMessage(_asCar, 0x2004, _mouseClickPos); + _mouseClicked = false; + } + if (_asCar->getX() < 300) { + if (_carClipFlag) { + _carClipFlag = false; + _asCar->setClipRect(_clipRect1); + if (!_asCar->isDoDeltaX()) + sendMessage(_asCar, 0x200E, 0); + } + } else if (!_carClipFlag) { + _carClipFlag = true; + _asCar->setClipRect(_clipRect3); + } +} + +uint32 Scene1608::hmLowerFloor(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x20250B1A) { + clearRectList(); + _klaymen->setVisible(false); + showMouse(false); + _sprite1->setVisible(false); + //sendMessage(_asDoor, 0x4809, 0); // Play sound? + _countdown1 = 28; + } + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + case 0x4826: + if (sender == _asTape) { + sendEntityMessage(_kmScene1608, 0x1014, _asTape); + setMessageList(0x004B4770); + } else if (sender == _asKey) + setMessageList(0x004B46C8); + break; + } + return 0; +} + +uint32 Scene1608::hmUpperFloor(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x60842040) + _carStatus = 1; + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + case 0x4826: + if (sender == _asKey) { + sendEntityMessage(_kmScene1608, 0x1014, _asKey); + setMessageList(0x004B4760); + } + break; + } + return 0; +} + +uint32 Scene1608::hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2005: + leaveScene(1); + break; + case 0x2006: + SetMessageHandler(&Scene1608::hmCarAtHome); + SetUpdateHandler(&Scene1608::upCarAtHome); + sendMessage(_asCar, 0x200F, 1); + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + } + return 0; +} + +uint32 Scene1608::hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x200A: + _carStatus = 2; + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + } + return 0; +} + +void Scene1608::updateKlaymenCliprect() { + if (_kmScene1608->getX() <= 375) + _kmScene1608->setClipRect(_clipRect1); + else + _kmScene1608->setClipRect(_clipRect2); +} + +Scene1609::Scene1609(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule), _countdown1(1), _currentSymbolIndex(0), _symbolPosition(0), _changeCurrentSymbol(true), _isSolved(false) { + + _vm->gameModule()->initCodeSymbolsPuzzle(); + _noisySymbolIndex = getGlobalVar(V_NOISY_SYMBOL_INDEX); + + SetMessageHandler(&Scene1609::handleMessage); + SetUpdateHandler(&Scene1609::update); + + setBackground(0x92124A14); + setPalette(0x92124A14); + insertPuzzleMouse(0x24A10929, 20, 620); + + for (int symbolPosition = 0; symbolPosition < 12; symbolPosition++) + _asSymbols[symbolPosition] = insertSprite(symbolPosition, false); + + _ssButton = insertSprite(this, true); + addCollisionSprite(_ssButton); + loadSound(0, 0x68E25540); + +} + +void Scene1609::update() { + if (!_isSolved && _countdown1 != 0 && (--_countdown1 == 0)) { + if (_changeCurrentSymbol) { + _currentSymbolIndex++; + if (_currentSymbolIndex >= 12) + _currentSymbolIndex = 0; + _asSymbols[_symbolPosition]->change(_currentSymbolIndex + 12, _currentSymbolIndex == (int)getSubVar(VA_CODE_SYMBOLS, _noisySymbolIndex)); + _changeCurrentSymbol = false; + _countdown1 = 36; + } else { + _asSymbols[_symbolPosition]->hide(); + _changeCurrentSymbol = true; + _countdown1 = 12; + } + } + if (_isSolved && !isSoundPlaying(0)) + leaveScene(1); + Scene::update(); +} + +uint32 Scene1609::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) + leaveScene(0); + break; + case 0x2000: + if (!_isSolved) { + if (_changeCurrentSymbol) + _asSymbols[_symbolPosition]->change(_currentSymbolIndex + 12, false); + _asSymbols[_symbolPosition]->stopSymbolSound(); + _symbolPosition++; + if (_symbolPosition >= 12) { + if (testVars()) { + playSound(0); + setGlobalVar(V_CODE_SYMBOLS_SOLVED, 1); + _isSolved = true; + } else { + _symbolPosition = 0; + for (int i = 0; i < 12; i++) + _asSymbols[i]->hide(); + } + } + _changeCurrentSymbol = true; + _countdown1 = 1; + } + break; + } + return 0; +} + +bool Scene1609::testVars() { + int cmpSymbolIndex = 0; + + // Find the position of the first symbol + while ((int)getSubVar(VA_CODE_SYMBOLS, cmpSymbolIndex) != _asSymbols[0]->getSymbolIndex()) + cmpSymbolIndex++; + + // Check if the entered symbols match + for (int enteredSymbolIndex = 0; enteredSymbolIndex < 12; enteredSymbolIndex++) { + if ((int)getSubVar(VA_CODE_SYMBOLS, cmpSymbolIndex) != _asSymbols[enteredSymbolIndex]->getSymbolIndex()) + return false; + cmpSymbolIndex++; + if (cmpSymbolIndex >= 12) + cmpSymbolIndex = 0; + } + + return true; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1600.h b/engines/neverhood/modules/module1600.h new file mode 100644 index 0000000000..0bf44ff7b8 --- /dev/null +++ b/engines/neverhood/modules/module1600.h @@ -0,0 +1,183 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE1600_H +#define NEVERHOOD_MODULES_MODULE1600_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/modules/module3000.h" + +namespace Neverhood { + +// Module1600 + +class Module1600 : public Module { +public: + Module1600(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1600(); +protected: + int _sceneNum; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +class AsCommonCar : public AnimatedSprite { +public: + AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y); + ~AsCommonCar(); + void setPathPoints(NPointArray *pathPoints); +protected: + Scene *_parentScene; + NPointArray *_pathPoints; + int _newMoveDirection; + int _currMoveDirection; + int _exitDirection; + int _currPointIndex; + bool _hasAgainDestPoint; + NPoint _againDestPoint; + bool _hasAgainDestPointIndex; + int _againDestPointIndex; + bool _inMainArea; + bool _isBraking; + bool _isBusy; + bool _isIdle; + bool _isMoving; + bool _rectFlag; + int _idleCounter; + int _idleCounterMax; + int _steps; + int _stepError; + int _lastDistance; + int _yMoveTotalSteps; + int _ySteps; + int _newDeltaXType; + int _soundCounter; + int _turnMoveStatus; + int16 _destX, _destY; + NPoint pathPoint(uint index) { return (*_pathPoints)[index]; } + void update(); + void upIdle(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmLeaveCar(int messageNum, const MessageParam ¶m, Entity *sender); + void stCarAtHome(); + void updateTurnMovement(); + void updateMovement(); + void stEnterCar(); + void stLeaveCar(); + void stLeanForwardIdle(); + void evIdleDone(); + void stIdleBlink(); + void stUpdateMoveDirection(); + void stTurnCar(); + void moveToNextPoint(); + void stBrakeMoveToNextPoint(); + void stTurnCarMoveToNextPoint(); + void moveToPrevPoint(); + void stBrakeMoveToPrevPoint(); + void stTurnCarMoveToPrevPoint(); + void evTurnCarDone(); + void suMoveToNextPoint(); + void suMoveToPrevPoint(); + void updateSound(); +}; + +class AsCommonIdleCarLower : public AnimatedSprite { +public: + AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y); +}; + +class AsCommonIdleCarFull : public AnimatedSprite { +public: + AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y); +}; + +class AsCommonCarConnector : public AnimatedSprite { +public: + AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar); +protected: + AsCommonCar *_asCar; + void update(); +}; + +class Tracks : public Common::Array { +public: + void findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance, + DataResource &dataResource); +}; + +class Scene1608 : public Scene { +public: + Scene1608(NeverhoodEngine *vm, Module *parentModule, int which); + ~Scene1608(); +protected: + AsCommonCar *_asCar; + Sprite *_asKey; + Sprite *_asIdleCarLower; + Sprite *_asIdleCarFull; + Sprite *_sprite1; + Sprite *_sprite2; + Sprite *_sprite3; + Sprite *_asTape; + Klaymen *_kmScene1608; + NRect _clipRect1; + NRect _clipRect2; + NRect _clipRect3; + int _carStatus; + bool _carClipFlag; + bool _klaymenInCar; + int _countdown1; + NPointArray *_roomPathPoints; + void upLowerFloor(); + void upUpperFloor(); + void upCarAtHome(); + void upGettingOutOfCar(); + void upRidingCar(); + uint32 hmLowerFloor(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmUpperFloor(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender); + void updateKlaymenCliprect(); +}; + +class Scene1609 : public Scene { +public: + Scene1609(NeverhoodEngine *vm, Module *parentModule); +protected: + Sprite *_ssButton; + AsScene3011Symbol *_asSymbols[12]; + int _currentSymbolIndex; + int _noisySymbolIndex; + int _symbolPosition; + int _countdown1; + bool _changeCurrentSymbol; + bool _isSolved; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + bool testVars(); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1600_H */ diff --git a/engines/neverhood/modules/module1700.cpp b/engines/neverhood/modules/module1700.cpp new file mode 100644 index 0000000000..3a6d1f80cb --- /dev/null +++ b/engines/neverhood/modules/module1700.cpp @@ -0,0 +1,279 @@ +/* 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/modules/module1700.h" +#include "neverhood/gamemodule.h" + +namespace Neverhood { + +static const uint32 kModule1700SoundList[] = { + 0xB288D450, + 0x90804450, + 0x99801500, + 0xB288D455, + 0x93825040, + 0 +}; + +Module1700::Module1700(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + _vm->_soundMan->addMusic(0x04212331, 0x31114225); + _vm->_soundMan->addSoundList(0x04212331, kModule1700SoundList); + _vm->_soundMan->setSoundListParams(kModule1700SoundList, true, 50, 600, 5, 150); + _vm->_soundMan->playTwoSounds(0x04212331, 0x41861371, 0x43A2507F, 0); + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else if (which == 0) + createScene(0, -1); + else if (which == 1) + createScene(4, 1); + else + createScene(4, 3); + +} + +Module1700::~Module1700() { + _vm->_soundMan->deleteGroup(0x04212331); +} + +void Module1700::createScene(int sceneNum, int which) { + debug("Module1700::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _vm->_soundMan->setSoundListParams(kModule1700SoundList, false, 0, 0, 0, 0); + createSmackerScene(0x3028A005, true, true, false); + break; + case 1: + _vm->gameState().sceneNum = 1; + createNavigationScene(0x004AE8B8, which); + break; + case 2: + _vm->gameState().sceneNum = 2; + createNavigationScene(0x004AE8E8, which); + break; + case 3: + _vm->gameState().sceneNum = 3; + _vm->_soundMan->setSoundListParams(kModule1700SoundList, false, 0, 0, 0, 0); + createSmackerScene(0x01190041, true, true, false); + break; + case 4: + _vm->gameState().sceneNum = 4; + _vm->_soundMan->setSoundListParams(kModule1700SoundList, false, 0, 0, 0, 0); + _vm->_soundMan->startMusic(0x31114225, 0, 2); + _childObject = new Scene1705(_vm, this, which); + break; + } + SetUpdateHandler(&Module1700::updateScene); + _childObject->handleUpdate(); +} + +void Module1700::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + _vm->_soundMan->setSoundListParams(kModule1700SoundList, true, 0, 0, 0, 0); + createScene(1, 0); + break; + case 1: + if (_moduleResult == 0) + createScene(2, 0); + else if (_moduleResult == 1) + createScene(1, 1); + break; + case 2: + if (_moduleResult == 0) + createScene(3, -1); + else if (_moduleResult == 1) + createScene(1, 1); + else if (_moduleResult == 2) { + if (!isSoundPlaying(0)) { + setSoundVolume(0, 60); + playSound(0, 0x58B45E58); + } + createScene(2, 2); + } + break; + case 3: + createScene(4, 0); + break; + case 4: + leaveModule(1); + break; + } + } +} + +// Scene1705 + +static const uint32 kScene1705FileHashes[] = { + 0x910EA801, 0x920EA801, 0x940EA801, + 0x980EA801, 0x800EA801, 0xB00EA801, + 0xD00EA801, 0x100EA801, 0x900EA800, + 0xD10EA801, 0x110EA801, 0x910EA800 +}; + +SsScene1705WallSymbol::SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex) + : StaticSprite(vm, fileHash, 100) { + + _x = _spriteResource.getPosition().x + symbolIndex * 30; + _y = _spriteResource.getPosition().y + 160; + updatePosition(); +} + +SsScene1705Tape::SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash) + : StaticSprite(vm, fileHash, surfacePriority, x - 24, y - 4), _parentScene(parentScene), _tapeIndex(tapeIndex) { + + if (!getSubVar(VA_HAS_TAPE, _tapeIndex) && !getSubVar(VA_IS_TAPE_INSERTED, _tapeIndex)) { + SetMessageHandler(&SsScene1705Tape::handleMessage); + } else { + setVisible(false); + SetMessageHandler(NULL); + } + _collisionBoundsOffset = _drawOffset; + _collisionBoundsOffset.x -= 4; + _collisionBoundsOffset.y -= 8; + _collisionBoundsOffset.width += 8; + _collisionBoundsOffset.height += 16; + Sprite::updateBounds(); +} + +uint32 SsScene1705Tape::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x4806: + setSubVar(VA_HAS_TAPE, _tapeIndex, 1); + setVisible(false); + SetMessageHandler(NULL); + break; + } + return messageResult; +} + +Scene1705::Scene1705(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _paletteArea(1) { + + Sprite *tempSprite; + + setGlobalVar(V_FELL_DOWN_HOLE, 1); + _vm->gameModule()->initCannonSymbolsPuzzle(); + + SetMessageHandler(&Scene1705::handleMessage); + SetUpdateHandler(&Scene1705::update); + + setHitRects(0x004B69D8); + setBackground(0x03118226); + setPalette(0x03118226); + _palette->addBasePalette(0x91D3A391, 0, 64, 0); + _palette->copyBasePalette(0, 256, 0); + addEntity(_palette); + insertScreenMouse(0x18222039); + + insertSprite(kScene1705FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_2, 0)], 0); + insertSprite(kScene1705FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_2, 1)], 1); + insertSprite(kScene1705FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_2, 2)], 2); + _sprite = insertStaticSprite(0x31313A22, 1100); + _ssTape = insertSprite(this, 15, 1100, 238, 439, 0x02363852); + addCollisionSprite(_ssTape); + + if (which < 0) { + // Restoring game + insertKlaymen(231, 434); + setMessageList(0x004B69E8); + sendMessage(this, 0x2000, 0); + _klaymen->setClipRect(0, 0, _sprite->getDrawRect().x2(), 480); + } else if (which == 1) { + // Klaymen teleporting in + insertKlaymen(431, 434); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B6A08, false); + sendMessage(this, 0x2000, 1); + _klaymen->setClipRect(0, 0, _sprite->getDrawRect().x2(), 480); + } else if (which == 2) { + // Klaymen teleporting out + insertKlaymen(431, 434); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B6AA0, false); + sendMessage(this, 0x2000, 1); + _klaymen->setClipRect(0, 0, _sprite->getDrawRect().x2(), 480); + } else if (which == 3) { + // Klaymen returning from teleporter console + insertKlaymen(431, 434); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B6A18, false); + sendMessage(this, 0x2000, 1); + _klaymen->setClipRect(0, 0, _sprite->getDrawRect().x2(), 480); + } else { + // Klaymen falling through the hole + insertKlaymen(231, 74); + sendMessage(_klaymen, 0x2000, 0); + setMessageList(0x004B69F0); + sendMessage(this, 0x2000, 0); + tempSprite = insertStaticSprite(0x30303822, 1100); + _klaymen->setClipRect(0, tempSprite->getDrawRect().y, _sprite->getDrawRect().x2(), 480); + } + +} + +void Scene1705::update() { + Scene::update(); + if (_klaymen->getX() < 224 && _paletteArea != 0) { + _palette->addBasePalette(0xF2210C15, 0, 64, 0); + _palette->startFadeToPalette(12); + _paletteArea = 0; + } else if (_klaymen->getX() >= 224 && _paletteArea == 0) { + _palette->addBasePalette(0x91D3A391, 0, 64, 0); + _palette->startFadeToPalette(12); + _paletteArea = 1; + } +} + +uint32 Scene1705::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + if (param.asInteger()) { + setRectList(0x004B6B40); + _klaymen->setKlaymenIdleTable3(); + } else { + setRectList(0x004B6B30); + _klaymen->setKlaymenIdleTable1(); + } + break; + case 0x4826: + if (sender == _ssTape && _klaymen->getX() <= 318) { + sendEntityMessage(_klaymen, 0x1014, sender); + setMessageList(0x004B6AC0); + } + break; + } + return 0; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1700.h b/engines/neverhood/modules/module1700.h new file mode 100644 index 0000000000..f57c411a18 --- /dev/null +++ b/engines/neverhood/modules/module1700.h @@ -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 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE1700_H +#define NEVERHOOD_MODULES_MODULE1700_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/smackerscene.h" + +namespace Neverhood { + +class Module1700 : public Module { +public: + Module1700(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1700(); +protected: + int _sceneNum; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +// Scene1705 + +class SsScene1705WallSymbol : public StaticSprite { +public: + SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex); +}; + +class SsScene1705Tape : public StaticSprite { +public: + SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash); +protected: + Scene *_parentScene; + uint32 _tapeIndex; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1705 : public Scene { +public: + Scene1705(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_sprite; + Sprite *_ssTape; + int _paletteArea; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1700_H */ diff --git a/engines/neverhood/modules/module1800.cpp b/engines/neverhood/modules/module1800.cpp new file mode 100644 index 0000000000..2a6057f9c8 --- /dev/null +++ b/engines/neverhood/modules/module1800.cpp @@ -0,0 +1,181 @@ +/* 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/modules/module1800.h" +#include "neverhood/navigationscene.h" +#include "neverhood/menumodule.h" + +namespace Neverhood { + +static const uint32 kModule1800SoundList[] = { + 0x16805548, + 0x16805048, + 0xD0E14441, + 0x90E090C2, + 0x90E1D0C2, + 0x90E2D0C2, + 0 +}; + +Module1800::Module1800(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + _vm->_soundMan->addSoundList(0x04A14718, kModule1800SoundList); + _vm->_soundMan->setSoundListParams(kModule1800SoundList, true, 50, 600, 10, 150); + _vm->_soundMan->playTwoSounds(0x04A14718, 0x8A382B55, 0x0C242F1D, 0); + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else if (which == 2) + createScene(5, 0); + else if (which == 3) + createScene(0, 0); + else + createScene(3, 1); + +} + +Module1800::~Module1800() { + _vm->_soundMan->deleteGroup(0x04A14718); +} + +void Module1800::createScene(int sceneNum, int which) { + static const byte kNavigationTypes00[] = {1, 0, 2, 0}; + static const byte kNavigationTypes01[] = {5}; + debug("Module1800::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + createNavigationScene(0x004AFD38, which, kNavigationTypes00); + break; + case 1: + _vm->gameState().sceneNum = 1; + createNavigationScene(0x004AFD98, which, kNavigationTypes01); + break; + case 2: + _vm->gameState().sceneNum = 2; + createSmackerScene(0x006C0085, true, true, false); + break; + case 3: + _vm->gameState().sceneNum = 3; + createNavigationScene(0x004AFDB0, which); + break; + case 4: + _vm->gameState().sceneNum = 4; + createNavigationScene(0x004AFDE0, which); + break; + case 5: + _vm->gameState().sceneNum = 5; + createNavigationScene(0x004AFE40, which); + break; + case 6: + _vm->gameState().sceneNum = 6; + _vm->_soundMan->deleteGroup(0x04A14718); + createSmackerScene(0x08D84010, true, true, false); + break; + case 7: + _vm->gameState().sceneNum = 7; + _vm->_soundMan->setSoundListParams(kModule1800SoundList, false, 0, 0, 0, 0); + createSmackerScene(0x0168B121, true, true, false); + break; + case 8: + _vm->gameState().sceneNum = 8; + _childObject = new CreditsScene(_vm, this, false); + break; + case 1009: + _vm->gameState().sceneNum = 3; + // NOTE: Newly introduced sceneNum 1009 (was duplicate 3 with own update handler) + createSmackerScene(0x0A840C01, true, true, false); + break; + } + SetUpdateHandler(&Module1800::updateScene); + _childObject->handleUpdate(); +} + +void Module1800::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 1) + createScene(4, 0); + else if (_moduleResult == 2) + createScene(1, -1); + else if (_moduleResult == 3) + createScene(3, 0); + break; + case 1: + if (_navigationAreaType == 3) + createScene(7, -1); + else + createScene(2, -1); + break; + case 2: + createScene(0, 2); + break; + case 3: + if (_moduleResult == 0) + createScene(1009, -1); + else if (_moduleResult == 1) + createScene(0, 1); + break; + case 4: + if (_moduleResult == 0) + createScene(6, -1); + else if (_moduleResult == 1) + createScene(5, 0); + else if (_moduleResult == 2) + createScene(0, 3); + else if (_moduleResult == 3) + createScene(4, 3); + break; + case 5: + if (_moduleResult == 0) + leaveModule(2); + else if (_moduleResult == 1) + createScene(4, 3); + break; + case 6: + createScene(8, -1); + break; + case 7: + leaveModule(3); + break; + case 8: + // NOTE: After Klaymen jumped into the hole and died... + leaveModule(1); + break; + case 1009: + leaveModule(0); + break; + } + } else { + switch (_sceneNum) { + case 0: + if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 2) + _vm->_soundMan->setTwoSoundsPlayFlag(false); + break; + } + } +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1800.h b/engines/neverhood/modules/module1800.h new file mode 100644 index 0000000000..d3f3a635c3 --- /dev/null +++ b/engines/neverhood/modules/module1800.h @@ -0,0 +1,46 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE1800_H +#define NEVERHOOD_MODULES_MODULE1800_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +// Module1800 + +class Module1800 : public Module { +public: + Module1800(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1800(); +protected: + int _sceneNum; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1800_H */ diff --git a/engines/neverhood/modules/module1900.cpp b/engines/neverhood/modules/module1900.cpp new file mode 100644 index 0000000000..1a9ffa127b --- /dev/null +++ b/engines/neverhood/modules/module1900.cpp @@ -0,0 +1,650 @@ +/* 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/modules/module1900.h" +#include "neverhood/gamemodule.h" + +namespace Neverhood { + +static const uint32 kModule1900SoundList[] = { + 0xB4005E60, + 0x91835066, + 0x90E14440, + 0 +}; + +Module1900::Module1900(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + // NOTE: The original has a Scene1908 here as well but it's not used here but in another module... + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else + createScene(0, 0); + + _vm->_soundMan->addSoundList(0x04E1C09C, kModule1900SoundList); + _vm->_soundMan->setSoundListParams(kModule1900SoundList, true, 50, 600, 5, 150); + +} + +Module1900::~Module1900() { + _vm->_soundMan->deleteGroup(0x04E1C09C); +} + +void Module1900::createScene(int sceneNum, int which) { + debug("Module1900::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _childObject = new Scene1901(_vm, this, which); + break; + case 6: + _vm->gameState().sceneNum = 6; + _childObject = new Scene1907(_vm, this); + break; + } + SetUpdateHandler(&Module1900::updateScene); + _childObject->handleUpdate(); +} + +void Module1900::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 1) + createScene(6, 0); + else + leaveModule(0); + break; + case 6: + createScene(0, 1); + break; + } + } +} + +// Scene1901 + +Scene1901::Scene1901(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + Sprite *tempSprite; + + setRectList(0x004B34C8); + + setBackground(0x01303227); + setPalette(0x01303227); + insertScreenMouse(0x0322301B); + + insertStaticSprite(0x42213133, 1100); + + if (!getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) + insertStaticSprite(0x40A40168, 100); + else if (getGlobalVar(V_STAIRS_DOWN)) { + insertStaticSprite(0x124404C4, 100); + setGlobalVar(V_STAIRS_DOWN_ONCE, 1); + } else + insertStaticSprite(0x02840064, 100); + + if (which < 0) { + // Restoring game + insertKlaymen(120, 380); + setMessageList(0x004B3408); + } else if (which == 1) { + // Klaymen returning from the puzzle + insertKlaymen(372, 380); + setMessageList(0x004B3410); + } else { + // Klaymen entering from the left + insertKlaymen(0, 380); + setMessageList(0x004B3400); + } + + tempSprite = insertStaticSprite(0x4830A402, 1100); + _klaymen->setClipRect(tempSprite->getDrawRect().x, 0, 640, 480); + +} + +static const NPoint kAsScene1907SymbolGroundPositions[] = { + {160, 310}, { 90, 340}, {210, 335}, + {210, 380}, {310, 340}, {290, 400}, + {400, 375}, {370, 435}, {475, 415} +}; + +static const NPoint kAsScene1907SymbolPluggedInPositions[] = { + {275, 125}, {244, 125}, {238, 131}, + {221, 135}, {199, 136}, {168, 149}, + {145, 152}, {123, 154}, {103, 157} +}; + +static const NPoint kAsScene1907SymbolGroundHitPositions[] = { + {275, 299}, {244, 299}, {238, 305}, + {221, 309}, {199, 310}, {168, 323}, + {145, 326}, {123, 328}, {103, 331} +}; + +static const NPoint kAsScene1907SymbolPluggedInDownPositions[] = { + {275, 136}, {244, 156}, {238, 183}, + {221, 207}, {199, 228}, {168, 262}, + {145, 285}, {123, 307}, {103, 331} +}; + +static const uint32 kAsScene1907SymbolFileHashes[] = { + 0x006A1034, 0x006A1010, 0x006A1814, + 0x006A1016, 0x006A0014, 0x002A1014, + 0x00EA1014, 0x206A1014, 0x046A1414 +}; + +bool AsScene1907Symbol::_plugInFailed = false; +int AsScene1907Symbol::_plugInTryCount = 0; + +AsScene1907Symbol::AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex) + : AnimatedSprite(vm, 1000 - positionIndex), _parentScene(parentScene), _elementIndex(elementIndex), _isMoving(false) { + + _plugInFailed = false; + _plugInTryCount = 0; + + if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) { + _isPluggedIn = true; + _currPositionIndex = elementIndex; + if (!getGlobalVar(V_STAIRS_DOWN)) { + _x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x; + _y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y; + } else { + _x = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].x; + _y = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].y; + } + createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex); + startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + } else { + _isPluggedIn = false; + _currPositionIndex = positionIndex; + loadSound(0, 0x74231924); + loadSound(1, 0x36691914); + loadSound(2, 0x5421D806); + _parentScene->setPositionFree(_currPositionIndex, false); + _x = kAsScene1907SymbolGroundPositions[_currPositionIndex].x; + _y = kAsScene1907SymbolGroundPositions[_currPositionIndex].y; + createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex); + startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1); + _newStickFrameIndex = 0; + } + _collisionBoundsOffset.set(0, 0, 80, 80); + Sprite::updateBounds(); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1907Symbol::handleMessage); + +} + +void AsScene1907Symbol::update() { + updateAnim(); + handleSpriteUpdate(); + updatePosition(); + if (_plugInFailed && _plugInTryCount == 0) + _plugInFailed = false; +} + +uint32 AsScene1907Symbol::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (!_isPluggedIn && !_plugInFailed) { + tryToPlugIn(); + messageResult = 1; + } else + messageResult = 0; + break; + } + return messageResult; +} + +uint32 AsScene1907Symbol::hmTryToPlugIn(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1907Symbol::suTryToPlugIn() { + _currStep++; + _x -= _deltaX; + _y -= _deltaY; + if (_currStep == 16) { + _x -= _smallDeltaX; + _y -= _smallDeltaY; + SetSpriteUpdate(NULL); + } +} + +void AsScene1907Symbol::suFallOff() { + if (_fallOffDelay != 0) { + _fallOffDelay--; + } else { + _y += _yAccel; + _yAccel += 8; + if (_y >= kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) { + _y = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y; + stFallOffHitGround(); + } + } +} + +void AsScene1907Symbol::suFallOffHitGround() { + + if (_x == _someX - _xBreak) + _x -= _smallDeltaX; + else + _x -= _deltaX; + + if (_y == kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) { + _y -= _someY; + } + + if (_currStep < 8) { + _y -= _yAccel; + _yAccel -= 4; + if (_yAccel < 0) + _yAccel = 0; + } else if (_currStep < 15) { + _y += _yAccel; + _yAccel += 4; + } else { + _y = kAsScene1907SymbolGroundPositions[_newPositionIndex].y; + cbFallOffHitGroundEvent(); + } + + _currStep++; +} + +void AsScene1907Symbol::suMoveDown() { + _y += _yIncr; + if (_yIncr < 11) + _yIncr++; + if (_y >= kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y) { + _y = kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y; + _isMoving = false; + SetSpriteUpdate(NULL); + } +} + +void AsScene1907Symbol::suMoveUp() { + _y -= _yIncr; + if (getGlobalVar(V_WALL_BROKEN)) { + if (_y - (9 + (_elementIndex > 5 ? 31 : 0)) < kAsScene1907SymbolPluggedInPositions[_elementIndex].y) + _yIncr--; + else + _yIncr++; + } else + _yIncr = 2; + if (_yIncr > 9) + _yIncr = 9; + else if (_yIncr < 1) + _yIncr = 1; + if (_y < kAsScene1907SymbolPluggedInPositions[_elementIndex].y) { + _y = kAsScene1907SymbolPluggedInPositions[_elementIndex].y; + _isMoving = false; + SetSpriteUpdate(NULL); + } +} + +void AsScene1907Symbol::tryToPlugIn() { + _isPluggedIn = true; + _plugInTryCount++; + _newPositionIndex = _parentScene->getNextPosition(); + _parentScene->setPositionFree(_currPositionIndex, true); + sendMessage(_parentScene, 0x1022, 1100 + _newPositionIndex); + startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1); + SetUpdateHandler(&AsScene1907Symbol::update); + SetMessageHandler(&AsScene1907Symbol::hmTryToPlugIn); + SetSpriteUpdate(&AsScene1907Symbol::suTryToPlugIn); + _currStep = 0; + _deltaX = (_x - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x) / 16; + _smallDeltaX = _x - _deltaX * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x; + _deltaY = (_y - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y) / 16; + _smallDeltaY = _y - _deltaY * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y; + if (_elementIndex == _newPositionIndex) { + NextState(&AsScene1907Symbol::stPlugIn); + } else { + _plugInFailed = true; + NextState(&AsScene1907Symbol::stPlugInFail); + } +} + +void AsScene1907Symbol::fallOff(int newPositionIndex, int fallOffDelay) { + _isPluggedIn = false; + _newPositionIndex = newPositionIndex; + _fallOffDelay = fallOffDelay; + _parentScene->setPositionFree(_newPositionIndex, false); + _x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x; + _y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y; + _someX = _x; + _someY = _y; + startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, 0); + _playBackwards = true; + _newStickFrameIndex = STICK_LAST_FRAME; + _currStep = 0; + _yAccel = 1; + SetUpdateHandler(&AsScene1907Symbol::update); + SetMessageHandler(&AsScene1907Symbol::handleMessage); + SetSpriteUpdate(&AsScene1907Symbol::suFallOff); +} + +void AsScene1907Symbol::stFallOffHitGround() { + playSound(1); + sendMessage(_parentScene, 0x1022, 1000 + _newPositionIndex); + Entity::_priority = 1000 - _newPositionIndex; + _parentScene->removeCollisionSprite(this); + _parentScene->addCollisionSprite(this); + SetSpriteUpdate(&AsScene1907Symbol::suFallOffHitGround); + NextState(&AsScene1907Symbol::cbFallOffHitGroundEvent); + _newStickFrameIndex = 0; + _currStep = 0; + _yAccel = 30; + _deltaX = (_x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x) / 15; + _xBreak = _deltaX * 15; + _smallDeltaX = _x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x - _xBreak; + _someY = 0; + if (kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y > kAsScene1907SymbolGroundPositions[_newPositionIndex].y) + _someY = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y - kAsScene1907SymbolGroundPositions[_newPositionIndex].y; +} + +void AsScene1907Symbol::cbFallOffHitGroundEvent() { + _currPositionIndex = _newPositionIndex; + if (_plugInTryCount > 0) + _plugInTryCount--; + startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1); + _newStickFrameIndex = 0; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1907Symbol::handleMessage); + SetSpriteUpdate(NULL); + updateBounds(); + playSound(2); +} + +void AsScene1907Symbol::stPlugIn() { + playSound(0); + _currPositionIndex = _newPositionIndex; + stopAnimation(); + SetMessageHandler(&AsScene1907Symbol::handleMessage); + SetSpriteUpdate(NULL); + if (_elementIndex == 8) + sendMessage(_parentScene, 0x2001, 0); +} + +void AsScene1907Symbol::stPlugInFail() { + _currPositionIndex = _newPositionIndex; + stopAnimation(); + _parentScene->plugInFailed(); +} + +void AsScene1907Symbol::moveUp() { + startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1); + stopAnimation(); + SetMessageHandler(&AsScene1907Symbol::handleMessage); + SetSpriteUpdate(&AsScene1907Symbol::suMoveUp); + _yIncr = 1; + _isMoving = true; +} + +void AsScene1907Symbol::moveDown() { + startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1); + stopAnimation(); + SetMessageHandler(&AsScene1907Symbol::handleMessage); + SetSpriteUpdate(&AsScene1907Symbol::suMoveDown); + _yIncr = 4; + _isMoving = true; +} + +SsScene1907UpDownButton::SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol) + : StaticSprite(vm, 1400), _parentScene(parentScene), _asScene1907Symbol(asScene1907Symbol), + _countdown1(0) { + + loadSprite(0x64516424, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 1400); + setVisible(false); + loadSound(0, 0x44061000); + SetUpdateHandler(&SsScene1907UpDownButton::update); + SetMessageHandler(&SsScene1907UpDownButton::handleMessage); + if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) { + if (getGlobalVar(V_STAIRS_DOWN)) + setToDownPosition(); + else + setToUpPosition(); + } +} + +void SsScene1907UpDownButton::update() { + updatePosition(); + if (_countdown1 != 0 && (--_countdown1 == 0)) { + setVisible(false); + sendMessage(_parentScene, 0x2000, 0); + } +} + +uint32 SsScene1907UpDownButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown1 == 0 && !_asScene1907Symbol->isMoving() && getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) { + setVisible(true); + _countdown1 = 4; + updatePosition(); + playSound(0); + } + messageResult = 1; + } + return messageResult; +} + +void SsScene1907UpDownButton::setToUpPosition() { + _y = _spriteResource.getPosition().y; + updateBounds(); + updatePosition(); +} + +void SsScene1907UpDownButton::setToDownPosition() { + _y = _spriteResource.getPosition().y + 174; + updateBounds(); + updatePosition(); +} + +AsScene1907WaterHint::AsScene1907WaterHint(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1400) { + + createSurface1(0x110A1061, 1500); + _x = 320; + _y = 240; + startAnimation(0x110A1061, 0, -1); + _newStickFrameIndex = 0; + setVisible(false); + _needRefresh = true; + AnimatedSprite::updatePosition(); + SetUpdateHandler(&AsScene1907WaterHint::update); + SetMessageHandler(&Sprite::handleMessage); +} + +void AsScene1907WaterHint::update() { + updateAnim(); + updatePosition(); +} + +uint32 AsScene1907WaterHint::hmShowing(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1907WaterHint::show() { + setVisible(true); + startAnimation(0x110A1061, 0, -1); + SetMessageHandler(&AsScene1907WaterHint::hmShowing); + NextState(&AsScene1907WaterHint::hide); +} + +void AsScene1907WaterHint::hide() { + stopAnimation(); + setVisible(false); + SetMessageHandler(&Sprite::handleMessage); +} + +Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule), _currMovingSymbolIndex(0), _pluggedInCount(0), + _moveDownCountdown(0), _moveUpCountdown(0), _countdown3(0), _hasPlugInFailed(false) { + + setBackground(0x20628E05); + setPalette(0x20628E05); + + for (int i = 0; i < 9; i++) + _positionFree[i] = true; + + for (int i = 0; i < 9; i++) { + _asSymbols[i] = insertSprite(this, i, getRandomPositionIndex()); + addCollisionSprite(_asSymbols[i]); + } + + _ssUpDownButton = insertSprite(this, _asSymbols[8]); + addCollisionSprite(_ssUpDownButton); + + _asWaterHint = insertSprite(); + + insertPuzzleMouse(0x28E0120E, 20, 620); + + SetMessageHandler(&Scene1907::handleMessage); + SetUpdateHandler(&Scene1907::update); + + if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) + _pluggedInCount = 9; + + loadSound(0, 0x72004A10); + loadSound(1, 0x22082A12); + loadSound(2, 0x21100A10); + loadSound(3, 0x68E25540); + +} + +void Scene1907::update() { + Scene::update(); + + if (_hasPlugInFailed) { + int fallOffDelay = 0; + _hasPlugInFailed = false; + for (int i = 0; i < 9; i++) { + AsScene1907Symbol *asSymbol = _asSymbols[8 - i]; + if (asSymbol->isPluggedIn()) { + asSymbol->fallOff(getRandomPositionIndex(), fallOffDelay); + fallOffDelay += _vm->_rnd->getRandomNumber(10 - 1) + 4; + } + } + } + + if (_moveDownCountdown != 0 && (--_moveDownCountdown == 0)) { + _asSymbols[_currMovingSymbolIndex]->moveDown(); + if (_currMovingSymbolIndex > 0) { + _moveDownCountdown = 2; + _currMovingSymbolIndex--; + } + } + + if (_moveUpCountdown != 0 && (--_moveUpCountdown == 0)) { + _moveDownCountdown = 0; + for (int i = 0; i < 9; i++) + _asSymbols[i]->moveUp(); + } + + if (_countdown3 != 0 && (--_countdown3 == 0)) { + _asWaterHint->show(); + _moveUpCountdown = 4; + } + +} + +uint32 Scene1907::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && + !_hasPlugInFailed && _moveDownCountdown == 0 && _moveUpCountdown == 0 && _countdown3 == 0) { + leaveScene(0); + } + break; + case 0x2000: + if (getGlobalVar(V_STAIRS_DOWN)) { + playSound(0); + for (int i = 0; i < 9; i++) + _asSymbols[i]->moveUp(); + _ssUpDownButton->setToUpPosition(); + setGlobalVar(V_STAIRS_DOWN, 0); + } else { + if (!getGlobalVar(V_WALL_BROKEN)) { + playSound(2); + _countdown3 = 5; + } else { + playSound(1); + _ssUpDownButton->setToDownPosition(); + setGlobalVar(V_STAIRS_DOWN, 1); + } + _moveDownCountdown = 1; + _currMovingSymbolIndex = 8; + } + break; + case 0x2001: + playSound(3); + setGlobalVar(V_STAIRS_PUZZLE_SOLVED, 1); + break; + } + return 0; +} + +void Scene1907::plugInFailed() { + _pluggedInCount = 0; + _hasPlugInFailed = true; +} + +int Scene1907::getRandomPositionIndex() { + bool found = false; + int index = 0; + // Check if any position is free + for (int i = 0; i < 9; i++) + if (_positionFree[i]) + found = true; + if (found) { + // Get a random free position + found = false; + while (!found) { + index = _vm->_rnd->getRandomNumber(9 - 1); + if (_positionFree[index]) + found = true; + } + } + return index; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1900.h b/engines/neverhood/modules/module1900.h new file mode 100644 index 0000000000..abb5eb1d87 --- /dev/null +++ b/engines/neverhood/modules/module1900.h @@ -0,0 +1,143 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE1900_H +#define NEVERHOOD_MODULES_MODULE1900_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/modules/module1200.h" + +namespace Neverhood { + +class Module1900 : public Module { +public: + Module1900(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1900(); +protected: + int _sceneNum; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void createScene(int sceneNum, int which); + void updateScene(); +}; + +// Scene1901 + +class Scene1901 : public Scene { +public: + Scene1901(NeverhoodEngine *vm, Module *parentModule, int which); +}; + +// Scene1907 + +class Scene1907; + +class AsScene1907Symbol : public AnimatedSprite { +public: + AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex); + void moveUp(); + void moveDown(); + void fallOff(int newPositionIndex, int fallOffDelay); + bool isPluggedIn() { return _isPluggedIn; } + bool isMoving() { return _isMoving; } +protected: + Scene1907 *_parentScene; + int _elementIndex; + int _currPositionIndex; + int _newPositionIndex; + bool _isPluggedIn; + bool _isMoving; + int _someX, _someY; + int _xBreak; + int _currStep; + int _yAccel; + int _yIncr; + int _fallOffDelay; + int _deltaX, _smallDeltaX; + int _deltaY, _smallDeltaY; + // Dumb, change if possible + static bool _plugInFailed; + static int _plugInTryCount; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmTryToPlugIn(int messageNum, const MessageParam ¶m, Entity *sender); + void suTryToPlugIn(); + void suFallOff(); + void suFallOffHitGround(); + void suMoveDown(); + void suMoveUp(); + void tryToPlugIn(); + void stFallOffHitGround(); + void cbFallOffHitGroundEvent(); + void stPlugIn(); + void stPlugInFail(); +}; + +class AsScene1907WaterHint : public AnimatedSprite { +public: + AsScene1907WaterHint(NeverhoodEngine *vm); + void show(); +protected: + void update(); + uint32 hmShowing(int messageNum, const MessageParam ¶m, Entity *sender); + void hide(); +}; + +class SsScene1907UpDownButton : public StaticSprite { +public: + SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol); + void setToUpPosition(); + void setToDownPosition(); +protected: + Scene1907 *_parentScene; + AsScene1907Symbol *_asScene1907Symbol; + int _countdown1; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1907 : public Scene { +public: + Scene1907(NeverhoodEngine *vm, Module *parentModule); + void plugInFailed(); + void setPositionFree(int index, bool value) { _positionFree[index] = value; } + int getNextPosition() { return _pluggedInCount++; } +protected: + AsScene1907Symbol *_asSymbols[9]; + SsScene1907UpDownButton *_ssUpDownButton; + AsScene1907WaterHint *_asWaterHint; + int _currMovingSymbolIndex; + int _pluggedInCount; + int _moveDownCountdown; + int _moveUpCountdown; + int _countdown3; + bool _hasPlugInFailed; + bool _positionFree[9]; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + int getRandomPositionIndex(); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1900_H */ diff --git a/engines/neverhood/modules/module2000.cpp b/engines/neverhood/modules/module2000.cpp new file mode 100644 index 0000000000..5039da1b01 --- /dev/null +++ b/engines/neverhood/modules/module2000.cpp @@ -0,0 +1,160 @@ +/* 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/modules/module2000.h" +#include "neverhood/gamemodule.h" +#include "neverhood/navigationscene.h" + +namespace Neverhood { + +Module2000::Module2000(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else if (which == 0) + createScene(0, 1); + else if (which == 1) + createScene(0, 3); + +} + +Module2000::~Module2000() { + _vm->_soundMan->deleteGroup(0x81293110); +} + +void Module2000::createScene(int sceneNum, int which) { + debug("Module2000::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _childObject = new Scene2001(_vm, this, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + createNavigationScene(getGlobalVar(V_WORLDS_JOINED) ? 0x004B7B48 : 0x004B7B00, which); + break; + case 2: + _vm->gameState().sceneNum = 2; + setGlobalVar(V_WORLDS_JOINED, 1); + setSubVar(V_TELEPORTER_DEST_AVAILABLE, 1, 1); + createSmackerScene(0x204B2031, true, true, false); + break; + } + SetUpdateHandler(&Module2000::updateScene); + _childObject->handleUpdate(); +} + +void Module2000::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 1) + leaveModule(0); + else + createScene(1, 0); + break; + case 1: + if (_moduleResult == 0) { + if (getGlobalVar(V_WORLDS_JOINED)) + createScene(1, 0); + else + createScene(2, -1); + } else if (_moduleResult == 1) + createScene(1, 1); + else if (_moduleResult == 2) + createScene(0, 0); + break; + case 2: + createScene(1, 0); + break; + } + } +} + +// Scene2001 + +Scene2001::Scene2001(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + Sprite *tempSprite; + + SetMessageHandler(&Scene2001::handleMessage); + + setBackground(0xA6417244); + setPalette(0xA6417244); + insertScreenMouse(0x17240A6C); + + tempSprite = insertStaticSprite(0x0D641724, 1100); + + if (which < 0) { + // Restoring game + insertKlaymen(300, 345); + setMessageList(0x004B3538); + sendMessage(this, 0x2000, 0); + } else if (which == 1) { + // Klaymen teleporting in + insertKlaymen(116, 345); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B3540, false); + sendMessage(this, 0x2000, 1); + } else if (which == 2) { + // Klaymen teleporting out + insertKlaymen(116, 345); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B35F0, false); + sendMessage(this, 0x2000, 1); + } else if (which == 3) { + // Klaymen returning from teleporter console + insertKlaymen(116, 345); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B3550, false); + sendMessage(this, 0x2000, 1); + } else { + // Klaymen standing around + insertKlaymen(390, 345); + setMessageList(0x004B3530); + sendMessage(this, 0x2000, 0); + _klaymen->setDoDeltaX(1); + } + + _klaymen->setClipRect(tempSprite->getDrawRect().x, 0, 640, 480); + +} + +uint32 Scene2001::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + if (param.asInteger()) { + setRectList(0x004B3680); + _klaymen->setKlaymenIdleTable3(); + } else { + setRectList(0x004B3670); + _klaymen->setKlaymenIdleTable1(); + } + } + return 0; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module2000.h b/engines/neverhood/modules/module2000.h new file mode 100644 index 0000000000..fa62f9a70e --- /dev/null +++ b/engines/neverhood/modules/module2000.h @@ -0,0 +1,55 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE2000_H +#define NEVERHOOD_MODULES_MODULE2000_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/modules/module1200.h" + +namespace Neverhood { + +class Module2000 : public Module { +public: + Module2000(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module2000(); +protected: + int _sceneNum; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void createScene(int sceneNum, int which); + void updateScene(); +}; + +// Scene2001 + +class Scene2001 : public Scene { +public: + Scene2001(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE2000_H */ diff --git a/engines/neverhood/modules/module2100.cpp b/engines/neverhood/modules/module2100.cpp new file mode 100644 index 0000000000..0d7f3dd22a --- /dev/null +++ b/engines/neverhood/modules/module2100.cpp @@ -0,0 +1,336 @@ +/* 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/modules/module2100.h" +#include "neverhood/gamemodule.h" +#include "neverhood/modules/module1200.h" + +namespace Neverhood { + +Module2100::Module2100(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + _vm->_soundMan->addMusic(0x10A10C14, 0x11482B95); + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else if (which == 1) + createScene(0, 0); + else if (which == 2) + createScene(0, 3); + else + createScene(0, 1); + +} + +Module2100::~Module2100() { + _vm->_soundMan->deleteMusicGroup(0x10A10C14); +} + +void Module2100::createScene(int sceneNum, int which) { + debug("Module2100::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _vm->_soundMan->startMusic(0x11482B95, 0, 1); + _childObject = new Scene2101(_vm, this, which); + break; + } + SetUpdateHandler(&Module2100::updateScene); + _childObject->handleUpdate(); +} + +void Module2100::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 1) { + setGlobalVar(V_DOOR_PASSED, 1); + leaveModule(0); + } else + leaveModule(1); + break; + } + } +} + +// Scene2101 + +AsScene2101Door::AsScene2101Door(NeverhoodEngine *vm, bool isOpen) + : AnimatedSprite(vm, 1100) { + + createSurface(100, 328, 347); + _x = 320; + _y = 240; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2101Door::handleMessage); + if (isOpen) { + startAnimation(0x0C202B9C, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + } else + setVisible(false); +} + +uint32 AsScene2101Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + case 0x4808: + stOpenDoor(); + break; + case 0x4809: + stCloseDoor(); + break; + } + return messageResult; +} + +void AsScene2101Door::stOpenDoor() { + startAnimation(0x0C202B9C, 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + setVisible(true); + playSound(0, calcHash("fxDoorOpen32")); +} + +void AsScene2101Door::stCloseDoor() { + startAnimation(0xC222A8D4, 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + setVisible(true); + playSound(0, calcHash("fxDoorClose32")); + NextState(&AsScene2101Door::stCloseDoorDone); +} + +void AsScene2101Door::stCloseDoorDone() { + stopAnimation(); + setVisible(false); +} + +AsScene2101HitByDoorEffect::AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen) + : AnimatedSprite(vm, 1400), _klaymen(klaymen) { + + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2101HitByDoorEffect::handleMessage); + createSurface(1200, 88, 165); + setVisible(false); +} + +uint32 AsScene2101HitByDoorEffect::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2001: + _x = _klaymen->getX(); + _y = _klaymen->getY() - 132; + startAnimation(0x0422255A, 0, -1); + setVisible(true); + break; + case 0x3002: + stopAnimation(); + setVisible(false); + break; + } + return messageResult; +} + +SsCommonFloorButton::SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash) + : StaticSprite(vm, 1100), _parentScene(parentScene), _countdown(0), + _fileHash1(fileHash1), _fileHash2(fileHash2), _soundFileHash(soundFileHash) { + + SetUpdateHandler(&SsCommonFloorButton::update); + SetMessageHandler(&SsCommonFloorButton::handleMessage); + if (_soundFileHash == 0) + _soundFileHash = 0x44141000; + createSurface(1010, 61, 30); + if (_fileHash1) + loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition); + else + setVisible(false); +} + +void SsCommonFloorButton::update() { + if (_countdown != 0 && (--_countdown == 0)) { + sendMessage(_parentScene, 0x1022, 1010); + if (_fileHash1) + loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition); + else + setVisible(false); + } +} + +uint32 SsCommonFloorButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x480B: + sendMessage(_parentScene, 0x480B, 0); + setVisible(true); + sendMessage(_parentScene, 0x1022, 990); + loadSprite(_fileHash2, kSLFDefDrawOffset | kSLFDefPosition); + _countdown = 16; + playSound(0, _soundFileHash); + break; + } + return messageResult; +} + +Scene2101::Scene2101(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + Sprite *tempSprite; + + SetMessageHandler(&Scene2101::handleMessage); + SetUpdateHandler(&Scene2101::update); + + setBackground(0x44242305); + setPalette(0x44242305); + insertScreenMouse(0x4230144A); + + insertStaticSprite(0x00502330, 1100); + tempSprite = insertStaticSprite(0x78492010, 1100); + _ssFloorButton = insertSprite(this, 0x72427010, 0x32423010, 200, 0); + _asTape1 = insertSprite(this, 18, 1100, 412, 443, 0x9148A011); + addCollisionSprite(_asTape1); + _asTape2 = insertSprite(this, 11, 1100, 441, 443, 0x9148A011); + addCollisionSprite(_asTape2); + + if (which < 0) { + insertKlaymen(380, 438); + setMessageList(0x004B8E48); + sendMessage(this, 0x2000, 0); + _asDoor = insertSprite(false); + _doorStatus = 1; + _countdown1 = 0; + } else if (which == 1) { + // Klaymen entering from the right + insertKlaymen(640, 438); + setMessageList(0x004B8E50); + sendMessage(this, 0x2000, 0); + _asDoor = insertSprite(true); + _doorStatus = 2; + _countdown1 = 48; + } else if (which == 2) { + // Klaymen teleporting out + insertKlaymen(115, 438); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B8F58); + sendMessage(this, 0x2000, 1); + _asDoor = insertSprite(false); + _doorStatus = 1; + _countdown1 = 0; + } else if (which == 3) { + // Klaymen returning from the teleporter console + insertKlaymen(115, 438); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B8EB0); + sendMessage(this, 0x2000, 1); + _asDoor = insertSprite(false); + _doorStatus = 1; + _countdown1 = 0; + } else { + // Klaymen teleporting in + insertKlaymen(115, 438); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004B8EA0); + sendMessage(this, 0x2000, 1); + _asDoor = insertSprite(false); + _doorStatus = 1; + _countdown1 = 0; + } + + _asHitByDoorEffect = insertSprite(_klaymen); + _klaymen->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480); + +} + +void Scene2101::update() { + if (_countdown1 != 0) { + if (_doorStatus == 2) { + if (--_countdown1 == 0) { + sendMessage(_asDoor, 0x4809, 0); + _doorStatus = 1; + } + } else { + if (_klaymen->getX() > 575) + _canAcceptInput = false; + if (--_countdown1 == 0) { + if (_klaymen->getX() < 480) { + sendMessage(_asDoor, 0x4809, 0); + _doorStatus = 1; + } else if (_klaymen->getX() >= 480 && _klaymen->getX() <= 575) { + _klaymen->setDoDeltaX(0); + setMessageList2(0x004B8F48); + sendMessage(_asDoor, 0x4809, 0); + sendMessage(_asHitByDoorEffect, 0x2001, 0); + _doorStatus = 1; + } + } + } + } else if (_doorStatus == 1 && _messageValue >= 0 && _klaymen->getX() > 470 && !isMessageList2(0x004B8F48)) + setMessageList2(0x004B8F50); + Scene::update(); +} + +uint32 Scene2101::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x02144CB1) + sendEntityMessage(_klaymen, 0x1014, _ssFloorButton); + else if (param.asInteger() == 0x21E64A00) { + if (_doorStatus == 0) + setMessageList(0x004B8E80); + else + setMessageList(0x004B8EC8); + } else if (param.asInteger() == 0x41442820) + cancelMessageList(); + break; + case 0x2000: + if (param.asInteger() != 0) { + setRectList(0x004B9008); + _klaymen->setKlaymenIdleTable3(); + } else { + setRectList(0x004B8FF8); + _klaymen->setKlaymenIdleTable1(); + } + break; + case 0x480B: + if (sender == _ssFloorButton && _doorStatus == 1) { + sendMessage(_asDoor, 0x4808, 0); + _doorStatus = 0; + _countdown1 = 90; + } + break; + case 0x4826: + if (sender == _asTape1 || sender == _asTape2) { + if (_klaymen->getX() >= 228 && _klaymen->getX() <= 500) { + sendEntityMessage(_klaymen, 0x1014, sender); + setMessageList(0x004B8F78); + } else if (_klaymen->getX() < 228) + setMessageList2(0x004B8F00); + } + break; + } + return 0; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module2100.h b/engines/neverhood/modules/module2100.h new file mode 100644 index 0000000000..369f5ac0cc --- /dev/null +++ b/engines/neverhood/modules/module2100.h @@ -0,0 +1,92 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE2100_H +#define NEVERHOOD_MODULES_MODULE2100_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +class Module2100 : public Module { +public: + Module2100(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module2100(); +protected: + int _sceneNum; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void createScene(int sceneNum, int which); + void updateScene(); +}; + +// Scene1901 + +class AsScene2101Door : public AnimatedSprite { +public: + AsScene2101Door(NeverhoodEngine *vm, bool isOpen); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stOpenDoor(); + void stCloseDoor(); + void stCloseDoorDone(); +}; + +class AsScene2101HitByDoorEffect : public AnimatedSprite { +public: + AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen); +protected: + Sprite *_klaymen; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsCommonFloorButton : public StaticSprite { +public: + SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash); +protected: + Scene *_parentScene; + uint32 _soundFileHash; + uint32 _fileHash1, _fileHash2; + int16 _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2101 : public Scene { +public: + Scene2101(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_ssFloorButton; + Sprite *_asTape1; + Sprite *_asTape2; + Sprite *_asDoor; + Sprite *_asHitByDoorEffect; + int _countdown1; + int _doorStatus; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE2100_H */ diff --git a/engines/neverhood/modules/module2200.cpp b/engines/neverhood/modules/module2200.cpp new file mode 100644 index 0000000000..b8da0f64ff --- /dev/null +++ b/engines/neverhood/modules/module2200.cpp @@ -0,0 +1,2564 @@ +/* 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/modules/module2200.h" +#include "neverhood/modules/module1000.h" +#include "neverhood/modules/module1200.h" +#include "neverhood/gamemodule.h" +#include "neverhood/diskplayerscene.h" + +namespace Neverhood { + +Module2200::Module2200(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + debug("Create Module2200(%d)", which); + + _vm->_soundMan->addMusic(0x11391412, 0x601C908C); + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else + createScene(0, 0); + +} + +Module2200::~Module2200() { + _vm->_soundMan->deleteGroup(0x11391412); +} + +void Module2200::createScene(int sceneNum, int which) { + debug("Module2200::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _childObject = new Scene2201(_vm, this, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + _vm->_soundMan->startMusic(0x601C908C, 0, 2); + _childObject = new Scene2202(_vm, this, which); + break; + case 2: + _vm->gameState().sceneNum = 2; + _vm->_soundMan->startMusic(0x601C908C, 0, 2); + _childObject = new Scene2203(_vm, this, which); + break; + case 3: + _vm->gameState().sceneNum = 3; + _vm->_soundMan->stopMusic(0x601C908C, 0, 2); + _childObject = new DiskplayerScene(_vm, this, 3); + break; + case 4: + _vm->gameState().sceneNum = 4; + _vm->_soundMan->stopMusic(0x601C908C, 0, 2); + _childObject = new Scene2205(_vm, this, which); + break; + case 5: + _vm->gameState().sceneNum = 5; + _vm->_soundMan->stopMusic(0x601C908C, 0, 2); + _childObject = new Scene2206(_vm, this, which); + break; + case 6: + _vm->gameState().sceneNum = 6; + _childObject = new Scene2207(_vm, this); + break; + case 7: + if (which >= 0) + _vm->gameState().which = _vm->gameState().sceneNum; + _vm->gameState().sceneNum = 7; + _childObject = new Scene2208(_vm, this, which); + break; + case 8: + _vm->gameState().sceneNum = 8; + _childObject = new Scene2208(_vm, this, which); + break; + case 9: + _vm->gameState().sceneNum = 9; + createHallOfRecordsScene(which, 0x004B7180); + break; + case 10: + _vm->gameState().sceneNum = 10; + createHallOfRecordsScene(which, 0x004B7198); + break; + case 11: + _vm->gameState().sceneNum = 11; + createHallOfRecordsScene(which, 0x004B71B0); + break; + case 12: + _vm->gameState().sceneNum = 12; + createHallOfRecordsScene(which, 0x004B71C8); + break; + case 13: + _vm->gameState().sceneNum = 13; + createHallOfRecordsScene(which, 0x004B71E0); + break; + case 14: + _vm->gameState().sceneNum = 14; + createHallOfRecordsScene(which, 0x004B71F8); + break; + case 15: + _vm->gameState().sceneNum = 15; + createHallOfRecordsScene(which, 0x004B7210); + break; + case 16: + _vm->gameState().sceneNum = 16; + createHallOfRecordsScene(which, 0x004B7228); + break; + case 17: + _vm->gameState().sceneNum = 17; + createHallOfRecordsScene(which, 0x004B7240); + break; + case 18: + _vm->gameState().sceneNum = 18; + createHallOfRecordsScene(which, 0x004B7258); + break; + case 19: + _vm->gameState().sceneNum = 19; + createHallOfRecordsScene(which, 0x004B7270); + break; + case 20: + _vm->gameState().sceneNum = 20; + createHallOfRecordsScene(which, 0x004B7288); + break; + case 21: + _vm->gameState().sceneNum = 21; + createHallOfRecordsScene(which, 0x004B72A0); + break; + case 22: + _vm->gameState().sceneNum = 22; + createHallOfRecordsScene(which, 0x004B72B8); + break; + case 23: + _vm->gameState().sceneNum = 23; + createHallOfRecordsScene(which, 0x004B72D0); + break; + case 24: + _vm->gameState().sceneNum = 24; + createHallOfRecordsScene(which, 0x004B72E8); + break; + case 25: + _vm->gameState().sceneNum = 25; + createHallOfRecordsScene(which, 0x004B7300); + break; + case 26: + _vm->gameState().sceneNum = 26; + createHallOfRecordsScene(which, 0x004B7318); + break; + case 27: + _vm->gameState().sceneNum = 27; + createHallOfRecordsScene(which, 0x004B7330); + break; + case 28: + _vm->gameState().sceneNum = 28; + createHallOfRecordsScene(which, 0x004B7348); + break; + case 29: + _vm->gameState().sceneNum = 29; + createHallOfRecordsScene(which, 0x004B7360); + break; + case 30: + _vm->gameState().sceneNum = 30; + createHallOfRecordsScene(which, 0x004B7378); + break; + case 31: + _vm->gameState().sceneNum = 31; + createHallOfRecordsScene(which, 0x004B7390); + break; + case 32: + _vm->gameState().sceneNum = 32; + createHallOfRecordsScene(which, 0x004B73A8); + break; + case 33: + _vm->gameState().sceneNum = 33; + createHallOfRecordsScene(which, 0x004B73C0); + break; + case 34: + _vm->gameState().sceneNum = 34; + createHallOfRecordsScene(which, 0x004B73D8); + break; + case 35: + _vm->gameState().sceneNum = 35; + createHallOfRecordsScene(which, 0x004B73F0); + break; + case 36: + _vm->gameState().sceneNum = 36; + createHallOfRecordsScene(which, 0x004B7408); + break; + case 37: + _vm->gameState().sceneNum = 37; + createHallOfRecordsScene(which, 0x004B7420); + break; + case 38: + _vm->gameState().sceneNum = 38; + createHallOfRecordsScene(which, 0x004B7438); + break; + case 39: + _vm->gameState().sceneNum = 39; + createHallOfRecordsScene(which, 0x004B7450); + break; + case 40: + _vm->gameState().sceneNum = 40; + createHallOfRecordsScene(which, 0x004B7468); + break; + case 41: + _vm->gameState().sceneNum = 41; + _childObject = new Scene2242(_vm, this, which); + break; + case 42: + _vm->gameState().sceneNum = 42; + createHallOfRecordsScene(which, 0x004B7480); + break; + case 43: + _vm->gameState().sceneNum = 43; + createHallOfRecordsScene(which, 0x004B7498); + break; + case 44: + _vm->gameState().sceneNum = 44; + createHallOfRecordsScene(which, 0x004B74B0); + break; + case 45: + _vm->gameState().sceneNum = 45; + createHallOfRecordsScene(which, 0x004B74C8); + break; + case 46: + _vm->gameState().sceneNum = 46; + _childObject = new Scene2247(_vm, this, which); + break; + case 47: + _vm->gameState().sceneNum = 47; + if (!getGlobalVar(V_WORLDS_JOINED)) { + if (getGlobalVar(V_LIGHTS_ON)) + createStaticScene(0x83110287, 0x10283839); + else + createStaticScene(0x83412B9D, 0x12B9983C); + } else { + if (getGlobalVar(V_LIGHTS_ON)) + createStaticScene(0x48632087, 0x3208348E); + else + createStaticScene(0x08C74886, 0x74882084); + } + break; + } + SetUpdateHandler(&Module2200::updateScene); + _childObject->handleUpdate(); +} + +#define HallOfRecordsSceneLink(nextSceneNum, prevSceneNum) \ + if (_moduleResult == 1) createScene(nextSceneNum, 0); else if (_moduleResult == 2) createScene(7, 0); else createScene(prevSceneNum, 1) + +void Module2200::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 1) + createScene(2, 0); + else if (_moduleResult == 2) + createScene(1, 0); + else + leaveModule(0); + break; + case 1: + createScene(0, 2); + break; + case 2: + if (_moduleResult == 1) + createScene(4, 0); + else if (_moduleResult == 2) + createScene(3, 0); + else + createScene(0, 1); + break; + case 3: + createScene(2, 2); + break; + case 4: + if (_moduleResult == 1) + createScene(5, 0); + else if (_moduleResult == 2) + createScene(4, 2); + else + createScene(2, 1); + break; + case 5: + if (_moduleResult == 1) + createScene(46, 0); + else if (_moduleResult == 2) + createScene(6, 0); + else if (_moduleResult == 3) + createScene(8, 0); + else + createScene(4, 1); + break; + case 6: + createScene(5, 2); + break; + case 7: + createScene(_vm->gameState().which, 2); + break; + case 8: + createScene(5, 3); + break; + case 9: + HallOfRecordsSceneLink(10, 46); + break; + case 10: + HallOfRecordsSceneLink(11, 9); + break; + case 11: + HallOfRecordsSceneLink(12, 10); + break; + case 12: + HallOfRecordsSceneLink(13, 11); + break; + case 13: + HallOfRecordsSceneLink(14, 12); + break; + case 14: + HallOfRecordsSceneLink(15, 13); + break; + case 15: + HallOfRecordsSceneLink(16, 14); + break; + case 16: + HallOfRecordsSceneLink(17, 15); + break; + case 17: + HallOfRecordsSceneLink(18, 16); + break; + case 18: + HallOfRecordsSceneLink(19, 17); + break; + case 19: + HallOfRecordsSceneLink(20, 18); + break; + case 20: + HallOfRecordsSceneLink(21, 19); + break; + case 21: + HallOfRecordsSceneLink(22, 20); + break; + case 22: + HallOfRecordsSceneLink(23, 21); + break; + case 23: + HallOfRecordsSceneLink(24, 22); + break; + case 24: + HallOfRecordsSceneLink(25, 23); + break; + case 25: + HallOfRecordsSceneLink(26, 24); + break; + case 26: + HallOfRecordsSceneLink(27, 25); + break; + case 27: + HallOfRecordsSceneLink(28, 26); + break; + case 28: + HallOfRecordsSceneLink(29, 27); + break; + case 29: + HallOfRecordsSceneLink(30, 28); + break; + case 30: + HallOfRecordsSceneLink(31, 29); + break; + case 31: + HallOfRecordsSceneLink(32, 30); + break; + case 32: + HallOfRecordsSceneLink(33, 31); + break; + case 33: + HallOfRecordsSceneLink(34, 32); + break; + case 34: + HallOfRecordsSceneLink(42, 33); + break; + case 35: + HallOfRecordsSceneLink(36, 45); + break; + case 36: + HallOfRecordsSceneLink(37, 35); + break; + case 37: + HallOfRecordsSceneLink(38, 36); + break; + case 38: + HallOfRecordsSceneLink(39, 37); + break; + case 39: + HallOfRecordsSceneLink(40, 38); + break; + case 40: + HallOfRecordsSceneLink(41, 39); + break; + case 41: + HallOfRecordsSceneLink(47, 40); + break; + case 42: + HallOfRecordsSceneLink(43, 34); + break; + case 43: + HallOfRecordsSceneLink(44, 42); + break; + case 44: + HallOfRecordsSceneLink(45, 43); + break; + case 45: + HallOfRecordsSceneLink(35, 44); + break; + case 46: + HallOfRecordsSceneLink(9, 5); + break; + case 47: + createScene(41, 1); + break; + } + } +} + +#undef HallOfRecordsSceneLink + +void Module2200::createHallOfRecordsScene(int which, uint32 hallOfRecordsInfoId) { + _childObject = new HallOfRecordsScene(_vm, this, which, hallOfRecordsInfoId); +} + +// Scene2201 + +AsScene2201CeilingFan::AsScene2201CeilingFan(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100) { + + _x = 403; + _y = 259; + createSurface(100, 233, 96); + startAnimation(0x8600866, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); +} + +AsScene2201Door::AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen) + : AnimatedSprite(vm, 1100), _klaymen(klaymen), _ssDoorLight(ssDoorLight), _countdown(0), _isOpen(isOpen) { + + _x = 408; + _y = 290; + createSurface(900, 63, 266); + SetUpdateHandler(&AsScene2201Door::update); + SetMessageHandler(&AsScene2201Door::handleMessage); + if (_isOpen) { + startAnimation(0xE2CB0412, -1, -1); + _countdown = 48; + _newStickFrameIndex = STICK_LAST_FRAME; + } else { + startAnimation(0xE2CB0412, 0, -1); + _newStickFrameIndex = 0; + _ssDoorLight->setVisible(false); + } +} + +void AsScene2201Door::update() { + if (_countdown != 0 && _isOpen && (--_countdown == 0)) + stCloseDoor(); + AnimatedSprite::update(); +} + +uint32 AsScene2201Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x11001090) { + if (_isOpen) + _ssDoorLight->setVisible(true); + } else if (param.asInteger() == 0x11283090) { + if (!_isOpen) + _ssDoorLight->setVisible(false); + } + break; + case 0x2000: + if (_isOpen) + _countdown = 144; + messageResult = _isOpen ? 1 : 0; + break; + case 0x3002: + gotoNextState(); + break; + case 0x4808: + _countdown = 144; + if (!_isOpen) + stOpenDoor(); + break; + } + return messageResult; +} + +void AsScene2201Door::stOpenDoor() { + _isOpen = true; + startAnimation(0xE2CB0412, 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + playSound(0, calcHash("fxDoorOpen33")); +} + +void AsScene2201Door::stCloseDoor() { + _isOpen = false; + startAnimation(0xE2CB0412, -1, -1); + _playBackwards = true; + _newStickFrameIndex = 0; + playSound(0, calcHash("fxDoorClose33")); +} + +SsScene2201PuzzleCube::SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex) + : StaticSprite(vm, 900) { + + createSurface(100, 16, 16); + loadSprite(kSsScene2201PuzzleCubeFileHashes[cubeIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 0, + kSsScene2201PuzzleCubePoints[positionIndex].x, kSsScene2201PuzzleCubePoints[positionIndex].y); +} + +Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _isSoundPlaying(false) { + + Sprite *tempSprite; + + _vm->gameModule()->initCubeSymbolsPuzzle(); + + SetMessageHandler(&Scene2201::handleMessage); + SetUpdateHandler(&Scene2201::update); + + loadDataResource(0x04104242); + loadHitRectList(); + setBackground(0x40008208); + setPalette(0x40008208); + insertScreenMouse(0x0820C408); + + _asTape = insertSprite(this, 7, 1100, 459, 432, 0x9148A011); + addCollisionSprite(_asTape); + _ssDoorButton = insertSprite(this, 0xE4A43E29, 0xE4A43E29, 100, 0); + + for (uint32 cubeIndex = 0; cubeIndex < 9; cubeIndex++) + if ((int16)getSubVar(VA_CUBE_POSITIONS, cubeIndex) >= 0) + insertSprite(cubeIndex, (int16)getSubVar(VA_CUBE_POSITIONS, cubeIndex)); + + _clipRects[0].y1 = 0; + _clipRects[0].x2 = 640; + _clipRects[1].x2 = 640; + _clipRects[1].y2 = 480; + + if (!getGlobalVar(V_TILE_PUZZLE_SOLVED)) + insertStaticSprite(0x00026027, 900); + + tempSprite = insertStaticSprite(0x030326A0, 1100); + _clipRects[0].x1 = tempSprite->getDrawRect().x; + insertStaticSprite(0x811DA061, 1100); + tempSprite = insertStaticSprite(0x11180022, 1100); + _clipRects[1].x1 = tempSprite->getDrawRect().x; + tempSprite = insertStaticSprite(0x0D411130, 1100); + _clipRects[0].y2 = tempSprite->getDrawRect().y2(); + _clipRects[1].y1 = tempSprite->getDrawRect().y2(); + _ssDoorLight = insertStaticSprite(0xA4062212, 900); + + if (which < 0) { + // Restoring game + insertKlaymen(300, 427, _clipRects, 2); + setMessageList(0x004B8118); + _asDoor = insertSprite(_klaymen, _ssDoorLight, false); + } else if (which == 1) { + // Klaymen entering from the back + insertKlaymen(412, 393, _clipRects, 2); + setMessageList(0x004B8130); + _asDoor = insertSprite(_klaymen, _ssDoorLight, false); + } else if (which == 2) { + // Klaymen returning from the puzzle + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { + insertKlaymen(379, 427, _clipRects, 2); + _klaymen->setDoDeltaX(1); + } else + insertKlaymen(261, 427, _clipRects, 2); + setMessageList(0x004B8178); + _asDoor = insertSprite(_klaymen, _ssDoorLight, false); + } else { + // Klaymen entering from the left + NPoint pt = _dataResource.getPoint(0x0304D8DC); + insertKlaymen(pt.x, pt.y, _clipRects, 2); + setMessageList(0x004B8120); + _asDoor = insertSprite(_klaymen, _ssDoorLight, true); + } + + insertSprite(); + + _vm->_soundMan->addSound(0x04106220, 0x81212040); + +} + +Scene2201::~Scene2201() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); + _vm->_soundMan->deleteSoundGroup(0x04106220); +} + +void Scene2201::update() { + Scene::update(); + if (!_isSoundPlaying) { + _vm->_soundMan->playSoundLooping(0x81212040); + _isSoundPlaying = true; + } +} + +uint32 Scene2201::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x402064D8) + sendEntityMessage(_klaymen, 0x1014, _ssDoorButton); + else if (param.asInteger() == 0x35803198) { + if (sendMessage(_asDoor, 0x2000, 0)) + setMessageList(0x004B81A0); + else + setMessageList(0x004B81B8); + } else if (param.asInteger() == 0x51445010) { + if (getGlobalVar(V_TILE_PUZZLE_SOLVED)) + setMessageList(0x004B8108); + else + setMessageList(0x004B8150); + } else if (param.asInteger() == 0x1D203082) + setMessageList(0x004B8180); + else if (param.asInteger() == 0x00049091) { + if (getGlobalVar(V_TILE_PUZZLE_SOLVED)) + setMessageList(0x004B8138); + else + setMessageList(0x004B8108); + } + break; + case 0x480B: + if (sender == _ssDoorButton) + sendMessage(_asDoor, 0x4808, 0); + break; + case 0x4826: + if (sender == _asTape) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004B81C8); + } + break; + } + return 0; +} + +static const NPoint kSsScene2202PuzzleCubePoints[] = { + {196, 105}, {323, 102}, {445, 106}, + {192, 216}, {319, 220}, {446, 216}, + {188, 320}, {319, 319}, {443, 322} +}; + +static const uint32 kSsScene2202PuzzleCubeFileHashes1[] = { + 0xA500800C, 0x2182910C, 0x2323980C, + 0x23049084, 0x21008080, 0x2303900C, + 0x6120980C, 0x2504D808 +}; + +static const uint32 kSsScene2202PuzzleCubeFileHashes2[] = { + 0x0AAD8080, 0x0A290291, 0x0A2BA398, + 0x822B8490, 0x86298080, 0x0A2B8390, + 0x0A69A098, 0x0E2D84D8 +}; + +SsScene2202PuzzleCube::SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol) + : StaticSprite(vm, 900), _parentScene(parentScene), _cubeSymbol(cubeSymbol), _cubePosition(cubePosition), _isMoving(false) { + + int surfacePriority; + + SetUpdateHandler(&SsScene2202PuzzleCube::update); + SetMessageHandler(&SsScene2202PuzzleCube::handleMessage); + if (_cubePosition >= 0 && _cubePosition <= 2) + surfacePriority = 100; + else if (_cubePosition >= 3 && _cubePosition <= 5) + surfacePriority = 300; + else + surfacePriority = 500; + loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset | kSLFSetPosition | kSLFDefCollisionBoundsOffset, 0, + kSsScene2202PuzzleCubePoints[_cubePosition].x, kSsScene2202PuzzleCubePoints[_cubePosition].y); + loadSound(0, 0x40958621); + loadSound(1, 0x51108241); +} + +void SsScene2202PuzzleCube::update() { + handleSpriteUpdate(); + updatePosition(); +} + +uint32 SsScene2202PuzzleCube::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (!_isMoving && !getGlobalVar(V_TILE_PUZZLE_SOLVED)) + sendMessage(_parentScene, 0x2000, _cubePosition); + messageResult = 1; + break; + case 0x2001: + _isMoving = true; + moveCube(param.asInteger()); + break; + } + return messageResult; +} + +void SsScene2202PuzzleCube::suMoveCubeX() { + + bool done = false; + + if (_counterDirection) { + if (_counter > 2) + _counter -= 2; + } else { + if (_counter < 20) + _counter += 2; + } + + for (int16 i = 0; i < _counter; i++) { + _x += _xIncr; + _errValue += _yDelta; + if (_errValue >= _xDelta) { + _errValue -= _xDelta; + _y += _yIncr; + } + if (_x == _newX && _y == _newY) { + done = true; + break; + } + if (_x == _xFlagPos) + _counterDirection = true; + } + + if (done) + stopMoving(); + + updateBounds(); + +} + +void SsScene2202PuzzleCube::suMoveCubeY() { + + bool done = false; + + if (_counterDirection) { + if (_counter > 2) + _counter -= 2; + } else { + if (_counter < 20) + _counter += 2; + } + + for (int16 i = 0; i < _counter; i++) { + _y += _yIncr; + _errValue += _xDelta; + if (_errValue >= _yDelta) { + _errValue -= _yDelta; + _x += _xIncr; + } + if (_x == _newX && _y == _newY) { + done = true; + break; + } + if (_x == _xFlagPos) + _counterDirection = true; + } + + if (done) + stopMoving(); + + updateBounds(); + +} + +void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) { + + loadSprite(kSsScene2202PuzzleCubeFileHashes1[_cubeSymbol], kSLFCenteredDrawOffset); + + setSubVar(VA_CUBE_POSITIONS, _cubePosition, (uint32)-1); + setSubVar(VA_CUBE_POSITIONS, newCubePosition, (uint32)_cubeSymbol); + + _cubePosition = newCubePosition; + _errValue = 0; + _counterDirection = false; + _counter = 0; + _newX = kSsScene2202PuzzleCubePoints[newCubePosition].x; + _newY = kSsScene2202PuzzleCubePoints[newCubePosition].y; + + if (_x == _newX && _y == _newY) + return; + + if (_x <= _newX) { + if (_y <= _newY) { + _xDelta = _newX - _x; + _yDelta = _newY - _y; + _xIncr = 1; + _yIncr = 1; + } else { + _xDelta = _newX - _x; + _yDelta = _y - _newY; + _xIncr = 1; + _yIncr = -1; + } + } else { + if (_y <= _newY) { + _xDelta = _x - _newX; + _yDelta = _newY - _y; + _xIncr = -1; + _yIncr = 1; + } else { + _xDelta = _x - _newX; + _yDelta = _y - _newY; + _xIncr = -1; + _yIncr = -1; + } + } + + if (_xDelta > _yDelta) { + SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeX); + if (_xIncr > 0) { + if (_newX - _x >= 180) + _xFlagPos = _newX - 90; + else + _xFlagPos = _x + _newX / 2; + } else { + if (_x - _newX >= 180) + _xFlagPos = _x + 90; + else + _xFlagPos = _x / 2 + _newX; + } + playSound(0); + } else { + SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeY); + if (_yIncr > 0) { + if (_newY - _y >= 180) + _xFlagPos = _newY - 90; + else + _xFlagPos = _y + _newY / 2; + } else { + if (_y - _newY >= 180) + _xFlagPos = _y + 90; + else + _xFlagPos = _y / 2 + _newY; + } + playSound(1); + } + +} + +void SsScene2202PuzzleCube::stopMoving() { + loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset); + SetSpriteUpdate(NULL); + _isMoving = false; + sendMessage(_parentScene, 0x2002, _cubePosition); +} + +Scene2202::Scene2202(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _isSolved(false), _leaveScene(false), _isCubeMoving(false), + _ssMovingCube(NULL), _ssDoneMovingCube(NULL) { + + _vm->gameModule()->initCubeSymbolsPuzzle(); + + SetMessageHandler(&Scene2202::handleMessage); + SetUpdateHandler(&Scene2202::update); + + setBackground(0x08100A0C); + setPalette(0x08100A0C); + addEntity(_palette); + insertPuzzleMouse(0x00A08089, 20, 620); + + for (uint32 cubePosition = 0; cubePosition < 9; cubePosition++) { + int16 cubeSymbol = (int16)getSubVar(VA_CUBE_POSITIONS, cubePosition); + if (cubeSymbol >= 0) { + Sprite *puzzleCubeSprite = insertSprite(this, cubePosition, cubeSymbol); + addCollisionSprite(puzzleCubeSprite); + } + } + + insertStaticSprite(0x55C043B8, 200); + insertStaticSprite(0x85500158, 400); + insertStaticSprite(0x25547028, 600); + + loadSound(0, 0x68E25540); + loadSound(1, 0x40400457); + + _vm->_soundMan->addSound(0x60400854, 0x8101A241); + _vm->_soundMan->playSoundLooping(0x8101A241); + +} + +Scene2202::~Scene2202() { + _vm->_soundMan->deleteSoundGroup(0x60400854); +} + +void Scene2202::update() { + Scene::update(); + + if (_leaveScene && !isSoundPlaying(1)) + leaveScene(0); + + if (_isSolved && !isSoundPlaying(0)) { + playSound(1); + _isSolved = false; + _leaveScene = true; + } + + if (_ssMovingCube && !_isCubeMoving) { + int16 freeCubePosition = getFreeCubePosition(_movingCubePosition); + if (freeCubePosition != -1) { + setSurfacePriority(_ssMovingCube->getSurface(), 700); + sendMessage(_ssMovingCube, 0x2001, freeCubePosition); + _ssMovingCube = NULL; + _isCubeMoving = true; + } + } + + if (_ssDoneMovingCube) { + setSurfacePriority(_ssDoneMovingCube->getSurface(), _surfacePriority); + _ssDoneMovingCube = NULL; + if (testIsSolved()) { + playSound(0); + setGlobalVar(V_TILE_PUZZLE_SOLVED, 1); + _isSolved = true; + } + } + +} + +uint32 Scene2202::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) + leaveScene(0); + break; + case 0x2000: + _movingCubePosition = (int16)param.asInteger(); + _ssMovingCube = (Sprite*)sender; + break; + case 0x2002: + _isCubeMoving = false; + _ssDoneMovingCube = (Sprite*)sender; + if (param.asInteger() <= 2) + _surfacePriority = 100; + else if (param.asInteger() >= 3 && param.asInteger() <= 5) + _surfacePriority = 300; + else + _surfacePriority = 500; + break; + } + return 0; +} + +int16 Scene2202::getFreeCubePosition(int16 cubePosition) { + if (cubePosition >= 3 && (int16)getSubVar(VA_CUBE_POSITIONS, cubePosition - 3) == -1) + return cubePosition - 3; + else if (cubePosition <= 5 && (int16)getSubVar(VA_CUBE_POSITIONS, cubePosition + 3) == -1) + return cubePosition + 3; + else if (cubePosition != 0 && cubePosition != 3 && cubePosition != 6 && (int16)getSubVar(VA_CUBE_POSITIONS, cubePosition - 1) == -1) + return cubePosition - 1; + else if (cubePosition != 2 && cubePosition != 5 && cubePosition != 8 && (int16)getSubVar(VA_CUBE_POSITIONS, cubePosition + 1) == -1) + return cubePosition + 1; + else + return -1; +} + +bool Scene2202::testIsSolved() { + return + getSubVar(VA_CUBE_POSITIONS, 0) == 0 && + getSubVar(VA_CUBE_POSITIONS, 2) == 2 && + getSubVar(VA_CUBE_POSITIONS, 3) == 3 && + getSubVar(VA_CUBE_POSITIONS, 4) == 4 && + getSubVar(VA_CUBE_POSITIONS, 5) == 5 && + getSubVar(VA_CUBE_POSITIONS, 6) == 6 && + getSubVar(VA_CUBE_POSITIONS, 8) == 7; +} + +static const uint32 kAsCommonKeyFileHashes[] = { + 0x2450D850, 0x0C9CE8D0, 0x2C58A152 +}; + +AsCommonKey::AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y) + : AnimatedSprite(vm, kAsCommonKeyFileHashes[keyIndex], surfacePriority, x, y), _parentScene(parentScene), _keyIndex(keyIndex) { + + if (!getSubVar(VA_HAS_KEY, _keyIndex) && !getSubVar(VA_IS_KEY_INSERTED, _keyIndex)) { + SetMessageHandler(&AsCommonKey::handleMessage); + } else { + // If Klaymen already has the key or it's already inserted then don't show it + setVisible(false); + SetMessageHandler(NULL); + } +} + +uint32 AsCommonKey::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x4806: + setSubVar(VA_HAS_KEY, _keyIndex, 1); + setVisible(false); + SetMessageHandler(NULL); + } + return messageResult; +} + +static const uint32 kAsScene2203DoorFileHashes[] = { + 0x7868AE10, 0x1A488110 +}; + +AsScene2203Door::AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _doorIndex(doorIndex) { + + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2203Door::handleMessage); + _x = 320; + _y = 240; + createSurface1(kAsScene2203DoorFileHashes[_doorIndex], 900); + if (getGlobalVar(V_LARGE_DOOR_NUMBER) == _doorIndex) { + startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + } else { + startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 0, -1); + _newStickFrameIndex = 0; + } +} + +uint32 AsScene2203Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER)) + sendMessage(_parentScene, 0x2002, 0); + else + sendMessage(_parentScene, 0x2001, 0); + messageResult = 1; + break; + case 0x2000: + _otherDoor = (Sprite*)param.asEntity(); + break; + case 0x3002: + if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER)) + sendMessage(_parentScene, 0x4808, 0); + stopAnimation(); + break; + case 0x4808: + setGlobalVar(V_LARGE_DOOR_NUMBER, _doorIndex); + sendMessage(_otherDoor, 0x4809, 0); + openDoor(); + break; + case 0x4809: + closeDoor(); + sendMessage(_parentScene, 0x2003, 0); + break; + } + return messageResult; +} + +void AsScene2203Door::openDoor() { + playSound(0, 0x341014C4); + startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 1, -1); +} + +void AsScene2203Door::closeDoor() { + startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1); + _playBackwards = true; + _newStickFrameIndex = 0; +} + +Scene2203::Scene2203(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) + setGlobalVar(V_KEY3_LOCATION, 1); + + SetMessageHandler(&Scene2203::handleMessage); + + setBackground(0x82C80334); + setPalette(0x82C80334); + insertScreenMouse(0x80330824); + setHitRects(0x004B8320); + setRectList(0x004B8420); + + if (getGlobalVar(V_KEY3_LOCATION) == 1) { + _asKey = insertSprite(this, 2, 1100, 282, 432); + addCollisionSprite(_asKey); + } + + _asTape = insertSprite(this, 1, 1100, 435, 432, 0x9148A011); + addCollisionSprite(_asTape); + _asLeftDoor = insertSprite(this, 0); + _asRightDoor = insertSprite(this, 1); + _ssSmallLeftDoor = insertStaticSprite(0x542CC072, 1100); + _ssSmallRightDoor = insertStaticSprite(0x0A2C0432, 1100); + _leftDoorClipRect.set(_ssSmallLeftDoor->getDrawRect().x, 0, 640, 480); + _rightDoorClipRect.set(0, 0, _ssSmallRightDoor->getDrawRect().x2(), 480); + sendEntityMessage(_asLeftDoor, 0x2000, _asRightDoor); + sendEntityMessage(_asRightDoor, 0x2000, _asLeftDoor); + addCollisionSprite(_asLeftDoor); + addCollisionSprite(_asRightDoor); + + if (which < 0) { + // Restoring game + insertKlaymen(200, 427); + setMessageList(0x004B8340); + } else if (which == 1) { + // Klaymen entering from the right + insertKlaymen(640, 427); + setMessageList(0x004B8350); + } else if (which == 2) { + // Klaymen returning from the displayer + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { + insertKlaymen(362, 427); + _klaymen->setDoDeltaX(1); + } else + insertKlaymen(202, 427); + setMessageList(0x004B8358); + } else { + // Klaymen entering from the left + insertKlaymen(0, 427); + setMessageList(0x004B8348); + } + + if (getGlobalVar(V_LARGE_DOOR_NUMBER)) { + _ssSmallLeftDoor->setVisible(false); + _klaymen->setClipRect(_rightDoorClipRect); + } else { + _ssSmallRightDoor->setVisible(false); + _klaymen->setClipRect(_leftDoorClipRect); + } + +} + +Scene2203::~Scene2203() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); +} + +uint32 Scene2203::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2001: + sendEntityMessage(_klaymen, 0x1014, sender); + if (sender == _asLeftDoor) + setMessageList2(0x004B83B0); + else + setMessageList2(0x004B83C8); + break; + case 0x2002: + if (sender == _asLeftDoor) + setMessageList2(0x004B8370); + else + setMessageList2(0x004B8360); + break; + case 0x2003: + if (sender == _asLeftDoor) + _ssSmallLeftDoor->setVisible(false); + else + _ssSmallRightDoor->setVisible(false); + break; + case 0x4808: + if (sender == _asLeftDoor) { + _ssSmallLeftDoor->setVisible(true); + _klaymen->setClipRect(_leftDoorClipRect); + } else { + _ssSmallRightDoor->setVisible(true); + _klaymen->setClipRect(_rightDoorClipRect); + } + break; + case 0x4826: + if (sender == _asTape) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004B83E0); + } else if (sender == _asKey) { + sendEntityMessage(_klaymen, 0x1014, _asKey); + setMessageList(0x004B83F0); + } + break; + } + return messageResult; +} + +SsScene2205DoorFrame::SsScene2205DoorFrame(NeverhoodEngine *vm) + : StaticSprite(vm, 900) { + + SetMessageHandler(&SsScene2205DoorFrame::handleMessage); + createSurface(1100, 45, 206); + loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition); +} + +uint32 SsScene2205DoorFrame::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition); + break; + } + return messageResult; +} + +Scene2205::Scene2205(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + SetMessageHandler(&Scene2205::handleMessage); + SetUpdateHandler(&Scene2205::update); + + setHitRects(0x004B0620); + if (getGlobalVar(V_LIGHTS_ON)) { + _isLightOn = true; + setBackground(0x0008028D); + setPalette(0x0008028D); + addEntity(_palette); + insertScreenMouse(0x80289008); + _ssLightSwitch = insertSprite(this, 0x2D339030, 0x2D309030, 100, 0); + } else { + _isLightOn = false; + setBackground(0xD00A028D); + setPalette(0xD00A028D); + addEntity(_palette); + insertScreenMouse(0xA0289D08); + _ssLightSwitch = insertSprite(this, 0x2D339030, 0xDAC86E84, 100, 0); + } + _palette->addBasePalette(0xD00A028D, 0, 256, 0); + _ssDoorFrame = insertSprite(); + + if (which < 0) { + // Restoring game + insertKlaymen(320, 417); + setMessageList(0x004B0658); + if (!getGlobalVar(V_LIGHTS_ON)) + _palette->addPalette(0x68033B1C, 0, 65, 0); + _isKlaymenInLight = false; + } else if (which == 1) { + // Klaymen entering from the right + insertKlaymen(640, 417); + setMessageList(0x004B0648); + if (!getGlobalVar(V_LIGHTS_ON)) + _palette->addPalette(0x68033B1C, 0, 65, 0); + _isKlaymenInLight = false; + } else { + // Klaymen entering from the left + insertKlaymen(0, 417); + setMessageList(0x004B0640); + _isKlaymenInLight = true; + } + + _klaymen->setClipRect(_ssDoorFrame->getDrawRect().x, 0, 640, 480); + _klaymen->setSoundFlag(true); + + loadDataResource(0x00144822); + +} + +void Scene2205::update() { + Scene::update(); + if (!_isLightOn && getGlobalVar(V_LIGHTS_ON)) { + _palette->addPalette(0x0008028D, 0, 256, 0); + changeBackground(0x0008028D); + _ssLightSwitch->setFileHashes(0x2D339030, 0x2D309030); + sendMessage(_ssDoorFrame, 0x2000, 0); + changeMouseCursor(0x80289008); + _isLightOn = true; + } else if (_isLightOn && !getGlobalVar(V_LIGHTS_ON)) { + _palette->addPalette(0xD00A028D, 0, 256, 0); + changeBackground(0xD00A028D); + _ssLightSwitch->setFileHashes(0x2D339030, 0xDAC86E84); + sendMessage(_ssDoorFrame, 0x2000, 0); + changeMouseCursor(0xA0289D08); + _isKlaymenInLight = true; + if (_klaymen->getX() > 85) { + _palette->addPalette(0x68033B1C, 0, 65, 0); + _isKlaymenInLight = false; + } + _isLightOn = false; + } + if (!getGlobalVar(V_LIGHTS_ON)) { + if (_isKlaymenInLight && _klaymen->getX() > 85) { + _palette->addBasePalette(0x68033B1C, 0, 65, 0); + _palette->startFadeToPalette(12); + _isKlaymenInLight = false; + } else if (!_isKlaymenInLight && _klaymen->getX() <= 85) { + _palette->addBasePalette(0xD00A028D, 0, 65, 0); + _palette->startFadeToPalette(12); + _isKlaymenInLight = true; + } + } +} + +uint32 Scene2205::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x6449569A) + setMessageList(0x004B0690); + else if (param.asInteger() == 0x2841369C) + setMessageList(0x004B0630); + else if (param.asInteger() == 0x402064D8) + sendEntityMessage(_klaymen, 0x1014, _ssLightSwitch); + break; + case 0x480B: + setGlobalVar(V_LIGHTS_ON, getGlobalVar(V_LIGHTS_ON) ? 0 : 1); + break; + } + return 0; +} + +static const int16 kScene2206XPositions[] = { + 384, 480, 572 +}; + +static const uint32 kScene2206MessageIds1[] = { + 0x004B8998, 0x004B89B8, 0x004B89D8 +}; + +static const uint32 kScene2206MessageIds2[] = { + 0x004B89F8, 0x004B8A20, 0x004B8A48 +}; + +static const int16 kAsScene2206DoorSpikesXDeltasOpen[] = { + -24, -28, -18, 6, 9, -8 +}; + +static const int16 kAsScene2206DoorSpikesXDeltasClose[] = { + -8, 7, 11, 26, 13, 14 +}; + +AsScene2206DoorSpikes::AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash) + : StaticSprite(vm, fileHash, 200) { + + if (getGlobalVar(V_SPIKES_RETRACTED)) + _x -= 63; + SetUpdateHandler(&AsScene2206DoorSpikes::update); + SetMessageHandler(&AsScene2206DoorSpikes::handleMessage); + SetSpriteUpdate(NULL); +} + +void AsScene2206DoorSpikes::update() { + handleSpriteUpdate(); + updatePosition(); +} + +uint32 AsScene2206DoorSpikes::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4808: + _deltaIndex = 0; + playSound(0, 0x032746E0); + SetMessageHandler(NULL); + SetSpriteUpdate(&AsScene2206DoorSpikes::suOpen); + break; + case 0x4809: + _deltaIndex = 0; + playSound(0, 0x002642C0); + SetMessageHandler(NULL); + SetSpriteUpdate(&AsScene2206DoorSpikes::suClose); + break; + } + return messageResult; +} + +void AsScene2206DoorSpikes::suOpen() { + if (_deltaIndex < 6) { + _x += kAsScene2206DoorSpikesXDeltasOpen[_deltaIndex]; + _deltaIndex++; + } else { + SetMessageHandler(&AsScene2206DoorSpikes::handleMessage); + SetSpriteUpdate(NULL); + } +} + +void AsScene2206DoorSpikes::suClose() { + if (_deltaIndex < 6) { + _x += kAsScene2206DoorSpikesXDeltasClose[_deltaIndex]; + _deltaIndex++; + } else { + SetMessageHandler(&AsScene2206DoorSpikes::handleMessage); + SetSpriteUpdate(NULL); + } +} + +AsScene2206Platform::AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash) + : StaticSprite(vm, fileHash, 50) { + + SetUpdateHandler(&AsScene2206Platform::update); + SetMessageHandler(&AsScene2206Platform::handleMessage); + SetSpriteUpdate(NULL); +} + +void AsScene2206Platform::update() { + handleSpriteUpdate(); + updatePosition(); +} + +uint32 AsScene2206Platform::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4803: + _yDelta = 0; + SetMessageHandler(NULL); + SetSpriteUpdate(&AsScene2206Platform::suMoveDown); + break; + } + return messageResult; +} + +void AsScene2206Platform::suMoveDown() { + _yDelta++; + _y += _yDelta; +} + +SsScene2206TestTube::SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash) + : StaticSprite(vm, fileHash, surfacePriority), _parentScene(parentScene) { + + if (getGlobalVar(V_HAS_TEST_TUBE)) { + setVisible(false); + SetMessageHandler(NULL); + } else + SetMessageHandler(&SsScene2206TestTube::handleMessage); + _collisionBoundsOffset = _drawOffset; + updateBounds(); +} + +uint32 SsScene2206TestTube::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x4806: + setGlobalVar(V_HAS_TEST_TUBE, 1); + setVisible(false); + SetMessageHandler(NULL); + break; + } + return messageResult; +} + +Scene2206::Scene2206(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + uint32 fileHash; + + SetUpdateHandler(&Scene::update); + SetMessageHandler(&Scene2206::handleMessage); + + if (getGlobalVar(V_LIGHTS_ON)) { + fileHash = 0x41983216; + _sprite1 = insertStaticSprite(0x2201266A, 100); + _sprite2 = insertStaticSprite(0x3406A333, 300); + _sprite3 = insertStaticSprite(0x24A223A2, 100); + _asDoorSpikes = insertSprite(0x26133023); + _asDoorSpikes->setClipRect(_sprite2->getDrawRect().x, 0, 640, 480); + setRectList(0x004B8AF8); + _ssButton = insertSprite(this, 0x0E038022, 100, 0); + insertScreenMouse(0x83212411); + _ssTestTube = insertSprite(this, 1100, /*464, 433, */0x5E00E262); + _asPlatform = insertSprite(0x085E25E0); + } else { + fileHash = 0xE0102A45; + _sprite1 = insertStaticSprite(0x1C1106B8, 100); + _sprite2 = insertStaticSprite(0x020462E0, 300); + _sprite3 = insertStaticSprite(0x900626A2, 100); + _asDoorSpikes = insertSprite(0x544822A8); + _asDoorSpikes->setClipRect(_sprite2->getDrawRect().x, 0, 640, 480); + setRectList(0x004B8B58); + _ssButton = insertSprite(this, 0x16882608, 100, 0); + insertScreenMouse(0x02A41E09); + _ssTestTube = insertSprite(this, 1100, /*464, 433, */0x52032563); + _asPlatform = insertSprite(0x317831A0); + } + + _asPlatform->setClipRect(_sprite2->getDrawRect().x, 0, _sprite3->getDrawRect().x2(), _sprite1->getDrawRect().y2()); + setBackground(fileHash); + setPalette(fileHash); + addEntity(_palette); + _palette->addBasePalette(fileHash, 0, 256, 0); + if (!getGlobalVar(V_LIGHTS_ON)) + _palette->addPalette(0x0263D144, 0, 65, 0); + addCollisionSprite(_ssTestTube); + + if (which < 0) { + // Restoring game + insertKlaymen(200, 430); + setMessageList(0x004B88A8); + } else if (which == 1) { + // Klaymen entering from the right + insertKlaymen(640, 430); + setMessageList(0x004B88B8); + } else if (which == 2) { + // Klaymen entering from the back + insertKlaymen(205, 396); + setMessageList(0x004B88C8); + _palette->addPalette(getGlobalVar(V_LIGHTS_ON) ? 0xB103B604 : 0x0263D144, 0, 65, 0); + klaymenBehindSpikes(); + playSound(0, 0x53B8284A); + } else if (which == 3) { + // Klaymen entering from reading a text column + insertKlaymen(kScene2206XPositions[getGlobalVar(V_CLICKED_COLUMN_INDEX)], 430); + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) + _klaymen->setDoDeltaX(1); + setMessageList(0x004B8A70); + } else { + // Klaymen entering from the left + insertKlaymen(0, 430); + setMessageList(0x004B88B0); + } + + _klaymen->setSoundFlag(true); + _klaymen->setKlaymenIdleTable2(); + +} + +Scene2206::~Scene2206() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); +} + +uint32 Scene2206::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x800C6694) + readClickedColumn(); + else if (param.asInteger() == 0x402064D8) + sendEntityMessage(_klaymen, 0x1014, _ssButton); + else if (param.asInteger() == 0x11C40840) { + if (getGlobalVar(V_SPIKES_RETRACTED)) + setMessageList(0x004B8948); + else + setMessageList(0x004B8970); + } + break; + case 0x4803: + sendMessage(_asPlatform, 0x4803, 0); + break; + case 0x480B: + if (sender == _ssButton) { + setGlobalVar(V_SPIKES_RETRACTED, getGlobalVar(V_SPIKES_RETRACTED) ? 0 : 1); + if (getGlobalVar(V_SPIKES_RETRACTED)) + sendMessage(_asDoorSpikes, 0x4808, 0); + else + sendMessage(_asDoorSpikes, 0x4809, 0); + } + break; + case 0x4826: + sendEntityMessage(_klaymen, 0x1014, _ssTestTube); + setMessageList(0x004B8988); + break; + case 0x482A: + klaymenBehindSpikes(); + break; + case 0x482B: + klaymenInFrontSpikes(); + break; + } + return messageResult; +} + +void Scene2206::klaymenInFrontSpikes() { + if (getGlobalVar(V_LIGHTS_ON)) { + _palette->addBasePalette(0x41983216, 0, 65, 0); + _palette->startFadeToPalette(12); + } + setSurfacePriority(_sprite1->getSurface(), 100); + setSurfacePriority(_sprite2->getSurface(), 300); + setSurfacePriority(_sprite3->getSurface(), 100); + setSurfacePriority(_asDoorSpikes->getSurface(), 200); + _klaymen->setClipRect(0, 0, 640, 480); +} + +void Scene2206::klaymenBehindSpikes() { + if (!getGlobalVar(V_LIGHTS_ON)) { + _palette->addBasePalette(0xB103B604, 0, 65, 0); + _palette->startFadeToPalette(12); + } + setSurfacePriority(_sprite1->getSurface(), 1100); + setSurfacePriority(_sprite2->getSurface(), 1300); + setSurfacePriority(_sprite3->getSurface(), 1100); + setSurfacePriority(_asDoorSpikes->getSurface(), 1200); + _klaymen->setClipRect(_sprite2->getDrawRect().x, 0, _sprite3->getDrawRect().x2(), _sprite1->getDrawRect().y2()); +} + +void Scene2206::readClickedColumn() { + setGlobalVar(V_CLICKED_COLUMN_INDEX, (_mouseClickPos.x - 354) / 96); + if (getGlobalVar(V_CLICKED_COLUMN_INDEX) > 2) + setGlobalVar(V_CLICKED_COLUMN_INDEX, 2); + setGlobalVar(V_CLICKED_COLUMN_ROW, (_mouseClickPos.y - 183) / 7); + setGlobalVar(V_COLUMN_TEXT_NAME, calcHash("stLineagex")); + setGlobalVar(V_COLUMN_BACK_NAME, 0); + if (ABS(kScene2206XPositions[getGlobalVar(V_CLICKED_COLUMN_INDEX)] - _klaymen->getX()) >= 144) + setMessageList2(kScene2206MessageIds1[getGlobalVar(V_CLICKED_COLUMN_INDEX)]); + else + setMessageList2(kScene2206MessageIds2[getGlobalVar(V_CLICKED_COLUMN_INDEX)]); +} + +static const uint32 kScene2207FileHashes[] = { + 0x33B1E12E, 0x33D1E12E, 0x3311E12E, + 0x3291E12E, 0x3191E12E, 0x3791E12E, + 0x3B91E12E, 0x2391E12E, 0x1391E12E, + 0x3BB1E12E, 0x23B1E12E, 0x13B1E12E +}; + +AsScene2207Elevator::AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 900), _parentScene(parentScene), _pointIndex(0), _destPointIndex(0), _destPointIndexDelta(0) { + + NPoint pt; + + _dataResource.load(0x00524846); + _pointArray = _dataResource.getPointArray(0x005B02B7); + pt = _dataResource.getPoint(0x403A82B1); + _x = pt.x; + _y = pt.y; + createSurface(1100, 129, 103); + startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, 0, 0); + _newStickFrameIndex = 0; + SetUpdateHandler(&AsScene2207Elevator::update); + SetMessageHandler(&AsScene2207Elevator::handleMessage); + SetSpriteUpdate(&AsScene2207Elevator::suSetPosition); +} + +AsScene2207Elevator::~AsScene2207Elevator() { + _vm->_soundMan->deleteSoundGroup(0x02700413); +} + +void AsScene2207Elevator::update() { + + if (_destPointIndex + _destPointIndexDelta > _pointIndex) { + _pointIndex++; + startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex); + _newStickFrameIndex = _pointIndex; + if (_destPointIndex + _destPointIndexDelta == _pointIndex) { + if (_destPointIndexDelta != 0) + _destPointIndexDelta = 0; + else { + _vm->_soundMan->deleteSound(0xD3B02847); + playSound(0, 0x53B8284A); + } + } + } + + if (_destPointIndex + _destPointIndexDelta < _pointIndex) { + _pointIndex--; + if (_pointIndex == 0) + sendMessage(_parentScene, 0x2003, 0); + startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex); + _newStickFrameIndex = _pointIndex; + if (_destPointIndex + _destPointIndexDelta == _pointIndex) { + if (_destPointIndexDelta != 0) + _destPointIndexDelta = 0; + else { + _vm->_soundMan->deleteSound(0xD3B02847); + playSound(0, 0x53B8284A); + } + } + } + + if (_pointIndex > 20 && _surface->getPriority() != 900) + sendMessage(_parentScene, 0x2002, 900); + else if (_pointIndex < 20 && _surface->getPriority() != 1100) + sendMessage(_parentScene, 0x2002, 1100); + + AnimatedSprite::update(); + + if (_destPointIndex + _destPointIndexDelta == _pointIndex && _isMoving) { + sendMessage(_parentScene, 0x2004, 0); + _isMoving = false; + } + +} + +void AsScene2207Elevator::suSetPosition() { + _x = (*_pointArray)[_pointIndex].x; + _y = (*_pointArray)[_pointIndex].y - 60; + updateBounds(); +} + +uint32 AsScene2207Elevator::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + moveToY(param.asInteger()); + break; + } + return messageResult; +} + +void AsScene2207Elevator::moveToY(int16 y) { + int16 minDistance = 480; + + if (!_pointArray || _pointArray->size() == 0) + return; + + for (uint i = 0; i < _pointArray->size(); i++) { + int16 distance = ABS(y - (*_pointArray)[i].y); + if (distance < minDistance) { + minDistance = distance; + _destPointIndex = i; + } + } + + if (_destPointIndex != _pointIndex) { + if (_destPointIndex == 0 || _destPointIndex == (int)_pointArray->size() - 1) + _destPointIndexDelta = 0; + else if (_destPointIndex < _pointIndex) + _destPointIndexDelta = -2; + else + _destPointIndexDelta = 2; + _vm->_soundMan->addSound(0x02700413, 0xD3B02847); + _vm->_soundMan->playSoundLooping(0xD3B02847); + } + + _isMoving = true; + +} + +AsScene2207Lever::AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX) + : AnimatedSprite(vm, 1100), _parentScene(parentScene) { + + _x = x; + _y = y; + createSurface(1010, 71, 73); + setDoDeltaX(doDeltaX); + startAnimation(0x80880090, 0, -1); + _newStickFrameIndex = 0; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2207Lever::handleMessage); +} + +uint32 AsScene2207Lever::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x3002: + gotoNextState(); + stopAnimation(); + break; + case 0x4807: + stLeverUp(); + break; + case 0x480F: + stLeverDown(); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +void AsScene2207Lever::stLeverDown() { + startAnimation(0x80880090, 1, -1); + playSound(0, 0x40581882); + FinalizeState(&AsScene2207Lever::stLeverDownEvent); +} + +void AsScene2207Lever::stLeverDownEvent() { + sendMessage(_parentScene, 0x480F, 0); +} + +void AsScene2207Lever::stLeverUp() { + startAnimation(0x80880090, 6, -1); + _playBackwards = true; + playSound(0, 0x40581882); + FinalizeState(&AsScene2207Lever::stLeverUpEvent); +} + +void AsScene2207Lever::stLeverUpEvent() { + sendMessage(_parentScene, 0x4807, 0); +} + +AsScene2207WallRobotAnimation::AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1200), _idle(true) { + + _x = 309; + _y = 320; + createSurface1(0xCCFD6090, 100); + startAnimation(0xCCFD6090, 0, -1); + _newStickFrameIndex = 0; + loadSound(1, 0x40330872); + loadSound(2, 0x72A2914A); + loadSound(3, 0xD4226080); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2207WallRobotAnimation::handleMessage); +} + +AsScene2207WallRobotAnimation::~AsScene2207WallRobotAnimation() { + _vm->_soundMan->deleteSoundGroup(0x80D00820); +} + +uint32 AsScene2207WallRobotAnimation::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (!_idle) { + if (param.asInteger() == 0x3423093) { + _vm->_soundMan->addSound(0x80D00820, 0x12121943); + _vm->_soundMan->playSoundLooping(0x12121943); + } else if (param.asInteger() == 0x834AB011) { + stopSound(0); + stopSound(1); + stopSound(2); + stopSound(3); + _vm->_soundMan->deleteSound(0x12121943); + } else if (param.asInteger() == 0x3A980501) + playSound(1); + else if (param.asInteger() == 0x2A2AD498) + playSound(2); + else if (param.asInteger() == 0xC4980008) + playSound(3); + else if (param.asInteger() == 0x06B84228) + playSound(0, 0xE0702146); + } + break; + case 0x2006: + stStartAnimation(); + break; + case 0x2007: + stStopAnimation(); + break; + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene2207WallRobotAnimation::stStartAnimation() { + if (!_idle) { + NextState(NULL); + } else { + startAnimation(0xCCFD6090, 0, -1); + _idle = false; + setVisible(true); + } +} + +void AsScene2207WallRobotAnimation::stStopAnimation() { + NextState(&AsScene2207WallRobotAnimation::cbStopAnimation); +} + +void AsScene2207WallRobotAnimation::cbStopAnimation() { + stopAnimation(); + stopSound(0); + stopSound(1); + stopSound(2); + stopSound(3); + _vm->_soundMan->deleteSound(0x12121943); + _idle = true; + setVisible(false); +} + +AsScene2207WallCannonAnimation::AsScene2207WallCannonAnimation(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1200), _idle(true) { + + _x = 309; + _y = 320; + createSurface1(0x8CAA0099, 100); + startAnimation(0x8CAA0099, 0, -1); + _newStickFrameIndex = 0; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2207WallCannonAnimation::handleMessage); +} + +uint32 AsScene2207WallCannonAnimation::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2006: + stStartAnimation(); + break; + case 0x2007: + stStopAnimation(); + break; + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene2207WallCannonAnimation::stStartAnimation() { + if (!_idle) { + NextState(NULL); + } else { + setVisible(true); + startAnimation(0x8CAA0099, 0, -1); + _idle = false; + } +} + +void AsScene2207WallCannonAnimation::stStopAnimation() { + NextState(&AsScene2207WallCannonAnimation::cbStopAnimation); +} + +void AsScene2207WallCannonAnimation::cbStopAnimation() { + stopAnimation(); + setVisible(false); + _idle = true; +} + +SsScene2207Symbol::SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index) + : StaticSprite(vm, fileHash, 100) { + + _x = 330; + _y = 246 + index * 50; + updatePosition(); +} + +Scene2207::Scene2207(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule), _klaymenAtElevator(true), _elevatorSurfacePriority(0) { + + _vm->gameModule()->initCannonSymbolsPuzzle(); + + if (!getSubVar(VA_IS_PUZZLE_INIT, 0x88460852)) + setSubVar(VA_IS_PUZZLE_INIT, 0x88460852, 1); + + SetMessageHandler(&Scene2207::handleMessage); + SetUpdateHandler(&Scene2207::update); + + insertKlaymen(0, 0); + _klaymen->setRepl(64, 0); + setMessageList(0x004B38E8); + _asElevator = insertSprite(this); + + if (getGlobalVar(V_LIGHTS_ON)) { + setBackground(0x88C00241); + setPalette(0x88C00241); + insertScreenMouse(0x00245884); + _ssMaskPart1 = insertStaticSprite(0xE20A28A0, 1200); + _ssMaskPart2 = insertStaticSprite(0x688F62A5, 1100); + _ssMaskPart3 = insertStaticSprite(0x0043B038, 1100); + _asTape = insertSprite(this, 4, 1100, 277, 428, 0x9148A011); + addCollisionSprite(_asTape); + _asLever = insertSprite(this, 527, 333, 0); + addCollisionSprite(_asLever); + _asWallRobotAnimation = insertSprite(this); + _asWallCannonAnimation = insertSprite(); + _asWallRobotAnimation->setVisible(false); + _asWallCannonAnimation->setVisible(false); + _ssButton = insertSprite(this, 0x2C4061C4, 100, 0); + _asLever->setClipRect(0, 0, _ssMaskPart3->getDrawRect().x2(), 480); + _klaymen->setClipRect(0, _ssMaskPart1->getDrawRect().y, 640, _ssMaskPart2->getDrawRect().y2()); + _asElevator->setClipRect(0, _ssMaskPart1->getDrawRect().y, 640, _ssMaskPart2->getDrawRect().y2()); + } else { + setGlobalVar(V_SEEN_SYMBOLS_NO_LIGHT, 1); + setBackground(0x05C02A55); + setPalette(0x05C02A55); + insertScreenMouse(0x02A51054); + _ssMaskPart1 = insertStaticSprite(0x980E46A4, 1200); + insertSprite(kScene2207FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_1, 0)], 0); + insertSprite(kScene2207FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_1, 1)], 1); + insertSprite(kScene2207FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_1, 2)], 2); + _asTape = NULL; + _asLever = NULL; + _asWallRobotAnimation = NULL; + _asWallCannonAnimation = NULL; + _ssButton = NULL; + _klaymen->setClipRect(0, _ssMaskPart1->getDrawRect().y, 640, 480); + _asElevator->setClipRect(0, _ssMaskPart1->getDrawRect().y, 640, 480); + } + + _dataResource.load(0x00524846); + setRectList(0x004B38B8); + + sendEntityMessage(_klaymen, 0x1014, _asElevator); + sendMessage(_klaymen, 0x2001, 0); + sendMessage(_asElevator, 0x2000, 480); + + loadSound(1, calcHash("fxFogHornSoft")); + +} + +void Scene2207::update() { + Scene::update(); + if (_elevatorSurfacePriority != 0) { + setSurfacePriority(_asElevator->getSurface(), _elevatorSurfacePriority); + _elevatorSurfacePriority = 0; + } + if (_klaymen->getY() == 423) + _klaymenAtElevator = _klaymen->getX() > 459 && _klaymen->getX() < 525; +} + +uint32 Scene2207::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x0014F275) { + if (_klaymenAtElevator) { + sendMessage(_asElevator, 0x2000, _mouseClickPos.y); + sendEntityMessage(_klaymen, 0x1014, _asElevator); + sendMessage(_klaymen, 0x2001, 0); + } else + cancelMessageList(); + } else if (param.asInteger() == 0x34569073) { + if (_klaymenAtElevator) { + _isKlaymenBusy = true; + sendMessage(_asElevator, 0x2000, 0); + sendEntityMessage(_klaymen, 0x1014, _asElevator); + sendMessage(_klaymen, 0x2001, 0); + } else + cancelMessageList(); + } else if (param.asInteger() == 0x4054C877) { + if (_klaymenAtElevator) { + sendMessage(_asElevator, 0x2000, 480); + sendEntityMessage(_klaymen, 0x1014, _asElevator); + sendMessage(_klaymen, 0x2001, 0); + } else + cancelMessageList(); + } else if (param.asInteger() == 0x0CBC6211) { + sendEntityMessage(_klaymen, 0x1014, _asElevator); + sendMessage(_klaymen, 0x2001, 0); + setRectList(0x004B38B8); + } else if (param.asInteger() == 0x402064D8) + sendEntityMessage(_klaymen, 0x1014, _ssButton); + else if (param.asInteger() == 0x231DA241) { + if (_ssButton) + setMessageList(0x004B38F0); + else + setMessageList(0x004B37D8); + } + break; + case 0x2002: + _elevatorSurfacePriority = param.asInteger(); + break; + case 0x2003: + _isKlaymenBusy = false; + break; + case 0x4807: + sendMessage(_asWallRobotAnimation, 0x2007, 0); + sendMessage(_asWallCannonAnimation, 0x2007, 0); + break; + case 0x480B: + if (sender == _ssButton) { + if (getSubVar(VA_LOCKS_DISABLED, 0x40119852)) { + setSubVar(VA_LOCKS_DISABLED, 0x40119852, 0); + playSound(0, calcHash("fx3LocksDisable")); + } else { + setSubVar(VA_LOCKS_DISABLED, 0x40119852, 1); + playSound(1); + } + } + break; + case 0x480F: + sendMessage(_asWallRobotAnimation, 0x2006, 0); + sendMessage(_asWallCannonAnimation, 0x2006, 0); + _asWallRobotAnimation->setVisible(true); + _asWallCannonAnimation->setVisible(true); + break; + case 0x4826: + if (sender == _asTape) { + if (_klaymen->getY() == 423) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004B3958); + } + } else if (_klaymenAtElevator) { + SetMessageHandler(&Scene2207::handleMessage2); + sendMessage(_asElevator, 0x2000, 347); + sendEntityMessage(_klaymen, 0x1014, _asElevator); + sendMessage(_klaymen, 0x2001, 0); + } + break; + } + return messageResult; +} + +uint32 Scene2207::handleMessage2(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2002: + _elevatorSurfacePriority = param.asInteger(); + break; + case 0x2004: + SetMessageHandler(&Scene2207::handleMessage); + sendMessage(_klaymen, 0x2005, 0); + sendEntityMessage(_klaymen, 0x1014, _asLever); + setMessageList(0x004B3920); + setRectList(0x004B3948); + break; + } + return messageResult; +} + +static const uint32 kScene2208FileHashes1[] = { + 0x041023CB, 0x041020CB, 0x041026CB, 0x04102ACB, + 0x041032CB, 0x041002CB +}; + +static const uint32 kScene2208FileHashes2[] = { + 0x091206C9, 0x091406C9, 0x091806C9, 0x090006C9, + 0x093006C9, 0x095006C9 +}; + +Scene2208::Scene2208(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _textResource(vm) { + + SpriteResource spriteResource(_vm); + const char *textStart, *textEnd; + + if (!getGlobalVar(V_COLUMN_TEXT_NAME)) + setGlobalVar(V_COLUMN_TEXT_NAME, calcHash("stLineagex")); + + _textResource.load(getGlobalVar(V_COLUMN_TEXT_NAME)); + + textStart = _textResource.getString(getGlobalVar(V_CLICKED_COLUMN_INDEX), textEnd); + while (textStart < textEnd) { + _strings.push_back(textStart); + textStart += strlen(textStart) + 1; + } + + _maxRowIndex = 8 + 10 * (3 - (getGlobalVar(V_COLUMN_TEXT_NAME) == calcHash("stLineagex") ? 1 : 0)); + + _background = new Background(_vm, 0); + _background->createSurface(0, 640, 528); + _background->getSpriteResource().getPosition().y = 480; + addBackground(_background); + setPalette(0x08100289); + addEntity(_palette); + insertPuzzleMouse(0x0028D089, 40, 600); + + _fontSurface = FontSurface::createFontSurface(_vm, 0x0800090C); + + _backgroundSurface = new BaseSurface(_vm, 0, 640, 480); + spriteResource.load(0x08100289, true); + _backgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0); + + _topBackgroundSurface = new BaseSurface(_vm, 0, 640, 192); + spriteResource.load(!getGlobalVar(V_COLUMN_BACK_NAME) + ? kScene2208FileHashes1[getGlobalVar(V_CLICKED_COLUMN_INDEX) % 6] + : getGlobalVar(V_COLUMN_BACK_NAME), true); + _topBackgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0); + + _bottomBackgroundSurface = new BaseSurface(_vm, 0, 640, 192); + spriteResource.load(kScene2208FileHashes2[getGlobalVar(V_CLICKED_COLUMN_INDEX) % 6], true); + _bottomBackgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0); + + SetUpdateHandler(&Scene2208::update); + SetMessageHandler(&Scene2208::handleMessage); + + _visibleRowsCount = 10; + _newRowIndex = (int16)getGlobalVar(V_CLICKED_COLUMN_ROW); + if (_newRowIndex + _visibleRowsCount > _maxRowIndex) + _newRowIndex = _maxRowIndex - _visibleRowsCount; + if (_newRowIndex < 6) + _newRowIndex = 0; + _rowScrollY = 0; + _backgroundScrollY = 48 * _newRowIndex; + _currRowIndex = _newRowIndex; + + for (int16 rowIndex = 0; rowIndex < _visibleRowsCount; rowIndex++) + drawRow(_newRowIndex + rowIndex); + + _background->getSurface()->getSysRect().y = _backgroundScrollY; + +} + +Scene2208::~Scene2208() { + delete _fontSurface; + delete _backgroundSurface; + delete _topBackgroundSurface; + delete _bottomBackgroundSurface; +} + +void Scene2208::update() { + + int16 mouseY = _vm->getMouseY(); + + if (mouseY < 48) { + if (_currRowIndex > 0) + _newRowIndex = _currRowIndex - 1; + } else if (mouseY > 432) { + if (_currRowIndex < _maxRowIndex - _visibleRowsCount) + _newRowIndex = _currRowIndex + 1; + } else { + if (_currRowIndex > _newRowIndex) + _newRowIndex = _currRowIndex; + } + + if (_currRowIndex < _newRowIndex) { + if (_rowScrollY == 0) + drawRow(_currRowIndex + _visibleRowsCount); + _backgroundScrollY += 4; + _rowScrollY += 4; + if (_rowScrollY == 48) { + _rowScrollY = 0; + _currRowIndex++; + } + _background->getSurface()->getSysRect().y = _backgroundScrollY; + } else if (_currRowIndex > _newRowIndex || _rowScrollY > 0) { + if (_rowScrollY == 0) { + drawRow(_currRowIndex - 1); + _currRowIndex--; + } + _backgroundScrollY -= 4; + if (_rowScrollY == 0) + _rowScrollY = 48; + _rowScrollY -= 4; + _background->getSurface()->getSysRect().y = _backgroundScrollY; + } + + Scene::update(); + +} + +uint32 Scene2208::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 40 || param.asPoint().x >= 600) + leaveScene(0); + break; + } + return messageResult; +} + +void Scene2208::drawRow(int16 rowIndex) { + NDrawRect sourceRect; + int16 y = (rowIndex * 48) % 528; + if (rowIndex < 4) { + sourceRect.x = 0; + sourceRect.y = y; + sourceRect.width = 640; + sourceRect.height = 48; + _background->getSurface()->copyFrom(_topBackgroundSurface->getSurface(), 0, y, sourceRect); + } else if (rowIndex > _maxRowIndex - 5) { + sourceRect.x = 0; + sourceRect.y = (rowIndex - _maxRowIndex + 4) * 48; + sourceRect.width = 640; + sourceRect.height = 48; + _background->getSurface()->copyFrom(_bottomBackgroundSurface->getSurface(), 0, y, sourceRect); + } else { + rowIndex -= 4; + sourceRect.x = 0; + sourceRect.y = (rowIndex * 48) % 480; + sourceRect.width = 640; + sourceRect.height = 48; + _background->getSurface()->copyFrom(_backgroundSurface->getSurface(), 0, y, sourceRect); + if (rowIndex < (int)_strings.size()) { + const char *text = _strings[rowIndex]; + _fontSurface->drawString(_background->getSurface(), 95, y, (const byte*)text); + } + } +} + +static const int16 kScene2242XPositions[] = { + 68, 158 +}; + +static const uint32 kScene2242MessageListIds2[] = { + 0x004B3CB8, 0x004B3CD8 +}; + +static const uint32 kScene2242MessageListIds1[] = { + 0x004B3CF8, 0x004B3D20 +}; + +Scene2242::Scene2242(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _isKlaymenInLight(false) { + + SetMessageHandler(&Scene2242::handleMessage); + SetUpdateHandler(&Scene2242::update); + + if (getGlobalVar(V_LIGHTS_ON)) { + setBackground(0x11840E24); + setPalette(0x11840E24); + insertScreenMouse(0x40E20110); + setRectList(0x004B3DC8); + } else { + setBackground(0x25848E24); + setPalette(0x25848E24); + addEntity(_palette); + _palette->copyBasePalette(0, 256, 0); + _palette->addPalette(0x68033B1C, 0, 65, 0); + insertScreenMouse(0x48E20250); + setRectList(0x004B3E18); + } + + _asTape = insertSprite(this, 10, 1100, 464, 435, 0x9148A011); + addCollisionSprite(_asTape); + + if (which < 0) { + // Restoring game + insertKlaymen(200, 430); + setMessageList(0x004B3C18); + } else if (which == 1) { + // Klaymen entering from looking through the window + insertKlaymen(530, 430); + setMessageList(0x004B3D60); + } else if (which == 2) { + // Klaymen returning from reading a text column + insertKlaymen(kScene2242XPositions[!getGlobalVar(V_CLICKED_COLUMN_INDEX) ? 0 : 1], 430); + setMessageList(0x004B3D48); + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) + _klaymen->setDoDeltaX(1); + } else { + // Klaymen entering from the left + insertKlaymen(0, 430); + setMessageList(0x004B3C20); + } + + _klaymen->setSoundFlag(true); + +} + +Scene2242::~Scene2242() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); +} + +void Scene2242::update() { + if (!getGlobalVar(V_LIGHTS_ON)) { + if (_isKlaymenInLight && _klaymen->getX() < 440) { + _palette->addBasePalette(0x68033B1C, 0, 65, 0); + _palette->startFadeToPalette(12); + _isKlaymenInLight = false; + } else if (!_isKlaymenInLight && _klaymen->getX() >= 440) { + _palette->addBasePalette(0x25848E24, 0, 65, 0); + _palette->startFadeToPalette(12); + _isKlaymenInLight = true; + } + } + Scene::update(); +} + +uint32 Scene2242::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x800C6694) + readClickedColumn(); + break; + case 0x4826: + if (sender == _asTape) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004B3D50); + } + break; + } + return messageResult; +} + +void Scene2242::readClickedColumn() { + int index; + if (_mouseClickPos.x < 108) { + setGlobalVar(V_COLUMN_TEXT_NAME, 0x04290188); + setGlobalVar(V_CLICKED_COLUMN_INDEX, 42); + setGlobalVar(V_COLUMN_BACK_NAME, calcHash("bgRecPanelStart1")); + index = 0; + } else { + setGlobalVar(V_COLUMN_TEXT_NAME, 0x04290188); + setGlobalVar(V_CLICKED_COLUMN_INDEX, 43); + setGlobalVar(V_COLUMN_BACK_NAME, calcHash("bgRecPanelStart2")); + index = 1; + } + setGlobalVar(V_CLICKED_COLUMN_ROW, (_mouseClickPos.y - 100) / 7); + if (ABS(_klaymen->getX() - kScene2242XPositions[index]) < 133) + setMessageList2(kScene2242MessageListIds1[index]); + else + setMessageList2(kScene2242MessageListIds2[index]); +} + +static const int16 kHallOfRecordsKlaymenXPos[] = { + 68, 157, 246, 335, + 424, 513, 602 +}; + +static const uint32 kHallOfRecordsSceneMessageListIds2[] = { + 0x004B2978, 0x004B2998, 0x004B29B8, 0x004B29D8, + 0x004B29F8, 0x004B2A18, 0x004B2A38 +}; + +static const uint32 kHallOfRecordsSceneMessageListIds1[] = { + 0x004B2A58, 0x004B2A80, 0x004B2AA8, 0x004B2AD0, + 0x004B2AF8, 0x004B2B20, 0x004B2B48 +}; + +HallOfRecordsScene::HallOfRecordsScene(NeverhoodEngine *vm, Module *parentModule, int which, uint32 hallOfRecordsInfoId) + : Scene(vm, parentModule) { + + _hallOfRecordsInfo = _vm->_staticData->getHallOfRecordsInfoItem(hallOfRecordsInfoId); + + SetMessageHandler(&HallOfRecordsScene::handleMessage); + SetUpdateHandler(&Scene::update); + + if (!getGlobalVar(V_LIGHTS_ON) && _hallOfRecordsInfo->bgFilename2) { + setRectList(0x004B2BF8); + setBackground(_hallOfRecordsInfo->bgFilename2); + setPalette(_hallOfRecordsInfo->bgFilename2); + insertScreenMouse(0x14320138); + } else { + setRectList(0x004B2BB8); + setBackground(_hallOfRecordsInfo->bgFilename1); + setPalette(_hallOfRecordsInfo->bgFilename1); + insertScreenMouse(0x63A40028); + } + + if (which < 0) { + // Restoring game + insertKlaymen(200, 430); + setMessageList(0x004B2900); + } else if (which == 1) { + // Klaymen entering from the right + insertKlaymen(640, 430); + setMessageList(0x004B2910); + } else if (which == 2) { + // Klaymen returning from reading a text column + insertKlaymen(kHallOfRecordsKlaymenXPos[getGlobalVar(V_CLICKED_COLUMN_INDEX) - _hallOfRecordsInfo->xPosIndex], 430); + setMessageList(0x004B2B70); + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) + _klaymen->setDoDeltaX(1); + } else { + // Klaymen entering from the left + insertKlaymen(0, 430); + setMessageList(0x004B2908); + } + + _klaymen->setSoundFlag(true); + _klaymen->setKlaymenIdleTable2(); + +} + +HallOfRecordsScene::~HallOfRecordsScene() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); +} + +uint32 HallOfRecordsScene::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x800C6694) + readClickedColumn(); + break; + } + return messageResult; +} + +void HallOfRecordsScene::readClickedColumn() { + int16 index = (_mouseClickPos.x - 23) / 89; + if (index >= _hallOfRecordsInfo->count) + setMessageList2(0x004B2920); + else { + setGlobalVar(V_CLICKED_COLUMN_INDEX, _hallOfRecordsInfo->xPosIndex + index); + setGlobalVar(V_CLICKED_COLUMN_ROW, (_mouseClickPos.y - 100) / 7); + setGlobalVar(V_COLUMN_TEXT_NAME, _hallOfRecordsInfo->txFilename); + if (index == 0 && _hallOfRecordsInfo->bgFilename3) + setGlobalVar(V_COLUMN_BACK_NAME, _hallOfRecordsInfo->bgFilename3); + else + setGlobalVar(V_COLUMN_BACK_NAME, 0); + if (ABS(_klaymen->getX() - kHallOfRecordsKlaymenXPos[index]) < 133) + setMessageList2(kHallOfRecordsSceneMessageListIds1[index]); + else + setMessageList2(kHallOfRecordsSceneMessageListIds2[index]); + } +} + +static const int16 kScene2247XPositions[] = { + 513, 602 +}; + +static const uint32 kScene2247MessageListIds2[] = { + 0x004B54A0, 0x004B54C0 +}; + +static const uint32 kScene2247MessageListIds1[] = { + 0x004B54E0, 0x004B5508 +}; + +Scene2247::Scene2247(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + SetMessageHandler(&Scene2247::handleMessage); + SetUpdateHandler(&Scene::update); + + if (getGlobalVar(V_LIGHTS_ON)) { + setRectList(0x004B5588); + setBackground(0x40339414); + setPalette(0x40339414); + insertScreenMouse(0x3941040B); + } else { + setRectList(0x004B55C8); + setBackground(0x071963E5); + setPalette(0x071963E5); + insertScreenMouse(0x14320138); + } + + if (which < 0) { + // Restoring game + insertKlaymen(200, 430); + setMessageList(0x004B5428); + } else if (which == 1) { + // Klaymen entering from the right + insertKlaymen(640, 430); + setMessageList(0x004B5438); + } else if (which == 2) { + // Klaymen returning from reading a text column + insertKlaymen(kScene2247XPositions[getGlobalVar(V_COLUMN_TEXT_NAME) == 0x0008E486 ? 0 : 1], 430); + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) + _klaymen->setDoDeltaX(1); + setMessageList(0x004B5530); + } else { + // Klaymen entering from the left + insertKlaymen(0, 430); + setMessageList(0x004B5430); + } + + _klaymen->setSoundFlag(true); + +} + +Scene2247::~Scene2247() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); +} + +uint32 Scene2247::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x800C6694) + readClickedColumn(); + break; + } + return messageResult; +} + +void Scene2247::readClickedColumn() { + int index; + if (_mouseClickPos.x < 553) { + setGlobalVar(V_COLUMN_TEXT_NAME, 0x0008E486); + setGlobalVar(V_COLUMN_BACK_NAME, calcHash("bgFatherHeader")); + index = 0; + } else { + setGlobalVar(V_COLUMN_TEXT_NAME, 0x03086004); + setGlobalVar(V_COLUMN_BACK_NAME, calcHash("bgQuaterHeader")); + index = 1; + } + setGlobalVar(V_CLICKED_COLUMN_INDEX, 0); + setGlobalVar(V_CLICKED_COLUMN_ROW, (_mouseClickPos.y - 100) / 7); + if (ABS(_klaymen->getX() - kScene2247XPositions[index]) < 133) + setMessageList2(kScene2247MessageListIds1[index]); + else + setMessageList2(kScene2247MessageListIds2[index]); +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module2200.h b/engines/neverhood/modules/module2200.h new file mode 100644 index 0000000000..af7171dd53 --- /dev/null +++ b/engines/neverhood/modules/module2200.h @@ -0,0 +1,375 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE2200_H +#define NEVERHOOD_MODULES_MODULE2200_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/modules/module1000.h" +#include "neverhood/graphics.h" + +namespace Neverhood { + +// Module2200 + +class Module2200 : public Module { +public: + Module2200(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module2200(); +protected: + int _sceneNum; + void createScene(int sceneNum, int which); + void updateScene(); + void createHallOfRecordsScene(int which, uint32 hallOfRecordsInfoId); +}; + +// Scene2201 + +static const NPoint kSsScene2201PuzzleCubePoints[] = { + {305, 305}, {321, 305}, {336, 305}, {305, 319}, + {321, 319}, {336, 319}, {305, 332}, {321, 332}, + {336, 333} +}; + +static const uint32 kSsScene2201PuzzleCubeFileHashes[] = { + 0x88134A44, 0xAA124340, 0xB8124602, 0xA902464C, + 0x890A4244, 0xA8124642, 0xB812C204, 0x381A4A4C +}; + +class AsScene2201CeilingFan : public AnimatedSprite { +public: + AsScene2201CeilingFan(NeverhoodEngine *vm); +}; + +class AsScene2201Door : public AnimatedSprite { +public: + AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen); +protected: + Klaymen *_klaymen; + Sprite *_ssDoorLight; + bool _isOpen; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stOpenDoor(); + void stCloseDoor(); +}; + +class SsScene2201PuzzleCube : public StaticSprite { +public: + SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex); +}; + +class Scene2201 : public Scene { +public: + Scene2201(NeverhoodEngine *vm, Module *parentModule, int which); + ~Scene2201(); +protected: + NRect _clipRects[2]; + Sprite *_ssDoorLight; + Sprite *_asDoor; + Sprite *_ssDoorButton; + Sprite *_asTape; + bool _isSoundPlaying; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene2202PuzzleCube : public StaticSprite { +public: + SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol); +protected: + Scene *_parentScene; + int16 _cubeSymbol; + int16 _cubePosition; + int16 _newX, _newY; + int16 _xDelta, _yDelta; + int16 _xIncr; + int16 _yIncr; + int16 _errValue; + int16 _counter; + int16 _xFlagPos; + bool _counterDirection; + bool _isMoving; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suMoveCubeX(); + void suMoveCubeY(); + void moveCube(int16 newCubePosition); + void stopMoving(); +}; + +class Scene2202 : public Scene { +public: + Scene2202(NeverhoodEngine *vm, Module *parentModule, int which); + ~Scene2202(); +protected: + Sprite *_ssMovingCube; + Sprite *_ssDoneMovingCube; + bool _isCubeMoving; + int16 _movingCubePosition; + int _surfacePriority; + bool _leaveScene; + bool _isSolved; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + int16 getFreeCubePosition(int16 index); + bool testIsSolved(); +}; + +class AsCommonKey : public AnimatedSprite { +public: + AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y); +protected: + Scene *_parentScene; + int _keyIndex; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2203Door : public AnimatedSprite { +public: + AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex); +protected: + Scene *_parentScene; + Sprite *_otherDoor; + uint _doorIndex; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void openDoor(); + void closeDoor(); +}; + +class Scene2203 : public Scene { +public: + Scene2203(NeverhoodEngine *vm, Module *parentModule, int which); + ~Scene2203(); +protected: + Sprite *_asLeftDoor; + Sprite *_asRightDoor; + Sprite *_ssSmallLeftDoor; + Sprite *_ssSmallRightDoor; + Sprite *_asTape; + Sprite *_asKey; + NRect _leftDoorClipRect; + NRect _rightDoorClipRect; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene2205DoorFrame : public StaticSprite { +public: + SsScene2205DoorFrame(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2205 : public Scene { +public: + Scene2205(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + SsCommonPressButton *_ssLightSwitch; + Sprite *_ssDoorFrame; + bool _isKlaymenInLight; + bool _isLightOn; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2206DoorSpikes : public StaticSprite { +public: + AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash); +protected: + int _deltaIndex; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suOpen(); + void suClose(); +}; + +class AsScene2206Platform : public StaticSprite { +public: + AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash); +protected: + int16 _yDelta; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suMoveDown(); +}; + +class SsScene2206TestTube : public StaticSprite { +public: + SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2206 : public Scene { +public: + Scene2206(NeverhoodEngine *vm, Module *parentModule, int which); + ~Scene2206(); +protected: + Sprite *_sprite1; + Sprite *_sprite2; + Sprite *_sprite3; + Sprite *_asDoorSpikes; + Sprite *_ssButton; + Sprite *_asPlatform; + Sprite *_ssTestTube; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void klaymenInFrontSpikes(); + void klaymenBehindSpikes(); + void readClickedColumn(); +}; + +class AsScene2207Elevator : public AnimatedSprite { +public: + AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene); + ~AsScene2207Elevator(); +protected: + Scene *_parentScene; + NPointArray *_pointArray; + int16 _pointIndex; + int16 _destPointIndex, _destPointIndexDelta; + bool _isMoving; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suSetPosition(); + void moveToY(int16 y); +}; + +class AsScene2207Lever : public AnimatedSprite { +public: + AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stLeverDown(); + void stLeverDownEvent(); + void stLeverUp(); + void stLeverUpEvent(); +}; + +class AsScene2207WallRobotAnimation : public AnimatedSprite { +public: + AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene); + ~AsScene2207WallRobotAnimation(); +protected: + bool _idle; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stStartAnimation(); + void stStopAnimation(); + void cbStopAnimation(); +}; + +class AsScene2207WallCannonAnimation : public AnimatedSprite { +public: + AsScene2207WallCannonAnimation(NeverhoodEngine *vm); +protected: + bool _idle; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stStartAnimation(); + void stStopAnimation(); + void cbStopAnimation(); +}; + +class SsScene2207Symbol : public StaticSprite { +public: + SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index); +}; + +class Scene2207 : public Scene { +public: + Scene2207(NeverhoodEngine *vm, Module *parentModule); +protected: + Sprite *_asElevator; + Sprite *_ssMaskPart1; + Sprite *_ssMaskPart2; + Sprite *_ssMaskPart3; + Sprite *_asTape; + Sprite *_asLever; + Sprite *_asWallRobotAnimation; + Sprite *_asWallCannonAnimation; + Sprite *_ssButton; + int _elevatorSurfacePriority; + bool _klaymenAtElevator; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage2(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2208 : public Scene { +public: + Scene2208(NeverhoodEngine *vm, Module *parentModule, int which); + ~Scene2208(); +protected: + FontSurface *_fontSurface; + BaseSurface *_backgroundSurface; + BaseSurface *_topBackgroundSurface; + BaseSurface *_bottomBackgroundSurface; + TextResource _textResource; + int16 _backgroundScrollY; + int16 _newRowIndex; + int16 _currRowIndex; + int16 _rowScrollY; + int16 _maxRowIndex; + int16 _visibleRowsCount; + Common::Array _strings; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void drawRow(int16 rowIndex); +}; + +class Scene2242 : public Scene { +public: + Scene2242(NeverhoodEngine *vm, Module *parentModule, int which); + ~Scene2242(); +protected: + Sprite *_asTape; + bool _isKlaymenInLight; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void readClickedColumn(); +}; + +class HallOfRecordsScene : public Scene { +public: + HallOfRecordsScene(NeverhoodEngine *vm, Module *parentModule, int which, uint32 hallOfRecordsInfoId); + ~HallOfRecordsScene(); +protected: + HallOfRecordsInfo *_hallOfRecordsInfo; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void readClickedColumn(); +}; + +class Scene2247 : public Scene { +public: + Scene2247(NeverhoodEngine *vm, Module *parentModule, int which); + ~Scene2247(); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void readClickedColumn(); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE2200_H */ diff --git a/engines/neverhood/modules/module2300.cpp b/engines/neverhood/modules/module2300.cpp new file mode 100644 index 0000000000..34eca14bea --- /dev/null +++ b/engines/neverhood/modules/module2300.cpp @@ -0,0 +1,186 @@ +/* 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/modules/module2300.h" +#include "neverhood/navigationscene.h" + +namespace Neverhood { + +static const uint32 kModule2300SoundList[] = { + 0x90805C50, 0x90804450, 0xB4005E60, 0x91835066, + 0x90E14440, 0x90F0D1C3, 0 +}; + +Module2300::Module2300(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule), _soundVolume(0) { + + _vm->_soundMan->addSoundList(0x1A214010, kModule2300SoundList); + _vm->_soundMan->setSoundListParams(kModule2300SoundList, true, 50, 600, 10, 150); + + _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; + + if (_isWallBroken) { + _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); + _vm->_soundMan->playSoundLooping(0x90F0D1C3); + } else { + _vm->_soundMan->setSoundParams(0x90F0D1C3, false, 0, 0, 0, 0); + } + + _vm->_soundMan->playTwoSounds(0x1A214010, 0x48498E46, 0x50399F64, 0); + _vm->_soundMan->playTwoSounds(0x1A214010, 0x41861371, 0x43A2507F, 0); + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else if (which == 1) + createScene(2, 0); + else if (which == 2) + createScene(3, 0); + else if (which == 3) + createScene(4, -1); + else if (which == 4) + createScene(1, 3); + else + createScene(0, 1); + +} + +Module2300::~Module2300() { + _vm->_soundMan->deleteGroup(0x1A214010); +} + +void Module2300::createScene(int sceneNum, int which) { + debug("Module2300::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + createNavigationScene(0x004B67B8, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + createNavigationScene(0x004B67E8, which); + if (_isWallBroken) { + _soundVolume = 15; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, 15); + } + break; + case 2: + _vm->gameState().sceneNum = 2; + createNavigationScene(0x004B6878, which); + break; + case 3: + _vm->gameState().sceneNum = 3; + if (getGlobalVar(V_WALL_BROKEN)) + createNavigationScene(0x004B68F0, which); + else { + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + createNavigationScene(0x004B68A8, which); + if (_isWallBroken) { + _soundVolume = 87; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, 87); + } + } + break; + case 4: + _vm->gameState().sceneNum = 4; + _vm->_soundMan->setTwoSoundsPlayFlag(true); + createSmackerScene(0x20080A0B, true, true, false); + break; + case 9999: + createDemoScene(); + break; + } + SetUpdateHandler(&Module2300::updateScene); + _childObject->handleUpdate(); +} + +void Module2300::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 1) + createScene(1, 4); + else + leaveModule(0); + break; + case 1: + if (_moduleResult == 1) + createScene(0, 0); + else if (_vm->isDemo()) + createScene(9999, 0); + else if (_moduleResult == 2) + createScene(2, 1); + else if (_moduleResult == 3) + createScene(1, 3); + else if (_moduleResult == 4) + createScene(3, 1); + else if (_moduleResult == 5) + leaveModule(3); + else + leaveModule(4); + break; + case 2: + if (_moduleResult == 1) + leaveModule(1); + else + createScene(1, 5); + break; + case 3: + if (_moduleResult == 1) + leaveModule(2); + else + createScene(1, 1); + break; + case 4: + _vm->_soundMan->setTwoSoundsPlayFlag(false); + createScene(1, 2); + break; + case 9999: + createScene(1, -1); + break; + } + } else { + switch (_sceneNum) { + case 1: + if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 4 && + navigationScene()->getFrameNumber() % 2) { + _soundVolume++; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + } + if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 0 && + navigationScene()->getFrameNumber() == 50) { + _vm->_soundMan->playTwoSounds(0x1A214010, 0x48498E46, 0x50399F64, 0); + _vm->_soundMan->setSoundVolume(0x48498E46, 70); + _vm->_soundMan->setSoundVolume(0x50399F64, 70); + } + break; + case 3: + if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getFrameNumber() % 2) { + _soundVolume--; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + } + break; + } + } +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module2300.h b/engines/neverhood/modules/module2300.h new file mode 100644 index 0000000000..0a1e1d57a4 --- /dev/null +++ b/engines/neverhood/modules/module2300.h @@ -0,0 +1,48 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE2300_H +#define NEVERHOOD_MODULES_MODULE2300_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +// Module2300 + +class Module2300 : public Module { +public: + Module2300(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module2300(); +protected: + int _sceneNum; + bool _isWallBroken; + int _soundVolume; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE2300_H */ diff --git a/engines/neverhood/modules/module2400.cpp b/engines/neverhood/modules/module2400.cpp new file mode 100644 index 0000000000..450812a5f3 --- /dev/null +++ b/engines/neverhood/modules/module2400.cpp @@ -0,0 +1,992 @@ +/* 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/modules/module2400.h" + +namespace Neverhood { + +Module2400::Module2400(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + _vm->_soundMan->addMusic(0x202D1010, 0xB110382D); + + if (which < 0) + createScene(_vm->gameState().sceneNum, _vm->gameState().which); + else + createScene(0, 0); + +} + +Module2400::~Module2400() { + _vm->_soundMan->deleteMusicGroup(0x202D1010); +} + +void Module2400::createScene(int sceneNum, int which) { + debug("Module2400::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _vm->_soundMan->stopMusic(0xB110382D, 0, 0); + _childObject = new Scene2401(_vm, this, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + _vm->_soundMan->startMusic(0xB110382D, 0, 2); + _childObject = new Scene2402(_vm, this, which); + break; + case 2: + _vm->gameState().sceneNum = 2; + _vm->_soundMan->startMusic(0xB110382D, 0, 0); + _childObject = new Scene2403(_vm, this, which); + break; + case 4: + _vm->gameState().sceneNum = 4; + _vm->_soundMan->stopMusic(0xB110382D, 0, 2); + _childObject = new DiskplayerScene(_vm, this, 0); + break; + case 5: + _vm->gameState().sceneNum = 5; + _vm->_soundMan->startMusic(0xB110382D, 0, 2); + _childObject = new Scene2406(_vm, this, which); + break; + case 6: + _vm->gameState().sceneNum = 6; + _vm->_soundMan->stopMusic(0xB110382D, 0, 2); + createSmackerScene(0x20D80001, true, true, false); + break; + case 7: + _vm->gameState().sceneNum = 7; + createStaticScene(0x81523218, 0x2321C81D); + break; + case 8: + _vm->gameState().sceneNum = 8; + createStaticScene(0x08100210, 0x00214089); + break; + case 9: + _vm->gameState().sceneNum = 9; + createStaticScene(0x8C020505, 0x205018C8); + break; + } + SetUpdateHandler(&Module2400::updateScene); + _childObject->handleUpdate(); +} + +void Module2400::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 1) + createScene(1, 0); + else + leaveModule(0); + break; + case 1: + if (_moduleResult == 1) + createScene(5, 0); + else if (_moduleResult == 2) + createScene(7, -1); + else + createScene(0, 1); + break; + case 2: + if (_moduleResult == 1) + createScene(9, -1); + else if (_moduleResult == 2) + createScene(6, -1); + else + createScene(5, 1); + break; + case 4: + createScene(5, 2); + break; + case 5: + if (_moduleResult == 1) + createScene(2, 0); + else if (_moduleResult == 2) + createScene(4, 0); + else if (_moduleResult == 3) + createScene(8, -1); + else + createScene(1, 1); + break; + case 6: + createScene(2, 2); + break; + case 7: + createScene(1, 2); + break; + case 8: + createScene(5, 3); + break; + case 9: + createScene(2, 1); + break; + } + } +} + +static const NPoint kScene2401Points[] = { + {384, 389}, {406, 389}, {429, 389}, + {453, 389}, {477, 389} +}; + +static const uint32 kScene2401FileHashes1[] = { + 0x02842920, 0x02882920, 0x02902920, + 0x02A02920, 0x02C02920, 0x02002920, + 0x03802920, 0x00802920, 0x06802920, + 0x03842920 +}; + +static const uint32 kScene2401FileHashes2[] = { + 0xD0910020, 0xD0910038, 0xD0910008, + 0xD0910068, 0xD09100A8, 0 +}; + +static const uint32 kScene2401FileHashes3[] = { + 0xD0910020, 0xD0910038, 0xD0910008, + 0xD0910068, 0xD09100A8, 0 +}; + +static const NRect kScene2401Rects[] = { + NRect(369, 331, 394, 389), + NRect(395, 331, 419, 389), + NRect(420, 331, 441, 389), + NRect(442, 331, 464, 389), + NRect(465, 331, 491, 389) +}; + +static const uint32 kAsScene2401WaterSpitFileHashes2[] = { + 0x5C044690, 0x5C644690, 0x5CA44690, + 0x5D244690, 0x5E244690 +}; + +static const uint32 kAsScene2401WaterSpitFileHashes1[] = { + 0xF4418408, 0xF4418808, 0xF4419008, + 0xF441A008, 0xCD4F8411 +}; + +AsScene2401WaterSpit::AsScene2401WaterSpit(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1200) { + + _x = 240; + _y = 447; + createSurface(100, 146, 74); + setVisible(false); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2401WaterSpit::handleMessage); + SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); +} + +uint32 AsScene2401WaterSpit::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x120A0013) + playSound(0, kAsScene2401WaterSpitFileHashes1[_soundIndex]); + break; + case 0x2000: + _x = 240; + _y = 447; + _soundIndex = getSubVar(VA_CURR_WATER_PIPES_LEVEL, param.asInteger()); + startAnimation(kAsScene2401WaterSpitFileHashes2[param.asInteger()], 0, -1); + setVisible(true); + playSound(0, 0x48640244); + break; + case 0x3002: + stopAnimation(); + setVisible(false); + break; + } + return messageResult; +} + +AsScene2401FlowingWater::AsScene2401FlowingWater(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1200), _isWaterFlowing(false) { + + _x = 88; + _y = 421; + createSurface1(0x10203116, 100); + setVisible(false); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2401FlowingWater::handleMessage); +} + +AsScene2401FlowingWater::~AsScene2401FlowingWater() { + _vm->_soundMan->deleteSoundGroup(0x40F11C09); +} + +uint32 AsScene2401FlowingWater::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (_isWaterFlowing && param.asInteger() == 0x02421405) + startAnimationByHash(0x10203116, 0x01084280, 0); + break; + case 0x2002: + if (!_isWaterFlowing) { + _vm->_soundMan->addSound(0x40F11C09, 0x980C1420); + _vm->_soundMan->playSoundLooping(0x980C1420); + startAnimation(0x10203116, 0, -1); + setVisible(true); + _isWaterFlowing = true; + } + break; + case 0x2003: + _vm->_soundMan->deleteSound(0x980C1420); + _isWaterFlowing = false; + break; + case 0x3002: + stopAnimation(); + setVisible(false); + break; + } + return messageResult; +} + +AsScene2401WaterFlushing::AsScene2401WaterFlushing(NeverhoodEngine *vm, int16 x, int16 y) + : AnimatedSprite(vm, 1200), _countdown(0), _flushLoopCount(0) { + + _x = x; + _y = y; + createSurface1(0xB8596884, 100); + setVisible(false); + SetUpdateHandler(&AsScene2401WaterFlushing::update); + SetMessageHandler(&AsScene2401WaterFlushing::handleMessage); +} + +void AsScene2401WaterFlushing::update() { + if (_countdown != 0 && (--_countdown) == 0) { + setDoDeltaX(_vm->_rnd->getRandomNumber(1)); + startAnimation(0xB8596884, 0, -1); + setVisible(true); + } + AnimatedSprite::update(); +} + +uint32 AsScene2401WaterFlushing::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (_flushLoopCount > 0 && param.asInteger() == 0x02421405) { + startAnimationByHash(0xB8596884, 0x01084280, 0); + _flushLoopCount--; + } + break; + case 0x2002: + if (param.asInteger() > 0) { + _flushLoopCount = param.asInteger() - 1; + _countdown = _vm->_rnd->getRandomNumber(3) + 1; + } + break; + case 0x3002: + stopAnimation(); + setVisible(false); + break; + } + return messageResult; +} + +AsScene2401Door::AsScene2401Door(NeverhoodEngine *vm, bool isOpen) + : AnimatedSprite(vm, 1100), _countdown(0), _isOpen(isOpen) { + + _x = 320; + _y = 240; + createSurface1(0x44687810, 100); + _newStickFrameIndex = STICK_LAST_FRAME; + if (_isOpen) { + stopAnimation(); + setVisible(false); + _countdown = 48; + } else { + startAnimation(0x44687810, 0, -1); + _newStickFrameIndex = 0; + } + SetUpdateHandler(&AsScene2401Door::update); + SetMessageHandler(&AsScene2401Door::handleMessage); +} + +void AsScene2401Door::update() { + if (_isOpen && _countdown != 0 && (--_countdown) == 0) { + _isOpen = false; + setVisible(true); + startAnimation(0x44687810, -1, -1); + _newStickFrameIndex = 0; + _playBackwards = true; + playSound(0, calcHash("fxDoorClose38")); + } + AnimatedSprite::update(); +} + +uint32 AsScene2401Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2004: + if (_isOpen) + _countdown = 168; + messageResult = _isOpen ? 1 : 0; + break; + case 0x3002: + gotoNextState(); + break; + case 0x4808: + if (!_isOpen) { + _countdown = 168; + _isOpen = true; + setVisible(true); + startAnimation(0x44687810, 0, -1); + playSound(0, calcHash("fxDoorOpen38")); + NextState(&AsScene2401Door::stDoorOpenFinished); + } + break; + } + return messageResult; +} + +void AsScene2401Door::stDoorOpenFinished() { + stopAnimation(); + setVisible(false); +} + +Scene2401::Scene2401(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _countdown1(0), _countdown2(0), _unkFlag(false), + _soundToggle(false), _asWaterSpitIndex(0) { + + _vm->gameModule()->initWaterPipesPuzzle(); + + SetMessageHandler(&Scene2401::handleMessage); + SetUpdateHandler(&Scene2401::update); + + setRectList(0x004B3140); + setBackground(0x8C030206); + setPalette(0x8C030206); + addEntity(_palette); + _palette->addBasePalette(0x8C030206, 0, 256, 0); + _palette->addPalette(0x91D3A391, 0, 65, 0); + insertScreenMouse(0x302028C8); + + _sprite1 = insertStaticSprite(0x2E068A23, 200); + insertStaticSprite(0x401410A6, 200); + _asFlowingWater = insertSprite(); + insertStaticSprite(0x90C0A4B4, 200); + _ssButton = insertSprite(this, 0x0092916A, 100, 0); + _ssFloorButton = insertSprite(this, 0x28001120, 0x00911068, 100, 0); + + for (uint i = 0; i < 5; i++) + _asWaterFlushing[i] = insertSprite(kScene2401Points[i].x, kScene2401Points[i].y); + + for (uint i = 0; i < 10; i++) { + _ssWaterPipes[i] = insertStaticSprite(kScene2401FileHashes1[i], 300); + _ssWaterPipes[i]->setVisible(false); + } + + _asWaterSpit[0] = insertSprite(); + _asWaterSpit[1] = insertSprite(); + + if (which < 0) { + // Restoring game + insertKlaymen(200, 447); + setMessageList(0x004B2F70); + _asDoor = insertSprite(false); + } else if (which == 1) { + // Klaymen entering from the back + insertKlaymen(280, 413); + setMessageList(0x004B2F80); + _palette->addBasePalette(0xB103B604, 0, 65, 0); + _palette->addPalette(0xB103B604, 0, 65, 0); + _asDoor = insertSprite(true); + } else { + // Klaymen entering from the left + insertKlaymen(-20, 447); + setMessageList(0x004B2F78); + _asDoor = insertSprite(false); + } + +} + +void Scene2401::update() { + + if (_countdown1 != 0 && (--_countdown1) == 0) { + if (_pipeStatus > 0 && _pipeStatus <= 10) + _ssWaterPipes[_pipeStatus - 1]->setVisible(false); + if (_pipeStatus >= 10) { + bool puzzleSolved = true, waterInside = false; + for (uint pipeIndex = 0; pipeIndex < 5; pipeIndex++) { + if (getSubVar(VA_CURR_WATER_PIPES_LEVEL, pipeIndex) != getSubVar(VA_GOOD_WATER_PIPES_LEVEL, pipeIndex)) + puzzleSolved = false; + if (getSubVar(VA_CURR_WATER_PIPES_LEVEL, pipeIndex) != 0) + waterInside = true; + } + if (puzzleSolved) { + setGlobalVar(V_NOTES_DOOR_UNLOCKED, 1); + setGlobalVar(V_NOTES_PUZZLE_SOLVED, 1); + sendMessage(_asDoor, 0x4808, 0); + } else if (waterInside) { + playPipeSound(0xD0431020); + for (uint i = 0; i < 5; i++) { + sendMessage(_asWaterFlushing[i], 0x2002, getSubVar(VA_CURR_WATER_PIPES_LEVEL, i)); + setSubVar(VA_CURR_WATER_PIPES_LEVEL, i, 0); + } + } + } else if (_pipeStatus >= 5) { + _ssWaterPipes[_pipeStatus]->setVisible(true); + _countdown1 = 8; + playPipeSound(kScene2401FileHashes3[getSubVar(VA_CURR_WATER_PIPES_LEVEL, _pipeStatus - 5)]); + } else { + _ssWaterPipes[_pipeStatus]->setVisible(true); + _countdown1 = _pipeStatus == 4 ? 16 : 8; + playPipeSound(kScene2401FileHashes3[getSubVar(VA_GOOD_WATER_PIPES_LEVEL, _pipeStatus)]); + } + _pipeStatus++; + } + + if (_countdown2 != 0 && (--_countdown2) == 0) + sendMessage(_asFlowingWater, 0x2003, 0); + + Scene::update(); + +} + +uint32 Scene2401::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x402064D8) + sendEntityMessage(_klaymen, 0x1014, _ssButton); + else if (param.asInteger() == 0x02144CB1) + sendEntityMessage(_klaymen, 0x1014, _ssFloorButton); + else if (param.asInteger() == 0x11C40840) { + if (getGlobalVar(V_NOTES_DOOR_UNLOCKED) && sendMessage(_asDoor, 0x2004, 0)) + setMessageList(0x004B3090); + else + setMessageList(0x004B30B0); + } else if (param.asInteger() == 0x412722C0) { + if (_countdown2 > 0 && getGlobalVar(V_HAS_TEST_TUBE)) { + _countdown2 = 144; + setMessageList(0x004B3020); + } else + setMessageList(0x004B3050); + } else if (param.asInteger() == 0x21142050) { + if (_unkFlag && _countdown1 == 0 && !getGlobalVar(V_NOTES_PUZZLE_SOLVED)) + setMessageList(0x004B2FA8); + else + setMessageList(0x004B2FC8); + } else if (param.asInteger() == 0x87441031) + setSurfacePriority(_sprite1->getSurface(), 1100); + else if (param.asInteger() == 0x80C40322) { + setSurfacePriority(_sprite1->getSurface(), 200); + cancelMessageList(); + _unkFlag = true; + } else if (param.asInteger() == 0x09C4B40A && _countdown2 > 12) + _countdown2 = 12; + break; + case 0x2000: + messageResult = 0; + for (uint32 i = 0; i < 5; i++) + if (kScene2401Rects[i].contains(_mouseClickPos.x, _mouseClickPos.y)) { + messageResult = i; + break; + } + break; + case 0x2001: + sendMessage(_asWaterSpit[_asWaterSpitIndex], 0x2000, param.asInteger()); + _asWaterSpitIndex = (_asWaterSpitIndex + 1) & 1; + incSubVar(VA_CURR_WATER_PIPES_LEVEL, param.asInteger(), 1); + if (getSubVar(VA_CURR_WATER_PIPES_LEVEL, param.asInteger()) >= 5) + setSubVar(VA_CURR_WATER_PIPES_LEVEL, param.asInteger(), 4); + break; + case 0x480B: + if (sender == _ssButton) { + _pipeStatus = 0; + _countdown1 = 8; + } else if (sender == _ssFloorButton && getGlobalVar(V_WATER_RUNNING)) { + _countdown2 = 144; + sendMessage(_asFlowingWater, 0x2002, 0); + playSound(0, 0xE1130324); + } + break; + case 0x482A: + _palette->addBasePalette(0xB103B604, 0, 65, 0); + _palette->startFadeToPalette(12); + break; + case 0x482B: + _palette->addBasePalette(0x91D3A391, 0, 65, 0); + _palette->startFadeToPalette(12); + break; + } + return messageResult; +} + +void Scene2401::playPipeSound(uint32 fileHash) { + playSound(_soundToggle ? 0 : 1, fileHash); + _soundToggle = !_soundToggle; +} + +static const uint32 kScene2402FileHashes[] = { + 0xD0910020, 0xD0910038, 0xD0910008, + 0xD0910068, 0xD09100A8 +}; + +AsScene2402Door::AsScene2402Door(NeverhoodEngine *vm, Scene *parentScene, bool isOpen) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _isOpen(isOpen), _countdown(0) { + + _x = 320; + _y = 240; + createSurface1(0x80495831, 100); + if (_isOpen) { + startAnimation(0x80495831, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + _countdown = 48; + } else { + stopAnimation(); + setVisible(false); + } + SetUpdateHandler(&AsScene2402Door::update); + SetMessageHandler(&AsScene2402Door::handleMessage); +} + +void AsScene2402Door::update() { + if (_isOpen && _countdown != 0 && (--_countdown) == 0) { + _isOpen = false; + setVisible(true); + startAnimation(0x80495831, -1, -1); + _playBackwards = true; + playSound(0, calcHash("fxDoorClose38")); + NextState(&AsScene2402Door::stDoorClosingFinished); + } + AnimatedSprite::update(); +} + +uint32 AsScene2402Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + if (_isOpen) + _countdown = 144; + messageResult = _isOpen ? 1 : 0; + break; + case 0x3002: + gotoNextState(); + break; + case 0x4808: + _countdown = 144; + _isOpen = true; + setVisible(true); + startAnimation(0x80495831, 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + playSound(0, calcHash("fxDoorOpen38")); + break; + } + return messageResult; +} + +void AsScene2402Door::stDoorClosingFinished() { + sendMessage(_parentScene, 0x2001, 0); + setVisible(false); +} + +AsScene2402TV::AsScene2402TV(NeverhoodEngine *vm, Klaymen *klaymen) + : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown1(0), _countdown2(0) { + + _x = 260; + _y = 210; + createSurface(100, 127, 90); + setDoDeltaX(1); + SetMessageHandler(&Sprite::handleMessage); + if (!getGlobalVar(V_TV_JOKE_TOLD)) { + loadSound(0, 0x58208810); + _countdown1 = 48; + startAnimation(0x4919397A, 0, -1); + _newStickFrameIndex = 0; + SetUpdateHandler(&AsScene2402TV::upWait); + } else { + int16 frameIndex; + if (_klaymen->getX() > 320) + _currFrameIndex = 29; + frameIndex = CLIP((_klaymen->getX() - _x + 150) / 10, 0, 29); + startAnimation(0x050A0103, frameIndex, -1); + _newStickFrameIndex = frameIndex; + _countdown1 = 0; + SetUpdateHandler(&AsScene2402TV::upFocusKlaymen); + } +} + +AsScene2402TV::~AsScene2402TV() { + _vm->_soundMan->deleteSoundGroup(0x01520123); +} + +void AsScene2402TV::upWait() { + if (_countdown1 != 0 && (--_countdown1) == 0) { + startAnimation(0x4919397A, 0, -1); + SetMessageHandler(&AsScene2402TV::hmJoke); + NextState(&AsScene2402TV::stJokeFinished); + } + AnimatedSprite::update(); +} + +void AsScene2402TV::upFocusKlaymen() { + int16 frameIndex = CLIP((_klaymen->getX() - _x + 150) / 10, 0, 29); + if (frameIndex != _currFrameIndex) { + if (frameIndex > _currFrameIndex) + _currFrameIndex++; + else if (frameIndex < _currFrameIndex) + _currFrameIndex--; + startAnimation(0x050A0103, _currFrameIndex, -1); + _newStickFrameIndex = _currFrameIndex; + if (_countdown2 == 0) { + _vm->_soundMan->addSound(0x01520123, 0xC42D4528); + _vm->_soundMan->playSoundLooping(0xC42D4528); + } + _countdown2 = 5; + } else if (_countdown2 != 0 && (--_countdown2 == 0)) + _vm->_soundMan->deleteSound(0xC42D4528); + AnimatedSprite::update(); +} + +void AsScene2402TV::stJokeFinished() { + setGlobalVar(V_TV_JOKE_TOLD, 1); + startAnimation(0x050A0103, 0, -1); + _newStickFrameIndex = 0; + SetUpdateHandler(&AsScene2402TV::upFocusKlaymen); +} + +uint32 AsScene2402TV::hmJoke(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x431EA0B0) + playSound(0); + break; + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +Scene2402::Scene2402(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _countdown(0), _soundToggle(false) { + + Sprite *tempSprite; + + SetMessageHandler(&Scene2402::handleMessage); + SetUpdateHandler(&Scene2402::update); + + setRectList(0x004AF900); + setBackground(0x81660220); + setPalette(0x81660220); + insertScreenMouse(0x6022481E); + _asTape = insertSprite(this, 9, 1100, 286, 409, 0x9148A011); + addCollisionSprite(_asTape); + _ssButton = insertSprite(this, 0x15288120, 100, 0); + + if (which < 0) { + // Restoring game + insertKlaymen(198, 404); + setMessageList(0x004AF7C8); + } else if (which == 1) { + // Klaymen entering from the right + insertKlaymen(660, 404); + setMessageList(0x004AF7D8); + } else if (which == 2) { + // Klaymen returning from looking through the window + insertKlaymen(409, 404); + _klaymen->setDoDeltaX(getGlobalVar(V_KLAYMEN_IS_DELTA_X) ? 1 : 0); + setMessageList(0x004AF888); + } else { + // Klaymen entering from the left + insertKlaymen(0, 404); + setMessageList(0x004AF7D0); + } + + tempSprite = insertStaticSprite(0x081A60A8, 1100); + _ssDoorFrame = (StaticSprite*)insertStaticSprite(0x406C0AE0, 1100); + _klaymen->setClipRect(_ssDoorFrame->getDrawRect().x, 0, 639, tempSprite->getDrawRect().y2()); + _asDoor = insertSprite(this, which == 0); + insertSprite(_klaymen); + insertStaticSprite(0x3A01A020, 200); + +} + +Scene2402::~Scene2402() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); +} + +void Scene2402::update() { + if (_countdown != 0 && (--_countdown) == 0) { + if (_pipeStatus >= 10) { + sendMessage(_asDoor, 0x4808, 0); + _ssDoorFrame->loadSprite(0x00B415E0, kSLFDefDrawOffset | kSLFDefPosition); + } else if (_pipeStatus >= 5) { + _countdown = 8; + playPipeSound(kScene2402FileHashes[getSubVar(VA_CURR_WATER_PIPES_LEVEL, _pipeStatus - 5)]); + } else { + _countdown = _pipeStatus == 4 ? 16 : 8; + playPipeSound(kScene2402FileHashes[getSubVar(VA_GOOD_WATER_PIPES_LEVEL, _pipeStatus)]); + } + _pipeStatus++; + } + Scene::update(); +} + +uint32 Scene2402::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x402064D8) + sendEntityMessage(_klaymen, 0x1014, _ssButton); + else if (param.asInteger() == 0x01C66840) { + if (sendMessage(_asDoor, 0x2000, 0)) + setMessageList(0x004AF800); + else + setMessageList(0x004AF818); + } + break; + case 0x2001: + _ssDoorFrame->loadSprite(0x406C0AE0, kSLFDefDrawOffset | kSLFDefPosition); + break; + case 0x480B: + if (sender == _ssButton) { + _pipeStatus = 0; + _countdown = 8; + } + break; + case 0x4826: + if (sender == _asTape) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004AF890); + } + break; + } + return messageResult; +} + +void Scene2402::playPipeSound(uint32 fileHash) { + playSound(_soundToggle ? 0 : 1, fileHash); + _soundToggle = !_soundToggle; +} + +Scene2403::Scene2403(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + Sprite *tempSprite1, *tempSprite2, *tempSprite3; + + SetMessageHandler(&Scene2403::handleMessage); + setBackground(0x0C05060C); + setPalette(0x0C05060C); + _palette->addPalette(0x414364B0, 0, 65, 0); + insertScreenMouse(0x506080C8); + _asTape = insertSprite(this, 2, 1100, 480, 454, 0x9148A011); + addCollisionSprite(_asTape); + _asLightCord = insertSprite(this, 0xA1095A10, 0x836D3813, 368, 200); + _asLightCord->setClipRect(0, 25, 640, 480); + + if (which < 0) { + // Restoring game + _isClimbingLadder = false; + insertKlaymen(220, 449); + setMessageList(0x004B5C98); + setRectList(0x004B5E18); + } else if (which == 1) { + // Klaymen returning from looking through the window + _isClimbingLadder = false; + insertKlaymen(433, 449); + setMessageList(0x004B5D70); + setRectList(0x004B5E18); + } else if (which == 2) { + // Klaymen standing around after the critter video + _isClimbingLadder = false; + insertKlaymen(440, 449); + _klaymen->setDoDeltaX(1); + setMessageList(0x004B5C98); + setRectList(0x004B5E18); + } else { + // Klaymen coming up from ladder + _isClimbingLadder = true; + insertKlaymen(122, 599); + setMessageList(0x004B5CA0); + setRectList(0x004B5E28); + } + + _ssButton = insertSprite(this, 0x3130B0EB, 100, 0); + tempSprite1 = insertStaticSprite(0x20C24220, 1100); + tempSprite2 = insertStaticSprite(0x03080900, 1300); + tempSprite3 = insertSprite(_klaymen); + tempSprite3->setClipRect(tempSprite1->getDrawRect().x, 0, 640, tempSprite2->getDrawRect().y2()); + _klaymen->setClipRect(tempSprite1->getDrawRect().x, 0, 640, tempSprite2->getDrawRect().y2()); + loadSound(1, calcHash("fxFogHornSoft")); +} + +uint32 Scene2403::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x040424D0) + sendEntityMessage(_klaymen, 0x1014, _ssButton); + else if (param.asInteger() == 0x180CE614) + sendEntityMessage(_klaymen, 0x1014, _asLightCord); + break; + case 0x2000: + _isClimbingLadder = true; + setRectList(0x004B5E28); + break; + case 0x2001: + _isClimbingLadder = false; + setRectList(0x004B5E18); + break; + case 0x480B: + if (sender == _ssButton) { + if (getSubVar(VA_LOCKS_DISABLED, 0x304008D2)) { + setSubVar(VA_LOCKS_DISABLED, 0x304008D2, 0); + playSound(0, calcHash("fx3LocksDisable")); + } else { + setSubVar(VA_LOCKS_DISABLED, 0x304008D2, 1); + playSound(1); + } + } + break; + case 0x480F: + if (sender == _asLightCord) + leaveScene(2); + break; + case 0x4826: + if (sender == _asTape && !_isClimbingLadder) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004B5D98); + } + break; + } + return messageResult; +} + +Scene2406::Scene2406(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + Sprite *tempSprite1, *tempSprite2; + + if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) + setGlobalVar(V_KEY3_LOCATION, 2); + + SetMessageHandler(&Scene2406::handleMessage); + + setRectList(0x004B78C8); + insertScreenMouse(0xB03001A8); + + if (getGlobalVar(V_KEY3_LOCATION) == 2) { + _asKey = insertSprite(this, 2, 1100, 560, 409); + addCollisionSprite(_asKey); + } + + _asTape = insertSprite(this, 5, 1100, 456, 409, 0x9148A011); + addCollisionSprite(_asTape); + tempSprite2 = insertStaticSprite(0x19625293, 1100); + _clipRects[0].x1 = 0; + _clipRects[0].y1 = 0; + _clipRects[0].x2 = tempSprite2->getDrawRect().x2(); + _clipRects[0].y2 = 480; + + if (getGlobalVar(V_SPIKES_RETRACTED)) { + setBackground(0x1A0B0304); + setPalette(0x1A0B0304); + tempSprite1 = insertStaticSprite(0x32923922, 1100); + } else { + setBackground(0x0A038595); + setPalette(0x0A038595); + tempSprite1 = insertStaticSprite(0x1712112A, 1100); + } + + tempSprite2 = insertStaticSprite(0x22300924, 1300); + _clipRects[1].x1 = tempSprite1->getDrawRect().x; + _clipRects[1].y1 = tempSprite2->getDrawRect().y; + _clipRects[1].x2 = 640; + _clipRects[1].y2 = 480; + + if (which < 0) { + // Restoring game + _isClimbingLadder = false; + insertKlaymen(307, 404, _clipRects, 2); + setMessageList(0x004B76C8); + setRectList(0x004B78C8); + } else if (which == 1) { + // Klaymen coming down the ladder + _isClimbingLadder = true; + insertKlaymen(253, -16, _clipRects, 2); + setMessageList(0x004B76D8); + setRectList(0x004B78D8); + } else if (which == 2) { + // Klaymen returning from the diskplayer + _isClimbingLadder = false; + insertKlaymen(480, 404, _clipRects, 2); + setMessageList(0x004B77C0); + setRectList(0x004B78C8); + } else if (which == 3) { + // Klaymen returning from looking through the window + _isClimbingLadder = false; + insertKlaymen(387, 404, _clipRects, 2); + setMessageList(0x004B7810); + setRectList(0x004B78C8); + } else { + // Klaymen entering from the left + _isClimbingLadder = false; + insertKlaymen(0, 404, _clipRects, 2); + setMessageList(0x004B76D0); + setRectList(0x004B78C8); + } + + tempSprite2 = insertSprite(_klaymen); + tempSprite2->setClipRect(_clipRects[1]); + +} + +uint32 Scene2406::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x41062804) { + if (getGlobalVar(V_SPIKES_RETRACTED)) + setMessageList(0x004B7758); + else + setMessageList(0x004B7738); + } + break; + case 0x2000: + _isClimbingLadder = true; + setRectList(0x004B78D8); + break; + case 0x2001: + _isClimbingLadder = false; + setRectList(0x004B78C8); + break; + case 0x4826: + if (sender == _asTape && !_isClimbingLadder) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004B77C8); + } else if (sender == _asKey && !_isClimbingLadder) { + sendEntityMessage(_klaymen, 0x1014, _asKey); + setMessageList(0x004B77D8); + } + break; + } + return messageResult; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module2400.h b/engines/neverhood/modules/module2400.h new file mode 100644 index 0000000000..b50fff91c4 --- /dev/null +++ b/engines/neverhood/modules/module2400.h @@ -0,0 +1,182 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE2400_H +#define NEVERHOOD_MODULES_MODULE2400_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/gamemodule.h" +#include "neverhood/modules/module1000.h" +#include "neverhood/modules/module1100.h" +#include "neverhood/modules/module1200.h" +#include "neverhood/modules/module2100.h" +#include "neverhood/modules/module2200.h" +#include "neverhood/modules/module2800.h" +#include "neverhood/diskplayerscene.h" + +namespace Neverhood { + +// Module2400 + +class Module2400 : public Module { +public: + Module2400(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module2400(); +protected: + int _sceneNum; + void createScene(int sceneNum, int which); + void updateScene(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2401WaterSpit : public AnimatedSprite { +public: + AsScene2401WaterSpit(NeverhoodEngine *vm); +protected: + int _soundIndex; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2401FlowingWater : public AnimatedSprite { +public: + AsScene2401FlowingWater(NeverhoodEngine *vm); + virtual ~AsScene2401FlowingWater(); +protected: + bool _isWaterFlowing; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2401WaterFlushing : public AnimatedSprite { +public: + AsScene2401WaterFlushing(NeverhoodEngine *vm, int16 x, int16 y); +protected: + int _countdown; + int _flushLoopCount; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2401Door : public AnimatedSprite { +public: + AsScene2401Door(NeverhoodEngine *vm, bool isOpen); +protected: + int _countdown; + bool _isOpen; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stDoorOpenFinished(); +}; + +class Scene2401 : public Scene { +public: + Scene2401(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_sprite1; + Sprite *_asFlowingWater; + Sprite *_ssButton; + Sprite *_ssFloorButton; + Sprite *_asWaterSpit[2]; + Sprite *_ssWaterPipes[10]; + Sprite *_asWaterFlushing[5]; + Sprite *_asDoor; + bool _soundToggle; + bool _unkFlag; + int _countdown1; + int _countdown2; + int _pipeStatus; + int _asWaterSpitIndex; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void playPipeSound(uint32 fileHash); +}; + +class AsScene2402Door : public AnimatedSprite { +public: + AsScene2402Door(NeverhoodEngine *vm, Scene *parentScene, bool isOpen); +protected: + Scene *_parentScene; + int _countdown; + bool _isOpen; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stDoorClosingFinished(); +}; + +class AsScene2402TV : public AnimatedSprite { +public: + AsScene2402TV(NeverhoodEngine *vm, Klaymen *klaymen); + virtual ~AsScene2402TV(); +protected: + Klaymen *_klaymen; + int _countdown1; + int _countdown2; + void upWait(); + void upFocusKlaymen(); + void stJokeFinished(); + uint32 hmJoke(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2402 : public Scene { +public: + Scene2402(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene2402(); +protected: + Sprite *_asDoor; + Sprite *_ssButton; + Sprite *_asTape; + StaticSprite *_ssDoorFrame; + int _pipeStatus; + int _countdown; + bool _soundToggle; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void playPipeSound(uint32 fileHash); +}; + +class Scene2403 : public Scene { +public: + Scene2403(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_ssButton; + Sprite *_asTape; + Sprite *_asKey; + Sprite *_asLightCord; + bool _isClimbingLadder; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2406 : public Scene { +public: + Scene2406(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_asTape; + Sprite *_asKey; + NRect _clipRects[2]; + bool _isClimbingLadder; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE2400_H */ diff --git a/engines/neverhood/modules/module2500.cpp b/engines/neverhood/modules/module2500.cpp new file mode 100644 index 0000000000..a997b5aab1 --- /dev/null +++ b/engines/neverhood/modules/module2500.cpp @@ -0,0 +1,546 @@ +/* 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/modules/module2500.h" +#include "neverhood/modules/module1600.h" + +namespace Neverhood { + +static const uint32 kScene2505StaticSprites[] = { + 0x4000A226, 0 +}; + +static const NRect kScene2505ClipRect = NRect(0, 0, 564, 480); + +static const uint32 kScene2506StaticSprites[] = { + 0x4027AF02, 0 +}; + +static const NRect kScene2506ClipRect = NRect(0, 0, 640, 441); + +static const uint32 kScene2508StaticSprites1[] = { + 0x2F08E610, 0xD844E6A0, 0 +}; + +static const NRect kScene2508ClipRect1 = NRect(0, 0, 594, 448); + +static const uint32 kScene2508StaticSprites2[] = { + 0x2F08E610, 0 +}; + +static const NRect kScene2508ClipRect2 = NRect(0, 0, 594, 448); + +Module2500::Module2500(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule), _soundIndex(0) { + + _vm->_soundMan->addMusic(0x29220120, 0x05343184); + _vm->_soundMan->startMusic(0x05343184, 0, 0); + SetMessageHandler(&Module2500::handleMessage); + + if (which < 0) + createScene(_vm->gameState().sceneNum, _vm->gameState().which); + else + createScene(0, 0); + + loadSound(0, 0x00880CCC); + loadSound(1, 0x00880CC0); + loadSound(2, 0x00880CCC); + loadSound(3, 0x00880CC0); + +} + +Module2500::~Module2500() { + _vm->_soundMan->deleteMusicGroup(0x29220120); +} + +void Module2500::createScene(int sceneNum, int which) { + debug("Module2500::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _childObject = new Scene2501(_vm, this, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + _vm->gameState().which = which; + createScene2704(which, 0x004B01B8, 220); + break; + case 2: + _vm->gameState().sceneNum = 2; + _vm->gameState().which = which; + if (getGlobalVar(V_WORLDS_JOINED)) + createScene2704(which, 0x004B01E0, 150); + else + createScene2704(which, 0x004B0208, 150); + break; + case 3: + _vm->gameState().sceneNum = 3; + _childObject = new Scene2504(_vm, this, which); + break; + case 4: + _vm->gameState().sceneNum = 4; + _vm->gameState().which = which; + createScene2704(which, 0x004B0230, 150, kScene2505StaticSprites, &kScene2505ClipRect); + break; + case 5: + setGlobalVar(V_CAR_DELTA_X, 1); + _vm->gameState().sceneNum = 5; + _vm->gameState().which = which; + createScene2704(which, 0x004B0268, 150, kScene2506StaticSprites, &kScene2506ClipRect); + break; + case 6: + _vm->gameState().sceneNum = 6; + _vm->gameState().which = which; + createScene2704(which, 0x004B02A0, 150); + break; + case 7: + _vm->gameState().sceneNum = 7; + _vm->gameState().which = which; + if (getGlobalVar(V_ENTRANCE_OPEN)) + createScene2704(which, 0x004B02C8, 150, kScene2508StaticSprites1, &kScene2508ClipRect1); + else + createScene2704(which, 0x004B02C8, 150, kScene2508StaticSprites2, &kScene2508ClipRect2); + break; + case 8: + _vm->gameState().sceneNum = 8; + _childObject = new Scene1608(_vm, this, which); + break; + case 9: + _vm->gameState().sceneNum = 9; + if (getGlobalVar(V_ENTRANCE_OPEN)) + createStaticScene(0xC62A0645, 0xA0641C6A); + else + createStaticScene(0x7A343546, 0x435427AB); + break; + } + SetUpdateHandler(&Module2500::updateScene); + _childObject->handleUpdate(); +} + +void Module2500::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 1) + createScene(2, 0); + else if (_moduleResult == 2) + createScene(1, 0); + else + leaveModule(0); + break; + case 1: + if (_moduleResult == 1) + createScene(3, -1); + else + createScene(0, 2); + break; + case 2: + if (_moduleResult == 1) + createScene(4, 0); + else + createScene(0, 1); + break; + case 3: + createScene(1, 1); + break; + case 4: + if (_moduleResult == 1) + createScene(5, 0); + else + createScene(2, 1); + break; + case 5: + if (_moduleResult == 1) + createScene(6, 0); + else + createScene(4, 1); + break; + case 6: + if (_moduleResult == 1) + createScene(7, 0); + else + createScene(5, 1); + break; + case 7: + if (_moduleResult == 1) + createScene(8, 1); + else + createScene(6, 1); + break; + case 8: + if (_moduleResult == 2) + createScene(9, -1); + else + createScene(7, 1); + break; + case 9: + createScene(8, 2); + break; + } + } +} + +uint32 Module2500::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Module::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x200D: + playSound(_soundIndex); + _soundIndex++; + if (_soundIndex >= 4) + _soundIndex = 0; + break; + } + return messageResult; +} + +void Module2500::createScene2704(int which, uint32 sceneInfoId, int16 value, const uint32 *staticSprites, const NRect *clipRect) { + _childObject = new Scene2704(_vm, this, which, sceneInfoId, value, staticSprites, clipRect); +} + +Scene2501::Scene2501(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B2628)); + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B264C)); + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B2670)); + + setGlobalVar(V_CAR_DELTA_X, 1); + SetUpdateHandler(&Scene2501::update); + setBackground(0x1B8E8115); + setPalette(0x1B8E8115); + _palette->addPalette(0x00128842, 65, 31, 65); + _palette->addPalette("paKlayRed", 0, 64, 0); + insertScreenMouse(0xE81111B0); + + _ssTrackShadowBackground = createSprite(0x99BE9015); // Don't add this to the sprite list + addEntity(_ssTrackShadowBackground); + _asCar = createSprite(this, 211, 400); // Create but don't add to the sprite list yet + _asIdleCarLower = insertSprite(211, 400); + _asIdleCarFull = insertSprite(211, 400); + insertStaticSprite(0xC42AC521, 1500); + + if (which < 0) { + // Restoring game + insertKlaymen(162, 393); + _kmScene2501 = _klaymen; + _klaymenInCar = false; + setMessageList(0x004B2538); + setRectList(0x004B2608); + SetMessageHandler(&Scene2501::handleMessage); + SetUpdateHandler(&Scene2501::update); + sendMessage(_asCar, 0x2009, 0); + _asCar->setVisible(false); + _currTrackIndex = 0; + } else if (which == 1 || which == 2) { + // 1: Klaymen entering riding the car on the left track + // 2: Klaymen entering riding the car on the bottom track + addSprite(_asCar); + _kmScene2501 = (Klaymen*)new KmScene2501(_vm, this, 275, 393); + _klaymenInCar = true; + sendMessage(_kmScene2501, 0x2000, 1); + _kmScene2501->setDoDeltaX(1); + SetMessageHandler(&Scene2501::hmRidingCar); + SetUpdateHandler(&Scene2501::upRidingCar); + _asIdleCarLower->setVisible(false); + _asIdleCarFull->setVisible(false); + _currTrackIndex = which; + } else { + // Klaymen entering the car + insertKlaymen(162, 393); + _kmScene2501 = _klaymen; + _klaymenInCar = false; + setMessageList(0x004B2538); + setRectList(0x004B2608); + SetMessageHandler(&Scene2501::handleMessage); + SetUpdateHandler(&Scene2501::update); + sendMessage(_asCar, 0x2009, 0); + _asCar->setVisible(false); + _currTrackIndex = 0; + } + + _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + insertSprite(_asCar); + + _newTrackIndex = -1; + _dataResource.load(calcHash("Ashooded")); + + _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); + _asCar->setPathPoints(_trackPoints); + + if (which >= 0 && _tracks[_currTrackIndex]->which2 == which) { + NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1]; + sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); + if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480) + sendMessage(_asCar, 0x2007, 150); + } else { + NPoint testPoint = (*_trackPoints)[0]; + sendMessage(_asCar, 0x2002, 0); + if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480) + sendMessage(_asCar, 0x2008, 150); + } + + _carStatus = 0; + +} + +Scene2501::~Scene2501() { + // Free sprites not currently in the sprite list + if (_klaymenInCar) + delete _kmScene2501; + else + delete _asCar; +} + +void Scene2501::update() { + Scene::update(); + if (_carStatus == 1) { + removeSprite(_klaymen); + addSprite(_asCar); + clearRectList(); + _klaymenInCar = true; + SetMessageHandler(&Scene2501::hmCarAtHome); + SetUpdateHandler(&Scene2501::upCarAtHome); + _asIdleCarLower->setVisible(false); + _asIdleCarFull->setVisible(false); + _asCar->setVisible(true); + sendMessage(_asCar, 0x2009, 0); + _asCar->handleUpdate(); + _klaymen = NULL; + _carStatus = 0; + } + updateKlaymenClipRect(); +} + +void Scene2501::upCarAtHome() { + Scene::update(); + if (_mouseClicked) { + if (_mouseClickPos.x <= 210 && _asCar->getX() == 211 && _asCar->getY() == 400) { + sendMessage(_asCar, 0x200A, 0); + SetUpdateHandler(&Scene2501::upGettingOutOfCar); + } else { + moveCarToPoint(_mouseClickPos); + SetMessageHandler(&Scene2501::hmRidingCar); + SetUpdateHandler(&Scene2501::upRidingCar); + } + _mouseClicked = false; + } + updateKlaymenClipRect(); +} + +void Scene2501::upGettingOutOfCar() { + Scene::update(); + if (_carStatus == 2) { + _klaymen = _kmScene2501; + removeSprite(_asCar); + addSprite(_klaymen); + _klaymenInCar = false; + SetMessageHandler(&Scene2501::handleMessage); + SetUpdateHandler(&Scene2501::update); + setRectList(0x004B2608); + _asIdleCarLower->setVisible(true); + _asIdleCarFull->setVisible(true); + _asCar->setVisible(false); + setMessageList(0x004B2570); + processMessageList(); + _klaymen->handleUpdate(); + _carStatus = 0; + } + updateKlaymenClipRect(); +} + +void Scene2501::upRidingCar() { + Scene::update(); + if (_mouseClicked) { + moveCarToPoint(_mouseClickPos); + _mouseClicked = false; + } +} + +uint32 Scene2501::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x60842040) + _carStatus = 1; + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + } + return messageResult; +} + +uint32 Scene2501::hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2005: + if (_tracks[_currTrackIndex]->which1 < 0 && _newTrackIndex >= 0) + changeTrack(); + else if (_tracks[_currTrackIndex]->which1 == 0) { + SetMessageHandler(&Scene2501::hmCarAtHome); + SetUpdateHandler(&Scene2501::upCarAtHome); + sendMessage(_asCar, 0x200F, 1); + } else if (_tracks[_currTrackIndex]->which1 > 0) + leaveScene(_tracks[_currTrackIndex]->which1); + break; + case 0x2006: + if (_tracks[_currTrackIndex]->which2 < 0 && _newTrackIndex >= 0) + changeTrack(); + else if (_tracks[_currTrackIndex]->which2 == 0) { + SetMessageHandler(&Scene2501::hmCarAtHome); + SetUpdateHandler(&Scene2501::upCarAtHome); + sendMessage(_asCar, 0x200F, 1); + } else if (_tracks[_currTrackIndex]->which2 > 0) + leaveScene(_tracks[_currTrackIndex]->which2); + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + } + return messageResult; +} + +uint32 Scene2501::hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x200A: + _carStatus = 2; + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + } + return messageResult; +} + +void Scene2501::moveCarToPoint(NPoint &pt) { + int minMatchTrackIndex, minMatchDistance; + _tracks.findTrackPoint(pt, minMatchTrackIndex, minMatchDistance, _dataResource); + if (minMatchTrackIndex >= 0 && minMatchTrackIndex != _currTrackIndex) { + _newTrackIndex = minMatchTrackIndex; + _clickPoint = pt; + if (_currTrackIndex == 0) + sendMessage(_asCar, 0x2003, _trackPoints->size() - 1); + else + sendMessage(_asCar, 0x2003, 0); + } else { + _newTrackIndex = -1; + sendMessage(_asCar, 0x2004, pt); + } +} + +void Scene2501::changeTrack() { + _currTrackIndex = _newTrackIndex; + _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); + _asCar->setPathPoints(_trackPoints); + if (_currTrackIndex == 0) + sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); + else + sendMessage(_asCar, 0x2002, 0); + sendPointMessage(_asCar, 0x2004, _clickPoint); + _newTrackIndex = -1; +} + +void Scene2501::updateKlaymenClipRect() { + if (_kmScene2501->getX() <= 211) + _kmScene2501->setClipRect(0, 0, 640, 480); + else + _kmScene2501->setClipRect(0, 0, 640, 388); +} + +SsScene2504Button::SsScene2504Button(NeverhoodEngine *vm) + : StaticSprite(vm, 1400), _countdown(0), _isSoundPlaying(false) { + + loadSprite(0x070220D9, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); + setVisible(false); + loadSound(0, 0x4600204C); + loadSound(1, 0x408C0034); + loadSound(2, 0x44043000); + loadSound(3, 0x44045000); + SetMessageHandler(&SsScene2504Button::handleMessage); + SetUpdateHandler(&SsScene2504Button::update); +} + +void SsScene2504Button::update() { + updatePosition(); + if (_isSoundPlaying && !isSoundPlaying(0) && !isSoundPlaying(1)) { + playSound(3); + setVisible(false); + _isSoundPlaying = false; + } + if (_countdown != 0 && (--_countdown) == 0) { + if (getSubVar(VA_LOCKS_DISABLED, 0x01180951)) + playSound(0); + else + playSound(1); + _isSoundPlaying = true; + } +} + +uint32 SsScene2504Button::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown == 0 && !_isSoundPlaying) { + setVisible(true); + _countdown = 2; + if (getSubVar(VA_LOCKS_DISABLED, 0x01180951)) + setSubVar(VA_LOCKS_DISABLED, 0x01180951, 0); + else + setSubVar(VA_LOCKS_DISABLED, 0x01180951, 1); + playSound(2); + } + messageResult = 1; + break; + } + return messageResult; +} + +Scene2504::Scene2504(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + Sprite *ssButton; + + setBackground(0x90791B80); + setPalette(0x90791B80); + ssButton = insertSprite(); + addCollisionSprite(ssButton); + insertPuzzleMouse(0x91B8490F, 20, 620); + SetMessageHandler(&Scene2504::handleMessage); + SetUpdateHandler(&Scene::update); +} + +uint32 Scene2504::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) + leaveScene(0); + break; + } + return messageResult; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module2500.h b/engines/neverhood/modules/module2500.h new file mode 100644 index 0000000000..07db7907d5 --- /dev/null +++ b/engines/neverhood/modules/module2500.h @@ -0,0 +1,101 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE2500_H +#define NEVERHOOD_MODULES_MODULE2500_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/modules/module1000.h" +#include "neverhood/modules/module1600.h" +#include "neverhood/modules/module2700.h" + +namespace Neverhood { + +// Module2500 + +class Module2500 : public Module { +public: + Module2500(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module2500(); +protected: + int _sceneNum; + int _soundIndex; + void createScene(int sceneNum, int which); + void updateScene(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void createScene2704(int which, uint32 sceneInfoId, int16 value, const uint32 *staticSprites = NULL, const NRect *clipRect = NULL); +}; + +class Scene2501 : public Scene { +public: + Scene2501(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene2501(); +protected: + AsCommonCar *_asCar; + Sprite *_ssTrackShadowBackground; + Sprite *_asCarShadow; + Sprite *_asCarConnectorShadow; + Sprite *_asCarTrackShadow; + Sprite *_asIdleCarLower; + Sprite *_asIdleCarFull; + Klaymen *_kmScene2501; + Tracks _tracks; + NPointArray *_trackPoints; + int _currTrackIndex; + NPoint _clickPoint; + int _newTrackIndex; + int _carStatus; + bool _klaymenInCar; + void update(); + void upCarAtHome(); + void upGettingOutOfCar(); + void upRidingCar(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender); + void moveCarToPoint(NPoint &pt); + void changeTrack(); + void updateKlaymenClipRect(); +}; + +class SsScene2504Button : public StaticSprite { +public: + SsScene2504Button(NeverhoodEngine *vm); +protected: + int _countdown; + bool _isSoundPlaying; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2504 : public Scene { +public: + Scene2504(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE2500_H */ diff --git a/engines/neverhood/modules/module2600.cpp b/engines/neverhood/modules/module2600.cpp new file mode 100644 index 0000000000..b8dbf7bff1 --- /dev/null +++ b/engines/neverhood/modules/module2600.cpp @@ -0,0 +1,348 @@ +/* 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/modules/module2600.h" + +namespace Neverhood { + +static const uint32 kModule2600SoundList[] = { + 0xB288D450, + 0x90804450, + 0x99801500, + 0xB288D455, + 0x93825040, + 0 +}; + +Module2600::Module2600(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + if (which < 0) + createScene(_vm->gameState().sceneNum, -1); + else if (which == 1) + createScene(4, 1); + else + createScene(0, 1); + + _vm->_soundMan->addSoundList(0x40271018, kModule2600SoundList); + _vm->_soundMan->setSoundListParams(kModule2600SoundList, true, 50, 600, 5, 150); + _vm->_soundMan->playTwoSounds(0x40271018, 0x41861371, 0x43A2507F, 0); + +} + +Module2600::~Module2600() { + _vm->_soundMan->deleteGroup(0x40271018); +} + +void Module2600::createScene(int sceneNum, int which) { + debug("Module2600::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + createNavigationScene(0x004B8608, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + createNavigationScene(0x004B8638, which); + break; + case 2: + _vm->gameState().sceneNum = 2; + createNavigationScene(0x004B86C8, which); + break; + case 3: + _vm->gameState().sceneNum = 3; + if (getGlobalVar(V_CREATURE_ANGRY)) + createNavigationScene(0x004B8758, which); + else + createNavigationScene(0x004B86F8, which); + break; + case 4: + _vm->gameState().sceneNum = 4; + createNavigationScene(0x004B87B8, which); + break; + case 6: + _vm->gameState().sceneNum = 6; + createNavigationScene(0x004B8698, which); + break; + case 7: + _vm->gameState().sceneNum = 7; + _vm->_soundMan->deleteGroup(0x40271018); + createSmackerScene(0x30090001, true, true, false); + break; + case 8: + _vm->gameState().sceneNum = 8; + _childObject = new Scene2609(_vm, this, which); + break; + case 1002: + _vm->gameState().sceneNum = 2; + if (getGlobalVar(V_FRUIT_COUNTING_INDEX) == 1) + createSmackerScene(0x018C0404, true, true, false); + else if (getGlobalVar(V_FRUIT_COUNTING_INDEX) == 2) + createSmackerScene(0x018C0407, true, true, false); + else + createSmackerScene(0x818C0405, true, true, false); + if (getGlobalVar(V_FRUIT_COUNTING_INDEX) >= 2) + setGlobalVar(V_FRUIT_COUNTING_INDEX, 0); + else + incGlobalVar(V_FRUIT_COUNTING_INDEX, +1); + break; + case 1003: + _vm->gameState().sceneNum = 3; + createSmackerScene(0x001C0007, true, true, false); + break; + case 1006: + _vm->gameState().sceneNum = 6; + if (getGlobalVar(V_WATER_RUNNING)) + createSmackerScene(0x049A1181, true, true, false); + else + createSmackerScene(0x04981181, true, true, false); + break; + case 1008: + _vm->gameState().sceneNum = 8; + if (getGlobalVar(V_WATER_RUNNING)) + createSmackerScene(0x42B80941, true, true, false); + else + createSmackerScene(0x42980941, true, true, false); + break; + case 9999: + createDemoScene(); + break; + } + SetUpdateHandler(&Module2600::updateScene); + _childObject->handleUpdate(); +} + +void Module2600::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == 1) + createScene(1, 3); + else + leaveModule(0); + break; + case 1: + if (_moduleResult == 0) + createScene(6, 0); + else if (_moduleResult == 1) + createScene(0, 0); + else if (_moduleResult == 2) + createScene(2, 1); + else if (_moduleResult == 3) + createScene(3, 0); + break; + case 2: + if (_moduleResult == 0) + createScene(1, 0); + else if (_moduleResult == 1) { + if (_vm->isDemo()) + createScene(9999, -1); + else + createScene(1002, -1); + } + break; + case 3: + if (_moduleResult == 0) { + if (getGlobalVar(V_CREATURE_ANGRY)) + createScene(4, 0); + else + createScene(1003, -1); + } else if (_moduleResult == 2) + createScene(1, 1); + else if (_moduleResult == 3) { + if (getGlobalVar(V_CREATURE_ANGRY)) + createScene(4, 0); + else { + setGlobalVar(V_CREATURE_ANGRY, 1); + createScene(7, -1); + } + } + break; + case 4: + if (_moduleResult == 0) + leaveModule(1); + else + createScene(3, 1); + break; + case 6: + if (_moduleResult == 0) { + if (_vm->isDemo()) + createScene(9999, -1); + else + createScene(1006, -1); + } + else if (_moduleResult == 1) + createScene(1, 2); + break; + case 7: + leaveModule(0); + break; + case 8: + createScene(1008, -1); + break; + case 1002: + createScene(2, 1); + break; + case 1003: + createScene(3, 0); + break; + case 1006: + createScene(8, -1); + break; + case 1008: + createScene(6, 0); + break; + case 9999: + createScene(_vm->gameState().sceneNum, -1); + break; + } + } +} + +SsScene2609Button::SsScene2609Button(NeverhoodEngine *vm, Scene *parentScene) + : StaticSprite(vm, 1400), _parentScene(parentScene), _countdown(0) { + + SetUpdateHandler(&SsScene2609Button::update); + SetMessageHandler(&SsScene2609Button::handleMessage); + + loadSprite(0x825A6923, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); + if (!getGlobalVar(V_WATER_RUNNING)) + setVisible(false); + loadSound(0, 0x10267160); + loadSound(1, 0x7027FD64); + loadSound(2, 0x44043000); + loadSound(3, 0x44045000); +} + +void SsScene2609Button::update() { + updatePosition(); + if (_countdown != 0 && (--_countdown == 0)) { + if (getGlobalVar(V_WATER_RUNNING)) { + setGlobalVar(V_WATER_RUNNING, 0); + sendMessage(_parentScene, 0x2001, 0); + } else { + setGlobalVar(V_WATER_RUNNING, 1); + sendMessage(_parentScene, 0x2002, 0); + } + } +} + +uint32 SsScene2609Button::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown == 0) { + sendMessage(_parentScene, 0x2000, 0); + if (getGlobalVar(V_WATER_RUNNING)) { + setVisible(false); + playSound(3); + playSound(1); + _countdown = 12; + } else { + setVisible(true); + playSound(2); + playSound(0); + _countdown = 96; + } + } + messageResult = 1; + break; + } + return messageResult; +} + +AsScene2609Water::AsScene2609Water(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1000) { + + _x = 240; + _y = 420; + setDoDeltaX(1); + createSurface1(0x9C210C90, 1200); + setClipRect(260, 260, 400, 368); + _vm->_soundMan->addSound(0x08526C36, 0xDC2769B0); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2609Water::handleMessage); + if (getGlobalVar(V_WATER_RUNNING)) + sendMessage(this, 0x2002, 0); +} + +AsScene2609Water::~AsScene2609Water() { + _vm->_soundMan->deleteSoundGroup(0x08526C36); +} + +uint32 AsScene2609Water::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2001: + stopAnimation(); + setVisible(false); + _vm->_soundMan->stopSound(0xDC2769B0); + break; + case 0x2002: + startAnimation(0x9C210C90, 0, -1); + setVisible(true); + _vm->_soundMan->playSoundLooping(0xDC2769B0); + break; + } + return messageResult; +} + +Scene2609::Scene2609(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _isBusy(false) { + + SetUpdateHandler(&Scene::update); + SetMessageHandler(&Scene2609::handleMessage); + + setBackground(0x51409A16); + setPalette(0x51409A16); + _asWater = insertSprite(); + _ssButton = insertSprite(this); + addCollisionSprite(_ssButton); + insertPuzzleMouse(0x09A1251C, 20, 620); + insertStaticSprite(0x02138002, 1200); + insertStaticSprite(0x825E2827, 1200); +} + +uint32 Scene2609::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && !_isBusy) + leaveScene(0); + break; + case 0x2000: + _isBusy = true; + break; + case 0x2001: + _isBusy = false; + sendMessage(_asWater, 0x2001, 0); + break; + case 0x2002: + _isBusy = false; + sendMessage(_asWater, 0x2002, 0); + break; + } + return 0; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module2600.h b/engines/neverhood/modules/module2600.h new file mode 100644 index 0000000000..d972e0fb0d --- /dev/null +++ b/engines/neverhood/modules/module2600.h @@ -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 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE2600_H +#define NEVERHOOD_MODULES_MODULE2600_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +// Module2600 + +class Module2600 : public Module { +public: + Module2600(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module2600(); +protected: + int _sceneNum; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +class SsScene2609Button : public StaticSprite { +public: + SsScene2609Button(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2609Water : public AnimatedSprite { +public: + AsScene2609Water(NeverhoodEngine *vm); + virtual ~AsScene2609Water(); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2609 : public Scene { +public: + Scene2609(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + bool _isBusy; + Sprite *_asWater; + Sprite *_ssButton; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE2600_H */ diff --git a/engines/neverhood/modules/module2700.cpp b/engines/neverhood/modules/module2700.cpp new file mode 100644 index 0000000000..8b69bc050e --- /dev/null +++ b/engines/neverhood/modules/module2700.cpp @@ -0,0 +1,1211 @@ +/* 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/modules/module2700.h" +#include "neverhood/gamemodule.h" +#include "neverhood/modules/module1000.h" + +namespace Neverhood { + +static const NRect kScene2710ClipRect = NRect(0, 0, 626, 480); + +static const uint32 kScene2710StaticSprites[] = { + 0x0D2016C0, + 0 +}; + +static const NRect kScene2711ClipRect = NRect(0, 0, 521, 480); + +static const uint32 kScene2711FileHashes1[] = { + 0, + 0x100801A1, + 0x201081A0, + 0x006800A4, + 0x40390120, + 0x000001B1, + 0x001000A1, + 0 +}; + +static const uint32 kScene2711FileHashes2[] = { + 0, + 0x40403308, + 0x71403168, + 0x80423928, + 0x224131A8, + 0x50401328, + 0x70423328, + 0 +}; + +static const uint32 kScene2711FileHashes3[] = { + 0, + 0x1088A021, + 0x108120E5, + 0x18A02321, + 0x148221A9, + 0x10082061, + 0x188820E1, + 0 +}; + +static const NRect kScene2724ClipRect = NRect(0, 141, 640, 480); + +static const uint32 kScene2724StaticSprites[] = { + 0xC20D00A5, + 0 +}; + +static const NRect kScene2725ClipRect = NRect(0, 0, 640, 413); + +static const uint32 kScene2725StaticSprites[] = { + 0xC20E00A5, + 0 +}; + +Module2700::Module2700(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule), _soundIndex(0), _raidoMusicInitialized(false) { + + _vm->_soundMan->addMusic(0x42212411, 0x04020210); + _vm->_soundMan->startMusic(0x04020210, 24, 2); + SetMessageHandler(&Module2700::handleMessage); + + if (which < 0) { + which = _vm->gameState().which; + // Scenes 0, 30 and 31 are "normal" scenes, whereas the other scenes are tracks. + // "gameState().which" indicates which track the car is at. + if (_vm->gameState().sceneNum == 0 || _vm->gameState().sceneNum == 30 || _vm->gameState().sceneNum == 31) + which = -1; + createScene(_vm->gameState().sceneNum, which); + } else + createScene(0, 0); + + loadSound(0, 0x00880CCC); + loadSound(1, 0x00880CC0); + loadSound(2, 0x00880CCC); + loadSound(3, 0x00880CC0); + +} + +Module2700::~Module2700() { + _vm->_soundMan->deleteGroup(0x42212411); +} + +void Module2700::createScene(int sceneNum, int which) { + debug("Module2700::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _vm->gameState().which = which; + _childObject = new Scene2701(_vm, this, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + _vm->gameState().which = which; + _childObject = new Scene2702(_vm, this, which); + break; + case 2: + _vm->gameState().sceneNum = 2; + _vm->gameState().which = which; + if (which == 6 || which == 7) + createScene2703(which, 0x004B1710); + else if (which == 4 || which == 5) + createScene2703(which, 0x004B1738); + else if (which == 2 || which == 3) + createScene2703(which, 0x004B1760); + else + createScene2703(which, 0x004B1788); + break; + case 3: + _vm->gameState().sceneNum = 3; + _vm->gameState().which = which; + createScene2704(which, 0x004B17B0, 150); + break; + case 4: + _vm->gameState().sceneNum = 4; + _vm->gameState().which = which; + createScene2704(which, 0x004B17D8, 150); + break; + case 5: + _vm->gameState().sceneNum = 5; + _vm->gameState().which = which; + if (which >= 4) + _childObject = new Scene2706(_vm, this, which); + else if (which == 2 || which == 3) + createScene2704(which, 0x004B1828, 150); + else + createScene2704(which, 0x004B1800, 150); + break; + case 6: + _vm->gameState().sceneNum = 6; + _vm->gameState().which = which; + createScene2704(which, 0x004B1850, 150); + break; + case 7: + _vm->gameState().sceneNum = 7; + _vm->gameState().which = which; + if (which == 2 || which == 3) + createScene2704(which, 0x004B1878, 150); + else + createScene2704(which, 0x004B18A0, 150); + break; + case 8: + _vm->gameState().sceneNum = 8; + _vm->gameState().which = which; + if (which == 2 || which == 3) + createScene2704(which, 0x004B18C8, 150); + else + createScene2704(which, 0x004B18F0, 150); + break; + case 9: + _vm->gameState().sceneNum = 9; + _vm->gameState().which = which; + createScene2704(which, 0x004B1918, 150, kScene2710StaticSprites, &kScene2710ClipRect); + break; + case 10: + _vm->gameState().sceneNum = 10; + _vm->gameState().which = which; + _vm->gameModule()->initTestTubes2Puzzle(); + _scene2711StaticSprites[0] = kScene2711FileHashes1[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2)]; + _scene2711StaticSprites[1] = kScene2711FileHashes2[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1)]; + _scene2711StaticSprites[2] = kScene2711FileHashes3[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0)]; + _scene2711StaticSprites[3] = 0x0261282E; + _scene2711StaticSprites[4] = 0x9608E5A0; + _scene2711StaticSprites[5] = 0; + createScene2704(which, 0x004B1950, 150, _scene2711StaticSprites, &kScene2711ClipRect); + break; + case 11: + _vm->gameState().sceneNum = 11; + _vm->gameState().which = which; + createScene2704(which, 0x004B19E0, 150); + break; + case 12: + _vm->gameState().sceneNum = 12; + _vm->gameState().which = which; + createScene2704(which, 0x004B1A08, 150); + break; + case 13: + _vm->gameState().sceneNum = 13; + _vm->gameState().which = which; + createScene2704(which, 0x004B1A30, 150); + break; + case 14: + _vm->gameState().sceneNum = 14; + _vm->gameState().which = which; + if (which == 4 || which == 5) + createScene2704(which, 0x004B1A58, 150); + else if (which == 2 || which == 3) + createScene2704(which, 0x004B1A80, 150); + else + createScene2704(which, 0x004B1AA8, 150); + break; + case 15: + _vm->gameState().sceneNum = 15; + _vm->gameState().which = which; + if (which == 4 || which == 5) + createScene2704(which, 0x004B1AD0, 150); + else if (which == 2 || which == 3) + createScene2704(which, 0x004B1AF8, 150); + else + createScene2704(which, 0x004B1B20, 150); + break; + case 16: + _vm->gameState().sceneNum = 16; + _vm->gameState().which = which; + if (which == 4 || which == 5) + createScene2704(which, 0x004B1B48, 150); + else if (which == 2 || which == 3) + createScene2704(which, 0x004B1B70, 150); + else + createScene2704(which, 0x004B1B98, 150); + break; + case 17: + _vm->gameState().sceneNum = 17; + _vm->gameState().which = which; + if (which == 4 || which == 5) + createScene2704(which, 0x004B1BC0, 150); + else if (which == 2 || which == 3) + createScene2704(which, 0x004B1BE8, 150); + else + createScene2704(which, 0x004B1C10, 150); + break; + case 18: + _vm->gameState().sceneNum = 18; + _vm->gameState().which = which; + if (which == 2 || which == 3) + createScene2704(which, 0x004B1C38, 150); + else + createScene2704(which, 0x004B1C60, 150); + break; + case 19: + _vm->gameState().sceneNum = 19; + _vm->gameState().which = which; + if (which == 2 || which == 3) + createScene2704(which, 0x004B1CB0, 150); + else + createScene2704(which, 0x004B1C88, 150); + break; + case 20: + _vm->gameState().sceneNum = 20; + _vm->gameState().which = which; + if (which == 2 || which == 3) + createScene2704(which, 0x004B1CD8, 150); + else + createScene2704(which, 0x004B1D00, 150); + break; + case 21: + _vm->gameState().sceneNum = 21; + _vm->gameState().which = which; + createScene2704(which, 0x004B1D28, 150); + break; + case 22: + _vm->gameState().sceneNum = 22; + _vm->gameState().which = which; + createScene2704(which, 0x004B1D50, 150); + break; + case 23: + _vm->gameState().sceneNum = 23; + _vm->gameState().which = which; + createScene2704(which, 0x004B1D78, 150, kScene2724StaticSprites, &kScene2724ClipRect); + break; + case 24: + _vm->gameState().sceneNum = 24; + _vm->gameState().which = which; + createScene2704(which, 0x004B1DB0, 150, kScene2725StaticSprites, &kScene2725ClipRect); + break; + case 25: + _vm->gameState().sceneNum = 25; + _vm->gameState().which = which; + createScene2704(which, 0x004B1DE8, 150); + break; + case 26: + _vm->gameState().sceneNum = 26; + _vm->gameState().which = which; + createScene2704(which, 0x004B1E10, 150); + break; + case 27: + _vm->gameState().sceneNum = 27; + _vm->gameState().which = which; + createScene2704(which, 0x004B1E38, 150); + break; + case 28: + _vm->gameState().sceneNum = 28; + _vm->gameState().which = which; + createScene2704(which, 0x004B1E60, 150); + break; + case 30: + _vm->gameState().sceneNum = 30; + createStaticScene(0x09507248, 0x0724C09D); + break; + case 31: + _vm->gameState().sceneNum = 31; + _childObject = new Scene2732(_vm, this); + break; + } + SetUpdateHandler(&Module2700::updateScene); + _childObject->handleUpdate(); +} + +#define SceneLinkIf(moduleResult, sceneNum, which) \ + if (_moduleResult == moduleResult) { createScene(sceneNum, which); break; } + +void Module2700::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + SceneLinkIf(1, 1, 0); + leaveModule(0); + break; + case 1: + SceneLinkIf(1, 14, 1); + SceneLinkIf(2, 2, 2); + SceneLinkIf(3, 14, 3); + SceneLinkIf(4, 2, 6); + SceneLinkIf(5, 2, 4); + createScene(0, 1); + break; + case 2: + SceneLinkIf(1, 5, 0); + SceneLinkIf(2, 1, 2); + SceneLinkIf(3, 5, 2); + SceneLinkIf(4, 1, 5); + SceneLinkIf(5, 5, 4); + SceneLinkIf(6, 1, 4); + SceneLinkIf(7, 11, 0); + createScene(3, 0); + break; + case 3: + createScene(2, 0); + break; + case 4: + SceneLinkIf(1, 7, 2); + createScene(5, 5); + break; + case 5: + SceneLinkIf(1, 6, 0); + SceneLinkIf(2, 2, 3); + SceneLinkIf(3, 8, 2); + SceneLinkIf(4, 2, 5); + SceneLinkIf(5, 4, 0); + SceneLinkIf(6, 7, 0); + createScene(2, 1); + break; + case 6: + SceneLinkIf(1, 8, 0); + createScene(5, 1); + break; + case 7: + SceneLinkIf(1, 8, 3); + SceneLinkIf(2, 4, 1); + SceneLinkIf(3, 9, 0); + createScene(5, 6); + break; + case 8: + SceneLinkIf(1, 10, 0); + SceneLinkIf(2, 5, 3); + SceneLinkIf(3, 7, 1); + createScene(6, 1); + break; + case 9: + SceneLinkIf(1, 10, 1); + createScene(7, 3); + break; + case 10: + SceneLinkIf(1, 9, 1); + createScene(8, 1); + break; + case 11: + SceneLinkIf(1, 12, 0); + createScene(2, 7); + break; + case 12: + SceneLinkIf(1, 13, 0); + createScene(11, 1); + break; + case 13: + SceneLinkIf(1, 30, 0); + createScene(12, 1); + break; + case 14: + SceneLinkIf(1, 1, 1); + SceneLinkIf(2, 15, 3); + SceneLinkIf(3, 1, 3); + SceneLinkIf(4, 15, 5); + SceneLinkIf(5, 22, 0); + createScene(15, 1); + break; + case 15: + SceneLinkIf(1, 14, 0); + SceneLinkIf(2, 16, 3); + SceneLinkIf(3, 14, 2); + SceneLinkIf(4, 16, 5); + SceneLinkIf(5, 14, 4); + createScene(16, 1); + break; + case 16: + SceneLinkIf(1, 15, 0); + SceneLinkIf(2, 17, 3); + SceneLinkIf(3, 15, 2); + SceneLinkIf(4, 17, 5); + SceneLinkIf(5, 15, 4); + createScene(17, 1); + break; + case 17: + SceneLinkIf(1, 16, 0); + SceneLinkIf(2, 18, 3); + SceneLinkIf(3, 16, 2); + SceneLinkIf(4, 20, 1); + SceneLinkIf(5, 16, 4); + createScene(18, 1); + break; + case 18: + SceneLinkIf(1, 17, 0); + SceneLinkIf(2, 19, 2); + SceneLinkIf(3, 17, 2); + createScene(19, 0); + break; + case 19: + SceneLinkIf(1, 20, 2); + SceneLinkIf(2, 18, 2); + SceneLinkIf(3, 20, 0); + createScene(18, 0); + break; + case 20: + SceneLinkIf(1, 17, 4); + SceneLinkIf(2, 19, 1); + SceneLinkIf(3, 21, 0); + createScene(19, 3); + break; + case 21: + _vm->_soundMan->deleteMusic(_musicFileHash); + _vm->_soundMan->startMusic(0x04020210, 0, 2); + _vm->_soundMan->deleteSoundGroup(0x42212411); + createScene(20, 3); + break; + case 22: + SceneLinkIf(1, 23, 0); + createScene(14, 5); + break; + case 23: + SceneLinkIf(1, 24, 0); + createScene(22, 1); + break; + case 24: + SceneLinkIf(1, 25, 0); + createScene(23, 1); + break; + case 25: + SceneLinkIf(1, 26, 0); + createScene(24, 1); + break; + case 26: + SceneLinkIf(1, 27, 0); + createScene(25, 1); + break; + case 27: + SceneLinkIf(1, 28, 0); + createScene(26, 1); + break; + case 28: + SceneLinkIf(1, 31, 0); + createScene(27, 1); + break; + case 30: + createScene(13, 1); + break; + case 31: + createScene(28, 1); + break; + } + } else { + switch (_sceneNum) { + case 21: + if (!_raidoMusicInitialized) { + _vm->_soundMan->stopMusic(0x04020210, 0, 1); + _vm->gameModule()->initRadioPuzzle(); + _musicFileHash = getGlobalVar(V_GOOD_RADIO_MUSIC_NAME); + _vm->_soundMan->addMusic(0x42212411, _musicFileHash); + _vm->_soundMan->startMusic(_musicFileHash, 0, 2); + _vm->_soundMan->addSound(0x42212411, 0x44014282); + _vm->_soundMan->setSoundParams(0x44014282, true, 120, 360, 72, 0); + _raidoMusicInitialized = true; + } + break; + } + } +} + +uint32 Module2700::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Module::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x200D: + playSound(_soundIndex); + _soundIndex++; + if (_soundIndex >= 4) + _soundIndex = 0; + break; + } + return messageResult; +} + +void Module2700::createScene2703(int which, uint32 trackInfoId) { + _childObject = new Scene2703(_vm, this, which, trackInfoId); +} + +void Module2700::createScene2704(int which, uint32 trackInfoId, int16 value, const uint32 *staticSprites, const NRect *clipRect) { + _childObject = new Scene2704(_vm, this, which, trackInfoId, value, staticSprites, clipRect); +} + +static const NPoint kCarShadowOffsets[] = { + {-63, 3}, {-48, 40}, {-33, 58}, + { 0, 65}, { 40, 53}, { 56, 27}, + { 63, 0}, {-30, 26}, { 0, 30}, + { 26, 25} +}; + +SsCommonTrackShadowBackground::SsCommonTrackShadowBackground(NeverhoodEngine *vm, uint32 fileHash) + : StaticSprite(vm, 0) { + + loadSprite(fileHash, kSLFDefDrawOffset | kSLFDefPosition, 0); +} + +AsCommonCarShadow::AsCommonCarShadow(NeverhoodEngine *vm, AnimatedSprite *asCar, BaseSurface *shadowSurface, uint index) + : AnimatedSprite(vm, 1100), _asCar(asCar), _index(index), _animFileHash(0) { + + SetUpdateHandler(&AsCommonCarShadow::update); + createShadowSurface(shadowSurface, 211, 147, 100); + updateShadow(); +} + +void AsCommonCarShadow::update() { + updateShadow(); + AnimatedSprite::update(); +} + +void AsCommonCarShadow::updateShadow() { + if (_asCar->getFrameIndex() != _currFrameIndex || _asCar->getCurrAnimFileHash() != _animFileHash) { + uint32 fileHash = _asCar->getCurrAnimFileHash(); + if (fileHash == 0x35698F78 || fileHash == 0x192ADD30 || fileHash == 0x9C220DA4 || + fileHash == 0x9966B138 || fileHash == 0xB579A77C || fileHash == 0xA86A9538 || + fileHash == 0xD4220027 || fileHash == 0xD00A1364 || fileHash == 0xD4AA03A4 || + fileHash == 0xF46A0324) { + startAnimation(fileHash, _asCar->getFrameIndex(), -1); + _newStickFrameIndex = _asCar->getFrameIndex(); + } + _animFileHash = fileHash; + } + _x = _asCar->getX() + kCarShadowOffsets[_index].x; + _y = _asCar->getY() + kCarShadowOffsets[_index].y; + if (!_asCar->getVisible()) { + startAnimation(0x1209E09F, 0, -1); + _newStickFrameIndex = 0; + } + setDoDeltaX(_asCar->isDoDeltaX() ? 1 : 0); +} + +AsCommonCarConnectorShadow::AsCommonCarConnectorShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, uint index) + : AnimatedSprite(vm, 1100), _asCar(asCar), _index(index) { + + SetUpdateHandler(&AsCommonCarConnectorShadow::update); + createShadowSurface1(shadowSurface, 0x60281C10, 150); + startAnimation(0x60281C10, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; +} + +void AsCommonCarConnectorShadow::update() { + _x = _asCar->getX() + kCarShadowOffsets[_index].x; + _y = _asCar->getY() + kCarShadowOffsets[_index].y; + AnimatedSprite::update(); +} + +AsCommonCarTrackShadow::AsCommonCarTrackShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, int16 frameIndex) + : AnimatedSprite(vm, 1100), _asCar(asCar) { + + SetUpdateHandler(&AsCommonCarTrackShadow::update); + createShadowSurface1(shadowSurface, 0x0759129C, 100); + startAnimation(0x0759129C, frameIndex, -1); + _newStickFrameIndex = frameIndex; +} + +void AsCommonCarTrackShadow::update() { + _x = _asCar->getX(); + _y = _asCar->getY(); + AnimatedSprite::update(); +} + +Scene2701::Scene2701(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + Sprite *tempSprite; + + NRect clipRect; + TrackInfo *tracks = _vm->_staticData->getTrackInfo(0x004B2240); + setGlobalVar(V_CAR_DELTA_X, 1); + + setBackground(tracks->bgFilename); + setPalette(tracks->bgFilename); + _palette->addPalette(calcHash("paPodFloor"), 65, 31, 65); + _palette->addPalette(calcHash("paKlayFloor"), 0, 65, 0); + insertScreenMouse(0x08B08180); + + tempSprite = insertStaticSprite(0x1E086325, 1200); + clipRect.set(0, 0, 640, tempSprite->getDrawRect().y2()); + + if (tracks->bgShadowFilename) { + _ssTrackShadowBackground = createSprite(tracks->bgShadowFilename); + addEntity(_ssTrackShadowBackground); + _asCar = insertSprite(this, 320, 240); + _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + } else { + _ssTrackShadowBackground = NULL; + _asCar = insertSprite(this, 320, 240); + } + + _asCarConnector = insertSprite(_asCar); + _which1 = tracks->which1; + _which2 = tracks->which2; + _dataResource.load(tracks->dataResourceFilename); + _trackPoints = _dataResource.getPointArray(tracks->trackPointsName); + _asCar->setPathPoints(_trackPoints); + + if (which == _which2) { + NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1]; + sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); + if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480) + sendMessage(_asCar, 0x2007, 150); + } else { + NPoint testPoint = (*_trackPoints)[0]; + sendMessage(_asCar, 0x2002, 0); + if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480) + sendMessage(_asCar, 0x2008, 150); + } + + _asCar->setClipRect(clipRect); + _asCarConnector->setClipRect(clipRect); + + if (which == 1) { + SetMessageHandler(&Scene2701::hmRidingCar); + } else { + sendMessage(_asCar, 0x2009, 0); + SetMessageHandler(&Scene2701::hmCarAtHome); + } + +} + +uint32 Scene2701::hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + sendPointMessage(_asCar, 0x2004, param.asPoint()); + break; + case 0x2005: + if (_which1 >= 0) + SetMessageHandler(&Scene2701::hmCarAtHome); + break; + case 0x2006: + if (_which2 >= 0) + leaveScene(_which2); + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + } + return 0; +} + +uint32 Scene2701::hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x >= 385) + leaveScene(0); + else { + sendPointMessage(_asCar, 0x2004, param.asPoint()); + SetMessageHandler(&Scene2701::hmRidingCar); + } + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + } + return 0; +} + +Scene2702::Scene2702(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _isInLight(true), _newTrackIndex(-1) { + + SetMessageHandler(&Scene2702::handleMessage); + SetUpdateHandler(&Scene2702::update); + + setBackground(0x18808B00); + setPalette(0x18808B00); + _palette->addPalette(calcHash("paPodFloor"), 65, 31, 65); + _palette->addPalette(calcHash("paKlayFloor"), 0, 65, 0); + addEntity(_palette); + insertScreenMouse(0x08B04180); + + _ssTrackShadowBackground = createSprite(0x12002035); + addEntity(_ssTrackShadowBackground); + _asCar = insertSprite(this, 320, 240); + _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + insertSprite(_asCar); + _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _dataResource.load(0x04310014); + + if (which == 1) { + _isUpperTrack = false; + _currTrackIndex = 1; + } else if (which == 2) { + _isUpperTrack = false; + _currTrackIndex = 2; + _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); + _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); + _isInLight = false; + } else if (which == 3) { + _isUpperTrack = true; + _currTrackIndex = 0; + } else if (which == 4) { + _isUpperTrack = true; + _currTrackIndex = 2; + _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); + _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); + _isInLight = false; + } else if (which == 5) { + _isUpperTrack = true; + _currTrackIndex = 1; + _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); + _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); + _isInLight = false; + } else { + _isUpperTrack = false; + _currTrackIndex = 0; + } + + if (_isUpperTrack) { + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5F68)); + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5F8C)); + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FB0)); + } else { + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FD8)); + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FFC)); + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B6020)); + } + + _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); + _asCar->setPathPoints(_trackPoints); + + if (which == _tracks[_currTrackIndex]->which2) { + sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); + sendMessage(_asCar, 0x2007, 150); + } else { + sendMessage(_asCar, 0x2002, 0); + sendMessage(_asCar, 0x2008, 150); + } + + _palette->copyBasePalette(0, 256, 0); + +} + +void Scene2702::update() { + Scene::update(); + if (_isInLight && _asCar->getX() > 422) { + _palette->addBasePalette(calcHash("paPodShade"), 65, 31, 65); + _palette->addBasePalette(calcHash("paKlayShade"), 0, 65, 0); + _palette->startFadeToPalette(12); + _isInLight = false; + } else if (!_isInLight && _asCar->getX() <= 422) { + _palette->addBasePalette(calcHash("paPodFloor"), 65, 31, 65); + _palette->addBasePalette(calcHash("paKlayFloor"), 0, 65, 0); + _palette->startFadeToPalette(12); + _isInLight = true; + } +} + +uint32 Scene2702::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + moveCarToPoint(param.asPoint()); + break; + case 0x2005: + if (_newTrackIndex >= 0) { + if (_tracks[_currTrackIndex]->which1 < 0) + changeTrack(); + } else if (_tracks[_currTrackIndex]->which1 >= 0) + leaveScene(_tracks[_currTrackIndex]->which1); + break; + case 0x2006: + if (_newTrackIndex >= 0) { + if (_tracks[_currTrackIndex]->which2 < 0) + changeTrack(); + } else if (_tracks[_currTrackIndex]->which2 >= 0) + leaveScene(_tracks[_currTrackIndex]->which2); + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + } + return 0; +} + +void Scene2702::moveCarToPoint(NPoint pt) { + int minMatchTrackIndex, minMatchDistance; + _tracks.findTrackPoint(pt, minMatchTrackIndex, minMatchDistance, _dataResource); + if (minMatchTrackIndex >= 0 && minMatchTrackIndex != _currTrackIndex) { + _newTrackIndex = minMatchTrackIndex; + _newTrackDestX = pt.x; + if (_isUpperTrack) { + if (_currTrackIndex == 0) + sendMessage(_asCar, 0x2003, _trackPoints->size() - 1); + else + sendMessage(_asCar, 0x2003, 0); + } else if (_currTrackIndex == 2) + sendMessage(_asCar, 0x2003, 0); + else + sendMessage(_asCar, 0x2003, _trackPoints->size() - 1); + } else { + _newTrackIndex = -1; + sendMessage(_asCar, 0x2004, pt.x); + } +} + +void Scene2702::changeTrack() { + _currTrackIndex = _newTrackIndex; + _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); + _asCar->setPathPoints(_trackPoints); + if (_isUpperTrack) { + if (_currTrackIndex == 0) + sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); + else + sendMessage(_asCar, 0x2002, 0); + } else if (_currTrackIndex == 2) + sendMessage(_asCar, 0x2002, 0); + else + sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); + sendMessage(_asCar, 0x2004, _newTrackDestX); + _newTrackIndex = -1; +} + +Scene2703::Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint32 trackInfoId) + : Scene(vm, parentModule) { + + TrackInfo *tracks = _vm->_staticData->getTrackInfo(trackInfoId); + + SetMessageHandler(&Scene2703::handleMessage); + SetUpdateHandler(&Scene2703::update); + + setBackground(tracks->bgFilename); + setPalette(tracks->bgFilename); + _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); + _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); + addEntity(_palette); + insertScreenMouse(tracks->mouseCursorFilename); + + _palStatus = 2; + + if (tracks->bgShadowFilename) { + _ssTrackShadowBackground = createSprite(tracks->bgShadowFilename); + addEntity(_ssTrackShadowBackground); + _asCar = insertSprite(this, 320, 240); + _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + } else { + _ssTrackShadowBackground = NULL; + _asCarShadow = NULL; + _asCar = insertSprite(this, 320, 240); + } + + _asCarConnector = insertSprite(_asCar); + _which1 = tracks->which1; + _which2 = tracks->which2; + _dataResource.load(tracks->dataResourceFilename); + _trackPoints = _dataResource.getPointArray(tracks->trackPointsName); + _asCar->setPathPoints(_trackPoints); + + if (which == _which2) { + NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1]; + sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); + if (testPoint.x > 0 && testPoint.x < 640 && testPoint.y > 0 && testPoint.y < 480) + sendMessage(_asCar, 0x2009, 0); + else + sendMessage(_asCar, 0x2007, 150); + } else { + NPoint testPoint = (*_trackPoints)[0]; + sendMessage(_asCar, 0x2002, 0); + if (testPoint.x > 0 && testPoint.x < 640 && testPoint.y > 0 && testPoint.y < 480) + sendMessage(_asCar, 0x2009, 0); + else + sendMessage(_asCar, 0x2008, 150); + } + + if (which == 0) { + _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); + _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); + _palStatus = 1; + } else if (which == 2 || which == 4 || which == 6) { + _palette->addPalette(calcHash("paPodBlack"), 65, 31, 65); + _palette->addPalette(calcHash("paKlayBlack"), 0, 65, 0); + _palStatus = 0; + } + + _palette->copyBasePalette(0, 256, 0); + +} + +void Scene2703::update() { + Scene::update(); + if (_mouseClicked) { + sendPointMessage(_asCar, 0x2004, _mouseClickPos); + _mouseClicked = false; + } + if (_asCar->getX() > 469) { + if (_palStatus != 2) { + _palette->addBasePalette(calcHash("paPodShade"), 65, 31, 65); + _palette->addBasePalette(calcHash("paKlayShade"), 0, 65, 0); + _palette->startFadeToPalette(12); + _palStatus = 2; + } + } else if (_asCar->getX() > 181) { + if (_palStatus != 1) { + _palette->addBasePalette(calcHash("paPodShade"), 65, 31, 65); + _palette->addBasePalette(calcHash("paKlayShade"), 0, 65, 0); + _palette->startFadeToPalette(12); + _palStatus = 1; + } + } else if (_palStatus != 0) { + _palette->addBasePalette(calcHash("paPodBlack"), 65, 31, 65); + _palette->addBasePalette(calcHash("paKlayBlack"), 0, 65, 0); + _palette->startFadeToPalette(12); + _palStatus = 0; + } +} + +uint32 Scene2703::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2005: + if (_which1 >= 0) + leaveScene(_which1); + break; + case 0x2006: + if (_which2 >= 0) + leaveScene(_which2); + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + } + return 0; +} + +Scene2704::Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint32 trackInfoId, int16 value, + const uint32 *staticSprites, const NRect *clipRect) + : Scene(vm, parentModule) { + + TrackInfo *tracks = _vm->_staticData->getTrackInfo(trackInfoId); + + SetMessageHandler(&Scene2704::handleMessage); + SetUpdateHandler(&Scene2704::update); + + setBackground(tracks->bgFilename); + setPalette(tracks->bgFilename); + + if (tracks->exPaletteFilename1) + _palette->addPalette(tracks->exPaletteFilename1, 0, 65, 0); + + if (tracks->exPaletteFilename2) + _palette->addPalette(tracks->exPaletteFilename2, 65, 31, 65); + + while (staticSprites && *staticSprites) + insertStaticSprite(*staticSprites++, 1100); + + insertScreenMouse(tracks->mouseCursorFilename); + + if (tracks->bgShadowFilename) { + _ssTrackShadowBackground = createSprite(tracks->bgShadowFilename); + addEntity(_ssTrackShadowBackground); + _asCar = insertSprite(this, 320, 240); + _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + } else { + _ssTrackShadowBackground = NULL; + _asCarShadow = NULL; + _asCar = insertSprite(this, 320, 240); + } + + _asCarConnector = insertSprite(_asCar); + _which1 = tracks->which1; + _which2 = tracks->which2; + _dataResource.load(tracks->dataResourceFilename); + _trackPoints = _dataResource.getPointArray(tracks->trackPointsName); + _asCar->setPathPoints(_trackPoints); + + if (which == _which2) { + NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1]; + sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); + if (testPoint.x > 0 && testPoint.x < 640 && testPoint.y > 0 && testPoint.y < 480) + sendMessage(_asCar, 0x2009, 0); + else + sendMessage(_asCar, 0x2007, 0); + } else { + NPoint testPoint = (*_trackPoints)[0]; + sendMessage(_asCar, 0x2002, 0); + if (testPoint.x > 0 && testPoint.x < 640 && testPoint.y > 0 && testPoint.y < 480) + sendMessage(_asCar, 0x2009, 0); + else + sendMessage(_asCar, 0x2008, 0); + } + + if (clipRect) { + _asCar->getClipRect() = *clipRect; + if (_asCarShadow) + _asCarShadow->getClipRect() = *clipRect; + if (_asCarTrackShadow) + _asCarTrackShadow->getClipRect() = *clipRect; + if (_asCarConnectorShadow) + _asCarConnectorShadow->getClipRect() = *clipRect; + if (_asCarConnector) + _asCarConnector->getClipRect() = *clipRect; + } + +} + +void Scene2704::update() { + Scene::update(); + if (_mouseClicked) { + sendPointMessage(_asCar, 0x2004, _mouseClickPos); + _mouseClicked = false; + } +} + +uint32 Scene2704::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2005: + if (_which1 >= 0) + leaveScene(_which1); + break; + case 0x2006: + if (_which2 >= 0) + leaveScene(_which2); + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + } + return 0; +} + +Scene2706::Scene2706(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _newTrackIndex(-1) { + + SetMessageHandler(&Scene2706::handleMessage); + + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22A0)); + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22C4)); + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22E8)); + + setBackground(0x18808B88); + setPalette(0x18808B88); + + _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); + _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); + + insertScreenMouse(0x08B8C180); + + _ssTrackShadowBackground = createSprite(0x18808B88); + addEntity(_ssTrackShadowBackground); + + _asCar = insertSprite(this, 320, 240); + _asCarShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _asCarConnector = insertSprite(_asCar); + _asCarTrackShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + _asCarConnectorShadow = insertSprite(_asCar, _ssTrackShadowBackground->getSurface(), 4); + + _dataResource.load(0x06000162); + + if (which == 5) + _currTrackIndex = 2; + else if (which == 6) + _currTrackIndex = 1; + else + _currTrackIndex = 0; + + _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); + _asCar->setPathPoints(_trackPoints); + + if (which == _tracks[_currTrackIndex]->which2) { + sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); + if (which == 5) + sendMessage(_asCar, 0x2007, 50); + else + sendMessage(_asCar, 0x2007, 150); + } else { + sendMessage(_asCar, 0x2002, 0); + if (which == 5) + sendMessage(_asCar, 0x2008, 50); + else + sendMessage(_asCar, 0x2008, 150); + } + +} + +uint32 Scene2706::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + moveCarToPoint(param.asPoint()); + break; + case 0x2005: + if (_newTrackIndex >= 0) { + if (_tracks[_currTrackIndex]->which1 < 0) + changeTrack(); + } else if (_tracks[_currTrackIndex]->which1 >= 0) + leaveScene(_tracks[_currTrackIndex]->which1); + break; + case 0x2006: + if (_newTrackIndex >= 0) { + if (_tracks[_currTrackIndex]->which2 < 0) + changeTrack(); + } else if (_tracks[_currTrackIndex]->which2 >= 0) + leaveScene(_tracks[_currTrackIndex]->which2); + break; + case 0x200D: + sendMessage(_parentModule, 0x200D, 0); + break; + } + return 0; +} + +void Scene2706::moveCarToPoint(NPoint pt) { + int minMatchTrackIndex, minMatchDistance; + _tracks.findTrackPoint(pt, minMatchTrackIndex, minMatchDistance, _dataResource); + if (minMatchTrackIndex >= 0 && minMatchTrackIndex != _currTrackIndex) { + _newTrackIndex = minMatchTrackIndex; + _newTrackDestX = pt.x; + if (_currTrackIndex == 0) + sendMessage(_asCar, 0x2003, _trackPoints->size() - 1); + else + sendMessage(_asCar, 0x2003, 0); + } else { + _newTrackIndex = -1; + sendMessage(_asCar, 0x2004, pt.x); + } +} + +void Scene2706::changeTrack() { + _currTrackIndex = _newTrackIndex; + _trackPoints = _dataResource.getPointArray(_tracks[_currTrackIndex]->trackPointsName); + _asCar->setPathPoints(_trackPoints); + if (_currTrackIndex == 0) + sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); + else + sendMessage(_asCar, 0x2002, 0); + sendMessage(_asCar, 0x2004, _newTrackDestX); + _newTrackIndex = -1; +} + +Scene2732::Scene2732(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule) { + + Sprite *tempSprite; + + setBackground(0x0220C041); + setPalette(0x0220C041); + insertScreenMouse(0x0C04502A); + setRectList(0x004AE360); + + insertKlaymen(108, 331); + setMessageList(0x004AE328); + + tempSprite = insertStaticSprite(0x50C22C48, 1100); + _klaymen->setClipRect(tempSprite->getDrawRect().x, 0, 640, 480); + +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module2700.h b/engines/neverhood/modules/module2700.h new file mode 100644 index 0000000000..003666bb7f --- /dev/null +++ b/engines/neverhood/modules/module2700.h @@ -0,0 +1,182 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE2700_H +#define NEVERHOOD_MODULES_MODULE2700_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/modules/module1600.h" + +namespace Neverhood { + +// Module2700 + +class Module2700 : public Module { +public: + Module2700(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module2700(); +protected: + int _sceneNum; + int _soundIndex; + bool _raidoMusicInitialized; + uint32 _scene2711StaticSprites[6]; + uint32 _musicFileHash; + void createScene(int sceneNum, int which); + void updateScene(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void createScene2703(int which, uint32 trackInfoId); + void createScene2704(int which, uint32 trackInfoId, int16 value, const uint32 *staticSprites = NULL, const NRect *clipRect = NULL); +}; + +class SsCommonTrackShadowBackground : public StaticSprite { +public: + SsCommonTrackShadowBackground(NeverhoodEngine *vm, uint32 fileHash); +}; + +class AsCommonCarShadow : public AnimatedSprite { +public: + AsCommonCarShadow(NeverhoodEngine *vm, AnimatedSprite *asCar, BaseSurface *shadowSurface, uint index); +protected: + uint _index; + AnimatedSprite *_asCar; + uint32 _animFileHash; + void update(); + void updateShadow(); +}; + +class AsCommonCarConnectorShadow : public AnimatedSprite { +public: + AsCommonCarConnectorShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, uint index); +protected: + uint _index; + Sprite *_asCar; + void update(); +}; + +class AsCommonCarTrackShadow : public AnimatedSprite { +public: + AsCommonCarTrackShadow(NeverhoodEngine *vm, Sprite *asCar, BaseSurface *shadowSurface, int16 frameIndex); +protected: + Sprite *_asCar; + void update(); +}; + +class Scene2701 : public Scene { +public: + Scene2701(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + AsCommonCar *_asCar; + Sprite *_ssTrackShadowBackground; + Sprite *_asCarShadow; + Sprite *_asCarTrackShadow; + Sprite *_asCarConnectorShadow; + Sprite *_asCarConnector; + int _which1, _which2; + NPointArray *_trackPoints; + uint32 hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmCarAtHome(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2702 : public Scene { +public: + Scene2702(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + AsCommonCar *_asCar; + Sprite *_ssTrackShadowBackground; + Sprite *_asCarShadow; + Sprite *_asCarTrackShadow; + Sprite *_asCarConnectorShadow; + int16 _newTrackDestX; + bool _isInLight; + int _currTrackIndex, _newTrackIndex; + bool _isUpperTrack; + Tracks _tracks; + NPointArray *_trackPoints; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void moveCarToPoint(NPoint pt); + void changeTrack(); +}; + +class Scene2703 : public Scene { +public: + Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint32 trackInfoId); +protected: + AsCommonCar *_asCar; + Sprite *_ssTrackShadowBackground; + Sprite *_asCarShadow; + Sprite *_asCarConnector; + Sprite *_asCarTrackShadow; + Sprite *_asCarConnectorShadow; + int _palStatus; + int _which1, _which2; + NPointArray *_trackPoints; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2704 : public Scene { +public: + Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint32 trackInfoId, int16 value, + const uint32 *staticSprites = NULL, const NRect *clipRect = NULL); +protected: + AsCommonCar *_asCar; + Sprite *_ssTrackShadowBackground; + Sprite *_asCarShadow; + Sprite *_asCarConnector; + Sprite *_asCarTrackShadow; + Sprite *_asCarConnectorShadow; + int _which1, _which2; + NPointArray *_trackPoints; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2706 : public Scene { +public: + Scene2706(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + AsCommonCar *_asCar; + Sprite *_ssTrackShadowBackground; + Sprite *_asCarShadow; + Sprite *_asCarConnector; + Sprite *_asCarTrackShadow; + Sprite *_asCarConnectorShadow; + int16 _newTrackDestX; + int _currTrackIndex, _newTrackIndex; + Tracks _tracks; + NPointArray *_trackPoints; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void moveCarToPoint(NPoint pt); + void changeTrack(); +}; + +class Scene2732 : public Scene { +public: + Scene2732(NeverhoodEngine *vm, Module *parentModule); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE2700_H */ diff --git a/engines/neverhood/modules/module2800.cpp b/engines/neverhood/modules/module2800.cpp new file mode 100644 index 0000000000..183de8e6b2 --- /dev/null +++ b/engines/neverhood/modules/module2800.cpp @@ -0,0 +1,3205 @@ +/* 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/modules/module2800.h" +#include "neverhood/gamemodule.h" +#include "neverhood/modules/module1000.h" +#include "neverhood/modules/module1200.h" +#include "neverhood/modules/module1700.h" +#include "neverhood/modules/module2200.h" +#include "neverhood/diskplayerscene.h" + +namespace Neverhood { + +Module2800::Module2800(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule), _musicResource(NULL) { + + _currentMusicFileHash = 0; + _vm->_soundMan->addMusic(0x64210814, 0xD2FA4D14); + setGlobalVar(V_RADIO_MOVE_DISH_VIDEO, 1); + + if (which < 0) { + createScene(_vm->gameState().sceneNum, which); + } else if (which == 2) { + createScene(4, 3); + } else if (which == 1) { + createScene(4, 1); + } else { + createScene(0, 0); + } + +} + +Module2800::~Module2800() { + if (_musicResource) { + _musicResource->unload(); + delete _musicResource; + } + _vm->_soundMan->deleteGroup(0x64210814); +} + +void Module2800::createScene(int sceneNum, int which) { + debug("Module2800::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _vm->_soundMan->stopMusic(0xD2FA4D14, 0, 0); + _childObject = new Scene2801(_vm, this, which); + break; + case 1: + _vm->gameState().sceneNum = 1; + _vm->_soundMan->stopMusic(0xD2FA4D14, 0, 0); + if (getGlobalVar(V_RADIO_ENABLED)) + _childObject = new Scene2802(_vm, this, which); + else + createStaticScene(0x000C6444, 0xC6440008); + break; + case 2: + _vm->gameState().sceneNum = 2; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + if (getGlobalVar(V_KLAYMEN_SMALL)) + _childObject = new Scene2803Small(_vm, this, which); + else + _childObject = new Scene2803(_vm, this, which); + break; + case 3: + _vm->gameState().sceneNum = 3; + _childObject = new Scene2804(_vm, this, which); + break; + case 4: + _vm->gameState().sceneNum = 4; + _vm->_soundMan->stopMusic(0xD2FA4D14, 0, 2); + _childObject = new Scene2805(_vm, this, which); + break; + case 5: + _vm->gameState().sceneNum = 5; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + _childObject = new Scene2806(_vm, this, which); + break; + case 6: + _vm->gameState().sceneNum = 6; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + _childObject = new Scene2807(_vm, this, which); + break; + case 7: + _vm->gameState().sceneNum = 7; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + _childObject = new Scene2808(_vm, this, 0); + break; + case 8: + _vm->gameState().sceneNum = 8; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + _childObject = new Scene2809(_vm, this, which); + break; + case 9: + _vm->gameState().sceneNum = 9; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + _childObject = new Scene2810(_vm, this, which); + break; + case 10: + _vm->gameState().sceneNum = 10; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + _childObject = new Scene2808(_vm, this, 1); + break; + case 11: + _vm->gameState().sceneNum = 11; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + _childObject = new Scene2812(_vm, this, which); + break; + case 12: + _vm->gameState().sceneNum = 12; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0x0000A245, 0x0A241008); + break; + case 13: + _vm->gameState().sceneNum = 13; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0x81C60635, 0x60631814); + break; + case 14: + _vm->gameState().sceneNum = 14; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0xCA811204, 0x11200CA0); + break; + case 15: + _vm->gameState().sceneNum = 15; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0x2D438A00, 0x38A042DC); + break; + case 16: + _vm->gameState().sceneNum = 16; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0x0A806204, 0x062000A0); + break; + case 17: + _vm->gameState().sceneNum = 17; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0x010F9284, 0xF9280018); + break; + case 18: + _vm->gameState().sceneNum = 18; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0x0100022B, 0x0022F018); + break; + case 19: + _vm->gameState().sceneNum = 19; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0x10866205, 0x66201100); + break; + case 20: + _vm->gameState().sceneNum = 20; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0x01C58000, 0x58004014); + break; + case 21: + _vm->gameState().sceneNum = 21; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + _childObject = new Scene2822(_vm, this, which); + break; + case 22: + _vm->gameState().sceneNum = 22; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0x9408121E, 0x8121A948); + break; + case 23: + _vm->gameState().sceneNum = 23; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0x048C0600, 0xC0604040); + break; + case 24: + _vm->gameState().sceneNum = 24; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + createStaticScene(0x04270A94, 0x70A9004A); + break; + case 25: + _vm->gameState().sceneNum = 25; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + if (getGlobalVar(V_SHRINK_LIGHTS_ON)) + createStaticScene(0x01600204, 0x0020001E); + else + createStaticScene(0x08611204, 0x1120008E); + break; + case 26: + _vm->gameState().sceneNum = 26; + _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); + _childObject = new DiskplayerScene(_vm, this, 4); + break; + case 1001: + _vm->_soundMan->stopMusic(0xD2FA4D14, 0, 0); + createSmackerScene(0x00800801, true, true, false); + break; + } + SetUpdateHandler(&Module2800::updateScene); + _childObject->handleUpdate(); +} + +void Module2800::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult != 2) { + if (_musicResource) { + _musicResource->unload(); + delete _musicResource; + _musicResource = NULL; + } + _currentMusicFileHash = 0; + } + if (_moduleResult == 1) { + createScene(2, 0); + } else if (_moduleResult == 2) { + createScene(1, 0); + } else { + leaveModule(0); + } + break; + case 1: + if (_moduleResult == 0) { + createScene(0, 2); + } else { + createScene(1001, -1); + } + break; + case 2: + if (_moduleResult == 1) + createScene(3, 0); + else if (_moduleResult == 2) + createScene(5, 0); + else if (_moduleResult == 3) + createScene(6, 0); + else if (_moduleResult == 4) + createScene(9, 0); + else if (_moduleResult == 5) + createScene(25, 0); + else + createScene(0, 1); + break; + case 3: + createScene(2, 1); + break; + case 4: + if (_moduleResult == 1) { + leaveModule(1); + } else { + createScene(11, 1); + } + break; + case 5: + if (_moduleResult == 1) { + createScene(7, 0); + } else { + createScene(2, 2); + } + break; + case 6: + createScene(2, 3); + break; + case 7: + createScene(5, _moduleResult); + break; + case 8: + if (_moduleResult == 1) + createScene(10, 0); + else + createScene(9, 4); + break; + case 9: + if (_moduleResult == 1) + createScene(11, 0); + else if (_moduleResult == 2) + createScene(2, 0); + else if (_moduleResult == 3) + createScene(24, 0); + else if (_moduleResult == 4) + createScene(8, 0); + else if (_moduleResult == 6) + createScene(2, 6); + else if (_moduleResult == 11) + createScene(12, 0); + else if (_moduleResult == 12) + createScene(13, 0); + else if (_moduleResult == 13) + createScene(14, 0); + else if (_moduleResult == 14) + createScene(15, 0); + else if (_moduleResult == 15) + createScene(16, 0); + else if (_moduleResult == 16) + createScene(17, 0); + else if (_moduleResult == 17) + createScene(18, 0); + else if (_moduleResult == 18) + createScene(19, 0); + else if (_moduleResult == 19) + createScene(20, 0); + else if (_moduleResult == 20) + createScene(21, 0); + else if (_moduleResult == 21) + createScene(22, 0); + else if (_moduleResult == 22) + createScene(23, 0); + else + createScene(2, 4); + break; + case 10: + createScene(8, _moduleResult); + break; + case 11: + if (_moduleResult == 1) + createScene(4, 0); + else if (_moduleResult == 2) + createScene(26, 0); + else if (_moduleResult == 3) + createScene(9, 5); + else + createScene(9, 1); + break; + case 12: + createScene(9, 11); + break; + case 13: + createScene(9, 12); + break; + case 14: + createScene(9, 13); + break; + case 15: + createScene(9, 14); + break; + case 16: + createScene(9, 15); + break; + case 17: + createScene(9, 16); + break; + case 18: + createScene(9, 17); + break; + case 19: + createScene(9, 18); + break; + case 20: + createScene(9, 19); + break; + case 21: + createScene(9, 20); + break; + case 22: + createScene(9, 21); + break; + case 23: + createScene(9, 22); + break; + case 24: + createScene(9, 3); + break; + case 25: + createScene(2, 5); + break; + case 26: + createScene(11, 2); + break; + case 1001: + createScene(1, -1); + break; + } + } else { + switch (_sceneNum) { + case 0: + updateMusic(true); + break; + case 1: + updateMusic(false); + break; + } + } +} + +void Module2800::updateMusic(bool halfVolume) { + + uint32 newMusicFileHash = _vm->_gameModule->getCurrRadioMusicFileHash(); + + if (!_musicResource) + _musicResource = new MusicResource(_vm); + + if (newMusicFileHash != _currentMusicFileHash) { + _currentMusicFileHash = newMusicFileHash; + if (_currentMusicFileHash != 0) { + _musicResource->load(_currentMusicFileHash); + _musicResource->setVolume(halfVolume ? 60 : 100); + _musicResource->play(0); + } else { + _musicResource->stop(0); + } + } else if (_currentMusicFileHash != 0) { + if (!_musicResource->isPlaying()) { + _musicResource->setVolume(halfVolume ? 60 : 100); + _musicResource->play(0); + } else { + _musicResource->setVolume(halfVolume ? 60 : 100); + } + } else { + _musicResource->stop(0); + } + +} + +Scene2801::Scene2801(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + Sprite *_sprite1; + Sprite *_sprite2; + + _vm->gameModule()->initRadioPuzzle(); + + SetMessageHandler(&Scene2801::handleMessage); + SetUpdateHandler(&Scene::update); + + // Display the disabled radio; only possible when the left door is open + if (!getGlobalVar(V_RADIO_ENABLED)) + insertStaticSprite(0x0001264C, 100); + + if (which < 0) { + insertKlaymen(194, 430); + setMessageList(0x004B6BB8); + } else if (which == 1) { + insertKlaymen(443, 398); + setMessageList(0x004B6BC0); + } else if (which == 2) { + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { + insertKlaymen(312, 432); + _klaymen->setDoDeltaX(1); + } else { + insertKlaymen(194, 432); + } + setMessageList(0x004B6C10); + } else { + insertKlaymen(0, 432); + setMessageList(0x004B6BB0); + } + + if (getGlobalVar(V_RADIO_ROOM_LEFT_DOOR)) { + setRectList(0x004B6CE0); + setBackground(0x01400666); + setPalette(0x01400666); + _paletteHash = 0x15021024; + _palette->addBasePalette(0x01400666, 0, 256, 0); + _sprite1 = insertStaticSprite(0x100CA0A8, 1100); + _sprite2 = insertStaticSprite(0x287C21A4, 1100); + _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite2->getDrawRect().x2(), 480); + insertScreenMouse(0x0066201C); + _asTape = insertSprite(this, 8, 1100, 302, 437, 0x9148A011); + addCollisionSprite(_asTape); + } else if (getGlobalVar(V_RADIO_ROOM_RIGHT_DOOR)) { + setRectList(0x004B6CD0); + setBackground(0x11E00684); + setPalette(0x11E00684); + _paletteHash = 0x15021024; + _palette->addBasePalette(0x11E00684, 0, 256, 0); + _sprite2 = insertStaticSprite(0x061601C8, 1100); + _klaymen->setClipRect(0, 0, _sprite2->getDrawRect().x2(), 480); + insertScreenMouse(0x00680116); + _asTape = insertSprite(this, 8, 1100, 302, 437, 0x01142428); + addCollisionSprite(_asTape); + } else { + setRectList(0x004B6CF0); + setBackground(0x030006E6); + setPalette(0x030006E6); + _paletteHash = 0x15021024; + _palette->addBasePalette(0x030006E6, 0, 256, 0); + _sprite2 = insertStaticSprite(0x273801CE, 1100); + _klaymen->setClipRect(0, 0, _sprite2->getDrawRect().x2(), 480); + insertScreenMouse(0x006E2038); + _asTape = insertSprite(this, 8, 1100, 302, 437, 0x9148A011); + addCollisionSprite(_asTape); + } + + addEntity(_palette); + + if (which == 1) { + _palette->addPalette(0xB103B604, 0, 65, 0); + _palette->addBasePalette(0xB103B604, 0, 65, 0); + } else { + _palette->addPalette(_paletteHash, 0, 65, 0); + _palette->addBasePalette(_paletteHash, 0, 65, 0); + } + +} + +Scene2801::~Scene2801() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); +} + +uint32 Scene2801::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4826: + if (sender == _asTape) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004B6C40); + } + break; + case 0x482A: + _palette->addBasePalette(0xB103B604, 0, 65, 0); + _palette->startFadeToPalette(12); + break; + case 0x482B: + _palette->addBasePalette(_paletteHash, 0, 65, 0); + _palette->startFadeToPalette(12); + break; + } + return messageResult; +} + +Scene2802::Scene2802(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _currTuneStatus(0), _countdown1(0), _countdown2(0) { + + SetMessageHandler(&Scene2802::handleMessage); + SetUpdateHandler(&Scene2802::update); + insertPuzzleMouse(0x008810A8, 20, 620); + _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, 0x8284C100, true, true, true)); + _currRadioMusicIndex = getGlobalVar(V_CURR_RADIO_MUSIC_INDEX); + // Need to go to the first frame first to load up the palette + _smackerPlayer->gotoFrame(0); + // Now we can actually set the current radio frame + _smackerPlayer->gotoFrame(_currRadioMusicIndex); + _vm->_soundMan->addSound(0x04360A18, 0x422630C2); + _vm->_soundMan->addSound(0x04360A18, 0x00632252); + _vm->_soundMan->addSound(0x04360A18, 0x00372241); + _vm->_soundMan->setSoundVolume(0x00372241, 60); + changeTuneStatus(0, 0); + _vm->_soundMan->playSoundLooping(0x00372241); +} + +Scene2802::~Scene2802() { + _vm->_soundMan->deleteSoundGroup(0x04360A18); + if (_currRadioMusicIndex == 0) { + setGlobalVar(V_RADIO_ROOM_LEFT_DOOR, 1); + setGlobalVar(V_RADIO_ROOM_RIGHT_DOOR, 0); + } else if (_currRadioMusicIndex == getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX)) { + setGlobalVar(V_RADIO_ROOM_LEFT_DOOR, 0); + setGlobalVar(V_RADIO_ROOM_RIGHT_DOOR, 1); + } else { + setGlobalVar(V_RADIO_ROOM_LEFT_DOOR, 0); + setGlobalVar(V_RADIO_ROOM_RIGHT_DOOR, 0); + } + setGlobalVar(V_CURR_RADIO_MUSIC_INDEX, _currRadioMusicIndex); +} + +void Scene2802::update() { + int prevTuneStatus = _currTuneStatus; + uint prevRadioMusicIndex = _currRadioMusicIndex; + + Scene::update(); + if (_countdown1 > 0) + --_countdown1; + else if (_currTuneStatus == 1) + _currTuneStatus = 3; + else if (_currTuneStatus == 4) + _currTuneStatus = 6; + + switch (_currTuneStatus) { + case 2: + if (_currRadioMusicIndex < 90) + incRadioMusicIndex(+1); + _currTuneStatus = 0; + break; + case 3: + if (_countdown2 > 0) + --_countdown2; + else if (_currRadioMusicIndex < 90) { + incRadioMusicIndex(+1); + _countdown2 = 1; + } else + _currTuneStatus = 0; + break; + case 5: + if (_currRadioMusicIndex > 0) + incRadioMusicIndex(-1); + _currTuneStatus = 0; + break; + case 6: + if (_countdown2 > 0) + --_countdown2; + else if (_currRadioMusicIndex > 0) { + incRadioMusicIndex(-1); + _countdown2 = 1; + } else + _currTuneStatus = 0; + break; + + } + + if (prevRadioMusicIndex != _currRadioMusicIndex) + _smackerPlayer->gotoFrame(_currRadioMusicIndex); + + if (prevTuneStatus != _currTuneStatus) + changeTuneStatus(prevTuneStatus, _currTuneStatus); + + //DEBUG>>> + //debug("_currRadioMusicIndex = %d; V_GOOD_RADIO_MUSIC_INDEX = %d", _currRadioMusicIndex, getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX)); + //DEBUG<<< + + if (getGlobalVar(V_RADIO_MOVE_DISH_VIDEO) && prevTuneStatus != _currTuneStatus && _currRadioMusicIndex != 0) { + setGlobalVar(V_RADIO_MOVE_DISH_VIDEO, 0); + leaveScene(1); + } + +} + +uint32 Scene2802::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + int prevTuneStatus = _currTuneStatus; + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { + leaveScene(0); + } else if (_currTuneStatus == 0) { + if (param.asPoint().x > 180 && param.asPoint().x < 300 && + param.asPoint().y > 130 && param.asPoint().y < 310) { + _currTuneStatus = 4; + } else if (param.asPoint().x > 300 && param.asPoint().x < 400 && + param.asPoint().y > 130 && param.asPoint().y < 310) { + _currTuneStatus = 1; + } + if (_currTuneStatus == 1 || _currTuneStatus == 4) { + _countdown1 = 8; + changeTuneStatus(0, _currTuneStatus); + } + } + break; + case 0x0002: + if (_countdown1 == 0) + _currTuneStatus = 0; + else { + if (_currTuneStatus == 1) + _currTuneStatus = 2; + else if (_currTuneStatus == 4) + _currTuneStatus = 5; + else + _currTuneStatus = 0; + _countdown1 = 0; + } + if (prevTuneStatus != _currTuneStatus) + changeTuneStatus(prevTuneStatus, _currTuneStatus); + break; + } + return 0; +} + +void Scene2802::incRadioMusicIndex(int delta) { + _currRadioMusicIndex += delta; + setGlobalVar(V_CURR_RADIO_MUSIC_INDEX, _currRadioMusicIndex); +} + +void Scene2802::changeTuneStatus(int prevTuneStatus, int newTuneStatus) { + + if (prevTuneStatus == 3 || prevTuneStatus == 6) { + _vm->_soundMan->stopSound(0x422630C2); + _vm->_soundMan->stopSound(0x00632252); + } + + if (newTuneStatus == 0) { + if (_vm->_gameModule->getCurrRadioMusicFileHash() != 0) + _vm->_soundMan->stopSound(0x00632252); + else + _vm->_soundMan->playSoundLooping(0x00632252); + } else if (newTuneStatus == 3 || newTuneStatus == 6) { + _vm->_soundMan->playSoundLooping(0x422630C2); + _vm->_soundMan->playSoundLooping(0x00632252); + } + +} + +AsScene2803LightCord::AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _fileHash1(fileHash1), _fileHash2(fileHash2), + _isPulled(false), _isBusy(false) { + + createSurface(1010, 28, 379); + SetUpdateHandler(&AnimatedSprite::update); + SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); + _x = x; + _y = y; + stIdle(); +} + +uint32 AsScene2803LightCord::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (!_isBusy && param.asInteger() == calcHash("ClickSwitch")) { + sendMessage(_parentScene, 0x480F, 0); + playSound(0, 0x4E1CA4A0); + } + break; + case 0x480F: + stPulled(); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +uint32 AsScene2803LightCord::hmPulled(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene2803LightCord::stPulled() { + _isBusy = false; + _isPulled = true; + startAnimation(_fileHash2, 0, -1); + SetMessageHandler(&AsScene2803LightCord::hmPulled); + NextState(&AsScene2803LightCord::stIdle); +} + +void AsScene2803LightCord::stIdle() { + _isPulled = false; + startAnimation(_fileHash1, 0, -1); + SetMessageHandler(&AsScene2803LightCord::handleMessage); +} + +void AsScene2803LightCord::setFileHashes(uint32 fileHash1, uint32 fileHash2) { + _fileHash1 = fileHash1; + _fileHash2 = fileHash2; + if (_isPulled) { + startAnimation(_fileHash2, _currFrameIndex, -1); + _isBusy = true; + } else { + startAnimation(_fileHash1, 0, -1); + } +} + +AsScene2803TestTubeOne::AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2) + : AnimatedSprite(vm, 1200), _fileHash1(fileHash1), _fileHash2(fileHash2) { + + createSurface1(fileHash1, 100); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2803TestTubeOne::handleMessage); + _x = 529; + _y = 326; +} + +uint32 AsScene2803TestTubeOne::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + if (param.asInteger()) + startAnimation(_fileHash2, 0, -1); + else + startAnimation(_fileHash1, 0, -1); + break; + } + return messageResult; +} + +AsScene2803Rope::AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x) + : AnimatedSprite(vm, 1100), _parentScene(parentScene) { + + createSurface(990, 68, 476); + SetUpdateHandler(&AnimatedSprite::update); + SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); + SetMessageHandler(&AsScene2803Rope::handleMessage); + startAnimation(0x9D098C23, 35, 53); + NextState(&AsScene2803Rope::stReleased); + _x = x; + _y = -276; +} + +uint32 AsScene2803Rope::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + startAnimation(0x9D098C23, 50, -1); + SetMessageHandler(&AsScene2803Rope::hmReleased); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +uint32 AsScene2803Rope::hmReleased(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +void AsScene2803Rope::stReleased() { + startAnimation(0x8258A030, 0, 1); + NextState(&AsScene2803Rope::stHide); +} + +void AsScene2803Rope::stHide() { + stopAnimation(); + setVisible(false); +} + +Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _paletteArea(0) { + + static const uint32 kScene2803FileHashes1[] = { + 0, + 0x081000F1, + 0x08100171, + 0x08100271 + }; + + static const uint32 kScene2803FileHashes2[] = { + 0, + 0x286800D4, + 0x286806D4, + 0x28680AD4 + }; + + setGlobalVar(V_BEEN_SHRINKING_ROOM, 1); + _vm->gameModule()->initTestTubes1Puzzle(); + + SetMessageHandler(&Scene2803::handleMessage); + + loadDataResource(0x00900849); + + _background = new Background(_vm, 0); + _background->createSurface(0, 640, 480); + addBackground(_background); + + setPalette(0x412A423E); + addEntity(_palette); + + insertScreenMouse(0xA423A41A); + + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 0) { + _asTestTubeOne = (StaticSprite*)insertStaticSprite(0x66121222, 100); + } else { + _asTestTubeOne = (StaticSprite*)insertSprite( + kScene2803FileHashes1[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)], + kScene2803FileHashes2[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)]); + } + + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) + _asTestTubeTwo = (StaticSprite*)insertStaticSprite(0x64330236, 100); + + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) + _asTestTubeThree = (StaticSprite*)insertStaticSprite(0x2E4A22A2, 100); + + _asLightCord = insertSprite(this, 0x8FAD5932, 0x276E1A3D, 578, 200); + _sprite3 = (StaticSprite*)insertStaticSprite(0xA40EF2FB, 1100); + _sprite4 = (StaticSprite*)insertStaticSprite(0x0C03AA23, 1100); + _sprite5 = (StaticSprite*)insertStaticSprite(0x2A822E2E, 1100); + _sprite6 = (StaticSprite*)insertStaticSprite(0x2603A202, 1100); + _sprite7 = (StaticSprite*)insertStaticSprite(0x24320220, 1100); + _sprite8 = (StaticSprite*)insertStaticSprite(0x3C42022F, 1100); + _sprite9 = (StaticSprite*)insertStaticSprite(0x341A0237, 1100); + _sprite10 = insertStaticSprite(0x855820A3, 1200); + + _clipRectsFloor[0].x1 = 0; + _clipRectsFloor[0].y1 = 0; + _clipRectsFloor[0].x2 = 640; + _clipRectsFloor[0].y2 = _sprite8->getDrawRect().y2(); + + _clipRectsFloor[1].x1 = _sprite8->getDrawRect().x2(); + _clipRectsFloor[1].y1 = _sprite8->getDrawRect().y2(); + _clipRectsFloor[1].x2 = 640; + _clipRectsFloor[1].y2 = 480; + + _clipRectsStairs[0].x1 = _sprite5->getDrawRect().x; + _clipRectsStairs[0].y1 = 0; + _clipRectsStairs[0].x2 = _sprite5->getDrawRect().x2(); + _clipRectsStairs[0].y2 = _sprite5->getDrawRect().y2(); + + _clipRectsStairs[1].x1 = _sprite6->getDrawRect().x; + _clipRectsStairs[1].y1 = 0; + _clipRectsStairs[1].x2 = _sprite3->getDrawRect().x; + _clipRectsStairs[1].y2 = _sprite6->getDrawRect().y2(); + + _clipRectsStairs[2].x1 = _sprite3->getDrawRect().x; + _clipRectsStairs[2].y1 = 0; + _clipRectsStairs[2].x2 = _sprite4->getDrawRect().x2(); + _clipRectsStairs[2].y2 = 480; + + if (which < 0) { + insertKlaymen(302, 445, _clipRectsFloor, 2); + setMessageList(0x004B79F0); + klaymenFloor(); + } else if (which == 1) { + insertKlaymen(200, 445, _clipRectsFloor, 2); + setMessageList(0x004B79C8); + klaymenFloor(); + } else if (which == 3) { + NPoint pt = _dataResource.getPoint(0xC2A08694); + insertKlaymen(pt.x, pt.y, _clipRectsStairs, 3); + setMessageList(0x004B7A00); + klaymenStairs(); + } else if (which == 5) { + insertKlaymen(253, 298, _clipRectsStairs, 3); + setMessageList(0x004B7A00); + klaymenStairs(); + } else if (which == 6) { + _asRope = insertSprite(this, 384); + _asRope->setClipRect(0, 25, 640, 480); + insertKlaymen(384, 0, _clipRectsFloor, 2); + sendEntityMessage(_klaymen, 0x1014, _asRope); + _klaymen->setClipRect(0, 25, 640, 480); + setMessageList(0x004B7A78); + klaymenFloor(); + } else if (which == 2) { + insertKlaymen(400, 445, _clipRectsFloor, 2); + setMessageList(0x004B79F8); + klaymenFloor(); + } else { + insertKlaymen(50, 231, _clipRectsStairs, 3); + setMessageList(0x004B79C0); + klaymenStairs(); + } + + changeBackground(); + +} + +void Scene2803::upKlaymenStairs() { + if (_klaymen->getX() < 350) { + setPaletteArea0(); + } else { + setPaletteArea1(); + } + Scene::update(); +} + +uint32 Scene2803::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x480F: + toggleBackground(); + // NOTE Intentional fall-through + case 0x100D: + if (param.asInteger() == 0x84251F82) + setMessageList(0x004B7A50); + else if (param.asInteger() == 0x4254A2D2) + setMessageList(0x004B7A58); + else if (param.asInteger() == 0xE90A40A0) + setMessageList(0x004B7A08); + else if (param.asInteger() == 0x482D1210) + setMessageList(0x004B7A30); + else if (param.asInteger() == 0x802402B2) { + sendEntityMessage(_klaymen, 0x1014, _asLightCord); + setMessageList(0x004B7A68); + } else if (param.asInteger() == 0x9626F390) + setMessageList(0x004B7A88); + break; + case 0x482A: + klaymenStairs(); + setPaletteArea1(); + break; + case 0x482B: + klaymenFloor(); + setPaletteArea0(); + break; + } + return messageResult; +} + +void Scene2803::klaymenStairs() { + SetUpdateHandler(&Scene2803::upKlaymenStairs); + _klaymen->getSurface()->setClipRects(_clipRectsStairs, 3); + sendMessage(_klaymen, 0x482C, 0xE5A48297); + _sprite3->setVisible(true); + _sprite4->setVisible(true); + _sprite5->setVisible(true); + _sprite6->setVisible(true); + _sprite7->setVisible(true); + _sprite8->setVisible(false); + _sprite9->setVisible(false); +} + +void Scene2803::klaymenFloor() { + SetUpdateHandler(&Scene::update); + _klaymen->getSurface()->setClipRects(_clipRectsFloor, 2); + sendMessage(_klaymen, 0x482C, 0); + _sprite3->setVisible(false); + _sprite4->setVisible(false); + _sprite5->setVisible(false); + _sprite6->setVisible(false); + _sprite7->setVisible(false); + _sprite8->setVisible(true); + _sprite9->setVisible(true); +} + +void Scene2803::toggleBackground() { + setGlobalVar(V_SHRINK_LIGHTS_ON, getGlobalVar(V_SHRINK_LIGHTS_ON) ? 0 : 1); + changeBackground(); +} + +void Scene2803::changeBackground() { + if (getGlobalVar(V_SHRINK_LIGHTS_ON)) { + _asLightCord->setFileHashes(0x8FAD5932, 0x276E1A3D); + _background->load(0x412A423E); + _palette->addPalette(0x412A423E, 0, 256, 0); + _palette->addBasePalette(0x412A423E, 0, 256, 0); + _sprite3->loadSprite(0xA40EF2FB); + _sprite4->loadSprite(0x0C03AA23); + _sprite5->loadSprite(0x2A822E2E); + _sprite6->loadSprite(0x2603A202); + _sprite7->loadSprite(0x24320220); + _mouseCursor->load(0xA423A41A); + _mouseCursor->updateCursor(); + _sprite8->loadSprite(0x3C42022F); + _sprite9->loadSprite(0x341A0237); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 0) + _asTestTubeOne->loadSprite(0x66121222); + else + sendMessage(_asTestTubeOne, 0x2000, 0); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) + _asTestTubeTwo->loadSprite(0x64330236); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) + _asTestTubeThree->loadSprite(0x2E4A22A2); + _sprite10->setVisible(true); + } else { + _asLightCord->setFileHashes(0xAFAD591A, 0x276E321D); + _background->load(0x29800A01); + _palette->addPalette(0x29800A01, 0, 256, 0); + _palette->addBasePalette(0x29800A01, 0, 256, 0); + _sprite3->loadSprite(0x234340A0); + _sprite4->loadSprite(0x16202200); + _sprite5->loadSprite(0x1030169A); + _sprite6->loadSprite(0x1600A6A8); + _sprite7->loadSprite(0xD0802EA0); + _mouseCursor->load(0x00A05290); + _mouseCursor->updateCursor(); + _sprite8->loadSprite(0x108012C1); + _sprite9->loadSprite(0x708072E0); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) != 0) + sendMessage(_asTestTubeOne, 0x2000, 1); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) + _asTestTubeTwo->loadSprite(0xD48077A0); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) + _asTestTubeThree->loadSprite(0x30022689); + _sprite10->setVisible(false); + } + updatePaletteArea(); +} + +void Scene2803::setPaletteArea0() { + if (_paletteArea != 0) { + _paletteArea = 0; + updatePaletteArea(); + } +} + +void Scene2803::setPaletteArea1() { + if (_paletteArea != 1) { + _paletteArea = 1; + updatePaletteArea(); + } +} + +void Scene2803::updatePaletteArea() { + uint32 fadePaletteHash; + if (getGlobalVar(V_SHRINK_LIGHTS_ON)) + fadePaletteHash = (_paletteArea == 1) ? 0xB103B604 : 0x412A423E; + else + fadePaletteHash = (_paletteArea == 1) ? 0x0263D144 : 0x29800A01; + _palette->addBasePalette(fadePaletteHash, 0, 64, 0); + _palette->startFadeToPalette(12); +} + +Scene2803Small::Scene2803Small(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _paletteArea(0) { + + static const uint32 kScene2803SmallFileHashes1[] = { + 0, 0x081000F1, 0x08100171, 0x08100271 + }; + + static const uint32 kScene2803SmallFileHashes2[] = { + 0, 0x286800D4, 0x286806D4, 0x28680AD4 + }; + + SetMessageHandler(&Scene2803Small::handleMessage); + + loadDataResource(0x81120132); + insertScreenMouse(0x00A05290); + + insertSprite(this, 0xAFAD591A, 0x276E321D, 578, 200); + + if (getGlobalVar(V_SHRINK_LIGHTS_ON)) { + setBackground(0x412A423E); + setPalette(0x412A423E); + _palette->addBasePalette(0x412A423E, 0, 256, 0); + addEntity(_palette); + _sprite1 = insertStaticSprite(0x0C03AA23, 1100); + _sprite2 = insertStaticSprite(0x24320220, 1100); + _sprite3 = insertStaticSprite(0x1A032204, 1100); + _sprite4 = insertStaticSprite(0x18032204, 1100); + _sprite5 = insertStaticSprite(0x34422912, 1100); + _sprite6 = insertStaticSprite(0x3C42022F, 1100); + _sprite7 = insertStaticSprite(0x341A0237, 1100); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 0) + insertStaticSprite(0x66121222, 100); + else + insertSprite(kScene2803SmallFileHashes1[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)], 100, 529, 326); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) + insertStaticSprite(0x64330236, 100); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) + insertStaticSprite(0x2E4A22A2, 100); + } else { + setBackground(0x29800A01); + setPalette(0x29800A01); + _palette->addBasePalette(0x29800A01, 0, 256, 0); + addEntity(_palette); + _sprite1 = insertStaticSprite(0x16202200, 1100); + _sprite2 = insertStaticSprite(0xD0802EA0, 1100); + _sprite3 = insertStaticSprite(0x780C2E30, 1100); + _sprite4 = insertStaticSprite(0x700C2E30, 1100); + _sprite5 = insertStaticSprite(0x102CE6E1, 900); + _sprite6 = insertStaticSprite(0x108012C1, 1100); + _sprite7 = insertStaticSprite(0x708072E0, 1100); + insertStaticSprite(0x90582EA4, 100); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) != 0) + insertSprite(kScene2803SmallFileHashes2[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)], 100, 529, 326); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) + insertStaticSprite(0xD48077A0, 100); + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) + insertStaticSprite(0x30022689, 100); + } + + _sprite6->setVisible(false); + _sprite7->setVisible(false); + + if (which < 0) { + insertKlaymen(479, 435); + klaymenFloor(); + setMessageList(0x004B60D8); + } else if (which == 3) { + NPoint pt = _dataResource.getPoint(0x096520ED); + insertKlaymen(pt.x, pt.y); + klaymenSlope(); + setMessageList(0x004B6100); + _klaymen->setRepl(64, 0); + } else if (which == 4) { + NPoint pt = _dataResource.getPoint(0x20C6238D); + insertKlaymen(pt.x, pt.y); + klaymenSlope(); + setMessageList(0x004B60F8); + _klaymen->setRepl(64, 0); + } else if (which == 5) { + NPoint pt = _dataResource.getPoint(0x2146690D); + insertKlaymen(pt.x, pt.y); + klaymenSlope(); + setMessageList(0x004B6100); + _klaymen->setRepl(64, 0); + } else if (which == 2) { + NPoint pt = _dataResource.getPoint(0x104C03ED); + insertKlaymen(pt.x, pt.y); + klaymenFloor(); + setMessageList(0x004B6138); + } else { + insertKlaymen(135, 444); + klaymenFloor(); + setMessageList(0x004B60E0, false); + _sprite6->setVisible(true); + _sprite7->setVisible(true); + } + +} + +uint32 Scene2803Small::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0xB4E4884C) { + setMessageList(0x004B6180); + } else if (param.asInteger() == 0xB1FDAB2E) { + NPoint pt = _dataResource.getPoint(0x0D84A1AD); + _klaymen->setX(pt.x); + _klaymen->setY(pt.y); + _klaymen->updateBounds(); + klaymenFloor(); + _klaymen->setClipRect(517, 401, 536, 480); + setMessageList(0x004B6198); + } else if (param.asInteger() == 0xB00C7C48) { + setMessageList(0x004B6108); + } else if (param.asInteger() == 0x61F64346) { + setMessageList(0x004B6150); + } else if (param.asInteger() == 0xAC69A28D) { + setMessageList(0x004B6168); + } else if (param.asInteger() == 0x00086212) { + _klaymen->setClipRect(0, 0, 560, 315); + _klaymen->setX(560); + _klaymen->setY(315); + _klaymen->updateBounds(); + klaymenSlope(); + setMessageList(0x004B61A0); + } else if (param.asInteger() == 0x002CAA68) { + setMessageList(0x004B61A8); + } + break; + case 0x482A: + if (_klaymen->getX() < 200) { + setPaletteArea3(); + } else if (_klaymen->getX() < 500) { + setSurfacePriority(_sprite5->getSurface(), 1100); + sendMessage(_klaymen, 0x482C, 0); + setPaletteArea2(); + } else { + _klaymen->setClipRect(517, 401, 536, 480); + setPaletteArea2(); + } + break; + case 0x482B: + _sprite6->setVisible(false); + _sprite7->setVisible(false); + _klaymen->setClipRect(0, 0, 640, 480); + setSurfacePriority(_sprite5->getSurface(), 900); + sendMessage(_klaymen, 0x482C, 0x2086222D); + break; + } + return 0; +} + +void Scene2803Small::upKlaymenSlope() { + if (_klaymen->getX() < 388) { + _klaymen->setClipRect(_sprite3->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); + setPaletteArea0(); + } else if (_klaymen->getX() < 500) { + _klaymen->setClipRect(0, 0, _sprite1->getDrawRect().x2(), _sprite1->getDrawRect().y2()); + setPaletteArea1(); + } + Scene::update(); +} + +void Scene2803Small::upKlaymenFloor() { + if (_klaymen->getX() > 194 && _klaymen->getX() < 273) + setPaletteArea2(); + else if (_klaymen->getX() > 155 && _klaymen->getX() < 300) + setPaletteArea0(); + Scene::update(); +} + +void Scene2803Small::klaymenSlope() { + SetUpdateHandler(&Scene2803Small::upKlaymenSlope); + sendMessage(_klaymen, 0x482C, 0x23C630D9); + _klaymen->setClipRect(0, 0, _sprite1->getDrawRect().x2(), _sprite1->getDrawRect().y2()); + _klaymen->setRepl(64, 0); + _sprite1->setVisible(true); +} + +void Scene2803Small::klaymenFloor() { + SetUpdateHandler(&Scene2803Small::upKlaymenFloor); + sendMessage(_klaymen, 0x482C, 0x2086222D); + _klaymen->setClipRect(0, 0, 640, 480); + _klaymen->clearRepl(); + _sprite1->setVisible(false); +} + +void Scene2803Small::setPaletteArea0() { + if (_paletteArea != 0) { + _paletteArea = 0; + updatePaletteArea(false); + } +} + +void Scene2803Small::setPaletteArea1() { + if (_paletteArea != 1) { + _paletteArea = 1; + updatePaletteArea(false); + } +} + +void Scene2803Small::setPaletteArea2() { + if (_paletteArea != 2) { + _paletteArea = 2; + updatePaletteArea(false); + } +} + +void Scene2803Small::setPaletteArea3() { + if (_paletteArea != 3) { + _paletteArea = 3; + updatePaletteArea(true); + } +} + +void Scene2803Small::updatePaletteArea(bool instantly) { + if (getGlobalVar(V_SHRINK_LIGHTS_ON)) { + switch (_paletteArea) { + case 1: + _palette->addBasePalette(0x0A938204, 0, 64, 0); + break; + case 2: + _palette->addBasePalette(0xB103B604, 0, 64, 0); + break; + case 3: + _palette->fillBaseBlack(0, 64); + break; + default: + _palette->addBasePalette(0x412A423E, 0, 64, 0); + break; + } + } else { + switch (_paletteArea) { + case 2: + _palette->addBasePalette(0x0263D144, 0, 64, 0); + break; + case 3: + _palette->fillBaseBlack(0, 64); + break; + default: + _palette->addBasePalette(0x29800A01, 0, 64, 0); + break; + } + } + _palette->startFadeToPalette(instantly ? 0 : 12); +} + +SsScene2804RedButton::SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene) + : StaticSprite(vm, 900), _countdown(0), _parentScene(parentScene) { + + loadSprite(getGlobalVar(V_SHRINK_LIGHTS_ON) ? 0x51A10202 : 0x11814A21, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); + setVisible(false); + SetUpdateHandler(&SsScene2804RedButton::update); + SetMessageHandler(&SsScene2804RedButton::handleMessage); + loadSound(0, 0x44241240); +} + +void SsScene2804RedButton::update() { + updatePosition(); + if (_countdown != 0 && (--_countdown) == 0) { + setVisible(false); + } +} + +uint32 SsScene2804RedButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown == 0 && !_parentScene->isWorking()) { + playSound(0); + setVisible(true); + _countdown = 4; + sendMessage(_parentScene, 0x2000, 0); + } + messageResult = 1; + break; + } + return messageResult; +} + +SsScene2804LightCoil::SsScene2804LightCoil(NeverhoodEngine *vm) + : StaticSprite(vm, 900) { + + loadSprite(0x8889B008, kSLFDefDrawOffset | kSLFDefPosition, 400); + setVisible(false); + SetMessageHandler(&SsScene2804LightCoil::handleMessage); +} + +uint32 SsScene2804LightCoil::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2002: + setVisible(true); + updatePosition(); + messageResult = 1; + break; + case 0x2003: + setVisible(false); + updatePosition(); + messageResult = 1; + break; + } + return messageResult; +} + +SsScene2804LightTarget::SsScene2804LightTarget(NeverhoodEngine *vm) + : StaticSprite(vm, 900) { + + loadSprite(0x06092132, kSLFDefDrawOffset | kSLFDefPosition, 400); + setVisible(false); + SetMessageHandler(&SsScene2804LightTarget::handleMessage); +} + +uint32 SsScene2804LightTarget::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2004: + setVisible(true); + updatePosition(); + messageResult = 1; + break; + case 0x2005: + setVisible(false); + updatePosition(); + messageResult = 1; + break; + } + return messageResult; +} + +SsScene2804Flash::SsScene2804Flash(NeverhoodEngine *vm) + : StaticSprite(vm, 900) { + + loadSprite(0x211003A0, kSLFDefDrawOffset | kSLFDefPosition, 400); + setVisible(false); + loadSound(0, 0xCB36BA54); +} + +void SsScene2804Flash::show() { + setVisible(true); + updatePosition(); + playSound(0); +} + +SsScene2804BeamCoilBody::SsScene2804BeamCoilBody(NeverhoodEngine *vm) + : StaticSprite(vm, 900) { + + loadSprite(0x9A816000, kSLFDefDrawOffset | kSLFDefPosition, 400); + setVisible(false); +} + +AsScene2804CrystalWaves::AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex) + : AnimatedSprite(vm, 1100), _crystalIndex(crystalIndex) { + + static const NPoint kAsScene2804CrystalWavesPoints[] = { + {323, 245}, + {387, 76}, + {454, 260}, + {527, 70} + }; + + _x = kAsScene2804CrystalWavesPoints[crystalIndex].x; + _y = kAsScene2804CrystalWavesPoints[crystalIndex].y; + createSurface1(0x840C41F0, 1200); + if (crystalIndex & 1) + setDoDeltaY(1); + setVisible(false); + _needRefresh = true; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&Sprite::handleMessage); +} + +void AsScene2804CrystalWaves::show() { + setVisible(true); + startAnimation(0x840C41F0, 0, -1); +} + +void AsScene2804CrystalWaves::hide() { + setVisible(false); + stopAnimation(); +} + +static const int16 kAsScene2804CrystalFrameNums[] = { + 0, 6, 2, 8, 1, 10, 0, 0 +}; + +static const uint32 kAsScene2804CrystalFileHashes[] = { + 0x000540B0, + 0x001280D0, + 0x003D0010, + 0x00620190, + 0x00DC0290 +}; + +AsScene2804Crystal::AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex) + : AnimatedSprite(vm, 1100), _asCrystalWaves(asCrystalWaves), _crystalIndex(crystalIndex), _isShowing(false) { + + static const NPoint kAsScene2804CrystalPoints[] = { + {204, 196}, + {272, 316}, + {334, 206}, + {410, 334}, + {470, 180} + }; + + _colorNum = (int16)getSubVar(VA_CURR_CRYSTAL_COLORS, crystalIndex); + _isLightOn = getGlobalVar(V_SHRINK_LIGHTS_ON) != 0; + if (_isLightOn) { + _x = kAsScene2804CrystalPoints[crystalIndex].x; + _y = kAsScene2804CrystalPoints[crystalIndex].y; + createSurface1(0x108DFB12, 1200); + startAnimation(0x108DFB12, kAsScene2804CrystalFrameNums[_colorNum], -1); + _needRefresh = true; + _newStickFrameIndex = kAsScene2804CrystalFrameNums[_colorNum]; + } else { + _x = 320; + _y = 240; + createSurface1(kAsScene2804CrystalFileHashes[crystalIndex], 1200); + startAnimation(kAsScene2804CrystalFileHashes[crystalIndex], _colorNum, -1); + setVisible(false); + _needRefresh = true; + _newStickFrameIndex = _colorNum; + } + loadSound(0, 0x725294D4); + SetUpdateHandler(&AnimatedSprite::update); +} + +void AsScene2804Crystal::show() { + if (!_isLightOn) { + setVisible(true); + _isShowing = true; + if (_asCrystalWaves) + _asCrystalWaves->show(); + playSound(0); + } +} + +void AsScene2804Crystal::hide() { + if (!_isLightOn) { + setVisible(false); + _isShowing = false; + if (_asCrystalWaves) + _asCrystalWaves->hide(); + } +} + +void AsScene2804Crystal::activate() { + if (!_isShowing) { + int16 frameNum = kAsScene2804CrystalFrameNums[_colorNum]; + _colorNum++; + if (_colorNum >= 6) + _colorNum = 0; + if (_isLightOn) { + startAnimation(0x108DFB12, frameNum, kAsScene2804CrystalFrameNums[_colorNum]); + _playBackwards = kAsScene2804CrystalFrameNums[_colorNum] < _colorNum; + _newStickFrameIndex = kAsScene2804CrystalFrameNums[_colorNum]; + } else { + startAnimation(kAsScene2804CrystalFileHashes[_crystalIndex], _colorNum, -1); + _newStickFrameIndex = _colorNum; + } + setSubVar(VA_CURR_CRYSTAL_COLORS, _crystalIndex, _colorNum); + } +} + +SsScene2804CrystalButton::SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex) + : StaticSprite(vm, 900), _countdown(0), _parentScene(parentScene), _asCrystal(asCrystal), _crystalIndex(crystalIndex) { + + static const uint32 kSsScene2804CrystalButtonFileHashes1[] = { + 0x911101B0, + 0x22226001, + 0x4444A362, + 0x888925A4, + 0x11122829 + }; + + static const uint32 kSsScene2804CrystalButtonFileHashes2[] = { + 0xB500A1A0, + 0x6A012021, + 0xD4022322, + 0xA8042525, + 0x5008292B + }; + + loadSprite(getGlobalVar(V_SHRINK_LIGHTS_ON) ? kSsScene2804CrystalButtonFileHashes1[crystalIndex] : kSsScene2804CrystalButtonFileHashes2[crystalIndex], + kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); + setVisible(false); + loadSound(0, 0x44045140); + SetUpdateHandler(&SsScene2804CrystalButton::update); + SetMessageHandler(&SsScene2804CrystalButton::handleMessage); +} + +void SsScene2804CrystalButton::update() { + updatePosition(); + if (_countdown != 0 && (--_countdown) == 0) { + setVisible(false); + } +} + +uint32 SsScene2804CrystalButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown == 0 && !_parentScene->isWorking()) { + playSound(0); + setVisible(true); + _countdown = 4; + _asCrystal->activate(); + } + messageResult = 1; + break; + } + return messageResult; +} + +AsScene2804BeamCoil::AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody) + : AnimatedSprite(vm, 1400), _parentScene(parentScene), _ssBeamCoilBody(ssBeamCoilBody), _countdown(0) { + + createSurface1(0x00494891, 1000); + _x = 125; + _y = 184; + setVisible(false); + _needRefresh = true; + AnimatedSprite::updatePosition(); + loadSound(0, 0x6352F051); + _vm->_soundMan->addSound(0xC5EA0B28, 0xEF56B094); + SetUpdateHandler(&AsScene2804BeamCoil::update); + SetMessageHandler(&AsScene2804BeamCoil::handleMessage); +} + +AsScene2804BeamCoil::~AsScene2804BeamCoil() { + _vm->_soundMan->deleteSoundGroup(0xC5EA0B28); +} + +void AsScene2804BeamCoil::update() { + updateAnim(); + updatePosition(); + if (_countdown != 0 && (--_countdown) == 0) { + sendMessage(_parentScene, 0x2001, 0); + } +} + +uint32 AsScene2804BeamCoil::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2002: + show(); + _countdown = 92; + messageResult = 1; + break; + case 0x2003: + hide(); + messageResult = 1; + break; + } + return messageResult; +} + +void AsScene2804BeamCoil::show() { + _ssBeamCoilBody->setVisible(true); + setVisible(true); + startAnimation(0x00494891, 0, -1); + playSound(0); + SetMessageHandler(&AsScene2804BeamCoil::hmBeaming); + NextState(&AsScene2804BeamCoil::stBeaming); +} + +void AsScene2804BeamCoil::hide() { + stopAnimation(); + SetMessageHandler(&AsScene2804BeamCoil::handleMessage); + setVisible(false); + _ssBeamCoilBody->setVisible(false); + _vm->_soundMan->stopSound(0xEF56B094); +} + +void AsScene2804BeamCoil::stBeaming() { + startAnimation(0x00494891, 93, -1); + NextState(&AsScene2804BeamCoil::stBeaming); + _vm->_soundMan->playSoundLooping(0xEF56B094); +} + +uint32 AsScene2804BeamCoil::hmBeaming(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +AsScene2804BeamTarget::AsScene2804BeamTarget(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1400) { + + createSurface1(0x03842000, 1000); + _x = 475; + _y = 278; + setVisible(false); + _needRefresh = true; + updatePosition(); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2804BeamTarget::handleMessage); +} + +uint32 AsScene2804BeamTarget::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2004: + setVisible(true); + startAnimation(0x03842000, 0, -1); + messageResult = 1; + break; + case 0x2005: + setVisible(false); + stopAnimation(); + messageResult = 1; + break; + } + return messageResult; +} + +Scene2804::Scene2804(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _countdown1(0), _countdown2(0), _countdown3(0), + _beamStatus(0), _isSolved(false), _isWorking(false) { + + _vm->gameModule()->initCrystalColorsPuzzle(); + + SetMessageHandler(&Scene2804::handleMessage); + SetUpdateHandler(&Scene2804::update); + + if (getGlobalVar(V_SHRINK_LIGHTS_ON)) { + setBackground(0xA1D03005); + setPalette(0xA1D03005); + addEntity(_palette); + insertPuzzleMouse(0x03001A15, 20, 620); + _asCoil = insertSprite(); + _asTarget = insertSprite(); + } else { + SsScene2804BeamCoilBody *ssBeamCoilBody; + setBackground(0x01C01414); + setPalette(0x01C01414); + addEntity(_palette); + insertPuzzleMouse(0x01410014, 20, 620); + ssBeamCoilBody = insertSprite(); + _asCoil = insertSprite(this, ssBeamCoilBody); + _asTarget = insertSprite(); + _ssFlash = insertSprite(); + } + + _ssRedButton = insertSprite(this); + addCollisionSprite(_ssRedButton); + + for (uint crystalIndex = 0; crystalIndex < 5; crystalIndex++) { + AsScene2804CrystalWaves *asCrystalWaves = NULL; + if (crystalIndex < 4 && getGlobalVar(V_SHRINK_LIGHTS_ON) == 0) + asCrystalWaves = insertSprite(crystalIndex); + _asCrystals[crystalIndex] = insertSprite(asCrystalWaves, crystalIndex); + _ssCrystalButtons[crystalIndex] = insertSprite(this, _asCrystals[crystalIndex], crystalIndex); + addCollisionSprite(_ssCrystalButtons[crystalIndex]); + } + +} + +uint32 Scene2804::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { + leaveScene(0); + } + break; + case 0x2000: + _isWorking = true; + sendMessage(_asCoil, 0x2002, 0); + if (getGlobalVar(V_SHRINK_LIGHTS_ON)) { + sendMessage(_asTarget, 0x2004, 0); + _countdown2 = 48; + } + break; + case 0x2001: + _countdown3 = 2; + _isSolved = true; + _beamStatus = 0; + for (uint index = 0; index < 5; index++) + if (_asCrystals[index]->getColorNum() != (int16)getSubVar(VA_GOOD_CRYSTAL_COLORS, index)) + _isSolved = false; + _countdown2 = 48; + break; + } + return 0; +} + +void Scene2804::update() { + + Scene::update(); + + if (_countdown1 != 0 && (--_countdown1) == 0) { + leaveScene(0); + } + + if (_countdown2 != 0 && (--_countdown2) == 0) { + _isWorking = false; + sendMessage(_asCoil, 0x2003, 0); + sendMessage(_asTarget, 0x2005, 0); + for (uint index = 0; index < 5; index++) + _asCrystals[index]->hide(); + } + + if (_countdown3 != 0 && (--_countdown3) == 0) { + if (_beamStatus == 5) { + sendMessage(_asTarget, 0x2004, 0); + if (_isSolved) { + _palette->fillBaseWhite(0, 256); + _palette->startFadeToPalette(18); + setGlobalVar(V_KLAYMEN_SMALL, 1); + _countdown1 = 48; + } + } else if (_beamStatus == 6) { + if (_isSolved) + _ssFlash->show(); + } else { + _asCrystals[_beamStatus]->show(); + } + _beamStatus++; + if (_beamStatus < 6) + _countdown3 = 2; + else if (_beamStatus < 7) + _countdown3 = 4; + } + +} + +Scene2805::Scene2805(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + SetMessageHandler(&Scene2805::handleMessage); + + setBackground(0x08021E04); + setPalette(0x08021E04); + _palette->addPalette(0x8A6B1F91, 0, 65, 0); + insertScreenMouse(0x21E00088); + + _sprite1 = insertStaticSprite(0x008261E7, 1100); + _sprite2 = insertStaticSprite(0x020CE421, 1100); + + if (which < 0) { + insertKlaymen(380, 338); + setMessageList(0x004AE1C8); + sendMessage(this, 0x2000, 0); + } else if (which == 1) { + insertKlaymen(493, 338); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004AE1D0, false); + sendMessage(this, 0x2000, 1); + } else if (which == 2) { + insertKlaymen(493, 338); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004AE288, false); + sendMessage(this, 0x2000, 1); + } else if (which == 3) { + insertKlaymen(493, 338); + sendMessage(_klaymen, 0x2000, 1); + setMessageList(0x004AE1E0, false); + sendMessage(this, 0x2000, 1); + } else { + insertKlaymen(340, 338); + setMessageList(0x004AE1C0); + sendMessage(this, 0x2000, 0); + } + + _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite2->getDrawRect().x2(), 480); + +} + +uint32 Scene2805::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + if (param.asInteger()) { + setRectList(0x004AE318); + _klaymen->setKlaymenIdleTable3(); + } else { + setRectList(0x004AE308); + _klaymen->setKlaymenIdleTable1(); + } + break; + } + return 0; +} + +AsScene2806Spew::AsScene2806Spew(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1200) { + + createSurface1(0x04211490, 1200); + _x = 378; + _y = 423; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2806Spew::handleMessage); + setDoDeltaX(1); + setVisible(false); +} + +uint32 AsScene2806Spew::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + playSound(0, 0x48640244); + startAnimation(0x04211490, 0, -1); + setVisible(true); + break; + case 0x3002: + stopAnimation(); + setVisible(false); + break; + } + return messageResult; +} + +Scene2806::Scene2806(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + Sprite *tempSprite; + + which = 3; + + SetMessageHandler(&Scene2806::handleMessage); + SetUpdateHandler(&Scene2806::update); + + loadDataResource(0x98182003); + loadHitRectList(); + + _pointList = _dataResource.getPointArray(0x3606A422); + + insertScreenMouse(0x22114C13); + setBackground(0xC1B22110); + setPalette(0xC1B22110); + + _sprite1 = insertStaticSprite(0xA21F82CB, 1100); + _clipRects[0].x1 = _sprite1->getDrawRect().x; + _clipRects[0].y1 = _sprite1->getDrawRect().y; + _clipRects[0].x2 = _sprite1->getDrawRect().x2(); + _clipRects[0].y2 = _sprite1->getDrawRect().y2(); + + _sprite2 = insertStaticSprite(0x92035301, 1100); + _clipRects[1].y2 = _sprite2->getDrawRect().y2(); + + _sprite3 = insertStaticSprite(0x3182220E, 1100); + + _sprite4 = insertStaticSprite(0x72090342, 1100); + _clipRects[1].x1 = _sprite4->getDrawRect().x; + _clipRects[1].y1 = _sprite4->getDrawRect().y; + + tempSprite = insertStaticSprite(0xD2012C02, 1100); + _clipRects[2].x1 = tempSprite->getDrawRect().x; + _clipRects[2].y2 = tempSprite->getDrawRect().y2(); + _clipRects[3].y1 = tempSprite->getDrawRect().y2(); + _clipRects[1].x2 = tempSprite->getDrawRect().x; + + tempSprite = insertStaticSprite(0x72875F42, 1100); + _clipRects[3].x1 = tempSprite->getDrawRect().x; + + insertStaticSprite(0x0201410A, 1100); + insertStaticSprite(0x72875F42, 1100); + + _asSpew = insertSprite(); + + _clipRects[2].y1 = 0; + _clipRects[3].y2 = 480; + _clipRects[2].x2 = 640; + _clipRects[3].x2 = 640; + + if (which < 0) { + insertKlaymen(441, 423, false, _clipRects, 4); + setMessageList(0x004AF098); + } else if (which == 1) { + insertKlaymen(378, 423, false, _clipRects, 4); + setMessageList(0x004AF098); + } else if (which == 2) { + insertKlaymen(378, 423, false, _clipRects, 4); + setMessageList(0x004AF0C8, false); + } else if (which == 3) { + insertKlaymen(378, 423, true, _clipRects, 4); + setMessageList(0x004AF0A0, false); + setGlobalVar(V_KLAYMEN_SMALL, 0); + } else { + insertKlaymen(670, 423, false, _clipRects, 4); + setMessageList(0x004AF090); + } + + _pointIndex = -1; + findClosestPoint(); + +} + +uint32 Scene2806::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x44262B12) { + setMessageList(0x004AF0E0); + } + break; + case 0x2000: + sendMessage(_asSpew, 0x2000, 0); + break; + } + return 0; +} + +void Scene2806::update() { + Scene::update(); + findClosestPoint(); +} + +void Scene2806::findClosestPoint() { + + static const uint32 kScene2806PaletteFileHashes[] = { + 0x48052508, + 0x01139404, + 0x01138C04, + 0x01138004, + 0x01138604, + 0x086B8890 + }; + + int16 x = MIN(_klaymen->getX(), 639); + int index = 1; + + while (index < (int)_pointList->size() && (*_pointList)[index].x < x) + ++index; + --index; + + if (_pointIndex != index) { + _pointIndex = index; + _palette->addPalette(kScene2806PaletteFileHashes[index], 0, 64, 0); + } + +} + +Scene2807::Scene2807(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + SetMessageHandler(&Scene2807::handleMessage); + + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 1) { + insertStaticSprite(0x103021E2, 300); + } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 2) { + insertStaticSprite(0x103022E2, 300); + } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 3) { + insertStaticSprite(0x103024E2, 300); + } + + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 1) { + insertStaticSprite(0x4800A52A, 200); + } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 2) { + insertStaticSprite(0x4800A62A, 200); + } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) { + insertStaticSprite(0x4800A02A, 200); + } + + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 1) { + insertStaticSprite(0x31203430, 100); + } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 2) { + insertStaticSprite(0x31203400, 100); + } else if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) { + insertStaticSprite(0x31203460, 100); + } + + setBackground(0x3E049A95); + setPalette(0x3E049A95); + insertPuzzleMouse(0x49A913E8, 20, 620); + +} + +uint32 Scene2807::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { + leaveScene(0); + } + break; + } + return 0; +} + +static const uint32 kScene2808FileHashes1[] = { + 0x90B0392, + 0x90B0192 +}; + +static const uint32 kScene2808FileHashes2[] = { + 0xB0396098, + 0xB0196098 +}; + +static const uint32 kClass428FileHashes[] = { + 0x140022CA, + 0x4C30A602, + 0xB1633402, + 0x12982135, + 0x0540B728, + 0x002A81E3, + 0x08982841, + 0x10982841, + 0x20982841, + 0x40982841, + 0x80982841, + 0x40800711 +}; + +static const int kClass428Countdowns1[] = { + 18, 16, 10, 0 +}; + +static const int kClass428Countdowns2[] = { + 9, 9, 8, 8, 5, 5, 0, 0 +}; + +static const uint32 kClass490FileHashes[] = { + 0x08100071, + 0x24084215, + 0x18980A10 +}; + +static const int16 kClass490FrameIndices1[] = { + 0, 8, 15, 19 +}; + +static const int16 kClass490FrameIndices2[] = { + 0, 4, 8, 11, 15, 17, 19, 0 +}; + +SsScene2808Dispenser::SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex) + : StaticSprite(vm, 900), _parentScene(parentScene), _countdown(0), _testTubeSetNum(testTubeSetNum), + _testTubeIndex(testTubeIndex) { + + loadSprite(kClass428FileHashes[testTubeSetNum * 3 + testTubeIndex], kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 1500); + setVisible(false); + SetUpdateHandler(&SsScene2808Dispenser::update); + SetMessageHandler(&SsScene2808Dispenser::handleMessage); +} + +void SsScene2808Dispenser::update() { + updatePosition(); + if (_countdown != 0 && (--_countdown) == 0) { + setVisible(false); + } +} + +uint32 SsScene2808Dispenser::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x2000, _testTubeIndex); + messageResult = 1; + break; + } + return messageResult; +} + +void SsScene2808Dispenser::startCountdown(int index) { + setVisible(true); + updatePosition(); + if (_testTubeSetNum == 0) { + _countdown = kClass428Countdowns1[index]; + } else { + _countdown = kClass428Countdowns2[index]; + } +} + +AsScene2808TestTube::AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser) + : AnimatedSprite(vm, 1100), _testTubeSetNum(testTubeSetNum), _testTubeIndex(testTubeIndex), _ssDispenser(ssDispenser), _fillLevel(0) { + + if (testTubeSetNum == 0) { + _x = 504; + _y = 278; + } else { + setDoDeltaX(1); + _x = 136; + _y = 278; + } + + createSurface1(kClass490FileHashes[testTubeIndex], 1100); + + if (testTubeSetNum == 0) { + loadSound(0, 0x30809E2D); + loadSound(1, 0x72811E2D); + loadSound(2, 0x78B01625); + } else { + loadSound(3, 0x70A41E0C); + loadSound(4, 0x50205E2D); + loadSound(5, 0xF8621E2D); + loadSound(6, 0xF1A03C2D); + loadSound(7, 0x70A43D2D); + loadSound(8, 0xF0601E2D); + } + + startAnimation(kClass490FileHashes[testTubeIndex], 0, -1); + _newStickFrameIndex = 0; + + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2808TestTube::handleMessage); + + if (_fillLevel == 0) + setVisible(false); + +} + +uint32 AsScene2808TestTube::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + fill(); + messageResult = 1; + break; + } + return messageResult; +} + +void AsScene2808TestTube::fill() { + if ((int)_fillLevel < _testTubeSetNum * 3 + 3) { + if (_testTubeSetNum == 0) { + playSound(_fillLevel); + setVisible(true); + startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices1[_fillLevel], kClass490FrameIndices1[_fillLevel + 1]); + _newStickFrameIndex = kClass490FrameIndices1[_fillLevel + 1]; + } else { + playSound(3 + _fillLevel); + setVisible(true); + startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices2[_fillLevel], kClass490FrameIndices2[_fillLevel + 1]); + _newStickFrameIndex = kClass490FrameIndices2[_fillLevel + 1]; + } + _ssDispenser->startCountdown(_fillLevel); + _fillLevel++; + } +} + +void AsScene2808TestTube::flush() { + if (_fillLevel != 0) { + if (_testTubeSetNum == 0) { + startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices1[_fillLevel], -1); + } else { + startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices2[_fillLevel], -1); + } + _newStickFrameIndex = 0; + _playBackwards = true; + setVisible(true); + } +} + +AsScene2808Handle::AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum) + : AnimatedSprite(vm, 1300), _parentScene(parentScene), _testTubeSetNum(testTubeSetNum), _isActivated(false) { + + loadSound(0, 0xE18D1F30); + _x = 320; + _y = 240; + if (_testTubeSetNum == 1) + setDoDeltaX(1); + createSurface1(0x040900D0, 1300); + startAnimation(0x040900D0, 0, -1); + _needRefresh = true; + _newStickFrameIndex = 0; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2808Handle::handleMessage); + AnimatedSprite::updatePosition(); +} + +uint32 AsScene2808Handle::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (!_isActivated) { + sendMessage(_parentScene, 0x2001, 0); + playSound(0); + activate(); + } + messageResult = 1; + break; + } + return messageResult; +} + +uint32 AsScene2808Handle::hmActivating(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene2808Handle::activate() { + startAnimation(0x040900D0, 0, -1); + SetMessageHandler(&AsScene2808Handle::hmActivating); + NextState(&AsScene2808Handle::stActivated); + _isActivated = true; + _newStickFrameIndex = -1; +} + +void AsScene2808Handle::stActivated() { + stopAnimation(); + sendMessage(_parentScene, 0x2002, 0); +} + +AsScene2808Flow::AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _testTubeSetNum(testTubeSetNum) { + + if (testTubeSetNum == 0) { + _x = 312; + _y = 444; + } else { + _x = 328; + _y = 444; + } + createSurface1(0xB8414818, 1200); + startAnimation(0xB8414818, 0, -1); + setVisible(false); + _newStickFrameIndex = 0; + _needRefresh = true; + loadSound(0, 0x6389B652); + SetUpdateHandler(&AnimatedSprite::update); + AnimatedSprite::updatePosition(); +} + +uint32 AsScene2808Flow::hmFlowing(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene2808Flow::start() { + startAnimation(0xB8414818, 0, -1); + setVisible(true); + SetMessageHandler(&AsScene2808Flow::hmFlowing); + NextState(&AsScene2808Flow::stKeepFlowing); + playSound(0); +} + +void AsScene2808Flow::stKeepFlowing() { + startAnimation(0xB8414818, 1, -1); + NextState(&AsScene2808Flow::stKeepFlowing); +} + +AsScene2808LightEffect::AsScene2808LightEffect(NeverhoodEngine *vm, int testTubeSetNum) + : AnimatedSprite(vm, 800), _countdown(1) { + + _x = 320; + _y = 240; + if (testTubeSetNum == 1) + setDoDeltaX(1); + createSurface1(0x804C2404, 800); + SetUpdateHandler(&AsScene2808LightEffect::update); + _needRefresh = true; + AnimatedSprite::updatePosition(); +} + +void AsScene2808LightEffect::update() { + if (_countdown != 0 && (--_countdown) == 0) { + int16 frameIndex = _vm->_rnd->getRandomNumber(3 - 1); + startAnimation(0x804C2404, frameIndex, frameIndex); + updateAnim(); + updatePosition(); + _countdown = _vm->_rnd->getRandomNumber(3 - 1) + 1; + } +} + +Scene2808::Scene2808(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _countdown(0), _testTubeSetNum(which), _leaveResult(0), _isFlowing(false) { + + Sprite *asHandle; + + if (which == 0) + _vm->gameModule()->initTestTubes1Puzzle(); + else + _vm->gameModule()->initTestTubes2Puzzle(); + + SetMessageHandler(&Scene2808::handleMessage); + SetUpdateHandler(&Scene2808::update); + + setBackground(kScene2808FileHashes1[which]); + setPalette(kScene2808FileHashes1[which]); + + asHandle = insertSprite(this, which); + addCollisionSprite(asHandle); + + _asFlow = insertSprite(this, which); + insertSprite(which); + + for (int testTubeIndex = 0; testTubeIndex < 3; testTubeIndex++) { + SsScene2808Dispenser *ssDispenser = insertSprite(this, which, testTubeIndex); + addCollisionSprite(ssDispenser); + _asTestTubes[testTubeIndex] = insertSprite(which, testTubeIndex, ssDispenser); + addCollisionSprite(_asTestTubes[testTubeIndex]); + } + + insertScreenMouse(kScene2808FileHashes2[which]); + +} + +uint32 Scene2808::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && !isAnyTestTubeFilled()) { + leaveScene(1); + } + break; + case 0x2000: + if (!_isFlowing) + _asTestTubes[param.asInteger()]->fill(); + break; + case 0x2001: + _isFlowing = true; + break; + case 0x2002: + if (isAnyTestTubeFilled()) { + _leaveResult = 3; + if (!isMixtureGood()) + _leaveResult = 2; + _asFlow->start(); + for (int i = 0; i < 3; i++) + _asTestTubes[i]->flush(); + _mouseCursor->setVisible(false); + _countdown = 16; + } else { + leaveScene(1); + } + break; + } + return 0; +} + +void Scene2808::update() { + + // DEBUG>>> Show correct values + #if 1 + debug("---------------"); + if (_testTubeSetNum == 0) + debug("%03d %03d %03d", getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2)); + else + debug("%03d %03d %03d", getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2)); + debug("%03d %03d %03d", _asTestTubes[0]->getFillLevel(), _asTestTubes[1]->getFillLevel(), _asTestTubes[2]->getFillLevel()); + #endif + // DEBUG<<< + + Scene::update(); + if (_countdown != 0 && (--_countdown) == 0) { + leaveScene(_leaveResult); + } +} + +bool Scene2808::isMixtureGood() { + if (_testTubeSetNum == 0) { + return + _asTestTubes[0]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) && + _asTestTubes[1]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) && + _asTestTubes[2]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2); + } else { + return + _asTestTubes[0]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0) && + _asTestTubes[1]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1) && + _asTestTubes[2]->getFillLevel() == getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2); + } +} + +bool Scene2808::isAnyTestTubeFilled() { + return + _asTestTubes[0]->getFillLevel() > 0 || + _asTestTubes[1]->getFillLevel() > 0 || + _asTestTubes[2]->getFillLevel() > 0; +} + +AsScene2809Spew::AsScene2809Spew(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1200) { + + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2809Spew::handleMessage); + createSurface1(0x04211490, 1200); + _x = 262; + _y = 423; + setDoDeltaX(0); + setVisible(false); +} + +uint32 AsScene2809Spew::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + playSound(0, 0x48640244); + startAnimation(0x04211490, 0, -1); + setVisible(true); + break; + case 0x3002: + stopAnimation(); + setVisible(false); + break; + } + return messageResult; +} + +Scene2809::Scene2809(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + Sprite *tempSprite; + + SetMessageHandler(&Scene2809::handleMessage); + SetUpdateHandler(&Scene2809::update); + + loadDataResource(0x1830009A); + loadHitRectList(); + + _pointList = _dataResource.getPointArray(0x064A310E); + + setBackground(0xB22116C5); + setPalette(0xB22116C5); + insertScreenMouse(0x116C1B2A); + + _sprite1 = insertStaticSprite(0x1FA2EB82, 1100); + + _clipRects[0].x1 = _sprite1->getDrawRect().x; + _clipRects[0].y1 = _sprite1->getDrawRect().y; + _clipRects[0].x2 = _sprite1->getDrawRect().x2(); + _clipRects[0].y2 = _sprite1->getDrawRect().y2(); + + _sprite2 = insertStaticSprite(0x037321B2, 1100); + _clipRects[1].y2 = _sprite2->getDrawRect().y2(); + + _sprite3 = insertStaticSprite(0x82022E11, 1100); + + _sprite4 = insertStaticSprite(0x09236252, 1100); + _clipRects[1].x2 = _sprite4->getDrawRect().x2(); + _clipRects[1].y1 = _sprite4->getDrawRect().y; + + tempSprite = insertStaticSprite(0x010C22F2, 1100); + _clipRects[2].x2 = tempSprite->getDrawRect().x2(); + _clipRects[2].y2 = tempSprite->getDrawRect().y2(); + _clipRects[3].y1 = tempSprite->getDrawRect().y2(); + _clipRects[1].x1 = tempSprite->getDrawRect().x2(); + + tempSprite = insertStaticSprite(0x877F6252, 1100); + _clipRects[3].x2 = tempSprite->getDrawRect().x2(); + + insertStaticSprite(0x01612A22, 1100); + insertStaticSprite(0x877F6252, 1100); + + _asSpew = insertSprite(); + _clipRects[2].y1 = 0; + _clipRects[3].y2 = 480; + _clipRects[2].x1 = 0; + _clipRects[3].x1 = 0; + + if (which < 0) { + insertKlaymen(226, 423, false, _clipRects, 4); + setMessageList(0x004B5B90); + } else if (which == 1) { + insertKlaymen(262, 423, false, _clipRects, 4); + setMessageList(0x004B5B90); + } else if (which == 2) { + insertKlaymen(262, 423, false, _clipRects, 4); + setMessageList(0x004B5BD0); + } else if (which == 3) { + insertKlaymen(262, 423, true, _clipRects, 4); + setMessageList(0x004B5BA8, false); + setGlobalVar(V_KLAYMEN_SMALL, 0); + } else { + insertKlaymen(-30, 423, false, _clipRects, 4); + setMessageList(0x004B5B88); + } + + _pointIndex = -1; + findClosestPoint(); + +} + +void Scene2809::update() { + Scene::update(); + findClosestPoint(); +} + +uint32 Scene2809::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x160DA937) { + setMessageList(0x004B5B98); + } + break; + case 0x2000: + sendMessage(_asSpew, 0x2000, 0); + break; + } + return 0; +} + +void Scene2809::findClosestPoint() { + + static const uint32 kScene2809PaletteFileHashes[] = { + 0x04260848, + 0x12970401, + 0x128F0401, + 0x12830401, + 0x12850401, + 0x6A8B9008 + }; + + int16 x = MAX(_klaymen->getX(), 2); + int index = 1; + + while (index < (int)_pointList->size() && (*_pointList)[index].x >= x) + ++index; + --index; + + if (_pointIndex != index) { + _pointIndex = index; + _palette->addPalette(kScene2809PaletteFileHashes[index], 0, 64, 0); + } + +} + +AsScene2810Rope::AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x) + : AnimatedSprite(vm, 1100) { + + createSurface(990, 68, 476); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2810Rope::handleMessage); + SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); + _x = x; + _y = -276; + startAnimation(0x9D098C23, 35, 53); +} + +uint32 AsScene2810Rope::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + startAnimation(0x9D098C23, 35, 53); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +Scene2810::Scene2810(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule) { + + Sprite *tempSprite; + + SetMessageHandler(&Scene2810::handleMessage); + + setBackground(0x26508804); + setPalette(0x26508804); + insertScreenMouse(0x0880026D); + + _sprite6 = insertStaticSprite(0x03615227, 1100); + _sprite5 = insertStaticSprite(0xE059A224, 1100); + + _clipRects[0].x1 = 0; + _clipRects[0].y1 = 0; + _clipRects[0].x2 = 640; + _clipRects[0].y2 = 400; + _clipRects[1].x1 = _sprite5->getDrawRect().x; + _clipRects[1].y1 = 400; + _clipRects[1].x2 = _sprite6->getDrawRect().x2(); + _clipRects[1].y2 = 480; + + if (getGlobalVar(V_KLAYMEN_SMALL)) { + _asTape = insertSprite(this, 0, 900, 245, 429, 0x9148A011); + addCollisionSprite(_asTape); + } else { + _asTape = insertSprite(this, 0, 1100, 245, 429, 0x9148A011); + addCollisionSprite(_asTape); + } + + _sprite1 = insertStaticSprite(0x430001C4, 1200); + + if (getGlobalVar(V_LADDER_DOWN)) { + setGlobalVar(V_BEEN_STATUE_ROOM, 1); + if (getGlobalVar(V_KLAYMEN_SMALL)) { + _sprite4 = insertStaticSprite(0x82653808, 100); + } else { + _sprite4 = insertStaticSprite(0x82653808, 1100); + } + _sprite4->setClipRect(0, _sprite1->getDrawRect().y, 640, 480); + } + + if (which < 0) { + if (getGlobalVar(V_KLAYMEN_SMALL)) { + insertKlaymen(240, 448); + _klaymen->setClipRect(_sprite5->getDrawRect().x, 0, 640, 480); + setMessageList(0x004AE438); + setRectList(0x004AE810); + _isRopingDown = false; + removeCollisionSprite(_asTape); + } else { + insertKlaymen(300, 424, _clipRects, 2); + setMessageList(0x004AE438); + if (getGlobalVar(V_LADDER_DOWN)) + loadDataResource(0x84130112); + else + loadDataResource(0x84500132); + tempSprite = insertSprite(_klaymen); + tempSprite->setClipRect(0, _sprite1->getDrawRect().y, 640, 480); + _clipRects[0].y1 = _sprite1->getDrawRect().y; + _isRopingDown = false; + } + } else if (which == 1) { + insertKlaymen(186, 64, _clipRects, 2); + setMessageList(0x004AE440); + loadDataResource(0x84130112); + tempSprite = insertSprite(_klaymen); + tempSprite->setClipRect(0, _sprite1->getDrawRect().y, 640, 480); + _isRopingDown = true; + _clipRects[0].y1 = _sprite1->getDrawRect().y; + } else if (which == 5) { + insertStaticSprite(0xC3007EA0, 100); + _sprite2 = insertStaticSprite(0x02780936, 1100); + _sprite3 = insertStaticSprite(0x1CA02160, 1100); + _asRope = insertSprite(this, 384); + insertKlaymen(384, 0, _clipRects, 0); + sendEntityMessage(_klaymen, 0x1014, _asRope); + setMessageList(0x004AE738); + _klaymen->setClipRect(0, _sprite2->getDrawRect().y, 640, _sprite3->getDrawRect().y2()); + _asRope->setClipRect(0, _sprite2->getDrawRect().y, 640, _sprite3->getDrawRect().y2()); + _vm->_soundMan->addSound(0x84400112, 0xC874EE6C); + _vm->_soundMan->playSoundLooping(0xC874EE6C); + _vm->_soundMan->setSoundVolume(0xC874EE6C, 50); + _isRopingDown = false; + } else if ((which >= 11 && which <= 14) || (which >= 19 && which <= 22) || which == 3) { + if (getGlobalVar(V_KLAYMEN_SMALL)) { + insertKlaymen((int16)getGlobalVar(V_KLAYMEN_SAVED_X), 448); + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) + _klaymen->setDoDeltaX(1); + _klaymen->setClipRect(_sprite5->getDrawRect().x, 0, 640, 480); + setMessageList(0x004AE6D8); + setRectList(0x004AE810); + _isRopingDown = false; + removeCollisionSprite(_asTape); + } else { + insertKlaymenLadder(); + if (getGlobalVar(V_LADDER_DOWN_ACTION)) { + setMessageList(0x004AE6E8); + setGlobalVar(V_LADDER_DOWN_ACTION, 0); + _isRopingDown = false; + } else { + setMessageList(0x004AE6D8); + _isRopingDown = false; + } + } + } else if (which >= 15 && which <= 18) { + insertKlaymenLadder(); + setMessageList(0x004AE6E0); + _isRopingDown = false; + } else if (which == 4) { + if (getGlobalVar(V_KLAYMEN_SMALL)) { + insertKlaymen(473, 448); + _klaymen->setClipRect(_sprite5->getDrawRect().x, 0, 640, 480); + setMessageList(0x004AE428); + setRectList(0x004AE810); + _isRopingDown = false; + removeCollisionSprite(_asTape); + } else { + insertKlaymen(450, 424, _clipRects, 2); + setMessageList(0x004AE418); + if (getGlobalVar(V_LADDER_DOWN)) + loadDataResource(0x84130112); + else + loadDataResource(0x84500132); + tempSprite = insertSprite(_klaymen); + tempSprite->setClipRect(0, _sprite1->getDrawRect().y, 640, 480); + _clipRects[0].y1 = _sprite1->getDrawRect().y; + _isRopingDown = false; + } + } else { + insertKlaymen(120, 448); + _klaymen->setClipRect(_sprite5->getDrawRect().x, 0, 640, 480); + setMessageList(0x004AE410); + setRectList(0x004AE810); + _isRopingDown = false; + removeCollisionSprite(_asTape); + } + +} + +Scene2810::~Scene2810() { + setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); + setGlobalVar(V_KLAYMEN_SAVED_X, _klaymen->getX()); + _vm->_soundMan->deleteSoundGroup(0x84400112); +} + +void Scene2810::insertKlaymenLadder() { + Sprite *tempSprite; + + if (getGlobalVar(V_LADDER_DOWN_ACTION)) { + insertKlaymen(430, 424, _clipRects, 2); + _klaymen->setDoDeltaX(1); + } else { + insertKlaymen((int16)getGlobalVar(V_KLAYMEN_SAVED_X), 424, _clipRects, 2); + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) + _klaymen->setDoDeltaX(1); + } + if (getGlobalVar(V_LADDER_DOWN)) + loadDataResource(0x84130112); + else + loadDataResource(0x84500132); + tempSprite = insertSprite(_klaymen); + tempSprite->setClipRect(0, _sprite1->getDrawRect().y, 640, 480); + _clipRects[0].y1 = _sprite1->getDrawRect().y; +} + +uint32 Scene2810::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0xE574F14C) + setMessageList(0x004AE458); + else if (param.asInteger() == 0x7214A05C || param.asInteger() == 0x2905E574) + setMessageList(0x004AE4A8); + else if (param.asInteger() == 0x7274E24C || param.asInteger() == 0x2D24E572) + setMessageList(0x004AE4D0); + else if (param.asInteger() == 0x4A07A040 || param.asInteger() == 0x190426F5) + setMessageList(0x004AE4F8); + else if (param.asInteger() == 0x6604200C || param.asInteger() == 0x2100E435) + setMessageList(0x004AE520); + else if (param.asInteger() == 0xE216A05C || param.asInteger() == 0x0905EC74) + setMessageList(0x004AE548); + else if (param.asInteger() == 0x721DA05C || param.asInteger() == 0xB905E574) + setMessageList(0x004AE570); + else if (param.asInteger() == 0x6214E09C || param.asInteger() == 0x2D09E474) + setMessageList(0x004AE598); + else if (param.asInteger() == 0x6276A04C || param.asInteger() == 0x0904E472) + setMessageList(0x004AE5C0); + else if (param.asInteger() == 0x6E14A00C || param.asInteger() == 0x2900E4B4) + setMessageList(0x004AE5E8); + else if (param.asInteger() == 0x6014A04D || param.asInteger() == 0x2904F454) + setMessageList(0x004AE610); + else if (param.asInteger() == 0x6215A3C4 || param.asInteger() == 0x393C6474) + setMessageList(0x004AE638); + else if (param.asInteger() == 0x6A54E24D || param.asInteger() == 0x2D24F4F0) + setMessageList(0x004AE660); + else if (param.asInteger() == 0x2064294C || param.asInteger() == 0x2194E053) + setMessageList(0x004AE688); + break; + case 0x2000: + setRectList(0x004AE800); + _isRopingDown = true; + break; + case 0x2001: + if (getGlobalVar(V_LADDER_DOWN)) + loadDataResource(0x84130112); + else + loadDataResource(0x84500132); + _isRopingDown = false; + break; + case 0x4826: + if (sender == _asTape && getGlobalVar(V_KLAYMEN_SMALL) == 0 && !_isRopingDown) { + sendEntityMessage(_klaymen, 0x1014, _asTape); + setMessageList(0x004AE750); + } + break; + } + return messageResult; +} + +AsScene2812Winch::AsScene2812Winch(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100) { + + createSurface1(0x20DA08A0, 1200); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2812Winch::handleMessage); + setVisible(false); + _x = 280; + _y = 184; +} + +AsScene2812Winch::~AsScene2812Winch() { + _vm->_soundMan->deleteSoundGroup(0x00B000E2); +} + +uint32 AsScene2812Winch::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + startAnimation(0x20DA08A0, 0, -1); + setVisible(true); + _vm->_soundMan->addSound(0x00B000E2, 0xC874EE6C); + _vm->_soundMan->playSoundLooping(0xC874EE6C); + break; + case 0x3002: + startAnimation(0x20DA08A0, 7, -1); + break; + } + return messageResult; +} + +AsScene2812Rope::AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1100), _parentScene(parentScene) { + + createSurface(990, 68, 476); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2812Rope::handleMessage); + SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); + startAnimation(0xAE080551, 0, -1); + _x = 334; + _y = 201; +} + +uint32 AsScene2812Rope::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4806: + setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0); + stRopingDown(); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +uint32 AsScene2812Rope::hmRopingDown(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene2812Rope::stRopingDown() { + sendMessage(_parentScene, 0x4806, 0); + startAnimation(0x9D098C23, 0, -1); + SetMessageHandler(&AsScene2812Rope::hmRopingDown); +} + +AsScene2812TrapDoor::AsScene2812TrapDoor(NeverhoodEngine *vm) + : AnimatedSprite(vm, 0x805D0029, 100, 320, 240) { + + SetMessageHandler(&AsScene2812TrapDoor::handleMessage); + _newStickFrameIndex = 0; +} + +uint32 AsScene2812TrapDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + startAnimation(0x805D0029, 0, -1); + playSound(0, 0xEA005F40); + _newStickFrameIndex = STICK_LAST_FRAME; + break; + } + return messageResult; +} + +Scene2812::Scene2812(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _paletteArea(0) { + + if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) + setGlobalVar(V_KEY3_LOCATION, 3); + + SetMessageHandler(&Scene2812::handleMessage); + SetUpdateHandler(&Scene2812::update); + + setRectList(0x004AF700); + + setBackground(0x03600606); + setPalette(0x03600606); + addEntity(_palette); + _palette->addBasePalette(0x03600606, 0, 256, 0); + + _sprite1 = insertStaticSprite(0x0C06C860, 1100); + insertScreenMouse(0x0060203E); + + if (getGlobalVar(V_KEY3_LOCATION) == 3) { + _asKey = insertSprite(this, 2, 1100, 474, 437); + addCollisionSprite(_asKey); + } + + _ssTape = insertSprite(this, 6, 1100, 513, 437, 0xA1361863); + addCollisionSprite(_ssTape); + + _asWinch = insertSprite(); + _asTrapDoor = insertSprite(); + _asRope = insertSprite(this); + + _sprite2 = insertStaticSprite(0x08478078, 1100); + _sprite3 = insertStaticSprite(0x2203B821, 1100); + _sprite4 = insertStaticSprite(0x08592134, 1100); + + if (which < 0) { + _isRopingDown = false; + insertKlaymen(272, 432); + setMessageList(0x004AF560); + _sprite1->setVisible(false); + _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); + } else if (which == 1) { + _isRopingDown = false; + insertKlaymen(338, 398); + setMessageList(0x004AF588); + setPaletteArea1(true); + _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite1->getDrawRect().x2(), _sprite3->getDrawRect().y2()); + } else if (which == 2) { + _isRopingDown = false; + if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) { + insertKlaymen(554, 432); + _klaymen->setDoDeltaX(1); + } else { + insertKlaymen(394, 432); + } + setMessageList(0x004AF5F0); + _sprite1->setVisible(false); + _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); + } else { + _isRopingDown = true; + insertKlaymen(150, 582); + setMessageList(0x004AF568); + setPaletteArea2(true); + _sprite1->setVisible(false); + _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); + } + + _asRope->setClipRect(0, _sprite2->getDrawRect().y, 640, _sprite3->getDrawRect().y2()); + +} + +void Scene2812::update() { + if (_klaymen->getX() < 220) + setPaletteArea2(false); + else if (_klaymen->getX() < 240) + setPaletteArea0(false); + Scene::update(); +} + +uint32 Scene2812::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x0004269B) + sendEntityMessage(_klaymen, 0x1014, _asRope); + break; + case 0x2001: + _isRopingDown = true; + setRectList(0x004AF710); + _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite4->getDrawRect().y2()); + break; + case 0x2002: + _isRopingDown = false; + setRectList(0x004AF700); + _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); + break; + case 0x4806: + sendMessage(_asWinch, 0x2000, 0); + sendMessage(_asTrapDoor, 0x2000, 0); + break; + case 0x4826: + if (sender == _ssTape && !_isRopingDown) { + sendEntityMessage(_klaymen, 0x1014, _ssTape); + setMessageList(0x004AF658); + } else if (sender == _asKey && !_isRopingDown) { + sendEntityMessage(_klaymen, 0x1014, _asKey); + setMessageList(0x004AF668); + } + break; + case 0x482A: + setPaletteArea1(false); + _sprite1->setVisible(true); + _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite1->getDrawRect().x2(), _sprite3->getDrawRect().y2()); + break; + case 0x482B: + setPaletteArea0(false); + _sprite1->setVisible(false); + _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); + break; + } + return messageResult; +} + +void Scene2812::setPaletteArea0(bool instantly) { + if (_paletteArea != 0) { + _paletteArea = 0; + updatePaletteArea(instantly); + } +} + +void Scene2812::setPaletteArea1(bool instantly) { + if (_paletteArea != 1) { + _paletteArea = 1; + updatePaletteArea(instantly); + } +} + +void Scene2812::setPaletteArea2(bool instantly) { + if (_paletteArea != 2) { + _paletteArea = 2; + updatePaletteArea(instantly); + } +} + +void Scene2812::updatePaletteArea(bool instantly) { + if (_paletteArea == 0) + _palette->addBasePalette(0x05D30F11, 0, 64, 0); + else if (_paletteArea == 1) + _palette->addBasePalette(0x92CA2C9B, 0, 64, 0); + else if (_paletteArea == 2) + _palette->addBasePalette(0x381F92C5, 0, 64, 0); + _palette->startFadeToPalette(instantly ? 0 : 12); +} + +Scene2822::Scene2822(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _countdown(0), _scrollIndex(0) { + + SetMessageHandler(&Scene2822::handleMessage); + SetUpdateHandler(&Scene2822::update); + _background = new Background(_vm, 0xD542022E, 0, 0); + addBackground(_background); + _background->getSurface()->getDrawRect().y = -10; + setPalette(0xD542022E); + insertPuzzleMouse(0x0028D089, 20, 620); + _ssButton = insertStaticSprite(0x1A4D4120, 1100); + _ssButton->setVisible(false); + loadSound(2, 0x19044E72); +} + +void Scene2822::update() { + + static const int16 kScene2822BackgroundYPositions[] = { + 0, -20, -5, -15, -8, -12, -9, -11, -10, 0 + }; + + Scene::update(); + + if (_countdown != 0) { + if ((--_countdown) == 0) { + if (_countdownStatus == 0) { + _ssButton->setVisible(false); + _countdownStatus = 1; + _countdown = 48; + } else if (_countdownStatus == 1) { + playSound(0, 0x1384CB60); + _countdownStatus = 2; + _countdown = 12; + } else if (_countdownStatus == 2 && getGlobalVar(V_LADDER_DOWN_ACTION)) { + leaveScene(0); + } + } else if (_countdownStatus == 2 && getGlobalVar(V_LADDER_DOWN_ACTION)) { + if (_scrollIndex < 9) { + _background->getSurface()->getDrawRect().y = kScene2822BackgroundYPositions[_scrollIndex]; + _scrollIndex++; + } else { + _background->getSurface()->getDrawRect().y = -10; + } + } + } + +} + +uint32 Scene2822::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { + leaveScene(0); + } else if (param.asPoint().x >= 257 && param.asPoint().y >= 235 && + param.asPoint().x <= 293 && param.asPoint().y <= 273) { + _ssButton->setVisible(true); + _countdownStatus = 0; + _countdown = 12; + playSound(1, 0x44061000); + if (getGlobalVar(V_LADDER_DOWN) == 0) { + setGlobalVar(V_LADDER_DOWN, 1); + setGlobalVar(V_LADDER_DOWN_ACTION, 1); + SetMessageHandler(NULL); + playSound(2); + _mouseCursor->setVisible(false); + } + } + break; + } + return messageResult; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module2800.h b/engines/neverhood/modules/module2800.h new file mode 100644 index 0000000000..fe62f11307 --- /dev/null +++ b/engines/neverhood/modules/module2800.h @@ -0,0 +1,505 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE2800_H +#define NEVERHOOD_MODULES_MODULE2800_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +// Module2800 + +class Module2800 : public Module { +public: + Module2800(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module2800(); +protected: + int _sceneNum; + uint32 _currentMusicFileHash; + MusicResource *_musicResource; + void createScene(int sceneNum, int which); + void updateScene(); + void updateMusic(bool halfVolume); +}; + +class Scene2801 : public Scene { +public: + Scene2801(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene2801(); +protected: + Sprite *_asTape; + uint32 _paletteHash; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2802 : public Scene { +public: + Scene2802(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene2802(); +protected: + SmackerPlayer *_smackerPlayer; + uint _currRadioMusicIndex; + int _currTuneStatus; + int _countdown1; + int _countdown2; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void incRadioMusicIndex(int delta); + void changeTuneStatus(int prevTuneStatus, int newTuneStatus); +}; + +class AsScene2803LightCord : public AnimatedSprite { +public: + AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y); + void stPulled(); + void stIdle(); + void setFileHashes(uint32 fileHash1, uint32 fileHash2); +protected: + Scene *_parentScene; + uint32 _fileHash1, _fileHash2; + bool _isPulled, _isBusy; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmPulled(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2803TestTubeOne : public AnimatedSprite { +public: + AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2); +protected: + uint32 _fileHash1, _fileHash2; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2803Rope : public AnimatedSprite { +public: + AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmReleased(int messageNum, const MessageParam ¶m, Entity *sender); + void stReleased(); + void stHide(); +}; + +class Scene2803 : public Scene { +public: + Scene2803(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + StaticSprite *_asTestTubeOne; + StaticSprite *_asTestTubeTwo; + StaticSprite *_asTestTubeThree; + Sprite *_asRope; + AsScene2803LightCord *_asLightCord; + StaticSprite *_sprite3; + StaticSprite *_sprite4; + StaticSprite *_sprite5; + StaticSprite *_sprite6; + StaticSprite *_sprite7; + StaticSprite *_sprite8; + StaticSprite *_sprite9; + Sprite *_sprite10; + NRect _clipRectsFloor[2]; + NRect _clipRectsStairs[3]; + int _paletteArea; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void upKlaymenStairs(); + void klaymenStairs(); + void klaymenFloor(); + void toggleBackground(); + void changeBackground(); + void setPaletteArea0(); + void setPaletteArea1(); + void updatePaletteArea(); +}; + +class Scene2803Small : public Scene { +public: + Scene2803Small(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + int _paletteArea; + Sprite *_sprite1; + Sprite *_sprite2; + Sprite *_sprite3; + Sprite *_sprite4; + Sprite *_sprite5; + Sprite *_sprite6; + Sprite *_sprite7; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void upKlaymenSlope(); + void upKlaymenFloor(); + void klaymenSlope(); + void klaymenFloor(); + void setPaletteArea0(); + void setPaletteArea1(); + void setPaletteArea2(); + void setPaletteArea3(); + void updatePaletteArea(bool instantly); +}; + +class Scene2804; + +class SsScene2804RedButton : public StaticSprite { +public: + SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene); +protected: + Scene2804 *_parentScene; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene2804LightCoil : public StaticSprite { +public: + SsScene2804LightCoil(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene2804BeamCoilBody : public StaticSprite { +public: + SsScene2804BeamCoilBody(NeverhoodEngine *vm); +}; + +class SsScene2804LightTarget : public StaticSprite { +public: + SsScene2804LightTarget(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene2804Flash : public StaticSprite { +public: + SsScene2804Flash(NeverhoodEngine *vm); + void show(); +}; + +class AsScene2804CrystalWaves : public AnimatedSprite { +public: + AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex); + void show(); + void hide(); +protected: + uint _crystalIndex; +}; + +class AsScene2804Crystal : public AnimatedSprite { +public: + AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex); + void show(); + void hide(); + void activate(); + int16 getColorNum() const { return _colorNum; } +protected: + AsScene2804CrystalWaves *_asCrystalWaves; + uint _crystalIndex; + int16 _colorNum; + bool _isLightOn; + bool _isShowing; +}; + +class SsScene2804CrystalButton : public StaticSprite { +public: + SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex); +protected: + Scene2804 *_parentScene; + AsScene2804Crystal *_asCrystal; + uint _crystalIndex; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2804BeamCoil : public AnimatedSprite { +public: + AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody); + virtual ~AsScene2804BeamCoil(); +protected: + Scene *_parentScene; + SsScene2804BeamCoilBody *_ssBeamCoilBody; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void show(); + void hide(); + void stBeaming(); + uint32 hmBeaming(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2804BeamTarget : public AnimatedSprite { +public: + AsScene2804BeamTarget(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2804 : public Scene { +public: + Scene2804(NeverhoodEngine *vm, Module *parentModule, int which); + bool isWorking() const { return _isWorking; } +protected: + int _countdown1; + int _countdown2; + int _countdown3; + int _beamStatus; + bool _isSolved; + bool _isWorking; + Sprite *_ssRedButton; + Sprite *_asCoil; + Sprite *_asTarget; + SsScene2804Flash *_ssFlash; + AsScene2804Crystal *_asCrystals[5]; + Sprite *_ssCrystalButtons[5]; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2805 : public Scene { +public: + Scene2805(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_sprite1; + Sprite *_sprite2; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2806Spew : public AnimatedSprite { +public: + AsScene2806Spew(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2806 : public Scene { +public: + Scene2806(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + NPointArray *_pointList; + int _pointIndex; + NRect _clipRects[4]; + Sprite *_sprite1; + Sprite *_sprite2; + Sprite *_sprite3; + Sprite *_sprite4; + Sprite *_asSpew; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void update(); + void findClosestPoint(); +}; + +class Scene2807 : public Scene { +public: + Scene2807(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene2808Dispenser : public StaticSprite { +public: + SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex); + void startCountdown(int index); +protected: + Scene *_parentScene; + int _countdown; + int _testTubeSetNum, _testTubeIndex; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2808TestTube : public AnimatedSprite { +public: + AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser); + void fill(); + void flush(); + uint32 getFillLevel() const { return _fillLevel; } +protected: + SsScene2808Dispenser *_ssDispenser; + int _testTubeSetNum; + uint32 _fillLevel; + int _testTubeIndex; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2808Handle : public AnimatedSprite { +public: + AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum); + void activate(); + void stActivated(); +protected: + Scene *_parentScene; + int _testTubeSetNum; + bool _isActivated; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmActivating(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2808Flow : public AnimatedSprite { +public: + AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum); + void start(); + void stKeepFlowing(); +protected: + Scene *_parentScene; + int _testTubeSetNum; + uint32 hmFlowing(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2808LightEffect : public AnimatedSprite { +public: + AsScene2808LightEffect(NeverhoodEngine *vm, int which); +protected: + int _countdown; + void update(); +}; + +class Scene2808 : public Scene { +public: + Scene2808(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + int _countdown; + int _testTubeSetNum; + AsScene2808Flow *_asFlow; + int _leaveResult; + bool _isFlowing; + AsScene2808TestTube *_asTestTubes[3]; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void update(); + bool isMixtureGood(); + bool isAnyTestTubeFilled(); +}; + +class AsScene2809Spew : public AnimatedSprite { +public: + AsScene2809Spew(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2809 : public Scene { +public: + Scene2809(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + NPointArray *_pointList; + int _pointIndex; + NRect _clipRects[4]; + Sprite *_sprite1; + Sprite *_sprite2; + Sprite *_sprite3; + Sprite *_sprite4; + Sprite *_asSpew; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void findClosestPoint(); +}; + +class AsScene2810Rope : public AnimatedSprite { +public: + AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2810 : public Scene { +public: + Scene2810(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene2810(); +protected: + Sprite *_sprite1; + Sprite *_sprite2; + Sprite *_sprite3; + Sprite *_asRope; + Sprite *_sprite4; + Sprite *_asTape; + Sprite *_sprite5; + Sprite *_sprite6; + bool _isRopingDown; + NRect _clipRects[2]; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void insertKlaymenLadder(); +}; + +class AsScene2812Winch : public AnimatedSprite { +public: + AsScene2812Winch(NeverhoodEngine *vm); + virtual ~AsScene2812Winch(); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2812Rope : public AnimatedSprite { +public: + AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmRopingDown(int messageNum, const MessageParam ¶m, Entity *sender); + void stRopingDown(); +}; + +class AsScene2812TrapDoor : public AnimatedSprite { +public: + AsScene2812TrapDoor(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2812 : public Scene { +public: + Scene2812(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_asWinch; + Sprite *_asTrapDoor; + Sprite *_asRope; + Sprite *_sprite3; + Sprite *_sprite2; + Sprite *_sprite4; + Sprite *_ssTape; + Sprite *_asKey; + Sprite *_sprite1; + bool _isRopingDown; + int _paletteArea; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void setPaletteArea0(bool instantly); + void setPaletteArea1(bool instantly); + void setPaletteArea2(bool instantly); + void updatePaletteArea(bool instantly); +}; + +class Scene2822 : public Scene { +public: + Scene2822(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_ssButton; + int _scrollIndex; + int _countdown; + int _countdownStatus; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE2800_H */ diff --git a/engines/neverhood/modules/module2900.cpp b/engines/neverhood/modules/module2900.cpp new file mode 100644 index 0000000000..bd95b82f4c --- /dev/null +++ b/engines/neverhood/modules/module2900.cpp @@ -0,0 +1,439 @@ +/* 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/modules/module2900.h" +#include "neverhood/gamemodule.h" +#include "neverhood/modules/module1100.h" +#include "neverhood/modules/module1300.h" +#include "neverhood/modules/module1700.h" +#include "neverhood/modules/module2000.h" +#include "neverhood/modules/module2100.h" +#include "neverhood/modules/module2800.h" + +namespace Neverhood { + +Module2900::Module2900(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + if (which >= 0) + setGlobalVar(V_TELEPORTER_WHICH, which); + + createScene(0, 0); + +} + +void Module2900::createScene(int sceneNum, int which) { + debug("Module2900::createScene(%d, %d)", sceneNum, which); + _sceneNum = sceneNum; + switch (_sceneNum) { + case 0: + _vm->gameState().sceneNum = 0; + _childObject = new Scene2901(_vm, this, getGlobalVar(V_TELEPORTER_WHICH)); + break; + case 1: + _vm->gameState().sceneNum = 0; + _childObject = new Scene2805(_vm, this, which); + break; + case 2: + _vm->gameState().sceneNum = 0; + _childObject = new Scene2101(_vm, this, which); + break; + case 3: + _vm->gameState().sceneNum = 0; + _childObject = new Scene1306(_vm, this, which); + break; + case 4: + _vm->gameState().sceneNum = 0; + _childObject = new Scene1705(_vm, this, which); + break; + case 5: + _vm->gameState().sceneNum = 0; + _childObject = new Scene1109(_vm, this, which); + break; + case 6: + _vm->gameState().sceneNum = 0; + _childObject = new Scene2001(_vm, this, which); + break; + } + SetUpdateHandler(&Module2900::updateScene); + _childObject->handleUpdate(); +} + +void Module2900::updateScene() { + if (!updateChild()) { + switch (_sceneNum) { + case 0: + if (_moduleResult == (uint32)-1) { + leaveModule((uint32)-1); + } else { + _teleporterModuleResult = _moduleResult; + switch (getGlobalVar(V_TELEPORTER_WHICH)) { + case 0: + createScene(3, 4); + break; + case 1: + createScene(2, 2); + break; + case 2: + createScene(5, 2); + break; + case 3: + createScene(4, 2); + break; + case 4: + createScene(6, 2); + break; + case 5: + createScene(1, 2); + break; + default: + leaveModule(_moduleResult); + break; + } + } + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + leaveModule(_teleporterModuleResult); + break; + } + } +} + +static const uint32 kScene2901FileHashes1[] = { + 0x023023B4, + 0x36204507, + 0x046CF08E, + 0x9313A237, + 0xA651F246, + 0x02108034 +}; + +static const uint32 kScene2901FileHashes2[] = { + 0x023B002B, + 0x0450336A, + 0xCF08A04E, + 0x3A233939, + 0x1F242A6D, + 0x08030029 +}; + +static const uint32 kSsScene2901LocationButtonFileHashes[] = { + 0x2311326A, + 0x212323AC, + 0x10098138, + 0x25213167, + 0x1119A363, + 0x94452612, + 0x39464212, + 0x01860450, + 0x53002104, + 0x58E68412, + 0x18600300, + 0xB650A890, + 0x2452A7C4, + 0xA0232748, + 0x08862B02, + 0x2491E648, + 0x0010EB46, + 0x214C8A11, + 0x16A31921, + 0x0AC33A00, + 0x238028AA, + 0x26737A21, + 0x063039A8, + 0x51286C60, + 0x464006B4, + 0x42242538, + 0x20716010, + 0x4A2000AE, + 0x225124A6, + 0x28E82E45, + 0x58652C04, + 0xC82210A4, + 0x62A84060, + 0xC0693CB4, + 0x22212C64, + 0x5034EA71 +}; + +static const NPoint kSsScene2901LocationButtonPoints[] = { + {525, 120}, {576, 149}, {587, 205}, + {538, 232}, {484, 205}, {479, 153} +}; + +static const uint32 kSsScene2901LocationButtonLightFileHashes1[] = { + 0x03136246, + 0x2106216E, + 0x4025A13A, + 0x21816927, + 0x110B2202, + 0xCC0522B2, + 0x3CC24258, + 0x59C600F0, + 0x534A2480, + 0x50E61019, + 0x34400150, + 0x225BA090, + 0xB059AFC4, + 0xE093A741, + 0x0086BF09, + 0x3281E760, + 0xA048AB42, + 0x20649C01, + 0x14611904, + 0x26E33850, + 0x23A52A68, + 0xA2733024, + 0x10203880, + 0x1B2DE860, + 0x0644A6EC, + 0x426E20BC, + 0x80292014, + 0x4360B02E, + 0x22742664, + 0x98682705, + 0x0925B82C, + 0x5C2918A4, + 0xD2284920, + 0x41083CA6, + 0x6824A864, + 0x50266B10 +}; + +static const uint32 kSsScene2901LocationButtonLightFileHashes2[] = { + 0x43C46D4C, + 0x43C4AD4C, + 0x43C52D4C, + 0x43C62D4C, + 0x43C02D4C, + 0x43CC2D4C +}; + +static const uint32 kSsScene2901BrokenButtonFileHashes[] = { + 0x3081BD3A, + 0xD3443003, + 0x0786A320, + 0xE3A22029, + 0x61611814, + 0x425848E2 +}; + +static const uint32 kSsScene2901BigButtonFileHashes[] = { + 0x010D7748, + 0x9D02019A, + 0x351A2F43, + 0x448138E5, + 0x02788CF0, + 0x71718024 +}; + +SsScene2901LocationButton::SsScene2901LocationButton(NeverhoodEngine *vm, Scene *parentScene, int which, uint index) + : StaticSprite(vm, 900), _parentScene(parentScene), _index(index), _countdown1(0) { + + const NPoint &pt = kSsScene2901LocationButtonPoints[_index]; + + loadSprite(kSsScene2901LocationButtonFileHashes[which * 6 + index], kSLFDefDrawOffset | kSLFDefPosition, 800); + _collisionBounds.set(pt.x - 25, pt.y - 25, pt.x + 25, pt.y + 25); + setVisible(false); + loadSound(0, 0x440430C0); + SetUpdateHandler(&SsScene2901LocationButton::update); + SetMessageHandler(&SsScene2901LocationButton::handleMessage); +} + +void SsScene2901LocationButton::update() { + updatePosition(); + if (_countdown1 != 0 && (--_countdown1) == 0) { + setVisible(false); + } +} + +uint32 SsScene2901LocationButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown1 == 0) { + playSound(0); + setVisible(true); + _countdown1 = 4; + sendMessage(_parentScene, 0x2001, _index); + } + messageResult = 1; + break; + } + return messageResult; +} + +SsScene2901LocationButtonLight::SsScene2901LocationButtonLight(NeverhoodEngine *vm, int which, uint index) + : StaticSprite(vm, 900), _index(index) { + + loadSprite(kSsScene2901LocationButtonLightFileHashes1[which * 6 + index], kSLFDefDrawOffset | kSLFDefPosition, 900); + setVisible(false); + loadSound(0, kSsScene2901LocationButtonLightFileHashes2[_index]); +} + +void SsScene2901LocationButtonLight::show() { + playSound(0); + setVisible(true); + updatePosition(); +} + +void SsScene2901LocationButtonLight::hide() { + setVisible(false); + updatePosition(); +} + +SsScene2901BrokenButton::SsScene2901BrokenButton(NeverhoodEngine *vm, int which) + : StaticSprite(vm, 900) { + + loadSprite(kSsScene2901BrokenButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 900); +} + +SsScene2901BigButton::SsScene2901BigButton(NeverhoodEngine *vm, Scene *parentScene, int which) + : StaticSprite(vm, 900), _parentScene(parentScene), _which(which), _countdown1(0) { + + loadSprite(kSsScene2901BigButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 400); + _collisionBounds.set(62, 94, 322, 350); + setVisible(false); + loadSound(0, 0xF3D420C8); + SetUpdateHandler(&SsScene2901BigButton::update); + SetMessageHandler(&SsScene2901BigButton::handleMessage); +} + +void SsScene2901BigButton::update() { + updatePosition(); + if (_countdown1 != 0 && (--_countdown1) == 0) { + setVisible(false); + sendMessage(_parentScene, 0x2000, 0); + } +} + +uint32 SsScene2901BigButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown1 == 0) { + playSound(0); + setVisible(true); + _countdown1 = 4; + } + messageResult = 1; + break; + } + return messageResult; +} + +Scene2901::Scene2901(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _currLocationButtonNum(which), _selectedButtonNum(which), + _currWhirlButtonNum(0), _prevWhirlButtonNum(0), _countdown1(1), _skipCountdown(0), _blinkOn(0) { + + _isButton2Broken = getGlobalVar(V_ENTRANCE_OPEN) != 0; + + setSubVar(V_TELEPORTER_DEST_AVAILABLE, which, 1); + setSubVar(V_TELEPORTER_DEST_AVAILABLE, 5, 1); + setSubVar(V_TELEPORTER_DEST_AVAILABLE, 4, 1); + + if (_currLocationButtonNum == 3) + setSubVar(V_TELEPORTER_DEST_AVAILABLE, 2, 1); + + setBackground(kScene2901FileHashes1[_currLocationButtonNum]); + setPalette(kScene2901FileHashes1[_currLocationButtonNum]); + + for (uint i = 0; i < 6; ++i) { + if (i != 2 || !_isButton2Broken) { + _ssLocationButtons[i] = insertSprite(this, _currLocationButtonNum, i); + addCollisionSprite(_ssLocationButtons[i]); + _ssLocationButtonLights[i] = insertSprite(_currLocationButtonNum, i); + } + } + + if (_isButton2Broken) + insertSprite(_currLocationButtonNum); + + _ssBigButton = insertSprite(this, _currLocationButtonNum); + addCollisionSprite(_ssBigButton); + + insertPuzzleMouse(kScene2901FileHashes2[_currLocationButtonNum], 20, 620); + + SetUpdateHandler(&Scene2901::update); + SetMessageHandler(&Scene2901::handleMessage); + +} + +void Scene2901::update() { + Scene::update(); + if (_countdown1 != 0 && (--_countdown1) == 0) { + if (_currLocationButtonNum == _selectedButtonNum) { + _ssLocationButtonLights[_currWhirlButtonNum]->hide(); + ++_currWhirlButtonNum; + while (!getSubVar(V_TELEPORTER_DEST_AVAILABLE, _currWhirlButtonNum) || (_currWhirlButtonNum == 2 && _isButton2Broken) || _currLocationButtonNum == _currWhirlButtonNum) { + ++_currWhirlButtonNum; + if (_currWhirlButtonNum >= 6) + _currWhirlButtonNum = 0; + } + if (_currWhirlButtonNum != _prevWhirlButtonNum || _skipCountdown == 0) { + _ssLocationButtonLights[_currWhirlButtonNum]->show(); + _skipCountdown = 4; + } + _countdown1 = 2; + --_skipCountdown; + _prevWhirlButtonNum = _currWhirlButtonNum; + } else if (_blinkOn) { + _blinkOn = false; + _ssLocationButtonLights[_selectedButtonNum]->hide(); + _countdown1 = 16; + } else { + _blinkOn = true; + _ssLocationButtonLights[_selectedButtonNum]->show(); + _countdown1 = 4; + } + } +} + +uint32 Scene2901::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) + leaveScene((uint32)-1); + break; + case 0x2000: + if (_currLocationButtonNum != _selectedButtonNum) + leaveScene(_selectedButtonNum); + break; + case 0x2001: + if (_currLocationButtonNum == _selectedButtonNum) + _selectedButtonNum = _currWhirlButtonNum; + _ssLocationButtonLights[_selectedButtonNum]->hide(); + _selectedButtonNum = param.asInteger(); + if (!getSubVar(V_TELEPORTER_DEST_AVAILABLE, _selectedButtonNum)) + _selectedButtonNum = _currLocationButtonNum; + break; + } + return 0; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module2900.h b/engines/neverhood/modules/module2900.h new file mode 100644 index 0000000000..75b29567f6 --- /dev/null +++ b/engines/neverhood/modules/module2900.h @@ -0,0 +1,102 @@ +/* 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE2900_H +#define NEVERHOOD_MODULES_MODULE2900_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +// Module2900 + +class Module2900 : public Module { +public: + Module2900(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + int _sceneNum; + int _teleporterModuleResult; + void createScene(int sceneNum, int which); + void updateScene(); + void updateMusic(bool halfVolume); +}; + +class SsScene2901LocationButton : public StaticSprite { +public: + SsScene2901LocationButton(NeverhoodEngine *vm, Scene *parentScene, int which, uint index); +protected: + Scene *_parentScene; + uint _index; + int _countdown1; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene2901LocationButtonLight : public StaticSprite { +public: + SsScene2901LocationButtonLight(NeverhoodEngine *vm, int which, uint index); + void show(); + void hide(); +protected: + uint _index; +}; + +class SsScene2901BrokenButton : public StaticSprite { +public: + SsScene2901BrokenButton(NeverhoodEngine *vm, int which); +}; + +class SsScene2901BigButton : public StaticSprite { +public: + SsScene2901BigButton(NeverhoodEngine *vm, Scene *parentScene, int which); +protected: + Scene *_parentScene; + int _which; + int _countdown1; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2901 : public Scene { +public: + Scene2901(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_ssLocationButtons[6]; + SsScene2901LocationButtonLight *_ssLocationButtonLights[6]; + Sprite *_ssBigButton; + int _currWhirlButtonNum; + int _prevWhirlButtonNum; + int _countdown1; + int _currLocationButtonNum; + int _selectedButtonNum; + int _skipCountdown; + int _blinkOn; + bool _isButton2Broken; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE2900_H */ diff --git a/engines/neverhood/modules/module3000.cpp b/engines/neverhood/modules/module3000.cpp new file mode 100644 index 0000000000..2bdb9f0497 --- /dev/null +++ b/engines/neverhood/modules/module3000.cpp @@ -0,0 +1,1548 @@ +/* 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/modules/module3000.h" +#include "neverhood/gamemodule.h" +#include "neverhood/navigationscene.h" + +namespace Neverhood { + +static const uint32 kModule3000SoundList[] = { + 0x92025040, + 0x90035066, + 0x90815450, + 0x99801500, + 0x90E14440, + 0x16805048, + 0x90F0D1C3, + 0 +}; + +Module3000::Module3000(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule), _soundVolume(0) { + + _vm->_soundMan->addSoundList(0x81293110, kModule3000SoundList); + _vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 50, 600, 5, 150); + _vm->_soundMan->setSoundParams(0x90F0D1C3, false, 20000, 30000, 20000, 30000); + _vm->_soundMan->playTwoSounds(0x81293110, 0x48498E46, 0x50399F64, 0); + _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); + _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); + + _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; + + if (_isWallBroken) { + _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); + _vm->_soundMan->playSoundLooping(0x90F0D1C3); + } + + if (which < 0) { + createScene(_vm->gameState().sceneNum, -1); + } else if (which == 0) { + createScene(1, 0); + } else if (which == 1) { + createScene(4, 2); + } else if (which == 2) { + createScene(4, 1); + } else if (which == 3) { + createScene(5, 1); + } + +} + +Module3000::~Module3000() { + _vm->_soundMan->deleteGroup(0x81293110); +} + +void Module3000::createScene(int sceneNum, int which) { + static const byte kNavigationTypes05[] = {3, 0}; + static const byte kNavigationTypes06[] = {5}; + debug("Module3000::createScene(%d, %d)", sceneNum, which); + _vm->gameState().sceneNum = sceneNum; + switch (_vm->gameState().sceneNum) { + case 1: + if (!getGlobalVar(V_BOLT_DOOR_OPEN)) { + createNavigationScene(0x004B7C80, which); + } else if (getGlobalVar(V_WALL_BROKEN)) { + createNavigationScene(0x004B7CE0, which); + } else { + createNavigationScene(0x004B7CB0, which); + } + break; + case 2: + _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); + if (_isWallBroken) { + _soundVolume = 90; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, 90); + } + if (getGlobalVar(V_WALL_BROKEN)) { + createNavigationScene(0x004B7D58, which); + } else { + createNavigationScene(0x004B7D10, which); + } + break; + case 3: + if (getGlobalVar(V_STAIRS_DOWN)) + createNavigationScene(0x004B7E60, which); + else if (getGlobalVar(V_WALL_BROKEN)) + createNavigationScene(0x004B7DA0, which); + else + createNavigationScene(0x004B7E00, which); + break; + case 4: + if (getGlobalVar(V_STAIRS_DOWN)) + createNavigationScene(0x004B7F20, which); + else + createNavigationScene(0x004B7EC0, which); + break; + case 5: + createNavigationScene(0x004B7F80, which, kNavigationTypes05); + break; + case 6: + createNavigationScene(0x004B7FB0, which, kNavigationTypes06); + break; + case 7: + _vm->_soundMan->setSoundListParams(kModule3000SoundList, false, 0, 0, 0, 0); + if (!getSubVar(VA_IS_PUZZLE_INIT, 0x089809C2)) { + setSubVar(VA_IS_PUZZLE_INIT, 0x089809C2, 1); + createSmackerScene(0x90022001, true, true, false); + } else + createSmackerScene(0x98022001, true, true, false); + break; + case 8: + _childObject = new Scene3009(_vm, this, which); + break; + case 9: + _childObject = new Scene3010(_vm, this, 0); + break; + case 10: + _childObject = new Scene3011(_vm, this, 0); + break; + case 11: + _vm->_soundMan->setSoundListParams(kModule3000SoundList, false, 0, 0, 0, 0); + if (!getSubVar(VA_IS_PUZZLE_INIT, 0x10130993)) { + setSubVar(VA_IS_PUZZLE_INIT, 0x10130993, 1); + createSmackerScene(0x31093019, true, true, false); + } else + createSmackerScene(0x20093019, true, true, false); + break; + case 12: + _childObject = new Scene3010(_vm, this, 1); + break; + // NOTE: Newly introduced sceneNums + case 1001: + if (!getGlobalVar(V_BOLT_DOOR_OPEN)) + if (getGlobalVar(V_WALL_BROKEN)) + createSmackerScene(0x00940021, true, true, false); + else + createSmackerScene(0x01140021, true, true, false); + else + if (getGlobalVar(V_WALL_BROKEN)) + createSmackerScene(0x001011B1, true, true, false); + else + createSmackerScene(0x001021B1, true, true, false); + setGlobalVar(V_BOLT_DOOR_OPEN, getGlobalVar(V_BOLT_DOOR_OPEN) ? 0 : 1); + break; + case 1006: + createSmackerScene(0x080810C5, true, true, false); + break; + case 1008: + createSmackerScene(getGlobalVar(V_CANNON_SMACKER_NAME), true, true, false); + break; + } + SetUpdateHandler(&Module3000::updateScene); + _childObject->handleUpdate(); +} + +void Module3000::updateScene() { + if (!updateChild()) { + switch (_vm->gameState().sceneNum) { + case 1: + if (!getGlobalVar(V_BOLT_DOOR_OPEN)) { + if (_moduleResult == 0) + createScene(9, -1); + else if (_moduleResult == 1) + leaveModule(0); + } else { + if (_moduleResult == 0) + if (_navigationAreaType == 2) + createScene(2, 0); + else + createScene(1001, -1); + else if (_moduleResult == 1) + leaveModule(0); + } + break; + case 2: + _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); + if (_isWallBroken) { + _soundVolume = 0; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); + } + if (_moduleResult == 0) { + createScene(3, 0); + } else if (_moduleResult == 1) { + setGlobalVar(V_BOLT_DOOR_OPEN, 0); + createScene(1, 1); + } + break; + case 3: + if (_moduleResult == 1) + createScene(4, 0); + else if (_moduleResult == 3) + createScene(10, -1); + else if (getGlobalVar(V_STAIRS_DOWN)) + createScene(5, 0); + else + createScene(2, 1); + break; + case 4: + if (_moduleResult == 0) + leaveModule(1); + else if (_moduleResult == 1) + createScene(7, -1); + else if (_moduleResult == 2) + createScene(3, 3); + break; + case 5: + if (_moduleResult == 0) + createScene(6, 0); + else if (_moduleResult == 1) + createScene(3, 0); + break; + case 6: + if (_navigationAreaType == 4) + createScene(11, -1); + else + createScene(1006, -1); + break; + case 7: + createScene(8, -1); + break; + case 8: + _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; + if (_moduleResult != 1) { + _vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 0, 0, 0, 0); + createScene(4, 1); + } else if (getGlobalVar(V_CANNON_SMACKER_NAME)) { + createScene(1008, -1); + } else { + _vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 0, 0, 0, 0); + createScene(4, 1); + } + break; + case 9: + if (_moduleResult == 0 || _moduleResult == 2) + createScene(1, 0); + else if (_moduleResult == 1) + createScene(1001, -1); + break; + case 10: + createScene(3, 3); + break; + case 11: + leaveModule(3); + break; + case 12: + createScene(1, 0); + break; + case 1001: + if (getGlobalVar(V_BOLT_DOOR_OPEN)) + createScene(1, 0); + else + createScene(12, -1); + break; + case 1006: + createScene(5, 0); + break; + case 1008: + createScene(8, -1); + break; + } + } else { + switch (_vm->gameState().sceneNum) { + case 1: + if (navigationScene()->isWalkingForward()) { + uint32 frameNumber = navigationScene()->getFrameNumber(); + int navigationIndex = navigationScene()->getNavigationIndex(); + if (navigationIndex == 1) { + if (frameNumber == 0) { + _vm->_soundMan->playTwoSounds(0x81293110, 0x48498E46, 0x50399F64, 0); + _vm->_soundMan->setSoundVolume(0x48498E46, 70); + _vm->_soundMan->setSoundVolume(0x50399F64, 70); + } else if (frameNumber == 100) { + _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); + } + } else if (navigationIndex == 0) { + if (frameNumber == 0) { + _vm->_soundMan->playTwoSounds(0x81293110, 0x48498E46, 0x50399F64, 0); + _vm->_soundMan->setSoundVolume(0x48498E46, 70); + _vm->_soundMan->setSoundVolume(0x50399F64, 70); + } else if (frameNumber == 10) { + _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); + } + if (_isWallBroken && _soundVolume < 90 && frameNumber % 2) { + if (frameNumber == 0) + _soundVolume = 40; + else + _soundVolume++; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + } + } + } + break; + case 2: + if (navigationScene()->isWalkingForward()) { + uint32 frameNumber = navigationScene()->getFrameNumber(); + int navigationIndex = navigationScene()->getNavigationIndex(); + if (_isWallBroken && _soundVolume > 1 && frameNumber % 2) { + _soundVolume--; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + } + if (navigationIndex == 0) { + if (frameNumber == 35) { + _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); + } + } else if (navigationIndex == 1) { + if (frameNumber == 55) { + _vm->_soundMan->playTwoSounds(0x81293110, 0x48498E46, 0x50399F64, 0); + _vm->_soundMan->setSoundVolume(0x48498E46, 70); + _vm->_soundMan->setSoundVolume(0x50399F64, 70); + } + } + } + break; + case 3: + if (navigationScene()->isWalkingForward()) { + uint32 frameNumber = navigationScene()->getFrameNumber(); + int navigationIndex = navigationScene()->getNavigationIndex(); + if (navigationIndex == 2) { + if (frameNumber == 40) { + _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); + } + if (_isWallBroken && _soundVolume < 90 && frameNumber % 2) { + if (frameNumber == 0) + _soundVolume = 40; + else + _soundVolume++; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + } + } + } + break; + case 5: + if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 0) { + _vm->_soundMan->setTwoSoundsPlayFlag(false); + } + break; + } + } +} + +// Scene3009 + +enum { + kCTSNull = 0, + kCTSBreakWall = 1, + kCTSWall = 2, + kCTSEmptyness = 3, + kCTSFireRobotNoTarget = 4, + kCTSFireRobotIsTarget = 5, + kCTSFireNoRobot = 6, + kCTSRaiseCannon = 7, + kCTSRightRobotNoTarget = 8, + kCTSRightRobotIsTarget = 9, + kCTSRightNoRobot = 10, + kCTSLeftRobotNoTarget = 11, + kCTSLeftRobotIsTarget = 12, + kCTSLeftNoRobot = 13, + kCTSLowerCannon = 14, + kCTSCount = 14 +}; + +static const uint32 kScene3009CannonScopeVideos[] = { + 0x1010000D, + 0x340A0049, + 0x340A0049, + 0x0282081D, + 0x0082080D, + 0x0882080D, + 0x0882080D, + 0x0282081D, + 0x004B000B, + 0x014B000B, + 0x044B000B, + 0x0282081D, + 0x0282081D, + 0x0282081D, + 0x340A0049 +}; + +static const uint32 kScene3009CannonActionVideos[] = { + 0x00000000, + 0x8004001B, // 1 Fire cannon at wall, it breaks (lowered) + 0x0004001A, // 2 Fire cannon at wall, nothing happens (lowered) + 0x1048404B, // 3 Fire cannon at emptyness (raised) + 0x50200109, // 4 Fire cannon, robot missed (raised) + 0x12032109, // 5 Fire cannon, robot hit (raised) + 0x10201109, // 6 Fire cannon, no robot (raised) + 0x000A2030, // 7 Raise the cannon + 0x000A0028, // 8 + 0x000A0028, // 9 + 0x000A0028, // 10 + 0x040A1069, // 11 + 0x040A1069, // 12 + 0x040A1069, // 13 + 0x240A1101 // 14 Lower the cannon +}; + +static const uint32 kSsScene3009SymbolEdgesFileHashes[] = { + 0x618827A0, + 0xB1A92322 +}; + +static const uint32 kSsScene3009TargetLineFileHashes[] = { + 0x4011018C, + 0x15086623 +}; + +static const NPoint kAsScene3009SymbolPoints[] = { + {289, 338}, + {285, 375}, + {284, 419}, + {456, 372}, + {498, 372}, + {541, 372} +}; + +static const uint32 kAsScene3009SymbolFileHashes[] = { + 0x24542582, + 0x1CD61D96 +}; + +static const uint32 kSsScene3009SymbolArrowFileHashes1[] = { + 0x24016060, + 0x21216221, + 0x486160A0, + 0x42216422, + 0x90A16120, + 0x84216824, + 0x08017029, + 0x08217029, + 0x10014032, + 0x10214032, + 0x20012004, + 0x20212004 +}; + +static const uint32 kSsScene3009SymbolArrowFileHashes2[] = { + 0x40092024, + 0x01636002, + 0x8071E028, + 0x02A56064, + 0x00806031, + 0x052960A8, + 0x0A116130, + 0x0A316130, + 0x14216200, + 0x14016200, + 0x28416460, + 0x28616460 +}; + +SsScene3009FireCannonButton::SsScene3009FireCannonButton(NeverhoodEngine *vm, Scene3009 *parentScene) + : StaticSprite(vm, 1400), _parentScene(parentScene), _isClicked(false) { + + loadSprite(0x120B24B0, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); + setVisible(false); + SetUpdateHandler(&SsScene3009FireCannonButton::update); + SetMessageHandler(&SsScene3009FireCannonButton::handleMessage); + loadSound(0, 0x3901B44F); +} + +void SsScene3009FireCannonButton::update() { + updatePosition(); + if (_isClicked && !isSoundPlaying(0)) { + sendMessage(_parentScene, 0x2000, 0); + setVisible(false); + } +} + +uint32 SsScene3009FireCannonButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (!_isClicked && !_parentScene->isTurning()) { + _isClicked = true; + setVisible(true); + playSound(0); + } + messageResult = 1; + break; + } + return messageResult; +} + +SsScene3009SymbolEdges::SsScene3009SymbolEdges(NeverhoodEngine *vm, int index) + : StaticSprite(vm, 1400), _blinkCountdown(0) { + + loadSprite(kSsScene3009SymbolEdgesFileHashes[index], kSLFDefDrawOffset | kSLFDefPosition, 600); + if (getGlobalVar(V_ROBOT_HIT)) + hide(); + else + startBlinking(); + SetUpdateHandler(&SsScene3009SymbolEdges::update); +} + +void SsScene3009SymbolEdges::update() { + if (_blinkCountdown != 0 && (--_blinkCountdown == 0)) { + if (_blinkToggle) { + setVisible(true); + } else { + setVisible(false); + } + updatePosition(); + _blinkCountdown = 3; + _blinkToggle = !_blinkToggle; + } +} + +void SsScene3009SymbolEdges::show() { + setVisible(true); + updatePosition(); + _blinkCountdown = 0; +} + +void SsScene3009SymbolEdges::hide() { + setVisible(false); + updatePosition(); + _blinkCountdown = 0; +} + +void SsScene3009SymbolEdges::startBlinking() { + setVisible(true); + updatePosition(); + _blinkCountdown = 3; + _blinkToggle = true; +} + +SsScene3009TargetLine::SsScene3009TargetLine(NeverhoodEngine *vm, int index) + : StaticSprite(vm, 1400) { + + loadSprite(kSsScene3009TargetLineFileHashes[index], kSLFDefDrawOffset | kSLFDefPosition, 600); + setVisible(false); +} + +void SsScene3009TargetLine::show() { + setVisible(true); + updatePosition(); +} + +SsScene3009SymbolArrow::SsScene3009SymbolArrow(NeverhoodEngine *vm, Sprite *asSymbol, int index) + : StaticSprite(vm, 1400), _asSymbol(asSymbol), _index(index), _enabled(true), _countdown(0) { + + _incrDecr = _index % 2; + + createSurface(1200, 33, 31); + loadSprite(kSsScene3009SymbolArrowFileHashes2[_index], kSLFDefPosition); + _drawOffset.set(0, 0, 33, 31); + _collisionBoundsOffset = _drawOffset; + updateBounds(); + _needRefresh = true; + + SetUpdateHandler(&SsScene3009SymbolArrow::update); + SetMessageHandler(&SsScene3009SymbolArrow::handleMessage); + loadSound(0, 0x2C852206); +} + +void SsScene3009SymbolArrow::hide() { + _enabled = false; + setVisible(false); +} + +void SsScene3009SymbolArrow::update() { + updatePosition(); + if (_countdown != 0 && (--_countdown == 0)) { + loadSprite(kSsScene3009SymbolArrowFileHashes2[_index], kSLFDefDrawOffset); + } +} + +uint32 SsScene3009SymbolArrow::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_enabled && _countdown == 0) { + _countdown = 2; + loadSprite(kSsScene3009SymbolArrowFileHashes1[_index], kSLFDefDrawOffset); + playSound(0); + sendMessage(_asSymbol, 0x2005, _incrDecr); + } + messageResult = 1; + break; + } + return messageResult; +} + +AsScene3009VerticalIndicator::AsScene3009VerticalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, int index) + : AnimatedSprite(vm, 1000), _parentScene(parentScene), _enabled(false) { + + _x = 300; + _y = getGlobalVar(V_CANNON_RAISED) ? 52 : 266; + createSurface1(0xC2463913, 1200); + _needRefresh = true; + updatePosition(); + setVisible(false); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene3009VerticalIndicator::handleMessage); +} + +void AsScene3009VerticalIndicator::show() { + startAnimation(0xC2463913, 0, -1); + setVisible(true); + updatePosition(); + _enabled = true; +} + +uint32 AsScene3009VerticalIndicator::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_enabled) { + sendMessage(_parentScene, 0x2002, 0); + } + messageResult = 1; + break; + } + return messageResult; +} + +AsScene3009HorizontalIndicator::AsScene3009HorizontalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, uint32 cannonTargetStatus) + : AnimatedSprite(vm, 1000), _parentScene(parentScene), _enabled(false) { + + _x = getGlobalVar(V_CANNON_TURNED) ? 533 : 92; + _y = 150; + createSurface1(0xC0C12954, 1200); + _needRefresh = true; + updatePosition(); + setVisible(false); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene3009HorizontalIndicator::handleMessage); + if (cannonTargetStatus == kCTSRightRobotNoTarget || cannonTargetStatus == kCTSRightRobotIsTarget || cannonTargetStatus == kCTSRightNoRobot) { + SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveRight); + _x = 280; + } +} + +uint32 AsScene3009HorizontalIndicator::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_enabled) { + sendMessage(_parentScene, 0x2004, 0); + } + messageResult = 1; + break; + } + return messageResult; +} + +void AsScene3009HorizontalIndicator::suMoveLeft() { + _x -= 6; + if (_x < 92) { + SetSpriteUpdate(NULL); + _x = 92; + } +} + +void AsScene3009HorizontalIndicator::suMoveRight() { + _x += 6; + if (_x > 533) { + SetSpriteUpdate(NULL); + _x = 533; + } +} + +void AsScene3009HorizontalIndicator::show() { + startAnimation(0xC0C12954, 0, -1); + setVisible(true); + updatePosition(); + _enabled = true; +} + +void AsScene3009HorizontalIndicator::stMoveLeft() { + _x = 533; + SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveLeft); +} + +void AsScene3009HorizontalIndicator::stMoveRight() { + _x = 330; + SetSpriteUpdate(&AsScene3009HorizontalIndicator::suMoveRight); +} + +AsScene3009Symbol::AsScene3009Symbol(NeverhoodEngine *vm, Scene3009 *parentScene, int symbolPosition) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _symbolPosition(symbolPosition) { + + _symbolIndex = getSubVar(VA_CURR_CANNON_SYMBOLS, _symbolPosition); + + _x = kAsScene3009SymbolPoints[_symbolPosition].x; + _y = kAsScene3009SymbolPoints[_symbolPosition].y; + createSurface1(kAsScene3009SymbolFileHashes[_symbolPosition / 3], 1200); + startAnimation(kAsScene3009SymbolFileHashes[_symbolPosition / 3], _symbolIndex, -1); + _newStickFrameIndex = _symbolIndex; + _needRefresh = true; + updatePosition(); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene3009Symbol::handleMessage); + _ssArrowPrev = _parentScene->insertSprite(this, _symbolPosition * 2 + 0); + _parentScene->addCollisionSprite(_ssArrowPrev); + _ssArrowNext = _parentScene->insertSprite(this, _symbolPosition * 2 + 1); + _parentScene->addCollisionSprite(_ssArrowNext); +} + +uint32 AsScene3009Symbol::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2005: + if (param.asInteger()) { + if (_symbolIndex == 11) + _symbolIndex = 0; + else + _symbolIndex++; + } else { + if (_symbolIndex == 0) + _symbolIndex = 11; + else + _symbolIndex--; + } + startAnimation(kAsScene3009SymbolFileHashes[_symbolPosition / 3], _symbolIndex, -1); + _newStickFrameIndex = _symbolIndex; + setSubVar(VA_CURR_CANNON_SYMBOLS, _symbolPosition, _symbolIndex); + if (_symbolPosition / 3 == 0) { + sendMessage(_parentScene, 0x2001, 0); + } else { + sendMessage(_parentScene, 0x2003, 0); + } + messageResult = 1; + break; + } + return messageResult; +} + +void AsScene3009Symbol::hide() { + _ssArrowPrev->hide(); + _ssArrowNext->hide(); +} + +Scene3009::Scene3009(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _keepVideo(false), _moveCannonLeftFirst(false), + _isTurning(false), _lockSymbolsPart1Countdown(1), _lockSymbolsPart2Countdown(1) { + + _cannonTargetStatus = getGlobalVar(V_CANNON_TARGET_STATUS); + + _vm->gameModule()->initCannonSymbolsPuzzle(); + + setGlobalVar(V_CANNON_SMACKER_NAME, 0); + + _vm->_screen->clear(); + + setBackground(0xD000420C); + setPalette(0xD000420C); + insertPuzzleMouse(0x04208D08, 20, 620); + + _ssFireCannonButton = insertSprite(this); + addCollisionSprite(_ssFireCannonButton); + + _asVerticalIndicator = insertSprite(this, _cannonTargetStatus); + addCollisionSprite(_asVerticalIndicator); + + _asHorizontalIndicator = insertSprite(this, _cannonTargetStatus); + addCollisionSprite(_asHorizontalIndicator); + + if (_cannonTargetStatus != kCTSNull && _cannonTargetStatus != kCTSRightRobotNoTarget && _cannonTargetStatus != kCTSRightRobotIsTarget && _cannonTargetStatus != kCTSRightNoRobot) { + _keepVideo = true; + } else { + _keepVideo = false; + if (_cannonTargetStatus != kCTSNull) { + _asHorizontalIndicator->stMoveRight(); + _isTurning = true; + } + } + + _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, kScene3009CannonScopeVideos[_cannonTargetStatus], false, _keepVideo)); + _smackerPlayer->setDrawPos(89, 37); + _palette->usePalette(); // Use it again since the SmackerPlayer overrides the usage + + insertStaticSprite(0x8540252C, 400); + + for (int i = 0; i < 2; i++) { + _ssSymbolEdges[i] = insertSprite(i); + _ssTargetLines[i] = insertSprite(i); + } + + for (int symbolPosition = 0; symbolPosition < 6; symbolPosition++) { + _asSymbols[symbolPosition] = insertSprite(this, symbolPosition); + if (symbolPosition < 3) + _correctSymbols[symbolPosition] = getSubVar(VA_GOOD_CANNON_SYMBOLS_1, symbolPosition); + else + _correctSymbols[symbolPosition] = getSubVar(VA_GOOD_CANNON_SYMBOLS_2, symbolPosition - 3); + } + + SetMessageHandler(&Scene3009::handleMessage); + SetUpdateHandler(&Scene3009::update); + + // DEBUG Enable to set the correct code +#if 0 + for (int i = 0; i < 6; i++) + setSubVar(VA_CURR_CANNON_SYMBOLS, i, _correctSymbols[i]); + sendMessage(this, 0x2003, 0); +#endif + +} + +void Scene3009::update() { + Scene::update(); + + if (!_keepVideo && _smackerPlayer->isDone() && _cannonTargetStatus <= kCTSCount) { + switch (_cannonTargetStatus) { + case kCTSNull: + case kCTSLowerCannon: + _smackerPlayer->open(0x340A0049, true); + _palette->usePalette(); + _keepVideo = true; + break; + case kCTSRightRobotNoTarget: + _smackerPlayer->open(0x0082080D, true); + _palette->usePalette(); + _keepVideo = true; + _isTurning = false; + break; + case kCTSRightRobotIsTarget: + _smackerPlayer->open(0x0282080D, true); + _palette->usePalette(); + _keepVideo = true; + _isTurning = false; + break; + case kCTSRightNoRobot: + _smackerPlayer->open(0x0882080D, true); + _palette->usePalette(); + _keepVideo = true; + _isTurning = false; + break; + case kCTSLeftRobotNoTarget: + case kCTSLeftRobotIsTarget: + case kCTSLeftNoRobot: + if (_moveCannonLeftFirst) { + if (_cannonTargetStatus == kCTSLeftRobotNoTarget) + _smackerPlayer->open(0x110A000F, false); + else if (_cannonTargetStatus == kCTSLeftRobotIsTarget) + _smackerPlayer->open(0x500B004F, false); + else if (_cannonTargetStatus == kCTSLeftNoRobot) + _smackerPlayer->open(0x100B010E, false); + _palette->usePalette(); + _moveCannonLeftFirst = false; + _asHorizontalIndicator->stMoveLeft(); + } else { + playActionVideo(); + } + break; + } + } + + if (_lockSymbolsPart1Countdown != 0 && (--_lockSymbolsPart1Countdown == 0) && isSymbolsPart1Solved()) { + for (int i = 0; i < 3; i++) + _asSymbols[i]->hide(); + if (!getGlobalVar(V_ROBOT_HIT) || getGlobalVar(V_CANNON_RAISED) || getGlobalVar(V_CANNON_TURNED)) { + _ssSymbolEdges[0]->show(); + _ssTargetLines[0]->show(); + _asVerticalIndicator->show(); + } + } + + if (_lockSymbolsPart2Countdown != 0 && (--_lockSymbolsPart2Countdown == 0) && isSymbolsPart2Solved()) { + for (int i = 3; i < 6; i++) + _asSymbols[i]->hide(); + if (!getGlobalVar(V_ROBOT_HIT) || getGlobalVar(V_CANNON_RAISED) || getGlobalVar(V_CANNON_TURNED)) { + _ssSymbolEdges[1]->show(); + _ssTargetLines[1]->show(); + _asHorizontalIndicator->show(); + } + } + +} + +uint32 Scene3009::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && !getGlobalVar(V_CANNON_RAISED)) { + setGlobalVar(V_CANNON_TARGET_STATUS, 0); + leaveScene(0); + } + break; + case 0x2000: + if (!getGlobalVar(V_CANNON_RAISED)) { + if (!getGlobalVar(V_WALL_BROKEN)) { + _cannonTargetStatus = kCTSBreakWall; + setGlobalVar(V_WALL_BROKEN, 1); + } else { + _cannonTargetStatus = kCTSWall; + } + } else if (!getGlobalVar(V_CANNON_TURNED)) { + _cannonTargetStatus = kCTSEmptyness; + } else if (!getGlobalVar(V_ROBOT_TARGET)) { + _cannonTargetStatus = kCTSFireRobotNoTarget; + } else if (!getGlobalVar(V_ROBOT_HIT)) { + setGlobalVar(V_ROBOT_HIT, 1); + _cannonTargetStatus = kCTSFireRobotIsTarget; + } else { + _cannonTargetStatus = kCTSFireNoRobot; + } + playActionVideo(); + break; + case 0x2001: + _lockSymbolsPart1Countdown = 24; + break; + case 0x2002: + // Raise/lower the cannon + if (!getGlobalVar(V_CANNON_TURNED) && !_isTurning) { + if (getGlobalVar(V_CANNON_RAISED)) { + _cannonTargetStatus = kCTSLowerCannon; + setGlobalVar(V_CANNON_RAISED, 0); + } else { + _cannonTargetStatus = kCTSRaiseCannon; + setGlobalVar(V_CANNON_RAISED, 1); + } + playActionVideo(); + } + break; + case 0x2003: + _lockSymbolsPart2Countdown = 24; + break; + case 0x2004: + // Turn the cannon if it's raised + if (getGlobalVar(V_CANNON_RAISED)) { + if (!getGlobalVar(V_CANNON_TURNED)) { + // Cannon is at the left position + if (!getGlobalVar(V_ROBOT_TARGET)) { + _cannonTargetStatus = kCTSRightRobotNoTarget; + } else if (!getGlobalVar(V_ROBOT_HIT)) { + _cannonTargetStatus = kCTSRightRobotIsTarget; + } else { + _cannonTargetStatus = kCTSRightNoRobot; + } + setGlobalVar(V_CANNON_TURNED, 1); + _isTurning = true; + playActionVideo(); + } else { + // Cannon is at the right position + if (!getGlobalVar(V_ROBOT_TARGET)) { + _cannonTargetStatus = kCTSLeftRobotNoTarget; + _smackerPlayer->open(0x108A000F, false); + } else if (!getGlobalVar(V_ROBOT_HIT)) { + _cannonTargetStatus = kCTSLeftRobotIsTarget; + _smackerPlayer->open(0x500B002F, false); + } else { + _cannonTargetStatus = kCTSLeftNoRobot; + _smackerPlayer->open(0x100B008E, false); + } + _palette->usePalette(); + _moveCannonLeftFirst = true; + _isTurning = true; + _keepVideo = false; + setGlobalVar(V_CANNON_TURNED, 0); + } + } + break; + } + return 0; +} + +void Scene3009::playActionVideo() { + setGlobalVar(V_CANNON_TARGET_STATUS, _cannonTargetStatus); + setGlobalVar(V_CANNON_SMACKER_NAME, kScene3009CannonActionVideos[_cannonTargetStatus]); + leaveScene(1); +} + +bool Scene3009::isSymbolsPart1Solved() { + for (int i = 0; i < 3; i++) + if (_correctSymbols[i] != getSubVar(VA_CURR_CANNON_SYMBOLS, i)) + return false; + return true; +} + +bool Scene3009::isSymbolsPart2Solved() { + for (int i = 3; i < 6; i++) + if (_correctSymbols[i] != getSubVar(VA_CURR_CANNON_SYMBOLS, i)) + return false; + return true; +} + +bool Scene3009::isTurning() { + return _isTurning; +} + +// Scene3010 + +static const uint32 kScene3010ButtonNameHashes[] = { + 0x304008D2, + 0x40119852, + 0x01180951 +}; + +static const uint32 kScene3010DeadBoltButtonFileHashes1[] = { + 0x301024C2, + 0x20280580, + 0x30200452 +}; + +static const uint32 kScene3010DeadBoltButtonFileHashes2[] = { + 0x50C025A8, + 0x1020A0A0, + 0x5000A7E8 +}; + +static const NPoint kAsScene3010DeadBoltPoints[] = { + {550, 307}, + {564, 415}, + {560, 514} +}; + +static const uint32 kAsScene3010DeadBoltFileHashes2[] = { + 0x181A0042, + 0x580A08F2, + 0x18420076 +}; + +static const uint32 kAsScene3010DeadBoltFileHashes1[] = { + 0x300E105A, + 0x804E0052, + 0x040E485A +}; + +SsScene3010DeadBoltButton::SsScene3010DeadBoltButton(NeverhoodEngine *vm, Scene *parentScene, int buttonIndex, int initCountdown, bool initDisabled) + : StaticSprite(vm, 900), _parentScene(parentScene), _buttonLocked(false), _countdown1(0), _countdown2(0), _buttonIndex(buttonIndex) { + + _buttonEnabled = getSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[_buttonIndex]) != 0; + createSurface(400, 88, 95); + setSprite(kScene3010DeadBoltButtonFileHashes2[_buttonIndex]); + if (initDisabled) + disableButton(); + else if (_buttonEnabled) + _countdown1 = initCountdown * 12 + 1; + loadSound(0, 0xF4217243); + loadSound(1, 0x44049000); + loadSound(2, 0x6408107E); + SetUpdateHandler(&SsScene3010DeadBoltButton::update); + SetMessageHandler(&SsScene3010DeadBoltButton::handleMessage); +} + +void SsScene3010DeadBoltButton::update() { + + if (_countdown1 != 0 && (--_countdown1 == 0)) { + playSound(0); + setVisible(false); + setSprite(kScene3010DeadBoltButtonFileHashes1[_buttonIndex]); + } + + if (_countdown2 != 0 && (--_countdown2 == 0)) { + setVisible(true); + setSprite(kScene3010DeadBoltButtonFileHashes2[_buttonIndex]); + } + +} + +uint32 SsScene3010DeadBoltButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (!_buttonLocked && _countdown1 == 0) { + if (_buttonEnabled) { + playSound(1); + playSound(2); + setVisible(true); + _buttonLocked = true; + sendMessage(_parentScene, 0x2000, _buttonIndex); + } else { + sendMessage(_parentScene, 0x2002, _buttonIndex); + } + _needRefresh = true; + updatePosition(); + } + messageResult = 1; + break; + } + return messageResult; +} + +void SsScene3010DeadBoltButton::disableButton() { + _buttonLocked = true; + setSprite(kScene3010DeadBoltButtonFileHashes1[_buttonIndex]); + setVisible(true); +} + +void SsScene3010DeadBoltButton::setSprite(uint32 fileHash) { + loadSprite(fileHash, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset); +} + +void SsScene3010DeadBoltButton::setCountdown(int count) { + _countdown2 = count * 18 + 1; +} + +AsScene3010DeadBolt::AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene, int boltIndex, bool initUnlocked) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _boltIndex(boltIndex), _soundToggle(true), + _unlocked(false), _locked(false), _countdown(0) { + + _x = kAsScene3010DeadBoltPoints[_boltIndex].x; + _y = kAsScene3010DeadBoltPoints[_boltIndex].y; + + if (getSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[_boltIndex])) { + createSurface1(kAsScene3010DeadBoltFileHashes1[_boltIndex], 1200); + startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1); + loadSound(0, 0x46005BC4); + } else { + createSurface1(kAsScene3010DeadBoltFileHashes2[_boltIndex], 1200); + startAnimation(kAsScene3010DeadBoltFileHashes2[_boltIndex], 0, -1); + loadSound(0, 0x420073DC); + loadSound(1, 0x420073DC); + } + + setVisible(false); + stIdle(); + if (initUnlocked) + unlock(true); + + _needRefresh = true; + AnimatedSprite::updatePosition(); + +} + +void AsScene3010DeadBolt::update() { + updateAnim(); + updatePosition(); + if (_countdown != 0 && (--_countdown == 0)) { + stDisabled(); + } +} + +uint32 AsScene3010DeadBolt::hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene3010DeadBolt::stIdle() { + stopAnimation(); + SetUpdateHandler(&AsScene3010DeadBolt::update); + SetMessageHandler(&Sprite::handleMessage); + _locked = false; +} + +void AsScene3010DeadBolt::unlock(bool skipAnim) { + if (!_unlocked) { + setVisible(true); + if (skipAnim) { + startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], -1, 0); + _newStickFrameIndex = STICK_LAST_FRAME; + } else { + startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1); + SetMessageHandler(&AsScene3010DeadBolt::hmAnimation); + FinalizeState(&AsScene3010DeadBolt::stIdleMessage); + NextState(&AsScene3010DeadBolt::stIdle); + playSound(0); + } + _unlocked = true; + loadSound(2, 0x4010C345); + } +} + +void AsScene3010DeadBolt::stIdleMessage() { + stopAnimation(); + SetMessageHandler(&Sprite::handleMessage); + sendMessage(_parentScene, 0x2001, _boltIndex); +} + +void AsScene3010DeadBolt::lock() { + if (!_locked) { + _locked = true; + setVisible(true); + startAnimation(kAsScene3010DeadBoltFileHashes2[_boltIndex], 0, -1); + SetMessageHandler(&AsScene3010DeadBolt::hmAnimation); + FinalizeState(&AsScene3010DeadBolt::stDisabledMessage); + NextState(&AsScene3010DeadBolt::stIdle); + if (_soundToggle) { + playSound(0); + } else { + playSound(1); + } + _soundToggle = !_soundToggle; + } +} + +void AsScene3010DeadBolt::setCountdown(int count) { + _countdown = count * 18 + 1; +} + +void AsScene3010DeadBolt::stDisabled() { + setVisible(true); + startAnimation(kAsScene3010DeadBoltFileHashes1[_boltIndex], 0, -1); + SetMessageHandler(&AsScene3010DeadBolt::hmAnimation); + FinalizeState(&AsScene3010DeadBolt::stDisabledMessage); + NextState(&AsScene3010DeadBolt::stIdle); + _playBackwards = true; + playSound(2); +} + +void AsScene3010DeadBolt::stDisabledMessage() { + setVisible(false); + sendMessage(_parentScene, 0x2003, _boltIndex); +} + +Scene3010::Scene3010(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _countdown(0), _doorUnlocked(false), _checkUnlocked(false) { + + int initCountdown = 0; + + // DEBUG Enable to activate all buttons +#if 0 + setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[0], 1); + setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[1], 1); + setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[2], 1); +#endif + + setBackground(0x80802626); + setPalette(0x80802626); + + for (int i = 0; i < 3; i++) { + _asDeadBolts[i] = insertSprite(this, i, which == 1);//CHECKME + _ssDeadBoltButtons[i] = insertSprite(this, i, initCountdown, which == 1);//CHECKME + addCollisionSprite(_ssDeadBoltButtons[i]); + if (getSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[i])) + initCountdown++; + _boltUnlocking[i] = false; + _boltUnlocked[i] = false; + } + + if (which == 0) { + insertPuzzleMouse(0x02622800, 20, 620); + } + + loadSound(0, 0x68E25540); + + SetMessageHandler(&Scene3010::handleMessage); + SetUpdateHandler(&Scene3010::update); + + if (which == 1) { + _checkUnlocked = true; + for (int i = 0; i < 3; i++) { + _boltUnlocked[i] = true; + _ssDeadBoltButtons[i]->setCountdown(i + 1); + _asDeadBolts[i]->setCountdown(i + 1); + } + } + +} + +void Scene3010::update() { + Scene::update(); + if (_checkUnlocked && !_boltUnlocked[0] && !_boltUnlocked[1] && !_boltUnlocked[2]) { + _countdown = 24; + _checkUnlocked = false; + } + if (_countdown != 0 && (--_countdown == 0)) { + leaveScene(_doorUnlocked ? 1 : 0); + } +} + +uint32 Scene3010::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && _countdown == 0 && !_checkUnlocked) { + if (!_boltUnlocking[0] && !_boltUnlocking[1] && !_boltUnlocking[2]) { + showMouse(false); + if (!_boltUnlocked[0] && !_boltUnlocked[1] && !_boltUnlocked[2]) { + _countdown = 1; + } else { + _checkUnlocked = true; + for (int i = 0; i < 3; i++) { + _ssDeadBoltButtons[i]->setCountdown(i); + if (_boltUnlocked[i]) { + _asDeadBolts[i]->setCountdown(i); + } + } + } + } + } + break; + case 0x2000: + if (!_boltUnlocked[param.asInteger()] && !_checkUnlocked && _countdown == 0) { + _asDeadBolts[param.asInteger()]->unlock(false); + _boltUnlocking[param.asInteger()] = true; + } + break; + case 0x2001: + _boltUnlocked[param.asInteger()] = true; + _boltUnlocking[param.asInteger()] = false; + if (_boltUnlocked[0] && _boltUnlocked[1] && _boltUnlocked[2]) { + if (!getGlobalVar(V_BOLT_DOOR_UNLOCKED)) { + setGlobalVar(V_BOLT_DOOR_UNLOCKED, 1); + playSound(0); + _countdown = 60; + } else { + _countdown = 48; + } + _doorUnlocked = true; + } + break; + case 0x2002: + if (!_checkUnlocked && _countdown == 0) { + _asDeadBolts[param.asInteger()]->lock(); + } + break; + case 0x2003: + _boltUnlocked[param.asInteger()] = false; + break; + } + return 0; +} + +// Scene3011 + +static const uint32 kAsScene3011SymbolFileHashes[] = { + 0x00C88050, + 0x01488050, + 0x02488050, + 0x04488050, + 0x08488050, + 0x10488050, + 0x20488050, + 0x40488050, + 0x80488050, + 0x00488051, + 0x00488052, + 0x00488054, + 0x008B0000, + 0x008D0000, + 0x00810000, + 0x00990000, + 0x00A90000, + 0x00C90000, + 0x00090000, + 0x01890000, + 0x02890000, + 0x04890000, + 0x08890000, + 0x10890000 +}; + +SsScene3011Button::SsScene3011Button(NeverhoodEngine *vm, Scene *parentScene, bool flag) + : StaticSprite(vm, 1400), _parentScene(parentScene), _countdown(0) { + + loadSprite(flag ? 0x11282020 : 0x994D0433, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); + setVisible(false); + loadSound(0, 0x44061000); + SetUpdateHandler(&SsScene3011Button::update); + SetMessageHandler(&SsScene3011Button::handleMessage); +} + +void SsScene3011Button::update() { + updatePosition(); + if (_countdown != 0 && (--_countdown == 0)) { + setVisible(false); + } +} + +uint32 SsScene3011Button::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + StaticSprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown == 0) { + setVisible(true); + _countdown = 4; + sendMessage(_parentScene, 0x2000, 0); + playSound(0); + } + messageResult = 1; + break; + } + return messageResult; +} + +AsScene3011Symbol::AsScene3011Symbol(NeverhoodEngine *vm, int symbolIndex, bool largeSymbol) + : AnimatedSprite(vm, 1000), _symbolIndex(symbolIndex), _largeSymbol(largeSymbol), _isNoisy(false) { + + if (_largeSymbol) { + _x = 310; + _y = 200; + createSurface1(kAsScene3011SymbolFileHashes[_symbolIndex], 1200); + loadSound(0, 0x6052C60F); + loadSound(1, 0x6890433B); + } else { + _symbolIndex = 12; + _x = symbolIndex * 39 + 96; + _y = 225; + createSurface(1200, 41, 48); + loadSound(0, 0x64428609); + loadSound(1, 0x7080023B); + } + setVisible(false); + _needRefresh = true; + SetUpdateHandler(&AnimatedSprite::update); +} + +void AsScene3011Symbol::show(bool isNoisy) { + _isNoisy = isNoisy; + startAnimation(kAsScene3011SymbolFileHashes[_symbolIndex], 0, -1); + setVisible(true); + if (_isNoisy) { + playSound(1); + } else { + playSound(0); + } +} + +void AsScene3011Symbol::hide() { + stopAnimation(); + setVisible(false); +} + +void AsScene3011Symbol::stopSymbolSound() { + if (_isNoisy) { + stopSound(1); + } else { + stopSound(0); + } +} + +void AsScene3011Symbol::change(int symbolIndex, bool isNoisy) { + _symbolIndex = symbolIndex; + _isNoisy = isNoisy; + startAnimation(kAsScene3011SymbolFileHashes[_symbolIndex], 0, -1); + setVisible(true); + if (_isNoisy) { + playSound(1); + } else { + playSound(0); + } +} + +Scene3011::Scene3011(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule), _updateStatus(0), _buttonClicked(false), _currentSymbolIndex(0), _countdown(0) { + + _vm->gameModule()->initCodeSymbolsPuzzle(); + _noisySymbolIndex = getGlobalVar(V_NOISY_SYMBOL_INDEX); + + SetMessageHandler(&Scene3011::handleMessage); + SetUpdateHandler(&Scene3011::update); + + setBackground(0x92124A04); + setPalette(0xA4070114); + addEntity(_palette); + + insertPuzzleMouse(0x24A00929, 20, 620); + + for (int symbolIndex = 0; symbolIndex < 12; symbolIndex++) + _asSymbols[symbolIndex] = insertSprite(symbolIndex, true); + + _ssButton = insertSprite(this, true); + addCollisionSprite(_ssButton); + +} + +void Scene3011::update() { + Scene::update(); + + if (_countdown != 0 && (--_countdown == 0)) { + switch (_updateStatus) { + case 0: + if (_buttonClicked) { + if (_noisySymbolIndex == _currentSymbolIndex) { + do { + _noisyRandomSymbolIndex = _vm->_rnd->getRandomNumber(12 - 1); + } while (_noisySymbolIndex == _noisyRandomSymbolIndex); + _asSymbols[getSubVar(VA_CODE_SYMBOLS, _noisyRandomSymbolIndex)]->show(true); + } else { + _asSymbols[getSubVar(VA_CODE_SYMBOLS, _currentSymbolIndex)]->show(false); + } + _updateStatus = 1; + _countdown = 24; + fadeIn(); + _buttonClicked = false; + } + break; + case 1: + _updateStatus = 2; + _countdown = 24; + break; + case 2: + fadeOut(); + _updateStatus = 3; + _countdown = 24; + break; + case 3: + _updateStatus = 0; + _countdown = 1; + if (_noisySymbolIndex == _currentSymbolIndex) { + _asSymbols[getSubVar(VA_CODE_SYMBOLS, _noisyRandomSymbolIndex)]->hide(); + } else { + _asSymbols[getSubVar(VA_CODE_SYMBOLS, _currentSymbolIndex)]->hide(); + } + _currentSymbolIndex++; + if (_currentSymbolIndex >= 12) + _currentSymbolIndex = 0; + break; + } + } +} + +uint32 Scene3011::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { + leaveScene(0); + } + break; + case 0x2000: + _buttonClicked = true; + if (_countdown == 0) + _countdown = 1; + break; + } + return 0; +} + +void Scene3011::fadeIn() { + _palette->addBasePalette(0x92124A04, 0, 256, 0); + _palette->startFadeToPalette(24); +} + +void Scene3011::fadeOut() { + _palette->addBasePalette(0xA4070114, 0, 256, 0); + _palette->startFadeToPalette(24); +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module3000.h b/engines/neverhood/modules/module3000.h new file mode 100644 index 0000000000..7634360d7c --- /dev/null +++ b/engines/neverhood/modules/module3000.h @@ -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 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. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE3000_H +#define NEVERHOOD_MODULES_MODULE3000_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/modules/module1200.h" + +namespace Neverhood { + +class Module3000 : public Module { +public: + Module3000(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module3000(); +protected: + int _soundVolume; + bool _isWallBroken; + void createScene(int sceneNum, int which); + void updateScene(); +}; + +// Scene3009 + +class Scene3009; + +class SsScene3009FireCannonButton : public StaticSprite { +public: + SsScene3009FireCannonButton(NeverhoodEngine *vm, Scene3009 *parentScene); +protected: + Scene3009 *_parentScene; + bool _isClicked; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene3009SymbolEdges : public StaticSprite { +public: + SsScene3009SymbolEdges(NeverhoodEngine *vm, int index); + void show(); + void hide(); + void startBlinking(); +protected: + int _blinkCountdown; + bool _blinkToggle; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene3009TargetLine : public StaticSprite { +public: + SsScene3009TargetLine(NeverhoodEngine *vm, int index); + void show(); +}; + +class SsScene3009SymbolArrow : public StaticSprite { +public: + SsScene3009SymbolArrow(NeverhoodEngine *vm, Sprite *asSymbol, int index); + void hide(); +protected: + Sprite *_asSymbol; + int _index; + int _incrDecr; + bool _enabled; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene3009VerticalIndicator : public AnimatedSprite { +public: + AsScene3009VerticalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, int index); + void show(); +protected: + Scene3009 *_parentScene; + bool _enabled; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene3009HorizontalIndicator : public AnimatedSprite { +public: + AsScene3009HorizontalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, uint32 cannonTargetStatus); + void show(); + void stMoveLeft(); + void stMoveRight(); +protected: + Scene3009 *_parentScene; + bool _enabled; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suMoveLeft(); + void suMoveRight(); +}; + +class AsScene3009Symbol : public AnimatedSprite { +public: + AsScene3009Symbol(NeverhoodEngine *vm, Scene3009 *parentScene, int symbolPosition); + void hide(); +protected: + Scene3009 *_parentScene; + int _symbolPosition; + uint32 _symbolIndex; + SsScene3009SymbolArrow *_ssArrowPrev; + SsScene3009SymbolArrow *_ssArrowNext; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene3009 : public Scene { +public: + Scene3009(NeverhoodEngine *vm, Module *parentModule, int which); + bool isTurning(); +protected: + int _lockSymbolsPart1Countdown; + int _lockSymbolsPart2Countdown; + SmackerPlayer *_smackerPlayer; + Sprite *_ssFireCannonButton; + SsScene3009SymbolEdges *_ssSymbolEdges[2]; + SsScene3009TargetLine *_ssTargetLines[2]; + AsScene3009VerticalIndicator *_asVerticalIndicator; + AsScene3009HorizontalIndicator *_asHorizontalIndicator; + AsScene3009Symbol *_asSymbols[6]; + uint32 _cannonTargetStatus; + uint32 _correctSymbols[6]; + bool _keepVideo; + bool _moveCannonLeftFirst; + bool _isTurning; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void playActionVideo(); + bool isSymbolsPart1Solved(); + bool isSymbolsPart2Solved(); +}; + +// Scene3010 + +class SsScene3010DeadBoltButton : public StaticSprite { +public: + SsScene3010DeadBoltButton(NeverhoodEngine *vm, Scene *parentScene, int buttonIndex, int initCountdown, bool initDisabled); + void setCountdown(int count); +protected: + Scene *_parentScene; + int _buttonIndex; + bool _buttonEnabled; + bool _buttonLocked; + int _countdown1; + int _countdown2; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void disableButton(); + void setSprite(uint32 fileHash); +}; + +class AsScene3010DeadBolt : public AnimatedSprite { +public: + AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene, int boltIndex, bool initUnlocked); + void setCountdown(int count); + void lock(); + void unlock(bool skipAnim); +protected: + Scene *_parentScene; + int _boltIndex; + int _countdown; + bool _soundToggle; + bool _unlocked; + bool _locked; + void update(); + uint32 hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender); + void stIdle(); + void stIdleMessage(); + void stDisabled(); + void stDisabledMessage(); +}; + +class Scene3010 : public Scene { +public: + Scene3010(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + int _countdown; + bool _doorUnlocked; + bool _checkUnlocked; + SsScene3010DeadBoltButton *_ssDeadBoltButtons[3]; + AsScene3010DeadBolt *_asDeadBolts[3]; + bool _boltUnlocked[3]; + bool _boltUnlocking[3]; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +// Scene3011 + +class SsScene3011Button : public StaticSprite { +public: + SsScene3011Button(NeverhoodEngine *vm, Scene *parentScene, bool flag); +protected: + Scene *_parentScene; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene3011Symbol : public AnimatedSprite { +public: + AsScene3011Symbol(NeverhoodEngine *vm, int symbolIndex, bool largeSymbol); + void show(bool isNoisy); + void hide(); + void stopSymbolSound(); + void change(int symbolIndex, bool isNoisy); + int getSymbolIndex() { return _largeSymbol ? _symbolIndex : _symbolIndex - 12; } +protected: + bool _largeSymbol; + bool _isNoisy; + int _symbolIndex; +}; + +class Scene3011 : public Scene { +public: + Scene3011(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_ssButton; + AsScene3011Symbol *_asSymbols[12]; + int _updateStatus; + bool _buttonClicked; + int _countdown; + int _noisySymbolIndex; + int _currentSymbolIndex; + int _noisyRandomSymbolIndex; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void fadeIn(); + void fadeOut(); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE3000_H */ -- cgit v1.2.3