diff options
-rw-r--r-- | engines/neverhood/gamemodule.cpp | 2 | ||||
-rw-r--r-- | engines/neverhood/module2800.cpp | 637 | ||||
-rw-r--r-- | engines/neverhood/module2800.h | 131 | ||||
-rw-r--r-- | engines/neverhood/palette.cpp | 11 | ||||
-rw-r--r-- | engines/neverhood/palette.h | 1 |
5 files changed, 757 insertions, 25 deletions
diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp index 384f419243..813222ccf1 100644 --- a/engines/neverhood/gamemodule.cpp +++ b/engines/neverhood/gamemodule.cpp @@ -328,7 +328,7 @@ void GameModule::startup() { createModule(2700, -1); #endif #if 1 - _vm->gameState().sceneNum = 5; + _vm->gameState().sceneNum = 3; createModule(2800, -1); #endif } diff --git a/engines/neverhood/module2800.cpp b/engines/neverhood/module2800.cpp index 0862205437..4757b4fcc5 100644 --- a/engines/neverhood/module2800.cpp +++ b/engines/neverhood/module2800.cpp @@ -82,6 +82,9 @@ void Module2800::createScene(int sceneNum, int which) { // TODO _childObject = new Scene2803(_vm, this, which); } break; + case 3: + _childObject = new Scene2804(_vm, this, which); + break; case 4: // TODO Music18hList_stop(0xD2FA4D14, 0, 2); _childObject = new Scene2805(_vm, this, which); @@ -154,6 +157,9 @@ void Module2800::updateScene() { else createScene(0, 1); break; + case 3: + createScene(2, 1); + break; case 4: if (_moduleResult == 1) { leaveModule(1); @@ -641,6 +647,601 @@ void Scene2803b::sub4601F0(bool flag) { } } +SsScene2804RedButton::SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene) + : StaticSprite(vm, 900), _countdown(0), _parentScene(parentScene), + _soundResource(vm) { + + if (getGlobalVar(0x190A1D18)) + _spriteResource.load2(0x51A10202); + else + _spriteResource.load2(0x11814A21); + createSurface(400, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height); + _drawRect.x = 0; + _drawRect.y = 0; + _drawRect.width = _spriteResource.getDimensions().width; + _drawRect.height = _spriteResource.getDimensions().height; + _x = _spriteResource.getPosition().x; + _y = _spriteResource.getPosition().y; + _deltaRect = _drawRect; + processDelta(); + setVisible(false); + _needRefresh = true; + SetUpdateHandler(&SsScene2804RedButton::update); + SetMessageHandler(&SsScene2804RedButton::handleMessage); + _soundResource.load(0x44241240); +} + +void SsScene2804RedButton::update() { + StaticSprite::update(); + if (_countdown != 0 && (--_countdown) == 0) { + setVisible(false); + } +} + +uint32 SsScene2804RedButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown == 0 && !_parentScene->isWorking()) { + _soundResource.play(); + setVisible(true); + _countdown = 4; + sendMessage(_parentScene, 0x2000, 0); + } + messageResult = 1; + break; + } + return messageResult; +} + +SsScene2808LightCoil::SsScene2808LightCoil(NeverhoodEngine *vm) + : StaticSprite(vm, 900) { + + _spriteResource.load2(0x8889B008); + createSurface(400, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height); + _drawRect.x = 0; + _drawRect.y = 0; + _drawRect.width = _spriteResource.getDimensions().width; + _drawRect.height = _spriteResource.getDimensions().height; + _x = _spriteResource.getPosition().x; + _y = _spriteResource.getPosition().y; + setVisible(false); + _needRefresh = true; + StaticSprite::update(); + SetMessageHandler(&SsScene2808LightCoil::handleMessage); +} + +uint32 SsScene2808LightCoil::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2002: + setVisible(true); + StaticSprite::update(); + messageResult = 1; + break; + case 0x2003: + setVisible(false); + StaticSprite::update(); + messageResult = 1; + break; + } + return messageResult; +} + +SsScene2808LightTarget::SsScene2808LightTarget(NeverhoodEngine *vm) + : StaticSprite(vm, 900) { + + _spriteResource.load2(0x06092132); + createSurface(400, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height); + _drawRect.x = 0; + _drawRect.y = 0; + _drawRect.width = _spriteResource.getDimensions().width; + _drawRect.height = _spriteResource.getDimensions().height; + _x = _spriteResource.getPosition().x; + _y = _spriteResource.getPosition().y; + setVisible(false); + _needRefresh = true; + StaticSprite::update(); + SetMessageHandler(&SsScene2808LightTarget::handleMessage); +} + +uint32 SsScene2808LightTarget::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2004: + setVisible(true); + StaticSprite::update(); + messageResult = 1; + break; + case 0x2005: + setVisible(false); + StaticSprite::update(); + messageResult = 1; + break; + } + return messageResult; +} + +SsScene2808Flash::SsScene2808Flash(NeverhoodEngine *vm) + : StaticSprite(vm, 900), _soundResource(vm) { + + _spriteResource.load2(0x211003A0); + createSurface(400, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height); + _drawRect.x = 0; + _drawRect.y = 0; + _drawRect.width = _spriteResource.getDimensions().width; + _drawRect.height = _spriteResource.getDimensions().height; + _x = _spriteResource.getPosition().x; + _y = _spriteResource.getPosition().y; + setVisible(false); + _needRefresh = true; + StaticSprite::update(); + _soundResource.load(0xCB36BA54); +} + +void SsScene2808Flash::show() { + setVisible(true); + StaticSprite::update(); + _soundResource.play(); +} + +SsScene2808BeamCoilBody::SsScene2808BeamCoilBody(NeverhoodEngine *vm) + : StaticSprite(vm, 900) { + + _spriteResource.load2(0x9A816000); + createSurface(400, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height); + _drawRect.x = 0; + _drawRect.y = 0; + _drawRect.width = _spriteResource.getDimensions().width; + _drawRect.height = _spriteResource.getDimensions().height; + _x = _spriteResource.getPosition().x; + _y = _spriteResource.getPosition().y; + setVisible(false); + _needRefresh = true; + StaticSprite::update(); +} + +AsScene2804CrystalWaves::AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex) + : AnimatedSprite(vm, 1100), _crystalIndex(crystalIndex) { + + static const NPoint kAsScene2804CrystalWavesPoints[] = { + {323, 245}, + {387, 76}, + {454, 260}, + {527, 70} + }; + + _x = kAsScene2804CrystalWavesPoints[crystalIndex].x; + _y = kAsScene2804CrystalWavesPoints[crystalIndex].y; + createSurface1(0x840C41F0, 1200); + if (crystalIndex & 1) + setDoDeltaX(1); + setVisible(false); + _needRefresh = true; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&Sprite::handleMessage); +} + +void AsScene2804CrystalWaves::show() { + setVisible(true); + startAnimation(0x840C41F0, 0, -1); +} + +void AsScene2804CrystalWaves::hide() { + setVisible(false); + stopAnimation(); +} + +static const int16 kAsScene2804CrystalFrameNums[] = { + 0, 6, 2, 8, 1, 10, 0, 0 +}; + +static const uint32 kAsScene2804CrystalFileHashes[] = { + 0x000540B0, + 0x001280D0, + 0x003D0010, + 0x00620190, + 0x00DC0290 +}; + +AsScene2804Crystal::AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex) + : AnimatedSprite(vm, 1100), _asCrystalWaves(asCrystalWaves), _crystalIndex(crystalIndex), + _isShowing(false), _soundResource(vm) { + + static const NPoint kAsScene2804CrystalPoints[] = { + {204, 196}, + {272, 316}, + {334, 206}, + {410, 334}, + {470, 180} + }; + + _colorNum = (int16)getSubVar(0xE11A1929, crystalIndex); + _isLightOn = getGlobalVar(0x190A1D18) != 0; + if (_isLightOn) { + _x = kAsScene2804CrystalPoints[crystalIndex].x; + _y = kAsScene2804CrystalPoints[crystalIndex].y; + createSurface1(0x108DFB12, 1200); + startAnimation(0x108DFB12, kAsScene2804CrystalFrameNums[_colorNum], -1); + _needRefresh = true; + _newStickFrameIndex = kAsScene2804CrystalFrameNums[_colorNum]; + } else { + _x = 320; + _y = 240; + createSurface1(kAsScene2804CrystalFileHashes[crystalIndex], 1200); + startAnimation(kAsScene2804CrystalFileHashes[crystalIndex], _colorNum, -1); + setVisible(false); + _needRefresh = true; + _newStickFrameIndex = _colorNum; + } + _soundResource.load(0x725294D4); + SetUpdateHandler(&AnimatedSprite::update); +} + +void AsScene2804Crystal::show() { + if (!_isLightOn) { + setVisible(true); + _isShowing = true; + if (_asCrystalWaves) + _asCrystalWaves->show(); + _soundResource.play(); + } +} + +void AsScene2804Crystal::hide() { + if (!_isLightOn) { + setVisible(false); + _isShowing = false; + if (_asCrystalWaves) + _asCrystalWaves->hide(); + } +} + +void AsScene2804Crystal::activate() { + if (!_isShowing) { + int16 frameNum = kAsScene2804CrystalFrameNums[_colorNum]; + _colorNum++; + if (_colorNum >= 6) + _colorNum = 0; + if (_isLightOn) { + startAnimation(0x108DFB12, frameNum, kAsScene2804CrystalFrameNums[_colorNum]); + _playBackwards = kAsScene2804CrystalFrameNums[_colorNum] < _colorNum; + _newStickFrameIndex = kAsScene2804CrystalFrameNums[_colorNum]; + } else { + startAnimation(kAsScene2804CrystalFileHashes[_crystalIndex], _colorNum, -1); + _newStickFrameIndex = _colorNum; + } + setSubVar(0xE11A1929, _crystalIndex, _colorNum); + } +} + +SsScene2804CrystalButton::SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex) + : StaticSprite(vm, 900), _countdown(0), _parentScene(parentScene), _asCrystal(asCrystal), + _crystalIndex(crystalIndex), _soundResource(vm) { + + static const uint32 kSsScene2804CrystalButtonFileHashes1[] = { + 0x911101B0, + 0x22226001, + 0x4444A362, + 0x888925A4, + 0x11122829 + }; + + static const uint32 kSsScene2804CrystalButtonFileHashes2[] = { + 0xB500A1A0, + 0x6A012021, + 0xD4022322, + 0xA8042525, + 0x5008292B + }; + + if (getGlobalVar(0x190A1D18)) + _spriteResource.load2(kSsScene2804CrystalButtonFileHashes1[crystalIndex]); + else + _spriteResource.load2(kSsScene2804CrystalButtonFileHashes2[crystalIndex]); + + createSurface(400, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height); + _drawRect.x = 0; + _drawRect.y = 0; + _drawRect.width = _spriteResource.getDimensions().width; + _drawRect.height = _spriteResource.getDimensions().height; + _x = _spriteResource.getPosition().x; + _y = _spriteResource.getPosition().y; + _deltaRect = _drawRect; + processDelta(); + setVisible(false); + _soundResource.load(0x44045140); + _needRefresh = true; + SetUpdateHandler(&SsScene2804CrystalButton::update); + SetMessageHandler(&SsScene2804CrystalButton::handleMessage); +} + +void SsScene2804CrystalButton::update() { + StaticSprite::update(); + if (_countdown != 0 && (--_countdown) == 0) { + setVisible(false); + } +} + +uint32 SsScene2804CrystalButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (_countdown == 0 && !_parentScene->isWorking()) { + _soundResource.play(); + setVisible(true); + _countdown = 4; + _asCrystal->activate(); + } + messageResult = 1; + break; + } + return messageResult; +} + +AsScene2804BeamCoil::AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2808BeamCoilBody *ssBeamCoilBody) + : AnimatedSprite(vm, 1400), _parentScene(parentScene), _ssBeamCoilBody(ssBeamCoilBody), + _countdown(0), _soundResource(vm) { + + createSurface1(0x00494891, 1000); + _x = 125; + _y = 184; + setVisible(false); + _needRefresh = true; + AnimatedSprite::updatePosition(); + _soundResource.load(0x6352F051); + // TODO Sound1ChList_addSoundResource(0xC5EA0B28, 0xEF56B094, true); + SetUpdateHandler(&AsScene2804BeamCoil::update); + SetMessageHandler(&AsScene2804BeamCoil::handleMessage); +} + +void AsScene2804BeamCoil::update() { + updateAnim(); + updatePosition(); + if (_countdown != 0 && (--_countdown) == 0) { + sendMessage(_parentScene, 0x2001, 0); + } +} + +uint32 AsScene2804BeamCoil::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2002: + show(); + _countdown = 92; + messageResult = 1; + break; + case 0x2003: + hide(); + messageResult = 1; + break; + } + return messageResult; +} + +void AsScene2804BeamCoil::show() { + _ssBeamCoilBody->setVisible(true); + // TODO _ssBeamCoilBody->update(); -> show() + setVisible(true); + startAnimation(0x00494891, 0, -1); + _soundResource.play(); + SetMessageHandler(&AsScene2804BeamCoil::hmBeaming); + NextState(&AsScene2804BeamCoil::stBeaming); +} + +void AsScene2804BeamCoil::hide() { + stopAnimation(); + SetMessageHandler(&AsScene2804BeamCoil::handleMessage); + setVisible(false); + _ssBeamCoilBody->setVisible(false); + // TODO _ssBeamCoilBody->update(); -> hide() + // TODO Sound1ChList_stop(0xEF56B094); +} + +void AsScene2804BeamCoil::stBeaming() { + startAnimation(0x00494891, 93, -1); + NextState(&AsScene2804BeamCoil::stBeaming); + // TODO Sound1ChList_playLooping(0xEF56B094); +} + +uint32 AsScene2804BeamCoil::hmBeaming(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + gotoNextState(); + break; + } + return messageResult; +} + +AsScene2804BeamTarget::AsScene2804BeamTarget(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1400) { + + createSurface1(0x03842000, 1000); + _x = 475; + _y = 278; + setVisible(false); + _needRefresh = true; + updatePosition(); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene2804BeamTarget::handleMessage); +} + +uint32 AsScene2804BeamTarget::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2004: + setVisible(true); + startAnimation(0x03842000, 0, -1); + messageResult = 1; + break; + case 0x2005: + setVisible(false); + stopAnimation(); + messageResult = 1; + break; + } + return messageResult; +} + +Scene2804::Scene2804(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule, true), _countdown1(0), _countdown2(0), _countdown3(0), + _beamStatus(0), _isSolved(false), _isWorking(false) { + + initCrystalColors(); + + _surfaceFlag = true; + SetMessageHandler(&Scene2804::handleMessage); + SetUpdateHandler(&Scene2804::update); + + //setGlobalVar(0x190A1D18, 1); // DEBUG Set lights on + + if (getGlobalVar(0x190A1D18)) { + setBackground(0xA1D03005); + setPalette(0xA1D03005); + addEntity(_palette); + insertMouse435(0x03001A15, 20, 620); + _asCoil = insertSprite<SsScene2808LightCoil>(); + _asTarget = insertSprite<SsScene2808LightTarget>(); + } else { + SsScene2808BeamCoilBody *ssBeamCoilBody; + setBackground(0x01C01414); + setPalette(0x01C01414); + addEntity(_palette); + insertMouse435(0x01410014, 20, 620); + ssBeamCoilBody = insertSprite<SsScene2808BeamCoilBody>(); + _asCoil = insertSprite<AsScene2804BeamCoil>(this, ssBeamCoilBody); + _asTarget = insertSprite<AsScene2804BeamTarget>(); + _ssFlash = insertSprite<SsScene2808Flash>(); + } + + _ssRedButton = insertSprite<SsScene2804RedButton>(this); + _vm->_collisionMan->addSprite(_ssRedButton); + + for (uint crystalIndex = 0; crystalIndex < 5; crystalIndex++) { + AsScene2804CrystalWaves *asCrystalWaves = NULL; + if (crystalIndex < 4 && getGlobalVar(0x190A1D18) == 0) + asCrystalWaves = insertSprite<AsScene2804CrystalWaves>(crystalIndex); + _asCrystals[crystalIndex] = insertSprite<AsScene2804Crystal>(asCrystalWaves, crystalIndex); + _ssCrystalButtons[crystalIndex] = insertSprite<SsScene2804CrystalButton>(this, _asCrystals[crystalIndex], crystalIndex); + _vm->_collisionMan->addSprite(_ssCrystalButtons[crystalIndex]); + } + +} + +uint32 Scene2804::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + // TODO DEBUG + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { + leaveScene(0); + } + break; + case 0x000D: + // TODO DEBUG + break; + case 0x2000: + _isWorking = true; + sendMessage(_asCoil, 0x2002, 0); + if (getGlobalVar(0x190A1D18)) { + sendMessage(_asTarget, 0x2004, 0); + _countdown2 = 48; + } + break; + case 0x2001: + _countdown3 = 2; + _isSolved = true; + _beamStatus = 0; + for (uint index = 0; index < 5; index++) + if (_asCrystals[index]->getColorNum() != (int16)getSubVar(0xD4B2089C, index)) + _isSolved = false; + _countdown2 = 48; + break; + } + return 0; +} + +void Scene2804::update() { + + Scene::update(); + + if (_countdown1 != 0 && (--_countdown1) == 0) { + leaveScene(0); + } + + if (_countdown2 != 0 && (--_countdown2) == 0) { + _isWorking = false; + sendMessage(_asCoil, 0x2003, 0); + sendMessage(_asTarget, 0x2005, 0); + for (uint index = 0; index < 5; index++) + _asCrystals[index]->hide(); + } + + if (_countdown3 != 0 && (--_countdown3) == 0) { + if (_beamStatus == 5) { + sendMessage(_asTarget, 0x2004, 0); + if (_isSolved) { + _palette->fillBaseWhite(0, 256); + _palette->startFadeToPalette(18); + setGlobalVar(0x1860C990, 1); + _countdown1 = 48; + } + } else if (_beamStatus == 6) { + if (_isSolved) + _ssFlash->show(); + } else { + _asCrystals[_beamStatus]->show(); + } + _beamStatus++; + if (_beamStatus < 6) + _countdown3 = 2; + else if (_beamStatus < 7) + _countdown3 = 4; + } + +} + +void Scene2804::initCrystalColors() { + // TODO Maybe move this into the GameModule so all puzzle init code is together + if (getGlobalVar(0xDE2EC914) == 0) { + TextResource textResource(_vm); + const char *textStart, *textEnd; + textResource.load(0x46691611); + textStart = textResource.getString(0, textEnd); + for (uint index = 0; index < 5; index++) { + char colorLetter = (byte)textStart[index]; + byte correctColorNum = 0, misalignedColorNum; + switch (colorLetter) { + case 'B': + correctColorNum = 4; + break; + case 'G': + correctColorNum = 3; + break; + case 'O': + correctColorNum = 1; + break; + case 'R': + correctColorNum = 0; + break; + case 'V': + correctColorNum = 5; + break; + case 'Y': + correctColorNum = 2; + break; + } + do { + misalignedColorNum = _vm->_rnd->getRandomNumber(6 - 1); + } while (misalignedColorNum == correctColorNum); + setSubVar(0xD4B2089C, index, correctColorNum); + setSubVar(0xE11A1929, index, misalignedColorNum); + } + setGlobalVar(0xDE2EC914, 1); + } +} + Scene2805::Scene2805(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule, true) { @@ -897,39 +1498,35 @@ static const int16 kClass490FrameIndices2[] = { 0, 4, 8, 11, 15, 17, 19, 0 }; -AsScene2808Dispenser::AsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex) +SsScene2808Dispenser::SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex) : StaticSprite(vm, 900), _parentScene(parentScene), _countdown(0), _testTubeSetNum(testTubeSetNum), _testTubeIndex(testTubeIndex) { _spriteResource.load2(kClass428FileHashes[testTubeSetNum * 3 + testTubeIndex]); createSurface(1500, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height); - - _surface->getDrawRect().x = 0; - _surface->getDrawRect().y = 0; - _surface->getDrawRect().width = _spriteResource.getDimensions().width; - _surface->getDrawRect().height = _spriteResource.getDimensions().height; + _drawRect.x = 0; + _drawRect.y = 0; + _drawRect.width = _spriteResource.getDimensions().width; + _drawRect.height = _spriteResource.getDimensions().height; _x = _spriteResource.getPosition().x; _y = _spriteResource.getPosition().y; _deltaRect = _drawRect; processDelta(); - - SetUpdateHandler(&AsScene2808Dispenser::update); - SetMessageHandler(&AsScene2808Dispenser::handleMessage); - + SetUpdateHandler(&SsScene2808Dispenser::update); + SetMessageHandler(&SsScene2808Dispenser::handleMessage); setVisible(false); _needRefresh = true; StaticSprite::update(); - } -void AsScene2808Dispenser::update() { +void SsScene2808Dispenser::update() { StaticSprite::update(); if (_countdown != 0 && (--_countdown) == 0) { setVisible(false); } } -uint32 AsScene2808Dispenser::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { +uint32 SsScene2808Dispenser::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); switch (messageNum) { case 0x1011: @@ -940,7 +1537,7 @@ uint32 AsScene2808Dispenser::handleMessage(int messageNum, const MessageParam &p return messageResult; } -void AsScene2808Dispenser::startCountdown(int index) { +void SsScene2808Dispenser::startCountdown(int index) { setVisible(true); StaticSprite::update(); if (_testTubeSetNum == 0) { @@ -950,8 +1547,8 @@ void AsScene2808Dispenser::startCountdown(int index) { } } -AsScene2808TestTube::AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, AsScene2808Dispenser *dispenser) - : AnimatedSprite(vm, 1100), _testTubeSetNum(testTubeSetNum), _testTubeIndex(testTubeIndex), _dispenser(dispenser), +AsScene2808TestTube::AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser) + : AnimatedSprite(vm, 1100), _testTubeSetNum(testTubeSetNum), _testTubeIndex(testTubeIndex), _ssDispenser(ssDispenser), _soundResource1(vm), _soundResource2(vm), _soundResource3(vm), _soundResource4(vm), _soundResource5(vm), _soundResource6(vm), _soundResource7(vm), _soundResource8(vm), _soundResource9(vm), _fillLevel(0) { @@ -1048,7 +1645,7 @@ void AsScene2808TestTube::fill() { startAnimation(kClass490FileHashes[_testTubeIndex], kClass490FrameIndices2[_fillLevel], kClass490FrameIndices2[_fillLevel + 1]); _newStickFrameIndex = kClass490FrameIndices2[_fillLevel + 1]; } - _dispenser->startCountdown(_fillLevel); + _ssDispenser->startCountdown(_fillLevel); _fillLevel++; } @@ -1213,9 +1810,9 @@ Scene2808::Scene2808(NeverhoodEngine *vm, Module *parentModule, int which) insertSprite<AsScene2808LightEffect>(which); for (int testTubeIndex = 0; testTubeIndex < 3; testTubeIndex++) { - AsScene2808Dispenser *dispenser = insertSprite<AsScene2808Dispenser>(this, which, testTubeIndex); - _vm->_collisionMan->addSprite(dispenser); - _asTestTubes[testTubeIndex] = insertSprite<AsScene2808TestTube>(which, testTubeIndex, dispenser); + SsScene2808Dispenser *ssDispenser = insertSprite<SsScene2808Dispenser>(this, which, testTubeIndex); + _vm->_collisionMan->addSprite(ssDispenser); + _asTestTubes[testTubeIndex] = insertSprite<AsScene2808TestTube>(which, testTubeIndex, ssDispenser); _vm->_collisionMan->addSprite(_asTestTubes[testTubeIndex]); } diff --git a/engines/neverhood/module2800.h b/engines/neverhood/module2800.h index 404f9ace1a..03e272fa98 100644 --- a/engines/neverhood/module2800.h +++ b/engines/neverhood/module2800.h @@ -93,6 +93,129 @@ protected: void sub4601F0(bool flag); }; +class Scene2804; + +class SsScene2804RedButton : public StaticSprite { +public: + SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene); +protected: + SoundResource _soundResource; + Scene2804 *_parentScene; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene2808LightCoil : public StaticSprite { +public: + SsScene2808LightCoil(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene2808BeamCoilBody : public StaticSprite { +public: + SsScene2808BeamCoilBody(NeverhoodEngine *vm); +}; + +class SsScene2808LightTarget : public StaticSprite { +public: + SsScene2808LightTarget(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class SsScene2808Flash : public StaticSprite { +public: + SsScene2808Flash(NeverhoodEngine *vm); + void show(); +protected: + SoundResource _soundResource; +}; + +class AsScene2804CrystalWaves : public AnimatedSprite { +public: + AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex); + void show(); + void hide(); +protected: + uint _crystalIndex; +}; + +class AsScene2804Crystal : public AnimatedSprite { +public: + AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex); + void show(); + void hide(); + void activate(); + int16 getColorNum() const { return _colorNum; } +protected: + AsScene2804CrystalWaves *_asCrystalWaves; + uint _crystalIndex; + int16 _colorNum; + bool _isLightOn; + bool _isShowing; + SoundResource _soundResource; +}; + +class SsScene2804CrystalButton : public StaticSprite { +public: + SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex); +protected: + SoundResource _soundResource; + Scene2804 *_parentScene; + AsScene2804Crystal *_asCrystal; + uint _crystalIndex; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2804BeamCoil : public AnimatedSprite { +public: + AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2808BeamCoilBody *ssBeamCoilBody); +protected: + SoundResource _soundResource; + Scene *_parentScene; + SsScene2808BeamCoilBody *_ssBeamCoilBody; + int _countdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void show(); + void hide(); + void stBeaming(); + uint32 hmBeaming(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class AsScene2804BeamTarget : public AnimatedSprite { +public: + AsScene2804BeamTarget(NeverhoodEngine *vm); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene2804 : public Scene { +public: + Scene2804(NeverhoodEngine *vm, Module *parentModule, int which); + bool isWorking() const { return _isWorking; } +protected: + int _countdown1; + int _countdown2; + int _countdown3; + int _beamStatus; + bool _isSolved; + bool _isWorking; + Sprite *_ssRedButton; + Sprite *_asCoil; + Sprite *_asTarget; + SsScene2808Flash *_ssFlash; + AsScene2804Crystal *_asCrystals[5]; + Sprite *_ssCrystalButtons[5]; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void initCrystalColors(); +}; + class Scene2805 : public Scene { public: Scene2805(NeverhoodEngine *vm, Module *parentModule, int which); @@ -128,9 +251,9 @@ protected: void findClosestPoint(); }; -class AsScene2808Dispenser : public StaticSprite { +class SsScene2808Dispenser : public StaticSprite { public: - AsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex); + SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex); void startCountdown(int index); protected: Scene *_parentScene; @@ -142,12 +265,12 @@ protected: class AsScene2808TestTube : public AnimatedSprite { public: - AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, AsScene2808Dispenser *dispenser); + AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser); void fill(); void flush(); uint32 getFillLevel() const { return _fillLevel; } protected: - AsScene2808Dispenser *_dispenser; + SsScene2808Dispenser *_ssDispenser; int _testTubeSetNum; uint32 _fillLevel; int _testTubeIndex; diff --git a/engines/neverhood/palette.cpp b/engines/neverhood/palette.cpp index 936ca39ac6..c27bd867bc 100644 --- a/engines/neverhood/palette.cpp +++ b/engines/neverhood/palette.cpp @@ -139,6 +139,17 @@ void Palette::startFadeToPalette(int counter) { _status = 2; } +void Palette::fillBaseWhite(int index, int count) { + if (index + count > 256) + count = 256 - index; + for (int i = 0; i < count; i++) { + _basePalette[(i + index) * 4 + 0] = 0xFF; + _basePalette[(i + index) * 4 + 1] = 0xFF; + _basePalette[(i + index) * 4 + 2] = 0xFF; + _basePalette[(i + index) * 4 + 3] = 0; + } +} + void Palette::update() { debug(2, "Palette::update() _status = %d", _status); if (_status == 1) { diff --git a/engines/neverhood/palette.h b/engines/neverhood/palette.h index 79660130e1..27f4816bb0 100644 --- a/engines/neverhood/palette.h +++ b/engines/neverhood/palette.h @@ -49,6 +49,7 @@ public: void startFadeToBlack(int counter); void startFadeToWhite(int counter); void startFadeToPalette(int counter); + void fillBaseWhite(int index, int count); protected: int _status; byte *_palette; |