aboutsummaryrefslogtreecommitdiff
path: root/engines/gnap/gnap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/gnap/gnap.cpp')
-rw-r--r--engines/gnap/gnap.cpp2404
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