aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjohndoe1232011-09-23 15:21:24 +0000
committerWillem Jan Palenstijn2013-05-08 20:39:41 +0200
commit236ca705e8082184aae61aae5e2d561d09b7043c (patch)
tree0d3331033f138aea2333cbb3bbda84e6f1cccfb0
parent2445e6aba8e9724737a069eb4e018f8e60015aac (diff)
downloadscummvm-rg350-236ca705e8082184aae61aae5e2d561d09b7043c.tar.gz
scummvm-rg350-236ca705e8082184aae61aae5e2d561d09b7043c.tar.bz2
scummvm-rg350-236ca705e8082184aae61aae5e2d561d09b7043c.zip
NEVERHOOD: Add Module1600 and Scene1608 (stuff will be renamed later)
-rw-r--r--engines/neverhood/gamemodule.cpp19
-rw-r--r--engines/neverhood/klayman.cpp89
-rw-r--r--engines/neverhood/klayman.h8
-rw-r--r--engines/neverhood/module.cpp4
-rw-r--r--engines/neverhood/module.h1
-rw-r--r--engines/neverhood/module.mk1
-rw-r--r--engines/neverhood/module1600.cpp1387
-rw-r--r--engines/neverhood/module1600.h176
-rw-r--r--engines/neverhood/scene.cpp4
-rw-r--r--engines/neverhood/scene.h30
10 files changed, 1716 insertions, 3 deletions
diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp
index 4d1c27d4df..854a5cc1fe 100644
--- a/engines/neverhood/gamemodule.cpp
+++ b/engines/neverhood/gamemodule.cpp
@@ -29,6 +29,7 @@
#include "neverhood/module1300.h"
#include "neverhood/module1400.h"
#include "neverhood/module1500.h"
+#include "neverhood/module1600.h"
#include "neverhood/module1700.h"
#include "neverhood/module1800.h"
#include "neverhood/module2000.h"
@@ -275,8 +276,9 @@ void GameModule::startup() {
createModule(1000, -1);
#endif
#if 1
- _vm->gameState().sceneNum = 8;
- createModule(1100, -1);
+ _vm->gameState().sceneNum = 7;
+ _vm->gameState().which = 1;
+ createModule(1600, -1);
#endif
}
@@ -309,6 +311,10 @@ void GameModule::createModule(int moduleNum, int which) {
setGlobalVar(0x91080831, 0x00F10114);
_childObject = new Module1500(_vm, this, which, true);
break;
+ case 1600:
+ setGlobalVar(0x91080831, 0x01A008D8);
+ _childObject = new Module1600(_vm, this, which);
+ break;
case 1700:
setGlobalVar(0x91080831, 0x04212331);
_childObject = new Module1700(_vm, this, which);
@@ -379,6 +385,15 @@ void GameModule::updateModule() {
case 1500:
createModule(1000, 0);
break;
+ case 1600:
+ if (_moduleResult == 1) {
+ createModule(1400, 0);
+ } else if (_moduleResult == 2) {
+ createModule(1700, 0);
+ } else {
+ createModule(2100, 0);
+ }
+ break;
case 1700:
if (_moduleResult == 1) {
createModule(2900, 3);
diff --git a/engines/neverhood/klayman.cpp b/engines/neverhood/klayman.cpp
index 4916056ab0..27ef84acb2 100644
--- a/engines/neverhood/klayman.cpp
+++ b/engines/neverhood/klayman.cpp
@@ -282,7 +282,7 @@ void Klayman::sub421350() {
SetMessageHandler(&Klayman::handleMessage41D360);
_counter3 = 0;
_counterMax = 8;
- _counter3Max = _vm->_rnd->getRandomNumber(64) + 24;
+ _counter3Max = _vm->_rnd->getRandomNumber(64 - 1) + 24;
}
void Klayman::update41D1C0() {
@@ -3719,6 +3719,93 @@ uint32 KmScene1404::xHandleMessage(int messageNum, const MessageParam &param) {
return 0;
}
+KmScene1608::KmScene1608(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y)
+ : Klayman(vm, parentScene, x, y, 1000, 1000), _flag1(false) {
+}
+
+uint32 KmScene1608::xHandleMessage(int messageNum, const MessageParam &param) {
+ switch (messageNum) {
+ case 0x2032:
+ _flag1 = param.asInteger() != 0;
+ break;
+ case 0x4001:
+ case 0x4800:
+ sub41C930(param.asPoint().x, false);
+ break;
+ case 0x4004:
+ if (_flag1)
+ setCallback2(AnimationCallback(&Klayman::sub421350));
+ else
+ setCallback2(AnimationCallback(&Klayman::sub41FC80));
+ break;
+ case 0x4812:
+ if (param.asInteger() == 2) {
+ setCallback2(AnimationCallback(&Klayman::sub420060));
+ } else if (param.asInteger() == 1) {
+ setCallback2(AnimationCallback(&Klayman::sub41FFF0));
+ } else {
+ setCallback2(AnimationCallback(&Klayman::sub41FF80));
+ }
+ break;
+ case 0x4817:
+ setDoDeltaX(param.asInteger());
+ sub41C7B0();
+ break;
+ case 0x481B:
+ if (param.asPoint().y != 0) {
+ sub41CC40(param.asPoint().y, param.asPoint().x);
+ } else {
+ sub41CCE0(param.asPoint().x);
+ }
+ break;
+ case 0x481D:
+ if (_flag1)
+ setCallback2(AnimationCallback(&Klayman::sub4214D0));
+ break;
+ case 0x481E:
+ if (_flag)
+ setCallback2(AnimationCallback(&Klayman::sub421510));
+ break;
+ case 0x481F:
+ if (param.asInteger() == 1) {
+ setCallback2(AnimationCallback(&Klayman::sub4208B0));
+ } else if (param.asInteger() == 0) {
+ setCallback2(AnimationCallback(&Klayman::sub420870));
+ } else if (param.asInteger() == 4) {
+ setCallback2(AnimationCallback(&Klayman::sub420930));
+ } else if (param.asInteger() == 3) {
+ setCallback2(AnimationCallback(&Klayman::sub4208F0));
+ } else {
+ setCallback2(AnimationCallback(&Klayman::sub420830));
+ }
+ break;
+ case 0x482D:
+ setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
+ sub41C7B0();
+ break;
+ case 0x4834:
+ setCallback2(AnimationCallback(&Klayman::sub421160));
+ break;
+ case 0x4835:
+ sendMessage(_parentScene, 0x2032, 1);
+ _flag1 = true;
+ setCallback2(AnimationCallback(&Klayman::sub4212C0));
+ break;
+ case 0x4836:
+ sendMessage(_parentScene, 0x2032, 0);
+ _flag1 = false;
+ setCallback2(AnimationCallback(&Klayman::sub421310));
+ break;
+ case 0x483F:
+ sub41CD00(param.asInteger());
+ break;
+ case 0x4840:
+ sub41CD70(param.asInteger());
+ break;
+ }
+ return 0;
+}
+
// KmScene1705
KmScene1705::KmScene1705(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y)
diff --git a/engines/neverhood/klayman.h b/engines/neverhood/klayman.h
index 7b3530c93d..84cb05acf5 100644
--- a/engines/neverhood/klayman.h
+++ b/engines/neverhood/klayman.h
@@ -413,6 +413,14 @@ protected:
uint32 xHandleMessage(int messageNum, const MessageParam &param);
};
+class KmScene1608 : public Klayman {
+public:
+ KmScene1608(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y);
+protected:
+ bool _flag1;
+ uint32 xHandleMessage(int messageNum, const MessageParam &param);
+};
+
class KmScene1705 : public Klayman {
public:
KmScene1705(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y);
diff --git a/engines/neverhood/module.cpp b/engines/neverhood/module.cpp
index 79197ed04b..5be9a6321f 100644
--- a/engines/neverhood/module.cpp
+++ b/engines/neverhood/module.cpp
@@ -110,4 +110,8 @@ bool Module::updateChild() {
return true;
}
+void Module::leaveModule(uint32 result) {
+ sendMessage(_parentModule, 0x1009, result);
+}
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/module.h b/engines/neverhood/module.h
index 2f6ce69d3a..57a42c623b 100644
--- a/engines/neverhood/module.h
+++ b/engines/neverhood/module.h
@@ -62,6 +62,7 @@ protected:
void createSmackerScene(uint32 fileHash, bool doubleSurface, bool flag1, bool canAbort);
void createSmackerScene(const uint32 *fileHashList, bool doubleSurface, bool flag1, bool canAbort);
bool updateChild();
+ void leaveModule(uint32 result);
};
} // End of namespace Neverhood
diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk
index bbbbb02c01..5a597fb3e2 100644
--- a/engines/neverhood/module.mk
+++ b/engines/neverhood/module.mk
@@ -17,6 +17,7 @@ MODULE_OBJS = \
module1300.o \
module1400.o \
module1500.o \
+ module1600.o \
module1700.o \
module1800.o \
module2000.o \
diff --git a/engines/neverhood/module1600.cpp b/engines/neverhood/module1600.cpp
new file mode 100644
index 0000000000..a23e7101b4
--- /dev/null
+++ b/engines/neverhood/module1600.cpp
@@ -0,0 +1,1387 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "neverhood/module1600.h"
+#include "neverhood/gamemodule.h"
+#include "neverhood/module1200.h"
+#include "neverhood/module2200.h"
+
+namespace Neverhood {
+
+Module1600::Module1600(NeverhoodEngine *vm, Module *parentModule, int which)
+ : Module(vm, parentModule) {
+
+ if (which < 0) {
+ createScene(_vm->gameState().sceneNum, -1);
+ } else if (which == 1) {
+ createScene(4, 1);
+ } else if (which == 2) {
+ createScene(5, 0);
+ } else if (which == 3) {
+ createScene(6, 1);
+ } else if (which == 4) {
+ createScene(1, 0);
+ } else {
+ createScene(0, 0);
+ }
+
+ // TODO Sound1ChList_addSoundResources(0x1A008D8, dword_4B3BB0, true);
+ // TODO Sound1ChList_setSoundValuesMulti(dword_4B3BB0, true, 50, 600, 5, 150);
+ // TODO Sound1ChList_sub_407C70(0x1A008D8, 0x41861371, 0x43A2507F, 0);
+
+}
+
+Module1600::~Module1600() {
+ // TODO Sound1ChList_sub_407A50(0x1A008D8);
+}
+
+void Module1600::createScene(int sceneNum, int which) {
+ debug("Module1600::createScene(%d, %d)", sceneNum, which);
+ _vm->gameState().sceneNum = sceneNum;
+ switch (_vm->gameState().sceneNum) {
+ case 0:
+ createNavigationScene(0x004B39D0, which);
+ break;
+ case 1:
+ createNavigationScene(0x004B3A30, which);
+ break;
+ case 2:
+ createNavigationScene(0x004B3A60, which);
+ break;
+ case 3:
+ createNavigationScene(0x004B3A90, which);
+ break;
+ case 4:
+ createNavigationScene(0x004B3B20, which);
+ break;
+ case 5:
+ createNavigationScene(0x004B3B50, which);
+ break;
+ case 6:
+ createNavigationScene(0x004B3B80, which);
+ break;
+ case 7:
+ _childObject = new Scene1608(_vm, this, which);
+ break;
+ case 8:
+//TODO _childObject = new Scene1609(_vm, this, which);
+ break;
+ case 1001:
+ if (getGlobalVar(0xA0808898) == 1) {
+ createSmackerScene(0x80050200, true, true, false);
+ } else if (getGlobalVar(0xA0808898) == 2) {
+ createSmackerScene(0x80090200, true, true, false);
+ } else {
+ createSmackerScene(0x80000200, true, true, false);
+ }
+ if (getGlobalVar(0xA0808898) >= 2)
+ setGlobalVar(0xA0808898, 0);
+ else
+ incGlobalVar(0xA0808898, +1);
+ break;
+ }
+ SetUpdateHandler(&Module1600::updateScene);
+ _childObject->handleUpdate();
+}
+
+void Module1600::updateScene() {
+ if (!updateChild()) {
+ switch (_vm->gameState().sceneNum) {
+ case 0:
+ if (_moduleResult == 0)
+ createScene(2, 0);
+ else if (_moduleResult == 1)
+ createScene(1, 0);
+ else if (_moduleResult == 2)
+ leaveModule(4);
+ break;
+ case 1:
+ if (_moduleResult == 0)
+ createScene(1001, -1);
+ else if (_moduleResult == 1)
+ createScene(0, 3);
+ break;
+ case 2:
+ if (_moduleResult == 0)
+ createScene(3, 0);
+ else if (_moduleResult == 1)
+ createScene(0, 2);
+ break;
+ case 3:
+ if (_moduleResult == 0)
+ createScene(5, 0);
+ else if (_moduleResult == 2)
+ createScene(6, 0);
+ else if (_moduleResult == 3)
+ createScene(2, 1);
+ else if (_moduleResult == 4)
+ createScene(4, 0);
+ break;
+ case 4:
+ if (_moduleResult == 0)
+ leaveModule(1);
+ else if (_moduleResult == 1)
+ createScene(3, 1);
+ break;
+ case 5:
+ if (_moduleResult == 0)
+ leaveModule(2);
+ else if (_moduleResult == 1)
+ createScene(3, 3);
+ break;
+ case 6:
+ if (_moduleResult == 0)
+ createScene(8, -1);
+ else if (_moduleResult == 1)
+ createScene(3, 5);
+ break;
+ case 7:
+ createScene(6, 1);
+ break;
+ case 8:
+ if (_moduleResult == 0)
+ createScene(6, 0);
+ else
+ createScene(7, 0);
+ break;
+ case 1001:
+ createScene(1, 0);
+ break;
+ }
+ }
+}
+
+Class521::Class521(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+ : AnimatedSprite(vm, 1000), _parentScene(parentScene) {
+
+ SetUpdateHandler(&Class521::update);
+ SetMessageHandler(&Class521::handleMessage);
+ SetSpriteCallback(NULL);
+
+ // TODO createSurface2(200, dword_4AF4C0);
+ createSurface(200, 640, 480); //TODO: Remove once the line above is done
+ _x = x;
+ _y = y;
+
+ _field100 = 0;
+ _exitDirection = 0;
+ _currPointIndex = 0;
+ _againDestPtFlag = 0;
+ _stepError = 0;
+ _againDestPointFlag = 0;
+ _steps = 0;
+ _flag10E = 0;
+ _moreY = 0;
+ _flag10F = 0;
+ _flag113 = 0;
+ _flag114 = 1;
+ _flag11A = 0;
+ _newDeltaXType = -1;
+ _field11E = 0;
+ _pathPoints = NULL;
+ _rectList = NULL;
+
+ setFileHash(0xD4220027, 0, -1);
+ setDoDeltaX(getGlobalVar(0x21E60190));
+
+}
+
+Class521::~Class521() {
+ if (_callback1Cb == AnimationCallback(&Class521::sub45D620)) {
+ setGlobalVar(0x21E60190, !getGlobalVar(0x21E60190));
+ }
+}
+
+void Class521::setPathPoints(NPointArray *pathPoints) {
+ _pathPoints = pathPoints;
+}
+
+void Class521::update() {
+ if (_newDeltaXType >= 0) {
+ setDoDeltaX(_newDeltaXType);
+ _newDeltaXType = -1;
+ }
+ AnimatedSprite::update();
+ if (_againDestPtFlag && _moreY == 0 && !_flag10F) {
+ _againDestPtFlag = 0;
+ _againDestPointFlag = 0;
+ sendPointMessage(this, 0x2004, _againDestPt);
+ } else if (_againDestPointFlag && _moreY == 0 && !_flag10F) {
+ _againDestPointFlag = 0;
+ sendMessage(this, 0x2003, _againDestPointIndex);
+ }
+ sub45CE10();
+ sub45E0A0();
+}
+
+void Class521::update45C790() {
+ Class521::update();
+ if (++_idleCounter >= _idleCounterMax)
+ sub45D050();
+ sub45E0A0();
+}
+
+uint32 Class521::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1019:
+ SetSpriteCallback(NULL);
+ break;
+ /* NOTE: Implemented in setPathPoints
+ case 0x2000:
+ case 0x2001:
+ */
+ case 0x2002:
+ // Set the current position without moving
+ _currPointIndex = param.asInteger();
+ _stepError = 0;
+ _x = pathPoint(_currPointIndex).x;
+ _y = pathPoint(_currPointIndex).y;
+ break;
+ case 0x2003:
+ // Move to a point by its index
+ {
+ int newPointIndex = param.asInteger();
+ if (_moreY <= 0 && !_flag10F) {
+ _someX = pathPoint(newPointIndex).x;
+ _someY = pathPoint(newPointIndex).y;
+ if (_currPointIndex < newPointIndex) {
+ moveToNextPoint();
+ } else if (_currPointIndex == newPointIndex && _stepError == 0) {
+ if (_currPointIndex == 0) {
+ _moreY = 0;
+ sendMessage(_parentScene, 0x2005, 0);
+ } else if (_currPointIndex == (int)_pathPoints->size()) {
+ _moreY = 0;
+ sendMessage(_parentScene, 0x2006, 0);
+ }
+ } else {
+ moveToPrevPoint();
+ }
+ } else {
+ _againDestPointFlag = 1;
+ _againDestPointIndex = newPointIndex;
+ }
+ }
+ break;
+ case 0x2004:
+ // Move to the point closest to the parameter point
+ {
+ int minMatchIndex = -1;
+ int minMatchDistance, distance;
+ NPoint pt = param.asPoint();
+ if (_moreY <= 0 && !_flag10F) {
+ // Check if we're already exiting (or something)
+ if ((pt.x <= 20 && _exitDirection == 1) ||
+ (pt.x >= 620 && _exitDirection == 3) ||
+ (pt.y <= 20 && _exitDirection == 2) ||
+ (pt.y >= 460 && _exitDirection == 4))
+ break;
+ _someX = pt.x;
+ _someY = pt.y;
+ minMatchDistance = calcDistance(_someX, _someY, _x, _y) + 1;
+ for (int i = _currPointIndex + 1; i < (int)_pathPoints->size(); i++) {
+ distance = calcDistance(_someX, _someY, pathPoint(i).x, pathPoint(i).y);
+ if (distance >= minMatchDistance)
+ break;
+ minMatchDistance = distance;
+ minMatchIndex = i;
+ }
+ for (int i = _currPointIndex; i >= 0; i--) {
+ distance = calcDistance(_someX, _someY, pathPoint(i).x, pathPoint(i).y);
+ if (distance >= minMatchDistance)
+ break;
+ minMatchDistance = distance;
+ minMatchIndex = i;
+ }
+ if (minMatchIndex == -1) {
+ if (_currPointIndex == 0) {
+ moveToPrevPoint();
+ } else {
+ SetSpriteCallback(NULL);
+ }
+ } else {
+ if (minMatchIndex > _currPointIndex) {
+ moveToNextPoint();
+ } else {
+ moveToPrevPoint();
+ }
+ }
+ } else {
+ _againDestPtFlag = 1;
+ _againDestPt = pt;
+ }
+ }
+ break;
+ case 0x2007:
+ _moreY = param.asInteger();
+ _steps = 0;
+ _flag10E = 0;
+ SetSpriteCallback(&Class521::suMoveToPrevPoint);
+ _lastDistance = 640;
+ break;
+ case 0x2008:
+ _moreY = param.asInteger();
+ _steps = 0;
+ _flag10E = 0;
+ SetSpriteCallback(&Class521::suMoveToNextPoint);
+ _lastDistance = 640;
+ break;
+ case 0x2009:
+ sub45CF80();
+ break;
+ case 0x200A:
+ sub45CFB0();
+ break;
+ /* NOTE: Implemented in setRectList
+ case 0x200B:
+ case 0x200C:
+ */
+ case 0x200E:
+ sub45D180();
+ break;
+ case 0x200F:
+ sub45CD00();
+ _newDeltaXType = param.asInteger();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 Class521::handleMessage45CC30(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Class521::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (_flag10F && param.asInteger() == 0x025424A2) {
+ removeCallbacks();
+ }
+ break;
+ case 0x3002:
+ removeCallbacks();
+ break;
+ }
+ return messageResult;
+}
+
+uint32 Class521::handleMessage45CCA0(int messageNum, const MessageParam &param, Entity *sender) {
+ switch (messageNum) {
+ case 0x2009:
+ sub45CF80();
+ break;
+ case 0x3002:
+ sendMessage(_parentScene, 0x200A, 0);
+ SetMessageHandler(&Class521::handleMessage);
+ break;
+ }
+ return 0;
+}
+
+void Class521::sub45CD00() {
+ bool doDeltaX = _doDeltaX;
+ SetSpriteCallback(NULL);
+ _againDestPtFlag = 0;
+ _againDestPointFlag = 0;
+ _flag10E = 0;
+ _flag10F = 0;
+ _flag113 = 0;
+ _flag114 = 0;
+ _flag11A = 0;
+ _rectList = NULL;
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetAnimationCallback3(&Class521::sub45CFE0);
+ setFileHash(0x35698F78, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update45C790);
+ setCallback1(AnimationCallback(&Class521::sub45D040));
+ setDoDeltaX(doDeltaX ? 1 : 0);
+ _currMoveDirection = 0;
+ _newMoveDirection = 0;
+ _steps = 0;
+ _idleCounter = 0;
+ _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
+}
+
+void Class521::sub45CDC0() {
+ if (_value112 == 1) {
+ _lastDistance = 640;
+ _flag113 = 0;
+ _flag10E = 0;
+ SetSpriteCallback(&Class521::suMoveToNextPoint);
+ } else if (_value112 == 2) {
+ _lastDistance = 640;
+ _flag113 = 0;
+ _flag10E = 0;
+ SetSpriteCallback(&Class521::suMoveToPrevPoint);
+ }
+}
+
+void Class521::sub45CE10() {
+ if (_flag10E && !_flag113 && !_flag10F) {
+ removeCallbacks();
+ _flag114 = 0;
+ _flag113 = 1;
+ setFileHash(0x192ADD30, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ SetAnimationCallback3(&Class521::sub45CFE0);
+ } else if (!_flag10E && _steps && _flag113) {
+ removeCallbacks();
+ _flag113 = 0;
+ setFileHash(0x9966B138, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ SetAnimationCallback3(&Class521::sub45D100);
+ } else {
+ bool flag = false;
+ uint index = 0;
+ if (_rectList && _rectList->size() > 0) {
+ while (index < _rectList->size()) {
+ NRect r = (*_rectList)[index];
+ if (_x >= r.x1 && _x <= r.x2 && _y >= r.y1 && _y <= r.y2)
+ break;
+ }
+ if (index < _rectList->size() && !_flag11A)
+ flag = true;
+ _flag11A = index < _rectList->size();
+ }
+ if (flag) {
+ removeCallbacks();
+ sub45D0A0();
+ } else if (_newMoveDirection != _currMoveDirection && _flag114 && !_flag10F) {
+ removeCallbacks();
+ _currMoveDirection = _newMoveDirection;
+ sub45D100();
+ }
+ }
+}
+
+void Class521::sub45CF80() {
+ setFileHash(0xA86A9538, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ SetAnimationCallback3(&Class521::sub45CFE0);
+}
+
+void Class521::sub45CFB0() {
+ setFileHash(0xA86A9538, -1, -1);
+ _playBackwards = true;
+ SetMessageHandler(&Class521::handleMessage45CCA0);
+ SetUpdateHandler(&Class521::update);
+}
+
+void Class521::sub45CFE0() {
+ setFileHash(0x35698F78, 0, -1);
+ SetMessageHandler(&Class521::handleMessage);
+ SetUpdateHandler(&Class521::update45C790);
+ setCallback1(AnimationCallback(&Class521::sub45D040));
+ _idleCounter = 0;
+ _currMoveDirection = 0;
+ _newMoveDirection = 0;
+ _steps = 0;
+ _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
+}
+
+void Class521::sub45D040() {
+ SetUpdateHandler(&Class521::update);
+}
+
+void Class521::sub45D050() {
+ setFileHash(0xB579A77C, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ SetAnimationCallback3(&Class521::sub45CFE0);
+ _idleCounter = 0;
+ _idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
+}
+
+void Class521::sub45D0A0() {
+ _flag10F = 1;
+ removeCallbacks();
+ setFileHash(0x9C220DA4, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ setCallback1(AnimationCallback(&Class521::sub45D0E0));
+}
+
+void Class521::sub45D0E0() {
+ _flag10F = 0;
+ _newMoveDirection = 0;
+ sub45D100();
+}
+
+void Class521::sub45D100() {
+ _flag114 = 1;
+ if (_currMoveDirection == 1) {
+ setFileHash(0xD4AA03A4, 0, -1);
+ } else if (_currMoveDirection == 3) {
+ setFileHash(0xD00A1364, 0, -1);
+ } else if ((_currMoveDirection == 2 && _doDeltaX) || (_currMoveDirection == 4 && !_doDeltaX)) {
+ sub45D180();
+ } else {
+ setFileHash(0xD4220027, 0, -1);
+ }
+ setGlobalVar(0x21E60190, _doDeltaX ? 1 : 0);
+}
+
+void Class521::sub45D180() {
+ _flag10F = 1;
+ removeCallbacks();
+ setFileHash(0xF46A0324, 0, -1);
+ _value112 = 0;
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ setCallback1(AnimationCallback(&Class521::sub45D620));
+ sub45CDC0();
+}
+
+void Class521::moveToNextPoint() {
+ if (_currPointIndex >= (int)_pathPoints->size() - 1) {
+ _moreY = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2006, 0);
+ } else {
+ NPoint nextPt = pathPoint(_currPointIndex + 1);
+ NPoint currPt = pathPoint(_currPointIndex);
+ if (ABS(nextPt.y - currPt.y) <= ABS(nextPt.x - currPt.x) && nextPt.x >= currPt.x &&
+ (_currMoveDirection == 4 || _currMoveDirection == 2)) {
+ if (_currMoveDirection == 4)
+ _currMoveDirection = 2;
+ else if (_currMoveDirection == 2)
+ _currMoveDirection = 4;
+ if (_flag113)
+ sub45D390();
+ else
+ sub45D350();
+ } else {
+ if (_steps == 0) {
+ removeCallbacks();
+ _flag113 = 0;
+ setFileHash(0x9966B138, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ SetAnimationCallback3(&Class521::sub45D100);
+ }
+ _flag10E = 0;
+ SetSpriteCallback(&Class521::suMoveToNextPoint);
+ _lastDistance = 640;
+ }
+ }
+}
+
+void Class521::sub45D350() {
+ removeCallbacks();
+ _flag10F = 1;
+ _flag10E = 1;
+ setFileHash(0x192ADD30, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ SetAnimationCallback3(&Class521::sub45D390);
+}
+
+void Class521::sub45D390() {
+ removeCallbacks();
+ _flag10F = 1;
+ setFileHash(0xF46A0324, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ setCallback1(AnimationCallback(&Class521::sub45D620));
+ _value112 = 1;
+ sub45CDC0();
+}
+
+void Class521::moveToPrevPoint() {
+ if (_currPointIndex == 0 && _stepError == 0) {
+ _moreY = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2005, 0);
+ } else {
+ NPoint prevPt;
+ NPoint currPt;
+ if (_stepError == 0) {
+ prevPt = pathPoint(_currPointIndex - 1);
+ currPt = pathPoint(_currPointIndex);
+ } else {
+ prevPt = pathPoint(_currPointIndex);
+ currPt = pathPoint(_currPointIndex + 1);
+ }
+ if (ABS(prevPt.y - currPt.y) <= ABS(prevPt.x - currPt.x) && currPt.x >= prevPt.x &&
+ (_currMoveDirection == 2 || _currMoveDirection == 4)) {
+ if (_currMoveDirection == 2)
+ _currMoveDirection = 4;
+ else if (_currMoveDirection == 4)
+ _currMoveDirection = 2;
+ if (_flag113)
+ sub45D5D0();
+ else
+ sub45D580();
+ } else {
+ if (_steps == 0) {
+ removeCallbacks();
+ _flag113 = 0;
+ setFileHash(0x9966B138, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ SetAnimationCallback3(&Class521::sub45D100);
+ }
+ _flag10E = 0;
+ SetSpriteCallback(&Class521::suMoveToPrevPoint);
+ _lastDistance = 640;
+ }
+ }
+}
+
+void Class521::sub45D580() {
+ _flag10F = 1;
+ _flag10E = 1;
+ setCallback1(NULL);
+ setFileHash(0x192ADD30, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ SetAnimationCallback3(&Class521::sub45D5D0);
+}
+
+void Class521::sub45D5D0() {
+ _flag10F = 1;
+ setCallback1(NULL);
+ setFileHash(0xF46A0324, 0, -1);
+ SetMessageHandler(&Class521::handleMessage45CC30);
+ SetUpdateHandler(&Class521::update);
+ setCallback1(AnimationCallback(&Class521::sub45D620));
+ _value112 = 2;
+ sub45CDC0();
+}
+
+void Class521::sub45D620() {
+ _flag10F = 0;
+ _newMoveDirection = 0;
+ setDoDeltaX(2);
+ sub45D100();
+}
+
+void Class521::suMoveToNextPoint() {
+ int16 newX = _x, newY = _y;
+
+ if (_currPointIndex >= (int)_pathPoints->size()) {
+ _moreY = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2006, 0);
+ return;
+ }
+
+ if (_flag10E) {
+ if (_steps <= 0) {
+ sendMessage(this, 0x1019, 0);
+ return;
+ } else {
+ _steps--;
+ }
+ } else if (_steps < 11) {
+ _steps++;
+ }
+
+ bool firstTime = true;
+ _anotherY = _steps;
+ int stepsCtr = _steps;
+
+ while (stepsCtr > 0) {
+ NPoint pt1;
+ NPoint pt2 = pathPoint(_currPointIndex);
+ if (_currPointIndex + 1 >= (int)_pathPoints->size())
+ pt1 = pathPoint(0);
+ else
+ pt1 = pathPoint(_currPointIndex + 1);
+ int16 deltaX = ABS(pt1.x - pt2.x);
+ int16 deltaY = ABS(pt1.y - pt2.y);
+ if (deltaX >= deltaY) {
+ _newMoveDirection = 2;
+ if (pt1.x < pt2.x)
+ _newMoveDirection = 4;
+ if (stepsCtr + _stepError >= deltaX) {
+ stepsCtr -= deltaX;
+ stepsCtr += _stepError;
+ _stepError = 0;
+ _currPointIndex++;
+ if (_currPointIndex == (int)_pathPoints->size() - 1)
+ stepsCtr = 0;
+ newX = pathPoint(_currPointIndex).x;
+ newY = pathPoint(_currPointIndex).y;
+ } else {
+ _stepError += stepsCtr;
+ if (pt1.x >= pt2.x)
+ newX += stepsCtr;
+ else
+ newX -= stepsCtr;
+ if (pt1.y >= pt2.y)
+ newY = pt2.y + (deltaY * _stepError) / deltaX;
+ else
+ newY = pt2.y - (deltaY * _stepError) / deltaX;
+ stepsCtr = 0;
+ }
+ } else {
+ _newMoveDirection = 3;
+ if (pt1.y < pt2.y)
+ _newMoveDirection = 1;
+ if (firstTime) {
+ if (pt1.y >= pt2.y) {
+ stepsCtr += 7;
+ } else {
+ stepsCtr -= 4;
+ if (stepsCtr < 0)
+ stepsCtr = 0;
+ }
+ _anotherY = stepsCtr;
+ }
+ if (stepsCtr + _stepError >= deltaY) {
+ stepsCtr -= deltaY;
+ stepsCtr += _stepError;
+ _stepError = 0;
+ _currPointIndex++;
+ if (_currPointIndex == (int)_pathPoints->size() - 1)
+ stepsCtr = 0;
+ newX = pathPoint(_currPointIndex).x;
+ newY = pathPoint(_currPointIndex).y;
+ } else {
+ _stepError += stepsCtr;
+ if (pt1.x >= pt2.x)
+ newX = pt2.x + (deltaX * _stepError) / deltaY;
+ else
+ newX = pt2.x - (deltaX * _stepError) / deltaY;
+ if (pt1.y >= pt2.y)
+ newY += stepsCtr;
+ else
+ newY -= stepsCtr;
+ stepsCtr = 0;
+ }
+ }
+ firstTime = false;
+ }
+
+ if (_moreY != 0) {
+ _x = newX;
+ _y = newY;
+ _moreY -= _anotherY;
+ if (_moreY <= 0) {
+ _flag10E = 1;
+ _moreY = 0;
+ }
+ } else {
+ int distance = calcDistance(_someX, _someY, _x, _y);
+ _x = newX;
+ _y = newY;
+ if (newX > 20 && newX < 620 && newY > 20 && newY < 460) {
+ _exitDirection = 0;
+ _field100 = 1;
+ } else if (_field100) {
+ _someX = pathPoint(_pathPoints->size() - 1).x;
+ _someY = pathPoint(_pathPoints->size() - 1).y;
+ _field100 = 0;
+ if (_x <= 20)
+ _exitDirection = 1;
+ else if (_x >= 620)
+ _exitDirection = 3;
+ else if (_y <= 20)
+ _exitDirection = 2;
+ else if (_y >= 460)
+ _exitDirection = 4;
+ if (_exitDirection != 0 && _flag10E) {
+ _flag10E = 0;
+ _steps = 11;
+ }
+ }
+ if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) ||
+ (_exitDirection == 0 && _lastDistance + 20 < distance))
+ _flag10E = 1;
+ if (distance < _lastDistance)
+ _lastDistance = distance;
+ if (_currPointIndex == (int)_pathPoints->size() - 1) {
+ _flag10E = 1;
+ _moreY = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2006, 0);
+ }
+ }
+
+}
+
+void Class521::suMoveToPrevPoint() {
+ int16 newX = _x, newY = _y;
+
+ if (_currPointIndex == 0 && _stepError == 0) {
+ _moreY = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2005, 0);
+ return;
+ }
+
+ if (_flag10E) {
+ if (_steps <= 0) {
+ sendMessage(this, 0x1019, 0);
+ return;
+ } else {
+ _steps--;
+ }
+ } else if (_steps < 11) {
+ _steps++;
+ }
+
+ bool firstTime = true;
+ _anotherY = _steps;
+ int stepsCtr = _steps;
+
+ while (stepsCtr > 0) {
+ if (_stepError == 0)
+ _currPointIndex--;
+ NPoint pt1;
+ NPoint pt2 = pathPoint(_currPointIndex);
+ if (_currPointIndex + 1 >= (int)_pathPoints->size())
+ pt1 = pathPoint(0);
+ else
+ pt1 = pathPoint(_currPointIndex + 1);
+ int16 deltaX = ABS(pt1.x - pt2.x);
+ int16 deltaY = ABS(pt1.y - pt2.y);
+ if (deltaX >= deltaY) {
+ _newMoveDirection = 4;
+ if (pt1.x < pt2.x)
+ _newMoveDirection = 2;
+ if (_stepError == 0)
+ _stepError = deltaX;
+ if (stepsCtr > _stepError) {
+ stepsCtr -= _stepError;
+ _stepError = 0;
+ if (_currPointIndex == 0)
+ stepsCtr = 0;
+ newX = pathPoint(_currPointIndex).x;
+ newY = pathPoint(_currPointIndex).y;
+ } else {
+ _stepError -= stepsCtr;
+ if (pt1.x >= pt2.x)
+ newX -= stepsCtr;
+ else
+ newX += stepsCtr;
+ if (pt1.y >= pt2.y)
+ newY = pt2.y + (deltaY * _stepError) / deltaX;
+ else
+ newY = pt2.y - (deltaY * _stepError) / deltaX;
+ stepsCtr = 0;
+ }
+ } else {
+ _newMoveDirection = 1;
+ if (pt1.y < pt2.y)
+ _newMoveDirection = 3;
+ if (firstTime) {
+ if (pt1.y >= pt2.y) {
+ stepsCtr -= 4;
+ if (stepsCtr < 0)
+ stepsCtr = 0;
+ } else {
+ stepsCtr += 7;
+ }
+ _anotherY = stepsCtr;
+ }
+ if (_stepError == 0)
+ _stepError = deltaY;
+ if (stepsCtr > _stepError) {
+ stepsCtr -= _stepError;
+ _stepError = 0;
+ if (_currPointIndex == 0)
+ stepsCtr = 0;
+ newX = pathPoint(_currPointIndex).x;
+ newY = pathPoint(_currPointIndex).y;
+ } else {
+ _stepError -= stepsCtr;
+ if (pt1.x >= pt2.x)
+ newX = pt2.x + (deltaX * _stepError) / deltaY;
+ else
+ newX = pt2.x - (deltaX * _stepError) / deltaY;
+ if (pt1.y >= pt2.y)
+ newY -= stepsCtr;
+ else
+ newY += stepsCtr;
+ stepsCtr = 0;
+ }
+ }
+ firstTime = false;
+ }
+
+ if (_moreY != 0) {
+ _x = newX;
+ _y = newY;
+ _moreY -= _anotherY;
+ if (_moreY <= 0) {
+ _flag10E = 1;
+ _moreY = 0;
+ }
+ } else {
+ int distance = calcDistance(_someX, _someY, _x, _y);
+ _x = newX;
+ _y = newY;
+ if (newX > 20 && newX < 620 && newY > 20 && newY < 460) {
+ _exitDirection = 0;
+ _field100 = 1;
+ } else if (_field100) {
+ _someX = pathPoint(0).x;
+ _someY = pathPoint(0).y;
+ _field100 = 0;
+ if (_x <= 20)
+ _exitDirection = 1;
+ else if (_x >= 620)
+ _exitDirection = 3;
+ else if (_y <= 20)
+ _exitDirection = 2;
+ else if (_y >= 460)
+ _exitDirection = 4;
+ if (_exitDirection != 0 && _flag10E) {
+ _flag10E = 0;
+ _steps = 11;
+ }
+ }
+ if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) ||
+ (_exitDirection == 0 && _lastDistance + 20 < distance))
+ _flag10E = 1;
+ if (distance < _lastDistance)
+ _lastDistance = distance;
+ if (_currPointIndex == 0 && _stepError == 0) {
+ _flag10E = 1;
+ _moreY = 0;
+ sendMessage(this, 0x1019, 0);
+ sendMessage(_parentScene, 0x2005, 0);
+ }
+ }
+
+}
+
+void Class521::sub45E0A0() {
+ // TODO
+}
+
+int Class521::calcDistance(int16 x1, int16 y1, int16 x2, int16 y2) {
+ int16 deltaX = ABS(x1 - x2);
+ int16 deltaY = ABS(y1 - y2);
+ return sqrt(deltaX * deltaX + deltaY * deltaY);
+}
+
+Class546::Class546(NeverhoodEngine *vm, Scene *parentScene)
+ : AnimatedSprite(vm, 0x08C80144, 900, 320, 240), _soundResource(vm),
+ _parentScene(parentScene) {
+
+ setVisible(false);
+ SetMessageHandler(&Class546::handleMessage);
+ setFileHash1();
+}
+
+uint32 Class546::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x3002:
+ removeCallbacks();
+ break;
+ case 0x4808:
+ sub44D710();
+ break;
+ case 0x4809:
+ sub44D790();
+ break;
+ }
+ return messageResult;
+}
+
+void Class546::sub44D710() {
+ setFileHash(0x08C80144, 0, -1);
+ setVisible(true);
+ SetAnimationCallback3(&Class546::sub44D760);
+ _soundResource.play(calcHash("fxDoorOpen23"));
+}
+
+void Class546::sub44D760() {
+ sendMessage(_parentScene, 0x2033, 0);
+ setFileHash1();
+ setVisible(false);
+}
+
+void Class546::sub44D790() {
+ setFileHash(0x08C80144, -1, -1);
+ setVisible(true);
+ SetAnimationCallback3(&Class546::sub44D7F0);
+ _soundResource.play(calcHash("fxDoorClose23"));
+}
+
+void Class546::sub44D7F0() {
+ sendMessage(_parentScene, 0x2034, 0);
+ setFileHash1();
+}
+
+Class547::Class547(NeverhoodEngine *vm, int16 x, int16 y)
+ : AnimatedSprite(vm, 0x1209E09F, 1100, x, y) {
+
+ setDoDeltaX(1);
+ setFileHash(0x1209E09F, 1, -1);
+ _newHashListIndex = 1;
+}
+
+Class548::Class548(NeverhoodEngine *vm, int16 x, int16 y)
+ : AnimatedSprite(vm, 0x1209E09F, 100, x, y) {
+
+ setDoDeltaX(1);
+ _newHashListIndex = 0;
+}
+
+Class518::Class518(NeverhoodEngine *vm, Class521 *class521)
+ : AnimatedSprite(vm, 1100), _class521(class521) {
+
+ SetUpdateHandler(&Class518::update);
+ createSurface1(0x60281C10, 150);
+ setFileHash(0x60281C10, -1, -1);
+ _newHashListIndex = -2;
+}
+
+void Class518::update() {
+ _x = _class521->getX();
+ _y = _class521->getY();
+ AnimatedSprite::update();
+}
+
+Scene1608::Scene1608(NeverhoodEngine *vm, Module *parentModule, int which)
+ : Scene(vm, parentModule, true), _class521(NULL), _countdown1(0) {
+
+ setGlobalVar(0x21E60190, 1);
+
+ _surfaceFlag = true;
+ SetMessageHandler(&Scene1608::handleMessage44D2A0);
+
+ _class545 = insertSprite<Class545>(this, 1, 1100, 198, 220);
+ _vm->_collisionMan->addSprite(_class545);
+
+ if (which < 0) {
+ if (_vm->gameState().which == 1)
+ which = 1;
+ else {
+ setRectList(0x004B47D0);
+ insertKlayman<KmScene1608>(380, 438);
+ _klayman2 = _klayman;
+ _flag4 = false;
+ _class546 = insertSprite<Class546>(this);
+ _sprite1 = insertStaticSprite(0x7D0404E8, 1100);
+ setMessageList(0x004B46A8);
+ setBackground(0x10080E01);
+ setPalette(0x10080E01);
+ _asTape = insertSprite<AsScene1201Tape>(this, 13, 1100, 412, 443, 0x9148A011);
+ _vm->_collisionMan->addSprite(_asTape);
+ _klayman->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480);
+ SetUpdateHandler(&Scene1608::update44CE90);
+ insertMouse433(0x80E05108);
+ insertStaticSprite(0x4B18F868, 1200);
+ }
+ } else if (which == 0) {
+ _vm->gameState().which = 0;
+ setRectList(0x004B47D0);
+ insertKlayman<KmScene1608>(0, 438);
+ _klayman2 = _klayman;
+ _flag4 = false;
+ setMessageList(0x004B46B0);
+ setBackground(0x10080E01);
+ setPalette(0x10080E01);
+ _asTape = insertSprite<AsScene1201Tape>(this, 13, 1100, 412, 443, 0x9148A011);
+ _vm->_collisionMan->addSprite(_asTape);
+ insertMouse433(0x80E05108);
+ _sprite1 = insertStaticSprite(0x7D0404E8, 1100);
+ _class546 = insertSprite<Class546>(this);
+ _klayman->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480);
+ SetUpdateHandler(&Scene1608::update44CE90);
+ sendMessage(_class546, 0x4808, 0);
+ insertStaticSprite(0x4B18F868, 1200);
+ } else if (which == 2) {
+ _vm->gameState().which = 1;
+ _dataResource.load(0x003C0492);
+ _roomPathPoints = _dataResource.getPointArray(calcHash("meArchroArchRoomPath"));
+ setBackground(0x98001604);
+ setPalette(0x98001604);
+ _palette->addPalette("paPodRed", 65, 31, 65);
+ insertMouse433(0x01600988);
+ _sprite2 = insertStaticSprite(0x491F38A8, 1100);
+ _class521 = createSprite<Class521>(this, 375, 227); // Create but don't add to the sprite list yet
+ _class547 = insertSprite<Class547>(375, 227);
+ _class548 = insertSprite<Class548>(375, 227);
+ _class521->setVisible(false);
+ if (getGlobalVar(0xC0418A02)) {
+ insertKlayman<KmScene1608>(373, 220);
+ _klayman->setDoDeltaX(1);
+ } else {
+ insertKlayman<KmScene1608>(283, 220);
+ }
+ _klayman2 = _klayman;
+ setMessageList(0x004B47A8);
+ SetMessageHandler(&Scene1608::handleMessage44D3C0);
+ SetUpdateHandler(&Scene1608::update44CED0);
+ // NOTE: Setting the point array was handled by messages 0x2000 (array) and 0x2001 (count) in the original
+ _class521->setPathPoints(_roomPathPoints);
+ sendMessage(_class521, 0x2002, _roomPathPoints->size() - 1);
+ _sprite3 = insertStaticSprite(0xB47026B0, 1100);
+ _rect1.set(_sprite3->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2());
+ _rect3.set(_sprite2->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2());
+ _rect2 = _rect1;
+ _rect2.y2 = 215;
+ _klayman->setClipRect(_rect1);
+ _class521->setClipRect(_rect1);
+ _class547->setClipRect(_rect1);
+ _class548->setClipRect(_rect1);
+ _asTape = insertSprite<AsScene1201Tape>(this, 13, 1100, 412, 443, 0x9148A011);
+ _vm->_collisionMan->addSprite(_asTape);
+ insertSprite<Class518>(_class521)->setClipRect(_rect1);
+ _flag4 = false;
+ _flag2 = false;
+ _flag1 = 0;
+ setRectList(0x004B4810);
+ }
+
+ // NOTE: Not in the else because 'which' is set to 1 in the true branch
+ if (which == 1) {
+ _vm->gameState().which = 1;
+ _dataResource.load(0x003C0492);
+ _roomPathPoints = _dataResource.getPointArray(calcHash("meArchroArchRoomPath"));
+ setBackground(0x98001604);
+ setPalette(0x98001604);
+ _palette->addPalette("paPodRed", 65, 31, 65);
+ insertMouse433(0x01600988);
+ _class521 = insertSprite<Class521>(this, 375, 227);
+ _class547 = insertSprite<Class547>(375, 227);
+ _class548 = insertSprite<Class548>(375, 227);
+ _sprite2 = insertStaticSprite(0x491F38A8, 1100);
+ _klayman2 = createSprite<KmScene1608>(this, 439, 220); // Special Klayman handling...
+ sendMessage(_klayman2, 0x2032, 1);
+ _klayman2->setDoDeltaX(1);
+ SetMessageHandler(&Scene1608::handleMessage44D470);
+ SetUpdateHandler(&Scene1608::update44D1E0);
+ _class547->setVisible(false);
+ _class548->setVisible(false);
+ // NOTE: Setting the point array was handled by messages 0x2000 (array) and 0x2001 (count) in the original
+ _class521->setPathPoints(_roomPathPoints);
+ sendMessage(_class521, 0x2002, 0);
+ sendMessage(_class521, 0x2008, 90);
+ _sprite3 = insertStaticSprite(0xB47026B0, 1100);
+ _rect1.set(_sprite3->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2());
+ _rect3.set(_sprite2->getDrawRect().x, _sprite3->getDrawRect().y, 640, _sprite2->getDrawRect().y2());
+ _rect2 = _rect1;
+ _rect2.y2 = 215;
+ _klayman2->setClipRect(_rect1);
+ _class521->setClipRect(_rect1);
+ _class547->setClipRect(_rect1);
+ _class548->setClipRect(_rect1);
+ _asTape = insertSprite<AsScene1201Tape>(this, 13, 1100, 412, 443, 0x9148A011);
+ // ... _vm->_collisionMan->addSprite(_asTape);
+ insertSprite<Class518>(_class521)->setClipRect(_rect1);
+ _flag4 = true;
+ _flag2 = true;
+ _flag1 = 0;
+ }
+
+ _palette->addPalette("paKlayRed", 0, 64, 0);
+
+}
+
+Scene1608::~Scene1608() {
+ setGlobalVar(0xC0418A02, _klayman2->isDoDeltaX() ? 1 : 0);
+ // Weird
+ if (_flag4) {
+ delete _klayman2;
+ } else {
+ delete _class521;
+ }
+}
+
+void Scene1608::update44CE90() {
+ Scene::update();
+ if (_countdown1 != 0 && (--_countdown1 == 0)) {
+ leaveScene(0);
+ }
+}
+
+void Scene1608::update44CED0() {
+ Scene::update();
+ if (_flag1 == 1) {
+ removeSurface(_klayman->getSurface());
+ removeEntity(_klayman);
+ addSprite(_class521);
+ _flag4 = true;
+ clearRectList();
+ SetUpdateHandler(&Scene1608::update44CFE0);
+ SetMessageHandler(&Scene1608::handleMessage44D510);
+ _class547->setVisible(false);
+ _class548->setVisible(false);
+ _class521->setVisible(true);
+ sendMessage(_class521, 0x2009, 0);
+ _class521->handleUpdate();
+ _klayman = NULL;
+ _flag1 = 0;
+ }
+ if (_klayman2->getX() <= 375) {
+ _klayman2->setClipRect(_rect1);
+ } else {
+ _klayman2->setClipRect(_rect2);
+ }
+}
+
+void Scene1608::update44CFE0() {
+ Scene::update();
+ if (_mouseClicked) {
+ if (_mouseClickPos.x <= 329 && _class521->getX() == 375 && _class521->getY() == 227) {
+ sendMessage(_class521, 0x200A, 0);
+ SetUpdateHandler(&Scene1608::update44D0C0);
+ } else {
+ sendPointMessage(_class521, 0x2004, _mouseClickPos);
+ SetMessageHandler(&Scene1608::handleMessage44D470);
+ SetUpdateHandler(&Scene1608::update44D1E0);
+ }
+ _mouseClicked = false;
+ }
+ if (_klayman2->getX() <= 375) {
+ _klayman2->setClipRect(_rect1);
+ } else {
+ _klayman2->setClipRect(_rect2);
+ }
+}
+
+void Scene1608::update44D0C0() {
+ Scene::update();
+ if (_flag1 == 2) {
+ _klayman = _klayman2;
+ removeSurface(_class521->getSurface());
+ removeEntity(_class521);
+ addSprite(_klayman);
+ _flag4 = false;
+ SetMessageHandler(&Scene1608::handleMessage44D3C0);
+ SetUpdateHandler(&Scene1608::update44CED0);
+ setRectList(0x004B4810);
+ _class547->setVisible(true);
+ _class548->setVisible(true);
+ _class521->setVisible(false);
+ setMessageList(0x004B4748);
+ runMessageList();
+ _klayman->handleUpdate();
+ _flag1 = 0;
+ }
+ if (_klayman2->getX() <= 375) {
+ _klayman2->setClipRect(_rect1);
+ } else {
+ _klayman2->setClipRect(_rect2);
+ }
+}
+
+void Scene1608::update44D1E0() {
+ Scene::update();
+ if (_mouseClicked) {
+ sendPointMessage(_class521, 0x2004, _mouseClickPos);
+ _mouseClicked = false;
+ }
+ if (_class521->getX() < 300) {
+ if (_flag2) {
+ _flag2 = false;
+ _class521->setClipRect(_rect1);
+ if (!_class521->isDoDeltaX())
+ sendMessage(_class521, 0x200E, 0);
+ }
+ } else if (!_flag2) {
+ _flag2 = true;
+ _class521->setClipRect(_rect3);
+ }
+}
+
+uint32 Scene1608::handleMessage44D2A0(int messageNum, const MessageParam &param, Entity *sender) {
+ Scene::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x20250B1A) {
+ clearRectList();
+ _klayman->setVisible(false);
+ showMouse(false);
+ _sprite1->setVisible(false);
+ sendMessage(_class546, 0x4809, 0);
+ _countdown1 = 28;
+ }
+ break;
+ case 0x200D:
+ sendMessage(_parentModule, 0x200D, 0);
+ break;
+ case 0x4826:
+ if (sender == _asTape) {
+ sendEntityMessage(_klayman2, 0x1014, _asTape);
+ setMessageList(0x004B4770);
+ } else if (sender == _class545) {
+ setMessageList(0x004B46C8);
+ }
+ break;
+ }
+ return 0;
+}
+
+uint32 Scene1608::handleMessage44D3C0(int messageNum, const MessageParam &param, Entity *sender) {
+ Scene::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x100D:
+ if (param.asInteger() == 0x60842040) {
+ _flag1 = true;
+ }
+ break;
+ case 0x200D:
+ sendMessage(_parentModule, 0x200D, 0);
+ break;
+ case 0x4826:
+ if (sender == _class545) {
+ sendEntityMessage(_klayman2, 0x1014, _class545);
+ setMessageList(0x004B4760);
+ }
+ break;
+ }
+ return 0;
+}
+
+uint32 Scene1608::handleMessage44D470(int messageNum, const MessageParam &param, Entity *sender) {
+ Scene::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x2005:
+ leaveScene(1);
+ break;
+ case 0x2006:
+ SetMessageHandler(&Scene1608::handleMessage44D510);
+ SetUpdateHandler(&Scene1608::update44CFE0);
+ sendMessage(_class521, 0x200F, 1);
+ break;
+ case 0x200D:
+ sendMessage(_parentModule, 0x200D, 0);
+ break;
+ }
+ return 0;
+}
+
+uint32 Scene1608::handleMessage44D510(int messageNum, const MessageParam &param, Entity *sender) {
+ Scene::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x200A:
+ _flag1 = 2;
+ break;
+ case 0x200D:
+ sendMessage(_parentModule, 0x200D, 0);
+ break;
+ }
+ return 0;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/module1600.h b/engines/neverhood/module1600.h
new file mode 100644
index 0000000000..9af1a19b39
--- /dev/null
+++ b/engines/neverhood/module1600.h
@@ -0,0 +1,176 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NEVERHOOD_MODULE1600_H
+#define NEVERHOOD_MODULE1600_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+// Module1600
+
+class Module1600 : public Module {
+public:
+ Module1600(NeverhoodEngine *vm, Module *parentModule, int which);
+ virtual ~Module1600();
+protected:
+ void createScene(int sceneNum, int which);
+ void updateScene();
+};
+
+class Class521 : public AnimatedSprite {
+public:
+ Class521(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+ ~Class521();
+ void setPathPoints(NPointArray *pathPoints);
+protected:
+ Scene *_parentScene;
+ NPointArray *_pathPoints;
+ NRectArray *_rectList;
+ int _newMoveDirection;
+ int _currMoveDirection;
+ int _exitDirection;
+ int _currPointIndex;
+ NPoint _againDestPt;
+ int _againDestPtFlag;
+ int _steps;
+ int _stepError;
+ int _idleCounter;
+ int _idleCounterMax;
+ int _lastDistance;
+ int _field100;
+ int _againDestPointFlag;
+ int _flag10E;
+ int _moreY;
+ int _flag10F;
+ int _flag113;
+ int _flag114;
+ int _flag11A;
+ int _newDeltaXType;
+ int _field11E;
+ int _againDestPointIndex;
+ int _value112;
+ int _anotherY;
+ int16 _someX, _someY;
+ NPoint pathPoint(uint index) { return (*_pathPoints)[index]; }
+ void update();
+ void update45C790();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 handleMessage45CC30(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 handleMessage45CCA0(int messageNum, const MessageParam &param, Entity *sender);
+ void sub45CD00();
+ void sub45CDC0();
+ void sub45CE10();
+ void sub45CF80();
+ void sub45CFB0();
+ void sub45CFE0();
+ void sub45D040();
+ void sub45D050();
+ void sub45D0A0();
+ void sub45D0E0();
+ void sub45D100();
+ void sub45D180();
+ void moveToNextPoint();
+ void sub45D350();
+ void sub45D390();
+ void moveToPrevPoint();
+ void sub45D580();
+ void sub45D5D0();
+ void sub45D620();
+ void suMoveToNextPoint();
+ void suMoveToPrevPoint();
+ void sub45E0A0();
+ int calcDistance(int16 x1, int16 y1, int16 x2, int16 y2);
+};
+
+class Class546 : public AnimatedSprite {
+public:
+ Class546(NeverhoodEngine *vm, Scene *parentScene);
+protected:
+ Scene *_parentScene;
+ SoundResource _soundResource;
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void sub44D710();
+ void sub44D760();
+ void sub44D790();
+ void sub44D7F0();
+};
+
+class Class547 : public AnimatedSprite {
+public:
+ Class547(NeverhoodEngine *vm, int16 x, int16 y);
+};
+
+class Class548 : public AnimatedSprite {
+public:
+ Class548(NeverhoodEngine *vm, int16 x, int16 y);
+};
+
+class Class518 : public AnimatedSprite {
+public:
+ Class518(NeverhoodEngine *vm, Class521 *class521);
+protected:
+ Class521 *_class521;
+ void update();
+};
+
+class Scene1608 : public Scene {
+public:
+ Scene1608(NeverhoodEngine *vm, Module *parentModule, int which);
+ ~Scene1608();
+protected:
+ Class521 *_class521;
+ Sprite *_class545;
+ Sprite *_class546;
+ Sprite *_class547;
+ Sprite *_class548;
+ Sprite *_sprite1;
+ Sprite *_sprite2;
+ Sprite *_sprite3;
+ Sprite *_asTape;
+ Klayman *_klayman2;
+ NRect _rect1;
+ NRect _rect2;
+ NRect _rect3;
+ int _flag1;
+ bool _flag2;
+ bool _flag3;
+ bool _flag4;
+ int _countdown1;
+ NPointArray *_roomPathPoints;
+ void update44CE90();
+ void update44CED0();
+ void update44CFE0();
+ void update44D0C0();
+ void update44D1E0();
+ uint32 handleMessage44D2A0(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 handleMessage44D3C0(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 handleMessage44D470(int messageNum, const MessageParam &param, Entity *sender);
+ uint32 handleMessage44D510(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULE1600_H */
diff --git a/engines/neverhood/scene.cpp b/engines/neverhood/scene.cpp
index 441ee1e291..9a588f283f 100644
--- a/engines/neverhood/scene.cpp
+++ b/engines/neverhood/scene.cpp
@@ -274,6 +274,10 @@ void Scene::update() {
}
+void Scene::leaveScene(uint32 result) {
+ sendMessage(_parentModule, 0x1009, result);
+}
+
uint32 Scene::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
switch (messageNum) {
case 0: // mouse moved
diff --git a/engines/neverhood/scene.h b/engines/neverhood/scene.h
index 09d34b5734..e962266168 100644
--- a/engines/neverhood/scene.h
+++ b/engines/neverhood/scene.h
@@ -64,6 +64,7 @@ public:
void changeMouseCursor(uint32 fileHash);
SmackerPlayer *addSmackerPlayer(SmackerPlayer *smackerPlayer);
void update();
+ void leaveScene(uint32 result);
// Some crazy templated functions to make the logic code smaller/simpler (imo!)
// insertKlayman
template<class T>
@@ -123,6 +124,35 @@ public:
T* insertSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6) {
return (T*)addSprite(new T(_vm, arg1, arg2, arg3, arg4, arg5, arg6));
}
+ // createSprite
+ template<class T>
+ T* createSprite() {
+ return new T(_vm);
+ }
+ template<class T, class Arg1>
+ T* createSprite(Arg1 arg1) {
+ return new T(_vm, arg1);
+ }
+ template<class T, class Arg1, class Arg2>
+ T* createSprite(Arg1 arg1, Arg2 arg2) {
+ return new T(_vm, arg1, arg2);
+ }
+ template<class T, class Arg1, class Arg2, class Arg3>
+ T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
+ return new T(_vm, arg1, arg2, arg3);
+ }
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4>
+ T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) {
+ return new T(_vm, arg1, arg2, arg3, arg4);
+ }
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
+ T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) {
+ return new T(_vm, arg1, arg2, arg3, arg4, arg5);
+ }
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6>
+ T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6) {
+ return new T(_vm, arg1, arg2, arg3, arg4, arg5, arg6);
+ }
protected:
Module *_parentModule;
Common::Array<Entity*> _entities;