diff options
Diffstat (limited to 'engines/gnap/gnap.cpp')
-rw-r--r-- | engines/gnap/gnap.cpp | 2404 |
1 files changed, 2404 insertions, 0 deletions
diff --git a/engines/gnap/gnap.cpp b/engines/gnap/gnap.cpp new file mode 100644 index 0000000000..08f598551e --- /dev/null +++ b/engines/gnap/gnap.cpp @@ -0,0 +1,2404 @@ +/* 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 "gnap/gnap.h" +#include "gnap/datarchive.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" +#include "gnap/sound.h" + +#include "common/config-manager.h" +#include "common/debug-channels.h" +#include "common/error.h" +#include "common/fs.h" +#include "common/timer.h" + +#include "engines/util.h" + +#include "graphics/cursorman.h" + +namespace Gnap { + +static const int kCursors[] = { + LOOK_CURSOR, + GRAB_CURSOR, + TALK_CURSOR, + PLAT_CURSOR +}; + +static const int kDisabledCursors[] = { + NOLOOK_CURSOR, + NOGRAB_CURSOR, + NOTALK_CURSOR, + NOPLAT_CURSOR +}; + +static const char *kCursorNames[] = { + "LOOK_CURSOR", + "GRAB_CURSOR", + "TALK_CURSOR", + "PLAT_CURSOR", + "NOLOOK_CURSOR", + "NOGRAB_CURSOR", + "NOTALK_CURSOR", + "NOPLAT_CURSOR", + "EXIT_L_CURSOR", + "EXIT_R_CURSOR", + "EXIT_U_CURSOR", + "EXIT_D_CURSOR", + "EXIT_NE_CURSOR", + "EXIT_NW_CURSOR", + "EXIT_SE_CURSOR", + "EXIT_SW_CURSOR", + "WAIT_CURSOR" +}; + + +static const int kCursorSpriteIds[30] = { + 0x005, 0x008, 0x00A, 0x004, 0x009, 0x003, + 0x006, 0x007, 0x00D, 0x00F, 0x00B, 0x00C, + 0x019, 0x01C, 0x015, 0x014, 0x010, 0x01A, + 0x018, 0x013, 0x011, 0x012, 0x01B, 0x016, + 0x017, 0x01D, 0x01E, 0x01F, 0x76A, 0x76B +}; + +static const char *kSceneNames[] = { + "open", "pigpn", "truck", "creek", "mafrm", "frbrn", "inbrn", "crash", + "porch", "barbk", "kitch", "bar", "juke", "wash", "john", "jkbox", + "brawl", "stret", "frtoy", "intoy", "frgro", "park", "cash", "ingro", + "frcir", "booth", "circ", "outcl", "incln", "monk", "elcir", "beer", + "pig2", "trk2", "creek", "frbrn", "inbrn", "mafrm", "infrm", "efair", + "fair", "souv", "chick", "ship", "kiss", "disco", "boot", "can", + "can2", "drive", "tung", "puss", "space", "phone", "can3" +}; + +GnapEngine::GnapEngine(OSystem *syst, const ADGameDescription *gd) : + Engine(syst), _gameDescription(gd) { + + _random = new Common::RandomSource("gnap"); + + Engine::syncSoundSettings(); + +} + +GnapEngine::~GnapEngine() { + + delete _random; + +} + +Common::Error GnapEngine::run() { + // Initialize the graphics mode to ARGB8888 + Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); + initGraphics(800, 600, true, &format); + + // We do not support color conversion yet + if (_system->getScreenFormat() != format) + return Common::kUnsupportedColorMode; + + _lastUpdateClock = 0; + + // >>>>> Variable initialization + _cursorIndex = -1; + _verbCursor = 1; + invClear(); + clearFlags(); + _grabCursorSprite = 0; + _newGrabCursorSpriteIndex = -1; + _backgroundSurface = 0; + _isStockDatLoaded = false; + _gameDone = false; + _isPaused = false; + _pauseSprite = 0; + + //////////////////////////////////////////////////////////////////////////// + + _exe = new Common::PEResources(); + if (!_exe->loadFromEXE("ufos.exe")) + error("Could not load ufos.exe"); + + _dat = new DatManager(); + _spriteCache = new SpriteCache(_dat); + _soundCache = new SoundCache(_dat); + _sequenceCache = new SequenceCache(_dat); + _gameSys = new GameSys(this); + _soundMan = new SoundMan(this); + + _menuBackgroundSurface = 0; + + initGlobalSceneVars(); + +#if 1 + + mainLoop(); + +#else + + Graphics::Surface *testBack = new Graphics::Surface(); + testBack->create(800, 600, _system->getScreenFormat()); + //testBack->fillRect(Common::Rect(0, 0, 800, 600), 0xFFFFFFFF); + testBack->fillRect(Common::Rect(0, 0, 800, 600), 0xFF000000); + + _currentSceneNum = 26; + + Common::String datFilename = Common::String::format("%s_n.dat", kSceneNames[_currentSceneNum]); + _dat->open(0, datFilename.c_str()); + + _gameSys->setBackgroundSurface(testBack, 0, 500, 1, 1000); + + _gameSys->insertSequence(0x5b, 100, -1, -1, 0, 0, 0, 0); + + CursorMan.showMouse(true); + + while (!shouldQuit()) { + Common::Event event; + + while (_eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + break; + case Common::EVENT_LBUTTONUP: + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_RBUTTONUP: + case Common::EVENT_RBUTTONDOWN: + case Common::EVENT_MOUSEMOVE: + break; + case Common::EVENT_QUIT: + quitGame(); + break; + default: + break; + } + } + + _gameSys->fatUpdate(); + _gameSys->drawSprites(); + _gameSys->updateScreen(); + _gameSys->_gameSysClock++; + updateTimers(); + + _system->updateScreen(); + _system->delayMillis(100); + + } + + _dat->close(0); + + testBack->free(); + delete testBack; + + return Common::kNoError; + +#endif + + delete _soundMan; + delete _gameSys; + delete _sequenceCache; + delete _soundCache; + delete _spriteCache; + delete _dat; + + delete _exe; + + debug("run() done"); + + return Common::kNoError; +} + +bool GnapEngine::hasFeature(EngineFeature f) const { + return + false; +} + +void GnapEngine::updateEvents() { + Common::Event event; + + while (_eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + _keyPressState[event.kbd.keycode] = 1; + _keyDownState[event.kbd.keycode] = 1; + break; + case Common::EVENT_KEYUP: + _keyDownState[event.kbd.keycode] = 0; + break; + case Common::EVENT_MOUSEMOVE: + _mouseX = event.mouse.x; + _mouseY = event.mouse.y; + break; + case Common::EVENT_LBUTTONUP: + _mouseButtonState.left = false; + break; + case Common::EVENT_LBUTTONDOWN: + _leftClickMouseX = event.mouse.x; + _leftClickMouseY = event.mouse.y; + _mouseButtonState.left = true; + _mouseClickState.left = true; + break; + case Common::EVENT_RBUTTONUP: + _mouseButtonState.right = false; + break; + case Common::EVENT_RBUTTONDOWN: + _mouseButtonState.right = true; + _mouseClickState.right = true; + break; + case Common::EVENT_QUIT: + quitGame(); + break; + default: + break; + } + } +} + +void GnapEngine::gameUpdateTick() { + updateEvents(); + + // TODO Check _gameDone in the various game loops + if (shouldQuit()) { + _gameDone = true; + _sceneDone = true; + } + + // TODO Improve this (variable frame delay to keep ~15fps) + int currClock = _system->getMillis(); + if (currClock >= _lastUpdateClock + 66) { + _gameSys->fatUpdate(); + _gameSys->drawSprites(); + _gameSys->updateScreen(); + _gameSys->updatePlaySounds(); + _gameSys->_gameSysClock++; + updateTimers(); + _lastUpdateClock = currClock; + } + + _soundMan->update(); + _system->updateScreen(); + _system->delayMillis(5); + +} + +void GnapEngine::saveTimers() { + for (int i = 0; i < kMaxTimers; ++i ) + _savedTimers[i] = _timers[i]; +} + +void GnapEngine::restoreTimers() { + for (int i = 0; i < kMaxTimers; ++i ) + _timers[i] = _savedTimers[i]; +} + +void GnapEngine::pauseGame() { + if (!_isPaused) { + saveTimers(); + hideCursor(); + setGrabCursorSprite(-1); + _pauseSprite = _gameSys->createSurface(0x1076C); + _gameSys->insertSpriteDrawItem(_pauseSprite, (800 - _pauseSprite->w) / 2, (600 - _pauseSprite->h) / 2, 356); + _lastUpdateClock = 0; + gameUpdateTick(); + // TODO playMidi("pause.mid"); + _isPaused = true; + } +} + +void GnapEngine::resumeGame() { + if (_isPaused) { + restoreTimers(); + _gameSys->removeSpriteDrawItem(_pauseSprite, 356); + _lastUpdateClock = 0; + gameUpdateTick(); + deleteSurface(&_pauseSprite); + // TODO stopMidi(); + _isPaused = false; + clearAllKeyStatus1(); + _mouseClickState.left = false; + _mouseClickState.right = false; + showCursor(); + _gameSys->_gameSysClock = 0; + _gameSys->_lastUpdateClock = 0; + } +} + +void GnapEngine::updatePause() { + while (_isPaused) { + gameUpdateTick(); + if (isKeyStatus1(Common::KEYCODE_p)) { + clearKeyStatus1(Common::KEYCODE_p); + resumeGame(); + } + //_system->delayMillis(100); + } +} + +int GnapEngine::getRandom(int max) { + return _random->getRandomNumber(max - 1); +} + +int GnapEngine::readSavegameDescription(int savegameNum, Common::String &description) { + description = Common::String::format("Savegame %d", savegameNum); + return 0; +} + +int GnapEngine::loadSavegame(int savegameNum) { + return 1; +} + +void GnapEngine::delayTicks(int a1) { + // TODO + gameUpdateTick(); +} + +void GnapEngine::delayTicksCursor(int a1) { + // TODO + gameUpdateTick(); +} + +void GnapEngine::setHotspot(int index, int16 x1, int16 y1, int16 x2, int16 y2, uint16 flags, + int16 walkX, int16 walkY) { + _hotspots[index].x1 = x1; + _hotspots[index].y1 = y1; + _hotspots[index].x2 = x2; + _hotspots[index].y2 = y2; + _hotspots[index].flags = flags; + _hotspots[index].id = index; + _hotspotsWalkPos[index].x = walkX; + _hotspotsWalkPos[index].y = walkY; +} + +int GnapEngine::getHotspotIndexAtPos(int16 x, int16 y) { + for (int i = 0; i < _hotspotsCount; ++i) + if (!_hotspots[i].isFlag(SF_DISABLED) && _hotspots[i].isPointInside(x, y)) + return i; + return -1; +} + +void GnapEngine::updateCursorByHotspot() { + if (!_isWaiting) { + int hotspotIndex = getHotspotIndexAtPos(_mouseX, _mouseY); + +#if 1 + // NOTE This causes some display glitches so don't worry + char t[256]; + sprintf(t, "hotspot = %d", hotspotIndex); + _gameSys->fillSurface(0, 10, 10, 80, 16, 0, 0, 0); + _gameSys->drawTextToSurface(0, 10, 10, 255, 255, 255, t); +#endif + + if (hotspotIndex < 0) + setCursor(kDisabledCursors[_verbCursor]); + else if (_hotspots[hotspotIndex].flags & SF_EXIT_L_CURSOR) + setCursor(EXIT_L_CURSOR); + else if (_hotspots[hotspotIndex].flags & SF_EXIT_R_CURSOR) + setCursor(EXIT_R_CURSOR); + else if (_hotspots[hotspotIndex].flags & SF_EXIT_U_CURSOR) + setCursor(EXIT_U_CURSOR); + else if (_hotspots[hotspotIndex].flags & SF_EXIT_D_CURSOR) + setCursor(EXIT_D_CURSOR); + else if (_hotspots[hotspotIndex].flags & SF_EXIT_NE_CURSOR) + setCursor(EXIT_NE_CURSOR); + else if (_hotspots[hotspotIndex].flags & SF_EXIT_NW_CURSOR) + setCursor(EXIT_NW_CURSOR); + else if (_hotspots[hotspotIndex].flags & SF_EXIT_SE_CURSOR) + setCursor(EXIT_SE_CURSOR); + else if (_hotspots[hotspotIndex].flags & SF_EXIT_SW_CURSOR) + setCursor(EXIT_SW_CURSOR); + else if (_hotspots[hotspotIndex].flags & (1 << _verbCursor)) + setCursor(kCursors[_verbCursor]); + else + setCursor(kDisabledCursors[_verbCursor]); + } + // Update platypus hotspot + _hotspots[0].x1 = _gridMinX + 75 * _platX - 30; + _hotspots[0].y1 = _gridMinY + 48 * _platY - 100; + _hotspots[0].x2 = _gridMinX + 75 * _platX + 30; + _hotspots[0].y2 = _gridMinY + 48 * _platY; +} + +int GnapEngine::getClickedHotspotId() { + int result = -1; + if (_isWaiting) + _mouseClickState.left = false; + else if (_mouseClickState.left) { + int hotspotIndex = getHotspotIndexAtPos(_leftClickMouseX, _leftClickMouseY); + if (hotspotIndex >= 0) { + _mouseClickState.left = false; + _timers[3] = 300; + result = _hotspots[hotspotIndex].id; + } + } + return result; +} + +int GnapEngine::getInventoryItemSpriteNum(int index) { + return kCursorSpriteIds[index]; +} + +void GnapEngine::updateMouseCursor() { + if (_mouseClickState.right) { + // Switch through the verb cursors + _mouseClickState.right = false; + _timers[3] = 300; + _verbCursor = (_verbCursor + 1) % 4; + if (!isFlag(0) && _verbCursor == PLAT_CURSOR && _cursorValue == 1) + _verbCursor = (_verbCursor + 1) % 4; + if (!_isWaiting) + setCursor(kDisabledCursors[_verbCursor]); + setGrabCursorSprite(-1); + } + if (_isWaiting && ((_gnapActionStatus < 0 && _beaverActionStatus < 0) || _sceneWaiting)) { + setCursor(kDisabledCursors[_verbCursor]); + _isWaiting = false; + } else if (!_isWaiting && (_gnapActionStatus >= 0 || _beaverActionStatus >= 0) && !_sceneWaiting) { + setCursor(WAIT_CURSOR); + _isWaiting = true; + } +} + +void GnapEngine::setVerbCursor(int verbCursor) { + _verbCursor = verbCursor; + if (!_isWaiting) + setCursor(kDisabledCursors[_verbCursor]); +} + +void GnapEngine::setCursor(int cursorIndex) { + if (_cursorIndex != cursorIndex) { + const char *cursorName = kCursorNames[cursorIndex]; + Graphics::WinCursorGroup *cursorGroup = Graphics::WinCursorGroup::createCursorGroup(*_exe, Common::WinResourceID(cursorName)); + if (cursorGroup) { + Graphics::Cursor *cursor = cursorGroup->cursors[0].cursor; + CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), + cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor()); + CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256); + delete cursorGroup; + } + _cursorIndex = cursorIndex; + } +} + +void GnapEngine::showCursor() { + CursorMan.showMouse(true); +} + +void GnapEngine::hideCursor() { + CursorMan.showMouse(false); +} + +void GnapEngine::setGrabCursorSprite(int index) { + freeGrabCursorSprite(); + if (index >= 0) { + createGrabCursorSprite(makeRid(1, kCursorSpriteIds[index])); + setVerbCursor(GRAB_CURSOR); + } + _grabCursorSpriteIndex = index; +} + +void GnapEngine::createGrabCursorSprite(int spriteId) { + _grabCursorSprite = _gameSys->createSurface(spriteId); + _gameSys->insertSpriteDrawItem(_grabCursorSprite, + _mouseX - (_grabCursorSprite->w / 2), + _mouseY - (_grabCursorSprite->h / 2), + 300); + delayTicks(5); +} + +void GnapEngine::freeGrabCursorSprite() { + if (_grabCursorSprite) { + _gameSys->removeSpriteDrawItem(_grabCursorSprite, 300); + _gameSys->removeSpriteDrawItem(_grabCursorSprite, 301); + delayTicks(5); + deleteSurface(&_grabCursorSprite); + } +} + +void GnapEngine::updateGrabCursorSprite(int x, int y) { + if (_grabCursorSprite) { + int newGrabCursorX = _mouseX - (_grabCursorSprite->w / 2) - x; + int newGrabCursorY = _mouseY - (_grabCursorSprite->h / 2) - y; + if (_currGrabCursorX != newGrabCursorX || _currGrabCursorY != newGrabCursorY) { + _currGrabCursorX = newGrabCursorX; + _currGrabCursorY = newGrabCursorY; + Common::Rect rect(newGrabCursorX, newGrabCursorY, + newGrabCursorX + _grabCursorSprite->w, newGrabCursorY + _grabCursorSprite->h); + _gameSys->invalidateGrabCursorSprite(300, rect, _grabCursorSprite, _grabCursorSprite); + } + } +} + +void GnapEngine::invClear() { + _inventory = 0; +} + +void GnapEngine::invAdd(int itemId) { + _inventory |= (1 << itemId); +} + +void GnapEngine::invRemove(int itemId) { + _inventory &= ~(1 << itemId); +} + +bool GnapEngine::invHas(int itemId) { + return (_inventory & (1 << itemId)) != 0; +} + +void GnapEngine::clearFlags() { + _gameFlags = 0; +} + +void GnapEngine::setFlag(int num) { + _gameFlags |= (1 << num); +} + +void GnapEngine::clearFlag(int num) { + _gameFlags &= ~(1 << num); +} + +bool GnapEngine::isFlag(int num) { + return (_gameFlags & (1 << num)) != 0; +} + +Graphics::Surface *GnapEngine::addFullScreenSprite(int resourceId, int id) { + _fullScreenSpriteId = id; + _fullScreenSprite = _gameSys->createSurface(resourceId); + _gameSys->insertSpriteDrawItem(_fullScreenSprite, 0, 0, id); + return _fullScreenSprite; +} + +void GnapEngine::removeFullScreenSprite() { + _gameSys->removeSpriteDrawItem(_fullScreenSprite, _fullScreenSpriteId); + deleteSurface(&_fullScreenSprite); +} + +void GnapEngine::showFullScreenSprite(int resourceId) { + hideCursor(); + setGrabCursorSprite(-1); + addFullScreenSprite(resourceId, 256); + while (!_mouseClickState.left && !isKeyStatus1(Common::KEYCODE_ESCAPE) && + !isKeyStatus1(Common::KEYCODE_SPACE) && !isKeyStatus1(29)) { + gameUpdateTick(); + } + _mouseClickState.left = false; + clearKeyStatus1(Common::KEYCODE_ESCAPE); + clearKeyStatus1(29); + clearKeyStatus1(Common::KEYCODE_SPACE); + removeFullScreenSprite(); + showCursor(); +} + +void GnapEngine::queueInsertDeviceIcon() { + _gameSys->insertSequence(0x10849, 20, 0, 0, kSeqNone, 0, _deviceX1, _deviceY1); +} + +void GnapEngine::insertDeviceIconActive() { + _gameSys->insertSequence(0x1084A, 21, 0, 0, kSeqNone, 0, _deviceX1, _deviceY1); +} + +void GnapEngine::removeDeviceIconActive() { + _gameSys->removeSequence(0x1084A, 21, 1); +} + +void GnapEngine::setDeviceHotspot(int hotspotIndex, int x1, int y1, int x2, int y2) { + _deviceX1 = x1; + _deviceX2 = x2; + _deviceY1 = y1; + _deviceY2 = y2; + if (x1 == -1) + _deviceX1 = 730; + if (x2 == -1) + _deviceX2 = 780; + if (y1 == -1) + _deviceY1 = 14; + if (y2 == -1) + _deviceY2 = 79; + _hotspots[hotspotIndex].x1 = _deviceX1; + _hotspots[hotspotIndex].y1 = _deviceY1; + _hotspots[hotspotIndex].x2 = _deviceX2; + _hotspots[hotspotIndex].y2 = _deviceY2; + _hotspots[hotspotIndex].flags = SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; + _hotspots[hotspotIndex].id = hotspotIndex; +} + +int GnapEngine::getSequenceTotalDuration(int resourceId) { + SequenceResource *sequenceResource = _sequenceCache->get(resourceId); + int maxValue = 0; + for (int i = 0; i < sequenceResource->_animationsCount; ++i) { + SequenceAnimation *animation = &sequenceResource->_animations[i]; + if (animation->field_4 + animation->field_A > maxValue) + maxValue = animation->field_4 + animation->field_A; + } + int totalDuration = maxValue + sequenceResource->_totalDuration; + _sequenceCache->release(resourceId); + return totalDuration; +} + +bool GnapEngine::isSoundPlaying(int resourceId) { + return _soundMan->isSoundPlaying(resourceId); +} + +void GnapEngine::playSound(int resourceId, bool looping) { + debug(0, "playSound(%08X, %d)", resourceId, looping); + _soundMan->playSound(resourceId, looping); +} + +void GnapEngine::stopSound(int resourceId) { + _soundMan->stopSound(resourceId); +} + +void GnapEngine::setSoundVolume(int resourceId, int volume) { + _soundMan->setSoundVolume(resourceId, volume); +} + +void GnapEngine::updateTimers() { + for (int i = 0; i < kMaxTimers; ++i) + if (_timers[i] > 0) + --_timers[i]; +} + +void GnapEngine::initGameFlags(int num) { + invClear(); + invAdd(kItemMagazine); + switch (num) { + case 1: + setFlag(26); + break; + case 2: + clearFlags(); + break; + case 3: + invAdd(kItemDiceQuarterHole); + clearFlags(); + break; + case 4: + invAdd(kItemDiceQuarterHole); + invAdd(kItemHorn); + invAdd(kItemLightbulb); + clearFlags(); + setFlag(0); + setFlag(1); + setFlag(2); + setFlag(3); + setFlag(4); + setFlag(5); + setFlag(6); + setFlag(7); + break; + } + + //DEBUG! +// setFlag(0); // Enable platypus + setFlag(25); + invClear(); + invAdd(kItemMagazine); +#if 0 + invAdd(kItemDisguise); +#endif +#if 1 + //invAdd(kItemGas); + invAdd(kItemJoint); + //invAdd(kItemKeys); + invAdd(kItemWrench); + //invAdd(kItemTongs); + invAdd(kItemDiceQuarterHole); + //invAdd(kItemPill); + invAdd(kItemBucketWithBeer); + invAdd(kItemChickenBucket); + invAdd(kItemGum); + invAdd(kItemPicture); +#endif +} + +void GnapEngine::loadStockDat() { + if (!_isStockDatLoaded) { + _isStockDatLoaded = true; + _dat->open(1, "stock_n.dat"); + //createMenuSprite(); + // NOTE Skipped preloading of data + } +} + +void GnapEngine::mainLoop() { + + _newCursorValue = 1; + _cursorValue = -1; + _newSceneNum = 0; + _currentSceneNum = 55; + _prevSceneNum = 55; + invClear(); + clearFlags(); + _grabCursorSpriteIndex = -1; + _grabCursorSprite = 0; + + debug("MainLoop #1"); + + // > DEBUG BEGIN + _currentSceneNum = 53; + _newSceneNum = 27; + _newCursorValue = 3; + // < DEBUG END + + loadStockDat(); + + while (!_gameDone) { + + debug("New scene: %d", _newSceneNum); + + _prevSceneNum = _currentSceneNum; + _currentSceneNum = _newSceneNum; + + debug("GnapEngine::mainLoop() _prevSceneNum: %d; _currentSceneNum: %d", _prevSceneNum, _currentSceneNum); + + if (_newCursorValue != _cursorValue) { + debug("_newCursorValue: %d", _newCursorValue); + _cursorValue = _newCursorValue; + if (!_wasSavegameLoaded) + initGameFlags(_cursorValue); + } + + _sceneSavegameLoaded = _wasSavegameLoaded; + _wasSavegameLoaded = false; + + initScene(); + + runSceneLogic(); + afterScene(); + + _soundMan->stopAll(); + + // Force purge all resources + _sequenceCache->purge(true); + _soundCache->purge(true); + _spriteCache->purge(true); + + if (isKeyStatus1(28)) { + clearKeyStatus1(28); + if (_debugLevel == 4) + _gameDone = true; + } + + } + + if (_backgroundSurface) + deleteSurface(&_backgroundSurface); + + _dat->close(1); + // TODO freeMenuSprite(); + // TODO freeFont(); + + debug("MainLoop #XXX2"); + +} + +void GnapEngine::initScene() { + + Common::String datFilename; + + _isLeavingScene = false; + _sceneDone = false; + _newSceneNum = 55; + _gnapActionStatus = -1; + _beaverActionStatus = -1; + gnapInitBrainPulseRndValue(); + hideCursor(); + clearAllKeyStatus1(); + _mouseClickState.left = false; + _mouseClickState.right = false; + _sceneClickedHotspot = -1; + + datFilename = Common::String::format("%s_n.dat", kSceneNames[_currentSceneNum]); + + debug("GnapEngine::initScene() datFilename: %s", datFilename.c_str()); + + _dat->open(0, datFilename.c_str()); + + int backgroundId = initSceneLogic(); + + if (!_backgroundSurface) { + if (_currentSceneNum != 0) + _backgroundSurface = _gameSys->loadBitmap(makeRid(1, 0x8AA)); + else + _backgroundSurface = _gameSys->loadBitmap(makeRid(0, backgroundId)); + _gameSys->setBackgroundSurface(_backgroundSurface, 0, 500, 1, 1000); + } + + if (_currentSceneNum != 0 && _currentSceneNum != 16 && _currentSceneNum != 47 && + _currentSceneNum != 48 && _currentSceneNum != 54) { + _gameSys->drawBitmap(backgroundId); + } + + if ((_cursorValue == 4 && isFlag(12)) || _currentSceneNum == 41) + playSound(makeRid(1, 0x8F6), true); + +} + +void GnapEngine::endSceneInit() { + showCursor(); + if (_newGrabCursorSpriteIndex >= 0) + setGrabCursorSprite(_newGrabCursorSpriteIndex); +} + +void GnapEngine::afterScene() { + + if (_gameDone) + return; + + if (_newCursorValue == _cursorValue && _newSceneNum != 0 && _newSceneNum != 16 && + _newSceneNum != 47 && _newSceneNum != 48 && _newSceneNum != 54 && _newSceneNum != 49 && + _newSceneNum != 50 && _newSceneNum != 51 && _newSceneNum != 52) + _newGrabCursorSpriteIndex = _grabCursorSpriteIndex; + else + _newGrabCursorSpriteIndex = -1; + + setGrabCursorSprite(-1); + + _gameSys->requestClear2(0); + _gameSys->requestClear1(); + _gameSys->waitForUpdate(); + + _gameSys->requestClear2(0); + _gameSys->requestClear1(); + _gameSys->waitForUpdate(); + + screenEffect(0, 0, 0, 0); + + _dat->close(0); + + for (int animationIndex = 0; animationIndex < 12; ++animationIndex) + _gameSys->setAnimation(0, 0, animationIndex); + + clearKeyStatus1(Common::KEYCODE_p); + + _mouseClickState.left = false; + _mouseClickState.right = false; + +} + +void GnapEngine::checkGameKeys() { + if (isKeyStatus1(Common::KEYCODE_p)) { + clearKeyStatus1(Common::KEYCODE_p); + pauseGame(); + updatePause(); + } + // TODO? Debug input +} + +void GnapEngine::startSoundTimerA(int timerIndex) { + _soundTimerIndexA = timerIndex; + _timers[timerIndex] = getRandom(50) + 100; +} + +int GnapEngine::playSoundA() { + + static const int kSoundIdsA[] = { + 0x93E, 0x93F, 0x941, 0x942, 0x943, 0x944, + 0x945, 0x946, 0x947, 0x948, 0x949 + }; + + int soundId = -1; + + if (!_timers[_soundTimerIndexA]) { + _timers[_soundTimerIndexA] = getRandom(50) + 100; + soundId = kSoundIdsA[getRandom(11)]; + playSound(soundId | 0x10000, 0); + } + return soundId; +} + +void GnapEngine::startSoundTimerB(int timerIndex) { + _soundTimerIndexB = timerIndex; + _timers[timerIndex] = getRandom(50) + 150; +} + +int GnapEngine::playSoundB() { + + static const int kSoundIdsB[] = { + 0x93D, 0x929, 0x92A, 0x92B, 0x92C, 0x92D, + 0x92E, 0x92F, 0x930, 0x931, 0x932, 0x933, + 0x934, 0x935, 0x936, 0x937, 0x938, 0x939, + 0x93A + }; + + int soundId = -1; + + if (!_timers[_soundTimerIndexB]) { + _timers[_soundTimerIndexB] = getRandom(50) + 150; + soundId = kSoundIdsB[getRandom(19)]; + playSound(soundId | 0x10000, 0); + } + return soundId; +} + +void GnapEngine::startSoundTimerC(int timerIndex) { + _soundTimerIndexC = timerIndex; + _timers[timerIndex] = getRandom(50) + 150; +} + +int GnapEngine::playSoundC() { + + static const int kSoundIdsC[] = { + 0x918, 0x91F, 0x920, 0x922, 0x923, 0x924, + 0x926 + }; + + int soundId = -1; + + if (!_timers[_soundTimerIndexC]) { + _timers[_soundTimerIndexC] = getRandom(50) + 150; + soundId = kSoundIdsC[getRandom(7)] ; + playSound(soundId | 0x10000, 0); + } + return soundId; +} + +void GnapEngine::startIdleTimer(int timerIndex) { + _idleTimerIndex = timerIndex; + _timers[timerIndex] = 3000; +} + +void GnapEngine::updateIdleTimer() { + if (!_timers[_idleTimerIndex]) { + _timers[_idleTimerIndex] = 3000; + _gameSys->insertSequence(0x1088B, 255, 0, 0, kSeqNone, 0, 0, 75); + } +} + +void GnapEngine::screenEffect(int dir, byte r, byte g, byte b) { + if (dir == 1) { + for (int y = 300; y < 600; y += 50) { + _gameSys->fillSurface(0, 0, y, 800, 50, r, g, b); + _gameSys->fillSurface(0, 0, 549 - y + 1, 800, 50, r, g, b); + gameUpdateTick(); + _system->delayMillis(50); + } + } else { + for (int y = 0; y < 300; y += 50) { + _gameSys->fillSurface(0, 0, y, 800, 50, r, g, b); + _gameSys->fillSurface(0, 0, 549 - y + 1, 800, 50, r, g, b); + gameUpdateTick(); + _system->delayMillis(50); + } + } +} + +bool GnapEngine::isKeyStatus1(int key) { + return _keyPressState[key] != 0;; +} + +bool GnapEngine::isKeyStatus2(int key) { + return _keyDownState[key] != 0;; +} + +void GnapEngine::clearKeyStatus1(int key) { + _keyPressState[key] = 0; + _keyDownState[key] = 0; +} + +void GnapEngine::clearAllKeyStatus1() { + _keyStatus1[0] = 0; + _keyStatus1[1] = 0; + memset(_keyPressState, 0, sizeof(_keyPressState)); + memset(_keyDownState, 0, sizeof(_keyDownState)); +} + +void GnapEngine::deleteSurface(Graphics::Surface **surface) { + if (surface && *surface) { + (*surface)->free(); + delete *surface; + *surface = 0; + } +} + +int GnapEngine::getGnapSequenceId(int kind, int gridX, int gridY) { + int sequenceId = 0; + + switch (kind) { + + case gskPullOutDevice: + if (gridX > 0 && gridY > 0) { + if (_gnapY > gridY) { + if (_gnapX > gridX) { + sequenceId = 0x83F; + _gnapIdleFacing = 5; + } else { + sequenceId = 0x83D; + _gnapIdleFacing = 7; + } + } else { + if (_gnapX > gridX) { + sequenceId = 0x83B; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x839; + _gnapIdleFacing = 1; + } + } + } else { + switch (_gnapIdleFacing) { + case 1: + sequenceId = 0x839; + break; + case 3: + sequenceId = 0x83B; + break; + case 7: + sequenceId = 0x83D; + break; + default: + sequenceId = 0x83F; + break; + } + } + break; + + case gskPullOutDeviceNonWorking: + if (gridX > 0 && gridY > 0) { + if (_gnapY > gridY) { + if (_gnapX > gridX) { + sequenceId = 0x829; + _gnapIdleFacing = 5; + } else { + sequenceId = 0x828; + _gnapIdleFacing = 7; + } + } else { + if (_gnapX > gridX) { + sequenceId = 0x827; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x826; + _gnapIdleFacing = 1; + } + } + } else { + switch (_gnapIdleFacing) { + case 1: + sequenceId = 0x826; + break; + case 3: + sequenceId = 0x827; + break; + case 7: + sequenceId = 0x828; + break; + default: + sequenceId = 0x829; + break; + } + } + break; + + case gskScratchingHead: + if (gridX > 0 && gridY > 0) { + if (_gnapY > gridY) { + if (_gnapX > gridX) { + sequenceId = 0x834; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x885; + _gnapIdleFacing = 7; + } + } else { + if (_gnapX > gridX) { + sequenceId = 0x834; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x833; + _gnapIdleFacing = 1; + } + } + } else { + switch (_gnapIdleFacing) { + case 1: + sequenceId = 0x833; + _gnapIdleFacing = 1; + break; + case 3: + sequenceId = 0x834; + _gnapIdleFacing = 3; + break; + case 7: + sequenceId = 0x885; + _gnapIdleFacing = 7; + break; + default: + sequenceId = 0x834; + _gnapIdleFacing = 3; + break; + } + } + break; + + case gskIdle: + if (gridX > 0 && gridY > 0) { + if (_gnapY > gridY) { + if (_gnapX > gridX) { + sequenceId = 0x7BC; + _gnapIdleFacing = 5; + } else { + sequenceId = 0x7BB; + _gnapIdleFacing = 7; + } + } else { + if (_gnapX > gridX) { + sequenceId = 0x7BA; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x7B9; + _gnapIdleFacing = 1; + } + } + } else { + switch (_gnapIdleFacing) { + case 1: + sequenceId = 0x7B9; + break; + case 3: + sequenceId = 0x7BA; + break; + case 7: + sequenceId = 0x7BB; + break; + default: + sequenceId = 0x7BC; + break; + } + } + break; + + case gskBrainPulsating: + _gnapBrainPulseNum = (_gnapBrainPulseNum + 1) & 1; + if (gridX > 0 && gridY > 0) { + if (_gnapY > gridY) { + if (_gnapX > gridX) { + sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x812; + _gnapIdleFacing = 5; + } else { + sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7FE; + _gnapIdleFacing = 7; + } + } else { + if (_gnapX > gridX) { + sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7D6; + _gnapIdleFacing = 3; + } else { + sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7EA; + _gnapIdleFacing = 1; + } + } + } else { + switch (_gnapIdleFacing) { + case 1: + sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7EA; + break; + case 3: + sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7D6; + break; + case 7: + sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7FE; + break; + default: + sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x812; + break; + } + } + break; + + case gskImpossible: + if (gridX > 0 && gridY > 0) { + if (_gnapY > gridY) { + if (_gnapX > gridX) { + sequenceId = 0x831; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x7A8; + _gnapIdleFacing = 1; + } + } else { + if (_gnapX > gridX) { + sequenceId = 0x831; + _gnapIdleFacing = 3; + } else { + if (_gnapX % 2) + sequenceId = 0x7A8; + else + sequenceId = 0x89A; + _gnapIdleFacing = 1; + } + } + } else if (_gnapIdleFacing != 1 && _gnapIdleFacing != 7) { + sequenceId = 0x831; + _gnapIdleFacing = 3; + } else { + if (_currentSceneNum % 2) + sequenceId = 0x7A8; + else + sequenceId = 0x89A; + _gnapIdleFacing = 1; + } + break; + + case gskDeflect: + if (gridX > 0 && gridY > 0) { + if (_gnapY > gridY) { + if (_gnapX > gridX) { + sequenceId = 0x830; + _gnapIdleFacing = 5; + } else { + sequenceId = 0x82F; + _gnapIdleFacing = 7; + } + } else { + if (_gnapX > gridX) { + sequenceId = 0x82E; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x7A7; + _gnapIdleFacing = 1; + } + } + } else { + switch (_gnapIdleFacing) { + case 1: + sequenceId = 0x7A7; + break; + case 3: + sequenceId = 0x82E; + break; + case 5: + sequenceId = 0x830; + break; + case 7: + sequenceId = 0x82F; + break; + } + } + break; + + case gskUseDevice: + switch (_gnapIdleFacing) { + case 1: + sequenceId = 0x83A; + break; + case 3: + sequenceId = 0x83C; + break; + case 5: + sequenceId = 0x840; + break; + case 7: + sequenceId = 0x83E; + break; + } + break; + + case gskMoan1: + if (gridX > 0 && gridY > 0) { + if (_gnapY > gridY) { + if (_gnapX > gridX) { + sequenceId = 0x832; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x7AA; + _gnapIdleFacing = 1; + } + } else { + if (_gnapX > gridX) { + sequenceId = 0x832; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x7AA; + _gnapIdleFacing = 1; + } + } + } else if (_gnapIdleFacing != 1 && _gnapIdleFacing != 7) { + sequenceId = 0x832; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x7AA; + _gnapIdleFacing = 1; + } + break; + + case gskMoan2: + if (gridX > 0 && gridY > 0) { + if (_gnapY > gridY) { + if (_gnapX > gridX) { + sequenceId = 0x832; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x7AA; + _gnapIdleFacing = 1; + } + } else { + if (_gnapX > gridX) { + sequenceId = 0x832; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x7AA; + _gnapIdleFacing = 1; + } + } + } else if (_gnapIdleFacing != 1 && _gnapIdleFacing != 7) { + sequenceId = 0x832; + _gnapIdleFacing = 3; + } else { + sequenceId = 0x7AA; + _gnapIdleFacing = 1; + } + break; + + } + + return sequenceId | 0x10000; +} + +int GnapEngine::getGnapShowSequenceId(int index, int gridX, int gridY) { + + int sequenceId; + int facing = _gnapIdleFacing; + + if (gridY > 0 && gridX > 0) { + if (_gnapY > gridY) { + if (_gnapX > gridX) + _gnapIdleFacing = 5; + else + _gnapIdleFacing = 7; + } else { + if (_gnapX > gridX) + _gnapIdleFacing = 5; + else + _gnapIdleFacing = 7; + } + } else if (_gnapIdleFacing != 1 && _gnapIdleFacing != 7) { + _gnapIdleFacing = 5; + } else { + _gnapIdleFacing = 7; + } + + switch (index) { + case 0: + if (_gnapIdleFacing == 7) + sequenceId = 0x8A0; + else + sequenceId = 0x8A1; + break; + case 1: + if (_gnapIdleFacing == 7) + sequenceId = 0x880; + else + sequenceId = 0x895; + break; + case 2: + if (_gnapIdleFacing == 7) + sequenceId = 0x884; + else + sequenceId = 0x899; + break; + //Skip 3 + case 4: + if (_gnapIdleFacing == 7) + sequenceId = 0x881; + else + sequenceId = 0x896; + break; + case 5: + if (_gnapIdleFacing == 7) + sequenceId = 0x883; + else + sequenceId = 0x898; + break; + case 6: + if (_gnapIdleFacing == 7) + sequenceId = 0x87E; + else + sequenceId = 0x893; + break; + case 7: + if (_gnapIdleFacing == 7) + sequenceId = 0x848; + else + sequenceId = 0x890; + break; + case 8: + if (_gnapIdleFacing == 7) + sequenceId = 0x87D; + else + sequenceId = 0x892; + break; + case 9: + if (_gnapIdleFacing == 7) + sequenceId = 0x882; + else + sequenceId = 0x897; + break; + case 10: + if (_gnapIdleFacing == 7) + sequenceId = 0x87C; + else + sequenceId = 0x891; + break; + case 11: + if (_gnapIdleFacing == 7) + sequenceId = 0x87C; + else + sequenceId = 0x891; + break; + case 12: + if (_gnapIdleFacing == 7) + sequenceId = 0x87D; + else + sequenceId = 0x892; + break; + case 13: + if (_gnapIdleFacing == 7) + sequenceId = 0x888; + else + sequenceId = 0x89D; + break; + case 14: + if (_gnapIdleFacing == 7) + sequenceId = 0x87F; + else + sequenceId = 0x894; + break; + case 15: + if (_gnapIdleFacing == 7) + sequenceId = 0x87B; + else + sequenceId = 0x8A3; + break; + case 16: + if (_gnapIdleFacing == 7) + sequenceId = 0x877; + else + sequenceId = 0x88C; + break; + //Skip 17 + case 18: + sequenceId = 0x887; + break; + case 19: + if (_gnapIdleFacing == 7) + sequenceId = 0x87A; + else + sequenceId = 0x88F; + break; + case 20: + if (_gnapIdleFacing == 7) + sequenceId = 0x878; + else + sequenceId = 0x88D; + break; + case 21: + if (_gnapIdleFacing == 7) + sequenceId = 0x879; + else + sequenceId = 0x88E; + break; + case 22: + if (_gnapIdleFacing == 7) + sequenceId = 0x88A; + else + sequenceId = 0x89F; + break; + case 23: + if (_gnapIdleFacing == 7) + sequenceId = 0x889; + else + sequenceId = 0x89E; + break; + case 24: + if (_gnapIdleFacing == 7) + sequenceId = 0x886; + else + sequenceId = 0x89B; + break; + case 25: + if (_gnapIdleFacing == 7) + sequenceId = 0x87A; + else + sequenceId = 0x88F; + break; + //Skip 26 + //Skip 27 + //Skip 28 + //Skip 29 + default: + _gnapIdleFacing = facing; + sequenceId = getGnapSequenceId(gskImpossible, 0, 0); + break; + } + return sequenceId; +} + +void GnapEngine::gnapIdle() { + if (_gnapSequenceId != -1 && _gnapSequenceDatNum == 1 && + (_gnapSequenceId == 0x7A6 || _gnapSequenceId == 0x7AA || + _gnapSequenceId == 0x832 || _gnapSequenceId == 0x841 || + _gnapSequenceId == 0x842 || _gnapSequenceId == 0x8A2 || + _gnapSequenceId == 0x833 || _gnapSequenceId == 0x834 || + _gnapSequenceId == 0x885 || _gnapSequenceId == 0x7A8 || + _gnapSequenceId == 0x831 || _gnapSequenceId == 0x89A)) { + _gameSys->insertSequence(getGnapSequenceId(gskIdle, 0, 0) | 0x10000, _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 32, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); + _gnapSequenceId = getGnapSequenceId(gskIdle, 0, 0); + _gnapSequenceDatNum = 1; + } +} + +void GnapEngine::gnapActionIdle(int sequenceId) { + if (_gnapSequenceId != -1 && ridToDatIndex(sequenceId) == _gnapSequenceDatNum && + ridToEntryIndex(sequenceId) == _gnapSequenceId) { + _gameSys->insertSequence(getGnapSequenceId(gskIdle, 0, 0) | 0x10000, _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 32, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); + _gnapSequenceId = getGnapSequenceId(gskIdle, 0, 0); + _gnapSequenceDatNum = 1; + } +} + +void GnapEngine::playGnapSequence(int sequenceId) { + _timers[2] = getRandom(30) + 20; + _timers[3] = 300; + gnapIdle(); + _gameSys->insertSequence(sequenceId, _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 9, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); + _gnapSequenceId = ridToEntryIndex(sequenceId); + _gnapSequenceDatNum = ridToDatIndex(sequenceId); +} + +void GnapEngine::playGnapImpossible(int gridX, int gridY) { + playGnapSequence(getGnapSequenceId(gskImpossible, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapScratchingHead(int gridX, int gridY) { + playGnapSequence(getGnapSequenceId(gskScratchingHead, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapMoan1(int gridX, int gridY) { + playGnapSequence(getGnapSequenceId(gskMoan1, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapMoan2(int gridX, int gridY) { + playGnapSequence(getGnapSequenceId(gskMoan2, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapBrainPulsating(int gridX, int gridY) { + playGnapSequence(getGnapSequenceId(gskBrainPulsating, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapPullOutDevice(int gridX, int gridY) { + playGnapSequence(getGnapSequenceId(gskPullOutDevice, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapPullOutDeviceNonWorking(int gridX, int gridY) { + playGnapSequence(getGnapSequenceId(gskPullOutDeviceNonWorking, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapUseDevice(int gridX, int gridY) { + playGnapSequence(getGnapSequenceId(gskUseDevice, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapIdle(int gridX, int gridY) { + playGnapSequence(getGnapSequenceId(gskIdle, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapShowItem(int itemIndex, int gridLookX, int gridLookY) { + playGnapSequence(getGnapShowSequenceId(itemIndex, gridLookX, gridLookY) | 0x10000); +} + +void GnapEngine::playGnapShowCurrItem(int gridX, int gridY, int gridLookX, int gridLookY) { + if (_platX == gridX && _platY == gridY) + beaverMakeRoom(); + gnapWalkTo(gridX, gridY, -1, -1, 1); + playGnapShowItem(_grabCursorSpriteIndex, gridLookX, gridLookY); +} + +void GnapEngine::updateGnapIdleSequence() { + if (_gnapActionStatus < 0) { + if (_timers[2] > 0) { + if (_timers[3] == 0) { + _timers[2] = 60; + _timers[3] = 300; + _gnapRandomValue = getRandom(5); + if (_gnapIdleFacing == 1) { + switch (_gnapRandomValue) { + case 0: + playGnapSequence(0x107A6); + break; + case 1: + playGnapSequence(0x107AA); + break; + case 2: + playGnapSequence(0x10841); + break; + default: + playGnapSequence(0x108A2); + break; + } + } else if (_gnapIdleFacing == 3) { + if (_gnapRandomValue > 2) + playGnapSequence(0x10832); + else + playGnapSequence(0x10842); + } + } + } else { + _timers[2] = getRandom(30) + 20; + if (_gnapIdleFacing == 1) { + _gameSys->insertSequence(0x107BD, _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 8, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); + _gnapSequenceId = 0x7BD; + _gnapSequenceDatNum = 1; + } else if (_gnapIdleFacing == 3) { + _gameSys->insertSequence(0x107BE, _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 8, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); + _gnapSequenceId = 0x7BE; + _gnapSequenceDatNum = 1; + } + } + } else { + _timers[2] = getRandom(30) + 20; + _timers[3] = 300; + } +} + +void GnapEngine::updateGnapIdleSequence2() { + if (_gnapActionStatus < 0) { + if (_timers[2] > 0) { + if (_timers[3] == 0) { + _timers[2] = 60; + _timers[3] = 300; + if (_gnapIdleFacing == 1) { + playGnapSequence(0x107AA); + } else if (_gnapIdleFacing == 3) { + playGnapSequence(0x10832); + } + } + } else { + _timers[2] = getRandom(30) + 20; + if (_gnapIdleFacing == 1) { + _gameSys->insertSequence(0x107BD, _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 8, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); + _gnapSequenceId = 0x7BD; + _gnapSequenceDatNum = 1; + } else if (_gnapIdleFacing == 3) { + _gameSys->insertSequence(0x107BE, _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 8, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); + _gnapSequenceId = 0x7BE; + _gnapSequenceDatNum = 1; + } + } + } else { + _timers[2] = getRandom(30) + 20; + _timers[3] = 300; + } +} + +bool GnapEngine::testWalk(int animationIndex, int someStatus, int gridX1, int gridY1, int gridX2, int gridY2) { + if (_mouseClickState.left && someStatus == _gnapActionStatus) { + _isLeavingScene = false; + _gameSys->setAnimation(0, 0, animationIndex); + _gnapActionStatus = -1; + _beaverActionStatus = -1; + gnapWalkTo(gridX1, gridY1, -1, -1, 1); + platypusWalkTo(gridX2, gridY2, -1, -1, 1); + _mouseClickState.left = false; + return true; + } + return false; +} + +void GnapEngine::initGnapPos(int gridX, int gridY, int facing) { + _timers[2] = 30; + _timers[3] = 300; + _gnapX = gridX; + _gnapY = gridY; + if (facing <= 0) + _gnapIdleFacing = 1; + else + _gnapIdleFacing = facing; + if (_gnapIdleFacing == 3) { + _gnapSequenceId = 0x7B8; + } else { + _gnapSequenceId = 0x7B5; + _gnapIdleFacing = 1; + } + _gnapId = 20 * _gnapY; + _gnapSequenceDatNum = 1; + _gameSys->insertSequence(makeRid(1, _gnapSequenceId), 20 * _gnapY, + 0, 0, + 1, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +} + +void GnapEngine::gnapInitBrainPulseRndValue() { + _gnapBrainPulseRndValue = 2 * getRandom(10); +} + +void GnapEngine::gnapUseDeviceOnBeaver() { + + playGnapSequence(makeRid(1, getGnapSequenceId(gskPullOutDevice, _platX, _platY))); + + if (_beaverFacing != 0) { + _gameSys->insertSequence(makeRid(1, 0x7D5), _beaverId, + makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, + 8, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY); + _beaverSequenceId = 0x7D5; + _beaverSequenceDatNum = 1; + } else { + _gameSys->insertSequence(makeRid(1, 0x7D4), _beaverId, + makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, + 8, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY); + _beaverSequenceId = 0x7D4; + _beaverSequenceDatNum = 1; + } + + int newSequenceId = getGnapSequenceId(gskUseDevice, 0, 0); + _gameSys->insertSequence(makeRid(1, newSequenceId), _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 8, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); + _gnapSequenceId = newSequenceId; + _gnapSequenceDatNum = 1; + +} + +void GnapEngine::doCallback(int callback) { + switch (callback) { + case 8: + scene08_updateAnimationsCb(); + break; + case 10: + scene10_updateAnimationsCb(); + break; + case 20: + scene20_updateAnimationsCb(); + break; + } +} + +bool GnapEngine::gnapPlatypusAction(int gridX, int gridY, int platSequenceId, int callback) { + bool result = false; + + if (_gnapActionStatus <= -1 && _beaverActionStatus <= -1) { + _gnapActionStatus = 100; + if (isPointBlocked(_platX + gridX, _platY + gridY) && (_platX + gridX != _gnapX || _platY + gridY != _gnapY)) + platypusWalkStep(); + if (!isPointBlocked(_platX + gridX, _platY + gridY) && (_platX + gridX != _gnapX || _platY + gridY != _gnapY)) { + gnapWalkTo(_platX + gridX, _platY + gridY, 0, 0x107B9, 1); + while (_gameSys->getAnimationStatus(0) != 2) { + updateMouseCursor(); + doCallback(callback); + gameUpdateTick(); + } + _gameSys->setAnimation(0, 0, 0); + if (_platX + gridX == _gnapX && _platY + gridY == _gnapY) { + _gameSys->setAnimation(platSequenceId, _beaverId, 1); + playBeaverSequence(platSequenceId); + while (_gameSys->getAnimationStatus(1) != 2) { + updateMouseCursor(); + doCallback(callback); + gameUpdateTick(); + } + result = true; + } + } + _gnapActionStatus = -1; + } + return result; +} + +void GnapEngine::gnapKissPlatypus(int callback) { + if (gnapPlatypusAction(-1, 0, 0x107D1, callback)) { + _gnapActionStatus = 100; + _gameSys->setAnimation(0, 0, 1); + _gameSys->setAnimation(0x10847, _gnapId, 0); + _gameSys->insertSequence(0x10847, _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 8, 0, 15 * (5 * _gnapX - 20) - (21 - _gridMinX), 48 * (_gnapY - 6) - (146 - _gridMinY)); + _gnapSequenceDatNum = 1; + _gnapSequenceId = 0x847; + _gameSys->insertSequence(0x107CB, _beaverId, + makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, + 8, getSequenceTotalDuration(0x10847), 75 * _platX - _platGridX, 48 * _platY - _platGridY); + _beaverSequenceDatNum = 1; + _beaverSequenceId = 0x7CB; + _beaverFacing = 0; + playGnapSequence(0x107B5); + while (_gameSys->getAnimationStatus(0) != 2) { + updateMouseCursor(); + doCallback(callback); + gameUpdateTick(); + } + _gameSys->setAnimation(0, 0, 0); + _gnapActionStatus = -1; + } else { + playGnapSequence(getGnapSequenceId(gskScratchingHead, _platX, _platY) | 0x10000); + } +} + +void GnapEngine::gnapUseJointOnPlatypus() { + setGrabCursorSprite(-1); + if (gnapPlatypusAction(1, 0, 0x107C1, 0)) { + _gnapActionStatus = 100; + _gameSys->setAnimation(0, 0, 1); + _gameSys->setAnimation(0x10876, _beaverId, 0); + _gameSys->insertSequence(0x10875, _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 8, 0, 15 * (5 * _gnapX - 30), 48 * (_gnapY - 7)); + _gnapSequenceDatNum = 1; + _gnapSequenceId = 0x875; + _gameSys->insertSequence(0x10876, _beaverId, + _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, + 8, 0, 15 * (5 * _platX - 25), 48 * (_platY - 7)); + _beaverSequenceDatNum = 1; + _beaverSequenceId = 0x876; + _beaverFacing = 0; + playGnapSequence(0x107B5); + gnapWalkStep(); + while (_gameSys->getAnimationStatus(0) != 2) { + updateMouseCursor(); + gameUpdateTick(); + } + _gameSys->setAnimation(0, 0, 0); + _gnapActionStatus = -1; + } else { + playGnapSequence(getGnapSequenceId(gskScratchingHead, _platX, _platY) | 0x10000); + } +} + +void GnapEngine::gnapUseDisguiseOnPlatypus() { + _gameSys->setAnimation(0x10846, _gnapId, 0); + playGnapSequence(0x10846); + while (_gameSys->getAnimationStatus(0) != 2) + gameUpdateTick(); + _newSceneNum = 47; + _isLeavingScene = true; + _sceneDone = true; + setFlag(10); +} + +int GnapEngine::getBeaverSequenceId(int kind, int gridX, int gridY) { + int sequenceId; + + // TODO kind is always 0, remove that parameter + if (kind != 0) + return 0; + + if (gridX > 0 && gridY > 0) { + if (gridX < _platX) { + sequenceId = 0x7CC; + _beaverFacing = 4; + } else { + sequenceId = 0x7CB; + _beaverFacing = 0; + } + } else if (_beaverFacing != 0) { + sequenceId = 0x7CC; + _beaverFacing = 4; + } else { + sequenceId = 0x7CB; + _beaverFacing = 0; + } + return sequenceId | 0x10000; +} + +void GnapEngine::playBeaverSequence(int sequenceId) { + _gameSys->insertSequence(sequenceId, _beaverId, + makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, + 9, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY); + _beaverSequenceId = ridToEntryIndex(sequenceId); + _beaverSequenceDatNum = ridToDatIndex(sequenceId); +} + +void GnapEngine::updateBeaverIdleSequence() { + if (_beaverActionStatus < 0 && _gnapActionStatus < 0) { + if (_timers[0] > 0) { + if (_timers[1] == 0) { + _timers[1] = getRandom(20) + 30; + _gnapRandomValue = getRandom(10); + if (_beaverFacing != 0) { + if (_gnapRandomValue != 0 || _beaverSequenceId != 0x7CA) { + if (_gnapRandomValue != 1 || _beaverSequenceId != 0x7CA) + playBeaverSequence(0x107CA); + else + playBeaverSequence(0x10845); + } else { + playBeaverSequence(0x107CC); + } + } else if (_gnapRandomValue != 0 || _beaverSequenceId != 0x7C9) { + if (_gnapRandomValue != 1 || _beaverSequenceId != 0x7C9) { + if (_gnapRandomValue != 2 || _beaverSequenceId != 0x7C9) + playBeaverSequence(0x107C9); + else + playBeaverSequence(0x108A4); + } else { + playBeaverSequence(0x10844); + } + } else { + playBeaverSequence(0x107CB); + } + } + } else { + _timers[0] = getRandom(75) + 75; + beaverMakeRoom(); + } + } else { + _timers[0] = 100; + _timers[1] = 35; + } +} + +void GnapEngine::beaverSub426234() { + if (_beaverActionStatus < 0 && _gnapActionStatus < 0) { + if (_timers[0]) { + if (!_timers[1]) { + _timers[1] = getRandom(20) + 30; + _gnapRandomValue = getRandom(10); + if (_beaverFacing != 0) { + if (_gnapRandomValue >= 2 || _beaverSequenceId != 0x7CA) + playBeaverSequence(0x107CA); + else + playBeaverSequence(0x107CC); + } else { + if (_gnapRandomValue >= 2 || _beaverSequenceId != 0x7C9) { + playBeaverSequence(0x107C9); + } else { + playBeaverSequence(0x107CB); + } + } + } + } else { + _timers[0] = getRandom(75) + 75; + beaverMakeRoom(); + } + } else { + _timers[0] = 100; + _timers[1] = 35; + } +} + +void GnapEngine::initBeaverPos(int gridX, int gridY, int facing) { + _timers[0] = 50; + _timers[1] = 20; + _platX = gridX; + _platY = gridY; + if (facing <= 0) + _beaverFacing = 0; + else + _beaverFacing = facing; + if (_beaverFacing == 4) { + _beaverSequenceId = 0x7D1; + } else { + _beaverSequenceId = 0x7C1; + _beaverFacing = 0; + } + _beaverId = 20 * _platY; + _beaverSequenceDatNum = 1; + _gameSys->insertSequence(makeRid(1, _beaverSequenceId), 20 * _platY, + 0, 0, + 1, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY); +} + +//////////////////////////////////////////////////////////////////////////////// + +void GnapEngine::initGlobalSceneVars() { + + // Scene 1 + _s01_pigsIdCtr = 0; + _s01_smokeIdCtr = 0; + _s01_spaceshipSurface = 0; + + // Scene 2 + _s02_truckGrillCtr = 0; + + // Scene 3 + _s03_nextPlatSequenceId = -1; + _s03_platypusScared = false; + _s03_platypusHypnotized = false; + + // Scene 4 + _s04_dogIdCtr = 0; + //_s04_triedWindow = true;//?? + _s04_triedWindow = false; + + // Scene 5 + _s05_nextChickenSequenceId = -1; + + // Scene 6 + _s06_nextPlatSequenceId = -1; + + // Scene 11 + _s11_billardBallCtr = 0; + + // Scene 13 + _s13_backToiletCtr = -1; + + // Scene 17 + _s17_platTryGetWrenchCtr = 0; + _s17_wrenchCtr = 2; + _s17_nextCarWindowSequenceId = -1; + _s17_nextWrenchSequenceId = -1; + _s17_canTryGetWrench = true; + _s17_platPhoneCtr = 0; + _s17_nextPhoneSequenceId = -1; + _s17_currPhoneSequenceId = -1; + + // Scene 18 + _s18_garbageCanPos = 8; + _s18_platPhoneCtr = 0; + _s18_platPhoneIter = 0; + _s18_nextPhoneSequenceId = -1; + _s18_currPhoneSequenceId = -1; + + // Scene 19 + _s19_toyGrabCtr = 0; + _s19_pictureSurface = 0; + _s19_shopAssistantCtr = 0; + + // Scene 20 + _s20_stonerGuyCtr = 3; + _s20_stonerGuyShowingJoint = false; + _s20_groceryStoreGuyCtr = 0; + + // Scene 22 + _s22_caughtBefore = false; + _s22_cashierCtr = 3; + + // Scene 50 + _s50_timesPlayed = 0; + _s50_timesPlayedModifier = 0; + _s50_attackCounter = 0; + _s50_leftTongueEnergyBarPos = 10; + _s50_leftTongueNextIdCtr = 0; + _s50_rightTongueEnergyBarPos = 10; + _s50_rightTongueNextIdCtr = 0; + + // Scene 52 + _s52_gameScore = 0; + _s52_aliensInitialized = false; + _s52_alienDirection = 0; + _s52_soundToggle = false; + + // Scene 53 + _s53_callsMadeCtr = 0; + _s53_callsRndUsed = 0; + + // Toy UFO + _toyUfoId = 0; + _toyUfoActionStatus = -1; + _toyUfoX = 0; + _toyUfoY = 50; + +} + +bool GnapEngine::sceneXX_sub_4466B1() { + + if (isKeyStatus1(Common::KEYCODE_ESCAPE)) { + clearKeyStatus1(Common::KEYCODE_ESCAPE); + clearKeyStatus1(Common::KEYCODE_UP); + clearKeyStatus1(Common::KEYCODE_RIGHT); + clearKeyStatus1(Common::KEYCODE_LEFT); + clearKeyStatus1(Common::KEYCODE_p); + return true; + } + + if (isKeyStatus1(Common::KEYCODE_p)) { + clearKeyStatus1(Common::KEYCODE_p); + pauseGame(); + updatePause(); + } + return false; + +} + +void GnapEngine::sceneXX_playRandomSound(int timerIndex) { + if (!_timers[timerIndex]) { + _timers[timerIndex] = getRandom(40) + 50; + _gnapRandomValue = getRandom(4); + switch (_gnapRandomValue) { + case 0: + playSound(0x1091B, 0); + break; + case 1: + playSound(0x10921, 0); + break; + case 2: + playSound(0x10927, 0); + break; + case 3: + playSound(0x1091D, 0); + break; + } + } +} + +void GnapEngine::playSequences(int fullScreenSpriteId, int sequenceId1, int sequenceId2, int sequenceId3) { + setGrabCursorSprite(-1); + _gameSys->setAnimation(sequenceId2, _gnapId, 0); + _gameSys->insertSequence(sequenceId2, _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 8, 0, 15 * (5 * _gnapX - 25), 48 * (_gnapY - 8)); + _gnapSequenceId = sequenceId2; + _gnapSequenceDatNum = 0; + while (_gameSys->getAnimationStatus(0) != 2) + gameUpdateTick(); + hideCursor(); + addFullScreenSprite(fullScreenSpriteId, 255); + _gameSys->setAnimation(sequenceId1, 256, 0); + _gameSys->insertSequence(sequenceId1, 256, 0, 0, kSeqNone, 0, 0, 0); + while (_gameSys->getAnimationStatus(0) != 2) + gameUpdateTick(); + _gameSys->setAnimation(sequenceId3, _gnapId, 0); + _gameSys->insertSequence(sequenceId3, _gnapId, + makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + 8, 0, 15 * (5 * _gnapX - 25), 48 * (_gnapY - 8)); + removeFullScreenSprite(); + showCursor(); + _gnapSequenceId = sequenceId3; +} + +// Scene 0 + +int GnapEngine::scene00_init() { + return 0x37C; +} + +void GnapEngine::toyUfoSetStatus(int a1) { + clearFlag(16); + clearFlag(17); + clearFlag(18); + clearFlag(19); + setFlag(a1); +} + +int GnapEngine::toyUfoGetSequenceId() { + if (isFlag(16)) + return 0x84E; + if (isFlag(17)) + return 0x84B; + if (isFlag(18)) + return 0x84D; + if (isFlag(19)) + return 0x84C; + return 0x84E; +} + +bool GnapEngine::toyUfoCheckTimer() { + if (!isFlag(12) || isFlag(18) || _timers[9] || + _toyUfoSequenceId == 0x870 || _toyUfoSequenceId == 0x871 || _toyUfoSequenceId == 0x872 || _toyUfoSequenceId == 0x873) + return false; + _sceneDone = true; + _newSceneNum = 41; + return true; +} + +void GnapEngine::toyUfoFlyTo(int destX, int destY, int a3, int a4, int a5, int a6, int animationIndex) { + int v21 = 0; + int v14 = 0; + int v17 = 36; + int v15 = 32; + int i = 0; + GridStruct v16[34]; + + if (destX == -1) + destX = _leftClickMouseX; + + if (destY == -1) + destY = _leftClickMouseY; + + //CHECKME + + int v25 = CLIP(destX, a3, a4); + int v26 = CLIP(destY, a5, a6); + int v24, v23; + int v13, v20; + + if (v25 == _toyUfoX) + v24 = 0; + else + v24 = (v25 - _toyUfoX) / ABS(v25 - _toyUfoX); + + if (v26 == _toyUfoY) + v23 = 0; + else + v23 = (v26 - _toyUfoY) / ABS(v26 - _toyUfoY); + + v13 = ABS(v25 - _toyUfoX); + v20 = ABS(v26 - _toyUfoY); + + if (v20 > v13) { + int v22 = v20 / v15; + while (v14 < v20 && i < 34) { + if (v22 - 5 >= i) { + v15 = MIN(36, 8 * i + 8); + } else { + v15 = MAX(6, v15 - 3); + } + v14 += v15; + v16[i].gridX1 = _toyUfoX + v24 * v13 * v14 / v20; + v16[i].gridY1 = _toyUfoY + v23 * v14; + ++i; + } + } else { + int v22 = v13 / v17; + while (v14 < v13 && i < 34) { + if (v22 - 5 >= i) { + v17 = MIN(38, 8 * i + 8); + } else { + v17 = MAX(6, v17 - 3); + } + v14 += v17; + v16[i].gridX1 = _toyUfoX + v24 * v14; + v16[i].gridY1 = _toyUfoY + v23 * v20 * v14 / v13; + ++i; + } + } + + v21 = i - 1; + + _toyUfoX = v25; + _toyUfoY = v26; + + debug("v21: %d", v21); + + if (i - 1 > 0) { + int v18; + if (isFlag(16)) + v18 = 0x867; + else if (isFlag(17)) + v18 = 0x84F; + else if (isFlag(18)) + v18 = 0x85F; + else if (isFlag(19)) + v18 = 0x857; + v16[0].sequenceId = v18; + v16[0].id = 0; + _gameSys->insertSequence(v18 | 0x10000, 0, + _toyUfoSequenceId | 0x10000, _toyUfoId, + 8, 0, v16[0].gridX1 - 365, v16[0].gridY1 - 128); + for (i = 1; i < v21; ++i) { + v16[i].sequenceId = v18 + (i % 8); + v16[i].id = i; + _gameSys->insertSequence(v16[i].sequenceId | 0x10000, v16[i].id, + v16[i - 1].sequenceId | 0x10000, v16[i - 1].id, + 8, 0, + v16[i].gridX1 - 365, v16[i].gridY1 - 128); + } + + _toyUfoSequenceId = v16[v21 - 1].sequenceId; + _toyUfoId = v16[v21 - 1].id; + + if (animationIndex >= 0) + _gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, animationIndex); + + } + +} + +// Scene 99 + +int GnapEngine::cutscene_init() { + return -1; +} + +void GnapEngine::cutscene_run() { + + int itemIndex = 0; + int soundId = -1; + int volume = 100; + int duration = 0; + bool skip = false; + + int v1 = 0; + + if (_prevSceneNum == 2) { + soundId = 0x36B; + duration = MAX(1, 300 / getSequenceTotalDuration(_s99_dword_47F370[_s99_itemsCount - 1]));//CHECKME + _timers[0] = 0; + } + + if (soundId != -1) + playSound(soundId, 0); + + hideCursor(); + + _gameSys->drawSpriteToBackground(0, 0, _s99_dword_47F2F0[0]); + + for (int j = 0; j < _s99_dword_47F330[0]; ++j) + _gameSys->insertSequence(_s99_dword_47F370[j], j + 2, 0, 0, kSeqNone, 0, 0, 0); + _gameSys->setAnimation(_s99_dword_47F370[0], 2, 0); + + clearKeyStatus1(Common::KEYCODE_ESCAPE); + clearKeyStatus1(Common::KEYCODE_SPACE); + clearKeyStatus1(29); + + _mouseClickState.left = false; + + while (!_sceneDone) { + + gameUpdateTick(); + + if (_gameSys->getAnimationStatus(0) == 2 || skip) { + skip = 0; + _gameSys->requestClear2(0); + _gameSys->requestClear1(); + _gameSys->setAnimation(0, 0, 0); + v1 += _s99_dword_47F330[itemIndex++]; + if (itemIndex >= _s99_itemsCount) { + _sceneDone = true; + } else { + for (int m = 0; m < _s99_dword_47F330[itemIndex]; ++m) + _gameSys->insertSequence(_s99_dword_47F370[v1 + m], m + 2, 0, 0, kSeqNone, 0, 0, 0); + _gameSys->drawSpriteToBackground(0, 0, _s99_dword_47F2F0[itemIndex]); + _gameSys->setAnimation(_s99_dword_47F370[v1], 2, 0); + } + } + + if (isKeyStatus1(Common::KEYCODE_ESCAPE) || isKeyStatus1(Common::KEYCODE_SPACE) || isKeyStatus1(29)) { + clearKeyStatus1(Common::KEYCODE_ESCAPE); + clearKeyStatus1(Common::KEYCODE_SPACE); + clearKeyStatus1(29); + if (_s99_canSkip[itemIndex] & 1) + skip = true; + else + _sceneDone = true; + } + + if (!_timers[0] && itemIndex == _s99_itemsCount - 1) { + _timers[0] = 2; + volume = MAX(1, volume - duration); + setSoundVolume(soundId, volume); + } + + } + + if (soundId != -1) + stopSound(soundId); + +} + +} // End of namespace Gnap |