aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/neverhood/gamemodule.cpp14
-rw-r--r--engines/neverhood/klayman.cpp39
-rw-r--r--engines/neverhood/klayman.h7
-rw-r--r--engines/neverhood/module.mk1
-rw-r--r--engines/neverhood/module1900.cpp691
-rw-r--r--engines/neverhood/module1900.h150
6 files changed, 901 insertions, 1 deletions
diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp
index 960e732ded..7f74590b68 100644
--- a/engines/neverhood/gamemodule.cpp
+++ b/engines/neverhood/gamemodule.cpp
@@ -32,6 +32,7 @@
#include "neverhood/module1600.h"
#include "neverhood/module1700.h"
#include "neverhood/module1800.h"
+#include "neverhood/module1900.h"
#include "neverhood/module2000.h"
#include "neverhood/module2200.h"
#include "neverhood/module2300.h"
@@ -275,11 +276,15 @@ void GameModule::startup() {
_vm->gameState().sceneNum = 1;
createModule(1000, -1);
#endif
-#if 1
+#if 0
_vm->gameState().sceneNum = 8;
_vm->gameState().which = 1;
createModule(1600, -1);
#endif
+#if 1
+ _vm->gameState().sceneNum = 6;
+ createModule(1900, -1);
+#endif
}
void GameModule::createModule(int moduleNum, int which) {
@@ -323,6 +328,10 @@ void GameModule::createModule(int moduleNum, int which) {
setGlobalVar(0x91080831, 0x04A14718);
_childObject = new Module1800(_vm, this, which);
break;
+ case 1900:
+ setGlobalVar(0x91080831, 0x04E1C09C);
+ _childObject = new Module1900(_vm, this, which);
+ break;
case 2000:
setGlobalVar(0x91080831, 0x08250000);
_childObject = new Module2000(_vm, this, which);
@@ -413,6 +422,9 @@ void GameModule::updateModule() {
createModule(2800, 0);
}
break;
+ case 1900:
+ createModule(3000, 1);
+ break;
case 2000:
createModule(2900, 4);
break;
diff --git a/engines/neverhood/klayman.cpp b/engines/neverhood/klayman.cpp
index 27ef84acb2..873ba68b8e 100644
--- a/engines/neverhood/klayman.cpp
+++ b/engines/neverhood/klayman.cpp
@@ -3953,6 +3953,45 @@ void KmScene1705::sub468B10() {
SetMessageHandler(&KmScene1705::handleMessage4689A0);
}
+KmScene1901::KmScene1901(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y)
+ : Klayman(vm, parentScene, x, y, 1000, 1000) {
+
+ // Empty
+}
+
+uint32 KmScene1901::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x4001:
+ case 0x4800:
+ sub41C930(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ setCallback2(AnimationCallback(&Klayman::sub41FC80));
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ sub41C7B0();
+ break;
+ case 0x481D:
+ setCallback2(AnimationCallback(&Klayman::sub4207A0));
+ break;
+ case 0x481E:
+ setCallback2(AnimationCallback(&Klayman::sub4207F0));
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ sub41C7B0();
+ break;
+ case 0x483F:
+ sub41CD00(param.asInteger());
+ break;
+ case 0x4840:
+ sub41CD70(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
KmScene2001::KmScene2001(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y)
: Klayman(vm, parentScene, x, y, 1000, 1000), _flag(false) {
diff --git a/engines/neverhood/klayman.h b/engines/neverhood/klayman.h
index 84cb05acf5..5c0429ee32 100644
--- a/engines/neverhood/klayman.h
+++ b/engines/neverhood/klayman.h
@@ -434,6 +434,13 @@ protected:
void sub468B10();
};
+class KmScene1901 : public Klayman {
+public:
+ KmScene1901(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y);
+protected:
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
class KmScene2001 : public Klayman {
public:
KmScene2001(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y);
diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk
index 5a597fb3e2..6530a7ff8c 100644
--- a/engines/neverhood/module.mk
+++ b/engines/neverhood/module.mk
@@ -20,6 +20,7 @@ MODULE_OBJS = \
module1600.o \
module1700.o \
module1800.o \
+ module1900.o \
module2000.o \
module2200.o \
module2300.o \
diff --git a/engines/neverhood/module1900.cpp b/engines/neverhood/module1900.cpp
new file mode 100644
index 0000000000..7a34a2bd28
--- /dev/null
+++ b/engines/neverhood/module1900.cpp
@@ -0,0 +1,691 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "neverhood/module1900.h"
+#include "neverhood/gamemodule.h"
+
+namespace Neverhood {
+
+Module1900::Module1900(NeverhoodEngine *vm, Module *parentModule, int which)
+ : Module(vm, parentModule) {
+
+ // NOTE: The original has a Scene1908 here as well but it's not used here but in another module...
+
+ if (which < 0) {
+ createScene(_vm->gameState().sceneNum, -1);
+ } else {
+ createScene(0, 0);
+ }
+
+ // TODO Sound1ChList_addSoundResources(0x04E1C09C, dword_4B8800, true);
+ // TODO Sound1ChList_setSoundValuesMulti(dword_4B8800, true, 50, 600, 5, 150);
+
+}
+
+Module1900::~Module1900() {
+ // TODO Sound1ChList_sub_407A50(0x04E1C09C);
+}
+
+void Module1900::createScene(int sceneNum, int which) {
+ debug("Module1900::createScene(%d, %d)", sceneNum, which);
+ _vm->gameState().sceneNum = sceneNum;
+ switch (_vm->gameState().sceneNum) {
+ case 0:
+ _childObject = new Scene1901(_vm, this, which);
+ break;
+ case 6:
+ _childObject = new Scene1907(_vm, this, which);
+ break;
+ }
+ SetUpdateHandler(&Module1900::updateScene);
+ _childObject->handleUpdate();
+}
+
+void Module1900::updateScene() {
+ if (!updateChild()) {
+ switch (_vm->gameState().sceneNum) {
+ case 0:
+ if (_moduleResult == 1) {
+ createScene(6, 0);
+ } else {
+ leaveModule(0);
+ }
+ break;
+ case 6:
+ createScene(0, 1);
+ break;
+ }
+ }
+}
+
+// Scene1901
+
+Scene1901::Scene1901(NeverhoodEngine *vm, Module *parentModule, int which)
+ : Scene(vm, parentModule, true) {
+
+ Sprite *tempSprite;
+
+ _surfaceFlag = true;
+
+ setRectList(0x004B34C8);
+
+ setBackground(0x01303227);
+ setPalette(0x01303227);
+ insertMouse433(0x0322301B);
+
+ insertStaticSprite(0x42213133, 1100);
+
+ if (!getGlobalVar(0xA9035F60)) {
+ insertStaticSprite(0x40A40168, 100);
+ } else if (getGlobalVar(0x09221A62)) {
+ insertStaticSprite(0x124404C4, 100);
+ setGlobalVar(0x2050861A, 1);
+ } else {
+ insertStaticSprite(0x02840064, 100);
+ }
+
+ if (which < 0) {
+ insertKlayman<KmScene1901>(120, 380);
+ setMessageList(0x004B3408);
+ } else if (which == 1) {
+ insertKlayman<KmScene1901>(372, 380);
+ setMessageList(0x004B3410);
+ } else {
+ insertKlayman<KmScene1901>(0, 380);
+ setMessageList(0x004B3400);
+ }
+
+ tempSprite = insertStaticSprite(0x4830A402, 1100);
+ _klayman->setClipRect(tempSprite->getDrawRect().x, 0, 640, 480);
+
+}
+
+static const NPoint kAsScene1907SymbolGroundPositions[] = {
+ {160, 310},
+ { 90, 340},
+ {210, 335},
+ {210, 380},
+ {310, 340},
+ {290, 400},
+ {400, 375},
+ {370, 435},
+ {475, 415}
+};
+
+static const NPoint kAsScene1907SymbolPluggedInPositions[] = {
+ {275, 125},
+ {244, 125},
+ {238, 131},
+ {221, 135},
+ {199, 136},
+ {168, 149},
+ {145, 152},
+ {123, 154},
+ {103, 157}
+};
+
+static const NPoint kAsScene1907SymbolGroundHitPositions[] = {
+ {275, 299},
+ {244, 299},
+ {238, 305},
+ {221, 309},
+ {199, 310},
+ {168, 323},
+ {145, 326},
+ {123, 328},
+ {103, 331}
+};
+
+static const NPoint kAsScene1907SymbolPluggedInDownPositions[] = {
+ {275, 136},
+ {244, 156},
+ {238, 183},
+ {221, 207},
+ {199, 228},
+ {168, 262},
+ {145, 285},
+ {123, 307},
+ {103, 331}
+};
+
+static const uint32 kAsScene1907SymbolFileHashes[] = {
+ 0x006A1034,
+ 0x006A1010,
+ 0x006A1814,
+ 0x006A1016,
+ 0x006A0014,
+ 0x002A1014,
+ 0x00EA1014,
+ 0x206A1014,
+ 0x046A1414
+};
+
+int AsScene1907Symbol::_symbolFlag1 = 0;
+int AsScene1907Symbol::_symbolFlag2 = 0;
+
+AsScene1907Symbol::AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex)
+ : AnimatedSprite(vm, 1000 - positionIndex), _soundResource1(vm), _soundResource2(vm), _soundResource3(vm),
+ _parentScene(parentScene), _elementIndex(elementIndex), _isMoving(false) {
+
+ _symbolFlag1 = 0;
+ _symbolFlag2 = 0;
+
+ if (getGlobalVar(0xA9035F60)) {
+ _isPluggedIn = true;
+ _currPositionIndex = elementIndex;
+ if (!getGlobalVar(0x09221A62)) {
+ _x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x;
+ _y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y;
+ } else {
+ _x = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].x;
+ _y = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].y;
+ }
+ createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex);
+ setFileHash(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
+ _newHashListIndex = -2;
+ } else {
+ _isPluggedIn = false;
+ _currPositionIndex = positionIndex;
+ _soundResource1.load(0x74231924);
+ _soundResource2.load(0x36691914);
+ _soundResource3.load(0x5421D806);
+ _parentScene->setPositionFree(_currPositionIndex, false);
+ _x = kAsScene1907SymbolGroundPositions[_currPositionIndex].x;
+ _y = kAsScene1907SymbolGroundPositions[_currPositionIndex].y;
+ createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex);
+ setFileHash(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
+ _newHashListIndex = 0;
+ }
+ _deltaRect.set(0, 0, 80, 80);
+ Sprite::processDelta();
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+
+}
+
+void AsScene1907Symbol::update() {
+ AnimatedSprite::updateAnim();
+ handleSpriteUpdate();
+ AnimatedSprite::updatePosition();
+ if (_symbolFlag1 && !_symbolFlag2)
+ _symbolFlag1 = 0;
+}
+
+uint32 AsScene1907Symbol::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (!_isPluggedIn && !_symbolFlag1) {
+ tryToPlugIn();
+ messageResult = 1;
+ } else {
+ messageResult = 0;
+ }
+ break;
+ }
+ return messageResult;
+}
+
+uint32 AsScene1907Symbol::hmTryToPlugIn(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ removeCallbacks();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1907Symbol::suTryToPlugIn() {
+ _currStep++;
+ _x -= _deltaX;
+ _y -= _deltaY;
+ if (_currStep == 16) {
+ _x -= _smallDeltaX;
+ _y -= _smallDeltaY;
+ SetSpriteCallback(NULL);
+ }
+}
+
+void AsScene1907Symbol::suFallOff() {
+ if (_fallOffDelay != 0) {
+ _fallOffDelay--;
+ } else {
+ _y += _yAccel;
+ _yAccel += 8;
+ if (_y >= kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) {
+ _y = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y;
+ stFallOffHitGround();
+ }
+ }
+}
+
+void AsScene1907Symbol::suFallOffHitGround() {
+
+ if (_x == _someX - _xBreak)
+ _x -= _smallDeltaX;
+ else
+ _x -= _deltaX;
+
+ if (_y == kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) {
+ _y -= _someY;
+ }
+
+ if (_currStep < 8) {
+ _y -= _yAccel;
+ _yAccel -= 4;
+ if (_yAccel < 0)
+ _yAccel = 0;
+ } else if (_currStep < 15) {
+ _y += _yAccel;
+ _yAccel += 4;
+ } else {
+ _y = kAsScene1907SymbolGroundPositions[_newPositionIndex].y;
+ cbFallOffHitGroundEvent();
+ }
+
+ _currStep++;
+}
+
+void AsScene1907Symbol::suMoveDown() {
+ _y += _yIncr;
+ if (_yIncr < 11)
+ _yIncr++;
+ if (_y >= kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y) {
+ _y = kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y;
+ _isMoving = false;
+ SetSpriteCallback(NULL);
+ }
+}
+
+void AsScene1907Symbol::suMoveUp() {
+ _y -= _yIncr;
+ if (getGlobalVar(0x10938830)) {
+ if (_y - (9 + (_elementIndex > 5 ? 31 : 0)) < kAsScene1907SymbolPluggedInPositions[_elementIndex].y) {
+ _yIncr--;
+ } else {
+ _yIncr++;
+ }
+ } else {
+ _yIncr = 2;
+ }
+ if (_yIncr > 9)
+ _yIncr = 9;
+ else if (_yIncr < 1)
+ _yIncr = 1;
+ if (_y < kAsScene1907SymbolPluggedInPositions[_elementIndex].y) {
+ _y = kAsScene1907SymbolPluggedInPositions[_elementIndex].y;
+ _isMoving = false;
+ SetSpriteCallback(NULL);
+ }
+}
+
+void AsScene1907Symbol::tryToPlugIn() {
+ _isPluggedIn = true;
+ _symbolFlag2++;
+ _newPositionIndex = _parentScene->getNextPosition();
+ _parentScene->setPositionFree(_currPositionIndex, true);
+ sendMessage(_parentScene, 0x1022, 1100 + _newPositionIndex);
+ setFileHash(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
+ SetUpdateHandler(&AsScene1907Symbol::update);
+ SetMessageHandler(&AsScene1907Symbol::hmTryToPlugIn);
+ SetSpriteCallback(&AsScene1907Symbol::suTryToPlugIn);
+ _currStep = 0;
+ _deltaX = (_x - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x) / 16;
+ _smallDeltaX = _x - _deltaX * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x;
+ _deltaY = (_y - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y) / 16;
+ _smallDeltaY = _y - _deltaY * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y;
+ if (_elementIndex == _newPositionIndex) {
+ SetAnimationCallback3(&AsScene1907Symbol::stPlugIn);
+ } else {
+ _symbolFlag1 = 1;
+ SetAnimationCallback3(&AsScene1907Symbol::stPlugInFail);
+ }
+}
+
+void AsScene1907Symbol::fallOff(int newPositionIndex, int fallOffDelay) {
+ _isPluggedIn = false;
+ _newPositionIndex = newPositionIndex;
+ _fallOffDelay = fallOffDelay;
+ _parentScene->setPositionFree(_newPositionIndex, false);
+ _x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x;
+ _y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y;
+ _someX = _x;
+ _someY = _y;
+ setFileHash(kAsScene1907SymbolFileHashes[_elementIndex], -1, 0);
+ _playBackwards = true;
+ _newHashListIndex = -2;
+ _currStep = 0;
+ _yAccel = 1;
+ SetUpdateHandler(&AsScene1907Symbol::update);
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+ SetSpriteCallback(&AsScene1907Symbol::suFallOff);
+}
+
+void AsScene1907Symbol::stFallOffHitGround() {
+ _soundResource2.play();
+ sendMessage(_parentScene, 0x1022, 1000 + _newPositionIndex);
+ // TODO: Meh...
+ Entity::_priority = 1000 - _newPositionIndex;
+ _vm->_collisionMan->removeSprite(this);
+ _vm->_collisionMan->addSprite(this);
+ SetSpriteCallback(&AsScene1907Symbol::suFallOffHitGround);
+ SetAnimationCallback3(&AsScene1907Symbol::cbFallOffHitGroundEvent);
+ _newHashListIndex = 0;
+ _currStep = 0;
+ _yAccel = 30;
+ _deltaX = (_x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x) / 15;
+ _xBreak = _deltaX * 15;
+ _smallDeltaX = _x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x - _xBreak;
+ _someY = 0;
+ if (kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y > kAsScene1907SymbolGroundPositions[_newPositionIndex].y)
+ _someY = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y - kAsScene1907SymbolGroundPositions[_newPositionIndex].y;
+}
+
+void AsScene1907Symbol::cbFallOffHitGroundEvent() {
+ _currPositionIndex = _newPositionIndex;
+ if (_symbolFlag2)
+ _symbolFlag2--;
+ setFileHash(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
+ _newHashListIndex = 0;
+ SetUpdateHandler(&AnimatedSprite::update);
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+ SetSpriteCallback(NULL);
+ processDelta();
+ _soundResource3.play();
+}
+
+void AsScene1907Symbol::stPlugIn() {
+ _soundResource1.play();
+ _currPositionIndex = _newPositionIndex;
+ setFileHash1();
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+ SetSpriteCallback(NULL);
+ if (_elementIndex == 8)
+ sendMessage(_parentScene, 0x2001, 0);
+}
+
+void AsScene1907Symbol::stPlugInFail() {
+ _currPositionIndex = _newPositionIndex;
+ setFileHash1();
+ _parentScene->plugInFailed();
+}
+
+void AsScene1907Symbol::moveUp() {
+ setFileHash(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);//????
+ setFileHash1();
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+ SetSpriteCallback(&AsScene1907Symbol::suMoveUp);
+ _yIncr = 1;
+ _isMoving = true;
+}
+
+void AsScene1907Symbol::moveDown() {
+ setFileHash(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);//????
+ setFileHash1();
+ SetMessageHandler(&AsScene1907Symbol::handleMessage);
+ SetSpriteCallback(&AsScene1907Symbol::suMoveDown);
+ _yIncr = 4;
+ _isMoving = true;
+}
+
+SsScene1907UpDownButton::SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *AsScene1907Symbol)
+ : StaticSprite(vm, 1400), _soundResource(vm), _parentScene(parentScene), _AsScene1907Symbol(AsScene1907Symbol),
+ _countdown1(0) {
+
+ _spriteResource.load2(0x64516424);
+ createSurface(1400, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height);
+ setVisible(false);
+ _drawRect.set(0, 0, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height);
+ _deltaRect = _drawRect;
+ _x = _spriteResource.getPosition().x;
+ _y = _spriteResource.getPosition().y;
+ processDelta();
+ _needRefresh = true;
+ _soundResource.load(0x44061000);
+ SetUpdateHandler(&SsScene1907UpDownButton::update);
+ SetMessageHandler(&SsScene1907UpDownButton::handleMessage);
+ if (getGlobalVar(0xA9035F60)) {
+ if (getGlobalVar(0x09221A62))
+ setToDownPosition();
+ else
+ setToUpPosition();
+ }
+}
+
+void SsScene1907UpDownButton::update() {
+ StaticSprite::update();
+ if (_countdown1 != 0 && (--_countdown1 == 0)) {
+ setVisible(false);
+ sendMessage(_parentScene, 0x2000, 0);
+ }
+}
+
+uint32 SsScene1907UpDownButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (_countdown1 == 0 && !_AsScene1907Symbol->isMoving() && getGlobalVar(0xA9035F60)) {
+ setVisible(true);
+ _countdown1 = 4;
+ StaticSprite::update();
+ _soundResource.play();
+ }
+ messageResult = 1;
+ }
+ return messageResult;
+}
+
+void SsScene1907UpDownButton::setToUpPosition() {
+ _y = _spriteResource.getPosition().y;
+ Sprite::processDelta();
+ StaticSprite::update();
+}
+
+void SsScene1907UpDownButton::setToDownPosition() {
+ _y = _spriteResource.getPosition().y + 174;
+ Sprite::processDelta();
+ StaticSprite::update();
+}
+
+AsScene1907WaterHint::AsScene1907WaterHint(NeverhoodEngine *vm)
+ : AnimatedSprite(vm, 1400) {
+
+ createSurface1(0x110A1061, 1500);
+ _x = 320;
+ _y = 240;
+ setFileHash(0x110A1061, 0, -1);
+ _newHashListIndex = 0;
+ setVisible(false);
+ _needRefresh = true;
+ AnimatedSprite::updatePosition();
+ SetUpdateHandler(&AsScene1907WaterHint::update);
+ SetMessageHandler(&Sprite::handleMessage);
+}
+
+void AsScene1907WaterHint::update() {
+ AnimatedSprite::updateAnim();
+ AnimatedSprite::updatePosition();
+}
+
+uint32 AsScene1907WaterHint::handleMessage46BA20(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ removeCallbacks();
+ break;
+ }
+ return messageResult;
+}
+
+void AsScene1907WaterHint::show() {
+ setVisible(true);
+ setFileHash(0x110A1061, 0, -1);
+ SetMessageHandler(&AsScene1907WaterHint::handleMessage46BA20);
+ SetAnimationCallback3(&AsScene1907WaterHint::hide);
+}
+
+void AsScene1907WaterHint::hide() {
+ setFileHash1();
+ setVisible(false);
+ SetMessageHandler(&Sprite::handleMessage);
+}
+
+Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule, int which)
+ : Scene(vm, parentModule, true), _soundResource1(vm), _soundResource2(vm),
+ _soundResource3(vm), _soundResource4(vm), _currMovingSymbolIndex(0), _pluggedInCount(0),
+ _moveDownCountdown(0), _moveUpCountdown(0), _countdown3(0), _hasPlugInFailed(false) {
+
+ _surfaceFlag = true;
+
+ //setGlobalVar(0x10938830, 1);
+
+ setBackground(0x20628E05);
+ setPalette(0x20628E05);
+
+ for (int i = 0; i < 9; i++)
+ _positionFree[i] = true;
+
+ for (int i = 0; i < 9; i++) {
+ _asSymbols[i] = insertSprite<AsScene1907Symbol>(this, i, getRandomPositionIndex());
+ _vm->_collisionMan->addSprite(_asSymbols[i]);
+ }
+
+ _ssUpDownButton = insertSprite<SsScene1907UpDownButton>(this, _asSymbols[8]);
+ _vm->_collisionMan->addSprite(_ssUpDownButton);
+
+ _asWaterHint = insertSprite<AsScene1907WaterHint>();
+
+ insertMouse435(0x28E0120E, 20, 620);
+
+ SetMessageHandler(&Scene1907::handleMessage);
+ SetUpdateHandler(&Scene1907::update);
+
+ if (getGlobalVar(0xA9035F60))
+ _pluggedInCount = 9;
+
+ _soundResource1.load(0x72004A10);
+ _soundResource2.load(0x22082A12);
+ _soundResource3.load(0x21100A10);
+ _soundResource4.load(0x68E25540);
+
+}
+
+void Scene1907::update() {
+ Scene::update();
+
+ if (_hasPlugInFailed) {
+ int fallOffDelay = 0;
+ _hasPlugInFailed = false;
+ for (int i = 0; i < 9; i++) {
+ AsScene1907Symbol *asSymbol = _asSymbols[8 - i];
+ if (asSymbol->isPluggedIn()) {
+ asSymbol->fallOff(getRandomPositionIndex(), fallOffDelay);
+ fallOffDelay += _vm->_rnd->getRandomNumber(10 - 1) + 4;
+ }
+ }
+ }
+
+ if (_moveDownCountdown != 0 && (--_moveDownCountdown == 0)) {
+ _asSymbols[_currMovingSymbolIndex]->moveDown();
+ if (_currMovingSymbolIndex > 0) {
+ _moveDownCountdown = 2;
+ _currMovingSymbolIndex--;
+ }
+ }
+
+ if (_moveUpCountdown != 0 && (--_moveUpCountdown == 0)) {
+ _moveDownCountdown = 0;
+ for (int i = 0; i < 9; i++)
+ _asSymbols[i]->moveUp();
+ }
+
+ if (_countdown3 != 0 && (--_countdown3 == 0)) {
+ _asWaterHint->show();
+ _moveUpCountdown = 4;
+ }
+
+}
+
+uint32 Scene1907::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ Scene::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x0001:
+ // TODO DEBUG stuff
+ if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) &&
+ !_hasPlugInFailed && _moveDownCountdown == 0 && _moveUpCountdown == 0 && _countdown3 == 0) {
+ leaveScene(0);
+ }
+ break;
+ // TODO Debug stuff
+ case 0x2000:
+ if (getGlobalVar(0x09221A62)) {
+ _soundResource1.play();
+ for (int i = 0; i < 9; i++)
+ _asSymbols[i]->moveUp();
+ _ssUpDownButton->setToUpPosition();
+ setGlobalVar(0x09221A62, 0);
+ } else {
+ if (!getGlobalVar(0x10938830)) {
+ _soundResource3.play();
+ _countdown3 = 5;
+ } else {
+ _soundResource2.play();
+ _ssUpDownButton->setToDownPosition();
+ setGlobalVar(0x09221A62, 1);
+ }
+ _moveDownCountdown = 1;
+ _currMovingSymbolIndex = 8;
+ }
+ break;
+ case 0x2001:
+ _soundResource4.play();
+ setGlobalVar(0xA9035F60, 1);
+ break;
+ }
+ return 0;
+}
+
+void Scene1907::plugInFailed() {
+ _pluggedInCount = 0;
+ _hasPlugInFailed = true;
+}
+
+int Scene1907::getRandomPositionIndex() {
+ bool flag = false;
+ int index = 0;
+ for (int i = 0; i < 9; i++) {
+ if (_positionFree[i])
+ flag = true;
+ }
+ if (flag) {
+ flag = false;
+ while (!flag) {
+ index = _vm->_rnd->getRandomNumber(9 - 1);
+ if (_positionFree[index])
+ flag = true;
+ }
+ }
+ return index;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/module1900.h b/engines/neverhood/module1900.h
new file mode 100644
index 0000000000..7b41c5780b
--- /dev/null
+++ b/engines/neverhood/module1900.h
@@ -0,0 +1,150 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NEVERHOOD_MODULE1900_H
+#define NEVERHOOD_MODULE1900_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+#include "neverhood/module1200.h"
+
+namespace Neverhood {
+
+class Module1900 : public Module {
+public:
+ Module1900(NeverhoodEngine *vm, Module *parentModule, int which);
+ virtual ~Module1900();
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void createScene(int sceneNum, int which);
+ void updateScene();
+};
+
+// Scene1901
+
+class Scene1901 : public Scene {
+public:
+ Scene1901(NeverhoodEngine *vm, Module *parentModule, int which);
+};
+
+// Scene1907
+
+class Scene1907;
+
+class AsScene1907Symbol : public AnimatedSprite {
+public:
+ AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex);
+ void moveUp();
+ void moveDown();
+ void fallOff(int newPositionIndex, int fallOffDelay);
+ bool isPluggedIn() { return _isPluggedIn; }
+ bool isMoving() { return _isMoving; }
+protected:
+ SoundResource _soundResource1;
+ SoundResource _soundResource2;
+ SoundResource _soundResource3;
+ Scene1907 *_parentScene;
+ int _elementIndex;
+ int _currPositionIndex;
+ int _newPositionIndex;
+ bool _isPluggedIn;
+ bool _isMoving;
+ int _someX, _someY;
+ int _xBreak;
+ int _currStep;
+ int _yAccel;
+ int _yIncr;
+ int _fallOffDelay;
+ int _deltaX, _smallDeltaX;
+ int _deltaY, _smallDeltaY;
+ // Dumb, change if possible
+ static int _symbolFlag1;
+ static int _symbolFlag2;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 hmTryToPlugIn(int messageNum, const MessageParam &param, Entity *sender);
+ void suTryToPlugIn();
+ void suFallOff();
+ void suFallOffHitGround();
+ void suMoveDown();
+ void suMoveUp();
+ void tryToPlugIn();
+ void stFallOffHitGround();
+ void cbFallOffHitGroundEvent();
+ void stPlugIn();
+ void stPlugInFail();
+};
+
+class AsScene1907WaterHint : public AnimatedSprite {
+public:
+ AsScene1907WaterHint(NeverhoodEngine *vm);
+ void show();
+protected:
+ void update();
+ uint32 handleMessage46BA20(int messageNum, const MessageParam &param, Entity *sender);
+ void hide();
+};
+
+class SsScene1907UpDownButton : public StaticSprite {
+public:
+ SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *AsScene1907Symbol);
+ void setToUpPosition();
+ void setToDownPosition();
+protected:
+ SoundResource _soundResource;
+ Scene1907 *_parentScene;
+ AsScene1907Symbol *_AsScene1907Symbol;
+ int _countdown1;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class Scene1907 : public Scene {
+public:
+ Scene1907(NeverhoodEngine *vm, Module *parentModule, int which);
+ void plugInFailed();
+ void setPositionFree(int index, bool value) { _positionFree[index] = value; }
+ int getNextPosition() { return _pluggedInCount++; }
+protected:
+ SoundResource _soundResource1;
+ SoundResource _soundResource2;
+ SoundResource _soundResource3;
+ SoundResource _soundResource4;
+ AsScene1907Symbol *_asSymbols[9];
+ SsScene1907UpDownButton *_ssUpDownButton;
+ AsScene1907WaterHint *_asWaterHint;
+ int _currMovingSymbolIndex;
+ int _pluggedInCount;
+ int _moveDownCountdown;
+ int _moveUpCountdown;
+ int _countdown3;
+ bool _hasPlugInFailed;
+ bool _positionFree[9];
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ int getRandomPositionIndex();
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULE1900_H */