aboutsummaryrefslogtreecommitdiff
path: root/engines/neverhood/modules/module2200.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/neverhood/modules/module2200.cpp')
-rw-r--r--engines/neverhood/modules/module2200.cpp2564
1 files changed, 2564 insertions, 0 deletions
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 &param, 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<AsScene1201Tape>(this, 7, 1100, 459, 432, 0x9148A011);
+ addCollisionSprite(_asTape);
+ _ssDoorButton = insertSprite<SsCommonPressButton>(this, 0xE4A43E29, 0xE4A43E29, 100, 0);
+
+ for (uint32 cubeIndex = 0; cubeIndex < 9; cubeIndex++)
+ if ((int16)getSubVar(VA_CUBE_POSITIONS, cubeIndex) >= 0)
+ insertSprite<SsScene2201PuzzleCube>(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<KmScene2201>(300, 427, _clipRects, 2);
+ setMessageList(0x004B8118);
+ _asDoor = insertSprite<AsScene2201Door>(_klaymen, _ssDoorLight, false);
+ } else if (which == 1) {
+ // Klaymen entering from the back
+ insertKlaymen<KmScene2201>(412, 393, _clipRects, 2);
+ setMessageList(0x004B8130);
+ _asDoor = insertSprite<AsScene2201Door>(_klaymen, _ssDoorLight, false);
+ } else if (which == 2) {
+ // Klaymen returning from the puzzle
+ if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) {
+ insertKlaymen<KmScene2201>(379, 427, _clipRects, 2);
+ _klaymen->setDoDeltaX(1);
+ } else
+ insertKlaymen<KmScene2201>(261, 427, _clipRects, 2);
+ setMessageList(0x004B8178);
+ _asDoor = insertSprite<AsScene2201Door>(_klaymen, _ssDoorLight, false);
+ } else {
+ // Klaymen entering from the left
+ NPoint pt = _dataResource.getPoint(0x0304D8DC);
+ insertKlaymen<KmScene2201>(pt.x, pt.y, _clipRects, 2);
+ setMessageList(0x004B8120);
+ _asDoor = insertSprite<AsScene2201Door>(_klaymen, _ssDoorLight, true);
+ }
+
+ insertSprite<AsScene2201CeilingFan>();
+
+ _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 &param, 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 &param, 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<SsScene2202PuzzleCube>(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 &param, 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 &param, 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 &param, 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<AsCommonKey>(this, 2, 1100, 282, 432);
+ addCollisionSprite(_asKey);
+ }
+
+ _asTape = insertSprite<AsScene1201Tape>(this, 1, 1100, 435, 432, 0x9148A011);
+ addCollisionSprite(_asTape);
+ _asLeftDoor = insertSprite<AsScene2203Door>(this, 0);
+ _asRightDoor = insertSprite<AsScene2203Door>(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<KmScene2203>(200, 427);
+ setMessageList(0x004B8340);
+ } else if (which == 1) {
+ // Klaymen entering from the right
+ insertKlaymen<KmScene2203>(640, 427);
+ setMessageList(0x004B8350);
+ } else if (which == 2) {
+ // Klaymen returning from the displayer
+ if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) {
+ insertKlaymen<KmScene2203>(362, 427);
+ _klaymen->setDoDeltaX(1);
+ } else
+ insertKlaymen<KmScene2203>(202, 427);
+ setMessageList(0x004B8358);
+ } else {
+ // Klaymen entering from the left
+ insertKlaymen<KmScene2203>(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 &param, 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 &param, 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<SsCommonPressButton>(this, 0x2D339030, 0x2D309030, 100, 0);
+ } else {
+ _isLightOn = false;
+ setBackground(0xD00A028D);
+ setPalette(0xD00A028D);
+ addEntity(_palette);
+ insertScreenMouse(0xA0289D08);
+ _ssLightSwitch = insertSprite<SsCommonPressButton>(this, 0x2D339030, 0xDAC86E84, 100, 0);
+ }
+ _palette->addBasePalette(0xD00A028D, 0, 256, 0);
+ _ssDoorFrame = insertSprite<SsScene2205DoorFrame>();
+
+ if (which < 0) {
+ // Restoring game
+ insertKlaymen<KmScene2205>(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<KmScene2205>(640, 417);
+ setMessageList(0x004B0648);
+ if (!getGlobalVar(V_LIGHTS_ON))
+ _palette->addPalette(0x68033B1C, 0, 65, 0);
+ _isKlaymenInLight = false;
+ } else {
+ // Klaymen entering from the left
+ insertKlaymen<KmScene2205>(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 &param, 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 &param, 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 &param, 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 &param, 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<AsScene2206DoorSpikes>(0x26133023);
+ _asDoorSpikes->setClipRect(_sprite2->getDrawRect().x, 0, 640, 480);
+ setRectList(0x004B8AF8);
+ _ssButton = insertSprite<SsCommonButtonSprite>(this, 0x0E038022, 100, 0);
+ insertScreenMouse(0x83212411);
+ _ssTestTube = insertSprite<SsScene2206TestTube>(this, 1100, /*464, 433, */0x5E00E262);
+ _asPlatform = insertSprite<AsScene2206Platform>(0x085E25E0);
+ } else {
+ fileHash = 0xE0102A45;
+ _sprite1 = insertStaticSprite(0x1C1106B8, 100);
+ _sprite2 = insertStaticSprite(0x020462E0, 300);
+ _sprite3 = insertStaticSprite(0x900626A2, 100);
+ _asDoorSpikes = insertSprite<AsScene2206DoorSpikes>(0x544822A8);
+ _asDoorSpikes->setClipRect(_sprite2->getDrawRect().x, 0, 640, 480);
+ setRectList(0x004B8B58);
+ _ssButton = insertSprite<SsCommonButtonSprite>(this, 0x16882608, 100, 0);
+ insertScreenMouse(0x02A41E09);
+ _ssTestTube = insertSprite<SsScene2206TestTube>(this, 1100, /*464, 433, */0x52032563);
+ _asPlatform = insertSprite<AsScene2206Platform>(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<KmScene2206>(200, 430);
+ setMessageList(0x004B88A8);
+ } else if (which == 1) {
+ // Klaymen entering from the right
+ insertKlaymen<KmScene2206>(640, 430);
+ setMessageList(0x004B88B8);
+ } else if (which == 2) {
+ // Klaymen entering from the back
+ insertKlaymen<KmScene2206>(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<KmScene2206>(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<KmScene2206>(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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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<KmScene2207>(0, 0);
+ _klaymen->setRepl(64, 0);
+ setMessageList(0x004B38E8);
+ _asElevator = insertSprite<AsScene2207Elevator>(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<AsScene1201Tape>(this, 4, 1100, 277, 428, 0x9148A011);
+ addCollisionSprite(_asTape);
+ _asLever = insertSprite<AsScene2207Lever>(this, 527, 333, 0);
+ addCollisionSprite(_asLever);
+ _asWallRobotAnimation = insertSprite<AsScene2207WallRobotAnimation>(this);
+ _asWallCannonAnimation = insertSprite<AsScene2207WallCannonAnimation>();
+ _asWallRobotAnimation->setVisible(false);
+ _asWallCannonAnimation->setVisible(false);
+ _ssButton = insertSprite<SsCommonButtonSprite>(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<SsScene2207Symbol>(kScene2207FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_1, 0)], 0);
+ insertSprite<SsScene2207Symbol>(kScene2207FileHashes[getSubVar(VA_GOOD_CANNON_SYMBOLS_1, 1)], 1);
+ insertSprite<SsScene2207Symbol>(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 &param, 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 &param, 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 &param, 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<AsScene1201Tape>(this, 10, 1100, 464, 435, 0x9148A011);
+ addCollisionSprite(_asTape);
+
+ if (which < 0) {
+ // Restoring game
+ insertKlaymen<KmScene2242>(200, 430);
+ setMessageList(0x004B3C18);
+ } else if (which == 1) {
+ // Klaymen entering from looking through the window
+ insertKlaymen<KmScene2242>(530, 430);
+ setMessageList(0x004B3D60);
+ } else if (which == 2) {
+ // Klaymen returning from reading a text column
+ insertKlaymen<KmScene2242>(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<KmScene2242>(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 &param, 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<KmHallOfRecords>(200, 430);
+ setMessageList(0x004B2900);
+ } else if (which == 1) {
+ // Klaymen entering from the right
+ insertKlaymen<KmHallOfRecords>(640, 430);
+ setMessageList(0x004B2910);
+ } else if (which == 2) {
+ // Klaymen returning from reading a text column
+ insertKlaymen<KmHallOfRecords>(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<KmHallOfRecords>(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 &param, 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<KmScene2247>(200, 430);
+ setMessageList(0x004B5428);
+ } else if (which == 1) {
+ // Klaymen entering from the right
+ insertKlaymen<KmScene2247>(640, 430);
+ setMessageList(0x004B5438);
+ } else if (which == 2) {
+ // Klaymen returning from reading a text column
+ insertKlaymen<KmScene2247>(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<KmScene2247>(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 &param, 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