diff options
Diffstat (limited to 'engines/access/amazon/amazon_logic.cpp')
-rw-r--r-- | engines/access/amazon/amazon_logic.cpp | 2230 |
1 files changed, 2230 insertions, 0 deletions
diff --git a/engines/access/amazon/amazon_logic.cpp b/engines/access/amazon/amazon_logic.cpp new file mode 100644 index 0000000000..6dffb85e5e --- /dev/null +++ b/engines/access/amazon/amazon_logic.cpp @@ -0,0 +1,2230 @@ +/* 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 "common/scummsys.h" +#include "access/access.h" +#include "access/resources.h" +#include "access/screen.h" +#include "access/amazon/amazon_game.h" +#include "access/amazon/amazon_logic.h" +#include "access/amazon/amazon_resources.h" + +namespace Access { + +namespace Amazon { + +PannedScene::PannedScene(AmazonEngine *vm) : AmazonManager(vm) { + for (int i = 0; i < PAN_SIZE; ++i) { + _pan[i]._pObject = nullptr; + _pan[i]._pImgNum = 0; + _pan[i]._pObjX = _pan[i]._pObjY = _pan[i]._pObjZ = 0; + _pan[i]._pObjXl = _pan[i]._pObjYl = 0; + } + + _xCount = 0; + _xTrack = _yTrack = _zTrack = 0; + _xCam = _yCam = _zCam = 0; + _pNumObj = 0; +} + +void PannedScene::pan() { + _zCam += _zTrack; + _xCam += _xTrack; + int tx = (_xTrack << 8) / _zCam; + _yCam += _yTrack; + int ty = (_yTrack << 8) / _zCam; + + if (_vm->_timers[24]._flag != 1) { + ++_vm->_timers[24]._flag; + for (int i = 0; i < _pNumObj; i++) { + _pan[i]._pObjZ += _zTrack; + _pan[i]._pObjXl += (_pan[i]._pObjZ * tx) & 0xff; + _pan[i]._pObjX += ((_pan[i]._pObjZ * tx) >> 8) + (_pan[i]._pObjXl >> 8); + _pan[i]._pObjXl &= 0xff; + + _pan[i]._pObjYl += (_pan[i]._pObjZ * ty) & 0xff; + _pan[i]._pObjY += ((_pan[i]._pObjZ * ty) >> 8) + (_pan[i]._pObjYl >> 8); + _pan[i]._pObjYl &= 0xff; + } + } + + for (int i = 0; i < _pNumObj; i++) { + ImageEntry ie; + ie._flags = IMGFLAG_UNSCALED; + ie._position = Common::Point(_pan[i]._pObjX, _pan[i]._pObjY); + ie._offsetY = 255; + ie._spritesPtr = _pan[i]._pObject; + ie._frameNumber = _pan[i]._pImgNum; + + _vm->_images.addToList(ie); + } +} + +/*------------------------------------------------------------------------*/ + +CampScene::CampScene(AmazonEngine *vm) : PannedScene(vm) { + _skipStart = false; +} + +void CampScene::mWhileDoOpen() { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + + screen.setDisplayScan(); + events.hideCursor(); + screen.forceFadeOut(); + _skipStart = false; + if (_vm->_conversation != 2) { + // Cutscene at start of chapter 1 + screen.setPanel(3); + _vm->startChapter(1); + _vm->establishCenter(0, 1); + } + + Resource *data = _vm->_files->loadFile(1, 0); + _vm->_objectsTable[1] = new SpriteResource(_vm, data); + delete data; + + _vm->_files->_setPaletteFlag = false; + _vm->_files->loadScreen(1, 2); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); + + // Load animation data + _vm->_animation->freeAnimationData(); + Resource *animResource = _vm->_files->loadFile(1, 1); + _vm->_animation->loadAnimations(animResource); + delete animResource; + + _xTrack = 8; + _yTrack = -3; + _zTrack = 0; + _xCam = _yCam = 0; + _zCam = 270; + _vm->_timers[24]._timer = _vm->_timers[24]._initTm = 1; + ++_vm->_timers[24]._flag; + _vm->_timers.updateTimers(); + + _pNumObj = 10; + for (int i = 0; i < _pNumObj; i++) { + _pan[i]._pObject = _vm->_objectsTable[1]; + _pan[i]._pImgNum = OPENING_OBJS[i][0]; + _pan[i]._pObjX = OPENING_OBJS[i][1]; + _pan[i]._pObjY = OPENING_OBJS[i][2]; + _pan[i]._pObjZ = OPENING_OBJS[i][3]; + _pan[i]._pObjXl = _pan[i]._pObjYl = 0; + } + + _vm->_oldRects.clear(); + _vm->_newRects.clear(); + Animation *anim = _vm->_animation->setAnimation(0); + _vm->_animation->setAnimTimer(anim); + anim = _vm->_animation->setAnimation(1); + _vm->_animation->setAnimTimer(anim); + _vm->_midi->newMusic(10, 0); + + bool startFl = false; + while (!_vm->shouldQuit()) { + _vm->_images.clear(); + _vm->_animation->animate(0); + _vm->_animation->animate(1); + pan(); + _vm->_buffer2.copyFrom(_vm->_buffer1); + _vm->_newRects.clear(); + _vm->plotList(); + _vm->copyBlocks(); + if (!startFl) { + startFl = true; + screen.forceFadeIn(); + } + + events.pollEventsAndWait(); + + if (_vm->_events->isKeyMousePressed()) { + _skipStart = true; + _vm->_midi->newMusic(10, 1); + break; + } + + if (_xCam > 680) { + events._vbCount = 125; + + while (!_vm->shouldQuit() && !events.isKeyMousePressed() && events._vbCount > 0) { + events.pollEventsAndWait(); + } + break; + } + } + + events.showCursor(); + _vm->_buffer2.copyFrom(*_vm->_screen); + _vm->_buffer1.copyFrom(*_vm->_screen); + + _vm->freeCells(); + _vm->_oldRects.clear(); + _vm->_newRects.clear(); + _vm->_numAnimTimers = 0; + _vm->_images.clear(); + + if (_vm->_conversation == 2) { + // Cutscene at end of Chapter 6 + Resource *spriteData = _vm->_files->loadFile(28, 37); + _vm->_objectsTable[28] = new SpriteResource(_vm, spriteData); + delete spriteData; + + _vm->_animation->freeAnimationData(); + animResource = _vm->_files->loadFile(28, 38); + _vm->_animation->loadAnimations(animResource); + delete animResource; + } +} + +/*------------------------------------------------------------------------*/ + +Opening::Opening(AmazonEngine *vm) : CampScene(vm) { + _pCount = 0; +} + +void Opening::doIntroduction() { + Screen &screen = *_vm->_screen; + + screen.setInitialPalettte(); + _vm->_events->setCursor(CURSOR_ARROW); + _vm->_events->showCursor(); + screen.setPanel(0); + screen.setPalette(); + + _vm->_events->setCursor(CURSOR_ARROW); + _vm->_events->showCursor(); + screen.setPanel(3); + doTitle(); + + if (_vm->shouldQuit() || _skipStart || _vm->isDemo()) + return; + + screen.setPanel(3); + mWhileDoOpen(); + + if (_vm->shouldQuit() || _skipStart) + return; + + doTent(); +} + +void Opening::doCredit() { + if (_pCount < 15) + return; + + if (_pCount <= 75) + _vm->_buffer2.plotImage(_vm->_objectsTable[0], _vm->isDemo()? 24 : 0, Common::Point(90, 35)); + else if (_pCount <= 210) + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 1, Common::Point(65, 35)); + else if (_pCount <= 272) + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 2, Common::Point(96, 45)); + else if (_pCount <= 334) + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 3, Common::Point(68, 54)); + else if (_pCount <= 396) + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(103, 54)); + else if (_pCount <= 458) { + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 5, Common::Point(8, 5)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 12, Common::Point(88, 55)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 6, Common::Point(194, 98)); + } else if (_pCount <= 520) { + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 7, Common::Point(32, 13)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 8, Common::Point(162, 80)); + } else if (_pCount <= 580) { + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 9, Common::Point(18, 15)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 10, Common::Point(164, 81)); + } else + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 11, Common::Point(106, 55)); +} + +void Opening::doCreditDemo() { + if (_pCount < 15) + return; + + if (_pCount <= 75) + _vm->_buffer2.plotImage(_vm->_objectsTable[0], _vm->isDemo()? 24 : 0, Common::Point(90, 35)); + else if (_pCount <= 210) + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 25, Common::Point(82, 35)); + else if (_pCount <= 272) { + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 23, Common::Point(77, 20)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(50, 35)); + } else if (_pCount <= 334) { + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 16, Common::Point(200, 70)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(170, 85)); + } else if (_pCount <= 396) { + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 15, Common::Point(65, 15)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 2, Common::Point(30, 30)); + } else if (_pCount <= 458) { + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 19, Common::Point(123, 40)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 10, Common::Point(115, 55)); + } else if (_pCount <= 520) { + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 18, Common::Point(50, 15)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 9, Common::Point(40, 30)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 0, Common::Point(40, 55)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 20, Common::Point(198, 95)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 3, Common::Point(160, 110)); + } else if (_pCount <= 580) { + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 21, Common::Point(40, 10)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 6, Common::Point(20, 25)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 22, Common::Point(145, 50)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 7, Common::Point(125, 65)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 12, Common::Point(207, 90)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 5, Common::Point(200, 105)); + } else { + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 11, Common::Point(125, 30)); + _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(115, 45)); + } +} + +void Opening::scrollTitle() { + _vm->copyBF1BF2(); + _vm->_newRects.clear(); + if (_vm->isDemo()) + doCreditDemo(); + else + doCredit(); + _vm->copyRects(); + _vm->copyBF2Vid(); +} + +void Opening::doTitle() { + Screen &screen = *_vm->_screen; + + screen.setDisplayScan(); + + screen.forceFadeOut(); + _vm->_events->hideCursor(); + + if (!_vm->isDemo()) { + _vm->_sound->loadSoundTable(0, 98, 30); + _vm->_sound->loadSoundTable(1, 98, 8); + + _vm->_files->_setPaletteFlag = false; + _vm->_files->loadScreen(0, 3); + + _vm->_buffer2.copyFrom(*_vm->_screen); + _vm->_buffer1.copyFrom(*_vm->_screen); + screen.forceFadeIn(); + _vm->_sound->playSound(1); + + // WORKAROUND: This delay has been added to replace original game delay that + // came from loading resources, since nowadays it would be too fast to be visible + // nowadays to be visible. + _vm->_events->_vbCount = 70; + while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0) + _vm->_events->pollEventsAndWait(); + if (_vm->shouldQuit()) + return; + + Resource *spriteData = _vm->_files->loadFile(0, 2); + _vm->_objectsTable[0] = new SpriteResource(_vm, spriteData); + delete spriteData; + + _vm->_files->_setPaletteFlag = false; + _vm->_files->loadScreen(0, 4); + _vm->_sound->playSound(1); + + _vm->_buffer2.copyFrom(*_vm->_screen); + _vm->_buffer1.copyFrom(*_vm->_screen); + + const int COUNTDOWN[6] = { 2, 0x80, 1, 0x7d, 0, 0x87 }; + for (_pCount = 0; _pCount < 3 && !_vm->shouldQuit(); ++_pCount) { + _vm->_buffer2.blitFrom(_vm->_buffer1); + int id = COUNTDOWN[_pCount * 2]; + int xp = COUNTDOWN[_pCount * 2 + 1]; + _vm->_buffer2.plotImage(_vm->_objectsTable[0], id, Common::Point(xp, 71)); + _vm->_buffer2.copyTo(_vm->_screen); + + _vm->_sound->playSound(1); + _vm->_events->_vbCount = 70; + while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0 && !_skipStart) { + _vm->_events->pollEventsAndWait(); + if (_vm->_events->_rightButton) + _skipStart = true; + } + } + if (_vm->shouldQuit()) + return; + + _vm->_sound->stopSound(); + _vm->_sound->playSound(0); + screen.forceFadeOut(); + _vm->_events->_vbCount = 100; + while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0) + _vm->_events->pollEventsAndWait(); + if (_vm->shouldQuit()) + return; + + _vm->_sound->freeSounds(); + delete _vm->_objectsTable[0]; + _vm->_objectsTable[0] = nullptr; + + _vm->_files->_setPaletteFlag = false; + _vm->_files->loadScreen(0, 5); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); + screen.forceFadeIn(); + _vm->_midi->newMusic(1, 0); + _vm->_events->_vbCount = 700; + while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0) && !_vm->_events->isKeyMousePressed()) { + _vm->_events->pollEventsAndWait(); + } + + if (_vm->_events->_rightButton) { + _skipStart = true; + _vm->_room->clearRoom(); + _vm->_events->showCursor(); + return; + } + + _vm->_midi->newMusic(1, 1); + _vm->_midi->setLoop(false); + _vm->_events->zeroKeys(); + } + + _vm->_buffer1.create(_vm->_screen->w + TILE_WIDTH, _vm->_screen->h); + _vm->_room->loadRoom(0); + screen.clearScreen(); + screen.setBufferScan(); + _vm->_scrollRow = _vm->_scrollCol = 0; + _vm->_scrollX = _vm->_scrollY = 0; + _vm->_player->_rawPlayer = Common::Point(0, 0); + screen.forceFadeOut(); + _vm->_room->buildScreen(); + _vm->copyBF2Vid(); + screen.forceFadeIn(); + _vm->_oldRects.clear(); + _vm->_newRects.clear(); + _vm->_events->clearEvents(); + _vm->_player->_scrollAmount = 1; + _pCount = 0; + + while (!_vm->shouldQuit()) { + if (_vm->_events->isKeyMousePressed()) { + if (_vm->_events->_rightButton) + _skipStart = true; + _vm->_room->clearRoom(); + _vm->_events->showCursor(); + return; + } + + _vm->_events->_vbCount = 4; + if (_vm->_scrollCol + screen._vWindowWidth != _vm->_room->_playFieldWidth) { + _vm->_scrollX += _vm->_player->_scrollAmount; + + while (_vm->_scrollX >= TILE_WIDTH) { + _vm->_scrollX -= TILE_WIDTH; + ++_vm->_scrollCol; + + _vm->_buffer1.moveBufferLeft(); + _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide); + } + scrollTitle(); + ++_pCount; + + while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0)) { + _vm->_events->pollEventsAndWait(); + } + continue; + } + + _vm->_events->_vbCount = 120; + while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0)) + _vm->_events->pollEventsAndWait(); + + while (!_vm->shouldQuit()) { + _pCount = 0; + _vm->_events->_vbCount = 3; + if (_vm->_scrollRow + screen._vWindowHeight >= _vm->_room->_playFieldHeight) { + _vm->_room->clearRoom(); + _vm->_events->showCursor(); + return; + } + + _vm->_scrollY = _vm->_scrollY + _vm->_player->_scrollAmount; + + while (_vm->_scrollY >= TILE_HEIGHT && !_vm->shouldQuit()) { + _vm->_scrollY -= TILE_HEIGHT; + ++_vm->_scrollRow; + _vm->_buffer1.moveBufferUp(); + + // WORKAROUND: the original was using screen._vWindowBytesWide * screen._vWindowLinesTall + _vm->_room->buildRow(_vm->_scrollRow + screen._vWindowHeight, screen._vWindowLinesTall); + + if (_vm->_scrollRow + screen._vWindowHeight >= _vm->_room->_playFieldHeight) { + _vm->_room->clearRoom(); + _vm->_events->showCursor(); + return; + } + } + scrollTitle(); + while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0)) + _vm->_events->pollEventsAndWait(); + } + } +} + +void Opening::doTent() { + int step = 0; + _vm->_screen->setDisplayScan(); + _vm->_screen->forceFadeOut(); + _vm->_events->hideCursor(); + _vm->_sound->loadSoundTable(0, 98, 39); + _vm->_sound->loadSoundTable(1, 98, 14); + _vm->_sound->loadSoundTable(2, 98, 15); + _vm->_sound->loadSoundTable(3, 98, 16); + _vm->_sound->loadSoundTable(4, 98, 31, 2); + _vm->_sound->loadSoundTable(5, 98, 52, 2); + _vm->_sound->playSound(0); + + _vm->_files->_setPaletteFlag = false; + _vm->_files->loadScreen(2, 0); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); + _vm->_screen->forceFadeIn(); + + _vm->_video->setVideo(_vm->_screen, Common::Point(126, 73), FileIdent(2, 1), 10); + int previousFrame = -1; + while (!_vm->shouldQuit() && !_vm->_video->_videoEnd) { + _vm->_video->playVideo(); + if (previousFrame != _vm->_video->_videoFrame) { + previousFrame = _vm->_video->_videoFrame; + + if ((_vm->_video->_videoFrame == 32) || (_vm->_video->_videoFrame == 34)) + _vm->_sound->playSound(4); + else if (_vm->_video->_videoFrame == 36) { + if (step != 2) { + _vm->_sound->playSound(2); + step = 2; + } + } else if (_vm->_video->_videoFrame == 18) { + if (step != 1) { + _vm->_midi->newMusic(73, 1); + _vm->_midi->newMusic(11, 0); + step = 1; + _vm->_sound->playSound(1); + } + } + } + _vm->_events->pollEventsAndWait(); + } + + _vm->_sound->playSound(5); + _vm->_video->setVideo(_vm->_screen, Common::Point(43, 11), FileIdent(2, 2), 10); + previousFrame = -1; + while (!_vm->shouldQuit() && !_vm->_video->_videoEnd) { + _vm->_video->playVideo(); + if (previousFrame != _vm->_video->_videoFrame) { + previousFrame = _vm->_video->_videoFrame; + if (_vm->_video->_videoFrame == 26) { + _vm->_sound->playSound(5); + } else if (_vm->_video->_videoFrame == 15) { + if (step !=3) { + _vm->_sound->playSound(3); + step = 3; + } + } + } + _vm->_events->pollEventsAndWait(); + } + + _vm->_events->_vbCount = 200; + while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0) + _vm->_events->pollEventsAndWait(); + + _vm->_events->showCursor(); + _vm->_midi->newMusic(11, 1); + _vm->_sound->_soundTable.clear(); + + _vm->establishCenter(0, 4); +} + +/*------------------------------------------------------------------------*/ + +Plane::Plane(AmazonEngine *vm) : PannedScene(vm) { + _pCount = 0; + _planeCount = 0; + _propCount = 0; +} + + +void Plane::doFlyCell() { + SpriteResource *sprites = _vm->_objectsTable[15]; + + if (_pCount <= 40) { + _vm->_buffer2.plotImage(sprites, 3, Common::Point(70, 74)); + } else if (_pCount <= 80) { + _vm->_buffer2.plotImage(sprites, 6, Common::Point(70, 74)); + } else if (_pCount <= 120) { + _vm->_buffer2.plotImage(sprites, 2, Common::Point(50, 76)); + } else if (_pCount <= 160) { + _vm->_buffer2.plotImage(sprites, 14, Common::Point(63, 78)); + } else if (_pCount <= 200) { + _vm->_buffer2.plotImage(sprites, 5, Common::Point(86, 74)); + } else if (_pCount <= 240) { + _vm->_buffer2.plotImage(sprites, 0, Common::Point(103, 76)); + } else if (_pCount <= 280) { + _vm->_buffer2.plotImage(sprites, 4, Common::Point(119, 77)); + } else { + _vm->_buffer2.plotImage(sprites, 1, Common::Point(111, 77)); + } + + if (_planeCount == 11 || _planeCount == 12) + ++_position.y; + else if (_planeCount >= 28) + --_position.y; + + _vm->_buffer2.plotImage(sprites, 7, _position); + _vm->_buffer2.plotImage(sprites, 8 + _propCount, Common::Point( + _position.x + 99, _position.y + 10)); + _vm->_buffer2.plotImage(sprites, 11 + _propCount, Common::Point( + _position.x + 104, _position.y + 18)); + + if (++_planeCount >= 30) + _planeCount = 0; + if (++_propCount >= 3) + _propCount = 0; + + ++_xCount; + if (_xCount == 1) + ++_position.x; + else + _xCount = 0; +} + +void Plane::doFallCell() { + if (_vm->_scaleI <= 20) + return; + + SpriteFrame *frame = _vm->_objectsTable[20]->getFrame(_planeCount / 6); + Common::Rect r(115, 11, 115 + _vm->_screen->_scaleTable1[frame->w], + 11 + _vm->_screen->_scaleTable1[frame->h]); + _vm->_buffer2.sPlotF(frame, r); + + _vm->_scaleI -= 3; + _vm->_scale = _vm->_scaleI; + _vm->_screen->setScaleTable(_vm->_scale); + ++_xCount; + if (_xCount == 5) + return; + _xCount = 0; + if (_planeCount == 18) + _planeCount = 0; + else + _planeCount += 6; +} + +void Plane::scrollFly() { + _vm->copyBF1BF2(); + _vm->_newRects.clear(); + doFlyCell(); + _vm->copyRects(); + _vm->copyBF2Vid(); +} + +void Plane::scrollFall() { + _vm->copyBF1BF2(); + _vm->_newRects.clear(); + doFallCell(); + _vm->copyRects(); + _vm->copyBF2Vid(); +} + +void Plane::mWhileFly() { + Screen &screen = *_vm->_screen; + Player &player = *_vm->_player; + EventsManager &events = *_vm->_events; + + events.hideCursor(); + screen.clearScreen(); + screen.setBufferScan(); + screen.fadeOut(); + _vm->_scrollX = 0; + + _vm->_room->buildScreen(); + _vm->copyBF2Vid(); + screen.fadeIn(); + _vm->_oldRects.clear(); + _vm->_newRects.clear(); + _vm->_events->clearEvents(); + + _vm->_scrollRow = _vm->_scrollCol = 0; + _vm->_scrollX = _vm->_scrollY = 0; + player._rawPlayer = Common::Point(0, 0); + player._scrollAmount = 1; + + _pCount = 0; + _planeCount = 0; + _propCount = 0; + _xCount = 0; + _position = Common::Point(20, 29); + + while (!_vm->shouldQuit() && !events.isKeyMousePressed() && + ((_vm->_scrollCol + screen._vWindowWidth) != _vm->_room->_playFieldWidth)) { + events._vbCount = 4; + _vm->_scrollX += player._scrollAmount; + + while (_vm->_scrollX >= TILE_WIDTH) { + _vm->_scrollX -= TILE_WIDTH; + ++_vm->_scrollCol; + + _vm->_buffer1.moveBufferLeft(); + _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide); + } + + scrollFly(); + ++_pCount; + + while (!_vm->shouldQuit() && events._vbCount > 0) { + _vm->_sound->playSound(0); + events.pollEventsAndWait(); + } + } + + events.showCursor(); +} + +void Plane::mWhileFall() { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + + events.hideCursor(); + screen.clearScreen(); + screen.setBufferScan(); + screen.fadeOut(); + _vm->_scrollX = 0; + + _vm->_room->buildScreen(); + _vm->copyBF2Vid(); + screen.fadeIn(); + _vm->_oldRects.clear(); + _vm->_newRects.clear(); + _vm->_events->clearEvents(); + + _vm->_scrollRow = _vm->_scrollCol = 0; + _vm->_scrollX = _vm->_scrollY = 0; + _vm->_player->_scrollAmount = 3; + _vm->_scaleI = 255; + + _xCount = 0; + _planeCount = 0; + + while (!_vm->shouldQuit() && !events.isKeyMousePressed() && + (_vm->_scrollCol + screen._vWindowWidth != _vm->_room->_playFieldWidth)) { + events._vbCount = 4; + _vm->_scrollX += _vm->_player->_scrollAmount; + + while (_vm->_scrollX >= TILE_WIDTH) { + _vm->_scrollX -= TILE_WIDTH; + ++_vm->_scrollCol; + + _vm->_buffer1.moveBufferLeft(); + _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide); + } + + scrollFall(); + + while (!_vm->shouldQuit() && events._vbCount > 0) { + events.pollEventsAndWait(); + } + } + + events.showCursor(); +} + +/*------------------------------------------------------------------------*/ + +Jungle::Jungle(AmazonEngine *vm) : CampScene(vm) { + for (int i = 0; i < JUNGLE_SIZE; ++i) { + _jCnt[i] = _jungleX[i] = -1; + } +} + +void Jungle::jungleMove() { + const static int jungleY[3] = { 27, 30, 29 }; + int count = 1; + int frameOffset = 0; + + if (!_vm->_timers[0]._flag) { + ++_vm->_timers[0]._flag; + _vm->_scrollX += _vm->_player->_scrollAmount; + + for (int i = 0; i < 3; ++i) { + int newJCnt = (_jCnt[i] + 1) % 8; + _jCnt[i] = newJCnt; + _jungleX[i] += 5; + } + + frameOffset = 4; + count = (_vm->_allenFlag != 1) ? 2 : 3; + } + + for (int i = 0; i < count; ++i) { + ImageEntry ie; + ie._flags = IMGFLAG_UNSCALED; + ie._spritesPtr = _vm->_objectsTable[24]; + ie._frameNumber = _jCnt[i] + frameOffset; + ie._position = Common::Point(_jungleX[i], jungleY[i]); + ie._offsetY = jungleY[i]; + + _vm->_images.addToList(ie); + frameOffset += 8; + } +} + +void Jungle::initJWalk2() { + const int JUNGLE1OBJ[7][4] = { + { 2, 470, 0, 20 }, + { 0, 290, 0, 50 }, + { 1, 210, 0, 40 }, + { 0, 500, 0, 30 }, + { 1, 550, 0, 20 }, + { 0, 580, 0, 60 }, + { 1, 650, 0, 30 } + }; + + Screen &screen = *_vm->_screen; + screen.fadeOut(); + _vm->_events->hideCursor(); + screen.clearScreen(); + _vm->_buffer2.clearBuffer(); + screen.setBufferScan(); + + _vm->_scrollX = _vm->_scrollY; + _vm->_scrollCol = _vm->_scrollRow; + _vm->_room->buildScreen(); + _vm->copyBF2Vid(); + screen.fadeIn(); + _vm->_events->clearEvents(); + + _xCount = 2; + _vm->_player->_scrollAmount = 5; + _xTrack = -10; + _yTrack = _zTrack = 0; + _xCam = 480; + _yCam = 0; + _zCam = 80; + + _vm->_timers[24]._timer = 1; + _vm->_timers[24]._initTm = 1; + ++_vm->_timers[24]._flag; + + _pNumObj = 7; + for (int i = 0; i < _pNumObj; i++) { + _pan[i]._pObject = _vm->_objectsTable[24]; + _pan[i]._pImgNum = JUNGLE1OBJ[i][0]; + _pan[i]._pObjX = JUNGLE1OBJ[i][1]; + _pan[i]._pObjY = JUNGLE1OBJ[i][2]; + _pan[i]._pObjZ = JUNGLE1OBJ[i][3]; + _pan[i]._pObjXl = _pan[i]._pObjYl = 0; + } + + _jCnt[0] = 0; + _jCnt[1] = 3; + _jCnt[2] = 5; + + _jungleX[0] = 50; + _jungleX[1] = 16; + _jungleX[2] = 93; +} + +void Jungle::mWhileJWalk() { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + Player &player = *_vm->_player; + + static const int JUNGLE_OBJ[7][4] = { + { 2, 77, 0, 40 }, + { 0, 290, 0, 50 }, + { 1, 210, 0, 70 }, + { 0, 50, 0, 30 }, + { 1, 70, 0, 20 }, + { 0, -280, 0, 60 }, + { 1, -150, 0, 30 }, + }; + + screen.fadeOut(); + events.hideCursor(); + screen.clearScreen(); + _vm->_buffer2.clearBuffer(); + screen.setBufferScan(); + _vm->_scrollX = 0; + + // Build the initial jungle scene and fade it in + _vm->_room->buildScreen(); + _vm->copyBF2Vid(); + screen.fadeIn(); + + // Set up the player to walk horizontally + player._xFlag = 1; + player._yFlag = 0; + player._moveTo.x = 160; + player._playerMove = true; + + _xCount = 2; + _xTrack = 10; + _yTrack = _zTrack = 0; + _xCam = 480; + _yCam = 0; + _zCam = 80; + + TimerEntry *te = &_vm->_timers[24]; + te->_initTm = te->_timer = 1; + te->_flag++; + + _pNumObj = 7; + for (int i = 0; i < _pNumObj; i++) { + _pan[i]._pObject = _vm->_objectsTable[24]; + _pan[i]._pImgNum = JUNGLE_OBJ[i][0]; + _pan[i]._pObjX = JUNGLE_OBJ[i][1]; + _pan[i]._pObjY = JUNGLE_OBJ[i][2]; + _pan[i]._pObjZ = JUNGLE_OBJ[i][3]; + _pan[i]._pObjXl = _pan[i]._pObjYl = 0; + } + + while (!_vm->shouldQuit() && !events.isKeyMousePressed() && (player._xFlag != 2)) { + _vm->_images.clear(); + events._vbCount = 6; + + _pan[0]._pImgNum = _xCount; + if (_xCount == 2) + ++_xCount; + else + --_xCount; + + player.checkMove(); + player.checkScroll(); + pan(); + scrollJWalk(); + + while (!_vm->shouldQuit() && events._vbCount > 0) { + events.pollEventsAndWait(); + } + } + + _vm->_images.clear(); + events.showCursor(); +} + +void Jungle::mWhileJWalk2() { + Screen &screen = *_vm->_screen; + + initJWalk2(); + + while (!_vm->shouldQuit() && !_vm->_events->isKeyMousePressed() && + (_vm->_scrollCol + screen._vWindowWidth) != _vm->_room->_playFieldWidth) { + _vm->_images.clear(); + _vm->_events->_vbCount = 6; + _pan[0]._pImgNum = _xCount; + + jungleMove(); + while (_vm->_scrollX >= TILE_WIDTH) { + _vm->_scrollX -= TILE_WIDTH; + ++_vm->_scrollCol; + _vm->_buffer1.moveBufferLeft(); + _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide); + } + + if (_xCount == 2) + ++_xCount; + else + --_xCount; + + pan(); + scrollJWalk(); + + while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0) { + _vm->_events->pollEventsAndWait(); + } + } + + _vm->_events->showCursor(); +} + +void Jungle::scrollJWalk() { + _vm->copyBF1BF2(); + _vm->_newRects.clear(); + _vm->plotList(); + _vm->copyRects(); + _vm->copyBF2Vid(); +} + +/*------------------------------------------------------------------------*/ + +Guard::Guard(AmazonEngine *vm) : PannedScene(vm) { + _guardCel = 0; + _gCode1 = _gCode2 = 0; + _xMid = _yMid = 0; +} + +void Guard::setVerticalCode() { + Screen &screen = *_vm->_screen; + + _gCode1 = 0; + _gCode2 = 0; + if (_topLeft.x < screen._orgX1) + _gCode1 |= 8; + else if (_topLeft.x == screen._orgX1) { + _gCode1 |= 8; + _gCode1 |= 2; + } else + _gCode1 |= 2; + + if (_bottomRight.x < screen._orgX1) + _gCode2 |= 8; + else if (_bottomRight.x == screen._orgX1) { + _gCode2 |= 8; + _gCode2 |= 2; + } else + _gCode2 |= 2; + + if (_topLeft.y < screen._orgY1) + _gCode1 |= 4; + else if (_topLeft.y > screen._orgY2) + _gCode1 |= 1; + + if (_bottomRight.y < screen._orgY1) + _gCode2 |= 4; + else if (_bottomRight.y > screen._orgY2) + _gCode2 |= 1; +} + +void Guard::setHorizontalCode() { + Screen &screen = *_vm->_screen; + + _gCode1 = 0; + _gCode2 = 0; + + if (_topLeft.y < screen._orgY1) + _gCode1 |= 4; + else if (_topLeft.x == screen._orgX1) { + _gCode1 |= 4; + _gCode1 |= 1; + } else + _gCode1 |= 1; + + if (_bottomRight.y < screen._orgY1) + _gCode2 |= 4; + else if (_bottomRight.x == screen._orgX1) { + _gCode2 |= 4; + _gCode2 |= 1; + } else + _gCode2 |= 1; + + if (_topLeft.x < screen._orgX1) + _gCode1 |= 8; + else if (_topLeft.x > screen._orgX2) + _gCode1 |= 2; + + if (_bottomRight.x < screen._orgX1) + _gCode2 |= 8; + else if (_bottomRight.x > screen._orgX2) + _gCode2 |= 2; +} + +void Guard::chkVLine() { + if (_position.x > _vm->_player->_rawPlayer.x) { + _topLeft = _vm->_player->_rawPlayer; + _bottomRight = _position; + } else { + _topLeft = _position; + _bottomRight = _vm->_player->_rawPlayer; + } + + if (_vm->_screen->_orgY1 > _vm->_screen->_orgY2) + SWAP(_vm->_screen->_orgY1, _vm->_screen->_orgY2); + + for (;;) { + setVerticalCode(); + int code = _gCode1 | _gCode2; + if (code == 10) { + _vm->_guardFind = 0; + return; + } + + int code2 = _gCode1 & _gCode2; + code2 &= 5; + if (((code & 10) == 8) || ((code & 10) == 2) || (code2 != 0)) + return; + + int midX = (_topLeft.x + _bottomRight.x) / 2; + int midY = (_topLeft.y + _bottomRight.y) / 2; + + if (midX < _vm->_screen->_orgX1) { + if ((midX == _topLeft.x) && (midY == _topLeft.y)) + return; + + _topLeft.x = midX; + _topLeft.y = midY; + } else { + if ((midX == _bottomRight.x) && (midY == _bottomRight.y)) + return; + + _bottomRight.x = midX; + _bottomRight.y = midY; + } + } +} + +void Guard::chkHLine() { + if (_position.y > _vm->_player->_rawPlayer.y) { + _topLeft = _vm->_player->_rawPlayer; + _bottomRight = _position; + } else { + _topLeft = _position; + _bottomRight = _vm->_player->_rawPlayer; + } + + if (_vm->_screen->_orgX1 > _vm->_screen->_orgX2) + SWAP(_vm->_screen->_orgX1, _vm->_screen->_orgX2); + + while (true) { + setHorizontalCode(); + int code = _gCode1 | _gCode2; + if (code == 5) { + _vm->_guardFind = 0; + return; + } + + int code2 = _gCode1 & _gCode2; + code2 &= 10; + if (((code & 5) == 4) || ((code & 5) == 1) || (code2 != 0)) + return; + + int midX = (_topLeft.x + _bottomRight.x) / 2; + int midY = (_topLeft.y + _bottomRight.y) / 2; + + if (midY < _vm->_screen->_orgY1) { + if ((midX == _topLeft.x) && (midY == _topLeft.y)) + return; + + _topLeft.x = midX; + _topLeft.y = midY; + } else { + if ((midX == _bottomRight.x) && (midY == _bottomRight.y)) + return; + + _bottomRight.x = midX; + _bottomRight.y = midY; + } + } +} + +void Guard::guardSee() { + Screen &screen = *_vm->_screen; + int tmpY = (_vm->_scrollRow << 4) + _vm->_scrollY; + _vm->_flags[140] = 0; + if (tmpY > _position.y) + return; + + tmpY += screen._vWindowLinesTall; + tmpY -= 11; + + if (tmpY < _position.y) + return; + + _vm->_guardFind = 1; + _vm->_flags[140] = 1; + + for (uint16 idx = 0; idx < _vm->_room->_plotter._walls.size(); idx++) { + screen._orgX1 = _vm->_room->_plotter._walls[idx].left; + screen._orgY1 = _vm->_room->_plotter._walls[idx].top; + screen._orgX2 = _vm->_room->_plotter._walls[idx].right; + screen._orgY2 = _vm->_room->_plotter._walls[idx].bottom; + if (screen._orgX1 == screen._orgX2) { + chkVLine(); + if (_vm->_guardFind == 0) + return; + } else if (screen._orgY1 == screen._orgY2) { + chkHLine(); + if (_vm->_guardFind == 0) + return; + } + } +} + +void Guard::setGuardFrame() { + ImageEntry ie; + ie._flags = IMGFLAG_UNSCALED; + + if (_vm->_guardLocation == 4) + ie._flags |= IMGFLAG_BACKWARDS; + ie._spritesPtr = _vm->_objectsTable[37]; + ie._frameNumber = _guardCel; + ie._position = _position; + ie._offsetY = 10; + _vm->_images.addToList(ie); +} + +void Guard::doGuard() { + // Skip the code dealing with the guard on the boat (chapter 8) + // if the cheat mode is activated + if (_vm->_cheatFl) + return; + + if (_vm->_timers[8]._flag) { + setGuardFrame(); + return; + } + + ++_vm->_timers[8]._flag; + ++_guardCel; + int curCel = _guardCel; + + switch (_vm->_guardLocation) { + case 1: + // Guard walking down + if (curCel <= 8 || curCel > 13) + _guardCel = curCel = 8; + + _position.y += _vm->_player->_walkOffDown[curCel - 8]; + guardSee(); + if (_position.y >= 272) { + _position.y = 272; + _vm->_guardLocation = 2; + } + break; + case 2: + // Guard walking left + if (curCel <= 43 || curCel > 48) + _guardCel = curCel = 43; + + _position.x -= _vm->_player->_walkOffLeft[curCel - 43]; + guardSee(); + if (_position.x <= 56) { + _position.x = 56; + _vm->_guardLocation = 3; + } + break; + case 3: + // Guard walking up + if (curCel <= 0 || curCel > 5) + _guardCel = curCel = 0; + + _position.y -= _vm->_player->_walkOffUp[curCel]; + guardSee(); + if (_position.y <= 89) { + _position.y = 89; + _vm->_guardLocation = 4; + if (_vm->_flags[121] == 1) + _vm->_guardLocation = 5; + } + break; + default: + // Guard walking right + if (curCel <= 43 || curCel > 48) + _guardCel = curCel = 43; + + _position.x += _vm->_player->_walkOffRight[curCel - 43]; + guardSee(); + if (_position.x >= 127) { + _position.x = 127; + _vm->_guardLocation = 1; + } + break; + } + + setGuardFrame(); +} + +void Guard::setPosition(const Common::Point &pt) { + _position = pt; +} + +/*------------------------------------------------------------------------*/ + +Cast::Cast(AmazonEngine *vm) : PannedScene(vm) { +} + +void Cast::doCast(int param1) { + Screen &screen = *_vm->_screen; + + screen.setDisplayScan(); + _vm->_events->hideCursor(); + screen.forceFadeOut(); + screen._clipHeight = 173; + screen.clearScreen(); + _vm->_chapter = 16; + _vm->tileScreen(); + _vm->updateSummary(param1); + screen.setPanel(3); + _vm->_chapter = 14; + + Resource *spriteData = _vm->_files->loadFile(91, 0); + _vm->_objectsTable[0] = new SpriteResource(_vm, spriteData); + delete spriteData; + spriteData = _vm->_files->loadFile(91, 1); + _vm->_objectsTable[1] = new SpriteResource(_vm, spriteData); + delete spriteData; + + _vm->_files->_setPaletteFlag = false; + _vm->_files->loadScreen(58, 1); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); + + _xTrack = 0; + _yTrack = -6; + _zTrack = 0; + _xCam = _yCam = 0; + _zCam = 60; + + _vm->_timers[24]._timer = 1; + _vm->_timers[24]._initTm = 1; + ++_vm->_timers[24]._flag; + + _pNumObj = 26; + for (int i = 0; i < _pNumObj; i++) { + _pan[i]._pObject = _vm->_objectsTable[0]; + _pan[i]._pImgNum = CAST_END_OBJ[i][0]; + _pan[i]._pObjX = CAST_END_OBJ[i][1]; + _pan[i]._pObjY = CAST_END_OBJ[i][2]; + _pan[i]._pObjZ = CAST_END_OBJ[i][3]; + _pan[i]._pObjXl = _pan[i]._pObjYl = 0; + } + + _pNumObj = 4; + for (int i = 0; i < _pNumObj; i++) { + _pan[26 + i]._pObject = _vm->_objectsTable[1]; + _pan[26 + i]._pImgNum = CAST_END_OBJ1[i][0]; + _pan[26 + i]._pObjX = CAST_END_OBJ1[i][1]; + _pan[26 + i]._pObjY = CAST_END_OBJ1[i][2]; + _pan[26 + i]._pObjZ = CAST_END_OBJ1[i][3]; + _pan[26 + i]._pObjXl = _pan[26 + i]._pObjYl = 0; + } + + _vm->_oldRects.clear(); + _vm->_newRects.clear(); + _vm->_numAnimTimers = 0; + + _vm->_midi->newMusic(58, 0); + screen.forceFadeIn(); + + while (!_vm->shouldQuit()) { + _vm->_images.clear(); + pan(); + _vm->_buffer2.blitFrom(_vm->_buffer1); + _vm->_newRects.clear(); + _vm->plotList(); + _vm->copyBlocks(); + + _vm->_events->pollEvents(); + if (_vm->_events->isKeyMousePressed()) + break; + + if (_yCam < -7550) { + _vm->_events->_vbCount = 50; + + while (!_vm->shouldQuit() && !_vm->_events->isKeyMousePressed() && _vm->_events->_vbCount > 0) { + _vm->_events->pollEventsAndWait(); + } + + while (!_vm->shouldQuit() && !_vm->_midi->checkMidiDone()) + _vm->_events->pollEventsAndWait(); + + break; + } + } + + _vm->_midi->newMusic(58, 1); + _vm->_events->showCursor(); + + _vm->freeCells(); + _vm->_oldRects.clear(); + _vm->_newRects.clear(); + _vm->_numAnimTimers = 0; + _vm->_images.clear(); + screen.forceFadeOut(); + + _vm->quitGame(); + _vm->_events->pollEvents(); +} + +/*------------------------------------------------------------------------*/ + +River::River(AmazonEngine *vm) : PannedScene(vm) { + _chickenOutFl = false; + _rScrollRow = 0; + _rScrollCol = 0; + _rScrollX = 0; + _rScrollY = 0; + _mapOffset = 0; + _screenVertX = 0; + _saveRiver = false; + _deathFlag = false; + _deathCount = 0; + _oldScrollCol = 0; + _maxHits = 0; + _mapPtr = nullptr; + _canoeMoveCount = 0; + _canoeVXPos = 0; + _canoeFrame = 0; + _canoeDir = 0; + _canoeLane = 0; + _canoeYPos = 0; + _hitCount = 0; + _riverIndex = 0; + _topList = _botList = nullptr; + _deathType = 0; + _hitSafe = 0; +} + +void River::setRiverPan() { + int delta = (_vm->_scrollCol * 16) + _vm->_scrollX; + + _xTrack = 9; + _yTrack = _zTrack = 0; + _xCam = 160; + _yCam = 0; + _zCam = 80; + + _vm->_timers[24]._timer = 1; + _vm->_timers[24]._initTm = 1; + ++_vm->_timers[24]._flag; + + _pNumObj = 23; + for (int i = 0; i < _pNumObj; i++) { + _pan[i]._pObject = _vm->_objectsTable[45]; + _pan[i]._pImgNum = RIVER1OBJ[i][0]; + _pan[i]._pObjX = RIVER1OBJ[i][1] + delta; + _pan[i]._pObjY = RIVER1OBJ[i][2]; + _pan[i]._pObjZ = RIVER1OBJ[i][3]; + _pan[i]._pObjXl = _pan[i]._pObjYl = 0; + } +} + +void River::initRiver() { + static const int RIVERVXTBL[3] = { 6719, 7039, 8319 }; + Screen &screen = *_vm->_screen; + + _vm->_events->centerMousePos(); + _vm->_events->restrictMouse(); + screen.setDisplayScan(); + screen.clearScreen(); + screen.savePalette(); + screen.forceFadeOut(); + + _vm->_files->_setPaletteFlag = false; + _vm->_files->loadScreen(95, 4); + _vm->_buffer2.blitFrom(*_vm->_screen); + + screen.restorePalette(); + screen.setBufferScan(); + _vm->_destIn = &_vm->_buffer2; + _vm->_room->roomMenu(); + + if (_saveRiver) { + // Restoring a savegame, so set properties from saved fields + _vm->_scrollRow = _rScrollRow; + _vm->_scrollCol = _rScrollCol; + _vm->_scrollX = _rScrollX; + _vm->_scrollY = _rScrollY; + } else { + // Set initial scene state + _vm->_scrollRow = 0; + _vm->_scrollCol = 140; + _vm->_scrollX = 0; + _vm->_scrollY = 0; + } + + _vm->_room->buildScreen(); + _vm->copyBF2Vid(); + screen.forceFadeIn(); + + if (!_saveRiver) { + // Reset draw rects + _vm->_oldRects.clear(); + _vm->_newRects.clear(); + _vm->_events->clearEvents(); + + } + + _vm->_player->_scrollAmount = 2; + setRiverPan(); + _vm->_timers[3]._timer = 1; + _vm->_timers[3]._initTm = 1; + ++_vm->_timers[3]._flag; + + _canoeFrame = 0; + _mapPtr = (const byte *)MAPTBL[_vm->_riverFlag] + 1; + if (_saveRiver) { + _mapPtr--; + _mapPtr += _mapOffset; + } else { + _screenVertX = RIVERVXTBL[_vm->_riverFlag] - 320; + _canoeLane = 3; + _hitCount = 0; + _hitSafe = 0; + _canoeYPos = 71; + } + + _riverIndex = _vm->_riverFlag; + _topList = RIVER_OBJECTS[_riverIndex][RIVER_START]; + updateObstacles(); + riverSetPhysX(); + _canoeDir = 0; + _deathFlag = false; + _deathCount = 0; + + _vm->_timers[11]._timer = 1200; + _vm->_timers[11]._initTm = 1200; + ++_vm->_timers[11]._flag; + _vm->_timers[12]._timer = 1500; + _vm->_timers[12]._initTm = 1500; + ++_vm->_timers[12]._flag; + + _maxHits = 2 - _vm->_riverFlag; + _saveRiver = false; + + // Set font colors for drawing using font2 + Font::_fontColors[0] = 0; + Font::_fontColors[1] = 33; + Font::_fontColors[2] = 34; + Font::_fontColors[3] = 35; +} + +void River::resetPositions() { + riverSetPhysX(); + int val = (_vm->_scrollCol + 1 - _oldScrollCol) * 16; + if (val < 0) { + val |= 0x80; + } + + for (int i = 0; i < _pNumObj; i++) + _pan[i]._pObjX += val; +} + +void River::checkRiverPan() { + int val = _vm->_scrollCol * 16 + 320; + + for (int i = 0; i < _pNumObj; i++) { + if (_pan[i]._pObjX < val) + return; + } + + setRiverPan(); +} + +bool River::riverJumpTest() { + if (_vm->_scrollCol == 120 || _vm->_scrollCol == 60 || _vm->_scrollCol == 0) { + int val = *++_mapPtr; + if (val == 0xFF) + return true; + + _oldScrollCol = _vm->_scrollCol; + + if (val == 0) { + _vm->_scrollCol = 139; + _vm->_scrollX = 14; + _vm->_room->buildScreen(); + resetPositions(); + return false; + } + } else if (_vm->_scrollCol == 105) { + int val1 = _mapPtr[1]; + int val2 = _mapPtr[2]; + _mapPtr += 3; + if (_canoeLane < 3) { + if (val1 != 0) { + _deathFlag = true; + _deathCount = 300; + _deathType = val2; + } + } else { + if (val1 != 1) { + _deathFlag = true; + _deathCount = 300; + _deathType = val2; + } + _oldScrollCol = _vm->_scrollCol; + _vm->_scrollCol = 44; + _vm->_scrollX = 14; + _vm->_room->buildScreen(); + resetPositions(); + return false; + } + } + + _vm->_scrollX = 14; + --_vm->_scrollCol; + _vm->_buffer1.moveBufferRight(); + _vm->_room->buildColumn(_vm->_scrollCol, 0); + checkRiverPan(); + return false; +} + +void River::riverSound() { + if (_vm->_timers[11]._flag == 0) { + ++_vm->_timers[11]._flag; + _vm->_sound->playSound(2); + } + + if (_vm->_timers[12]._flag == 0) { + ++_vm->_timers[12]._flag; + _vm->_sound->playSound(3); + } + + if ((_xCam >= 1300) && (_xCam <= 1320)) + _vm->_sound->playSound(1); +} + +void River::moveCanoe() { + EventsManager &events = *_vm->_events; + Common::Point pt = events.calcRawMouse(); + Common::Point mousePos = events.getMousePos(); + + // Do an event polling + _vm->_canSaveLoad = true; + events.pollEvents(); + _vm->_canSaveLoad = false; + if (_vm->_room->_function == FN_CLEAR1) + return; + + if (_canoeDir) { + // Canoe movement in progress + moveCanoe2(); + } else { + if (events._leftButton && pt.y >= 140) { + if (pt.x < RMOUSE[8][0]) { + // Disk icon wasn't clicked + _vm->_scripts->printString(BAR_MESSAGE); + } else { + // Clicked on the Disc icon. Show the ScummVM menu + _vm->_room->handleCommand(9); + + if (_vm->_room->_function != FN_CLEAR1) { + _vm->_room->buildScreen(); + _vm->copyBF2Vid(); + } + } + } else if (events._leftButton && mousePos.x < 35 && mousePos.y < 12) { + // Clicked on the Skip button. So chicken out + _chickenOutFl = true; + } else if ((events._leftButton && pt.y <= _canoeYPos) || + (!events._leftButton && _vm->_player->_move == UP)) { + // Move canoe up + if (_canoeLane > 0) { + _canoeDir = -1; + _canoeMoveCount = 0; + + moveCanoe2(); + } + } else if (events._leftButton || _vm->_player->_move == DOWN) { + // Move canoe down + if (_canoeLane < 7) { + _canoeDir = 1; + _canoeMoveCount = 0; + + moveCanoe2(); + } + } + } +} + +void River::moveCanoe2() { + _canoeYPos += _canoeDir; + + if (++_canoeMoveCount == 5) { + _canoeLane += _canoeDir; + _canoeDir = 0; + } +} + +void River::updateObstacles() { + RiverStruct *cur; + for (cur = _topList; cur < RIVER_OBJECTS[_riverIndex][RIVER_END]; ++cur) { + int val = cur->_riverX + cur->_width - 1; + if (val < _screenVertX) + // Obstacle is not yet on-screen + break; + + if (cur->_riverX < (_screenVertX + 319)) { + // Object is now on-screen. So set _topList/_botList to the range + // of river obstacles that are currently visible + _topList = cur; + _botList = cur; + + while (cur < RIVER_OBJECTS[_riverIndex][RIVER_END]) { + ++cur; + val = cur->_riverX + cur->_width - 1; + if (val < _screenVertX || (cur->_riverX >= (_screenVertX + 319))) + break; + + _botList = cur; + } + + return; + } + } + + cur = _topList; + cur--; + _botList = cur; +} + +void River::riverSetPhysX() { + int xAmt = (_vm->_scrollCol * 16) + _vm->_scrollX; + + for (RiverStruct *cur = _topList; cur <= _botList; ++cur) { + cur->_xp = xAmt - (_screenVertX - cur->_riverX); + } +} + +bool River::checkRiverCollide() { + if (_hitSafe) + return false; + + _canoeVXPos = _screenVertX + 170; + + for (RiverStruct *cur = _topList; cur <= _botList; ++cur) { + if (cur->_lane < _canoeLane) + continue; + + if ((cur->_lane == _canoeLane) || (cur->_lane == _canoeLane + 1)) { + if ((cur->_riverX + cur->_width - 1) >= _canoeVXPos && + cur->_riverX < (_canoeVXPos + 124)) { + _vm->_sound->playSound(4); + return true; + } + } + } + + return false; +} + +void River::plotRiver() { + // Handle cycling through the canoe rowing frames + if (_vm->_timers[3]._flag == 0) { + ++_vm->_timers[3]._flag; + + if (_canoeFrame++ == 12) + _canoeFrame = 0; + } + + // Draw the canoe + ImageEntry ie; + ie._flags = IMGFLAG_UNSCALED; + ie._spritesPtr = _vm->_objectsTable[45]; + ie._frameNumber = _canoeFrame; + ie._position.x = (_vm->_scrollCol * 16) + _vm->_scrollX + 160; + ie._position.y = _canoeYPos - 41; + ie._offsetY = 41; + _vm->_images.addToList(ie); + + // Draw any on-screen obstacles + for (RiverStruct *cur = _topList; cur <= _botList; ++cur) { + if (cur->_id != -1) { + ie._flags = IMGFLAG_UNSCALED; + ie._spritesPtr = _vm->_objectsTable[45]; + ie._frameNumber = cur->_id; + ie._position.x = cur->_xp; + ie._position.y = (cur->_lane * 5) + 56 - cur->_offsetY; + ie._offsetY = cur->_offsetY; + _vm->_images.addToList(ie); + } + } + + // Draw the text for skipping the river + Font &font2 = _vm->_fonts._font2; + font2.drawString(_vm->_screen, "SKIP", Common::Point(5, 5)); +} + +void River::mWhileDownRiver() { + Screen &screen = *_vm->_screen; + _vm->_events->hideCursor(); + + screen.setDisplayScan(); + screen.clearScreen(); + screen.savePalette(); + if (!_vm->isDemo()) + _vm->_files->loadScreen(95, 4); + _vm->_buffer2.blitFrom(*_vm->_screen); + screen.restorePalette(); + screen.setPalette(); + screen.setBufferScan(); + + _vm->_scrollX = 0; + _vm->_room->buildScreen(); + _vm->copyBF2Vid(); + + _vm->_player->_scrollAmount = 2; + _vm->_destIn = &_vm->_buffer2; + _xTrack = -7; + _yTrack = _zTrack = 0; + _xCam = _yCam = 0; + _zCam = 80; + + _vm->_timers[24]._timer = 1; + _vm->_timers[24]._initTm = 1; + ++_vm->_timers[24]._flag; + + _pNumObj = 14; + for (int i = 0; i <_pNumObj; i++) { + _pan[i]._pObject = _vm->_objectsTable[33]; + _pan[i]._pImgNum = DOWNRIVEROBJ[i][0]; + _pan[i]._pObjX = DOWNRIVEROBJ[i][1]; + _pan[i]._pObjY = DOWNRIVEROBJ[i][2]; + _pan[i]._pObjZ = DOWNRIVEROBJ[i][3]; + _pan[i]._pObjXl = _pan[i]._pObjYl = 0; + } + + _vm->_timers[3]._timer = 200; + _vm->_timers[3]._initTm = 200; + ++_vm->_timers[3]._flag; + _vm->_timers[4]._timer = 350; + _vm->_timers[4]._initTm = 350; + ++_vm->_timers[4]._flag; + + while (!_vm->shouldQuit() && !_vm->_events->isKeyMousePressed() && + (_vm->_scrollCol + screen._vWindowWidth != _vm->_room->_playFieldWidth)) { + _vm->_images.clear(); + _vm->_events->_vbCount = 6; + + _vm->_scrollX += _vm->_player->_scrollAmount; + while (_vm->_scrollX >= TILE_WIDTH) { + _vm->_scrollX -= TILE_WIDTH; + ++_vm->_scrollCol; + _vm->_buffer1.moveBufferLeft(); + _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide); + } + + pan(); + scrollRiver(); + + if (!_vm->_timers[3]._flag) { + ++_vm->_timers[3]._flag; + _vm->_sound->playSound(1); + } else if (!_vm->_timers[4]._flag) { + ++_vm->_timers[4]._flag; + _vm->_sound->playSound(0); + } + + while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0) { + _vm->_events->pollEventsAndWait(); + } + } + + _vm->_events->showCursor(); +} + +void River::scrollRiver() { + _vm->copyBF1BF2(); + _vm->_newRects.clear(); + _vm->_buffer2.plotImage(_vm->_objectsTable[33], 0, Common::Point(66, 30)); + _vm->plotList(); + _vm->copyRects(); + _vm->copyBF2Vid(); +} + +void River::scrollRiver1() { + _vm->copyBF1BF2(); + _vm->_newRects.clear(); + plotRiver(); + _vm->plotList(); + _vm->copyRects(); + _vm->copyBF2Vid(); +} + +void River::doRiver() { + static const int RIVERDEATH[5] = { 22, 23, 24, 25, 26 }; + + initRiver(); + _vm->_events->showCursor(); + + while (!_vm->shouldQuit()) { + _vm->_events->_vbCount = 4; + + // Move the river position + _screenVertX -= _vm->_player->_scrollAmount; + + if (_vm->_scrollX == 0) { + _vm->_midi->midiRepeat(); + if (riverJumpTest()) { + _chickenOutFl = false; + return; + } + } else { + _vm->_scrollX -= _vm->_player->_scrollAmount; + } + + if (_chickenOutFl) { + _chickenOutFl = false; + return; + } + + _vm->_images.clear(); + _vm->_animation->animate(0); + + riverSound(); + pan(); + moveCanoe(); + + if (_vm->_room->_function != FN_CLEAR1) { + updateObstacles(); + riverSetPhysX(); + bool checkCollide = checkRiverCollide(); + if (_hitSafe != 0) + _hitSafe -= 2; + + if (checkCollide) { + _vm->dead(RIVERDEATH[0]); + return; + } + + if (_deathFlag) { + if (--_deathCount == 0) { + _vm->dead(RIVERDEATH[_deathType]); + return; + } + } + + // Scroll the river + scrollRiver1(); + + // Allow time for new scrolled river position to be shown + _vm->_canSaveLoad = true; + while (!_vm->shouldQuit() && _vm->_room->_function == FN_NONE && + _vm->_events->_vbCount > 0) { + _vm->_events->pollEventsAndWait(); + } + _vm->_canSaveLoad = false; + } + + if (_vm->_room->_function == FN_CLEAR1) { + _vm->_scripts->_endFlag = true; + _vm->_scripts->_returnCode = 0; + _chickenOutFl = false; + break; + } + } +} + +void River::synchronize(Common::Serializer &s) { + if (_vm->_player->_roomNumber == 45) { + if (s.isSaving()) { + // Set river properties to be saved out + _rScrollRow = _vm->_scrollRow; + _rScrollCol = _vm->_scrollCol; + _rScrollX = _vm->_scrollX; + _rScrollY = _vm->_scrollY; + _mapOffset = _mapPtr - MAPTBL[_vm->_riverFlag]; + } + + s.syncAsSint16LE(_canoeLane); + s.syncAsSint16LE(_canoeYPos); + s.syncAsSint16LE(_hitCount); + s.syncAsSint16LE(_riverIndex); + s.syncAsSint16LE(_hitSafe); + s.syncAsUint16LE(_rScrollRow); + s.syncAsUint16LE(_rScrollCol); + s.syncAsSint16LE(_rScrollX); + s.syncAsSint16LE(_rScrollY); + s.syncAsUint16LE(_mapOffset); + s.syncAsUint16LE(_screenVertX); + + _saveRiver = s.isLoading(); + } +} + +/*------------------------------------------------------------------------*/ + +Ant::Ant(AmazonEngine *vm) : AmazonManager(vm) { + _antDirection = ANT_RIGHT; + _pitDirection = ANT_RIGHT; + _antCel = 0; + _torchCel = 0; + _pitCel = 0; + _stabCel = 0; + _antPos = Common::Point(0, 0); + _antDieFl = _antEatFl = false; + _stabFl = false; + _pitPos = Common::Point(0, 0); +} + +void Ant::plotTorchSpear(int indx, const int *&buf) { + int idx = indx; + + ImageEntry ie; + ie._flags = IMGFLAG_UNSCALED; + ie._spritesPtr = _vm->_objectsTable[62]; + ie._frameNumber = buf[(idx / 2)]; + ie._position = Common::Point(_pitPos.x + buf[(idx / 2) + 1], _pitPos.y + buf[(idx / 2) + 2]); + ie._offsetY = 255; + _vm->_images.addToList(ie); +} + +void Ant::plotPit(int indx, const int *&buf) { + int idx = indx; + ImageEntry ie; + ie._flags = IMGFLAG_UNSCALED; + ie._spritesPtr = _vm->_objectsTable[62]; + ie._frameNumber = buf[(idx / 2)]; + ie._position = Common::Point(_pitPos.x, _pitPos.y); + ie._offsetY = _pitPos.y; + _vm->_images.addToList(ie); + + _vm->_player->_rawPlayer = _pitPos; + if (_vm->_inventory->_inv[INV_TORCH]._value == ITEM_IN_INVENTORY) { + // Player has torch + idx = _torchCel; + buf = Amazon::TORCH; + _vm->_timers[14]._flag = 1; + idx += 6; + if (buf[idx / 2] == -1) + idx = 0; + _torchCel = idx; + plotTorchSpear(idx, buf); + } else if (!_stabFl && (_vm->_inventory->_inv[INV_KNIFE_SPEAR]._value == ITEM_IN_INVENTORY)) { + // Player has spear + idx = 0; + buf = Amazon::SPEAR; + plotTorchSpear(idx, buf); + } +} + +int Ant::antHandleRight(int indx, const int *&buf) { + int retval = indx; + if (_pitDirection == ANT_RIGHT) { + _pitDirection = ANT_LEFT; + _pitPos.y = 127; + } + retval = _pitCel; + buf = Amazon::PITWALK; + if (_pitPos.x < 230) { + if (retval == 0) { + retval = 48; + _pitPos.y = 127; + } + retval -= 6; + _pitPos.x -= buf[(retval / 2) + 1]; + _pitPos.y -= buf[(retval / 2) + 2]; + _pitCel = retval; + } + return retval; +} + +int Ant::antHandleLeft(int indx, const int *&buf) { + int retval = indx; + if (_pitDirection == ANT_LEFT) { + _pitDirection = ANT_RIGHT; + _pitPos.y = 127; + } + retval = _pitCel; + buf = Amazon::PITWALK; + retval += 6; + if (buf[retval / 2] == -1) { + retval = 0; + _pitPos.y = 127; + } + _pitPos.x += buf[(retval / 2) + 1]; + _pitPos.y += buf[(retval / 2) + 2]; + _pitCel = retval; + + return retval; +} + +int Ant::antHandleStab(int indx, const int *&buf) { + int retval = indx; + if (_vm->_inventory->_inv[INV_KNIFE_SPEAR]._value == ITEM_IN_INVENTORY) { + if (_stabFl) { + buf = Amazon::PITSTAB; + retval = _stabCel; + if (_vm->_timers[13]._flag == 0) { + _vm->_timers[13]._flag = 1; + retval += 6; + _stabCel = retval; + + if (buf[retval] == -1) { + _stabFl = false; + _pitCel = 0; + _pitPos.y = 127; + retval = 0; + buf = Amazon::PITWALK; + } else { + _pitPos.x += buf[(retval / 2) + 1]; + _pitPos.y += buf[(retval / 2) + 2]; + _pitCel = retval; + } + } + } else { + _stabFl = true; + _pitCel = 0; + retval = 0; + _stabCel = 0; + int dist = _pitPos.x - _antPos.x; + if (_antEatFl && !_antDieFl && (dist <= 80)) { + _antDieFl = true; + _antCel = 0; + _antPos.y = 123; + _vm->_sound->playSound(1); + } + } + } + + return retval; +} + +void Ant::doAnt() { + _antDirection = ANT_RIGHT; + if (_vm->_aniFlag != 1) { + _vm->_aniFlag = 1; + _antCel = 0; + _torchCel = 0; + _pitCel = 0; + + _vm->_timers[15]._timer = 16; + _vm->_timers[15]._initTm = 16; + _vm->_timers[15]._flag = 1; + + _vm->_timers[13]._timer = 5; + _vm->_timers[13]._initTm = 5; + _vm->_timers[13]._flag = 1; + + _vm->_timers[14]._timer = 10; + _vm->_timers[14]._initTm = 10; + _vm->_timers[14]._flag = 1; + + _antPos = Common::Point(-40, 123); + _antDieFl = _antEatFl = false; + _stabFl = false; + _pitPos = Common::Point(_vm->_player->_rawPlayer.x, 127); + } + + const int *buf = nullptr; + if (_antDieFl) { + buf = Amazon::ANTDIE; + } else if (_antEatFl) { + buf = Amazon::ANTEAT; + } else if (_antPos.x > 120 && _vm->_flags[198] == 1) { + _antEatFl = true; + _vm->_flags[235] = 1; + _antCel = 0; + buf = Amazon::ANTEAT; + } else { + buf = Amazon::ANTWALK; + if (_vm->_inventory->_inv[INV_TORCH]._value == ITEM_IN_INVENTORY) + // Player has burning torch, which scares the Ant + _antDirection = ANT_LEFT; + } + + int idx = _antCel; + if (_vm->_timers[15]._flag == 0) { + _vm->_timers[15]._flag = 1; + if (_antDirection == ANT_LEFT) { + if (_antPos.x > 10) { + if (idx == 0) + idx = 36; + else + idx -= 6; + + _antPos -= Common::Point(buf[(idx / 2) + 1], buf[(idx / 2) + 2]); + _antCel = idx; + } + } else { + idx += 6; + if (buf[(idx / 2)] != -1) { + _antPos += Common::Point(buf[(idx / 2) + 1], buf[(idx / 2) + 2]); + _antCel = idx; + } else if (!_antDieFl) { + idx = 0; + _antPos += Common::Point(buf[(idx / 2) + 1], buf[(idx / 2) + 2]); + _antCel = idx; + } else { + idx -= 6; + if (_vm->_flags[200] == 0) + _vm->_flags[200] = 1; + } + } + } + + ImageEntry ie; + ie._flags = IMGFLAG_UNSCALED; + ie._spritesPtr = _vm->_objectsTable[61]; + ie._frameNumber = buf[(idx / 2)]; + ie._position = Common::Point(_antPos.x, _antPos.y); + ie._offsetY = _antPos.y - 70; + _vm->_images.addToList(ie); + _antCel = idx; + + if (_vm->_flags[196] != 1) { + idx = _pitCel; + if (_stabFl) { + idx = antHandleStab(idx, buf); + } else { + buf = Amazon::PITWALK; + if (_vm->_timers[13]._flag == 0) { + _vm->_timers[13]._flag = 1; + _vm->_events->pollEvents(); + if (_vm->_events->_leftButton) { + // Handle moving the player whilst the mouse button is held down + Common::Point pt = _vm->_events->calcRawMouse(); + if (pt.x < _pitPos.x) + idx = antHandleLeft(idx, buf); + else if (pt.x > _pitPos.x) + idx = antHandleRight(idx, buf); + } else { + // Handle movement based on keyboard keys + buf = Amazon::PITWALK; + if (_vm->_player->_move == UP) + idx = antHandleStab(idx, buf); + else if (_vm->_player->_move == LEFT) + idx = antHandleLeft(idx, buf); + else if (_vm->_player->_move == RIGHT) + idx = antHandleRight(idx, buf); + } + } + } + plotPit(idx, buf); + } + + if (!_antDieFl) { + int dist = _pitPos.x - _antPos.x; + if ((_antEatFl && (dist <= 45)) || (!_antEatFl && (dist <= 80))) { + _vm->_flags[199] = 1; + _vm->_aniFlag = 0; + } + } +} + +void Ant::synchronize(Common::Serializer &s) { + if (_vm->_player->_roomNumber == 61) { + s.syncAsByte(_antDirection); + s.syncAsByte(_pitDirection); + s.syncAsSint16LE(_antCel); + s.syncAsSint16LE(_torchCel); + s.syncAsSint16LE(_pitCel); + s.syncAsSint16LE(_stabCel); + s.syncAsSint16LE(_antPos.x); + s.syncAsSint16LE(_antPos.y); + s.syncAsSint16LE(_pitPos.x); + s.syncAsSint16LE(_pitPos.y); + s.syncAsByte(_antDieFl); + s.syncAsByte(_antEatFl); + s.syncAsByte(_stabFl); + } +} + + +} // End of namespace Amazon + +} // End of namespace Access |