From bf96d305b59d1abbf59d3f03622bc025f494791f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 5 Oct 2013 21:12:28 +0300 Subject: NEVERHOOD: Split sprites from their scenes in modules 1300 and 1400 --- engines/neverhood/module.mk | 2 + engines/neverhood/modules/module1300.cpp | 608 +--------------- engines/neverhood/modules/module1300.h | 129 ---- engines/neverhood/modules/module1300_sprites.cpp | 630 ++++++++++++++++ engines/neverhood/modules/module1300_sprites.h | 162 +++++ engines/neverhood/modules/module1400.cpp | 876 +--------------------- engines/neverhood/modules/module1400.h | 151 +--- engines/neverhood/modules/module1400_sprites.cpp | 885 +++++++++++++++++++++++ engines/neverhood/modules/module1400_sprites.h | 170 +++++ 9 files changed, 1860 insertions(+), 1753 deletions(-) create mode 100644 engines/neverhood/modules/module1300_sprites.cpp create mode 100644 engines/neverhood/modules/module1300_sprites.h create mode 100644 engines/neverhood/modules/module1400_sprites.cpp create mode 100644 engines/neverhood/modules/module1400_sprites.h (limited to 'engines') diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk index cd0a9fa140..7a36bc3750 100644 --- a/engines/neverhood/module.mk +++ b/engines/neverhood/module.mk @@ -18,7 +18,9 @@ MODULE_OBJS = \ modules/module1100.o \ modules/module1200.o \ modules/module1300.o \ + modules/module1300_sprites.o \ modules/module1400.o \ + modules/module1400_sprites.o \ modules/module1500.o \ modules/module1600.o \ modules/module1600_sprites.o \ diff --git a/engines/neverhood/modules/module1300.cpp b/engines/neverhood/modules/module1300.cpp index 88f5784eaa..604f60d2ed 100644 --- a/engines/neverhood/modules/module1300.cpp +++ b/engines/neverhood/modules/module1300.cpp @@ -20,10 +20,11 @@ * */ -#include "neverhood/modules/module1300.h" #include "neverhood/modules/module1000.h" #include "neverhood/modules/module1200.h" -#include "neverhood/modules/module1400.h" +#include "neverhood/modules/module1300.h" +#include "neverhood/modules/module1300_sprites.h" +#include "neverhood/modules/module1400_sprites.h" #include "neverhood/modules/module2200_sprites.h" #include "neverhood/gamemodule.h" #include "neverhood/diskplayerscene.h" @@ -311,113 +312,6 @@ void Module1300::updateScene() { } } -AsScene1302Bridge::AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - - _x = 320; - _y = 240; - createSurface1(0x88148150, 500); - if (!getGlobalVar(V_FLYTRAP_RING_BRIDGE)) { - startAnimation(0x88148150, 0, -1); - _newStickFrameIndex = 0; - } else { - startAnimation(0x88148150, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - } - loadSound(0, 0x68895082); - loadSound(1, 0x689BD0C1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1302Bridge::handleMessage); -} - -uint32 AsScene1302Bridge::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - case 0x4808: - stLowerBridge(); - break; - case 0x4809: - stRaiseBridge(); - break; - } - return messageResult; -} - -void AsScene1302Bridge::stLowerBridge() { - startAnimation(0x88148150, 0, -1); - playSound(1); - NextState(&AsScene1302Bridge::cbLowerBridgeEvent); -} - -void AsScene1302Bridge::stRaiseBridge() { - startAnimation(0x88148150, 7, -1); - _playBackwards = true; - _newStickFrameIndex = 0; - playSound(0); -} - -void AsScene1302Bridge::cbLowerBridgeEvent() { - sendMessage(_parentScene, 0x2032, 0); - startAnimation(0x88148150, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; -} - -SsScene1302Fence::SsScene1302Fence(NeverhoodEngine *vm) - : StaticSprite(vm, 0x11122122, 200) { - - _firstY = _y; - if (getGlobalVar(V_FLYTRAP_RING_FENCE)) - _y += 152; - loadSound(0, 0x7A00400C); - loadSound(1, 0x78184098); - SetUpdateHandler(&SsScene1302Fence::update); - SetMessageHandler(&SsScene1302Fence::handleMessage); - SetSpriteUpdate(NULL); -} - -void SsScene1302Fence::update() { - handleSpriteUpdate(); - updatePosition(); -} - -uint32 SsScene1302Fence::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4808: - playSound(0); - SetMessageHandler(NULL); - SetSpriteUpdate(&SsScene1302Fence::suMoveDown); - break; - case 0x4809: - playSound(1); - SetMessageHandler(NULL); - SetSpriteUpdate(&SsScene1302Fence::suMoveUp); - break; - } - return messageResult; -} - -void SsScene1302Fence::suMoveDown() { - if (_y < _firstY + 152) - _y += 8; - else { - SetMessageHandler(&SsScene1302Fence::handleMessage); - SetSpriteUpdate(NULL); - } -} - -void SsScene1302Fence::suMoveUp() { - if (_y > _firstY) - _y -= 8; - else { - SetMessageHandler(&SsScene1302Fence::handleMessage); - SetSpriteUpdate(NULL); - } -} - Scene1302::Scene1302(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { @@ -581,54 +475,6 @@ uint32 Scene1302::handleMessage(int messageNum, const MessageParam ¶m, Entit return messageResult; } -AsScene1303Balloon::AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - - createSurface(200, 128, 315); - _x = 289; - _y = 390; - startAnimation(0x800278D2, 0, -1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1303Balloon::handleMessage); - SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); -} - -uint32 AsScene1303Balloon::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x2000: - stPopBalloon(); - break; - } - return messageResult; -} - -uint32 AsScene1303Balloon::hmBalloonPopped(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x020B0003) - playSound(0, 0x742B0055); - break; - case 0x3002: - playSound(0, 0x470007EE); - stopAnimation(); - setVisible(false); - SetMessageHandler(NULL); - break; - } - return messageResult; -} - -void AsScene1303Balloon::stPopBalloon() { - startAnimation(0xAC004CD0, 0, -1); - SetMessageHandler(&AsScene1303Balloon::hmBalloonPopped); -} - Scene1303::Scene1303(NeverhoodEngine *vm, Module *parentModule) : Scene(vm, parentModule), _asBalloon(NULL) { @@ -668,29 +514,6 @@ uint32 Scene1303::handleMessage(int messageNum, const MessageParam ¶m, Entit return 0; } -AsScene1304Needle::AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y) - : AnimatedSprite(vm, 0x548E9411, surfacePriority, x, y), _parentScene(parentScene) { - - // NOTE: Skipped check if Klaymen already has the needle since that's done in the scene itself - SetMessageHandler(&AsScene1304Needle::handleMessage); -} - -uint32 AsScene1304Needle::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x4806: - setGlobalVar(V_HAS_NEEDLE, 1); - setVisible(false); - SetMessageHandler(NULL); - break; - } - return messageResult; -} - Scene1304::Scene1304(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _asNeedle(NULL) { @@ -781,91 +604,6 @@ uint32 Scene1305::handleMessage(int messageNum, const MessageParam ¶m, Entit return Scene::handleMessage(messageNum, param, sender); } -AsScene1306Elevator::AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _asElevatorDoor(asElevatorDoor), _isUp(false), _isDown(true), - _countdown(0) { - - _x = 320; - _y = 240; - createSurface1(0x043B0270, 100); - startAnimation(0x043B0270, 0, -1); - _newStickFrameIndex = 0; - loadSound(0, 0x1C100E83); - loadSound(1, 0x1C08CEC5); - loadSound(2, 0x5D011E87); - SetMessageHandler(&AsScene1306Elevator::handleMessage); -} - -void AsScene1306Elevator::update() { - if (_isUp && _countdown != 0 && (--_countdown == 0)) - stGoingDown(); - AnimatedSprite::update(); - if (_currFrameIndex == 7 && _asElevatorDoor->getVisible()) { - playSound(1); - _asElevatorDoor->setVisible(false); - } -} - -void AsScene1306Elevator::upGoingDown() { - AnimatedSprite::update(); - if (_currFrameIndex == 5) - _asElevatorDoor->setVisible(true); -} - -uint32 AsScene1306Elevator::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2001: - if (_isUp) - _countdown = 144; - messageResult = _isUp ? 1 : 0; - break; - case 0x3002: - gotoNextState(); - break; - case 0x4808: - if (_isDown) - stGoingUp(); - break; - } - return messageResult; -} - -void AsScene1306Elevator::stGoingUp() { - setVisible(true); - _isDown = false; - startAnimation(0x043B0270, 0, -1); - playSound(0); - SetUpdateHandler(&AsScene1306Elevator::update); - NextState(&AsScene1306Elevator::cbGoingUpEvent); -} - -void AsScene1306Elevator::cbGoingUpEvent() { - sendMessage(_parentScene, 0x4808, 0); - _isUp = true; - _countdown = 144; - stopAnimation(); - setVisible(false); - SetUpdateHandler(&AsScene1306Elevator::update); -} - -void AsScene1306Elevator::stGoingDown() { - _isUp = false; - setVisible(true); - startAnimation(0x043B0270, -1, -1); - _playBackwards = true; - playSound(1); - SetUpdateHandler(&AsScene1306Elevator::upGoingDown); - NextState(&AsScene1306Elevator::cbGoingDownEvent); -} - -void AsScene1306Elevator::cbGoingDownEvent() { - _isDown = true; - sendMessage(_parentScene, 0x4809, 0); - stopAnimation(); - SetUpdateHandler(&AsScene1306Elevator::update); -} - Scene1306::Scene1306(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { @@ -1039,188 +777,6 @@ uint32 Scene1306::handleMessage416EB0(int messageNum, const MessageParam ¶m, return 0; } -static const uint32 kAsScene1307KeyResourceList1[] = { - 0x0438069C, 0x45B0023C, 0x05700217 -}; - -static const uint32 kAsScene1307KeyResourceList2[] = { - 0x04441334, 0x061433F0, 0x06019390 -}; - -static const uint32 kAsScene1307KeyResourceList3[] = { - 0x11A80030, 0x178812B1, 0x1488121C -}; - -static const uint32 *kAsScene1307KeyResourceLists[] = { - kAsScene1307KeyResourceList1, - kAsScene1307KeyResourceList2, - kAsScene1307KeyResourceList3 -}; - -static const int kAsScene1307KeySurfacePriorities[] = { - 700, 500, 300, 100 -}; - -const uint kAsScene1307KeyPointsCount = 12; - -static const NPoint kAsScene1307KeyPoints[] = { - {-2, 0}, {-5, 0}, { 5, 0}, - {12, 0}, {17, 0}, {25, 0}, - {16, -2}, {10, -6}, { 0, -7}, - {-7, -3}, {-3, 4}, { 2, 2} -}; - -const uint kAsScene1307KeyFrameIndicesCount = 20; - -static const int16 kAsScene1307KeyFrameIndices[] = { - 1, 4, 8, 11, 15, 16, 17, 17, 17, 16, - 15, 14, 12, 10, 9, 7, 5, 3, 2, 1 -}; - -const int kAsScene1307KeyDivValue = 200; -const int16 kAsScene1307KeyXDelta = 70; -const int16 kAsScene1307KeyYDelta = -12; - -AsScene1307Key::AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _keyIndex(keyIndex), _clipRects(clipRects), - _isClickable(true) { - - NPoint pt; - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; - - _dataResource.load(0x22102142); - _pointList = _dataResource.getPointArray(0xAC849240); - pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; - _x = pt.x; - _y = pt.y; - createSurface(kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4], 190, 148); - startAnimation(fileHashes[0], 0, -1); - loadSound(0, 0xDC4A1280); - loadSound(1, 0xCC021233); - loadSound(2, 0xC4C23844); - loadSound(3, 0xC4523208); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1307Key::handleMessage); -} - -uint32 AsScene1307Key::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (_isClickable) { - sendMessage(_parentScene, 0x4826, 0); - stRemoveKey(); - messageResult = 1; - } - break; - case 0x2000: - _isClickable = param.asInteger() != 0; - break; - case 0x2001: - setSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex, param.asInteger()); - stMoveKey(); - break; - case 0x2003: - playSound(3); - stUnlock(); - break; - case 0x2004: - playSound(2); - stInsert(); - break; - } - return messageResult; -} - -void AsScene1307Key::suRemoveKey() { - if (_pointIndex < kAsScene1307KeyPointsCount) { - _x += kAsScene1307KeyPoints[_pointIndex].x; - _y += kAsScene1307KeyPoints[_pointIndex].y; - updateBounds(); - _pointIndex++; - } else { - SetSpriteUpdate(NULL); - } -} - -void AsScene1307Key::suInsertKey() { - if (_pointIndex < kAsScene1307KeyPointsCount) { - _x -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].x; - _y -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].y; - updateBounds(); - _pointIndex++; - if (_pointIndex == 7) - playSound(0); - } else { - SetSpriteUpdate(NULL); - sendMessage(_parentScene, 0x2002, 0); - } -} - -void AsScene1307Key::suMoveKey() { - if (_pointIndex < kAsScene1307KeyFrameIndicesCount) { - _frameIndex += kAsScene1307KeyFrameIndices[_pointIndex]; - _x = _prevX + (_deltaX * _frameIndex) / kAsScene1307KeyDivValue; - _y = _prevY + (_deltaY * _frameIndex) / kAsScene1307KeyDivValue; - updateBounds(); - _pointIndex++; - } else { - NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; - _x = pt.x + kAsScene1307KeyXDelta; - _y = pt.y + kAsScene1307KeyYDelta; - stInsertKey(); - } -} - -void AsScene1307Key::stRemoveKey() { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; - _pointIndex = 0; - startAnimation(fileHashes[0], 0, -1); - playSound(1); - SetSpriteUpdate(&AsScene1307Key::suRemoveKey); -} - -void AsScene1307Key::stInsertKey() { - _pointIndex = 0; - sendMessage(_parentScene, 0x1022, kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]); - setClipRect(_clipRects[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]); - _newStickFrameIndex = STICK_LAST_FRAME; - SetSpriteUpdate(&AsScene1307Key::suInsertKey); -} - -void AsScene1307Key::stMoveKey() { - NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; - int16 newX = pt.x + kAsScene1307KeyXDelta; - int16 newY = pt.y + kAsScene1307KeyYDelta; - sendMessage(_parentScene, 0x1022, 1000); - setClipRect(0, 0, 640, 480); - _prevX = _x; - _prevY = _y; - if (newX == _x && newY == _y) { - stInsertKey(); - } else { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; - _pointIndex = 0; - _frameIndex = 0; - _deltaX = newX - _x; - _deltaY = newY - _y; - startAnimation(fileHashes[0], 0, -1); - SetSpriteUpdate(&AsScene1307Key::suMoveKey); - } -} - -void AsScene1307Key::stUnlock() { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; - startAnimation(fileHashes[1], 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; -} - -void AsScene1307Key::stInsert() { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; - startAnimation(fileHashes[2], 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; -} - Scene1307::Scene1307(NeverhoodEngine *vm, Module *parentModule) : Scene(vm, parentModule), _countdown(0), _asCurrKey(NULL), _isInsertingKey(false), _doLeaveScene(false), _isPuzzleSolved(false) { @@ -1360,164 +916,6 @@ static const uint32 kScene1308NumberFileHashes[] = { 0x00306322 }; -AsScene1308JaggyDoor::AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 0xBA0AE050, 1100, 320, 240), _parentScene(parentScene) { - - setVisible(false); - stopAnimation(); - SetMessageHandler(&AsScene1308JaggyDoor::handleMessage); -} - -uint32 AsScene1308JaggyDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - case 0x4808: - stOpenDoor(); - break; - case 0x4809: - stCloseDoor(); - break; - } - return messageResult; -} - -void AsScene1308JaggyDoor::stOpenDoor() { - startAnimation(0xBA0AE050, 0, -1); - setVisible(true); - playSound(0, calcHash("fxDoorOpen38")); - NextState(&AsScene1308JaggyDoor::stOpenDoorDone); -} - -void AsScene1308JaggyDoor::stOpenDoorDone() { - sendMessage(_parentScene, 0x2000, 0); - stopAnimation(); - setVisible(false); -} - -void AsScene1308JaggyDoor::stCloseDoor() { - startAnimation(0xBA0AE050, -1, -1); - _playBackwards = true; - setVisible(true); - playSound(0, calcHash("fxDoorClose38")); - NextState(&AsScene1308JaggyDoor::stCloseDoorDone); -} - -void AsScene1308JaggyDoor::stCloseDoorDone() { - sendMessage(_parentScene, 0x2001, 0); - stopAnimation(); -} - -AsScene1308KeyboardDoor::AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 0xA08A0851, 1100, 320, 240), _parentScene(parentScene) { - - playSound(0, 0x51456049); - SetMessageHandler(&AsScene1308KeyboardDoor::handleMessage); - NextState(&AsScene1308KeyboardDoor::stFallingKeys); -} - -uint32 AsScene1308KeyboardDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1308KeyboardDoor::stFallingKeys() { - startAnimation(0x6238B191, 0, -1); - _x = 580; - _y = 383; - NextState(&AsScene1308KeyboardDoor::stFallingKeysDone); -} - -void AsScene1308KeyboardDoor::stFallingKeysDone() { - sendMessage(_parentScene, 0x2004, 0); - stopAnimation(); - setVisible(false); -} - -AsScene1308LightWallSymbols::AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 0x80180A10, 100, 320, 240), _parentScene(parentScene) { - - setVisible(false); - stopAnimation(); - Entity::_priority = 1200; - SetMessageHandler(&AsScene1308LightWallSymbols::handleMessage); -} - -uint32 AsScene1308LightWallSymbols::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2002: - stFadeIn(); - break; - case 0x2003: - stFadeOut(); - break; - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1308LightWallSymbols::stFadeIn() { - startAnimation(0x80180A10, 0, -1); - setVisible(true); - _newStickFrameIndex = STICK_LAST_FRAME; -} - -void AsScene1308LightWallSymbols::stFadeOut() { - startAnimation(0x80180A10, -1, -1); - _playBackwards = true; - NextState(&AsScene1308LightWallSymbols::stFadeOutDone); -} - -void AsScene1308LightWallSymbols::stFadeOutDone() { - sendMessage(_parentScene, 0x2003, 0); - stopAnimation(); - setVisible(false); -} - -SsScene1308Number::SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index) - : StaticSprite(vm, fileHash, 100) { - - setVisible(false); - _x = _spriteResource.getPosition().x + index * 20; - updatePosition(); -} - -AsScene1308Mouse::AsScene1308Mouse(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100) { - - _x = 286; - _y = 429; - createSurface1(0xA282C472, 100); - startAnimation(0xA282C472, 0, -1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1308Mouse::handleMessage); -} - -uint32 AsScene1308Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x66382026) - playSound(0, 0x0CD84468); - else if (param.asInteger() == 0x6E28061C) - playSound(0, 0x78C8402C); - else if (param.asInteger() == 0x462F0410) - playSound(0, 0x60984E28); - break; - } - return messageResult; -} - Scene1308::Scene1308(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _isProjecting(false), _asProjector(NULL) { diff --git a/engines/neverhood/modules/module1300.h b/engines/neverhood/modules/module1300.h index 501f76304f..2f59ff16c2 100644 --- a/engines/neverhood/modules/module1300.h +++ b/engines/neverhood/modules/module1300.h @@ -30,8 +30,6 @@ namespace Neverhood { -// Module1300 - class Module1300 : public Module { public: Module1300(NeverhoodEngine *vm, Module *parentModule, int which); @@ -43,28 +41,6 @@ protected: void updateScene(); }; -class AsScene1302Bridge : public AnimatedSprite { -public: - AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stLowerBridge(); - void stRaiseBridge(); - void cbLowerBridgeEvent(); -}; - -class SsScene1302Fence : public StaticSprite { -public: - SsScene1302Fence(NeverhoodEngine *vm); -protected: - int16 _firstY; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suMoveDown(); - void suMoveUp(); -}; - class Scene1302 : public Scene { public: Scene1302(NeverhoodEngine *vm, Module *parentModule, int which); @@ -84,16 +60,6 @@ protected: uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; -class AsScene1303Balloon : public AnimatedSprite { -public: - AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmBalloonPopped(int messageNum, const MessageParam ¶m, Entity *sender); - void stPopBalloon(); -}; - class Scene1303 : public Scene { public: Scene1303(NeverhoodEngine *vm, Module *parentModule); @@ -103,14 +69,6 @@ protected: uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; -class AsScene1304Needle : public AnimatedSprite { -public: - AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - class Scene1304 : public Scene { public: Scene1304(NeverhoodEngine *vm, Module *parentModule, int which); @@ -128,24 +86,6 @@ protected: uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; -class AsScene1306Elevator : public AnimatedSprite { -public: - AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor); -protected: - Scene *_parentScene; - AnimatedSprite *_asElevatorDoor; - bool _isUp; - bool _isDown; - int _countdown; - void update(); - void upGoingDown(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stGoingUp(); - void cbGoingUpEvent(); - void stGoingDown(); - void cbGoingDownEvent(); -}; - class Scene1306 : public Scene { public: Scene1306(NeverhoodEngine *vm, Module *parentModule, int which); @@ -161,30 +101,6 @@ protected: uint32 handleMessage416EB0(int messageNum, const MessageParam ¶m, Entity *sender); }; -class AsScene1307Key : public AnimatedSprite { -public: - AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects); -protected: - Scene *_parentScene; - NPointArray *_pointList; - uint _pointIndex; - int _frameIndex; - uint _keyIndex; - NRect *_clipRects; - bool _isClickable; - int16 _prevX, _prevY; - int16 _deltaX, _deltaY; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suRemoveKey(); - void suInsertKey(); - void suMoveKey(); - void stRemoveKey(); - void stInsertKey(); - void stMoveKey(); - void stUnlock(); - void stInsert(); -}; - class Scene1307 : public Scene { public: Scene1307(NeverhoodEngine *vm, Module *parentModule); @@ -202,51 +118,6 @@ protected: uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; -class AsScene1308JaggyDoor : public AnimatedSprite { -public: - AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stOpenDoor(); - void stOpenDoorDone(); - void stCloseDoor(); - void stCloseDoorDone(); -}; - -class AsScene1308KeyboardDoor : public AnimatedSprite { -public: - AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stFallingKeys(); - void stFallingKeysDone(); -}; - -class AsScene1308LightWallSymbols : public AnimatedSprite { -public: - AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stFadeIn(); - void stFadeOut(); - void stFadeOutDone(); -}; - -class SsScene1308Number : public StaticSprite { -public: - SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index); -}; - -class AsScene1308Mouse : public AnimatedSprite { -public: - AsScene1308Mouse(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - class Scene1308 : public Scene { public: Scene1308(NeverhoodEngine *vm, Module *parentModule, int which); diff --git a/engines/neverhood/modules/module1300_sprites.cpp b/engines/neverhood/modules/module1300_sprites.cpp new file mode 100644 index 0000000000..1ddee349d2 --- /dev/null +++ b/engines/neverhood/modules/module1300_sprites.cpp @@ -0,0 +1,630 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "neverhood/modules/module1300_sprites.h" + +namespace Neverhood { + +AsScene1302Bridge::AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1100), _parentScene(parentScene) { + + _x = 320; + _y = 240; + createSurface1(0x88148150, 500); + if (!getGlobalVar(V_FLYTRAP_RING_BRIDGE)) { + startAnimation(0x88148150, 0, -1); + _newStickFrameIndex = 0; + } else { + startAnimation(0x88148150, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + } + loadSound(0, 0x68895082); + loadSound(1, 0x689BD0C1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1302Bridge::handleMessage); +} + +uint32 AsScene1302Bridge::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + case 0x4808: + stLowerBridge(); + break; + case 0x4809: + stRaiseBridge(); + break; + } + return messageResult; +} + +void AsScene1302Bridge::stLowerBridge() { + startAnimation(0x88148150, 0, -1); + playSound(1); + NextState(&AsScene1302Bridge::cbLowerBridgeEvent); +} + +void AsScene1302Bridge::stRaiseBridge() { + startAnimation(0x88148150, 7, -1); + _playBackwards = true; + _newStickFrameIndex = 0; + playSound(0); +} + +void AsScene1302Bridge::cbLowerBridgeEvent() { + sendMessage(_parentScene, 0x2032, 0); + startAnimation(0x88148150, -1, -1); + _newStickFrameIndex = STICK_LAST_FRAME; +} + +SsScene1302Fence::SsScene1302Fence(NeverhoodEngine *vm) + : StaticSprite(vm, 0x11122122, 200) { + + _firstY = _y; + if (getGlobalVar(V_FLYTRAP_RING_FENCE)) + _y += 152; + loadSound(0, 0x7A00400C); + loadSound(1, 0x78184098); + SetUpdateHandler(&SsScene1302Fence::update); + SetMessageHandler(&SsScene1302Fence::handleMessage); + SetSpriteUpdate(NULL); +} + +void SsScene1302Fence::update() { + handleSpriteUpdate(); + updatePosition(); +} + +uint32 SsScene1302Fence::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4808: + playSound(0); + SetMessageHandler(NULL); + SetSpriteUpdate(&SsScene1302Fence::suMoveDown); + break; + case 0x4809: + playSound(1); + SetMessageHandler(NULL); + SetSpriteUpdate(&SsScene1302Fence::suMoveUp); + break; + } + return messageResult; +} + +void SsScene1302Fence::suMoveDown() { + if (_y < _firstY + 152) + _y += 8; + else { + SetMessageHandler(&SsScene1302Fence::handleMessage); + SetSpriteUpdate(NULL); + } +} + +void SsScene1302Fence::suMoveUp() { + if (_y > _firstY) + _y -= 8; + else { + SetMessageHandler(&SsScene1302Fence::handleMessage); + SetSpriteUpdate(NULL); + } +} + +AsScene1303Balloon::AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1100), _parentScene(parentScene) { + + createSurface(200, 128, 315); + _x = 289; + _y = 390; + startAnimation(0x800278D2, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1303Balloon::handleMessage); + SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); +} + +uint32 AsScene1303Balloon::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x2000: + stPopBalloon(); + break; + } + return messageResult; +} + +uint32 AsScene1303Balloon::hmBalloonPopped(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x020B0003) + playSound(0, 0x742B0055); + break; + case 0x3002: + playSound(0, 0x470007EE); + stopAnimation(); + setVisible(false); + SetMessageHandler(NULL); + break; + } + return messageResult; +} + +void AsScene1303Balloon::stPopBalloon() { + startAnimation(0xAC004CD0, 0, -1); + SetMessageHandler(&AsScene1303Balloon::hmBalloonPopped); +} + +AsScene1304Needle::AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y) + : AnimatedSprite(vm, 0x548E9411, surfacePriority, x, y), _parentScene(parentScene) { + + // NOTE: Skipped check if Klaymen already has the needle since that's done in the scene itself + SetMessageHandler(&AsScene1304Needle::handleMessage); +} + +uint32 AsScene1304Needle::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x4806: + setGlobalVar(V_HAS_NEEDLE, 1); + setVisible(false); + SetMessageHandler(NULL); + break; + } + return messageResult; +} + +AsScene1306Elevator::AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _asElevatorDoor(asElevatorDoor), _isUp(false), _isDown(true), + _countdown(0) { + + _x = 320; + _y = 240; + createSurface1(0x043B0270, 100); + startAnimation(0x043B0270, 0, -1); + _newStickFrameIndex = 0; + loadSound(0, 0x1C100E83); + loadSound(1, 0x1C08CEC5); + loadSound(2, 0x5D011E87); + SetMessageHandler(&AsScene1306Elevator::handleMessage); +} + +void AsScene1306Elevator::update() { + if (_isUp && _countdown != 0 && (--_countdown == 0)) + stGoingDown(); + AnimatedSprite::update(); + if (_currFrameIndex == 7 && _asElevatorDoor->getVisible()) { + playSound(1); + _asElevatorDoor->setVisible(false); + } +} + +void AsScene1306Elevator::upGoingDown() { + AnimatedSprite::update(); + if (_currFrameIndex == 5) + _asElevatorDoor->setVisible(true); +} + +uint32 AsScene1306Elevator::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2001: + if (_isUp) + _countdown = 144; + messageResult = _isUp ? 1 : 0; + break; + case 0x3002: + gotoNextState(); + break; + case 0x4808: + if (_isDown) + stGoingUp(); + break; + } + return messageResult; +} + +void AsScene1306Elevator::stGoingUp() { + setVisible(true); + _isDown = false; + startAnimation(0x043B0270, 0, -1); + playSound(0); + SetUpdateHandler(&AsScene1306Elevator::update); + NextState(&AsScene1306Elevator::cbGoingUpEvent); +} + +void AsScene1306Elevator::cbGoingUpEvent() { + sendMessage(_parentScene, 0x4808, 0); + _isUp = true; + _countdown = 144; + stopAnimation(); + setVisible(false); + SetUpdateHandler(&AsScene1306Elevator::update); +} + +void AsScene1306Elevator::stGoingDown() { + _isUp = false; + setVisible(true); + startAnimation(0x043B0270, -1, -1); + _playBackwards = true; + playSound(1); + SetUpdateHandler(&AsScene1306Elevator::upGoingDown); + NextState(&AsScene1306Elevator::cbGoingDownEvent); +} + +void AsScene1306Elevator::cbGoingDownEvent() { + _isDown = true; + sendMessage(_parentScene, 0x4809, 0); + stopAnimation(); + SetUpdateHandler(&AsScene1306Elevator::update); +} + +static const uint32 kAsScene1307KeyResourceList1[] = { + 0x0438069C, 0x45B0023C, 0x05700217 +}; + +static const uint32 kAsScene1307KeyResourceList2[] = { + 0x04441334, 0x061433F0, 0x06019390 +}; + +static const uint32 kAsScene1307KeyResourceList3[] = { + 0x11A80030, 0x178812B1, 0x1488121C +}; + +static const uint32 *kAsScene1307KeyResourceLists[] = { + kAsScene1307KeyResourceList1, + kAsScene1307KeyResourceList2, + kAsScene1307KeyResourceList3 +}; + +static const int kAsScene1307KeySurfacePriorities[] = { + 700, 500, 300, 100 +}; + +const uint kAsScene1307KeyPointsCount = 12; + +static const NPoint kAsScene1307KeyPoints[] = { + {-2, 0}, {-5, 0}, { 5, 0}, + {12, 0}, {17, 0}, {25, 0}, + {16, -2}, {10, -6}, { 0, -7}, + {-7, -3}, {-3, 4}, { 2, 2} +}; + +const uint kAsScene1307KeyFrameIndicesCount = 20; + +static const int16 kAsScene1307KeyFrameIndices[] = { + 1, 4, 8, 11, 15, 16, 17, 17, 17, 16, + 15, 14, 12, 10, 9, 7, 5, 3, 2, 1 +}; + +const int kAsScene1307KeyDivValue = 200; +const int16 kAsScene1307KeyXDelta = 70; +const int16 kAsScene1307KeyYDelta = -12; + +AsScene1307Key::AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _keyIndex(keyIndex), _clipRects(clipRects), + _isClickable(true) { + + NPoint pt; + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + + _dataResource.load(0x22102142); + _pointList = _dataResource.getPointArray(0xAC849240); + pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; + _x = pt.x; + _y = pt.y; + createSurface(kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4], 190, 148); + startAnimation(fileHashes[0], 0, -1); + loadSound(0, 0xDC4A1280); + loadSound(1, 0xCC021233); + loadSound(2, 0xC4C23844); + loadSound(3, 0xC4523208); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1307Key::handleMessage); +} + +uint32 AsScene1307Key::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_isClickable) { + sendMessage(_parentScene, 0x4826, 0); + stRemoveKey(); + messageResult = 1; + } + break; + case 0x2000: + _isClickable = param.asInteger() != 0; + break; + case 0x2001: + setSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex, param.asInteger()); + stMoveKey(); + break; + case 0x2003: + playSound(3); + stUnlock(); + break; + case 0x2004: + playSound(2); + stInsert(); + break; + } + return messageResult; +} + +void AsScene1307Key::suRemoveKey() { + if (_pointIndex < kAsScene1307KeyPointsCount) { + _x += kAsScene1307KeyPoints[_pointIndex].x; + _y += kAsScene1307KeyPoints[_pointIndex].y; + updateBounds(); + _pointIndex++; + } else { + SetSpriteUpdate(NULL); + } +} + +void AsScene1307Key::suInsertKey() { + if (_pointIndex < kAsScene1307KeyPointsCount) { + _x -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].x; + _y -= kAsScene1307KeyPoints[kAsScene1307KeyPointsCount - _pointIndex - 1].y; + updateBounds(); + _pointIndex++; + if (_pointIndex == 7) + playSound(0); + } else { + SetSpriteUpdate(NULL); + sendMessage(_parentScene, 0x2002, 0); + } +} + +void AsScene1307Key::suMoveKey() { + if (_pointIndex < kAsScene1307KeyFrameIndicesCount) { + _frameIndex += kAsScene1307KeyFrameIndices[_pointIndex]; + _x = _prevX + (_deltaX * _frameIndex) / kAsScene1307KeyDivValue; + _y = _prevY + (_deltaY * _frameIndex) / kAsScene1307KeyDivValue; + updateBounds(); + _pointIndex++; + } else { + NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; + _x = pt.x + kAsScene1307KeyXDelta; + _y = pt.y + kAsScene1307KeyYDelta; + stInsertKey(); + } +} + +void AsScene1307Key::stRemoveKey() { + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + _pointIndex = 0; + startAnimation(fileHashes[0], 0, -1); + playSound(1); + SetSpriteUpdate(&AsScene1307Key::suRemoveKey); +} + +void AsScene1307Key::stInsertKey() { + _pointIndex = 0; + sendMessage(_parentScene, 0x1022, kAsScene1307KeySurfacePriorities[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]); + setClipRect(_clipRects[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex) % 4]); + _newStickFrameIndex = STICK_LAST_FRAME; + SetSpriteUpdate(&AsScene1307Key::suInsertKey); +} + +void AsScene1307Key::stMoveKey() { + NPoint pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; + int16 newX = pt.x + kAsScene1307KeyXDelta; + int16 newY = pt.y + kAsScene1307KeyYDelta; + sendMessage(_parentScene, 0x1022, 1000); + setClipRect(0, 0, 640, 480); + _prevX = _x; + _prevY = _y; + if (newX == _x && newY == _y) { + stInsertKey(); + } else { + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + _pointIndex = 0; + _frameIndex = 0; + _deltaX = newX - _x; + _deltaY = newY - _y; + startAnimation(fileHashes[0], 0, -1); + SetSpriteUpdate(&AsScene1307Key::suMoveKey); + } +} + +void AsScene1307Key::stUnlock() { + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + startAnimation(fileHashes[1], 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; +} + +void AsScene1307Key::stInsert() { + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + startAnimation(fileHashes[2], 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; +} + +AsScene1308JaggyDoor::AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 0xBA0AE050, 1100, 320, 240), _parentScene(parentScene) { + + setVisible(false); + stopAnimation(); + SetMessageHandler(&AsScene1308JaggyDoor::handleMessage); +} + +uint32 AsScene1308JaggyDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + case 0x4808: + stOpenDoor(); + break; + case 0x4809: + stCloseDoor(); + break; + } + return messageResult; +} + +void AsScene1308JaggyDoor::stOpenDoor() { + startAnimation(0xBA0AE050, 0, -1); + setVisible(true); + playSound(0, calcHash("fxDoorOpen38")); + NextState(&AsScene1308JaggyDoor::stOpenDoorDone); +} + +void AsScene1308JaggyDoor::stOpenDoorDone() { + sendMessage(_parentScene, 0x2000, 0); + stopAnimation(); + setVisible(false); +} + +void AsScene1308JaggyDoor::stCloseDoor() { + startAnimation(0xBA0AE050, -1, -1); + _playBackwards = true; + setVisible(true); + playSound(0, calcHash("fxDoorClose38")); + NextState(&AsScene1308JaggyDoor::stCloseDoorDone); +} + +void AsScene1308JaggyDoor::stCloseDoorDone() { + sendMessage(_parentScene, 0x2001, 0); + stopAnimation(); +} + +AsScene1308KeyboardDoor::AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 0xA08A0851, 1100, 320, 240), _parentScene(parentScene) { + + playSound(0, 0x51456049); + SetMessageHandler(&AsScene1308KeyboardDoor::handleMessage); + NextState(&AsScene1308KeyboardDoor::stFallingKeys); +} + +uint32 AsScene1308KeyboardDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1308KeyboardDoor::stFallingKeys() { + startAnimation(0x6238B191, 0, -1); + _x = 580; + _y = 383; + NextState(&AsScene1308KeyboardDoor::stFallingKeysDone); +} + +void AsScene1308KeyboardDoor::stFallingKeysDone() { + sendMessage(_parentScene, 0x2004, 0); + stopAnimation(); + setVisible(false); +} + +AsScene1308LightWallSymbols::AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 0x80180A10, 100, 320, 240), _parentScene(parentScene) { + + setVisible(false); + stopAnimation(); + Entity::_priority = 1200; + SetMessageHandler(&AsScene1308LightWallSymbols::handleMessage); +} + +uint32 AsScene1308LightWallSymbols::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2002: + stFadeIn(); + break; + case 0x2003: + stFadeOut(); + break; + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1308LightWallSymbols::stFadeIn() { + startAnimation(0x80180A10, 0, -1); + setVisible(true); + _newStickFrameIndex = STICK_LAST_FRAME; +} + +void AsScene1308LightWallSymbols::stFadeOut() { + startAnimation(0x80180A10, -1, -1); + _playBackwards = true; + NextState(&AsScene1308LightWallSymbols::stFadeOutDone); +} + +void AsScene1308LightWallSymbols::stFadeOutDone() { + sendMessage(_parentScene, 0x2003, 0); + stopAnimation(); + setVisible(false); +} + +SsScene1308Number::SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index) + : StaticSprite(vm, fileHash, 100) { + + setVisible(false); + _x = _spriteResource.getPosition().x + index * 20; + updatePosition(); +} + +AsScene1308Mouse::AsScene1308Mouse(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100) { + + _x = 286; + _y = 429; + createSurface1(0xA282C472, 100); + startAnimation(0xA282C472, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1308Mouse::handleMessage); +} + +uint32 AsScene1308Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x66382026) + playSound(0, 0x0CD84468); + else if (param.asInteger() == 0x6E28061C) + playSound(0, 0x78C8402C); + else if (param.asInteger() == 0x462F0410) + playSound(0, 0x60984E28); + break; + } + return messageResult; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1300_sprites.h b/engines/neverhood/modules/module1300_sprites.h new file mode 100644 index 0000000000..31775559e2 --- /dev/null +++ b/engines/neverhood/modules/module1300_sprites.h @@ -0,0 +1,162 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE1300_SPRITES_H +#define NEVERHOOD_MODULES_MODULE1300_SPRITES_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/smackerplayer.h" + +namespace Neverhood { + +class AsScene1302Bridge : public AnimatedSprite { +public: + AsScene1302Bridge(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stLowerBridge(); + void stRaiseBridge(); + void cbLowerBridgeEvent(); +}; + +class SsScene1302Fence : public StaticSprite { +public: + SsScene1302Fence(NeverhoodEngine *vm); +protected: + int16 _firstY; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suMoveDown(); + void suMoveUp(); +}; + +class AsScene1303Balloon : public AnimatedSprite { +public: + AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmBalloonPopped(int messageNum, const MessageParam ¶m, Entity *sender); + void stPopBalloon(); +}; + +class AsScene1304Needle : public AnimatedSprite { +public: + AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene1306Elevator : public AnimatedSprite { +public: + AsScene1306Elevator(NeverhoodEngine *vm, Scene *parentScene, AnimatedSprite *asElevatorDoor); +protected: + Scene *_parentScene; + AnimatedSprite *_asElevatorDoor; + bool _isUp; + bool _isDown; + int _countdown; + void update(); + void upGoingDown(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stGoingUp(); + void cbGoingUpEvent(); + void stGoingDown(); + void cbGoingDownEvent(); +}; + +class AsScene1307Key : public AnimatedSprite { +public: + AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects); +protected: + Scene *_parentScene; + NPointArray *_pointList; + uint _pointIndex; + int _frameIndex; + uint _keyIndex; + NRect *_clipRects; + bool _isClickable; + int16 _prevX, _prevY; + int16 _deltaX, _deltaY; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suRemoveKey(); + void suInsertKey(); + void suMoveKey(); + void stRemoveKey(); + void stInsertKey(); + void stMoveKey(); + void stUnlock(); + void stInsert(); +}; + +class AsScene1308JaggyDoor : public AnimatedSprite { +public: + AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stOpenDoor(); + void stOpenDoorDone(); + void stCloseDoor(); + void stCloseDoorDone(); +}; + +class AsScene1308KeyboardDoor : public AnimatedSprite { +public: + AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stFallingKeys(); + void stFallingKeysDone(); +}; + +class AsScene1308LightWallSymbols : public AnimatedSprite { +public: + AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stFadeIn(); + void stFadeOut(); + void stFadeOutDone(); +}; + +class SsScene1308Number : public StaticSprite { +public: + SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index); +}; + +class AsScene1308Mouse : public AnimatedSprite { +public: + AsScene1308Mouse(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1300_SPRITES_H */ diff --git a/engines/neverhood/modules/module1400.cpp b/engines/neverhood/modules/module1400.cpp index 7244d3c399..655aa15ad1 100644 --- a/engines/neverhood/modules/module1400.cpp +++ b/engines/neverhood/modules/module1400.cpp @@ -20,12 +20,14 @@ * */ -#include "neverhood/modules/module1400.h" +#include "neverhood/diskplayerscene.h" +#include "neverhood/gamemodule.h" #include "neverhood/modules/module1000.h" +#include "neverhood/modules/module1200.h" +#include "neverhood/modules/module1400.h" +#include "neverhood/modules/module1400_sprites.h" #include "neverhood/modules/module2100_sprites.h" #include "neverhood/modules/module2200_sprites.h" -#include "neverhood/diskplayerscene.h" -#include "neverhood/gamemodule.h" namespace Neverhood { @@ -135,497 +137,6 @@ void Module1400::updateScene() { } } -// Scene1401 - -AsScene1401Pipe::AsScene1401Pipe(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100), _countdown1(0), _countdown2(0) { - - createSurface(900, 152, 147); - _x = 454; - _y = 217; - startAnimation(0x4C210500, 0, -1); - SetUpdateHandler(&AsScene1401Pipe::update); - SetMessageHandler(&AsScene1401Pipe::handleMessage); -} - -AsScene1401Pipe::~AsScene1401Pipe() { - _vm->_soundMan->deleteSoundGroup(0x01104C08); -} - -void AsScene1401Pipe::update() { - AnimatedSprite::update(); - if (_countdown1 != 0 && (--_countdown1 == 0)) - stDoneSucking(); - if (_countdown2 != 0 && (--_countdown2 == 0)) { - _vm->_soundMan->addSound(0x01104C08, 0x4A116437); - _vm->_soundMan->playSoundLooping(0x4A116437); - } -} - -void AsScene1401Pipe::upSuckInProjector() { - AnimatedSprite::update(); - if (_countdown1 != 0) - _countdown1--; -} - -uint32 AsScene1401Pipe::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x0A8A1490) - playSound(1, 0x6AB6666F); - break; - case 0x2000: - _countdown1 = 70; - _countdown2 = 8; - stStartSucking(); - break; - case 0x483A: - stSuckInProjector(); - break; - } - return messageResult; -} - -uint32 AsScene1401Pipe::hmSuckInProjector(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - if (_countdown1 != 0) - stStartSucking(); - else - stDoneSucking(); - SetMessageHandler(&AsScene1401Pipe::handleMessage); - SetUpdateHandler(&AsScene1401Pipe::update); - break; - } - return messageResult; -} - -void AsScene1401Pipe::stStartSucking() { - startAnimation(0x4C240100, 0, -1); - playSound(0, 0x4A30063F); -} - -void AsScene1401Pipe::stDoneSucking() { - _vm->_soundMan->deleteSound(0x4A116437); - playSound(0, 0x4A120435); - startAnimation(0x4C210500, 0, -1); -} - -void AsScene1401Pipe::stSuckInProjector() { - startAnimation(0x6C210810, 0, -1); - SetUpdateHandler(&AsScene1401Pipe::upSuckInProjector); - SetMessageHandler(&AsScene1401Pipe::hmSuckInProjector); -} - -AsScene1401Mouse::AsScene1401Mouse(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100) { - - createSurface(100, 71, 41); - _x = 478; - _y = 433; - startAnimation(0xA282C472, 0, -1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1401Mouse::handleMessage); -} - -uint32 AsScene1401Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x100D: - if (param.asInteger() == 0x66382026) - playSound(0, 0x0CD84468); - else if (param.asInteger() == 0x6E28061C) - playSound(0, 0x78C8402C); - else if (param.asInteger() == 0x462F0410) - playSound(0, 0x60984E28); - break; - case 0x4839: - stSuckedIn(); - break; - } - return messageResult; -} - -void AsScene1401Mouse::suSuckedIn() { - AnimatedSprite::updateDeltaXY(); - if (_collisionBounds.y1 <= 150) { - playSound(0, 0x0E32247F); - stopAnimation(); - setVisible(false); - SetMessageHandler(NULL); - SetSpriteUpdate(NULL); - } -} - -void AsScene1401Mouse::stSuckedIn() { - startAnimation(0x34880040, 0, -1); - SetSpriteUpdate(&AsScene1401Mouse::suSuckedIn); -} - -AsScene1401Cheese::AsScene1401Cheese(NeverhoodEngine *vm) - : AnimatedSprite(vm, 1100) { - - createSurface(200, 152, 147); - _x = 427; - _y = 433; - startAnimation(0x461A1490, 0, -1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1401Cheese::handleMessage); -} - -uint32 AsScene1401Cheese::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x4839: - stSuckedIn(); - break; - } - return messageResult; -} - -void AsScene1401Cheese::suSuckedIn() { - AnimatedSprite::updateDeltaXY(); - if (_collisionBounds.y1 <= 150) { - playSound(0, 0x18020439); - stopAnimation(); - setVisible(false); - SetMessageHandler(NULL); - SetSpriteUpdate(NULL); - } -} - -void AsScene1401Cheese::stSuckedIn() { - startAnimation(0x103B8020, 0, -1); - SetSpriteUpdate(&AsScene1401Cheese::suSuckedIn); -} - -AsScene1401BackDoor::AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen) - : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown(0), _isOpen(isOpen) { - - _x = 320; - _y = 240; - createSurface1(0x04551900, 100); - if (isOpen) { - startAnimation(0x04551900, -1, -1); - _countdown = 48; - } else { - stopAnimation(); - setVisible(false); - } - _newStickFrameIndex = STICK_LAST_FRAME; - SetUpdateHandler(&AsScene1401BackDoor::update); - SetMessageHandler(&AsScene1401BackDoor::handleMessage); -} - -void AsScene1401BackDoor::update() { - if (_countdown != 0 && (--_countdown == 0)) - stCloseDoor(); - AnimatedSprite::update(); -} - - -uint32 AsScene1401BackDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2001: - if (_isOpen) - _countdown = 168; - messageResult = _isOpen ? 1 : 0; - break; - case 0x3002: - gotoNextState(); - break; - case 0x4808: - _countdown = 168; - if (!_isOpen) - stOpenDoor(); - break; - } - return messageResult; -} - -void AsScene1401BackDoor::stOpenDoor() { - _isOpen = true; - setVisible(true); - startAnimation(0x04551900, 0, -1); - _newStickFrameIndex = STICK_LAST_FRAME; - playSound(0, calcHash("fxDoorOpen24")); -} - -void AsScene1401BackDoor::stCloseDoor() { - _isOpen = false; - setVisible(true); - startAnimation(0x04551900, -1, -1); - playSound(0, calcHash("fxDoorClose24")); - _playBackwards = true; - NextState(&AsScene1401BackDoor::stCloseDoorDone); -} - -void AsScene1401BackDoor::stCloseDoorDone() { - stopAnimation(); - setVisible(false); -} - -static const AsCommonProjectorItem kAsCommonProjectorItems[] = { - {{154, 453}, 4, 2, 0, 0, 1}, - {{104, 391}, 4, -1, -1, 1, 1}, - {{ 22, 447}, 6, -1, -1, 1, 1}, - {{112, 406}, 2, -1, -1, 1, 0}, - {{262, 433}, 1, 1, 0, 0, 0} -}; - -AsCommonProjector::AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _klaymen(klaymen), _asPipe(asPipe) { - - _asProjectorItem = &kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)]; - createSurface(990, 101, 182); - startAnimation(0x10E3042B, 0, -1); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsCommonProjector::handleMessage); - _x = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; - _lockedInSlot = true; - moveProjector(); - setDoDeltaX(1); - if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex) - stStayLockedInSlot(); - loadSound(2, 0xC8C2507C); -} - -AsCommonProjector::~AsCommonProjector() { - _vm->_soundMan->deleteSoundGroup(0x05331081); -} - -uint32 AsCommonProjector::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x4807: - setGlobalVar(V_PROJECTOR_SLOT, (_x - _asProjectorItem->point.x) / 108); - if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex) - stStartLockedInSlot(); - else - stIdle(); - break; - case 0x480B: - if (param.asInteger() != 1) { - if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount) - incGlobalVar(V_PROJECTOR_SLOT, 1); - } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0) - incGlobalVar(V_PROJECTOR_SLOT, -1); - stMoving(); - break; - case 0x480C: - // Check if the projector can be moved - if (param.asInteger() != 1) - messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0; - else - messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0; - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - case 0x4839: - stStartSuckedIn(); - break; - } - return messageResult; -} - -uint32 AsCommonProjector::hmLockedInSlot(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (param.asPoint().x - _x >= 17 && param.asPoint().x - _x <= 56 && - param.asPoint().y - _y >= -120 && param.asPoint().y - _y <= -82) { - sendMessage(_parentScene, 0x4826, 1); - } else - sendMessage(_parentScene, 0x4826, 0); - messageResult = 1; - break; - case 0x4807: - sendMessage(_parentScene, 0x4807, 0); - stStopProjecting(); - break; - case 0x480B: - if (param.asInteger() != 1) { - if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount) - incGlobalVar(V_PROJECTOR_SLOT, 1); - } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0) - incGlobalVar(V_PROJECTOR_SLOT, -1); - stTurnToFront(); - break; - case 0x480C: - // Check if the projector can be moved - if (param.asInteger() != 1) - messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0; - else - messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0; - break; - case 0x480F: - stStartProjecting(); - break; - case 0x482A: - sendMessage(_parentScene, 0x1022, 990); - break; - case 0x482B: - sendMessage(_parentScene, 0x1022, 1010); - break; - } - return messageResult; -} - -uint32 AsCommonProjector::hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsCommonProjector::suMoving() { - if (_x <= _klaymen->getX()) - _x = _klaymen->getX() - 100; - else - _x = _klaymen->getX() + 100; - moveProjector(); - if (_beforeMoveX == _x) { - if (getGlobalVar(V_PROJECTOR_SLOT) == 0 && _asProjectorItem->leftBorderLeaves != 0) { - sendMessage(_parentScene, 0x1019, 0); - incGlobalVar(V_PROJECTOR_LOCATION, -1); - setGlobalVar(V_PROJECTOR_SLOT, kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)].maxSlotCount); - } else if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->maxSlotCount && _asProjectorItem->rightBorderLeaves != 0) { - sendMessage(_parentScene, 0x1019, 1); - incGlobalVar(V_PROJECTOR_LOCATION, +1); - setGlobalVar(V_PROJECTOR_SLOT, 0); - } - } - Sprite::updateBounds(); -} - -void AsCommonProjector::moveProjector() { - - bool nowLockedInSlot = false; - - _y = _asProjectorItem->point.y; - - if (_asProjectorItem->index1 != -1) { - int16 elX = _asProjectorItem->index1 * 108 + _asProjectorItem->point.x; - if (elX - 20 < _x && elX + 20 > _x) { - nowLockedInSlot = true; - _y = _asProjectorItem->point.y + 10; - } - } - - if (_asProjectorItem->lockSlotIndex != -1) { - int16 elX = _asProjectorItem->lockSlotIndex * 108 + _asProjectorItem->point.x; - if (elX - 20 < _x && elX + 20 > _x) { - nowLockedInSlot = true; - _y = _asProjectorItem->point.y + 10; - } - } - - if (_lockedInSlot && !nowLockedInSlot) - _lockedInSlot = false; - else if (!_lockedInSlot && nowLockedInSlot) { - playSound(1, 0x5440E474); - _lockedInSlot = true; - } - -} - -void AsCommonProjector::stSuckedIn() { - AnimatedSprite::updateDeltaXY(); - if (_collisionBounds.y1 <= 150) { - sendMessage(_asPipe, 0x483A, 0); - stopAnimation(); - setVisible(false); - SetMessageHandler(&Sprite::handleMessage); - SetSpriteUpdate(NULL); - } -} - -void AsCommonProjector::stIdle() { - startAnimation(0x10E3042B, 0, -1); - SetMessageHandler(&AsCommonProjector::handleMessage); - SetSpriteUpdate(NULL); -} - -void AsCommonProjector::stMoving() { - _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; - startAnimation(0x14A10137, 0, -1); - playSound(1, 0xEC008474); - SetMessageHandler(&AsCommonProjector::handleMessage); - SetSpriteUpdate(&AsCommonProjector::suMoving); -} - -void AsCommonProjector::stStartLockedInSlot() { - startAnimation(0x80C32213, 0, -1); - SetMessageHandler(&AsCommonProjector::hmAnimation); - SetSpriteUpdate(NULL); - NextState(&AsCommonProjector::stStayLockedInSlot); -} - -void AsCommonProjector::stStayLockedInSlot() { - startAnimation(0xD23B207F, 0, -1); - SetMessageHandler(&AsCommonProjector::hmLockedInSlot); - SetSpriteUpdate(NULL); -} - -void AsCommonProjector::stStartProjecting() { - startAnimation(0x50A80517, 0, -1); - setGlobalVar(V_PROJECTOR_ACTIVE, 1); - playSound(0, 0xCC4A8456); - _vm->_soundMan->addSound(0x05331081, 0xCE428854); - _vm->_soundMan->playSoundLooping(0xCE428854); - SetMessageHandler(&AsCommonProjector::hmAnimation); - SetSpriteUpdate(NULL); - NextState(&AsCommonProjector::stLockedInSlot); -} - -void AsCommonProjector::stLockedInSlot() { - sendMessage(_parentScene, 0x480F, 0); - startAnimation(0xD833207F, 0, -1); - SetMessageHandler(&AsCommonProjector::hmLockedInSlot); - SetSpriteUpdate(NULL); -} - -void AsCommonProjector::stStopProjecting() { - startAnimation(0x50A94417, 0, -1); - setGlobalVar(V_PROJECTOR_ACTIVE, 0); - playSound(0, 0xCC4A8456); - _vm->_soundMan->deleteSound(0xCE428854); - SetMessageHandler(&AsCommonProjector::hmAnimation); - SetSpriteUpdate(NULL); - NextState(&AsCommonProjector::stStayLockedInSlot); -} - -void AsCommonProjector::stTurnToFront() { - _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; - startAnimation(0x22CB4A33, 0, -1); - SetMessageHandler(&AsCommonProjector::hmAnimation); - SetSpriteUpdate(&AsCommonProjector::suMoving); - NextState(&AsCommonProjector::stMoving); -} - -void AsCommonProjector::stStartSuckedIn() { - setGlobalVar(V_PROJECTOR_LOCATION, 4); - setGlobalVar(V_PROJECTOR_SLOT, 0); - startAnimation(0x708D4712, 0, -1); - playSound(2); - SetMessageHandler(&Sprite::handleMessage); - SetSpriteUpdate(&AsCommonProjector::stSuckedIn); -} - Scene1401::Scene1401(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _projectorBorderFlag(false), _ssFloorButton(NULL), _asProjector(NULL), _asPipe(NULL), _asMouse(NULL), _asCheese(NULL), _asBackDoor(NULL), @@ -768,77 +279,6 @@ uint32 Scene1401::handleMessage(int messageNum, const MessageParam ¶m, Entit return 0; } -// Scene1402 - -SsScene1402BridgePart::SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority) - : StaticSprite(vm, fileHash, surfacePriority) { - - SetFilterY(&Sprite::defFilterY); - SetUpdateHandler(&StaticSprite::updatePosition); -} - -AsScene1402PuzzleBox::AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status) - : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - - createSurface(900, 347, 230); - - SetFilterY(&Sprite::defFilterY); - SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1402PuzzleBox::handleMessage); - _x = 279; - _y = 270; - if (status == 2) { - // Puzzle box after the puzzle was solved - startAnimation(0x20060259, 0, -1); - playSound(0, 0x419014AC); - loadSound(1, 0x61901C29); - NextState(&AsScene1402PuzzleBox::stMoveDownSolvedDone); - } else if (status == 1) { - // Puzzle box appears - startAnimation(0x210A0213, 0, -1); - playSound(0, 0x41809C6C); - NextState(&AsScene1402PuzzleBox::stMoveUpDone); - } else { - // Puzzle box is here - startAnimation(0x20060259, -1, -1); - loadSound(1, 0x61901C29); - _newStickFrameIndex = STICK_LAST_FRAME; - } -} - -uint32 AsScene1402PuzzleBox::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x2002: - playSound(1); - startAnimation(0x20060259, -1, -1); - _playBackwards = true; - NextState(&AsScene1402PuzzleBox::stMoveDownDone); - break; - case 0x3002: - gotoNextState(); - break; - } - return messageResult; -} - -void AsScene1402PuzzleBox::stMoveUpDone() { - sendMessage(_parentScene, 0x2000, 0); - stopAnimation(); - setVisible(false); -} - -void AsScene1402PuzzleBox::stMoveDownDone() { - sendMessage(_parentScene, 0x2001, 0); - stopAnimation(); - setVisible(false); -} - -void AsScene1402PuzzleBox::stMoveDownSolvedDone() { - sendMessage(_parentScene, 0x2003, 0); - stopAnimation(); -} - Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _isShaking(false), _asPuzzleBox(NULL), _asProjector(NULL) { @@ -988,237 +428,6 @@ void Scene1402::stopShaking() { _isShaking = false; } -// Scene1407 - -static const int16 kScene1407MouseFloorY[] = { - 106, 150, 191, 230, 267, 308, 350, 395 -}; - -static const struct { - int16 x; - int16 floorIndex; - int16 sectionIndex; - int16 nextHoleIndex; -} kScene1407MouseHoles[] = { - {125, 0, 0, 7}, - {452, 7, 21, 0}, - {337, 4, 11, 4}, - {286, 6, 17, 6}, - {348, 6, 17, 39}, - {536, 6, 18, 42}, - {111, 1, 3, 18}, - {203, 1, 3, 38}, - {270, 1, 3, 9}, - {197, 5, 14, 3}, - {252, 5, 14, 35}, - {297, 5, 14, 7}, - {359, 5, 14, 8}, - {422, 4, 12, 26}, - {467, 4, 12, 2}, - {539, 4, 12, 40}, - {111, 5, 13, 17}, - {211, 0, 1, 20}, - {258, 0, 1, 11}, - {322, 0, 1, 16}, - { 99, 6, 16, 31}, - {142, 6, 16, 27}, - {194, 6, 16, 12}, - {205, 2, 6, 45}, - {264, 2, 6, 10}, - { 98, 4, 10, 2}, - {152, 4, 10, 37}, - {199, 4, 10, 13}, - {258, 4, 10, 16}, - {100, 7, 19, 43}, - {168, 7, 19, 23}, - {123, 3, 8, 14}, - {181, 3, 8, 39}, - {230, 3, 8, 28}, - {292, 3, 8, 22}, - {358, 3, 8, 36}, - {505, 3, 9, 44}, - {400, 2, 7, 34}, - {454, 2, 7, 32}, - {532, 2, 7, 46}, - {484, 5, 15, 25}, - {529, 5, 15, 30}, - {251, 7, 20, 48}, - {303, 7, 20, 21}, - {360, 7, 20, 33}, - {503, 0, 2, 5}, - {459, 1, 4, 19}, - {530, 1, 4, 42}, - {111, 2, 5, 47}, - {442, 6, 18, 1} -}; - -static const struct { - int16 x1, x2; - int16 goodHoleIndex; -} kScene1407MouseSections[] = { - {100, 149, 0}, - {182, 351, 17}, - {430, 524, 45}, - { 89, 293, 7}, - {407, 555, 47}, - { 89, 132, 48}, - {178, 303, 23}, - {367, 551, 38}, - {105, 398, 31}, - {480, 537, 36}, - { 84, 275, 27}, - {318, 359, 2}, - {402, 560, 15}, - { 91, 132, 16}, - {179, 400, 10}, - {461, 552, 41}, - { 86, 218, 21}, - {267, 376, 4}, - {420, 560, 49}, - { 77, 188, 30}, - {237, 394, 44}, - {438, 515, 5} -}; - -AsScene1407Mouse::AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _currSectionIndex(0) { - - createSurface(100, 117, 45); - _x = 108; - _y = 106; - stIdleLookAtGoodHole(); - SetUpdateHandler(&AnimatedSprite::update); -} - -void AsScene1407Mouse::suWalkTo() { - int16 xdelta = _walkDestX - _x; - if (xdelta > _deltaX) - xdelta = _deltaX; - else if (xdelta < -_deltaX) - xdelta = -_deltaX; - _deltaX = 0; - if (_walkDestX == _x) - sendMessage(this, 0x1019, 0); - else { - _x += xdelta; - updateBounds(); - } -} - -void AsScene1407Mouse::upGoThroughHole() { - if (_countdown != 0 && (--_countdown == 0)) { - SetUpdateHandler(&AnimatedSprite::update); - gotoNextState(); - } - AnimatedSprite::update(); -} - -uint32 AsScene1407Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x0001: - { - int16 mouseX = param.asPoint().x; - int16 mouseY = param.asPoint().y; - int holeIndex; - for (holeIndex = 0; holeIndex < 50; holeIndex++) { - int16 holeX = kScene1407MouseHoles[holeIndex].x; - int16 holeY = kScene1407MouseFloorY[kScene1407MouseHoles[holeIndex].floorIndex]; - if (mouseX >= holeX - 14 && mouseX <= holeX + 14 && mouseY >= holeY - 36 && mouseY <= holeY) - break; - } - if (holeIndex < 50 && kScene1407MouseHoles[holeIndex].sectionIndex == _currSectionIndex) { - _nextHoleIndex = kScene1407MouseHoles[holeIndex].nextHoleIndex; - _walkDestX = kScene1407MouseHoles[holeIndex].x; - stWalkToHole(); - } else { - if (mouseX < kScene1407MouseSections[_currSectionIndex].x1) - _walkDestX = kScene1407MouseSections[_currSectionIndex].x1; - else if (mouseX > kScene1407MouseSections[_currSectionIndex].x2) - _walkDestX = kScene1407MouseSections[_currSectionIndex].x2; - else - _walkDestX = mouseX; - stWalkToDest(); - } - } - break; - case 0x1019: - gotoNextState(); - break; - case 0x2001: - { - // Reset the position - // Find the nearest hole and go through it, and exit at the first hole - int16 distance = 640; - int matchIndex = 50; - for (int index = 0; index < 50; index++) - if (kScene1407MouseHoles[index].sectionIndex == _currSectionIndex && - ABS(kScene1407MouseHoles[index].x - _x) < distance) { - matchIndex = index; - distance = ABS(kScene1407MouseHoles[index].x - _x); - } - if (matchIndex < 50) { - _nextHoleIndex = 0; - _walkDestX = kScene1407MouseHoles[matchIndex].x; - stWalkToHole(); - } - } - break; - } - return messageResult; -} - -void AsScene1407Mouse::stIdleLookAtGoodHole() { - setDoDeltaX(kScene1407MouseHoles[kScene1407MouseSections[_currSectionIndex].goodHoleIndex].x < _x ? 1 : 0); - startAnimation(0x72215194, 0, -1); - SetMessageHandler(&AsScene1407Mouse::handleMessage); - SetSpriteUpdate(NULL); -} - -void AsScene1407Mouse::stWalkToDest() { - if (_walkDestX != _x) { - setDoDeltaX(_walkDestX < _x ? 1 : 0); - startAnimation(0x22291510, 0, -1); - SetMessageHandler(&AsScene1407Mouse::handleMessage); - SetSpriteUpdate(&AsScene1407Mouse::suWalkTo); - NextState(&AsScene1407Mouse::stIdleLookAtGoodHole); - } -} - -void AsScene1407Mouse::stWalkToHole() { - setDoDeltaX(_walkDestX < _x ? 1 : 0); - startAnimation(0x22291510, 0, -1); - SetMessageHandler(&AsScene1407Mouse::handleMessage); - SetSpriteUpdate(&AsScene1407Mouse::suWalkTo); - NextState(&AsScene1407Mouse::stGoThroughHole); -} - -void AsScene1407Mouse::stGoThroughHole() { - startAnimation(0x72215194, 0, -1); - setVisible(false); - _countdown = 12; - SetUpdateHandler(&AsScene1407Mouse::upGoThroughHole); - SetMessageHandler(NULL); - SetSpriteUpdate(NULL); - NextState(&AsScene1407Mouse::stArriveAtHole); -} - -void AsScene1407Mouse::stArriveAtHole() { - _currSectionIndex = kScene1407MouseHoles[_nextHoleIndex].sectionIndex; - _x = kScene1407MouseHoles[_nextHoleIndex].x; - _y = kScene1407MouseFloorY[kScene1407MouseHoles[_nextHoleIndex].floorIndex]; - if (_nextHoleIndex == 1) { - sendMessage(_parentScene, 0x2000, 0); - _walkDestX = 512; - stWalkToDest(); - setVisible(true); - } else { - _walkDestX = _x + 14; - stWalkToDest(); - setVisible(true); - } -} - Scene1407::Scene1407(NeverhoodEngine *vm, Module *parentModule) : Scene(vm, parentModule), _puzzleSolvedCountdown(0), _resetButtonCountdown(0) { @@ -1275,8 +484,6 @@ uint32 Scene1407::handleMessage(int messageNum, const MessageParam ¶m, Entit return 0; } -// Scene1403 - Scene1403::Scene1403(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _asProjector(NULL), _isProjecting(false) { @@ -1379,8 +586,6 @@ uint32 Scene1403::handleMessage(int messageNum, const MessageParam ¶m, Entit return 0; } -// Scene1404 - Scene1404::Scene1404(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _asProjector(NULL), _asKey(NULL) { @@ -1480,77 +685,6 @@ uint32 Scene1404::handleMessage(int messageNum, const MessageParam ¶m, Entit return 0; } -// Scene1405 - -static const NPoint kAsScene1405TileItemPositions[] = { - {100, 80}, {162, 78}, {222, 76}, {292, 76}, - {356, 82}, {422, 84}, {488, 86}, {550, 90}, - {102, 134}, {164, 132}, {224, 136}, {294, 136}, - {360, 136}, {422, 138}, {484, 144}, {548, 146}, - { 98, 196}, {160, 200}, {228, 200}, {294, 202}, - {360, 198}, {424, 200}, {482, 202}, {548, 206}, - { 98, 260}, {160, 264}, {226, 260}, {296, 262}, - {358, 260}, {424, 262}, {486, 264}, {550, 266}, - { 94, 322}, {160, 316}, {226, 316}, {296, 320}, - {358, 322}, {422, 324}, {488, 322}, {550, 322}, - { 98, 380}, {160, 376}, {226, 376}, {294, 378}, - {356, 380}, {420, 380}, {490, 378}, {552, 376} -}; - -AsScene1405Tile::AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex) - : AnimatedSprite(vm, 1100), _parentScene(parentScene), _tileIndex(tileIndex), _countdown(0), _isShowing(false) { - - loadSound(0, 0x05308101); - setSoundPan(0, (tileIndex % 8 * 4 + 4) * 25 / 8); - _x = kAsScene1405TileItemPositions[_tileIndex].x; - _y = kAsScene1405TileItemPositions[_tileIndex].y; - createSurface1(0x844B805C, 1100); - setVisible(false); - if (getSubVar(VA_IS_TILE_MATCH, _tileIndex)) - _countdown = _vm->_rnd->getRandomNumber(36 - 1) + 1; - startAnimation(0x844B805C, getSubVar(VA_TILE_SYMBOLS, _tileIndex), -1); - _newStickFrameIndex = (int16)getSubVar(VA_TILE_SYMBOLS, _tileIndex); - SetUpdateHandler(&AsScene1405Tile::update); - SetMessageHandler(&AsScene1405Tile::handleMessage); -} - -void AsScene1405Tile::update() { - updateAnim(); - updatePosition(); - if (_countdown != 0 && (--_countdown == 0)) - show(); -} - -uint32 AsScene1405Tile::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); - switch (messageNum) { - case 0x1011: - if (getSubVar(VA_IS_TILE_MATCH, _tileIndex) == 0 && _parentScene->getCountdown() == 0) { - show(); - sendMessage(_parentScene, 0x2000, _tileIndex); - } - messageResult = 1; - break; - } - return messageResult; -} - -void AsScene1405Tile::show() { - if (!_isShowing) { - _isShowing = true; - playSound(0); - setVisible(true); - } -} - -void AsScene1405Tile::hide() { - if (_isShowing) { - _isShowing = false; - playSound(0); - setVisible(false); - } -} - Scene1405::Scene1405(NeverhoodEngine *vm, Module *parentModule) : Scene(vm, parentModule), _selectFirstTile(true), _tilesLeft(48), _countdown(0) { diff --git a/engines/neverhood/modules/module1400.h b/engines/neverhood/modules/module1400.h index 9a592c2952..53ad7125ab 100644 --- a/engines/neverhood/modules/module1400.h +++ b/engines/neverhood/modules/module1400.h @@ -26,7 +26,6 @@ #include "neverhood/neverhood.h" #include "neverhood/module.h" #include "neverhood/scene.h" -#include "neverhood/modules/module1200.h" namespace Neverhood { @@ -40,92 +39,9 @@ protected: void updateScene(); }; -// Scene1401 - -class AsScene1401Pipe : public AnimatedSprite { -public: - AsScene1401Pipe(NeverhoodEngine *vm); - virtual ~AsScene1401Pipe(); -protected: - int _countdown1; - int _countdown2; - void update(); - void upSuckInProjector(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmSuckInProjector(int messageNum, const MessageParam ¶m, Entity *sender); - void stStartSucking(); - void stDoneSucking(); - void stSuckInProjector(); -}; - -class AsScene1401Mouse : public AnimatedSprite { -public: - AsScene1401Mouse(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suSuckedIn(); - void stSuckedIn(); -}; - -class AsScene1401Cheese : public AnimatedSprite { -public: - AsScene1401Cheese(NeverhoodEngine *vm); -protected: - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suSuckedIn(); - void stSuckedIn(); -}; - -class AsScene1401BackDoor : public AnimatedSprite { -public: - AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen); -protected: - Sprite *_klaymen; - int _countdown; - bool _isOpen; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stOpenDoor(); - void stCloseDoor(); - void stCloseDoorDone(); -}; - -struct AsCommonProjectorItem { - NPoint point; - int8 maxSlotCount; - int8 lockSlotIndex; - int8 index1; - int8 leftBorderLeaves; - int8 rightBorderLeaves; -}; - -class AsCommonProjector : public AnimatedSprite { -public: - AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe); - virtual ~AsCommonProjector(); -protected: - Scene *_parentScene; - Sprite *_klaymen; - Sprite *_asPipe; - const AsCommonProjectorItem *_asProjectorItem; - int16 _beforeMoveX; - bool _lockedInSlot; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmLockedInSlot(int messageNum, const MessageParam ¶m, Entity *sender); - uint32 hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender); - void suMoving(); - void moveProjector(); - void stSuckedIn(); - void stIdle(); - void stMoving(); - void stStartLockedInSlot(); - void stStayLockedInSlot(); - void stStartProjecting(); - void stLockedInSlot(); - void stStopProjecting(); - void stTurnToFront(); - void stStartSuckedIn(); -}; +class AsCommonProjector; +class AsScene1201Tape; +class AsScene1405Tile; class Scene1401 : public Scene { public: @@ -146,24 +62,6 @@ protected: uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; -// Scene1402 - -class SsScene1402BridgePart : public StaticSprite { -public: - SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority); -}; - -class AsScene1402PuzzleBox : public AnimatedSprite { -public: - AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status); -protected: - Scene *_parentScene; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void stMoveUpDone(); - void stMoveDownDone(); - void stMoveDownSolvedDone(); -}; - class Scene1402 : public Scene { public: Scene1402(NeverhoodEngine *vm, Module *parentModule, int which); @@ -180,27 +78,6 @@ protected: void stopShaking(); }; -// Scene1407 - -class AsScene1407Mouse : public AnimatedSprite { -public: - AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene); -protected: - Scene *_parentScene; - int16 _walkDestX; - int16 _currSectionIndex; - int16 _nextHoleIndex; - int _countdown; - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void suWalkTo(); - void upGoThroughHole(); - void stIdleLookAtGoodHole(); - void stWalkToDest(); - void stWalkToHole(); - void stGoThroughHole(); - void stArriveAtHole(); -}; - class Scene1407 : public Scene { public: Scene1407(NeverhoodEngine *vm, Module *parentModule); @@ -213,8 +90,6 @@ protected: uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; -// Scene1403 - class Scene1403 : public Scene { public: Scene1403(NeverhoodEngine *vm, Module *parentModule, int which); @@ -229,8 +104,6 @@ protected: uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; -// Scene1404 - class Scene1404 : public Scene { public: Scene1404(NeverhoodEngine *vm, Module *parentModule, int which); @@ -243,24 +116,6 @@ protected: uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; -// Scene1405 - -class Scene1405; - -class AsScene1405Tile : public AnimatedSprite { -public: - AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex); - void show(); - void hide(); -protected: - Scene1405 *_parentScene; - bool _isShowing; - uint32 _tileIndex; - int _countdown; - void update(); - uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); -}; - class Scene1405 : public Scene { public: Scene1405(NeverhoodEngine *vm, Module *parentModule); diff --git a/engines/neverhood/modules/module1400_sprites.cpp b/engines/neverhood/modules/module1400_sprites.cpp new file mode 100644 index 0000000000..aba9bc8c28 --- /dev/null +++ b/engines/neverhood/modules/module1400_sprites.cpp @@ -0,0 +1,885 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "neverhood/modules/module1400_sprites.h" +#include "neverhood/modules/module1400.h" +#include "neverhood/gamemodule.h" + +namespace Neverhood { + +AsScene1401Pipe::AsScene1401Pipe(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100), _countdown1(0), _countdown2(0) { + + createSurface(900, 152, 147); + _x = 454; + _y = 217; + startAnimation(0x4C210500, 0, -1); + SetUpdateHandler(&AsScene1401Pipe::update); + SetMessageHandler(&AsScene1401Pipe::handleMessage); +} + +AsScene1401Pipe::~AsScene1401Pipe() { + _vm->_soundMan->deleteSoundGroup(0x01104C08); +} + +void AsScene1401Pipe::update() { + AnimatedSprite::update(); + if (_countdown1 != 0 && (--_countdown1 == 0)) + stDoneSucking(); + if (_countdown2 != 0 && (--_countdown2 == 0)) { + _vm->_soundMan->addSound(0x01104C08, 0x4A116437); + _vm->_soundMan->playSoundLooping(0x4A116437); + } +} + +void AsScene1401Pipe::upSuckInProjector() { + AnimatedSprite::update(); + if (_countdown1 != 0) + _countdown1--; +} + +uint32 AsScene1401Pipe::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x0A8A1490) + playSound(1, 0x6AB6666F); + break; + case 0x2000: + _countdown1 = 70; + _countdown2 = 8; + stStartSucking(); + break; + case 0x483A: + stSuckInProjector(); + break; + } + return messageResult; +} + +uint32 AsScene1401Pipe::hmSuckInProjector(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + if (_countdown1 != 0) + stStartSucking(); + else + stDoneSucking(); + SetMessageHandler(&AsScene1401Pipe::handleMessage); + SetUpdateHandler(&AsScene1401Pipe::update); + break; + } + return messageResult; +} + +void AsScene1401Pipe::stStartSucking() { + startAnimation(0x4C240100, 0, -1); + playSound(0, 0x4A30063F); +} + +void AsScene1401Pipe::stDoneSucking() { + _vm->_soundMan->deleteSound(0x4A116437); + playSound(0, 0x4A120435); + startAnimation(0x4C210500, 0, -1); +} + +void AsScene1401Pipe::stSuckInProjector() { + startAnimation(0x6C210810, 0, -1); + SetUpdateHandler(&AsScene1401Pipe::upSuckInProjector); + SetMessageHandler(&AsScene1401Pipe::hmSuckInProjector); +} + +AsScene1401Mouse::AsScene1401Mouse(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100) { + + createSurface(100, 71, 41); + _x = 478; + _y = 433; + startAnimation(0xA282C472, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1401Mouse::handleMessage); +} + +uint32 AsScene1401Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x66382026) + playSound(0, 0x0CD84468); + else if (param.asInteger() == 0x6E28061C) + playSound(0, 0x78C8402C); + else if (param.asInteger() == 0x462F0410) + playSound(0, 0x60984E28); + break; + case 0x4839: + stSuckedIn(); + break; + } + return messageResult; +} + +void AsScene1401Mouse::suSuckedIn() { + AnimatedSprite::updateDeltaXY(); + if (_collisionBounds.y1 <= 150) { + playSound(0, 0x0E32247F); + stopAnimation(); + setVisible(false); + SetMessageHandler(NULL); + SetSpriteUpdate(NULL); + } +} + +void AsScene1401Mouse::stSuckedIn() { + startAnimation(0x34880040, 0, -1); + SetSpriteUpdate(&AsScene1401Mouse::suSuckedIn); +} + +AsScene1401Cheese::AsScene1401Cheese(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100) { + + createSurface(200, 152, 147); + _x = 427; + _y = 433; + startAnimation(0x461A1490, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1401Cheese::handleMessage); +} + +uint32 AsScene1401Cheese::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4839: + stSuckedIn(); + break; + } + return messageResult; +} + +void AsScene1401Cheese::suSuckedIn() { + AnimatedSprite::updateDeltaXY(); + if (_collisionBounds.y1 <= 150) { + playSound(0, 0x18020439); + stopAnimation(); + setVisible(false); + SetMessageHandler(NULL); + SetSpriteUpdate(NULL); + } +} + +void AsScene1401Cheese::stSuckedIn() { + startAnimation(0x103B8020, 0, -1); + SetSpriteUpdate(&AsScene1401Cheese::suSuckedIn); +} + +AsScene1401BackDoor::AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen) + : AnimatedSprite(vm, 1100), _klaymen(klaymen), _countdown(0), _isOpen(isOpen) { + + _x = 320; + _y = 240; + createSurface1(0x04551900, 100); + if (isOpen) { + startAnimation(0x04551900, -1, -1); + _countdown = 48; + } else { + stopAnimation(); + setVisible(false); + } + _newStickFrameIndex = STICK_LAST_FRAME; + SetUpdateHandler(&AsScene1401BackDoor::update); + SetMessageHandler(&AsScene1401BackDoor::handleMessage); +} + +void AsScene1401BackDoor::update() { + if (_countdown != 0 && (--_countdown == 0)) + stCloseDoor(); + AnimatedSprite::update(); +} + + +uint32 AsScene1401BackDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2001: + if (_isOpen) + _countdown = 168; + messageResult = _isOpen ? 1 : 0; + break; + case 0x3002: + gotoNextState(); + break; + case 0x4808: + _countdown = 168; + if (!_isOpen) + stOpenDoor(); + break; + } + return messageResult; +} + +void AsScene1401BackDoor::stOpenDoor() { + _isOpen = true; + setVisible(true); + startAnimation(0x04551900, 0, -1); + _newStickFrameIndex = STICK_LAST_FRAME; + playSound(0, calcHash("fxDoorOpen24")); +} + +void AsScene1401BackDoor::stCloseDoor() { + _isOpen = false; + setVisible(true); + startAnimation(0x04551900, -1, -1); + playSound(0, calcHash("fxDoorClose24")); + _playBackwards = true; + NextState(&AsScene1401BackDoor::stCloseDoorDone); +} + +void AsScene1401BackDoor::stCloseDoorDone() { + stopAnimation(); + setVisible(false); +} + +static const AsCommonProjectorItem kAsCommonProjectorItems[] = { + {{154, 453}, 4, 2, 0, 0, 1}, + {{104, 391}, 4, -1, -1, 1, 1}, + {{ 22, 447}, 6, -1, -1, 1, 1}, + {{112, 406}, 2, -1, -1, 1, 0}, + {{262, 433}, 1, 1, 0, 0, 0} +}; + +AsCommonProjector::AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _klaymen(klaymen), _asPipe(asPipe) { + + _asProjectorItem = &kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)]; + createSurface(990, 101, 182); + startAnimation(0x10E3042B, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsCommonProjector::handleMessage); + _x = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; + _lockedInSlot = true; + moveProjector(); + setDoDeltaX(1); + if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex) + stStayLockedInSlot(); + loadSound(2, 0xC8C2507C); +} + +AsCommonProjector::~AsCommonProjector() { + _vm->_soundMan->deleteSoundGroup(0x05331081); +} + +uint32 AsCommonProjector::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x4807: + setGlobalVar(V_PROJECTOR_SLOT, (_x - _asProjectorItem->point.x) / 108); + if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->lockSlotIndex) + stStartLockedInSlot(); + else + stIdle(); + break; + case 0x480B: + if (param.asInteger() != 1) { + if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount) + incGlobalVar(V_PROJECTOR_SLOT, 1); + } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0) + incGlobalVar(V_PROJECTOR_SLOT, -1); + stMoving(); + break; + case 0x480C: + // Check if the projector can be moved + if (param.asInteger() != 1) + messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0; + else + messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0; + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + case 0x4839: + stStartSuckedIn(); + break; + } + return messageResult; +} + +uint32 AsCommonProjector::hmLockedInSlot(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (param.asPoint().x - _x >= 17 && param.asPoint().x - _x <= 56 && + param.asPoint().y - _y >= -120 && param.asPoint().y - _y <= -82) { + sendMessage(_parentScene, 0x4826, 1); + } else + sendMessage(_parentScene, 0x4826, 0); + messageResult = 1; + break; + case 0x4807: + sendMessage(_parentScene, 0x4807, 0); + stStopProjecting(); + break; + case 0x480B: + if (param.asInteger() != 1) { + if ((int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount) + incGlobalVar(V_PROJECTOR_SLOT, 1); + } else if (getGlobalVar(V_PROJECTOR_SLOT) > 0) + incGlobalVar(V_PROJECTOR_SLOT, -1); + stTurnToFront(); + break; + case 0x480C: + // Check if the projector can be moved + if (param.asInteger() != 1) + messageResult = (int8)getGlobalVar(V_PROJECTOR_SLOT) < _asProjectorItem->maxSlotCount ? 1 : 0; + else + messageResult = getGlobalVar(V_PROJECTOR_SLOT) > 0 ? 1 : 0; + break; + case 0x480F: + stStartProjecting(); + break; + case 0x482A: + sendMessage(_parentScene, 0x1022, 990); + break; + case 0x482B: + sendMessage(_parentScene, 0x1022, 1010); + break; + } + return messageResult; +} + +uint32 AsCommonProjector::hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsCommonProjector::suMoving() { + if (_x <= _klaymen->getX()) + _x = _klaymen->getX() - 100; + else + _x = _klaymen->getX() + 100; + moveProjector(); + if (_beforeMoveX == _x) { + if (getGlobalVar(V_PROJECTOR_SLOT) == 0 && _asProjectorItem->leftBorderLeaves != 0) { + sendMessage(_parentScene, 0x1019, 0); + incGlobalVar(V_PROJECTOR_LOCATION, -1); + setGlobalVar(V_PROJECTOR_SLOT, kAsCommonProjectorItems[getGlobalVar(V_PROJECTOR_LOCATION)].maxSlotCount); + } else if ((int8)getGlobalVar(V_PROJECTOR_SLOT) == _asProjectorItem->maxSlotCount && _asProjectorItem->rightBorderLeaves != 0) { + sendMessage(_parentScene, 0x1019, 1); + incGlobalVar(V_PROJECTOR_LOCATION, +1); + setGlobalVar(V_PROJECTOR_SLOT, 0); + } + } + Sprite::updateBounds(); +} + +void AsCommonProjector::moveProjector() { + + bool nowLockedInSlot = false; + + _y = _asProjectorItem->point.y; + + if (_asProjectorItem->index1 != -1) { + int16 elX = _asProjectorItem->index1 * 108 + _asProjectorItem->point.x; + if (elX - 20 < _x && elX + 20 > _x) { + nowLockedInSlot = true; + _y = _asProjectorItem->point.y + 10; + } + } + + if (_asProjectorItem->lockSlotIndex != -1) { + int16 elX = _asProjectorItem->lockSlotIndex * 108 + _asProjectorItem->point.x; + if (elX - 20 < _x && elX + 20 > _x) { + nowLockedInSlot = true; + _y = _asProjectorItem->point.y + 10; + } + } + + if (_lockedInSlot && !nowLockedInSlot) + _lockedInSlot = false; + else if (!_lockedInSlot && nowLockedInSlot) { + playSound(1, 0x5440E474); + _lockedInSlot = true; + } + +} + +void AsCommonProjector::stSuckedIn() { + AnimatedSprite::updateDeltaXY(); + if (_collisionBounds.y1 <= 150) { + sendMessage(_asPipe, 0x483A, 0); + stopAnimation(); + setVisible(false); + SetMessageHandler(&Sprite::handleMessage); + SetSpriteUpdate(NULL); + } +} + +void AsCommonProjector::stIdle() { + startAnimation(0x10E3042B, 0, -1); + SetMessageHandler(&AsCommonProjector::handleMessage); + SetSpriteUpdate(NULL); +} + +void AsCommonProjector::stMoving() { + _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; + startAnimation(0x14A10137, 0, -1); + playSound(1, 0xEC008474); + SetMessageHandler(&AsCommonProjector::handleMessage); + SetSpriteUpdate(&AsCommonProjector::suMoving); +} + +void AsCommonProjector::stStartLockedInSlot() { + startAnimation(0x80C32213, 0, -1); + SetMessageHandler(&AsCommonProjector::hmAnimation); + SetSpriteUpdate(NULL); + NextState(&AsCommonProjector::stStayLockedInSlot); +} + +void AsCommonProjector::stStayLockedInSlot() { + startAnimation(0xD23B207F, 0, -1); + SetMessageHandler(&AsCommonProjector::hmLockedInSlot); + SetSpriteUpdate(NULL); +} + +void AsCommonProjector::stStartProjecting() { + startAnimation(0x50A80517, 0, -1); + setGlobalVar(V_PROJECTOR_ACTIVE, 1); + playSound(0, 0xCC4A8456); + _vm->_soundMan->addSound(0x05331081, 0xCE428854); + _vm->_soundMan->playSoundLooping(0xCE428854); + SetMessageHandler(&AsCommonProjector::hmAnimation); + SetSpriteUpdate(NULL); + NextState(&AsCommonProjector::stLockedInSlot); +} + +void AsCommonProjector::stLockedInSlot() { + sendMessage(_parentScene, 0x480F, 0); + startAnimation(0xD833207F, 0, -1); + SetMessageHandler(&AsCommonProjector::hmLockedInSlot); + SetSpriteUpdate(NULL); +} + +void AsCommonProjector::stStopProjecting() { + startAnimation(0x50A94417, 0, -1); + setGlobalVar(V_PROJECTOR_ACTIVE, 0); + playSound(0, 0xCC4A8456); + _vm->_soundMan->deleteSound(0xCE428854); + SetMessageHandler(&AsCommonProjector::hmAnimation); + SetSpriteUpdate(NULL); + NextState(&AsCommonProjector::stStayLockedInSlot); +} + +void AsCommonProjector::stTurnToFront() { + _beforeMoveX = getGlobalVar(V_PROJECTOR_SLOT) * 108 + _asProjectorItem->point.x; + startAnimation(0x22CB4A33, 0, -1); + SetMessageHandler(&AsCommonProjector::hmAnimation); + SetSpriteUpdate(&AsCommonProjector::suMoving); + NextState(&AsCommonProjector::stMoving); +} + +void AsCommonProjector::stStartSuckedIn() { + setGlobalVar(V_PROJECTOR_LOCATION, 4); + setGlobalVar(V_PROJECTOR_SLOT, 0); + startAnimation(0x708D4712, 0, -1); + playSound(2); + SetMessageHandler(&Sprite::handleMessage); + SetSpriteUpdate(&AsCommonProjector::stSuckedIn); +} + +SsScene1402BridgePart::SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority) + : StaticSprite(vm, fileHash, surfacePriority) { + + SetFilterY(&Sprite::defFilterY); + SetUpdateHandler(&StaticSprite::updatePosition); +} + +AsScene1402PuzzleBox::AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status) + : AnimatedSprite(vm, 1100), _parentScene(parentScene) { + + createSurface(900, 347, 230); + + SetFilterY(&Sprite::defFilterY); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1402PuzzleBox::handleMessage); + _x = 279; + _y = 270; + if (status == 2) { + // Puzzle box after the puzzle was solved + startAnimation(0x20060259, 0, -1); + playSound(0, 0x419014AC); + loadSound(1, 0x61901C29); + NextState(&AsScene1402PuzzleBox::stMoveDownSolvedDone); + } else if (status == 1) { + // Puzzle box appears + startAnimation(0x210A0213, 0, -1); + playSound(0, 0x41809C6C); + NextState(&AsScene1402PuzzleBox::stMoveUpDone); + } else { + // Puzzle box is here + startAnimation(0x20060259, -1, -1); + loadSound(1, 0x61901C29); + _newStickFrameIndex = STICK_LAST_FRAME; + } +} + +uint32 AsScene1402PuzzleBox::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2002: + playSound(1); + startAnimation(0x20060259, -1, -1); + _playBackwards = true; + NextState(&AsScene1402PuzzleBox::stMoveDownDone); + break; + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +void AsScene1402PuzzleBox::stMoveUpDone() { + sendMessage(_parentScene, 0x2000, 0); + stopAnimation(); + setVisible(false); +} + +void AsScene1402PuzzleBox::stMoveDownDone() { + sendMessage(_parentScene, 0x2001, 0); + stopAnimation(); + setVisible(false); +} + +void AsScene1402PuzzleBox::stMoveDownSolvedDone() { + sendMessage(_parentScene, 0x2003, 0); + stopAnimation(); +} + +static const int16 kScene1407MouseFloorY[] = { + 106, 150, 191, 230, 267, 308, 350, 395 +}; + +static const struct { + int16 x; + int16 floorIndex; + int16 sectionIndex; + int16 nextHoleIndex; +} kScene1407MouseHoles[] = { + {125, 0, 0, 7}, + {452, 7, 21, 0}, + {337, 4, 11, 4}, + {286, 6, 17, 6}, + {348, 6, 17, 39}, + {536, 6, 18, 42}, + {111, 1, 3, 18}, + {203, 1, 3, 38}, + {270, 1, 3, 9}, + {197, 5, 14, 3}, + {252, 5, 14, 35}, + {297, 5, 14, 7}, + {359, 5, 14, 8}, + {422, 4, 12, 26}, + {467, 4, 12, 2}, + {539, 4, 12, 40}, + {111, 5, 13, 17}, + {211, 0, 1, 20}, + {258, 0, 1, 11}, + {322, 0, 1, 16}, + { 99, 6, 16, 31}, + {142, 6, 16, 27}, + {194, 6, 16, 12}, + {205, 2, 6, 45}, + {264, 2, 6, 10}, + { 98, 4, 10, 2}, + {152, 4, 10, 37}, + {199, 4, 10, 13}, + {258, 4, 10, 16}, + {100, 7, 19, 43}, + {168, 7, 19, 23}, + {123, 3, 8, 14}, + {181, 3, 8, 39}, + {230, 3, 8, 28}, + {292, 3, 8, 22}, + {358, 3, 8, 36}, + {505, 3, 9, 44}, + {400, 2, 7, 34}, + {454, 2, 7, 32}, + {532, 2, 7, 46}, + {484, 5, 15, 25}, + {529, 5, 15, 30}, + {251, 7, 20, 48}, + {303, 7, 20, 21}, + {360, 7, 20, 33}, + {503, 0, 2, 5}, + {459, 1, 4, 19}, + {530, 1, 4, 42}, + {111, 2, 5, 47}, + {442, 6, 18, 1} +}; + +static const struct { + int16 x1, x2; + int16 goodHoleIndex; +} kScene1407MouseSections[] = { + {100, 149, 0}, + {182, 351, 17}, + {430, 524, 45}, + { 89, 293, 7}, + {407, 555, 47}, + { 89, 132, 48}, + {178, 303, 23}, + {367, 551, 38}, + {105, 398, 31}, + {480, 537, 36}, + { 84, 275, 27}, + {318, 359, 2}, + {402, 560, 15}, + { 91, 132, 16}, + {179, 400, 10}, + {461, 552, 41}, + { 86, 218, 21}, + {267, 376, 4}, + {420, 560, 49}, + { 77, 188, 30}, + {237, 394, 44}, + {438, 515, 5} +}; + +AsScene1407Mouse::AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _currSectionIndex(0) { + + createSurface(100, 117, 45); + _x = 108; + _y = 106; + stIdleLookAtGoodHole(); + SetUpdateHandler(&AnimatedSprite::update); +} + +void AsScene1407Mouse::suWalkTo() { + int16 xdelta = _walkDestX - _x; + if (xdelta > _deltaX) + xdelta = _deltaX; + else if (xdelta < -_deltaX) + xdelta = -_deltaX; + _deltaX = 0; + if (_walkDestX == _x) + sendMessage(this, 0x1019, 0); + else { + _x += xdelta; + updateBounds(); + } +} + +void AsScene1407Mouse::upGoThroughHole() { + if (_countdown != 0 && (--_countdown == 0)) { + SetUpdateHandler(&AnimatedSprite::update); + gotoNextState(); + } + AnimatedSprite::update(); +} + +uint32 AsScene1407Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + { + int16 mouseX = param.asPoint().x; + int16 mouseY = param.asPoint().y; + int holeIndex; + for (holeIndex = 0; holeIndex < 50; holeIndex++) { + int16 holeX = kScene1407MouseHoles[holeIndex].x; + int16 holeY = kScene1407MouseFloorY[kScene1407MouseHoles[holeIndex].floorIndex]; + if (mouseX >= holeX - 14 && mouseX <= holeX + 14 && mouseY >= holeY - 36 && mouseY <= holeY) + break; + } + if (holeIndex < 50 && kScene1407MouseHoles[holeIndex].sectionIndex == _currSectionIndex) { + _nextHoleIndex = kScene1407MouseHoles[holeIndex].nextHoleIndex; + _walkDestX = kScene1407MouseHoles[holeIndex].x; + stWalkToHole(); + } else { + if (mouseX < kScene1407MouseSections[_currSectionIndex].x1) + _walkDestX = kScene1407MouseSections[_currSectionIndex].x1; + else if (mouseX > kScene1407MouseSections[_currSectionIndex].x2) + _walkDestX = kScene1407MouseSections[_currSectionIndex].x2; + else + _walkDestX = mouseX; + stWalkToDest(); + } + } + break; + case 0x1019: + gotoNextState(); + break; + case 0x2001: + { + // Reset the position + // Find the nearest hole and go through it, and exit at the first hole + int16 distance = 640; + int matchIndex = 50; + for (int index = 0; index < 50; index++) + if (kScene1407MouseHoles[index].sectionIndex == _currSectionIndex && + ABS(kScene1407MouseHoles[index].x - _x) < distance) { + matchIndex = index; + distance = ABS(kScene1407MouseHoles[index].x - _x); + } + if (matchIndex < 50) { + _nextHoleIndex = 0; + _walkDestX = kScene1407MouseHoles[matchIndex].x; + stWalkToHole(); + } + } + break; + } + return messageResult; +} + +void AsScene1407Mouse::stIdleLookAtGoodHole() { + setDoDeltaX(kScene1407MouseHoles[kScene1407MouseSections[_currSectionIndex].goodHoleIndex].x < _x ? 1 : 0); + startAnimation(0x72215194, 0, -1); + SetMessageHandler(&AsScene1407Mouse::handleMessage); + SetSpriteUpdate(NULL); +} + +void AsScene1407Mouse::stWalkToDest() { + if (_walkDestX != _x) { + setDoDeltaX(_walkDestX < _x ? 1 : 0); + startAnimation(0x22291510, 0, -1); + SetMessageHandler(&AsScene1407Mouse::handleMessage); + SetSpriteUpdate(&AsScene1407Mouse::suWalkTo); + NextState(&AsScene1407Mouse::stIdleLookAtGoodHole); + } +} + +void AsScene1407Mouse::stWalkToHole() { + setDoDeltaX(_walkDestX < _x ? 1 : 0); + startAnimation(0x22291510, 0, -1); + SetMessageHandler(&AsScene1407Mouse::handleMessage); + SetSpriteUpdate(&AsScene1407Mouse::suWalkTo); + NextState(&AsScene1407Mouse::stGoThroughHole); +} + +void AsScene1407Mouse::stGoThroughHole() { + startAnimation(0x72215194, 0, -1); + setVisible(false); + _countdown = 12; + SetUpdateHandler(&AsScene1407Mouse::upGoThroughHole); + SetMessageHandler(NULL); + SetSpriteUpdate(NULL); + NextState(&AsScene1407Mouse::stArriveAtHole); +} + +void AsScene1407Mouse::stArriveAtHole() { + _currSectionIndex = kScene1407MouseHoles[_nextHoleIndex].sectionIndex; + _x = kScene1407MouseHoles[_nextHoleIndex].x; + _y = kScene1407MouseFloorY[kScene1407MouseHoles[_nextHoleIndex].floorIndex]; + if (_nextHoleIndex == 1) { + sendMessage(_parentScene, 0x2000, 0); + _walkDestX = 512; + stWalkToDest(); + setVisible(true); + } else { + _walkDestX = _x + 14; + stWalkToDest(); + setVisible(true); + } +} + +static const NPoint kAsScene1405TileItemPositions[] = { + {100, 80}, {162, 78}, {222, 76}, {292, 76}, + {356, 82}, {422, 84}, {488, 86}, {550, 90}, + {102, 134}, {164, 132}, {224, 136}, {294, 136}, + {360, 136}, {422, 138}, {484, 144}, {548, 146}, + { 98, 196}, {160, 200}, {228, 200}, {294, 202}, + {360, 198}, {424, 200}, {482, 202}, {548, 206}, + { 98, 260}, {160, 264}, {226, 260}, {296, 262}, + {358, 260}, {424, 262}, {486, 264}, {550, 266}, + { 94, 322}, {160, 316}, {226, 316}, {296, 320}, + {358, 322}, {422, 324}, {488, 322}, {550, 322}, + { 98, 380}, {160, 376}, {226, 376}, {294, 378}, + {356, 380}, {420, 380}, {490, 378}, {552, 376} +}; + +AsScene1405Tile::AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _tileIndex(tileIndex), _countdown(0), _isShowing(false) { + + loadSound(0, 0x05308101); + setSoundPan(0, (tileIndex % 8 * 4 + 4) * 25 / 8); + _x = kAsScene1405TileItemPositions[_tileIndex].x; + _y = kAsScene1405TileItemPositions[_tileIndex].y; + createSurface1(0x844B805C, 1100); + setVisible(false); + if (getSubVar(VA_IS_TILE_MATCH, _tileIndex)) + _countdown = _vm->_rnd->getRandomNumber(36 - 1) + 1; + startAnimation(0x844B805C, getSubVar(VA_TILE_SYMBOLS, _tileIndex), -1); + _newStickFrameIndex = (int16)getSubVar(VA_TILE_SYMBOLS, _tileIndex); + SetUpdateHandler(&AsScene1405Tile::update); + SetMessageHandler(&AsScene1405Tile::handleMessage); +} + +void AsScene1405Tile::update() { + updateAnim(); + updatePosition(); + if (_countdown != 0 && (--_countdown == 0)) + show(); +} + +uint32 AsScene1405Tile::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (getSubVar(VA_IS_TILE_MATCH, _tileIndex) == 0 && _parentScene->getCountdown() == 0) { + show(); + sendMessage(_parentScene, 0x2000, _tileIndex); + } + messageResult = 1; + break; + } + return messageResult; +} + +void AsScene1405Tile::show() { + if (!_isShowing) { + _isShowing = true; + playSound(0); + setVisible(true); + } +} + +void AsScene1405Tile::hide() { + if (_isShowing) { + _isShowing = false; + playSound(0); + setVisible(false); + } +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1400_sprites.h b/engines/neverhood/modules/module1400_sprites.h new file mode 100644 index 0000000000..036267e8dc --- /dev/null +++ b/engines/neverhood/modules/module1400_sprites.h @@ -0,0 +1,170 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef NEVERHOOD_MODULES_MODULE1400_SPRITES_H +#define NEVERHOOD_MODULES_MODULE1400_SPRITES_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +class AsScene1401Pipe : public AnimatedSprite { +public: + AsScene1401Pipe(NeverhoodEngine *vm); + virtual ~AsScene1401Pipe(); +protected: + int _countdown1; + int _countdown2; + void update(); + void upSuckInProjector(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmSuckInProjector(int messageNum, const MessageParam ¶m, Entity *sender); + void stStartSucking(); + void stDoneSucking(); + void stSuckInProjector(); +}; + +class AsScene1401Mouse : public AnimatedSprite { +public: + AsScene1401Mouse(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suSuckedIn(); + void stSuckedIn(); +}; + +class AsScene1401Cheese : public AnimatedSprite { +public: + AsScene1401Cheese(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suSuckedIn(); + void stSuckedIn(); +}; + +class AsScene1401BackDoor : public AnimatedSprite { +public: + AsScene1401BackDoor(NeverhoodEngine *vm, Sprite *klaymen, bool isOpen); +protected: + Sprite *_klaymen; + int _countdown; + bool _isOpen; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stOpenDoor(); + void stCloseDoor(); + void stCloseDoorDone(); +}; + +struct AsCommonProjectorItem { + NPoint point; + int8 maxSlotCount; + int8 lockSlotIndex; + int8 index1; + int8 leftBorderLeaves; + int8 rightBorderLeaves; +}; + +class AsCommonProjector : public AnimatedSprite { +public: + AsCommonProjector(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, Sprite *asPipe); + virtual ~AsCommonProjector(); +protected: + Scene *_parentScene; + Sprite *_klaymen; + Sprite *_asPipe; + const AsCommonProjectorItem *_asProjectorItem; + int16 _beforeMoveX; + bool _lockedInSlot; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmLockedInSlot(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 hmAnimation(int messageNum, const MessageParam ¶m, Entity *sender); + void suMoving(); + void moveProjector(); + void stSuckedIn(); + void stIdle(); + void stMoving(); + void stStartLockedInSlot(); + void stStayLockedInSlot(); + void stStartProjecting(); + void stLockedInSlot(); + void stStopProjecting(); + void stTurnToFront(); + void stStartSuckedIn(); +}; + +class SsScene1402BridgePart : public StaticSprite { +public: + SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority); +}; + +class AsScene1402PuzzleBox : public AnimatedSprite { +public: + AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status); +protected: + Scene *_parentScene; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stMoveUpDone(); + void stMoveDownDone(); + void stMoveDownSolvedDone(); +}; + +class AsScene1407Mouse : public AnimatedSprite { +public: + AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + int16 _walkDestX; + int16 _currSectionIndex; + int16 _nextHoleIndex; + int _countdown; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suWalkTo(); + void upGoThroughHole(); + void stIdleLookAtGoodHole(); + void stWalkToDest(); + void stWalkToHole(); + void stGoThroughHole(); + void stArriveAtHole(); +}; + +class Scene1405; + +class AsScene1405Tile : public AnimatedSprite { +public: + AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex); + void show(); + void hide(); +protected: + Scene1405 *_parentScene; + bool _isShowing; + uint32 _tileIndex; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULES_MODULE1400_SPRITES_H */ -- cgit v1.2.3