aboutsummaryrefslogtreecommitdiff
path: root/engines/neverhood/modules/module1000.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/neverhood/modules/module1000.cpp')
-rw-r--r--engines/neverhood/modules/module1000.cpp1699
1 files changed, 1699 insertions, 0 deletions
diff --git a/engines/neverhood/modules/module1000.cpp b/engines/neverhood/modules/module1000.cpp
new file mode 100644
index 0000000000..415d0f72b1
--- /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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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<KmScene1001>(200, 433);
+ setMessageList(0x004B4888);
+ } else if (which == 1) {
+ // Klaymen entering from the right
+ setRectList(0x004B49F0);
+ insertKlaymen<KmScene1001>(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<KmScene1001>(390, 433);
+ _klaymen->setDoDeltaX(1);
+ } else {
+ insertKlaymen<KmScene1001>(300, 433);
+ }
+ setMessageList(0x004B4970);
+ } else {
+ // Klaymen sleeping
+ setRectList(0x004B4A00);
+ insertKlaymen<KmScene1001>(200, 433);
+ setMessageList(0x004B4890);
+ }
+
+ tempSprite = insertStaticSprite(0x2080A3A8, 1300);
+
+ _klaymen->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480);
+
+ if (!getGlobalVar(V_DOOR_BUSTED)) {
+ _asDoor = insertSprite<AsScene1001Door>();
+ _asDoor->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480);
+ }
+
+ _asLever = insertSprite<AsScene1001Lever>(this, 150, 433, 1);
+
+ insertStaticSprite(0x809861A6, 950);
+ insertStaticSprite(0x89C03848, 1100);
+
+ _ssButton = insertSprite<SsCommonButtonSprite>(this, 0x15288120, 100, 0);
+
+ if (!getGlobalVar(V_WINDOW_OPEN)) {
+ tempSprite = insertStaticSprite(0x8C066150, 200);
+ _asWindow = insertSprite<AsScene1001Window>();
+ _asWindow->setClipRect(tempSprite->getDrawRect());
+ }
+
+ _asHammer = insertSprite<AsScene1001Hammer>(_asDoor);
+
+}
+
+Scene1001::~Scene1001() {
+ setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX());
+}
+
+uint32 Scene1001::handleMessage(int messageNum, const MessageParam &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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), _countdown(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 &param, 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 &param, 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 &param, Entity *sender) {
+ uint32 messageResult = handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ gotoNextState();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1002VenusFlyTrap::hmAnimationExt(int messageNum, const MessageParam &param, 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 &param, 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 &param, 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 &param, 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<KmScene1002>(90, 226);
+ _asKlaymenLadderHands = insertSprite<AsScene1002KlaymenLadderHands>(_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<KmScene1002>(379, 435);
+ _asKlaymenLadderHands = insertSprite<AsScene1002KlaymenLadderHands>(_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<KmScene1002>(650, 435);
+ _asKlaymenLadderHands = insertSprite<AsScene1002KlaymenLadderHands>(_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<KmScene1002>(68, 645);
+ _asKlaymenLadderHands = insertSprite<AsScene1002KlaymenLadderHands>(_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<KmScene1002>(90, 226);
+ _asKlaymenLadderHands = insertSprite<AsScene1002KlaymenLadderHands>(_klaymen);
+ setMessageList(0x004B4470);
+ _klaymen->setClipRect(31, 0, _ssLadderArchPart2->getDrawRect().x2(), _ssLadderArchPart3->getDrawRect().y2());
+ _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect());
+ _asKlaymenPeekHand = insertSprite<AsScene1002KlaymenPeekHand>(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<AsScene1002Ring>(this, false, 258, 191, _ssCeiling->getDrawRect().y, false);
+ _asRing2 = insertSprite<AsScene1002Ring>(this, false, 297, 189, _ssCeiling->getDrawRect().y, false);
+ _asRing3 = insertSprite<AsScene1002Ring>(this, true, 370, 201, _ssCeiling->getDrawRect().y, getGlobalVar(V_FLYTRAP_RING_DOOR));
+ _asRing4 = insertSprite<AsScene1002Ring>(this, false, 334, 191, _ssCeiling->getDrawRect().y, false);
+ _asRing5 = insertSprite<AsScene1002Ring>(this, false, 425, 184, _ssCeiling->getDrawRect().y, false);
+
+ _asDoor = insertSprite<AsScene1002Door>(tempClipRect);
+ tempSprite = insertSprite<AsScene1002BoxingGloveHitEffect>();
+ _asDoorSpy = insertSprite<AsScene1002DoorSpy>(tempClipRect, this, _asDoor, tempSprite);
+ _ssPressButton = insertSprite<SsCommonPressButton>(this, 0x00412692, 0x140B60BE, 800, 0);
+ _asVenusFlyTrap = insertSprite<AsScene1002VenusFlyTrap>(this, _klaymen, false);
+ addCollisionSprite(_asVenusFlyTrap);
+
+ sendEntityMessage(_klaymen, 0x2007, _asVenusFlyTrap);
+
+ _asOutsideDoorBackground = insertSprite<AsScene1002OutsideDoorBackground>();
+
+ 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 &param, 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 &param, 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 &param, 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<KmScene1004>(330, 327);
+ setMessageList(0x004B7C18);
+ } else if (which == 1) {
+ // Klaymen returning from reading a note
+ setRectList(0x004B7C70);
+ insertKlaymen<KmScene1004>(330, 327);
+ setMessageList(0x004B7C08);
+ } else {
+ // Klaymen coming down the ladder
+ loadDataResource(0x01900A04);
+ insertKlaymen<KmScene1004>(_dataResource.getPoint(0x80052A29).x, 27);
+ setMessageList(0x004B7BF0);
+ }
+
+ updatePaletteArea();
+
+ _asKlaymenLadderHands = insertSprite<AsScene1002KlaymenLadderHands>(_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<AsScene1004TrashCan>();
+
+}
+
+void Scene1004::update() {
+ Scene::update();
+ updatePaletteArea();
+}
+
+uint32 Scene1004::handleMessage(int messageNum, const MessageParam &param, 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 &param, 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