aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjohndoe1232014-01-07 21:37:29 +0100
committerEugene Sandulenko2016-05-10 09:54:21 +0200
commitd80c7605a0892ae401953da4b889543598292986 (patch)
tree1be06a2ed0697d31fb97815e370661f87c14e6a3
parent1b24079f71a9af7c2a2754ebbc3132446fa46f67 (diff)
downloadscummvm-rg350-d80c7605a0892ae401953da4b889543598292986.tar.gz
scummvm-rg350-d80c7605a0892ae401953da4b889543598292986.tar.bz2
scummvm-rg350-d80c7605a0892ae401953da4b889543598292986.zip
GNAP: Initial commit
-rw-r--r--engines/gnap/datarchive.cpp121
-rw-r--r--engines/gnap/datarchive.h80
-rw-r--r--engines/gnap/detection.cpp195
-rw-r--r--engines/gnap/fontdata.h851
-rw-r--r--engines/gnap/gamesys.cpp1303
-rw-r--r--engines/gnap/gamesys.h216
-rw-r--r--engines/gnap/gnap.cpp2404
-rw-r--r--engines/gnap/gnap.h1117
-rw-r--r--engines/gnap/grid.cpp1392
-rw-r--r--engines/gnap/menu.cpp811
-rw-r--r--engines/gnap/module.mk70
-rw-r--r--engines/gnap/resource.cpp118
-rw-r--r--engines/gnap/resource.h196
-rw-r--r--engines/gnap/scenes/scene01.cpp373
-rw-r--r--engines/gnap/scenes/scene02.cpp539
-rw-r--r--engines/gnap/scenes/scene03.cpp517
-rw-r--r--engines/gnap/scenes/scene04.cpp571
-rw-r--r--engines/gnap/scenes/scene05.cpp467
-rw-r--r--engines/gnap/scenes/scene06.cpp446
-rw-r--r--engines/gnap/scenes/scene07.cpp275
-rw-r--r--engines/gnap/scenes/scene08.cpp527
-rw-r--r--engines/gnap/scenes/scene09.cpp241
-rw-r--r--engines/gnap/scenes/scene10.cpp500
-rw-r--r--engines/gnap/scenes/scene11.cpp488
-rw-r--r--engines/gnap/scenes/scene12.cpp564
-rw-r--r--engines/gnap/scenes/scene13.cpp455
-rw-r--r--engines/gnap/scenes/scene14.cpp194
-rw-r--r--engines/gnap/scenes/scene15.cpp343
-rw-r--r--engines/gnap/scenes/scene16.cpp82
-rw-r--r--engines/gnap/scenes/scene17.cpp846
-rw-r--r--engines/gnap/scenes/scene18.cpp1026
-rw-r--r--engines/gnap/scenes/scene19.cpp470
-rw-r--r--engines/gnap/scenes/scene20.cpp736
-rw-r--r--engines/gnap/scenes/scene21.cpp345
-rw-r--r--engines/gnap/scenes/scene22.cpp294
-rw-r--r--engines/gnap/scenes/scene23.cpp297
-rw-r--r--engines/gnap/scenes/scene24.cpp261
-rw-r--r--engines/gnap/scenes/scene25.cpp401
-rw-r--r--engines/gnap/scenes/scene26.cpp256
-rw-r--r--engines/gnap/scenes/scene27.cpp423
-rw-r--r--engines/gnap/scenes/scene28.cpp435
-rw-r--r--engines/gnap/scenes/scene29.cpp352
-rw-r--r--engines/gnap/scenes/scene30.cpp281
-rw-r--r--engines/gnap/scenes/scene31.cpp398
-rw-r--r--engines/gnap/scenes/scene32.cpp201
-rw-r--r--engines/gnap/scenes/scene33.cpp327
-rw-r--r--engines/gnap/scenes/scene38.cpp355
-rw-r--r--engines/gnap/scenes/scene39.cpp237
-rw-r--r--engines/gnap/scenes/scene40.cpp193
-rw-r--r--engines/gnap/scenes/scene41.cpp577
-rw-r--r--engines/gnap/scenes/scene42.cpp494
-rw-r--r--engines/gnap/scenes/scene43.cpp484
-rw-r--r--engines/gnap/scenes/scene44.cpp529
-rw-r--r--engines/gnap/scenes/scene45.cpp430
-rw-r--r--engines/gnap/scenes/scene46.cpp378
-rw-r--r--engines/gnap/scenes/scene47.cpp171
-rw-r--r--engines/gnap/scenes/scene48.cpp85
-rw-r--r--engines/gnap/scenes/scene49.cpp513
-rw-r--r--engines/gnap/scenes/scene50.cpp479
-rw-r--r--engines/gnap/scenes/scene51.cpp880
-rw-r--r--engines/gnap/scenes/scene52.cpp907
-rw-r--r--engines/gnap/scenes/scene53.cpp383
-rw-r--r--engines/gnap/scenes/scene54.cpp127
-rw-r--r--engines/gnap/scenes/scenecore.cpp658
-rw-r--r--engines/gnap/sound.cpp91
-rw-r--r--engines/gnap/sound.h56
66 files changed, 30832 insertions, 0 deletions
diff --git a/engines/gnap/datarchive.cpp b/engines/gnap/datarchive.cpp
new file mode 100644
index 0000000000..d480d31e67
--- /dev/null
+++ b/engines/gnap/datarchive.cpp
@@ -0,0 +1,121 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/dcl.h"
+#include "common/file.h"
+#include "common/stream.h"
+#include "common/substream.h"
+#include "gnap/datarchive.h"
+
+#include "engines/util.h"
+
+namespace Gnap {
+
+// DatArchive
+
+DatArchive::DatArchive(const char *filename) {
+ _fd = new Common::File();
+ if (!_fd->open(filename))
+ error("DatArchive::DatArchive() Could not open %s", filename);
+ _fd->skip(8); // Skip signature
+ _fd->skip(2); // Skip unknown
+ _fd->skip(2); // Skip unknown
+ _entriesCount = _fd->readUint32LE();
+ debug(1, "_entriesCount: %d", _entriesCount);
+ _fd->skip(4); // Skip unknown
+ _entries = new DatEntry[_entriesCount];
+ for (int i = 0; i < _entriesCount; ++i) {
+ _entries[i].ofs = _fd->readUint32LE();
+ _entries[i].outSize1 = _fd->readUint32LE();
+ _entries[i].type = _fd->readUint32LE();
+ _entries[i].outSize2 = _fd->readUint32LE();
+ }
+}
+
+DatArchive::~DatArchive() {
+ _fd->close();
+ delete _fd;
+ delete[] _entries;
+}
+
+byte *DatArchive::load(int index) {
+ _fd->seek(_entries[index].ofs);
+ debug(1, "_entries[index].outSize2: %d; _entries[index].outSize1: %d", _entries[index].outSize2, _entries[index].outSize1);
+ byte *buffer = new byte[_entries[index].outSize1];
+ if (!Common::decompressDCL(_fd, buffer, 0, _entries[index].outSize1))
+ error("DatArchive::load() Error during decompression of entry %d", index);
+ return buffer;
+}
+
+// DatManager
+
+DatManager::DatManager() {
+ for (int i = 0; i < kMaxDatArchives; ++i)
+ _datArchives[i] = 0;
+}
+
+DatManager::~DatManager() {
+ for (int i = 0; i < kMaxDatArchives; ++i)
+ delete _datArchives[i];
+}
+
+void DatManager::open(int index, const char *filename) {
+ close(index);
+ _datArchives[index] = new DatArchive(filename);
+}
+
+void DatManager::close(int index) {
+ delete _datArchives[index];
+ _datArchives[index] = 0;
+}
+
+byte *DatManager::loadResource(int resourceId) {
+ const int datIndex = ridToDatIndex(resourceId);
+ const int entryIndex = ridToEntryIndex(resourceId);
+ return _datArchives[datIndex] ? _datArchives[datIndex]->load(entryIndex) : 0;
+}
+
+uint32 DatManager::getResourceType(int resourceId) {
+ const int datIndex = ridToDatIndex(resourceId);
+ const int entryIndex = ridToEntryIndex(resourceId);
+ return _datArchives[datIndex] ? _datArchives[datIndex]->getEntryType(entryIndex) : 0;
+}
+
+uint32 DatManager::getResourceSize(int resourceId) {
+ const int datIndex = ridToDatIndex(resourceId);
+ const int entryIndex = ridToEntryIndex(resourceId);
+ return _datArchives[datIndex] ? _datArchives[datIndex]->getEntrySize(entryIndex) : 0;
+}
+
+int ridToDatIndex(int resourceId) {
+ return (resourceId & 0xFFFF0000) >> 16;
+}
+
+int ridToEntryIndex(int resourceId) {
+ return resourceId & 0xFFFF;
+}
+
+int makeRid(int datIndex, int entryIndex) {
+ return (datIndex << 16) | entryIndex;
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/datarchive.h b/engines/gnap/datarchive.h
new file mode 100644
index 0000000000..2fd431bf70
--- /dev/null
+++ b/engines/gnap/datarchive.h
@@ -0,0 +1,80 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GNAP_DATARCHIVE_H
+#define GNAP_DATARCHIVE_H
+
+#include "common/array.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/memstream.h"
+#include "common/random.h"
+#include "common/str.h"
+#include "common/substream.h"
+#include "common/system.h"
+#include "engines/engine.h"
+
+namespace Gnap {
+
+struct DatEntry {
+ uint32 ofs;
+ uint32 outSize1;
+ uint32 type;
+ uint32 outSize2;
+};
+
+class DatArchive {
+public:
+ DatArchive(const char *filename);
+ ~DatArchive();
+ byte *load(int index);
+ int getCount() const { return _entriesCount; }
+ uint32 getEntryType(int index) { return _entries[index].type; }
+ uint32 getEntrySize(int index) { return _entries[index].outSize1; }
+protected:
+ Common::File *_fd;
+ int _entriesCount;
+ DatEntry *_entries;
+};
+
+const int kMaxDatArchives = 2;
+
+class DatManager {
+public:
+ DatManager();
+ ~DatManager();
+ void open(int index, const char *filename);
+ void close(int index);
+ byte *loadResource(int resourceId);
+ uint32 getResourceType(int resourceId);
+ uint32 getResourceSize(int resourceId);
+protected:
+ DatArchive *_datArchives[kMaxDatArchives];
+};
+
+int ridToDatIndex(int resourceId);
+int ridToEntryIndex(int resourceId);
+int makeRid(int datIndex, int entryIndex);
+
+} // End of namespace Gnap
+
+#endif // GNAP_DATARCHIVE_H
diff --git a/engines/gnap/detection.cpp b/engines/gnap/detection.cpp
new file mode 100644
index 0000000000..8898d9069a
--- /dev/null
+++ b/engines/gnap/detection.cpp
@@ -0,0 +1,195 @@
+/* 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 "common/config-manager.h"
+#include "engines/advancedDetector.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "base/plugins.h"
+#include "graphics/thumbnail.h"
+
+static const PlainGameDescriptor gnapGames[] = {
+ { "gnap", "Gnap" },
+ { 0, 0 }
+};
+
+namespace Gnap {
+
+static const ADGameDescription gameDescriptions[] = {
+ {
+ "gnap", "",
+ {
+ {"stock_n.dat", 0, "46819043d019a2f36b727cc2bdd6980f", 12515823},
+ AD_LISTEND
+ },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_NO_FLAGS, GUIO0()
+ },
+
+ AD_TABLE_END_MARKER
+};
+
+} // End of namespace Gnap
+
+class GnapMetaEngine : public AdvancedMetaEngine {
+public:
+ GnapMetaEngine() : AdvancedMetaEngine(Gnap::gameDescriptions, sizeof(ADGameDescription), gnapGames) {
+ _singleid = "gnap";
+ _maxScanDepth = 3;
+ }
+
+ virtual const char *getName() const {
+ return "Gnap";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "Gnap (C) 1999";
+ }
+
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual int getMaximumSaveSlot() const;
+ virtual SaveStateList listSaves(const char *target) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+ virtual void removeSaveState(const char *target, int slot) const;
+};
+
+bool GnapMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ false;
+#if 0
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail) ||
+ (f == kSavesSupportCreationDate);
+#endif
+}
+
+void GnapMetaEngine::removeSaveState(const char *target, int slot) const {
+ Common::String fileName = Common::String::format("%s.%03d", target, slot);
+ g_system->getSavefileManager()->removeSavefile(fileName);
+}
+
+int GnapMetaEngine::getMaximumSaveSlot() const { return 99; }
+
+SaveStateList GnapMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ Common::String pattern = target;
+ pattern += ".???";
+
+ filenames = saveFileMan->listSavefiles(pattern);
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+#if 0
+ int slotNum = 0;
+ for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ slotNum = atoi(filename->c_str() + filename->size() - 3);
+
+ if (slotNum >= 0 && slotNum <= 99) {
+ Common::InSaveFile *file = saveFileMan->openForLoading(*filename);
+ if (file) {
+ int32 version = file->readSint32BE();
+ if (version != GNAP_SAVEGAME_VERSION) {
+ delete file;
+ continue;
+ }
+
+ // read name
+ uint16 nameSize = file->readUint16BE();
+ if (nameSize >= 255) {
+ delete file;
+ continue;
+ }
+ char name[256];
+ file->read(name, nameSize);
+ name[nameSize] = 0;
+
+ saveList.push_back(SaveStateDescriptor(slotNum, name));
+ delete file;
+ }
+ }
+ }
+#endif
+ return saveList;
+}
+
+SaveStateDescriptor GnapMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+#if 0
+ Common::String fileName = Common::String::format("%s.%03d", target, slot);
+ Common::InSaveFile *file = g_system->getSavefileManager()->openForLoading(fileName);
+ if (file) {
+
+ int32 version = file->readSint32BE();
+ if (version != GNAP_SAVEGAME_VERSION) {
+ delete file;
+ return SaveStateDescriptor();
+ }
+
+ uint32 saveNameLength = file->readUint16BE();
+ char saveName[256];
+ file->read(saveName, saveNameLength);
+ saveName[saveNameLength] = 0;
+
+ SaveStateDescriptor desc(slot, saveName);
+
+ Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*file);
+ desc.setThumbnail(thumbnail);
+
+ uint32 saveDate = file->readUint32BE();
+ uint16 saveTime = file->readUint16BE();
+
+ int day = (saveDate >> 24) & 0xFF;
+ int month = (saveDate >> 16) & 0xFF;
+ int year = saveDate & 0xFFFF;
+
+ desc.setSaveDate(year, month, day);
+
+ int hour = (saveTime >> 8) & 0xFF;
+ int minutes = saveTime & 0xFF;
+
+ desc.setSaveTime(hour, minutes);
+
+ delete file;
+ return desc;
+ }
+#endif
+ return SaveStateDescriptor();
+}
+
+bool GnapMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ if (desc) {
+ *engine = new Gnap::GnapEngine(syst, desc);
+ }
+ return desc != 0;
+}
+
+#if PLUGIN_ENABLED_DYNAMIC(GNAP)
+ REGISTER_PLUGIN_DYNAMIC(GNAP, PLUGIN_TYPE_ENGINE, GnapMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(GNAP, PLUGIN_TYPE_ENGINE, GnapMetaEngine);
+#endif
diff --git a/engines/gnap/fontdata.h b/engines/gnap/fontdata.h
new file mode 100644
index 0000000000..9ad0d23ae8
--- /dev/null
+++ b/engines/gnap/fontdata.h
@@ -0,0 +1,851 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GNAP_FONTDATA_H
+#define GNAP_FONTDATA_H
+
+namespace Gnap {
+
+struct FONT_CHAR_INFO {
+ const byte width; // width, in bits (or pixels), of the character
+ const uint16 offset; // offset of the character's bitmap, in bytes, into the the FONT_INFO's data array
+};
+
+/*
+** Font data for DejaVu Sans 9pt
+*/
+
+/* Character bitmaps for DejaVu Sans 9pt */
+const byte dejaVuSans9ptCharBitmaps[] =
+{
+ /* @0 ' ' (5 pixels wide) */
+ 0x00, 0x00, /* */
+ 0x00, 0x00, /* */
+ 0x00, 0x00, /* */
+ 0x00, 0x00, /* */
+ 0x00, 0x00, /* */
+
+ /* @10 '!' (1 pixels wide) */
+ 0x1B, 0xF0, /* ## ###### */
+
+ /* @12 '"' (3 pixels wide) */
+ 0x00, 0x70, /* ### */
+ 0x00, 0x00, /* */
+ 0x00, 0x70, /* ### */
+
+ /* @18 '#' (8 pixels wide) */
+ 0x04, 0x00, /* # */
+ 0x14, 0x80, /* # # # */
+ 0x0F, 0x80, /* ##### */
+ 0x04, 0xE0, /* # ### */
+ 0x1C, 0x80, /* ### # */
+ 0x07, 0xC0, /* ##### */
+ 0x04, 0xA0, /* # # # */
+ 0x00, 0x80, /* # */
+
+ /* @34 '$' (5 pixels wide) */
+ 0x09, 0xC0, /* # ### */
+ 0x11, 0x20, /* # # # */
+ 0x7F, 0xF0, /* ########### */
+ 0x12, 0x20, /* # # # */
+ 0x0E, 0x40, /* ### # */
+
+ /* @44 '%' (10 pixels wide) */
+ 0x00, 0xE0, /* ### */
+ 0x01, 0x10, /* # # */
+ 0x11, 0x10, /* # # # */
+ 0x0C, 0xE0, /* ## ### */
+ 0x03, 0x00, /* ## */
+ 0x01, 0x80, /* ## */
+ 0x0E, 0x60, /* ### ## */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x00, /* # # */
+ 0x0E, 0x00, /* ### */
+
+ /* @64 '&' (8 pixels wide) */
+ 0x0E, 0x00, /* ### */
+ 0x19, 0xE0, /* ## #### */
+ 0x10, 0x90, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x12, 0x20, /* # # # */
+ 0x0C, 0x00, /* ## */
+ 0x14, 0x00, /* # # */
+ 0x13, 0x00, /* # ## */
+
+ /* @80 ''' (1 pixels wide) */
+ 0x00, 0x70, /* ### */
+
+ /* @82 '(' (3 pixels wide) */
+ 0x07, 0xC0, /* ##### */
+ 0x38, 0x38, /* ### ### */
+ 0x20, 0x08, /* # # */
+
+ /* @88 ')' (3 pixels wide) */
+ 0x20, 0x08, /* # # */
+ 0x38, 0x38, /* ### ### */
+ 0x07, 0xC0, /* ##### */
+
+ /* @94 '*' (5 pixels wide) */
+ 0x01, 0x20, /* # # */
+ 0x00, 0xC0, /* ## */
+ 0x03, 0xF0, /* ###### */
+ 0x00, 0xC0, /* ## */
+ 0x01, 0x20, /* # # */
+
+ /* @104 '+' (7 pixels wide) */
+ 0x02, 0x00, /* # */
+ 0x02, 0x00, /* # */
+ 0x02, 0x00, /* # */
+ 0x1F, 0xC0, /* ####### */
+ 0x02, 0x00, /* # */
+ 0x02, 0x00, /* # */
+ 0x02, 0x00, /* # */
+
+ /* @118 ',' (1 pixels wide) */
+ 0x38, 0x00, /* ### */
+
+ /* @120 '-' (3 pixels wide) */
+ 0x02, 0x00, /* # */
+ 0x02, 0x00, /* # */
+ 0x02, 0x00, /* # */
+
+ /* @126 '.' (1 pixels wide) */
+ 0x18, 0x00, /* ## */
+
+ /* @128 '/' (4 pixels wide) */
+ 0x30, 0x00, /* ## */
+ 0x0E, 0x00, /* ### */
+ 0x01, 0xC0, /* ### */
+ 0x00, 0x30, /* ## */
+
+ /* @136 '0' (6 pixels wide) */
+ 0x07, 0xC0, /* ##### */
+ 0x18, 0x30, /* ## ## */
+ 0x10, 0x10, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x18, 0x30, /* ## ## */
+ 0x07, 0xC0, /* ##### */
+
+ /* @148 '1' (5 pixels wide) */
+ 0x10, 0x10, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x1F, 0xF0, /* ######### */
+ 0x10, 0x00, /* # */
+ 0x10, 0x00, /* # */
+
+ /* @158 '2' (6 pixels wide) */
+ 0x10, 0x20, /* # # */
+ 0x18, 0x10, /* ## # */
+ 0x14, 0x10, /* # # # */
+ 0x12, 0x10, /* # # # */
+ 0x11, 0x30, /* # # ## */
+ 0x10, 0xE0, /* # ### */
+
+ /* @170 '3' (6 pixels wide) */
+ 0x08, 0x20, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x0E, 0xE0, /* ### ### */
+
+ /* @182 '4' (6 pixels wide) */
+ 0x06, 0x00, /* ## */
+ 0x05, 0x80, /* # ## */
+ 0x04, 0x40, /* # # */
+ 0x04, 0x30, /* # ## */
+ 0x1F, 0xF0, /* ######### */
+ 0x04, 0x00, /* # */
+
+ /* @194 '5' (6 pixels wide) */
+ 0x08, 0xF0, /* # #### */
+ 0x10, 0x90, /* # # # */
+ 0x10, 0x90, /* # # # */
+ 0x10, 0x90, /* # # # */
+ 0x19, 0x90, /* ## ## # */
+ 0x0F, 0x00, /* #### */
+
+ /* @206 '6' (6 pixels wide) */
+ 0x07, 0xC0, /* ##### */
+ 0x19, 0x20, /* ## # # */
+ 0x10, 0x90, /* # # # */
+ 0x10, 0x90, /* # # # */
+ 0x19, 0x90, /* ## ## # */
+ 0x0F, 0x20, /* #### # */
+
+ /* @218 '7' (6 pixels wide) */
+ 0x00, 0x10, /* # */
+ 0x10, 0x10, /* # # */
+ 0x0C, 0x10, /* ## # */
+ 0x03, 0x10, /* ## # */
+ 0x00, 0xD0, /* ## # */
+ 0x00, 0x30, /* ## */
+
+ /* @230 '8' (6 pixels wide) */
+ 0x0E, 0xE0, /* ### ### */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x0E, 0xE0, /* ### ### */
+
+ /* @242 '9' (6 pixels wide) */
+ 0x09, 0xE0, /* # #### */
+ 0x13, 0x30, /* # ## ## */
+ 0x12, 0x10, /* # # # */
+ 0x12, 0x10, /* # # # */
+ 0x09, 0x30, /* # # ## */
+ 0x07, 0xC0, /* ##### */
+
+ /* @254 ':' (1 pixels wide) */
+ 0x19, 0x80, /* ## ## */
+
+ /* @256 ';' (1 pixels wide) */
+ 0x39, 0x80, /* ### ## */
+
+ /* @258 '<' (8 pixels wide) */
+ 0x03, 0x00, /* ## */
+ 0x03, 0x00, /* ## */
+ 0x03, 0x00, /* ## */
+ 0x04, 0x80, /* # # */
+ 0x04, 0x80, /* # # */
+ 0x04, 0x80, /* # # */
+ 0x0C, 0xC0, /* ## ## */
+ 0x08, 0x40, /* # # */
+
+ /* @274 '=' (8 pixels wide) */
+ 0x05, 0x00, /* # # */
+ 0x05, 0x00, /* # # */
+ 0x05, 0x00, /* # # */
+ 0x05, 0x00, /* # # */
+ 0x05, 0x00, /* # # */
+ 0x05, 0x00, /* # # */
+ 0x05, 0x00, /* # # */
+ 0x05, 0x00, /* # # */
+
+ /* @290 '>' (8 pixels wide) */
+ 0x08, 0x40, /* # # */
+ 0x0C, 0xC0, /* ## ## */
+ 0x04, 0x80, /* # # */
+ 0x04, 0x80, /* # # */
+ 0x04, 0x80, /* # # */
+ 0x03, 0x00, /* ## */
+ 0x03, 0x00, /* ## */
+ 0x03, 0x00, /* ## */
+
+ /* @306 '?' (5 pixels wide) */
+ 0x00, 0x20, /* # */
+ 0x00, 0x10, /* # */
+ 0x1B, 0x10, /* ## ## # */
+ 0x00, 0x90, /* # # */
+ 0x00, 0x60, /* ## */
+
+ /* @316 '@' (11 pixels wide) */
+ 0x0F, 0x80, /* ##### */
+ 0x10, 0x40, /* # # */
+ 0x20, 0x20, /* # # */
+ 0x47, 0x10, /* # ### # */
+ 0x48, 0x90, /* # # # # */
+ 0x48, 0x90, /* # # # # */
+ 0x48, 0x90, /* # # # # */
+ 0x4F, 0x90, /* # ##### # */
+ 0x28, 0x20, /* # # # */
+ 0x04, 0x60, /* # ## */
+ 0x03, 0x80, /* ### */
+
+ /* @338 'A' (8 pixels wide) */
+ 0x10, 0x00, /* # */
+ 0x0E, 0x00, /* ### */
+ 0x05, 0xC0, /* # ### */
+ 0x04, 0x30, /* # ## */
+ 0x04, 0x30, /* # ## */
+ 0x05, 0xC0, /* # ### */
+ 0x0E, 0x00, /* ### */
+ 0x10, 0x00, /* # */
+
+ /* @354 'B' (6 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x0E, 0xE0, /* ### ### */
+
+ /* @366 'C' (6 pixels wide) */
+ 0x07, 0xC0, /* ##### */
+ 0x08, 0x20, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x08, 0x20, /* # # */
+
+ /* @378 'D' (7 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+ 0x10, 0x10, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x08, 0x20, /* # # */
+ 0x07, 0xC0, /* ##### */
+
+ /* @392 'E' (6 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+
+ /* @404 'F' (5 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+ 0x01, 0x10, /* # # */
+ 0x01, 0x10, /* # # */
+ 0x01, 0x10, /* # # */
+ 0x01, 0x10, /* # # */
+
+ /* @414 'G' (7 pixels wide) */
+ 0x07, 0xC0, /* ##### */
+ 0x08, 0x20, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x0F, 0x20, /* #### # */
+
+ /* @428 'H' (7 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+ 0x01, 0x00, /* # */
+ 0x01, 0x00, /* # */
+ 0x01, 0x00, /* # */
+ 0x01, 0x00, /* # */
+ 0x01, 0x00, /* # */
+ 0x1F, 0xF0, /* ######### */
+
+ /* @442 'I' (1 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+
+ /* @444 'J' (3 pixels wide) */
+ 0x40, 0x00, /* # */
+ 0x40, 0x00, /* # */
+ 0x3F, 0xF0, /* ########## */
+
+ /* @450 'K' (6 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+ 0x01, 0x00, /* # */
+ 0x02, 0x80, /* # # */
+ 0x04, 0x40, /* # # */
+ 0x08, 0x20, /* # # */
+ 0x10, 0x10, /* # # */
+
+ /* @462 'L' (5 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+ 0x10, 0x00, /* # */
+ 0x10, 0x00, /* # */
+ 0x10, 0x00, /* # */
+ 0x10, 0x00, /* # */
+
+ /* @472 'M' (8 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+ 0x00, 0x60, /* ## */
+ 0x01, 0x80, /* ## */
+ 0x06, 0x00, /* ## */
+ 0x06, 0x00, /* ## */
+ 0x01, 0x80, /* ## */
+ 0x00, 0x60, /* ## */
+ 0x1F, 0xF0, /* ######### */
+
+ /* @488 'N' (7 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+ 0x00, 0x30, /* ## */
+ 0x00, 0xC0, /* ## */
+ 0x01, 0x00, /* # */
+ 0x06, 0x00, /* ## */
+ 0x18, 0x00, /* ## */
+ 0x1F, 0xF0, /* ######### */
+
+ /* @502 'O' (7 pixels wide) */
+ 0x07, 0xC0, /* ##### */
+ 0x08, 0x20, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x08, 0x20, /* # # */
+ 0x07, 0xC0, /* ##### */
+
+ /* @516 'P' (6 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+ 0x01, 0x10, /* # # */
+ 0x01, 0x10, /* # # */
+ 0x01, 0x10, /* # # */
+ 0x01, 0x10, /* # # */
+ 0x00, 0xE0, /* ### */
+
+ /* @528 'Q' (7 pixels wide) */
+ 0x07, 0xC0, /* ##### */
+ 0x08, 0x20, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x10, 0x10, /* # # */
+ 0x30, 0x10, /* ## # */
+ 0x48, 0x20, /* # # # */
+ 0x07, 0xC0, /* ##### */
+
+ /* @542 'R' (7 pixels wide) */
+ 0x1F, 0xF0, /* ######### */
+ 0x01, 0x10, /* # # */
+ 0x01, 0x10, /* # # */
+ 0x01, 0x10, /* # # */
+ 0x03, 0x10, /* ## # */
+ 0x0C, 0xE0, /* ## ### */
+ 0x10, 0x00, /* # */
+
+ /* @556 'S' (6 pixels wide) */
+ 0x08, 0xE0, /* # ### */
+ 0x11, 0x90, /* # ## # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x0E, 0x20, /* ### # */
+
+ /* @568 'T' (7 pixels wide) */
+ 0x00, 0x10, /* # */
+ 0x00, 0x10, /* # */
+ 0x00, 0x10, /* # */
+ 0x1F, 0xF0, /* ######### */
+ 0x00, 0x10, /* # */
+ 0x00, 0x10, /* # */
+ 0x00, 0x10, /* # */
+
+ /* @582 'U' (7 pixels wide) */
+ 0x0F, 0xF0, /* ######## */
+ 0x18, 0x00, /* ## */
+ 0x10, 0x00, /* # */
+ 0x10, 0x00, /* # */
+ 0x10, 0x00, /* # */
+ 0x18, 0x00, /* ## */
+ 0x0F, 0xF0, /* ######## */
+
+ /* @596 'V' (8 pixels wide) */
+ 0x00, 0x30, /* ## */
+ 0x01, 0xC0, /* ### */
+ 0x06, 0x00, /* ## */
+ 0x18, 0x00, /* ## */
+ 0x18, 0x00, /* ## */
+ 0x06, 0x00, /* ## */
+ 0x01, 0xC0, /* ### */
+ 0x00, 0x30, /* ## */
+
+ /* @612 'W' (11 pixels wide) */
+ 0x00, 0x10, /* # */
+ 0x00, 0xE0, /* ### */
+ 0x07, 0x00, /* ### */
+ 0x18, 0x00, /* ## */
+ 0x07, 0x80, /* #### */
+ 0x00, 0x70, /* ### */
+ 0x07, 0x80, /* #### */
+ 0x18, 0x00, /* ## */
+ 0x07, 0x00, /* ### */
+ 0x00, 0xE0, /* ### */
+ 0x00, 0x10, /* # */
+
+ /* @634 'X' (7 pixels wide) */
+ 0x10, 0x10, /* # # */
+ 0x08, 0x30, /* # ## */
+ 0x06, 0xC0, /* ## ## */
+ 0x01, 0x00, /* # */
+ 0x06, 0xC0, /* ## ## */
+ 0x08, 0x30, /* # ## */
+ 0x10, 0x10, /* # # */
+
+ /* @648 'Y' (7 pixels wide) */
+ 0x00, 0x10, /* # */
+ 0x00, 0x60, /* ## */
+ 0x01, 0x80, /* ## */
+ 0x1E, 0x00, /* #### */
+ 0x01, 0x80, /* ## */
+ 0x00, 0x60, /* ## */
+ 0x00, 0x10, /* # */
+
+ /* @662 'Z' (7 pixels wide) */
+ 0x18, 0x10, /* ## # */
+ 0x14, 0x10, /* # # # */
+ 0x12, 0x10, /* # # # */
+ 0x11, 0x10, /* # # # */
+ 0x10, 0x90, /* # # # */
+ 0x10, 0x50, /* # # # */
+ 0x10, 0x30, /* # ## */
+
+ /* @676 '[' (2 pixels wide) */
+ 0x7F, 0xF0, /* ########### */
+ 0x40, 0x10, /* # # */
+
+ /* @680 '\' (4 pixels wide) */
+ 0x00, 0x30, /* ## */
+ 0x01, 0xC0, /* ### */
+ 0x0E, 0x00, /* ### */
+ 0x30, 0x00, /* ## */
+
+ /* @688 ']' (2 pixels wide) */
+ 0x40, 0x10, /* # # */
+ 0x7F, 0xF0, /* ########### */
+
+ /* @692 '^' (6 pixels wide) */
+ 0x00, 0x40, /* # */
+ 0x00, 0x20, /* # */
+ 0x00, 0x10, /* # */
+ 0x00, 0x10, /* # */
+ 0x00, 0x20, /* # */
+ 0x00, 0x40, /* # */
+
+ /* @704 '_' (6 pixels wide) */
+ 0x80, 0x00, /* # */
+ 0x80, 0x00, /* # */
+ 0x80, 0x00, /* # */
+ 0x80, 0x00, /* # */
+ 0x80, 0x00, /* # */
+ 0x80, 0x00, /* # */
+
+ /* @716 '`' (2 pixels wide) */
+ 0x00, 0x08, /* # */
+ 0x00, 0x10, /* # */
+
+ /* @720 'a' (6 pixels wide) */
+ 0x0C, 0x80, /* ## # */
+ 0x12, 0x40, /* # # # */
+ 0x12, 0x40, /* # # # */
+ 0x12, 0x40, /* # # # */
+ 0x0A, 0x40, /* # # # */
+ 0x1F, 0x80, /* ###### */
+
+ /* @732 'b' (6 pixels wide) */
+ 0x1F, 0xF8, /* ########## */
+ 0x18, 0xC0, /* ## ## */
+ 0x10, 0x40, /* # # */
+ 0x10, 0x40, /* # # */
+ 0x18, 0xC0, /* ## ## */
+ 0x0F, 0x80, /* ##### */
+
+ /* @744 'c' (5 pixels wide) */
+ 0x0F, 0x80, /* ##### */
+ 0x18, 0xC0, /* ## ## */
+ 0x10, 0x40, /* # # */
+ 0x10, 0x40, /* # # */
+ 0x08, 0x80, /* # # */
+
+ /* @754 'd' (6 pixels wide) */
+ 0x0F, 0x80, /* ##### */
+ 0x18, 0xC0, /* ## ## */
+ 0x10, 0x40, /* # # */
+ 0x10, 0x40, /* # # */
+ 0x18, 0xC0, /* ## ## */
+ 0x1F, 0xF8, /* ########## */
+
+ /* @766 'e' (6 pixels wide) */
+ 0x0F, 0x80, /* ##### */
+ 0x0A, 0xC0, /* # # ## */
+ 0x12, 0x40, /* # # # */
+ 0x12, 0x40, /* # # # */
+ 0x12, 0xC0, /* # # ## */
+ 0x0B, 0x80, /* # ### */
+
+ /* @778 'f' (4 pixels wide) */
+ 0x00, 0x40, /* # */
+ 0x1F, 0xF0, /* ######### */
+ 0x00, 0x48, /* # # */
+ 0x00, 0x48, /* # # */
+
+ /* @786 'g' (6 pixels wide) */
+ 0x0F, 0x80, /* ##### */
+ 0x58, 0xC0, /* # ## ## */
+ 0x90, 0x40, /* # # # */
+ 0x90, 0x40, /* # # # */
+ 0xD8, 0xC0, /* ## ## ## */
+ 0x7F, 0xC0, /* ######### */
+
+ /* @798 'h' (6 pixels wide) */
+ 0x1F, 0xF8, /* ########## */
+ 0x00, 0x80, /* # */
+ 0x00, 0x40, /* # */
+ 0x00, 0x40, /* # */
+ 0x00, 0x40, /* # */
+ 0x1F, 0x80, /* ###### */
+
+ /* @810 'i' (1 pixels wide) */
+ 0x1F, 0xD0, /* ####### # */
+
+ /* @812 'j' (2 pixels wide) */
+ 0x80, 0x00, /* # */
+ 0xFF, 0xD0, /* ########## # */
+
+ /* @816 'k' (5 pixels wide) */
+ 0x1F, 0xF8, /* ########## */
+ 0x02, 0x00, /* # */
+ 0x05, 0x00, /* # # */
+ 0x08, 0x80, /* # # */
+ 0x10, 0x40, /* # # */
+
+ /* @826 'l' (1 pixels wide) */
+ 0x1F, 0xF8, /* ########## */
+
+ /* @828 'm' (9 pixels wide) */
+ 0x1F, 0xC0, /* ####### */
+ 0x00, 0x40, /* # */
+ 0x00, 0x40, /* # */
+ 0x00, 0x40, /* # */
+ 0x1F, 0x80, /* ###### */
+ 0x00, 0x40, /* # */
+ 0x00, 0x40, /* # */
+ 0x00, 0x40, /* # */
+ 0x1F, 0x80, /* ###### */
+
+ /* @846 'n' (6 pixels wide) */
+ 0x1F, 0xC0, /* ####### */
+ 0x00, 0x80, /* # */
+ 0x00, 0x40, /* # */
+ 0x00, 0x40, /* # */
+ 0x00, 0x40, /* # */
+ 0x1F, 0x80, /* ###### */
+
+ /* @858 'o' (6 pixels wide) */
+ 0x0F, 0x80, /* ##### */
+ 0x18, 0xC0, /* ## ## */
+ 0x10, 0x40, /* # # */
+ 0x10, 0x40, /* # # */
+ 0x18, 0xC0, /* ## ## */
+ 0x0F, 0x80, /* ##### */
+
+ /* @870 'p' (6 pixels wide) */
+ 0xFF, 0xC0, /* ########## */
+ 0x18, 0xC0, /* ## ## */
+ 0x10, 0x40, /* # # */
+ 0x10, 0x40, /* # # */
+ 0x18, 0xC0, /* ## ## */
+ 0x0F, 0x80, /* ##### */
+
+ /* @882 'q' (6 pixels wide) */
+ 0x0F, 0x80, /* ##### */
+ 0x18, 0xC0, /* ## ## */
+ 0x10, 0x40, /* # # */
+ 0x10, 0x40, /* # # */
+ 0x18, 0xC0, /* ## ## */
+ 0xFF, 0xC0, /* ########## */
+
+ /* @894 'r' (4 pixels wide) */
+ 0x1F, 0xC0, /* ####### */
+ 0x00, 0x80, /* # */
+ 0x00, 0x40, /* # */
+ 0x00, 0x40, /* # */
+
+ /* @902 's' (5 pixels wide) */
+ 0x09, 0x80, /* # ## */
+ 0x12, 0x40, /* # # # */
+ 0x12, 0x40, /* # # # */
+ 0x12, 0x40, /* # # # */
+ 0x0C, 0x80, /* ## # */
+
+ /* @912 't' (4 pixels wide) */
+ 0x00, 0x40, /* # */
+ 0x1F, 0xF0, /* ######### */
+ 0x10, 0x40, /* # # */
+ 0x10, 0x40, /* # # */
+
+ /* @920 'u' (6 pixels wide) */
+ 0x0F, 0xC0, /* ###### */
+ 0x10, 0x00, /* # */
+ 0x10, 0x00, /* # */
+ 0x10, 0x00, /* # */
+ 0x08, 0x00, /* # */
+ 0x1F, 0xC0, /* ####### */
+
+ /* @932 'v' (6 pixels wide) */
+ 0x00, 0xC0, /* ## */
+ 0x07, 0x00, /* ### */
+ 0x18, 0x00, /* ## */
+ 0x18, 0x00, /* ## */
+ 0x07, 0x00, /* ### */
+ 0x00, 0xC0, /* ## */
+
+ /* @944 'w' (9 pixels wide) */
+ 0x00, 0xC0, /* ## */
+ 0x07, 0x00, /* ### */
+ 0x18, 0x00, /* ## */
+ 0x07, 0x00, /* ### */
+ 0x00, 0xC0, /* ## */
+ 0x07, 0x00, /* ### */
+ 0x18, 0x00, /* ## */
+ 0x07, 0x00, /* ### */
+ 0x00, 0xC0, /* ## */
+
+ /* @962 'x' (6 pixels wide) */
+ 0x10, 0x40, /* # # */
+ 0x0D, 0x80, /* ## ## */
+ 0x02, 0x00, /* # */
+ 0x02, 0x00, /* # */
+ 0x0D, 0x80, /* ## ## */
+ 0x10, 0x40, /* # # */
+
+ /* @974 'y' (6 pixels wide) */
+ 0x80, 0xC0, /* # ## */
+ 0x83, 0x00, /* # ## */
+ 0x4C, 0x00, /* # ## */
+ 0x38, 0x00, /* ### */
+ 0x07, 0x00, /* ### */
+ 0x00, 0xC0, /* ## */
+
+ /* @986 'z' (5 pixels wide) */
+ 0x18, 0x40, /* ## # */
+ 0x14, 0x40, /* # # # */
+ 0x12, 0x40, /* # # # */
+ 0x11, 0x40, /* # # # */
+ 0x10, 0xC0, /* # ## */
+
+ /* @996 '{' (5 pixels wide) */
+ 0x02, 0x00, /* # */
+ 0x02, 0x00, /* # */
+ 0x7D, 0xF0, /* ##### ##### */
+ 0x40, 0x10, /* # # */
+ 0x40, 0x10, /* # # */
+
+ /* @1006 '|' (1 pixels wide) */
+ 0xFF, 0xF0, /* ############ */
+
+ /* @1008 '}' (5 pixels wide) */
+ 0x40, 0x10, /* # # */
+ 0x40, 0x10, /* # # */
+ 0x7D, 0xF0, /* ##### ##### */
+ 0x02, 0x00, /* # */
+ 0x02, 0x00, /* # */
+
+ /* @1018 '~' (8 pixels wide) */
+ 0x02, 0x00, /* # */
+ 0x01, 0x00, /* # */
+ 0x01, 0x00, /* # */
+ 0x01, 0x00, /* # */
+ 0x02, 0x00, /* # */
+ 0x02, 0x00, /* # */
+ 0x02, 0x00, /* # */
+ 0x01, 0x00, /* # */
+};
+
+/* Character descriptors for DejaVu Sans 9pt */
+/* { [Char width in bits], [Offset into dejaVuSans9ptCharBitmaps in bytes] } */
+const FONT_CHAR_INFO dejaVuSans9ptCharDescriptors[] =
+{
+ {5, 0}, /* */
+ {1, 10}, /* ! */
+ {3, 12}, /* " */
+ {8, 18}, /* # */
+ {5, 34}, /* $ */
+ {10, 44}, /* % */
+ {8, 64}, /* & */
+ {1, 80}, /* ' */
+ {3, 82}, /* ( */
+ {3, 88}, /* ) */
+ {5, 94}, /* * */
+ {7, 104}, /* + */
+ {1, 118}, /* , */
+ {3, 120}, /* - */
+ {1, 126}, /* . */
+ {4, 128}, /* / */
+ {6, 136}, /* 0 */
+ {5, 148}, /* 1 */
+ {6, 158}, /* 2 */
+ {6, 170}, /* 3 */
+ {6, 182}, /* 4 */
+ {6, 194}, /* 5 */
+ {6, 206}, /* 6 */
+ {6, 218}, /* 7 */
+ {6, 230}, /* 8 */
+ {6, 242}, /* 9 */
+ {1, 254}, /* : */
+ {1, 256}, /* ; */
+ {8, 258}, /* < */
+ {8, 274}, /* = */
+ {8, 290}, /* > */
+ {5, 306}, /* ? */
+ {11, 316}, /* @ */
+ {8, 338}, /* A */
+ {6, 354}, /* B */
+ {6, 366}, /* C */
+ {7, 378}, /* D */
+ {6, 392}, /* E */
+ {5, 404}, /* F */
+ {7, 414}, /* G */
+ {7, 428}, /* H */
+ {1, 442}, /* I */
+ {3, 444}, /* J */
+ {6, 450}, /* K */
+ {5, 462}, /* L */
+ {8, 472}, /* M */
+ {7, 488}, /* N */
+ {7, 502}, /* O */
+ {6, 516}, /* P */
+ {7, 528}, /* Q */
+ {7, 542}, /* R */
+ {6, 556}, /* S */
+ {7, 568}, /* T */
+ {7, 582}, /* U */
+ {8, 596}, /* V */
+ {11, 612}, /* W */
+ {7, 634}, /* X */
+ {7, 648}, /* Y */
+ {7, 662}, /* Z */
+ {2, 676}, /* [ */
+ {4, 680}, /* \ */
+ {2, 688}, /* ] */
+ {6, 692}, /* ^ */
+ {6, 704}, /* _ */
+ {2, 716}, /* ` */
+ {6, 720}, /* a */
+ {6, 732}, /* b */
+ {5, 744}, /* c */
+ {6, 754}, /* d */
+ {6, 766}, /* e */
+ {4, 778}, /* f */
+ {6, 786}, /* g */
+ {6, 798}, /* h */
+ {1, 810}, /* i */
+ {2, 812}, /* j */
+ {5, 816}, /* k */
+ {1, 826}, /* l */
+ {9, 828}, /* m */
+ {6, 846}, /* n */
+ {6, 858}, /* o */
+ {6, 870}, /* p */
+ {6, 882}, /* q */
+ {4, 894}, /* r */
+ {5, 902}, /* s */
+ {4, 912}, /* t */
+ {6, 920}, /* u */
+ {6, 932}, /* v */
+ {9, 944}, /* w */
+ {6, 962}, /* x */
+ {6, 974}, /* y */
+ {5, 986}, /* z */
+ {5, 996}, /* { */
+ {1, 1006}, /* | */
+ {5, 1008}, /* } */
+ {8, 1018}, /* ~ */
+};
+
+} // End of namespace Gnap
+
+#endif // GNAP_RESOURCE_H
diff --git a/engines/gnap/gamesys.cpp b/engines/gnap/gamesys.cpp
new file mode 100644
index 0000000000..d6f8db8c7a
--- /dev/null
+++ b/engines/gnap/gamesys.cpp
@@ -0,0 +1,1303 @@
+/* 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/gamesys.h"
+#include "gnap/fontdata.h"
+#include "graphics/fontman.h"
+#include "graphics/font.h"
+#include "graphics/decoders/bmp.h"
+
+namespace Gnap {
+
+void GfxItem::testUpdRect(const Common::Rect &updRect) {
+ Common::Rect intersectingRect;
+ if (!updFlag && prevFrame.spriteId != -1 &&
+ updRectsCount < 20 && intersectRect(intersectingRect, prevFrame.rect, updRect))
+ updRects[updRectsCount++] = intersectingRect;
+}
+
+// GameSys
+
+GameSys::GameSys(GnapEngine *vm)
+ : _vm(vm) {
+
+ _newSpriteDrawItemsCount = 0;
+ _removeSequenceItemsCount = 0;
+ _removeSpriteDrawItemsCount = 0;
+ _grabSpriteId = -1;
+ _grabSpriteChanged = false;
+ _reqRemoveSequenceItem = false;
+ _removeSequenceItemSequenceId = -1;
+ _removeSequenceItemValue = 0;
+ _gfxItemsCount = 0;
+ _animationsCount = 0;
+ _backgroundImageValue3 = 0;
+ _backgroundImageValue1 = 0;
+ _backgroundImageValue4 = 0;
+ _backgroundImageValue2 = 0;
+ _backgroundImageError = true;
+ _gameSysClock = 0;
+ _lastUpdateClock = 0;
+ _backgroundSurface = 0;
+ _frontSurface = 0;
+ for (int i = 0; i < kMaxAnimations; ++i) {
+ _animations[i].sequenceId = -1;
+ _animations[i].id = 0;
+ _animations[i].status = 0;
+ }
+ _screenRect = Common::Rect(0, 0, 800, 600);
+}
+
+GameSys::~GameSys() {
+}
+
+void GameSys::insertSequence(int sequenceId, int a2, int sequenceId2, int a4, int flags, int totalDuration, int16 x, int16 y) {
+ debug(0, "GameSys::insertSequence() [%08X, %d] -> [%08X, %d] (%d, %d)", sequenceId, a2, sequenceId2, a4, x, y);
+ Sequence sequence;
+ SequenceResource *sequenceResource = _vm->_sequenceCache->get(sequenceId);
+ sequenceResource->_sequenceId = sequenceId;
+ sequence.sequenceId = sequenceId;
+ sequence.id = a2 != -1 ? a2 : sequenceResource->_field_8;
+ sequence.sequenceId2 = sequenceId2 != (int32)0x80000000 ? sequenceId2 : sequenceResource->_sequenceId2;
+ sequence.id2 = a4 != -1 ? a4 : sequenceResource->_field_10;
+ sequence.flags = flags != -1 ? flags : sequenceResource->_flags;
+ sequence.totalDuration = totalDuration != -1 ? totalDuration : sequenceResource->_totalDuration;
+ sequence.x = (x < 10000 && x > -10000) ? x : sequenceResource->_xOffs;
+ sequence.y = (y < 10000 && y > -10000) ? y : sequenceResource->_yOffs;
+ _fatSequenceItems.push_back(sequence);
+}
+
+void GameSys::insertDirtyRect(const Common::Rect &rect) {
+ _dirtyRects.push_back(rect);
+}
+
+void GameSys::removeSequence(int sequenceId, int a2, int a3) {
+ //WaitForSingleObject(removeSequence2Mutex, INFINITE);
+ if (_removeSequenceItemsCount < kMaxSequenceItems) {
+ _removeSequenceItems[_removeSequenceItemsCount].sequenceId = sequenceId;
+ _removeSequenceItems[_removeSequenceItemsCount].id = a2;
+ _removeSequenceItems[_removeSequenceItemsCount].a3 = a3;
+ ++_removeSequenceItemsCount;
+ //ResetEvent(removeSequenceItemsEvent);
+ //ReleaseMutex(removeSequence2Mutex);
+ //WaitForSingleObject(removeSequenceItemsEvent, INFINITE);
+ }
+}
+
+void GameSys::invalidateGrabCursorSprite(int id, Common::Rect &rect, Graphics::Surface *surface1, Graphics::Surface *surface2) {
+ //WaitForSingleObject(grabSpriteMutex, INFINITE);
+ _grabSpriteId = id;
+ _grabSpriteRect = rect;
+ _grabSpriteSurface2 = surface2;
+ _grabSpriteSurface1 = surface1;
+ //ResetEvent(grabSpriteEvent);
+ _grabSpriteChanged = true;
+ //ReleaseMutex(grabSpriteMutex);
+ //WaitForSingleObject(grabSpriteEvent, INFINITE);
+}
+
+void GameSys::requestClear2(int a1) {
+ _fatSequenceItems.clear();
+ _seqItems.clear();
+ for (int i = 0; i < _gfxItemsCount; ++i) {
+ GfxItem *gfxItem = &_gfxItems[i];
+ gfxItem->sequenceId = -1;
+ gfxItem->animation = 0;
+ gfxItem->soundValue = 0;
+ if (a1) {
+ gfxItem->currFrame.duration = 0;
+ gfxItem->currFrame.spriteId = -1;
+ gfxItem->currFrame.soundId = -1;
+ gfxItem->currFrame.unkValue = -1;
+ gfxItem->updFlag = true;
+ } else {
+ gfxItem->updFlag = false;
+ }
+ }
+ _lastUpdateClock = 0;
+ _gameSysClock = 0;
+}
+
+void GameSys::requestClear1() {
+ _gfxItemsCount = 0;
+ _fatSequenceItems.clear();
+ _seqItems.clear();
+ _lastUpdateClock = 0;
+ _gameSysClock = 0;
+}
+
+void GameSys::requestRemoveSequence(int sequenceId, int a2) {
+ //WaitForSingleObject(removeSequence2Mutex, INFINITE);
+ _reqRemoveSequenceItem = true;
+ _removeSequenceItemSequenceId = sequenceId;
+ _removeSequenceItemValue = a2;
+
+ handleReqRemoveSequenceItem();//CHECKME?
+
+ //ResetEvent(reqClearEvent);
+ //ReleaseMutex(removeSequence2Mutex);
+ //WaitForSingleObject(reqClearEvent, INFINITE);
+}
+
+void GameSys::waitForUpdate() {
+ //ResetEvent(updateEvent);
+ //WaitForSingleObject(updateEvent, INFINITE);
+}
+
+int GameSys::isSequenceActive(int sequenceId, int a2) {
+ for (uint i = 0; i < _seqItems.size(); ++i)
+ if (_seqItems[i].sequenceId == sequenceId && _seqItems[i].id == a2)
+ return true;
+ return false;
+}
+
+void GameSys::setBackgroundSurface(Graphics::Surface *surface, int a4, int a5, int a6, int a7) {
+
+ debug(1, "GameSys::setBackgroundSurface() Setting background image");
+
+ _backgroundSurface = surface;
+ if (!_backgroundSurface) {
+ _backgroundImageError = true;
+ return;
+ }
+
+ if (!_frontSurface || _frontSurface->w != surface->w || _frontSurface->h != surface->h) {
+ debug(1, "GameSys::setBackgroundSurface() Creating background working surface");
+ if (_frontSurface)
+ _frontSurface->free();
+ delete _frontSurface;
+ _frontSurface = new Graphics::Surface();
+ _frontSurface->create(surface->w, surface->h, surface->format);
+ }
+
+ memcpy(_frontSurface->getPixels(), surface->getPixels(), surface->pitch * surface->h);
+
+ _vm->_system->copyRectToScreen(_frontSurface->getPixels(), _frontSurface->pitch, 0, 0, _frontSurface->w, _frontSurface->h);
+
+ _backgroundImageError = false;
+ _backgroundImageValue1 = a4;
+ _backgroundImageValue3 = a6;
+ _backgroundImageValue2 = a5;
+ _backgroundImageValue4 = a7;
+ _lastUpdateClock = 0;
+ _gameSysClock = 0;
+
+}
+
+void GameSys::setScaleValues(int a1, int a2, int a3, int a4) {
+ _backgroundImageValue1 = a1;
+ _backgroundImageValue3 = a3;
+ _backgroundImageValue2 = a2;
+ _backgroundImageValue4 = a4;
+}
+
+void GameSys::insertSpriteDrawItem(Graphics::Surface *surface, int x, int y, int id) {
+ if (surface && _newSpriteDrawItemsCount < kMaxSpriteDrawItems) {
+ _newSpriteDrawItems[_newSpriteDrawItemsCount].id = id;
+ _newSpriteDrawItems[_newSpriteDrawItemsCount].rect = Common::Rect(x, y, x + surface->w, y + surface->h);
+ _newSpriteDrawItems[_newSpriteDrawItemsCount].surface = surface;
+ ++_newSpriteDrawItemsCount;
+ }
+}
+
+void GameSys::removeSpriteDrawItem(Graphics::Surface *surface, int a2) {
+ if (surface && _removeSpriteDrawItemsCount < kMaxSpriteDrawItems) {
+ _removeSpriteDrawItems[_removeSpriteDrawItemsCount].id = a2;
+ _removeSpriteDrawItems[_removeSpriteDrawItemsCount].surface = surface;
+ ++_removeSpriteDrawItemsCount;
+ }
+}
+
+void GameSys::drawSpriteToBackground(int x, int y, int resourceId) {
+
+ SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId);
+ uint32 *sourcePalette = spriteResource->_palette;
+ byte *sourcePixels = spriteResource->_pixels;
+ int spriteWidth = spriteResource->_width;
+ int spriteHeight = spriteResource->_height;
+ Common::Rect dstRect(0, 0, spriteWidth, spriteHeight);
+ blitSprite32(_backgroundSurface, x, y, sourcePixels, spriteResource->_width, dstRect, sourcePalette, true);//spriteResource->_transparent != 0);
+ _vm->_spriteCache->release(resourceId);
+
+ // Add dirty rect so the modified background is redrawn
+ insertDirtyRect(Common::Rect(x, y, x + spriteWidth, y + spriteHeight));
+}
+
+Graphics::Surface *GameSys::allocSurface(int width, int height) {
+ Graphics::Surface *surface = new Graphics::Surface();
+ surface->create(width, height, _backgroundSurface->format);
+ surface->fillRect(Common::Rect(0, 0, surface->w, surface->h), 0xFFFF00FF);
+ return surface;
+}
+
+Graphics::Surface *GameSys::createSurface(int resourceId) {
+ debug(0, "GameSys::createSurface() resourceId: %08X", resourceId);
+
+ SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId);
+ Graphics::Surface *surface = allocSurface(spriteResource->_width, spriteResource->_height);
+ _vm->_spriteCache->release(resourceId);
+
+ drawSpriteToSurface(surface, 0, 0, resourceId);
+
+ return surface;
+}
+
+void GameSys::drawSpriteToSurface(Graphics::Surface *surface, int x, int y, int resourceId) {
+ SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId);
+ uint32 *sourcePalette = spriteResource->_palette;
+ byte *sourcePixels = spriteResource->_pixels;
+ Common::Rect dstRect(0, 0, spriteResource->_width, spriteResource->_height);
+ blitSprite32(surface, x, y, sourcePixels, spriteResource->_width, dstRect, sourcePalette, true);//spriteResource->_transparent != 0);
+ _vm->_spriteCache->release(resourceId);
+}
+
+void GameSys::drawTextToSurface(Graphics::Surface *surface, int x, int y, byte r, byte g, byte b, const char *text) {
+
+ // NOTE Not that nice but will have to do for now
+
+ bool doDirty = false;
+
+ if (!surface) {
+ surface = _backgroundSurface;
+ doDirty = true;
+ }
+
+ uint32 color = surface->format.RGBToColor(r, g, b);
+
+ for (const char *cp = text; *cp != 0; ++cp) {
+ byte c = *cp;
+ if (c < 32 || c > 127)
+ c = (byte)'_';
+ c -= 32;
+ int w = dejaVuSans9ptCharDescriptors[c].width;
+ const byte *data = dejaVuSans9ptCharBitmaps + dejaVuSans9ptCharDescriptors[c].offset;
+ for (int xc = 0; xc < w; ++xc) {
+ for (int yc = 15; yc >= 0; --yc) {
+ byte *dst = (byte*)surface->getBasePtr(x + xc, y + yc);
+ if (data[1 - (yc >> 3)] & (1 << (yc & 7)))
+ WRITE_LE_UINT32(dst, color);
+ }
+ data += 2;
+ }
+ x += w + 1;
+ }
+
+ if (doDirty) {
+ insertDirtyRect(Common::Rect(x, y, x + getTextWidth(text), y + 16));
+ }
+
+}
+
+int GameSys::getTextWidth(const char *text) {
+ int width = 0;
+ for (const char *cp = text; *cp != 0; ++cp) {
+ byte c = *cp;
+ if (c < 32 || c > 127)
+ c = (byte)'_';
+ c -= 32;
+ width += dejaVuSans9ptCharDescriptors[c].width + 1;
+ }
+ return width;
+}
+
+void GameSys::fillSurface(Graphics::Surface *surface, int x, int y, int width, int height, byte r, byte g, byte b) {
+ Common::Rect rect(x, y, x + width, y + height);
+ if (!surface) {
+ _backgroundSurface->fillRect(rect, _backgroundSurface->format.RGBToColor(r, g, b));
+ insertDirtyRect(rect);
+ } else {
+ surface->fillRect(rect, surface->format.RGBToColor(r, g, b));
+ }
+}
+
+void GameSys::setAnimation(int sequenceId, int id, int animationIndex) {
+ if (animationIndex < kMaxAnimations) {
+ _animations[animationIndex].sequenceId = sequenceId;
+ _animations[animationIndex].id = id;
+ _animations[animationIndex].status = 0;
+ }
+}
+
+int GameSys::getAnimationStatus(int animationIndex) {
+ int result = -1;
+ if (animationIndex < kMaxAnimations)
+ result = _animations[animationIndex].status;
+ return result;
+}
+
+int GameSys::getSpriteWidthById(int resourceId) {
+ SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId);
+ const int width = spriteResource->_width;
+ _vm->_spriteCache->release(resourceId);
+ return width;
+}
+
+int GameSys::getSpriteHeightById(int resourceId) {
+ SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId);
+ const int height = spriteResource->_height;
+ _vm->_spriteCache->release(resourceId);
+ return height;
+}
+
+Graphics::Surface *GameSys::loadBitmap(int resourceId) {
+ debug("GameSys::loadBitmap() resourceId: %08X", resourceId);
+ if (_vm->_dat->getResourceType(resourceId) != 1)
+ return 0;
+ byte *resourceData = _vm->_dat->loadResource(resourceId);
+ uint32 resourceSize = _vm->_dat->getResourceSize(resourceId);
+ Common::MemoryReadStream stream(resourceData, resourceSize, DisposeAfterUse::NO);
+ Graphics::Surface *bmpSurface;
+ Graphics::BitmapDecoder bmp;
+ if (!bmp.loadStream(stream))
+ error("GameSys::loadBitmap() Could not load bitmap resource %08X", resourceId);
+ bmpSurface = bmp.getSurface()->convertTo(_vm->_system->getScreenFormat());
+ delete[] resourceData;
+ return bmpSurface;
+}
+
+void GameSys::drawBitmap(int resourceId) {
+ Graphics::Surface *bmpSurface = loadBitmap(resourceId);
+ if (!bmpSurface || !_backgroundSurface) {
+ debug("GameSys::drawBitmap() Error loading the bitmap");
+ return;
+ }
+ if (bmpSurface->format != _backgroundSurface->format ||
+ bmpSurface->w != _backgroundSurface->w || bmpSurface->h != _backgroundSurface->h) {
+ debug("GameSys::drawBitmap() Different bitmap properties than current background");
+ } else {
+ byte *src = (byte*)bmpSurface->getPixels();
+ byte *dst = (byte*)_backgroundSurface->getPixels();
+ const int pitch = bmpSurface->pitch;
+ int height = bmpSurface->h;
+ while (height--) {
+ memcpy(dst, src, pitch);
+ src += pitch;
+ dst += pitch;
+ }
+ }
+ bmpSurface->free();
+ delete bmpSurface;
+
+ insertDirtyRect(Common::Rect(0, 0, 800, 600));
+}
+
+Sequence *GameSys::seqFind(int sequenceId, int a2, int *outIndex) {
+ for (uint i = 0; i < _seqItems.size(); ++i)
+ if (_seqItems[i].sequenceId == sequenceId && _seqItems[i].id == a2) {
+ if (outIndex)
+ *outIndex = i;
+ return &_seqItems[i];
+ }
+ return 0;
+}
+
+int GameSys::seqLocateGfx(int sequenceId, int id, int *outGfxIndex) {
+ for (int i = 0; i < _gfxItemsCount; ++i) {
+ GfxItem *gfxItem = &_gfxItems[i];
+ if (gfxItem->sequenceId == sequenceId && gfxItem->id == id) {
+ if (outGfxIndex)
+ *outGfxIndex = i;
+ return gfxItem->sequenceId;
+ }
+ if (gfxItem->id > id) {
+ if (outGfxIndex)
+ *outGfxIndex = i;
+ return 0;
+ }
+ }
+ if (outGfxIndex)
+ *outGfxIndex = _gfxItemsCount;
+ return 0;
+}
+
+void GameSys::seqInsertGfx(int index, int duration) {
+
+ Sequence *seqItem = &_seqItems[index];
+ SequenceResource *sequenceResource = _vm->_sequenceCache->get(seqItem->sequenceId);
+
+ if (sequenceResource->_animationsCount > 50 - _gfxItemsCount)
+ return;
+
+ int gfxIndex;
+ seqLocateGfx(seqItem->sequenceId, seqItem->id, &gfxIndex);
+
+ if (gfxIndex != _gfxItemsCount)
+ memcpy(&_gfxItems[gfxIndex + sequenceResource->_animationsCount], &_gfxItems[gfxIndex], sizeof(GfxItem) * (_gfxItemsCount - gfxIndex));
+ _gfxItemsCount += sequenceResource->_animationsCount;
+
+ for (int i = 0; i < sequenceResource->_animationsCount; ++i) {
+ int totalDuration;
+ GfxItem *gfxItem = &_gfxItems[i + gfxIndex];
+ SequenceAnimation *animation = &sequenceResource->_animations[i];
+
+ debug(0, "GameSys::seqInsertGfx() seqItem->sequenceId: %08X", seqItem->sequenceId);
+
+ gfxItem->sequenceId = seqItem->sequenceId;
+ gfxItem->id = seqItem->id;
+ gfxItem->animation = animation;
+ gfxItem->currFrameNum = 0;
+ gfxItem->flags = 0;
+ gfxItem->delayTicks = seqItem->totalDuration + animation->field_4;
+ gfxItem->updFlag = false;
+ gfxItem->updRectsCount = 0;
+ gfxItem->prevFrame.duration = 0;
+ gfxItem->prevFrame.spriteId = -1;
+ gfxItem->prevFrame.soundId = -1;
+ gfxItem->prevFrame.unkValue = -1;
+ totalDuration = duration;
+ if ((seqItem->flags & 4) && totalDuration > 0) {
+ gfxItem->prevFrame.duration = 1;
+ if (gfxItem->delayTicks <= totalDuration)
+ gfxItem->delayTicks = 0;
+ else
+ gfxItem->delayTicks -= totalDuration + 1;
+ gfxItem->updFlag = false;
+ } else if (gfxItem->delayTicks <= totalDuration) {
+ int j;
+ totalDuration -= gfxItem->delayTicks;
+ gfxItem->delayTicks = 0;
+ for (j = gfxItem->currFrameNum; j < animation->framesCount && animation->frames[j].duration <= totalDuration; ++j) {
+ if (animation->frames[j].soundId != -1)
+ _soundIds.push_back((gfxItem->sequenceId & 0xFFFF0000) | animation->frames[j].soundId);
+ totalDuration -= animation->frames[j].duration;
+ }
+ if (animation->framesCount > j)
+ gfxItem->currFrame = animation->frames[j++];
+ else
+ gfxItem->currFrame = animation->frames[j - 1];
+ if (gfxItem->currFrame.spriteId != -1 && (seqItem->x != 0 || seqItem->y != 0))
+ gfxItem->currFrame.rect.translate(seqItem->x, seqItem->y);
+ // Update sprite scaling
+ if ((seqItem->flags & 1) && gfxItem->currFrame.rect.bottom >= _backgroundImageValue1 && gfxItem->currFrame.rect.bottom <= _backgroundImageValue3) {
+ int v2 = _backgroundImageValue2 + (gfxItem->currFrame.rect.bottom - _backgroundImageValue1) *
+ (_backgroundImageValue4 - _backgroundImageValue2) /
+ (_backgroundImageValue3 - _backgroundImageValue1);
+ gfxItem->currFrame.rect.top = gfxItem->currFrame.rect.bottom - v2 * (gfxItem->currFrame.rect.bottom - gfxItem->currFrame.rect.top) / 1000;
+ gfxItem->currFrame.rect.right = v2 * (gfxItem->currFrame.rect.right - gfxItem->currFrame.rect.left) / 1000 + gfxItem->currFrame.rect.left;
+ gfxItem->currFrame.isScaled = 1;
+ }
+ gfxItem->currFrame.duration -= totalDuration;
+ if (gfxItem->currFrame.soundId != -1)
+ _soundIds.push_back((gfxItem->sequenceId & 0xFFFF0000) | gfxItem->currFrame.soundId);
+ gfxItem->currFrameNum = j;
+ gfxItem->updFlag = true;
+ } else {
+ gfxItem->delayTicks -= totalDuration + 1;
+ gfxItem->updFlag = false;
+ }
+ }
+
+ for (int k = 0; k < kMaxAnimations; ++k) {
+ if (_animations[k].sequenceId != -1 && _animations[k].sequenceId == seqItem->sequenceId && _animations[k].id == seqItem->id) {
+ _animations[k].status = 1;
+ break;
+ }
+ }
+
+}
+
+void GameSys::seqRemoveGfx(int sequenceId, int id) {
+ int gfxIndex;
+ if (seqLocateGfx(sequenceId, id, &gfxIndex)) {
+ GfxItem *gfxItem = &_gfxItems[gfxIndex];
+ while (gfxIndex < _gfxItemsCount && gfxItem->sequenceId == sequenceId && gfxItem->id == id) {
+ if (gfxItem->prevFrame.spriteId == -1) {
+ --_gfxItemsCount;
+ if (gfxIndex != _gfxItemsCount)
+ memcpy(&_gfxItems[gfxIndex], &_gfxItems[gfxIndex + 1], sizeof(GfxItem) * (_gfxItemsCount - gfxIndex));
+ } else {
+ gfxItem->sequenceId = -1;
+ gfxItem->animation = 0;
+ gfxItem->currFrame.duration = 0;
+ gfxItem->currFrame.spriteId = -1;
+ gfxItem->currFrame.soundId = -1;
+ gfxItem->currFrame.unkValue = -1;
+ gfxItem->updFlag = true;
+ ++gfxIndex;
+ gfxItem = &_gfxItems[gfxIndex];
+ }
+ }
+ }
+}
+
+bool GameSys::updateSequenceDuration(int sequenceId, int id, int *outDuration) {
+ bool found = false;
+ int duration = 0x7FFFFFFF;
+ for (int i = 0; i < _gfxItemsCount; ++i) {
+ GfxItem *gfxItem = &_gfxItems[i];
+ if (gfxItem->sequenceId == sequenceId && gfxItem->id == id) {
+ found = true;
+ SequenceAnimation *animation = gfxItem->animation;
+ if (animation) {
+ if (gfxItem->currFrameNum < animation->framesCount)
+ return false;
+ if (gfxItem->updFlag) {
+ if (gfxItem->currFrame.duration > 0)
+ return false;
+ if (-gfxItem->currFrame.duration < duration)
+ duration = -gfxItem->currFrame.duration;
+ } else {
+ if (gfxItem->prevFrame.duration > 0)
+ return false;
+ if (-gfxItem->prevFrame.duration < duration)
+ duration = -gfxItem->prevFrame.duration;
+ }
+ }
+ }
+ }
+ if (found)
+ *outDuration = duration;
+ return found;
+}
+
+void GameSys::updateAnimationsStatus(int sequenceId, int a2) {
+
+ Animation *foundAnimation = 0;
+ for (int animationIndex = 0; animationIndex < kMaxAnimations; ++animationIndex) {
+ Animation *animation = &_animations[animationIndex];
+ if (animation->sequenceId != -1 && animation->sequenceId == sequenceId && animation->id == a2) {
+ foundAnimation = animation;
+ break;
+ }
+ }
+
+ if (!foundAnimation)
+ return;
+
+ bool foundSequence = false;
+ for (int i = 0; i < _gfxItemsCount; ++i) {
+ GfxItem *gfxItem = &_gfxItems[i];
+ SequenceAnimation *animation = gfxItem->animation;
+ if (gfxItem->sequenceId == sequenceId && gfxItem->id == a2 && animation) {
+ foundSequence = true;
+ if (animation->framesCount > gfxItem->currFrameNum ||
+ (gfxItem->updFlag && gfxItem->currFrame.duration > 1) ||
+ gfxItem->prevFrame.duration > 1)
+ foundSequence = false;
+ break;
+ }
+ }
+
+ if (foundSequence) {
+ foundAnimation->sequenceId = -1;
+ foundAnimation->status = 2;
+ }
+
+}
+
+void GameSys::restoreBackgroundRect(const Common::Rect &rect) {
+ Common::Rect clipRect;
+ if (!intersectRect(clipRect, rect, _screenRect))
+ return;
+ byte *src = (byte*)_backgroundSurface->getBasePtr(clipRect.left, clipRect.top);
+ byte *dst = (byte*)_frontSurface->getBasePtr(clipRect.left, clipRect.top);
+ const int bytes = _backgroundSurface->format.bytesPerPixel * clipRect.width();
+ int height = clipRect.height();
+ while (height--) {
+ memcpy(dst, src, bytes);
+ src += _backgroundSurface->pitch;
+ dst += _frontSurface->pitch;
+ }
+}
+
+void GameSys::blitSurface32(Graphics::Surface *destSurface, int x, int y, Graphics::Surface *sourceSurface,
+ Common::Rect &sourceRect, bool transparent) {
+
+ const int sourcePitch = sourceSurface->pitch;
+ byte *dst = (byte*)destSurface->getBasePtr(x, y);
+ byte *src = (byte*)sourceSurface->getBasePtr(sourceRect.left, sourceRect.top);
+ int width = sourceRect.width();
+ int height = sourceRect.height();
+ while (height--) {
+ byte *rsrc = src;
+ byte *rdst = dst;
+ for (int xc = 0; xc < width; ++xc) {
+ uint32 pixel = READ_LE_UINT32(rsrc);
+ if (!transparent || pixel != 0xFFFF00FF)
+ WRITE_LE_UINT32(rdst, pixel);
+ rsrc += 4;
+ rdst += 4;
+ }
+ dst += destSurface->pitch;
+ src += sourcePitch;
+ }
+}
+
+void GameSys::blitSprite32(Graphics::Surface *destSurface, int x, int y, byte *sourcePixels,
+ int sourceWidth, Common::Rect &sourceRect, uint32 *sourcePalette, bool transparent) {
+
+ const int sourcePitch = (sourceWidth + 3) & 0xFFFFFFFC;
+ byte *dst = (byte*)destSurface->getBasePtr(x, y);
+ byte *src = sourcePixels + sourceRect.left + sourcePitch * sourceRect.top;
+ int width = sourceRect.width();
+ int height = sourceRect.height();
+ while (height--) {
+ byte *rdst = dst;
+ for (int xc = 0; xc < width; ++xc) {
+ byte srcPixel = src[xc];
+ if (!transparent || srcPixel) {
+ uint32 rgb = sourcePalette[srcPixel];
+ rdst[0] = rgb & 0x000000FF;
+ rdst[1] = (rgb & 0x0000FF00) >> 8;
+ rdst[2] = (rgb & 0x00FF0000) >> 16;
+ }
+ rdst += 4;
+ }
+ dst += destSurface->pitch;
+ src += sourcePitch;
+ }
+}
+
+void GameSys::blitSpriteScaled32(Graphics::Surface *destSurface, Common::Rect &frameRect,
+ Common::Rect &destRect, byte *sourcePixels, int sourceWidth, Common::Rect &sourceRect, uint32 *sourcePalette) {
+
+ if (frameRect.height() <= 0 || frameRect.width() <= 0)
+ return;
+
+ const int ys = ((sourceRect.bottom - sourceRect.top - 1) << 16) / (frameRect.bottom - frameRect.top - 1);
+ const int xs = ((sourceRect.right - sourceRect.left - 1) << 16) / (frameRect.right - frameRect.left - 1);
+ const int destPitch = destSurface->pitch;
+ const int sourcePitch = (sourceWidth + 3) & 0xFFFFFFFC;
+
+ if (!frameRect.equals(destRect)) {
+ byte *dst = (byte*)destSurface->getBasePtr(destRect.left, destRect.top);
+ byte *src = sourcePixels + sourcePitch * sourceRect.top + sourceRect.left;
+ const int height = destRect.bottom - destRect.top;
+ const int width = destRect.right - destRect.left;
+ int yi = ys * (destRect.top - frameRect.top);
+ byte *hsrc = src + sourcePitch * ((yi + 0x8000) >> 16);
+ for (int i = 0; i < height; ++i) {
+ byte *wdst = dst;
+ int xi = xs * (destRect.left - frameRect.left);
+ byte *wsrc = hsrc + ((xi + 0x8000) >> 16);
+ for (int j = 0; j < width; ++j) {
+ byte srcPixel = *wsrc;
+ if (srcPixel) {
+ uint32 rgb = sourcePalette[srcPixel];
+ wdst[0] = rgb & 0x000000FF;
+ wdst[1] = (rgb & 0x0000FF00) >> 8;
+ wdst[2] = (rgb & 0x00FF0000) >> 16;
+ }
+ wdst += 4;
+ xi += xs;
+ wsrc = hsrc + ((xi + 0x8000) >> 16);
+ }
+ dst += destPitch;
+ yi += ys;
+ hsrc = src + sourcePitch * ((yi + 0x8000) >> 16);
+ }
+ } else {
+ byte *dst = (byte*)destSurface->getBasePtr(frameRect.left, frameRect.top);
+ byte *src = sourcePixels + sourcePitch * sourceRect.top + sourceRect.left;
+ const int height = frameRect.bottom - frameRect.top;
+ const int width = frameRect.right - frameRect.left;
+ byte *hsrc = sourcePixels + sourcePitch * sourceRect.top + sourceRect.left;
+ int yi = 0;
+ for (int i = 0; i < height; ++i) {
+ byte *wdst = dst;
+ byte *wsrc = hsrc;
+ int xi = 0;
+ for (int j = 0; j < width; ++j) {
+ byte srcPixel = *wsrc;
+ if (srcPixel) {
+ uint32 rgb = sourcePalette[srcPixel];
+ wdst[0] = rgb & 0x000000FF;
+ wdst[1] = (rgb & 0x0000FF00) >> 8;
+ wdst[2] = (rgb & 0x00FF0000) >> 16;
+ }
+ wdst += 4;
+ xi += xs;
+ wsrc = hsrc + ((xi + 0x8000) >> 16);
+ }
+ dst += destPitch;
+ yi += ys;
+ hsrc = src + sourcePitch * ((yi + 0x8000) >> 16);
+ }
+ }
+
+}
+
+void GameSys::seqDrawStaticFrame(Graphics::Surface *surface, SequenceFrame &frame, Common::Rect *subRect) {
+ debug(1, "GameSys::seqDrawStaticFrame() rect: (%d, %d, %d, %d)",
+ frame.rect.left, frame.rect.top, frame.rect.right, frame.rect.bottom);
+
+ Common::Rect srcRect = subRect ? *subRect : frame.rect;
+ Common::Rect clipRect;
+
+ if (!intersectRect(clipRect, srcRect, _screenRect)) {
+ debug(1, "GameSys::seqDrawStaticFrame() Surface not inside screen");
+ return;
+ }
+
+ const int x = clipRect.left, y = clipRect.top;
+
+ clipRect.translate(-frame.rect.left, -frame.rect.top);
+
+ // TODO Save transparent flag somewhere
+ blitSurface32(_frontSurface, x, y, surface, clipRect, true);
+
+}
+
+void GameSys::seqDrawSpriteFrame(SpriteResource *spriteResource, SequenceFrame &frame, Common::Rect *subRect) {
+ debug(1, "GameSys::seqDrawSpriteFrame() spriteId: %04X; rect: (%d, %d, %d, %d)",
+ frame.spriteId, frame.rect.left, frame.rect.top, frame.rect.right, frame.rect.bottom);
+
+ Common::Rect srcRect = subRect ? *subRect : frame.rect;
+ Common::Rect clipRect;
+
+ if (!intersectRect(clipRect, srcRect, _screenRect)) {
+ debug(1, "GameSys::seqDrawSpriteFrame() Sprite not inside screen");
+ return;
+ }
+
+ uint32 *sourcePalette = spriteResource->_palette;
+ byte *sourcePixels = spriteResource->_pixels;
+
+ const int x = clipRect.left, y = clipRect.top;
+
+ debug(1, "GameSys::seqDrawSpriteFrame() destX: %d; destY: %d; frame.isScaled: %d", x, y, frame.isScaled);
+
+ // 32bit sprite drawing
+ if (frame.isScaled) {
+ Common::Rect sourceRect(0, 0, spriteResource->_width, spriteResource->_height);
+ blitSpriteScaled32(_frontSurface, frame.rect, clipRect, sourcePixels, spriteResource->_width, sourceRect, sourcePalette);
+ } else {
+ clipRect.translate(-frame.rect.left, -frame.rect.top);
+ blitSprite32(_frontSurface, x, y, sourcePixels, spriteResource->_width, clipRect, sourcePalette, true);//spriteResource->_transparent != 0);
+ }
+
+}
+
+void GameSys::drawSprites() {
+
+ debug(1, "GameSys::drawSprites() _gfxItemsCount: %d", _gfxItemsCount);
+
+ // TODO Split into multiple functions for clarity
+
+ // Restore dirty background and collect rects to be redrawn for all sprites
+ // which aren't marked to be redrawn yet
+ Common::Rect intersectingRect;
+ for (uint i = 0; i < _dirtyRects.size(); ++i) {
+ restoreBackgroundRect(_dirtyRects[i]);
+ for (int j = 0; j < _gfxItemsCount; ++j)
+ _gfxItems[j].testUpdRect(_dirtyRects[i]);
+ }
+
+ for (int k = 0; k < _gfxItemsCount; ++k) {
+ GfxItem *gfxItem2 = &_gfxItems[k];
+
+ if (!gfxItem2->updFlag)
+ continue;
+
+ if (gfxItem2->prevFrame.spriteId != -1) {
+ int transparent = 0;
+ if (gfxItem2->currFrame.spriteId != -1 && !(gfxItem2->flags & 2)) {
+ if (gfxItem2->flags & 1) {
+ transparent = 1;
+ } else {
+ int resourceId = (gfxItem2->sequenceId & 0xFFFF0000) | gfxItem2->currFrame.spriteId;
+ SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId);
+ transparent = spriteResource->_transparent;
+ _vm->_spriteCache->release(resourceId);
+ }
+ }
+ if ((gfxItem2->flags & 8) || gfxItem2->currFrame.spriteId == -1 ||
+ (!(gfxItem2->flags & 2) && (!gfxItem2->prevFrame.rect.equals(gfxItem2->currFrame.rect) || !transparent))) {
+ restoreBackgroundRect(gfxItem2->prevFrame.rect);
+ for (int l = 0; l < _gfxItemsCount; ++l)
+ _gfxItems[l].testUpdRect(gfxItem2->prevFrame.rect);
+ }
+ }
+
+ if (gfxItem2->currFrame.spriteId != -1) {
+ int transparent = 0;
+ if (gfxItem2->flags & 1) {
+ transparent = 1;
+ } else if (!(gfxItem2->flags & 2)) {
+ int resourceId = (gfxItem2->sequenceId & 0xFFFF0000) | gfxItem2->currFrame.spriteId;
+ SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId);
+ transparent = spriteResource->_transparent;
+ _vm->_spriteCache->release(resourceId);
+ }
+ if (((gfxItem2->flags & 2) && !(gfxItem2->flags & 8)) ||
+ gfxItem2->prevFrame.spriteId == -1 ||
+ !gfxItem2->prevFrame.rect.equals(gfxItem2->currFrame.rect) || transparent) {
+ for (int l = k; l < _gfxItemsCount; ++l)
+ _gfxItems[l].testUpdRect(gfxItem2->currFrame.rect);
+ }
+ }
+
+ }
+
+ for (int m = 0; m < _gfxItemsCount; ++m) {
+ GfxItem *gfxItem5 = &_gfxItems[m];
+
+ debug(0, "DrawGfxItem(%d) updFlag: %d; currFrame.spriteId: %04X; updRectsCount: %d; flags: %04X; sequenceId: %08X",
+ m, gfxItem5->updFlag, gfxItem5->currFrame.spriteId, gfxItem5->updRectsCount, gfxItem5->flags, gfxItem5->sequenceId);
+
+ if (gfxItem5->updFlag) {
+ if (gfxItem5->currFrame.spriteId != -1) {
+ if (gfxItem5->flags & 1) {
+ seqDrawStaticFrame(gfxItem5->surface, gfxItem5->currFrame, 0);
+ //debug("seqDrawStaticFrame");
+ } else if (gfxItem5->flags & 2) {
+ // TODO seqDrawAviFrame(gfxItem5->currFrame.spriteId, &gfxItem5->currFrame, 0, gfxItem5->flags & 8);
+ } else {
+ int resourceId = (gfxItem5->sequenceId & 0xFFFF0000) | gfxItem5->currFrame.spriteId;
+ SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId);
+ seqDrawSpriteFrame(spriteResource, gfxItem5->currFrame, 0);
+ _vm->_spriteCache->release(resourceId);
+ }
+ }
+ } else if (gfxItem5->updRectsCount > 0) {
+ if (gfxItem5->flags & 1) {
+ for (int n = 0; n < gfxItem5->updRectsCount; ++n)
+ seqDrawStaticFrame(gfxItem5->surface, gfxItem5->prevFrame, &gfxItem5->updRects[n]);
+ } else if (gfxItem5->flags & 2) {
+ /* TODO
+ spriteData4 = gfxItem5->prevFrame.spriteId;
+ for (int n = 0; n < gfxItem5->updRectsCount; ++n)
+ seqDrawAviFrame(spriteData4, &gfxItem5->prevFrame, &gfxItem5->updRects[n], gfxItem5->flags & 8);
+ */
+ } else {
+ int resourceId = (gfxItem5->sequenceId & 0xFFFF0000) | gfxItem5->prevFrame.spriteId;
+ SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId);
+ for (int n = 0; n < gfxItem5->updRectsCount; ++n)
+ seqDrawSpriteFrame(spriteResource, gfxItem5->prevFrame, &gfxItem5->updRects[n]);
+ _vm->_spriteCache->release(resourceId);
+ }
+ }
+ }
+
+ debug(1, "GameSys::drawSprites() OK");
+
+}
+
+void GameSys::updateRect(const Common::Rect &r) {
+ debug(1, "GameSys::updateRect() %d, %d, %d, %d [%d, %d]", r.left, r.top, r.right, r.bottom, r.width(), r.height());
+ if (r.width() > 0 && r.height() > 0) {
+ byte *pixels = (byte*)_frontSurface->getBasePtr(r.left, r.top);
+ _vm->_system->copyRectToScreen(pixels, _frontSurface->pitch, r.left, r.top,
+ r.width(), r.height());
+ }
+}
+
+void GameSys::updateScreen() {
+
+ debug(1, "GameSys::updateScreen()");
+
+ for (uint i = 0; i < _dirtyRects.size(); ++i)
+ updateRect(_dirtyRects[i]);
+
+ if (_dirtyRects.size() > 0) {
+ _dirtyRects.clear();
+ _lastUpdateClock = 0;
+ _gameSysClock = 0;
+ }
+
+ Common::Rect dstRect, srcRect, rcSrc2;
+
+ for (int j = 0; j < _gfxItemsCount; ++j) {
+
+ GfxItem *gfxItem = &_gfxItems[j];
+
+ if (!gfxItem->updFlag)
+ continue;
+
+ if (gfxItem->prevFrame.spriteId == -1 ||
+ !intersectRect(srcRect, _screenRect, gfxItem->prevFrame.rect)) {
+ if (gfxItem->currFrame.spriteId != -1 && intersectRect(rcSrc2, _screenRect, gfxItem->currFrame.rect))
+ updateRect(rcSrc2);
+ } else if (gfxItem->currFrame.spriteId != -1 &&
+ intersectRect(rcSrc2, _screenRect, gfxItem->currFrame.rect)) {
+ updateRect(srcRect);
+ updateRect(rcSrc2);
+ }
+ gfxItem->prevFrame = gfxItem->currFrame;
+ }
+
+ updateRect(Common::Rect(0, 0, 800, 600));
+
+ debug(1, "GameSys::updateScreen() OK");
+
+}
+
+void GameSys::handleReqRemoveSequenceItem() {
+ if (_reqRemoveSequenceItem) {
+ int gfxIndex2;
+ _reqRemoveSequenceItem = false;
+ if (seqFind(_removeSequenceItemSequenceId, _removeSequenceItemValue, &gfxIndex2))
+ _seqItems.remove_at(gfxIndex2);
+ if (seqLocateGfx(_removeSequenceItemSequenceId, _removeSequenceItemValue, &gfxIndex2)) {
+ int gfxIndex2a = gfxIndex2;
+ for (GfxItem *gfxItem = &_gfxItems[gfxIndex2a];
+ gfxIndex2a < _gfxItemsCount && gfxItem->sequenceId == _removeSequenceItemSequenceId && gfxItem->id == _removeSequenceItemValue;
+ gfxItem = &_gfxItems[gfxIndex2a])
+ ++gfxIndex2a;
+ _gfxItemsCount -= gfxIndex2a - gfxIndex2;
+ if (_gfxItemsCount != gfxIndex2)
+ memcpy(&_gfxItems[gfxIndex2], &_gfxItems[gfxIndex2a], sizeof(GfxItem) * (_gfxItemsCount - gfxIndex2));
+ }
+ }
+}
+
+void GameSys::handleReqRemoveSequenceItems() {
+ if (_removeSequenceItemsCount > 0) {
+ for (int i = 0; i < _removeSequenceItemsCount; ++i) {
+ int gfxIndex;
+ if (seqFind(_removeSequenceItems[i].sequenceId, _removeSequenceItems[i].id, &gfxIndex))
+ _seqItems.remove_at(gfxIndex);
+ seqLocateGfx(_removeSequenceItems[i].sequenceId, _removeSequenceItems[i].id, &gfxIndex);
+ for (GfxItem *gfxItem = &_gfxItems[gfxIndex];
+ gfxIndex < _gfxItemsCount && gfxItem->sequenceId == _removeSequenceItems[i].sequenceId && gfxItem->id == _removeSequenceItems[i].id;
+ gfxItem = &_gfxItems[gfxIndex]) {
+ gfxItem->sequenceId = -1;
+ gfxItem->animation = 0;
+ gfxItem->soundValue = 0;
+ if (_removeSequenceItems[i].a3) {
+ gfxItem->currFrame.duration = 0;
+ gfxItem->currFrame.spriteId = -1;
+ gfxItem->currFrame.soundId = -1;
+ gfxItem->currFrame.unkValue = -1;
+ gfxItem->updFlag = true;
+ } else {
+ gfxItem->updFlag = false;
+ }
+ ++gfxIndex;
+ }
+ }
+ _removeSequenceItemsCount = 0;
+ }
+}
+
+void GameSys::handleReqRemoveSpriteDrawItems() {
+ if (_removeSpriteDrawItemsCount > 0) {
+ for (int j = 0; j < _removeSpriteDrawItemsCount; ++j) {
+ for (int i = 0; i < _gfxItemsCount; ++i) {
+ GfxItem *gfxItem = &_gfxItems[i];
+ if (gfxItem->sequenceId == -1 && !gfxItem->animation && (gfxItem->flags & 1) &&
+ gfxItem->id == _removeSpriteDrawItems[j].id && _removeSpriteDrawItems[j].surface == gfxItem->surface) {
+ gfxItem->flags = 0;
+ gfxItem->currFrame.duration = 0;
+ gfxItem->currFrame.spriteId = -1;
+ gfxItem->currFrame.soundId = -1;
+ gfxItem->currFrame.unkValue = -1;
+ gfxItem->updFlag = true;
+ }
+ }
+ }
+ _removeSpriteDrawItemsCount = 0;
+ }
+}
+
+void GameSys::fatUpdateFrame() {
+
+ debug(1, "GameSys::fatUpdateFrame()");
+
+ int32 clockDelta = _gameSysClock - _lastUpdateClock;
+ _lastUpdateClock = _gameSysClock;
+
+ debug(1, "GameSys::fatUpdateFrame() clockDelta: %d", clockDelta);
+
+ if (clockDelta <= 0)
+ return;
+
+ bool updFlag = true;
+ int duration, v20, currFrameNum;
+
+ // NOTE Skipped avi code (reqAviStart)
+
+ for (int i = 0; i < _gfxItemsCount; ++i) {
+ GfxItem *gfxItem = &_gfxItems[i];
+ SequenceAnimation *animation = gfxItem->animation;
+ if ((gfxItem->sequenceId != -1 && animation) || (gfxItem->flags & 2) ||
+ gfxItem->prevFrame.spriteId != -1 || gfxItem->prevFrame.duration > 0) {
+ if (gfxItem->sequenceId == -1 || gfxItem->updFlag) {
+ if ((gfxItem->flags & 2) && !gfxItem->updFlag) {
+ // NOTE Skipped avi code
+ }
+ } else {
+ Sequence *seqItem = seqFind(gfxItem->sequenceId, gfxItem->id, 0);
+ if (!animation) {
+ updFlag = false;
+ gfxItem->sequenceId = -1;
+ gfxItem->animation = 0;
+ gfxItem->currFrame.duration = 0;
+ gfxItem->currFrame.spriteId = -1;
+ gfxItem->currFrame.soundId = -1;
+ gfxItem->currFrame.unkValue = -1;
+ gfxItem->updFlag = true;
+ } else if (!seqItem) {
+ updFlag = false;
+ gfxItem->animation = 0;
+ gfxItem->currFrame.duration = 0;
+ gfxItem->currFrame.spriteId = -1;
+ gfxItem->currFrame.soundId = -1;
+ gfxItem->currFrame.unkValue = -1;
+ gfxItem->updFlag = true;
+ } else if ((seqItem->flags & 4) && clockDelta > 1) {
+ updFlag = false;
+ if (gfxItem->delayTicks < clockDelta) {
+ duration = clockDelta - gfxItem->delayTicks;
+ gfxItem->delayTicks = 0;
+ if (gfxItem->prevFrame.duration <= duration)
+ gfxItem->prevFrame.duration = 1;
+ else
+ gfxItem->prevFrame.duration -= duration;
+ } else {
+ gfxItem->delayTicks -= clockDelta;
+ }
+ gfxItem->updFlag = false;
+ } else if (gfxItem->delayTicks < clockDelta) {
+ duration = clockDelta - gfxItem->delayTicks;
+ gfxItem->delayTicks = 0;
+ if (gfxItem->prevFrame.duration <= duration) {
+ v20 = 0;
+ if (gfxItem->prevFrame.duration > 0) {
+ duration -= gfxItem->prevFrame.duration;
+ gfxItem->prevFrame.duration = -duration;
+ } else {
+ gfxItem->prevFrame.duration = 0;
+ v20 = 1;
+ }
+ currFrameNum = gfxItem->currFrameNum;
+ if (animation->framesCount > currFrameNum) {
+ updFlag = false;
+ while (animation->framesCount > currFrameNum &&
+ animation->frames[currFrameNum].duration <= duration) {
+ if (animation->frames[currFrameNum].soundId != -1)
+ _soundIds.push_back((gfxItem->sequenceId & 0xFFFF0000) | animation->frames[currFrameNum].soundId);
+ duration -= animation->frames[currFrameNum].duration;
+ ++currFrameNum;
+ }
+ if (animation->framesCount > currFrameNum)
+ gfxItem->currFrame = animation->frames[currFrameNum++];
+ else
+ gfxItem->currFrame = animation->frames[currFrameNum - 1];
+ if (gfxItem->currFrame.spriteId != -1 && (seqItem->x != 0 || seqItem->y != 0))
+ gfxItem->currFrame.rect.translate(seqItem->x, seqItem->y);
+ // Update sprite scaling
+ if ((seqItem->flags & 1) && gfxItem->currFrame.rect.bottom >= _backgroundImageValue1 && gfxItem->currFrame.rect.bottom <= _backgroundImageValue3) {
+ int v17 = _backgroundImageValue2 + (gfxItem->currFrame.rect.bottom - _backgroundImageValue1) *
+ (_backgroundImageValue4 - _backgroundImageValue2) /
+ (_backgroundImageValue3 - _backgroundImageValue1);
+ gfxItem->currFrame.rect.top = gfxItem->currFrame.rect.bottom - v17 * (gfxItem->currFrame.rect.bottom - gfxItem->currFrame.rect.top) / 1000;
+ gfxItem->currFrame.rect.right = v17 * (gfxItem->currFrame.rect.right - gfxItem->currFrame.rect.left) / 1000 + gfxItem->currFrame.rect.left;
+ gfxItem->currFrame.isScaled = 1;
+ }
+ gfxItem->currFrame.duration -= duration;
+ if (gfxItem->currFrame.soundId != -1)
+ _soundIds.push_back((gfxItem->sequenceId & 0xFFFF0000) | gfxItem->currFrame.soundId);
+ gfxItem->currFrameNum = currFrameNum;
+ gfxItem->updFlag = true;
+ } else if (v20 && gfxItem->prevFrame.spriteId == -1) {
+ --_gfxItemsCount;
+ if (_gfxItemsCount != i)
+ memcpy(&_gfxItems[i], &_gfxItems[i + 1], sizeof(GfxItem) * (_gfxItemsCount - i));
+ --i;
+ } else {
+ gfxItem->updFlag = false;
+ }
+ } else {
+ updFlag = false;
+ gfxItem->prevFrame.duration -= duration;
+ gfxItem->updFlag = false;
+ }
+ } else {
+ updFlag = false;
+ gfxItem->delayTicks -= clockDelta;
+ gfxItem->updFlag = false;
+ }
+ }
+ } else {
+ --_gfxItemsCount;
+ if (_gfxItemsCount != i)
+ memcpy(&_gfxItems[i], &_gfxItems[i + 1], sizeof(GfxItem) * (_gfxItemsCount - i));
+ --i;
+ }
+ }
+
+ if (_newSpriteDrawItemsCount > 0) {
+ debug(0, "_newSpriteDrawItemsCount: %d", _newSpriteDrawItemsCount);
+ for (int k = 0; k < _newSpriteDrawItemsCount; ++k) {
+ if (_gfxItemsCount < 50) {
+ int insertIndex;
+ seqLocateGfx(-1, _newSpriteDrawItems[k].id, &insertIndex);
+ if (_gfxItemsCount != insertIndex)
+ memcpy(&_gfxItems[insertIndex + 1], &_gfxItems[insertIndex], sizeof(GfxItem) * (_gfxItemsCount - insertIndex));
+ ++_gfxItemsCount;
+ GfxItem *gfxItem = &_gfxItems[insertIndex];
+ gfxItem->sequenceId = -1;
+ gfxItem->id = _newSpriteDrawItems[k].id;
+ gfxItem->animation = 0;
+ gfxItem->currFrameNum = 0;
+ gfxItem->flags = 1;
+ gfxItem->delayTicks = 0;
+ gfxItem->updFlag = true;
+ gfxItem->updRectsCount = 0;
+ gfxItem->surface = _newSpriteDrawItems[k].surface;
+ gfxItem->prevFrame.duration = 0;
+ gfxItem->prevFrame.spriteId = -1;
+ gfxItem->prevFrame.soundId = -1;
+ gfxItem->prevFrame.unkValue = -1;
+ gfxItem->currFrame.duration = 0;
+ gfxItem->currFrame.isScaled = 0;
+ gfxItem->currFrame.rect = _newSpriteDrawItems[k].rect;
+ gfxItem->currFrame.spriteId = _newSpriteDrawItems[k].surface ? 0xCAFEBABE : -1;// TODO
+ gfxItem->currFrame.soundId = -1;
+ gfxItem->currFrame.unkValue = -1;
+ }
+ }
+ _newSpriteDrawItemsCount = 0;
+ }
+
+ if (_grabSpriteChanged) {
+ for (int i = 0; i < _gfxItemsCount; ++i) {
+ GfxItem *gfxItem = &_gfxItems[i];
+ if (gfxItem->sequenceId == -1 && !gfxItem->animation && (gfxItem->flags & 1) &&
+ gfxItem->id == _grabSpriteId && gfxItem->surface == _grabSpriteSurface1) {
+ gfxItem->currFrame.duration = 0;
+ gfxItem->currFrame.isScaled = 0;
+ gfxItem->currFrame.rect = _grabSpriteRect;
+ gfxItem->currFrame.spriteId = _grabSpriteSurface2 ? 1 : -1;// TODO
+ gfxItem->currFrame.soundId = -1;
+ gfxItem->currFrame.unkValue = -1;
+ gfxItem->updFlag = true;
+ gfxItem->surface = _grabSpriteSurface2;
+ break;
+ }
+ }
+ _grabSpriteChanged = false;
+ }
+
+ // NOTE Skipped avi code (reqAviStart)
+
+ debug(1, "GameSys::fatUpdateFrame() _fatSequenceItems.size(): %d", _fatSequenceItems.size());
+
+ for (uint i = 0; i < _fatSequenceItems.size(); ++i) {
+ Sequence *seqItem = &_fatSequenceItems[i];
+ if (((seqItem->flags & 8) || (seqItem->flags & 0x20)) && seqItem->sequenceId2 != -1) {
+ duration = 0;
+ if (((seqItem->flags & 0x20) && seqLocateGfx(seqItem->sequenceId2, seqItem->id2, 0)) ||
+ updateSequenceDuration(seqItem->sequenceId2, seqItem->id2, &duration)) {
+ int index;
+ bool found = false;
+ if (seqItem->sequenceId2 == seqItem->sequenceId && seqItem->id == seqItem->id2 &&
+ seqFind(seqItem->sequenceId, seqItem->id, &index)) {
+ _seqItems[index] = *seqItem;
+ found = true;
+ } else if (_seqItems.size() < 50) {
+ index = _seqItems.size();
+ _seqItems.push_back(*seqItem);
+ found = true;
+ }
+ if (found) {
+ updFlag = false;
+ seqRemoveGfx(seqItem->sequenceId2, seqItem->id2);
+ seqRemoveGfx(seqItem->sequenceId, seqItem->id);
+ _fatSequenceItems.remove_at(i);
+ --i;
+ seqInsertGfx(index, duration);
+ }
+ }
+ } else {
+ updFlag = false;
+ if (seqItem->totalDuration < clockDelta) {
+ int index;
+ bool found = false;
+ duration = clockDelta - seqItem->totalDuration;
+ seqItem->totalDuration = 0;
+ if (seqFind(seqItem->sequenceId, seqItem->id, &index)) {
+ _seqItems[index] = *seqItem;
+ found = true;
+ } else if (_seqItems.size() < 50) {
+ index = _seqItems.size();
+ _seqItems.push_back(*seqItem);
+ found = true;
+ }
+ if (found) {
+ seqRemoveGfx(seqItem->sequenceId, seqItem->id);
+ _fatSequenceItems.remove_at(i);
+ --i;
+ seqInsertGfx(index, duration - 1);
+ }
+ } else {
+ seqItem->totalDuration -= clockDelta;
+ }
+ }
+ }
+
+ debug(1, "GameSys::fatUpdateFrame() _seqItems.size(): %d", _seqItems.size());
+
+ for (uint i = 0; i < _seqItems.size(); ++i) {
+ Sequence *seqItem = &_seqItems[i];
+ if (seqLocateGfx(seqItem->sequenceId, seqItem->id, 0)) {
+ updateAnimationsStatus(seqItem->sequenceId, seqItem->id);
+ if (seqItem->flags & 2) {
+ int gfxDuration;
+ updFlag = false;
+ if (updateSequenceDuration(seqItem->sequenceId, seqItem->id, &gfxDuration)) {
+ seqRemoveGfx(seqItem->sequenceId, seqItem->id);
+ seqInsertGfx(i, gfxDuration);
+ }
+ }
+ } else {
+ _seqItems.remove_at(i);
+ --i;
+ }
+ }
+
+}
+
+void GameSys::fatUpdate() {
+
+ debug(1, "GameSys::fatUpdate() _gfxItemsCount: %d", _gfxItemsCount);
+
+ for (int i = 0; i < _gfxItemsCount; ++i) {
+ _gfxItems[i].updFlag = false;
+ _gfxItems[i].updRectsCount = 0;
+ }
+
+ handleReqRemoveSequenceItem();
+ handleReqRemoveSequenceItems();
+ handleReqRemoveSpriteDrawItems();
+ // NOTE Skipped avi stuff (reqAviStop)
+
+ fatUpdateFrame();
+
+}
+
+void GameSys::updatePlaySounds() {
+ for (uint i = 0; i < _soundIds.size(); ++i)
+ _vm->playSound(_soundIds[i], false);
+ _soundIds.clear();
+}
+
+bool intersectRect(Common::Rect &intersectingRect, const Common::Rect &r1, const Common::Rect &r2) {
+ if (r1.intersects(r2)) {
+ intersectingRect = r1.findIntersectingRect(r2);
+ return true;
+ } else
+ return false;
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/gamesys.h b/engines/gnap/gamesys.h
new file mode 100644
index 0000000000..5e996bf844
--- /dev/null
+++ b/engines/gnap/gamesys.h
@@ -0,0 +1,216 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GNAP_GAMESYS_H
+#define GNAP_GAMESYS_H
+
+#include "gnap/gnap.h"
+#include "gnap/resource.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+namespace Gnap {
+
+const int kMaxSequenceItems = 40;
+const int kMaxSpriteDrawItems = 30;
+const int kMaxSoundIds = 50;
+const int kMaxSeqItems = 50;
+const int kMaxUpdRects = 20;
+const int kMaxGfxItems = 50;
+const int kMaxAnimations = 12;
+
+enum {
+ kSeqNone = 0x00,
+ kSeqScale = 0x01, // Enable scaling
+ kSeqLoop = 0x02, // Loop
+ kSeqUnk = 0x04, // Unknown
+ kSeqSyncWait = 0x08, // Start if other sequence is done
+ kSeqSyncExists = 0x20 // Start if other sequence exists
+};
+
+struct Sequence {
+ int32 sequenceId;
+ int32 id;
+ int32 sequenceId2;
+ int32 id2;
+ uint32 flags;
+ int32 totalDuration;
+ int16 x, y;
+};
+
+struct SpriteDrawItem {
+ int id;
+ Common::Rect rect;
+ Graphics::Surface *surface;
+};
+
+struct RemoveSequenceItem {
+ int sequenceId;
+ int id;
+ int a3;
+};
+
+struct RemoveSpriteDrawItem {
+ int id;
+ Graphics::Surface *surface;
+};
+
+struct GfxItem {
+ int sequenceId;
+ int id;
+ int flags;
+ SequenceAnimation *animation;
+ int soundValue;
+ int field_18;
+ int field_1C;
+ int currFrameNum;
+ int delayTicks;
+ bool updFlag;
+ int updRectsCount;
+ Graphics::Surface *surface;
+ Common::Rect updRects[kMaxUpdRects];
+ SequenceFrame prevFrame;
+ SequenceFrame currFrame;
+ void testUpdRect(const Common::Rect &updRect);
+};
+
+struct Animation {
+ int sequenceId;
+ int id;
+ int status;
+};
+
+class GameSys {
+public:
+ GameSys(GnapEngine *vm);
+ ~GameSys();
+ void insertSequence(int sequenceId, int a2, int sequenceId2, int a4, int flags, int totalDuration, int16 x, int16 y);
+ void insertDirtyRect(const Common::Rect &rect);
+ void removeSequence(int sequenceId, int a2, int a3);
+ void invalidateGrabCursorSprite(int id, Common::Rect &rect, Graphics::Surface *surface1, Graphics::Surface *surface2);
+ void requestClear2(int a1);
+ void requestClear1();
+ void requestRemoveSequence(int sequenceId, int a2);
+ void waitForUpdate();
+ int isSequenceActive(int sequenceId, int a2);
+ void setBackgroundSurface(Graphics::Surface *surface, int a4, int a5, int a6, int a7);
+ void setScaleValues(int a1, int a2, int a3, int a4);
+ void insertSpriteDrawItem(Graphics::Surface *surface, int x, int y, int id);
+ void removeSpriteDrawItem(Graphics::Surface *surface, int a2);
+ void drawSpriteToBackground(int x, int y, int resourceId);
+ Graphics::Surface *allocSurface(int width, int height);
+ Graphics::Surface *createSurface(int resourceId);
+ void drawSpriteToSurface(Graphics::Surface *surface, int x, int y, int resourceId);
+ void drawTextToSurface(Graphics::Surface *surface, int x, int y, byte r, byte g, byte b, const char *text);
+ int getTextWidth(const char *text);
+ void fillSurface(Graphics::Surface *surface, int x, int y, int width, int height, byte r, byte g, byte b);
+ void setAnimation(int sequenceId, int id, int animationIndex);
+ int getAnimationStatus(int animationIndex);
+ int getSpriteWidthById(int resourceId);
+ int getSpriteHeightById(int resourceId);
+ Graphics::Surface *loadBitmap(int resourceId);
+ void drawBitmap(int resourceId);
+public:
+ GnapEngine *_vm;
+
+ Common::Array<Common::Rect> _dirtyRects;
+
+ SpriteDrawItem _newSpriteDrawItems[kMaxSpriteDrawItems];
+ int _newSpriteDrawItemsCount;
+
+ bool _spriteDrawItems1Changed;
+
+ RemoveSequenceItem _removeSequenceItems[kMaxSequenceItems];
+ int _removeSequenceItemsCount;
+
+ RemoveSpriteDrawItem _removeSpriteDrawItems[kMaxSpriteDrawItems];
+ int _removeSpriteDrawItemsCount;
+
+ int _grabSpriteId;
+ Common::Rect _grabSpriteRect;
+ bool _grabSpriteChanged;
+ Graphics::Surface *_grabSpriteSurface1, *_grabSpriteSurface2;
+
+ bool _reqRemoveSequenceItem;
+ int _removeSequenceItemSequenceId, _removeSequenceItemValue;
+
+ Common::Array<int> _soundIds;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ Common::Array<Sequence> _seqItems;
+ Common::Array<Sequence> _fatSequenceItems;
+
+ GfxItem _gfxItems[kMaxGfxItems];
+ int _gfxItemsCount;
+
+ Animation _animations[kMaxAnimations];
+ int _animationsCount;
+
+ int _backgroundImageValue3, _backgroundImageValue1;
+ int _backgroundImageValue4, _backgroundImageValue2;
+ bool _backgroundImageError;
+
+ int32 _gameSysClock, _lastUpdateClock;
+
+ Graphics::Surface *_backgroundSurface;
+ Graphics::Surface *_frontSurface;
+ Common::Rect _screenRect;
+
+ Sequence *seqFind(int sequenceId, int a2, int *outIndex);
+ int seqLocateGfx(int sequenceId, int id, int *outGfxIndex);
+ void seqInsertGfx(int index, int duration);
+ void seqRemoveGfx(int sequenceId, int id);
+ bool updateSequenceDuration(int sequenceId, int id, int *outDuration);
+ void updateAnimationsStatus(int sequenceId, int a2);
+
+ void restoreBackgroundRect(const Common::Rect &rect);
+
+ void blitSurface32(Graphics::Surface *destSurface, int x, int y, Graphics::Surface *sourceSurface,
+ Common::Rect &sourceRect, bool transparent);
+ void blitSprite32(Graphics::Surface *destSurface, int x, int y, byte *sourcePixels,
+ int sourceWidth, Common::Rect &sourceRect, uint32 *sourcePalette, bool transparent);
+ void blitSpriteScaled32(Graphics::Surface *destSurface, Common::Rect &frameRect,
+ Common::Rect &destRect, byte *sourcePixels, int sourceWidth, Common::Rect &sourceRect, uint32 *sourcePalette);
+
+ void seqDrawStaticFrame(Graphics::Surface *surface, SequenceFrame &frame, Common::Rect *subRect);
+ void seqDrawSpriteFrame(SpriteResource *spriteResource, SequenceFrame &frame, Common::Rect *subRect);
+
+ void drawSprites();
+ void updateRect(const Common::Rect &r);
+ void updateScreen();
+
+ void handleReqRemoveSequenceItem();
+ void handleReqRemoveSequenceItems();
+ void handleReqRemoveSpriteDrawItems();
+ void fatUpdateFrame();
+ void fatUpdate();
+ void updatePlaySounds();
+
+};
+
+bool intersectRect(Common::Rect &intersectingRect, const Common::Rect &r1, const Common::Rect &r2);
+
+} // End of namespace Gnap
+
+#endif // GNAP_GAMESYS_H
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
diff --git a/engines/gnap/gnap.h b/engines/gnap/gnap.h
new file mode 100644
index 0000000000..e1d13eca41
--- /dev/null
+++ b/engines/gnap/gnap.h
@@ -0,0 +1,1117 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GNAP_H
+#define GNAP_H
+
+#include "common/array.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/memstream.h"
+#include "common/random.h"
+#include "common/str.h"
+#include "common/substream.h"
+#include "common/system.h"
+#include "common/winexe.h"
+#include "common/winexe_pe.h"
+#include "engines/engine.h"
+#include "graphics/pixelformat.h"
+#include "graphics/wincursor.h"
+
+#include "gnap/resource.h"
+
+struct ADGameDescription;
+
+namespace Gnap {
+
+class DatManager;
+class SequenceResource;
+class SpriteResource;
+class GameSys;
+class SoundMan;
+
+struct MouseButtonState {
+ bool left;
+ bool right;
+ bool middle;
+ MouseButtonState() : left(false), right(false), middle(false) {
+ }
+};
+
+struct Hotspot {
+ int16 x1, y1, x2, y2;
+ int16 field_10;
+ int16 field_12;
+ uint16 flags;
+ int id;
+ bool isPointInside(int16 x, int16 y) const {
+ return x >= x1 && x <= x2 && y >= y1 && y <= y2;
+ }
+ bool isFlag(uint16 flag) const {
+ return (flags & flag) != 0;
+ }
+};
+
+struct GridStruct {
+ int deltaX, deltaY;
+ int gridX1, gridY1;
+ int sequenceId;
+ int id;
+};
+
+const int kMaxGridStructs = 30;
+const int kMaxTimers = 10;
+
+enum {
+ SF_LOOK_CURSOR = 0x0001,
+ SF_GRAB_CURSOR = 0x0002,
+ SF_TALK_CURSOR = 0x0004,
+ SF_PLAT_CURSOR = 0x0008,
+ SF_DISABLED = 0x0010,
+ SF_WALKABLE = 0x0020,
+ SF_EXIT_L_CURSOR = 0x0040,
+ SF_EXIT_R_CURSOR = 0x0080,
+ SF_EXIT_U_CURSOR = 0x0100,
+ SF_EXIT_D_CURSOR = 0x0200,
+ SF_EXIT_NW_CURSOR = 0x0400,
+ SF_EXIT_NE_CURSOR = 0x0800,
+ SF_EXIT_SW_CURSOR = 0x1000,
+ SF_EXIT_SE_CURSOR = 0x2000
+};
+
+enum {
+ LOOK_CURSOR = 0,
+ GRAB_CURSOR = 1,
+ TALK_CURSOR = 2,
+ PLAT_CURSOR = 3,
+ NOLOOK_CURSOR = 4,
+ NOGRAB_CURSOR = 5,
+ NOTALK_CURSOR = 6,
+ NOPLAT_CURSOR = 7,
+ EXIT_L_CURSOR = 8,
+ EXIT_R_CURSOR = 9,
+ EXIT_U_CURSOR = 10,
+ EXIT_D_CURSOR = 11,
+ EXIT_NE_CURSOR = 12,
+ EXIT_NW_CURSOR = 13,
+ EXIT_SE_CURSOR = 14,
+ EXIT_SW_CURSOR = 15,
+ WAIT_CURSOR = 16
+};
+
+enum {
+ gskPullOutDevice = 0,
+ gskPullOutDeviceNonWorking = 1,
+ gskIdle = 2,
+ gskBrainPulsating = 3,
+ gskImpossible = 4,
+ gskScratchingHead = 5,
+ gskDeflect = 6,
+ gskUseDevice = 7,
+ gskMoan1 = 8,
+ gskMoan2 = 9
+};
+
+enum {
+ kItemMagazine = 0,
+ kItemMud = 1,
+ kItemGrass = 2,
+ kItemDisguise = 3,
+ kItemNeedle = 4,
+ kItemTwig = 5,
+ kItemGas = 6,
+ kItemKeys = 7,
+ kItemDice = 8,
+ kItemTongs = 9,
+ kItemQuarter = 10,
+ kItemQuarterWithHole = 11,
+ kItemDiceQuarterHole = 12,
+ kItemWrench = 13,
+ kItemCowboyHat = 14,
+ kItemGroceryStoreHat = 15,
+ kItemBanana = 16,
+ kItemTickets = 17,
+ kItemPicture = 18,
+ kItemEmptyBucket = 19,
+ kItemBucketWithBeer = 20,
+ kItemBucketWithPill = 21,
+ kItemPill = 22,
+ kItemHorn = 23,
+ kItemJoint = 24,
+ kItemChickenBucket = 25,
+ kItemGum = 26,
+ kItemSpring = 27,
+ kItemLightbulb = 28,
+ kItemCereals = 29
+};
+
+enum {
+ kGFPlatypus = 0,
+ kGFMudTaken = 1,
+
+
+ kGFEnd
+};
+
+/*
+ Game flags
+ 0 1 With Platypus
+ 1 2 Mud taken
+ 2 4 Needle taken
+ 3 8 Twig taken
+ 4 0x10
+ 5 0x20 Keys taken
+ 6 0x40 Grass taken
+ 7 0x80 Barn padlock open
+ 8 0x100 Truck filled with gas
+ 9 0x200 Truck keys used
+ 10 0x400 Platypus disguised
+ 11 0x800 Scene flag 1
+ 12 0x1000 Gnap controls toy ufo
+ 13 0x2000
+ 14 0x4000
+ 15 0x8000 Spring taken
+ 16 0x10000
+ 17 0x20000 Joint taken
+ 18 0x40000
+ 19 0x80000 Grocery store hat taken
+ 20 0x100000 Picture taken
+ 21 0x200000
+ 22 0x400000
+ 23 0x800000
+ 24 0x1000000
+ 25 0x2000000
+ 26 0x4000000 Platypus talking with toy shop assistant
+ 27 0x8000000
+ 28 0x10000000
+ 29 0x20000000 Gas taken
+ 30 0x40000000
+ 31 0x80000000
+
+
+*/
+
+ // 0x7AB Gnap walks to the right 1
+ // 0x7AC Gnap walks to the right 2
+ // 0x7AF Gnap walks to the left 1
+ // 0x7B0 Gnap walks to the left 2
+
+struct Scene49Obstacle {
+ int currSequenceId;
+ int closerSequenceId;
+ int passedSequenceId;
+ int splashSequenceId;
+ int collisionSequenceId;
+ int prevId;
+ int currId;
+ int laneNum;
+};
+
+struct Scene51Item {
+ int currSequenceId;
+ int droppedSequenceId;
+ int x, y;
+ int collisionX;
+ int canCatch;
+ int isCollision;
+ int x2;
+ int id;
+};
+
+class GnapEngine : public Engine {
+protected:
+ Common::Error run();
+ virtual bool hasFeature(EngineFeature f) const;
+public:
+ GnapEngine(OSystem *syst, const ADGameDescription *gd);
+ ~GnapEngine();
+private:
+ const ADGameDescription *_gameDescription;
+ Graphics::PixelFormat _pixelFormat;
+public:
+ Common::RandomSource *_random;
+
+ Common::PEResources *_exe;
+
+ DatManager *_dat;
+ SpriteCache *_spriteCache;
+ SoundCache *_soundCache;
+ SequenceCache *_sequenceCache;
+ GameSys *_gameSys;
+ SoundMan *_soundMan;
+
+ int _lastUpdateClock;
+
+ int _debugLevel;
+ bool _gameDone;
+
+ byte _keyPressState[512];
+ byte _keyDownState[512];
+
+ bool _isPaused;
+ Graphics::Surface *_pauseSprite;
+ int _timers[kMaxTimers], _savedTimers[kMaxTimers];
+
+ MouseButtonState _mouseButtonState;
+ MouseButtonState _mouseClickState;
+
+ uint32 _keyStatus1[2];
+
+ bool _sceneSavegameLoaded, _wasSavegameLoaded;
+
+ Graphics::Surface *_backgroundSurface;
+ int _prevSceneNum, _currentSceneNum, _newSceneNum;
+ bool _sceneDone, _sceneWaiting;
+
+ uint32 _inventory, _gameFlags;
+
+ Hotspot _hotspots[20];
+ Common::Point _hotspotsWalkPos[20];
+ int _hotspotsCount;
+ int _sceneClickedHotspot;
+
+ bool _isWaiting;
+ bool _isLeavingScene;
+
+ bool _isStockDatLoaded;
+
+ int _newCursorValue, _cursorValue;
+
+ int _verbCursor, _cursorIndex;
+ int _mouseX, _mouseY;
+ int _leftClickMouseX, _leftClickMouseY;
+
+ Graphics::Surface *_grabCursorSprite;
+ int _currGrabCursorX, _currGrabCursorY;
+ int _grabCursorSpriteIndex, _newGrabCursorSpriteIndex;
+
+ Graphics::Surface *_fullScreenSprite;
+ int _fullScreenSpriteId;
+
+ int _deviceX1, _deviceY1, _deviceX2, _deviceY2;
+
+ int _soundTimerIndexA;
+ int _soundTimerIndexB;
+ int _soundTimerIndexC;
+ int _idleTimerIndex;
+
+ void updateEvents();
+ void gameUpdateTick();
+ void saveTimers();
+ void restoreTimers();
+
+ void pauseGame();
+ void resumeGame();
+ void updatePause();
+
+ int getRandom(int max);
+
+ int readSavegameDescription(int savegameNum, Common::String &description);
+ int loadSavegame(int savegameNum);
+
+ void delayTicks(int a1);
+ void delayTicksCursor(int a1);
+
+ void setHotspot(int index, int16 x1, int16 y1, int16 x2, int16 y2, uint16 flags = 0,
+ int16 walkX = -1, int16 walkY = -1);
+ int getHotspotIndexAtPos(int16 x, int16 y);
+ void updateCursorByHotspot();
+ int getClickedHotspotId();
+
+ int getInventoryItemSpriteNum(int index);
+
+ void updateMouseCursor();
+ void setVerbCursor(int verbCursor);
+ void setCursor(int cursorIndex);
+ void showCursor();
+ void hideCursor();
+
+ void setGrabCursorSprite(int index);
+ void createGrabCursorSprite(int spriteId);
+ void freeGrabCursorSprite();
+ void updateGrabCursorSprite(int x, int y);
+
+ void invClear();
+ void invAdd(int itemId);
+ void invRemove(int itemId);
+ bool invHas(int itemId);
+
+ void clearFlags();
+ void setFlag(int num);
+ void clearFlag(int num);
+ bool isFlag(int num);
+
+ Graphics::Surface *addFullScreenSprite(int resourceId, int id);
+ void removeFullScreenSprite();
+ void showFullScreenSprite(int resourceId);
+
+ void queueInsertDeviceIcon();
+ void insertDeviceIconActive();
+ void removeDeviceIconActive();
+ void setDeviceHotspot(int hotspotIndex, int x1, int y1, int x2, int y2);
+
+ int getSequenceTotalDuration(int resourceId);
+
+ bool isSoundPlaying(int resourceId);
+ void playSound(int resourceId, bool looping);
+ void stopSound(int resourceId);
+ void setSoundVolume(int resourceId, int volume);
+
+ void updateTimers();
+
+ void initGameFlags(int num);
+ void loadStockDat();
+
+ void mainLoop();
+ void initScene();
+ void endSceneInit();
+ void afterScene();
+
+ int initSceneLogic();
+ void runSceneLogic();
+
+ void checkGameKeys();
+
+ void startSoundTimerA(int timerIndex);
+ int playSoundA();
+ void startSoundTimerB(int timerIndex);
+ int playSoundB();
+ void startSoundTimerC(int timerIndex);
+ int playSoundC();
+ void startIdleTimer(int timerIndex);
+ void updateIdleTimer();
+
+ void screenEffect(int dir, byte r, byte g, byte b);
+
+ bool isKeyStatus1(int key);
+ bool isKeyStatus2(int key);
+ void clearKeyStatus1(int key);
+ void clearAllKeyStatus1();
+
+ void deleteSurface(Graphics::Surface **surface);
+
+ // Menu
+ int _menuStatus;
+ int _menuSpritesIndex;
+ bool _menuDone;
+ Graphics::Surface *_menuBackgroundSurface;
+ Graphics::Surface *_menuQuitQuerySprite;
+ Graphics::Surface *_largeSprite;
+ Graphics::Surface *_menuSaveLoadSprite;
+ Graphics::Surface *_menuSprite2;
+ Graphics::Surface *_menuSprite1;
+ char _savegameFilenames[7][30];
+ Graphics::Surface *_savegameSprites[7];
+ Graphics::Surface *_spriteHandle;
+ Graphics::Surface *_cursorSprite;
+ int _menuInventoryIndices[30];
+ Graphics::Surface *_menuInventorySprites[30];
+ int _savegameIndex;
+ void createMenuSprite();
+ void freeMenuSprite();
+ void initMenuHotspots1();
+ void initMenuHotspots2();
+ void initMenuQuitQueryHotspots();
+ void initSaveLoadHotspots();
+ void drawInventoryFrames();
+ void insertInventorySprites();
+ void removeInventorySprites();
+ void runMenu();
+ void updateMenuStatusInventory();
+ void updateMenuStatusMainMenu();
+ void updateMenuStatusSaveGame();
+ void updateMenuStatusLoadGame();
+ void updateMenuStatusQueryQuit();
+
+ // Grid common
+ int _gnapGridX, _gnapGridY;
+ int _platGridX, _platGridY;
+ int _gridMinX, _gridMinY;
+ int _gridMaxX, _gridMaxY;
+ bool isPointBlocked(int gridX, int gridY);
+ void initSceneGrid(int gridMinX, int gridMinY, int gridMaxX, int gridMaxY);
+ bool testWalk(int animationIndex, int someStatus, int gridX1, int gridY1, int gridX2, int gridY2);
+
+ // Gnap walking
+ int _gnapWalkNodesCount;
+ GridStruct _gnapWalkNodes[kMaxGridStructs];
+ int _gnapX, _gnapY;
+ int _gnapWalkDestX, _gnapWalkDestY;
+ int _gnapWalkDeltaX, _gnapWalkDeltaY, _gnapWalkDirX, _gnapWalkDirY, _gnapWalkDirXIncr, _gnapWalkDirYIncr;
+
+ int getGnapWalkSequenceId(int deltaX, int deltaY);
+ int getGnapWalkStopSequenceId(int deltaX, int deltaY);
+ int getGnapWalkFacing(int deltaX, int deltaY);
+ bool gridSub41F08B(int gridX, int gridY);
+ bool gridSub41F5FC(int gridX, int gridY, int index);
+ bool gridSub41FAD5(int gridX, int gridY, int index);
+ bool gnapFindPath3(int gridX, int gridY);
+ bool gnapWalkTo(int gridX, int gridY, int animationIndex, int sequenceId, int flags);
+ void gnapWalkStep();
+
+ // Beaver walking
+ int _platWalkNodesCount;
+ GridStruct _platWalkNodes[kMaxGridStructs];
+ int _platX, _platY;
+ int _platWalkDestX, _platWalkDestY;
+ int _platWalkDeltaX, _platWalkDeltaY, _platWalkDirX, _platWalkDirY, _platWalkDirXIncr, _platWalkDirYIncr;
+
+ int getBeaverWalkSequenceId(int deltaX, int deltaY);
+ bool gridSub423750(int gridX, int gridY);
+ bool gridSub423CC1(int gridX, int gridY, int index);
+ bool gridSub42419A(int gridX, int gridY, int index);
+ bool platFindPath3(int gridX, int gridY);
+ bool platypusWalkTo(int gridX, int gridY, int animationIndex, int sequenceId, int flags);
+ void platypusWalkStep();
+ void beaverMakeRoom();
+
+ // Gnap
+ int _gnapIdleFacing;
+ int _gnapActionStatus;
+ int _gnapBrainPulseNum, _gnapBrainPulseRndValue;
+ int _gnapSequenceId, _gnapSequenceDatNum, _gnapId;
+ int _gnapRandomValue;
+
+ int getGnapSequenceId(int kind, int gridX, int gridY);
+ int getGnapShowSequenceId(int index, int gridX, int gridY);
+ void gnapIdle();
+ void gnapActionIdle(int sequenceId);
+ void playGnapSequence(int sequenceId);
+ void playGnapImpossible(int gridX, int gridY);
+ void playGnapScratchingHead(int gridX, int gridY);
+ void playGnapMoan1(int gridX, int gridY);
+ void playGnapMoan2(int gridX, int gridY);
+ void playGnapBrainPulsating(int gridX, int gridY);
+ void playGnapPullOutDevice(int gridX, int gridY);
+ void playGnapPullOutDeviceNonWorking(int gridX, int gridY);
+ void playGnapUseDevice(int gridX, int gridY);
+ void playGnapIdle(int gridX, int gridY);
+ void playGnapShowItem(int itemIndex, int gridLookX, int gridLookY);
+ void playGnapShowCurrItem(int gridX, int gridY, int gridLookX, int gridLookY);
+ void updateGnapIdleSequence();
+ void updateGnapIdleSequence2();
+ void initGnapPos(int gridX, int gridY, int facing);
+ void gnapInitBrainPulseRndValue();
+ void gnapUseDeviceOnBeaver();
+ void doCallback(int callback);
+ bool gnapPlatypusAction(int gridX, int gridY, int platSequenceId, int callback);
+ void gnapKissPlatypus(int callback);
+ void gnapUseJointOnPlatypus();
+ void gnapUseDisguiseOnPlatypus();
+
+ // Beaver
+ int _beaverFacing;
+ int _beaverActionStatus;
+ int _beaverSequenceId, _beaverSequenceDatNum, _beaverId;
+ int getBeaverSequenceId(int kind, int gridX, int gridY);
+ void playBeaverSequence(int sequenceId);
+ void updateBeaverIdleSequence();
+ void beaverSub426234();
+ void initBeaverPos(int gridX, int gridY, int facing);
+
+ // Scenes
+
+ int _toyUfoNextSequenceId, _toyUfoSequenceId;
+ int _toyUfoId;
+ int _toyUfoActionStatus;
+ int _toyUfoX;
+ int _toyUfoY;
+
+ void initGlobalSceneVars();
+
+ bool sceneXX_sub_4466B1();
+ void sceneXX_playRandomSound(int timerIndex);
+ void playSequences(int fullScreenSpriteId, int sequenceId1, int sequenceId2, int sequenceId3);
+
+ // Scene 0
+ int scene00_init();
+
+ // Scene 1
+ int _s01_pigsIdCtr, _s01_smokeIdCtr;
+ Graphics::Surface *_s01_spaceshipSurface;
+ int scene01_init();
+ void scene01_updateHotspots();
+ void scene01_run();
+ void scene01_updateAnimations();
+
+ // Scene 2
+ int _s02_truckGrillCtr;
+ int _s02_nextChickenSequenceId, _s02_currChickenSequenceId;
+ int _s02_gnapTruckSequenceId;
+ int scene02_init();
+ void scene02_updateHotspots();
+ void scene02_run();
+ void scene02_updateAnimations();
+
+ // Scene 3
+ bool _s03_platypusHypnotized;
+ bool _s03_platypusScared;
+ int _s03_nextPlatSequenceId;
+ int _s03_nextFrogSequenceId, _s03_currFrogSequenceId;
+ int scene03_init();
+ void scene03_updateHotspots();
+ void scene03_run();
+ void scene03_updateAnimations();
+
+ // Scene 4
+ bool _s04_triedWindow;
+ int _s04_dogIdCtr;
+ int _s04_nextDogSequenceId, _s04_currDogSequenceId;
+ int scene04_init();
+ void scene04_updateHotspots();
+ void scene04_run();
+ void scene04_updateAnimations();
+
+ // Scene 5
+ int _s05_nextChickenSequenceId, _s05_currChickenSequenceId;
+ int scene05_init();
+ void scene05_updateHotspots();
+ void scene05_run();
+ void scene05_updateAnimations();
+
+ // Scene 6
+ bool _s06_horseTurnedBack;
+ int _s06_nextPlatSequenceId;
+ int _s06_nextHorseSequenceId, _s06_currHorseSequenceId;
+ int scene06_init();
+ void scene06_updateHotspots();
+ void scene06_run();
+ void scene06_updateAnimations();
+
+ // Scene 7
+ int scene07_init();
+ void scene07_updateHotspots();
+ void scene07_run();
+ void scene07_updateAnimations();
+
+ // Scene 8
+ int _s08_nextDogSequenceId, _s08_currDogSequenceId;
+ int _s08_nextManSequenceId, _s08_currManSequenceId;
+ int scene08_init();
+ void scene08_updateHotspots();
+ void scene08_updateAnimationsCb();
+ void scene08_run();
+ void scene08_updateAnimations();
+
+ // Scene 9
+ int scene09_init();
+ void scene09_updateHotspots();
+ void scene09_run();
+ void scene09_updateAnimations();
+
+ // Scene 10
+ int _s10_nextCookSequenceId, _s10_currCookSequenceId;
+ int scene10_init();
+ void scene10_updateHotspots();
+ void scene10_run();
+ void scene10_updateAnimations();
+ void scene10_updateAnimationsCb();
+
+ // Scene 11
+ int _s11_billardBallCtr;
+ int _s11_nextHookGuySequenceId, _s11_currHookGuySequenceId;
+ int _s11_nextGoggleGuySequenceId, _s11_currGoggleGuySequenceId;
+ int scene11_init();
+ void scene11_updateHotspots();
+ void scene11_run();
+ void scene11_updateAnimations();
+
+ // Scene 12
+ int _s12_nextBeardGuySequenceId, _s12_currBeardGuySequenceId;
+ int _s12_nextToothGuySequenceId, _s12_currToothGuySequenceId;
+ int _s12_nextBarkeeperSequenceId, _s12_currBarkeeperSequenceId;
+ int scene12_init();
+ void scene12_updateHotspots();
+ void scene12_run();
+ void scene12_updateAnimations();
+
+ // Scene 13
+ int _s13_backToiletCtr;
+ int scene13_init();
+ void scene13_updateHotspots();
+ void scene13_showScribble();
+ void scene13_run();
+ void scene13_updateAnimations();
+
+ // Scene 14
+ int scene14_init();
+ void scene14_updateHotspots();
+ void scene14_run();
+ void scene14_updateAnimations();
+
+ // Scene 15
+ int _s15_nextRecordSequenceId, _s15_currRecordSequenceId;
+ int _s15_nextSlotSequenceId, _s15_currSlotSequenceId;
+ int _s15_nextUpperButtonSequenceId, _s15_currUpperButtonSequenceId;
+ int _s15_nextLowerButtonSequenceId, _s15_currLowerButtonSequenceId;
+ int scene15_init();
+ void scene15_updateHotspots();
+ void scene15_run();
+ void scene15_updateAnimations();
+
+ // Scene 16
+ void scene16_initCutscene();
+
+ // Scene 17
+ bool _s17_canTryGetWrench;
+ int _s17_wrenchCtr, _s17_platPhoneCtr, _s17_platTryGetWrenchCtr;
+ int _s17_nextPhoneSequenceId, _s17_currPhoneSequenceId;
+ int _s17_nextWrenchSequenceId, _s17_currWrenchSequenceId;
+ int _s17_nextCarWindowSequenceId, _s17_currCarWindowSequenceId;
+ int scene17_init();
+ void scene17_updateHotspots();
+ void scene17_update();
+ void scene17_platHangUpPhone();
+ void scene17_run();
+ void scene17_updateAnimations();
+
+ // Scene 18
+ int _s18_garbageCanPos;
+ int _s18_platPhoneCtr;
+ int _s18_platPhoneIter;
+ int _s18_nextPhoneSequenceId, _s18_currPhoneSequenceId;
+ Graphics::Surface *_s18_cowboyHatSurface;
+ int scene18_init();
+ void scene18_updateHotspots();
+ void scene18_gnapCarryGarbageCanTo(int a1, int arg4, int animationIndex, int argC, int a5);
+ void scene18_putDownGarbageCan(int animationIndex);
+ void scene18_platEndPhoning(int a1);
+ void scene18_closeHydrantValve();
+ void scene18_waitForGnapAction();
+ void scene18_run();
+ void scene18_updateAnimations();
+
+ // Scene 19
+ int _s19_currShopAssistantSequenceId, _s19_nextShopAssistantSequenceId;
+ int _s19_toyGrabCtr;
+ int _s19_shopAssistantCtr;
+ Graphics::Surface *_s19_pictureSurface;
+ int scene19_init();
+ void scene19_updateHotspots();
+ void scene19_run();
+ void scene19_updateAnimations();
+
+ // Scene 20
+ int _s20_currStonerGuySequenceId, _s20_nextStonerGuySequenceId;
+ int _s20_currGroceryStoreGuySequenceId, _s20_nextGroceryStoreGuySequenceId;
+ int _s20_stonerGuyCtr;
+ bool _s20_stonerGuyShowingJoint;
+ int _s20_groceryStoreGuyCtr;
+ int scene20_init();
+ void scene20_updateHotspots();
+ void scene20_updateAnimationsCb();
+ void scene20_stopSounds();
+ void scene20_run();
+ void scene20_updateAnimations();
+
+ // Scene 21
+ int _s21_currOldLadySequenceId, _s21_nextOldLadySequenceId;
+ int scene21_init();
+ void scene21_updateHotspots();
+ void scene21_run();
+ void scene21_updateAnimations();
+
+ // Scene 22
+ int _s22_currCashierSequenceId, _s22_nextCashierSequenceId;
+ bool _s22_caughtBefore;
+ int _s22_cashierCtr;
+ int scene22_init();
+ void scene22_updateHotspots();
+ void scene22_run();
+ void scene22_updateAnimations();
+
+ // Scene 23
+ int _s23_currStoreClerkSequenceId, _s23_nextStoreClerkSequenceId;
+ int scene23_init();
+ void scene23_updateHotspots();
+ void scene23_run();
+ void scene23_updateAnimations();
+
+ // Scene 24
+ int _s24_currWomanSequenceId, _s24_nextWomanSequenceId;
+ int _s24_boySequenceId;
+ int _s24_girlSequenceId;
+ int scene24_init();
+ void scene24_updateHotspots();
+ void scene24_run();
+ void scene24_updateAnimations();
+
+ // Scene 25
+ int _s25_currTicketVendorSequenceId, _s25_nextTicketVendorSequenceId;
+ int scene25_init();
+ void scene25_updateHotspots();
+ void scene25_playAnims(int index);
+ void scene25_run();
+ void scene25_updateAnimations();
+
+ // Scene 26
+ int _s26_currKidSequenceId, _s26_nextKidSequenceId;
+ int scene26_init();
+ void scene26_updateHotspots();
+ void scene26_run();
+ void scene26_updateAnimations();
+
+ // Scene 27
+ int _s27_nextJanitorSequenceId;
+ int _s27_currJanitorSequenceId;
+ int scene27_init();
+ void scene27_updateHotspots();
+ void scene27_run();
+ void scene27_updateAnimations();
+
+ // Scene 28
+ int _s28_dword_47EA5C;
+ int _s28_dword_47EA60;
+ int _s28_dword_474938;
+ int scene28_init();
+ void scene28_updateHotspots();
+ void scene28_run();
+ void scene28_updateAnimations();
+
+ // Scene 29
+ int _s29_dword_47EA74;
+ int _s29_dword_47EA78;
+ int _s29_dword_47EA7C;
+ int _s29_dword_47EA80;
+ int scene29_init();
+ void scene29_updateHotspots();
+ void scene29_run();
+ void scene29_updateAnimations();
+
+ // Scene 30
+ int _s30_dword_47EA88;
+ int _s30_dword_47EA8C;
+ int scene30_init();
+ void scene30_updateHotspots();
+ void scene30_run();
+ void scene30_updateAnimations();
+
+ // Scene 31
+ int _s31_dword_47EAA8;
+ int _s31_dword_47EAAC;
+ int _s31_dword_47EAB0;
+ bool _s31_beerGuyDistracted;
+ int _s31_dword_474940;
+ int _s31_dword_47EAB4;
+ int scene31_init();
+ void scene31_updateHotspots();
+ void scene31_run();
+ void scene31_updateAnimations();
+
+ // Scene 32
+ int _s32_dword_47EADC;
+ int scene32_init();
+ void scene32_updateHotspots();
+ void scene32_run();
+ void scene32_updateAnimations();
+
+ int _s33_dword_47EAE4;
+ int _s33_dword_47EAE8;
+ int _s33_dword_47EAEC;
+ int scene33_init();
+ void scene33_updateHotspots();
+ void scene33_run();
+ void scene33_updateAnimations();
+
+ // Scene 38
+ int scene38_init();
+ void scene38_updateHotspots();
+ void scene38_run();
+ void scene38_updateAnimations();
+
+ // Scene 39
+ int _s39_dword_47EAF8;
+ int _s39_dword_47EAFC;
+ int scene39_init();
+ void scene39_updateHotspots();
+ void scene39_run();
+ void scene39_updateAnimations();
+
+ // Scene 40
+ int scene40_init();
+ void scene40_updateHotspots();
+ void scene40_run();
+ void scene40_updateAnimations();
+
+ // Scene 4x
+ void toyUfoSetStatus(int a1);
+ int toyUfoGetSequenceId();
+ bool toyUfoCheckTimer();
+ void toyUfoFlyTo(int destX, int destY, int a3, int a4, int a5, int a6, int animationIndex);
+
+ // Scene 41
+ int _s41_dword_47F2C0;
+ int _s41_dword_47F2C4;
+ int _s41_dword_47F2C8;
+ int _s41_dword_47F2CC;
+ int scene41_init();
+ void scene41_updateHotspots();
+ void scene41_run();
+ void scene41_updateAnimations();
+
+ // Scene 42
+ int _s42_dword_47F2B8;
+ int _s42_dword_47F2BC;
+ int scene42_init();
+ void scene42_updateHotspots();
+ void scene42_run();
+ void scene42_updateAnimations();
+
+ // Scene 43
+ int _s43_dword_47F2B0;
+ int _s43_dword_47F2B4;
+ int scene43_init();
+ void scene43_updateHotspots();
+ void scene43_run();
+ void scene43_updateAnimations();
+
+ // Scene 44
+ int _s44_dword_47EB04;
+ int _s44_dword_47EB08;
+ int _s44_dword_47EB0C;
+ int _s44_dword_47EB10;
+ int scene44_init();
+ void scene44_updateHotspots();
+ void scene44_run();
+ void scene44_updateAnimations();
+
+ // Scene 45
+ int _s45_dword_4749BC;
+ int _s45_dword_4749C0;
+ int scene45_init();
+ void scene45_updateHotspots();
+ void scene45_run();
+ void scene45_updateAnimations();
+
+ // Scene 46
+ int _s46_dword_47EB18;
+ int _s46_dword_47EB1C;
+ int _s46_dword_47EB20;
+ int _s46_dword_47EB24;
+ int scene46_init();
+ void scene46_updateHotspots();
+ void scene46_run();
+ void scene46_updateAnimations();
+
+ // Scene 47
+ void scene47_initCutscene1();
+ void scene47_initCutscene2();
+ void scene47_initCutscene3();
+ void scene47_initCutscene4();
+ void scene47_initCutscene5();
+ void scene47_initCutscene6();
+ void scene47_initCutscene7();
+
+ // Scene 48
+ void scene48_initCutscene();
+
+ // Scene 49
+ int _s49_scoreBarPos, _s49_scoreLevel, _s49_scoreBarFlash;
+ int _s49_obstacleIndex;
+ Scene49Obstacle _s49_obstacles[5];
+ int _s49_truckSequenceId, _s49_truckId, _s49_truckLaneNum;
+ int scene49_init();
+ void scene49_updateHotspots();
+ void scene49_checkObstacles();
+ void scene49_updateObstacle(int i);
+ void scene49_increaseScore(int amount);
+ void scene49_decreaseScore(int amount);
+ void scene49_refreshScoreBar();
+ void scene49_clearObstacle(int index);
+ void scene49_run();
+ void scene49_updateAnimations();
+
+ // Scene 50
+ bool _s50_fightDone;
+ int _s50_timesPlayed, _s50_timesPlayedModifier;
+ int _s50_attackCounter;
+ int _s50_roundNum, _s50_timeRemaining;
+ int _s50_leftTongueRoundsWon, _s50_rightTongueRoundsWon;
+ int _s50_leftTongueEnergyBarPos, _s50_rightTongueEnergyBarPos;
+ int _s50_leftTongueSequenceId, _s50_leftTongueId;
+ int _s50_leftTongueNextSequenceId, _s50_leftTongueNextId, _s50_leftTongueNextIdCtr;
+ int _s50_rightTongueSequenceId, _s50_rightTongueId;
+ int _s50_rightTongueNextSequenceId, _s50_rightTongueNextId, _s50_rightTongueNextIdCtr;
+ int _s50_leftTongueEnergy, _s50_rightTongueEnergy;
+ int scene50_init();
+ void scene50_updateHotspots();
+ bool scene50_tongueWinsRound(int tongueNum);
+ void scene50_playWinAnim(int tongueNum, bool fightOver);
+ void scene50_delayTicks();
+ void scene50_initRound();
+ bool scene50_updateCountdown();
+ void scene50_drawCountdown(int value);
+ void scene50_playTonguesIdle();
+ void scene50_playRoundAnim(int roundNum);
+ bool scene50_updateEnergyBars(int newLeftBarPos, int newRightBarPos);
+ void scene50_waitForAnim(int animationIndex);
+ int scene50_checkInput();
+ int scene50_getRightTongueAction();
+ void scene50_updateAnimations();
+ int scene50_getRightTongueActionTicks();
+ int scene50_getLeftTongueNextId();
+ int scene50_getRightTongueNextId();
+ void scene50_playWinBadgeAnim(int tongueNum);
+ void scene50_run();
+
+ // Scene 51
+ int _s51_cashAmount;
+ int _s51_digits[4];
+ int _s51_digitSequenceIds[4];
+ int _s51_guySequenceId, _s51_guyNextSequenceId;
+ int _s51_itemsCaughtCtr;
+ int _s51_dropSpeedTicks;
+ int _s51_nextDropItemKind, _s51_itemInsertX, _s51_itemInsertDirection;
+ int _s51_platypusSequenceId, _s51_platypusNextSequenceId, _s51_platypusJumpSequenceId;
+ bool _s51_dropLoseCash;
+ int _s51_itemsCtr,_s51_itemsCtr1, _s51_itemsCtr2;
+ Scene51Item _s51_items[6];
+
+ int scene51_init();
+ void scene51_updateHotspots();
+ void scene51_clearItem(Scene51Item *item);
+ void scene51_dropNextItem();
+ void scene51_updateItemAnimations();
+ int scene51_checkCollision(int sequenceId);
+ void scene51_updateItemAnimation(Scene51Item *item, int index);
+ void scene51_removeCollidedItems();
+ int scene51_itemIsCaught(Scene51Item *item);
+ bool scene51_isJumpingRight(int sequenceId);
+ bool scene51_isJumpingLeft(int sequenceId);
+ bool scene51_isJumping(int sequenceId);
+ void scene51_waitForAnim(int animationIndex);
+ int scene51_getPosRight(int sequenceId);
+ int scene51_getPosLeft(int sequenceId);
+ void scene51_playIntroAnim();
+ void scene51_updateGuyAnimation();
+ int scene51_incCashAmount(int sequenceId);
+ void scene51_winMinigame();
+ void scene51_playCashAppearAnim();
+ void scene51_updateCash(int amount);
+ void scene51_drawDigit(int digit, int position);
+ void scene51_initCashDisplay();
+ void scene51_run();
+
+ // Scene 52
+ int _s52_liveAlienRows;
+ int _s52_gameScore;
+ bool _s52_soundToggle;
+ int _s52_arcadeScreenLeft;
+ int _s52_arcadeScreenRight;
+ int _s52_arcadeScreenBottom;
+ int _s52_shipsLeft;
+ int _s52_shieldSpriteIds[3];
+ int _s52_shieldPosX[3];
+ int _s52_shipPosX;
+ int _s52_shipCannonFired, _s52_shipCannonPosX, _s52_shipCannonPosY;
+ int _s52_shipCannonFiring;
+ int _s52_shipCannonWidth, _s52_shipCannonHeight;
+ int _s52_shipCannonTopY;
+ int _s52_shipMidX, _s52_shipMidY;
+ bool _s52_shipFlag;
+ bool _s52_aliensInitialized;
+ int _s52_alienSpeed, _s52_alienDirection;
+ int _s52_alienWidth, _s52_alienHeight;
+ int _s52_alienLeftX, _s52_alienTopY;
+ int _s52_alienRowDownCtr;
+ int _s52_alienRowKind[7];
+ int _s52_alienRowAnims[7];
+ int _s52_alienRowIds[7];
+ int _s52_alienRowXOfs[7];
+ int _s52_alienCannonFired[3];
+ int _s52_alienCannonPosX[3];
+ int _s52_alienCannonPosY[3];
+ int _s52_alienCannonSequenceIds[3];
+ int _s52_alienCannonIds[3];
+ bool _s52_alienWave, _s52_alienSingle;
+ int _s52_alienCounter;
+ bool _s52_bottomAlienFlag;
+ int _s52_aliensCount;
+ int _s52_items[8][5];
+ int _s52_nextUfoSequenceId, _s52_ufoSequenceId;
+ int scene52_init();
+ void scene52_updateHotspots();
+ void scene52_update();
+ void scene52_initShipCannon(int bottomY);
+ void scene52_initAlienCannons();
+ void scene52_fireShipCannon(int posX);
+ void scene52_fireAlienCannon();
+ int scene52_getFreeShipCannon();
+ int scene52_getFreeAlienCannon();
+ void scene52_updateShipCannon();
+ void scene52_updateAlienCannons();
+ void scene52_initAliens();
+ void scene52_initAlienRowKind(int rowNum, int alienKind);
+ void scene52_insertAlienRow(int rowNum);
+ void scene52_insertAlienRowAliens(int rowNum);
+ void scene52_updateAlienRow(int rowNum);
+ void scene52_moveDownAlienRow();
+ int scene52_updateHitAlien();
+ int scene52_getHitAlienNum(int rowNum);
+ int scene52_alienCannonHitShip(int cannonNum);
+ int scene52_alienCannonHitShield(int cannonNum);
+ int scene52_shipCannonHitShield(int cannonNum);
+ int scene52_shipCannonHitAlien();
+ void scene52_shipExplode();
+ int scene52_checkAlienRow(int a1);
+ void scene52_updateAlienRowXOfs();
+ void scene52_initAlienSize();
+ void scene52_playSound();
+ void scene52_updateAliens();
+ void scene52_updateAlien(int rowNum);
+ void scene52_loseShip();
+ void scene52_initShields();
+ void scene52_initAnims();
+ void scene52_drawScore(int a1);
+ void scene52_run();
+
+ // Scene 53
+ int _s53_currHandSequenceId;
+ bool _s53_isGnapPhoning;
+ int _s53_callsMadeCtr;
+ uint _s53_callsRndUsed;
+ int scene53_init();
+ void scene53_updateHotspots();
+ int scene53_pressPhoneNumberButton(int phoneNumber, int buttonNum);
+ int scene53_getRandomCallIndex();
+ void scene53_runRandomCall();
+ void scene53_runChitChatLine();
+ void scene53_run();
+
+ // Scene 54
+ void scene54_initCutscene1();
+ void scene54_initCutscene2();
+
+ // Scene 99
+ int _s99_itemsCount;
+ int _s99_dword_47F2F0[16];
+ int _s99_dword_47F330[16];
+ int _s99_dword_47F370[50];
+ byte _s99_canSkip[16];
+ int cutscene_init();
+ void cutscene_run();
+
+};
+
+} // End of namespace Gnap
+
+#endif // GNAP_H
diff --git a/engines/gnap/grid.cpp b/engines/gnap/grid.cpp
new file mode 100644
index 0000000000..522c72c491
--- /dev/null
+++ b/engines/gnap/grid.cpp
@@ -0,0 +1,1392 @@
+/* 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"
+
+namespace Gnap {
+
+void GnapEngine::initSceneGrid(int gridMinX, int gridMinY, int gridMaxX, int gridMaxY) {
+ _gridMinX = gridMinX;
+ _gridMinY = gridMinY;
+ _gridMaxX = gridMaxX;
+ _gridMaxY = gridMaxY;
+ _gnapGridX = 410 - gridMinX;
+ _gnapGridY = 450 - gridMinY;
+ _platGridX = 396 - gridMinX;
+ _platGridY = 347 - gridMinY;
+}
+
+int GnapEngine::getGnapWalkSequenceId(int deltaX, int deltaY) {
+ static const int _gnapWalkSequenceIds[9] = {
+ 0x7B2, 0x000, 0x7B4,
+ 0x7AD, 0x000, 0x7AE,
+ 0x7B1, 0x000, 0x7B3
+ };
+ // CHECKME This is a little weird
+ return _gnapWalkSequenceIds[3 * deltaX + 3 + 1 + deltaY];
+}
+
+int GnapEngine::getGnapWalkStopSequenceId(int deltaX, int deltaY) {
+ static const int _gnapWalkStopSequenceIds[9] = {
+ 0x7BC, 0x7BA, 0x7BA,
+ 0x7BC, 0x000, 0x7BA,
+ 0x7BB, 0x7B9, 0x7B9
+ };
+ // CHECKME This is a little weird
+ return _gnapWalkStopSequenceIds[3 * deltaX + 3 + 1 + deltaY];
+}
+
+int GnapEngine::getGnapWalkFacing(int deltaX, int deltaY) {
+ static const int _gnapWalkFacings[9] = {
+ 5, 3, 3,
+ 5, 0, 3,
+ 7, 1, 1
+ };
+ // CHECKME This is a little weird
+ return _gnapWalkFacings[3 * deltaX + 3 + 1 + deltaY];
+}
+
+bool GnapEngine::isPointBlocked(int gridX, int gridY) {
+
+ if (gridX < 0 || gridX >= _gridMaxX || gridY < 0 || gridY >= _gridMaxY)
+ return true;
+
+ if ((gridX == _gnapX && gridY == _gnapY) || (gridX == _platX && gridY == _platY))
+ return true;
+
+ const int x = _gridMinX + 75 * gridX;
+ const int y = _gridMinY + 48 * gridY;
+
+ for (int i = 0; i < _hotspotsCount; ++i) {
+ if (x >= _hotspots[i].x1 && x <= _hotspots[i].x2 &&
+ y >= _hotspots[i].y1 && y <= _hotspots[i].y2 &&
+ !(_hotspots[i].flags & SF_WALKABLE))
+ return true;
+ }
+
+ return false;
+
+}
+
+bool GnapEngine::gridSub41F08B(int gridX, int gridY) {
+ bool result = false;
+
+ _gnapWalkNodesCount = 0;
+ _gnapWalkDirXIncr = 0;
+ _gnapWalkDirYIncr = 0;
+ _gnapWalkDeltaX = ABS(_gnapWalkDestX - gridX);
+ _gnapWalkDeltaY = ABS(_gnapWalkDestY - gridY);
+
+ if (_gnapWalkDeltaX)
+ _gnapWalkDirX = (_gnapWalkDestX - gridX) / _gnapWalkDeltaX;
+ else
+ _gnapWalkDirX = 0;
+
+ if (_gnapWalkDeltaY)
+ _gnapWalkDirY = (_gnapWalkDestY - gridY) / _gnapWalkDeltaY;
+ else
+ _gnapWalkDirY = 0;
+
+ while (_gnapWalkDirXIncr < _gnapWalkDeltaX && _gnapWalkDirYIncr < _gnapWalkDeltaY) {
+ _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr;
+ _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr;
+ if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirXIncr;
+ ++_gnapWalkDirYIncr;
+ } else if (_gnapWalkDeltaY - _gnapWalkDirYIncr > _gnapWalkDeltaX - _gnapWalkDirXIncr) {
+ if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirYIncr;
+ } else if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0;
+ ++_gnapWalkDirXIncr;
+ } else {
+ _gnapWalkDeltaX = _gnapWalkDirXIncr;
+ _gnapWalkDeltaY = _gnapWalkDirYIncr;
+ --_gnapWalkNodesCount;
+ }
+ } else {
+ if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0;
+ ++_gnapWalkDirXIncr;
+ } else if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirYIncr;
+ } else {
+ _gnapWalkDeltaX = _gnapWalkDirXIncr;
+ _gnapWalkDeltaY = _gnapWalkDirYIncr;
+ --_gnapWalkNodesCount;
+ }
+ }
+ ++_gnapWalkNodesCount;
+ }
+
+ while (_gnapWalkDirXIncr < _gnapWalkDeltaX) {
+ _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr;
+ _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = _gnapWalkDestY;
+ if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDestY)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0;
+ ++_gnapWalkDirXIncr;
+ ++_gnapWalkNodesCount;
+ } else {
+ _gnapWalkDeltaX = _gnapWalkDirXIncr;
+ }
+ }
+
+ while (_gnapWalkDirYIncr < _gnapWalkDeltaY) {
+ _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = _gnapWalkDestX;
+ _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr;
+ if (!isPointBlocked(_gnapWalkDestX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirYIncr;
+ ++_gnapWalkNodesCount;
+ } else {
+ _gnapWalkDeltaY = _gnapWalkDirYIncr;
+ }
+ }
+
+ if (gridX + _gnapWalkDirX * _gnapWalkDirXIncr != _gnapWalkDestX || gridY + _gnapWalkDirY * _gnapWalkDirYIncr != _gnapWalkDestY) {
+ _gnapWalkDestX = gridX + _gnapWalkDirX * _gnapWalkDirXIncr;
+ _gnapWalkDestY = gridY + _gnapWalkDirY * _gnapWalkDirYIncr;
+ result = false;
+ } else {
+ result = true;
+ }
+
+ return result;
+}
+
+bool GnapEngine::gridSub41F5FC(int gridX, int gridY, int index) {
+ _gnapWalkNodesCount = index;
+ _gnapWalkDirXIncr = 0;
+ _gnapWalkDirYIncr = 0;
+ _gnapWalkDeltaX = ABS(_gnapWalkDestX - gridX);
+ _gnapWalkDeltaY = ABS(_gnapWalkDestY - gridY);
+
+ if (_gnapWalkDeltaX)
+ _gnapWalkDirX = (_gnapWalkDestX - gridX) / _gnapWalkDeltaX;
+ else
+ _gnapWalkDirX = 0;
+
+ if (_gnapWalkDeltaY)
+ _gnapWalkDirY = (_gnapWalkDestY - gridY) / _gnapWalkDeltaY;
+ else
+ _gnapWalkDirY = 0;
+
+ while (_gnapWalkDirXIncr < _gnapWalkDeltaX && _gnapWalkDirYIncr < _gnapWalkDeltaY) {
+ _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr;
+ _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr;
+ if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirXIncr;
+ ++_gnapWalkDirYIncr;
+ } else if (_gnapWalkDeltaY - _gnapWalkDirYIncr > _gnapWalkDeltaX - _gnapWalkDirXIncr) {
+ if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirYIncr;
+ } else if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0;
+ ++_gnapWalkDirXIncr;
+ } else
+ return false;
+ } else {
+ if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0;
+ ++_gnapWalkDirXIncr;
+ } else if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirYIncr;
+ } else
+ return false;
+ }
+ ++_gnapWalkNodesCount;
+ }
+
+ while (_gnapWalkDirXIncr < _gnapWalkDeltaX) {
+ _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr;
+ _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = _gnapWalkDestY;
+ if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDestY)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0;
+ ++_gnapWalkDirXIncr;
+ ++_gnapWalkNodesCount;
+ } else
+ return false;
+ }
+
+ while (_gnapWalkDirYIncr < _gnapWalkDeltaY) {
+ _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = _gnapWalkDestX;
+ _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr;
+ if (!isPointBlocked(_gnapWalkDestX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirYIncr;
+ ++_gnapWalkNodesCount;
+ } else
+ return false;
+ }
+
+ return true;
+}
+
+bool GnapEngine::gridSub41FAD5(int gridX, int gridY, int index) {
+ _gnapWalkNodesCount = index;
+ _gnapWalkDirXIncr = 0;
+ _gnapWalkDirYIncr = 0;
+ _gnapWalkDeltaX = ABS(_gnapWalkDestX - gridX);
+ _gnapWalkDeltaY = ABS(_gnapWalkDestY - gridY);
+
+ if (_gnapWalkDeltaX)
+ _gnapWalkDirX = (_gnapWalkDestX - gridX) / _gnapWalkDeltaX;
+ else
+ _gnapWalkDirX = 0;
+
+ if (_gnapWalkDeltaY)
+ _gnapWalkDirY = (_gnapWalkDestY - gridY) / _gnapWalkDeltaY;
+ else
+ _gnapWalkDirY = 0;
+
+ while (_gnapWalkDeltaY < _gnapWalkDeltaX - _gnapWalkDirXIncr) {
+ _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr;
+ _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY;
+ if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, gridY)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0;
+ ++_gnapWalkDirXIncr;
+ ++_gnapWalkNodesCount;
+ } else
+ return false;
+ }
+
+ while (_gnapWalkDeltaX < _gnapWalkDeltaY - _gnapWalkDirYIncr) {
+ _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX;
+ _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr;
+ if (!isPointBlocked(gridX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirYIncr;
+ ++_gnapWalkNodesCount;
+ } else
+ return false;
+ }
+
+ while (_gnapWalkDirXIncr < _gnapWalkDeltaX && _gnapWalkDirYIncr < _gnapWalkDeltaY) {
+ _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr;
+ _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr;
+ if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirXIncr;
+ ++_gnapWalkDirYIncr;
+ } else if (_gnapWalkDeltaY - _gnapWalkDirYIncr > _gnapWalkDeltaX - _gnapWalkDirXIncr) {
+ if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirYIncr;
+ } else if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0;
+ ++_gnapWalkDirXIncr;
+ } else
+ return false;
+ } else {
+ if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0;
+ ++_gnapWalkDirXIncr;
+ } else if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirYIncr;
+ } else
+ return false;
+ }
+ ++_gnapWalkNodesCount;
+ }
+
+ while (_gnapWalkDirXIncr < _gnapWalkDeltaX) {
+ _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr;
+ _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = _gnapWalkDestY;
+ if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDestY)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0;
+ ++_gnapWalkDirXIncr;
+ ++_gnapWalkNodesCount;
+ } else
+ return false;
+ }
+
+ while (_gnapWalkDirYIncr < _gnapWalkDeltaY) {
+ _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = _gnapWalkDestX;
+ _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr;
+ if (!isPointBlocked(_gnapWalkDestX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) {
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0;
+ _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY;
+ ++_gnapWalkDirYIncr;
+ ++_gnapWalkNodesCount;
+ } else
+ return false;
+ }
+
+ return true;
+}
+
+bool GnapEngine::gnapFindPath3(int gridX, int gridY) {
+ int gridIncr = 1;
+ bool done = false;
+
+ while (!done && gridIncr < _gridMaxX) {
+ if (!isPointBlocked(gridX + gridIncr, gridY) && gridSub41F5FC(gridX + gridIncr, gridY, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX + i;
+ _gnapWalkNodes[i].gridY1 = gridY;
+ _gnapWalkNodes[i].deltaX = 1;
+ _gnapWalkNodes[i].deltaY = 0;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX - gridIncr, gridY) && gridSub41F5FC(gridX - gridIncr, gridY, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX - i;
+ _gnapWalkNodes[i].gridY1 = gridY;
+ _gnapWalkNodes[i].deltaX = -1;
+ _gnapWalkNodes[i].deltaY = 0;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX, gridY + gridIncr) && gridSub41F5FC(gridX, gridY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX;
+ _gnapWalkNodes[i].gridY1 = gridY + i;
+ _gnapWalkNodes[i].deltaX = 0;
+ _gnapWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX, gridY - gridIncr) && gridSub41F5FC(gridX, gridY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX;
+ _gnapWalkNodes[i].gridY1 = gridY - i;
+ _gnapWalkNodes[i].deltaX = 0;
+ _gnapWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX + gridIncr, gridY + gridIncr) && gridSub41F5FC(gridX + gridIncr, gridY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX + i;
+ _gnapWalkNodes[i].gridY1 = gridY + i;
+ _gnapWalkNodes[i].deltaX = 1;
+ _gnapWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX - gridIncr, gridY + gridIncr) && gridSub41F5FC(gridX - gridIncr, gridY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX - i;
+ _gnapWalkNodes[i].gridY1 = gridY + i;
+ _gnapWalkNodes[i].deltaX = -1;
+ _gnapWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX + gridIncr, gridY - gridIncr) && gridSub41F5FC(gridX + gridIncr, gridY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX + i;
+ _gnapWalkNodes[i].gridY1 = gridY - i;
+ _gnapWalkNodes[i].deltaX = 1;
+ _gnapWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX - gridIncr, gridY - gridIncr) && gridSub41F5FC(gridX - gridIncr, gridY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX - i;
+ _gnapWalkNodes[i].gridY1 = gridY - i;
+ _gnapWalkNodes[i].deltaX = -1;
+ _gnapWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX + gridIncr, gridY) && gridSub41FAD5(gridX + gridIncr, gridY, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX + i;
+ _gnapWalkNodes[i].gridY1 = gridY;
+ _gnapWalkNodes[i].deltaX = 1;
+ _gnapWalkNodes[i].deltaY = 0;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX - gridIncr, gridY) && gridSub41FAD5(gridX - gridIncr, gridY, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX - i;
+ _gnapWalkNodes[i].gridY1 = gridY;
+ _gnapWalkNodes[i].deltaX = -1;
+ _gnapWalkNodes[i].deltaY = 0;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX, gridY + gridIncr) && gridSub41FAD5(gridX, gridY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX;
+ _gnapWalkNodes[i].gridY1 = gridY + i;
+ _gnapWalkNodes[i].deltaX = 0;
+ _gnapWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX, gridY - gridIncr) && gridSub41FAD5(gridX, gridY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX;
+ _gnapWalkNodes[i].gridY1 = gridY - i;
+ _gnapWalkNodes[i].deltaX = 0;
+ _gnapWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX + gridIncr, gridY + gridIncr) && gridSub41FAD5(gridX + gridIncr, gridY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX + i;
+ _gnapWalkNodes[i].gridY1 = gridY + i;
+ _gnapWalkNodes[i].deltaX = 1;
+ _gnapWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX - gridIncr, gridY + gridIncr) && gridSub41FAD5(gridX - gridIncr, gridY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX - i;
+ _gnapWalkNodes[i].gridY1 = gridY + i;
+ _gnapWalkNodes[i].deltaX = -1;
+ _gnapWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX + gridIncr, gridY - gridIncr) && gridSub41FAD5(gridX + gridIncr, gridY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX + i;
+ _gnapWalkNodes[i].gridY1 = gridY - i;
+ _gnapWalkNodes[i].deltaX = 1;
+ _gnapWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(gridX - gridIncr, gridY - gridIncr) && gridSub41FAD5(gridX - gridIncr, gridY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _gnapWalkNodes[i].gridX1 = gridX - i;
+ _gnapWalkNodes[i].gridY1 = gridY - i;
+ _gnapWalkNodes[i].deltaX = -1;
+ _gnapWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ ++gridIncr;
+ }
+
+ return done;
+}
+
+bool GnapEngine::gnapWalkTo(int gridX, int gridY, int animationIndex, int sequenceId, int flags) {
+
+ int datNum = flags & 3;
+ bool done = false;
+
+ _timers[2] = 200;
+ _timers[3] = 300;
+
+ if (gridX < 0)
+ gridX = (_leftClickMouseX - _gridMinX + 37) / 75;
+
+ if (gridY < 0)
+ gridY = (_leftClickMouseY - _gridMinY + 24) / 48;
+
+ _gnapWalkDestX = CLIP(gridX, 0, _gridMaxX - 1);
+ _gnapWalkDestY = CLIP(gridY, 0, _gridMaxY - 1);
+
+ if (animationIndex >= 0 && _gnapWalkDestX == _platX && _gnapWalkDestY == _platY)
+ beaverMakeRoom();
+
+ if (gridSub41F5FC(_gnapX, _gnapY, 0))
+ done = true;
+
+ if (!done && gridSub41FAD5(_gnapX, _gnapY, 0))
+ done = true;
+
+ if (!done && gnapFindPath3(_gnapX, _gnapY))
+ done = true;
+
+ if (!done && gridSub41F08B(_gnapX, _gnapY))
+ done = true;
+
+ gnapIdle();
+
+ int gnapSequenceId = _gnapSequenceId;
+ int gnapId = _gnapId;
+ int gnapSequenceDatNum = _gnapSequenceDatNum;
+
+ debug(0, "_gnapWalkNodesCount: %d", _gnapWalkNodesCount);
+
+ for (int index = 0; index < _gnapWalkNodesCount; ++index) {
+ _gnapWalkNodes[index].id = index + 20 * _gnapWalkNodes[index].gridY1;
+ if (_gnapWalkNodes[index].deltaX == 1 && _gnapWalkNodes[index].deltaY == 0) {
+ if (index % 2) {
+ _gameSys->insertSequence(makeRid(datNum, 0x7AB), _gnapWalkNodes[index].id,
+ makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId,
+ 9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY);
+ _gnapWalkNodes[index].sequenceId = 0x7AB;
+ gnapSequenceId = 0x7AB;
+ } else {
+ _gameSys->insertSequence(makeRid(datNum, 0x7AC), _gnapWalkNodes[index].id,
+ makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId,
+ 9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY);
+ _gnapWalkNodes[index].sequenceId = 0x7AC;
+ gnapSequenceId = 0x7AC;
+ }
+ } else if (_gnapWalkNodes[index].deltaX == -1 && _gnapWalkNodes[index].deltaY == 0) {
+ if (index % 2) {
+ _gameSys->insertSequence(makeRid(datNum, 0x7AF), _gnapWalkNodes[index].id,
+ makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId,
+ 9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY);
+ _gnapWalkNodes[index].sequenceId = 0x7AF;
+ gnapSequenceId = 0x7AF;
+ } else {
+ _gameSys->insertSequence(makeRid(datNum, 0x7B0), _gnapWalkNodes[index].id,
+ makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId,
+ 9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY);
+ _gnapWalkNodes[index].sequenceId = 0x7B0;
+ gnapSequenceId = 0x7B0;
+ }
+ } else {
+ if (_gnapWalkNodes[index].deltaY == -1)
+ _gnapWalkNodes[index].id -= 10;
+ else
+ _gnapWalkNodes[index].id += 10;
+ int newSequenceId = getGnapWalkSequenceId(_gnapWalkNodes[index].deltaX, _gnapWalkNodes[index].deltaY);
+ _gameSys->insertSequence(makeRid(datNum, newSequenceId), _gnapWalkNodes[index].id,
+ makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId,
+ 9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY);
+ _gnapWalkNodes[index].sequenceId = newSequenceId;
+ gnapSequenceId = newSequenceId;
+ }
+ gnapId = _gnapWalkNodes[index].id;
+ gnapSequenceDatNum = datNum;
+ }
+
+ if (flags & 8) {
+ if (_gnapWalkNodesCount > 0) {
+ _gnapSequenceId = gnapSequenceId;
+ _gnapId = gnapId;
+ _gnapIdleFacing = getGnapWalkFacing(_gnapWalkNodes[_gnapWalkNodesCount - 1].deltaX, _gnapWalkNodes[_gnapWalkNodesCount - 1].deltaY);
+ _gnapSequenceDatNum = datNum;
+ if (animationIndex >= 0)
+ _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, animationIndex);
+ } else if (animationIndex >= 0) {
+ _gameSys->setAnimation(0x107D3, 1, animationIndex);
+ _gameSys->insertSequence(0x107D3, 1, 0, 0, 0, 0, 0, 0);
+ }
+ } else {
+ if (sequenceId >= 0 && sequenceId != -1) {
+ _gnapSequenceId = ridToEntryIndex(sequenceId);
+ _gnapSequenceDatNum = ridToDatIndex(sequenceId);
+ if (_gnapSequenceId == 0x7B9) {
+ _gnapIdleFacing = 1;
+ } else {
+ switch (_gnapSequenceId) {
+ case 0x7BA:
+ _gnapIdleFacing = 3;
+ break;
+ case 0x7BB:
+ _gnapIdleFacing = 7;
+ break;
+ case 0x7BC:
+ _gnapIdleFacing = 5;
+ break;
+ }
+ }
+ } else {
+ if (_gnapWalkNodesCount > 0) {
+ _gnapSequenceId = getGnapWalkStopSequenceId(_gnapWalkNodes[_gnapWalkNodesCount - 1].deltaX, _gnapWalkNodes[_gnapWalkNodesCount - 1].deltaY);
+ _gnapIdleFacing = getGnapWalkFacing(_gnapWalkNodes[_gnapWalkNodesCount - 1].deltaX, _gnapWalkNodes[_gnapWalkNodesCount - 1].deltaY);
+ } else if (gridX >= 0 || gridY >= 0) {
+ switch (_gnapIdleFacing) {
+ case 1:
+ _gnapSequenceId = 0x7B9;
+ break;
+ case 3:
+ _gnapSequenceId = 0x7BA;
+ break;
+ case 7:
+ _gnapSequenceId = 0x7BB;
+ break;
+ default:
+ _gnapSequenceId = 0x7BC;
+ break;
+ }
+ } else {
+ int v10 = _leftClickMouseX - (_gridMinX + 75 * _gnapX);
+ int v11 = _leftClickMouseY - (_gridMinY + 48 * _gnapY);
+ if (_leftClickMouseX == _gridMinX + 75 * _gnapX)
+ ++v10;
+ if (_leftClickMouseY == _gridMinY + 48 * _gnapY)
+ v11 = 1;
+ _gnapSequenceId = getGnapWalkStopSequenceId(v10 / abs(v10), v11 / abs(v11));
+ _gnapIdleFacing = getGnapWalkFacing(v10 / abs(v10), v11 / abs(v11));
+ }
+ _gnapSequenceDatNum = datNum;
+ }
+
+ if (animationIndex < 0) {
+ _gnapId = 20 * _gnapWalkDestY + 1;
+ } else {
+ _gnapId = _gnapWalkNodesCount + animationIndex + 20 * _gnapWalkDestY;
+ _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapWalkNodesCount + animationIndex + 20 * _gnapWalkDestY, animationIndex);
+ }
+
+ if (flags & 4) {
+ _gameSys->insertSequence(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId,
+ 9, 0, 0, 0);
+ } else {
+ _gameSys->insertSequence(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId,
+ 9, 0, 75 * _gnapWalkDestX - _gnapGridX, 48 * _gnapWalkDestY - _gnapGridY);
+ }
+
+ }
+
+ _gnapX = _gnapWalkDestX;
+ _gnapY = _gnapWalkDestY;
+
+ return done;
+}
+
+void GnapEngine::gnapWalkStep() {
+ bool done = false;
+ for (int i = 1; i < _gridMaxX && !done; ++i) {
+ done = true;
+ if (!isPointBlocked(_gnapX + i, _gnapY))
+ gnapWalkTo(_gnapX + i, _gnapY, -1, -1, 1);
+ else if (!isPointBlocked(_gnapX - i, _gnapY))
+ gnapWalkTo(_gnapX - i, _gnapY, -1, -1, 1);
+ else if (!isPointBlocked(_gnapX, _gnapY + 1))
+ gnapWalkTo(_gnapX, _gnapY + 1, -1, -1, 1);
+ else if (!isPointBlocked(_gnapX, _gnapY - 1))
+ gnapWalkTo(_gnapX, _gnapY - 1, -1, -1, 1);
+ else if (!isPointBlocked(_gnapX + 1, _gnapY + 1))
+ gnapWalkTo(_gnapX + 1, _gnapY + 1, -1, -1, 1);
+ else if (!isPointBlocked(_gnapX - 1, _gnapY + 1))
+ gnapWalkTo(_gnapX - 1, _gnapY + 1, -1, -1, 1);
+ else if (!isPointBlocked(_gnapX + 1, _gnapY - 1))
+ gnapWalkTo(_gnapX + 1, _gnapY - 1, -1, -1, 1);
+ else if (!isPointBlocked(_gnapX - 1, _gnapY - 1))
+ gnapWalkTo(_gnapX - 1, _gnapY - 1, -1, -1, 1);
+ else
+ done = false;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+int GnapEngine::getBeaverWalkSequenceId(int deltaX, int deltaY) {
+ static const int _beaverWalkSequenceIds[9] = {
+ 0x7C5, 0x000, 0x7C8,
+ 0x7C4, 0x000, 0x7C7,
+ 0x7C3, 0x000, 0x7C6
+ };
+ // CHECKME This is a little weird
+ return _beaverWalkSequenceIds[3 * deltaX + 3 + 1 + deltaY];
+}
+
+bool GnapEngine::gridSub423750(int gridX, int gridY) {
+ bool result = false;
+
+ _platWalkNodesCount = 0;
+ _platWalkDirXIncr = 0;
+ _platWalkDirYIncr = 0;
+ _platWalkDeltaX = ABS(_platWalkDestX - gridX);
+ _platWalkDeltaY = ABS(_platWalkDestY - gridY);
+
+ if (_platWalkDeltaX)
+ _platWalkDirX = (_platWalkDestX - gridX) / _platWalkDeltaX;
+ else
+ _platWalkDirX = 0;
+
+ if (_platWalkDeltaY)
+ _platWalkDirY = (_platWalkDestY - gridY) / _platWalkDeltaY;
+ else
+ _platWalkDirY = 0;
+
+ while (_platWalkDirXIncr < _platWalkDeltaX && _platWalkDirYIncr < _platWalkDeltaY) {
+ _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr;
+ _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr;
+ if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirXIncr;
+ ++_platWalkDirYIncr;
+ } else if (_platWalkDeltaY - _platWalkDirYIncr > _platWalkDeltaX - _platWalkDirXIncr) {
+ if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = 0;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirYIncr;
+ } else if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = 0;
+ ++_platWalkDirXIncr;
+ } else {
+ _platWalkDeltaX = _platWalkDirXIncr;
+ _platWalkDeltaY = _platWalkDirYIncr;
+ --_platWalkNodesCount;
+ }
+ } else {
+ if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = 0;
+ ++_platWalkDirXIncr;
+ } else if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = 0;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirYIncr;
+ } else {
+ _platWalkDeltaX = _platWalkDirXIncr;
+ _platWalkDeltaY = _platWalkDirYIncr;
+ --_platWalkNodesCount;
+ }
+ }
+ ++_platWalkNodesCount;
+ }
+
+ while (_platWalkDirXIncr < _platWalkDeltaX) {
+ _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr;
+ _platWalkNodes[_platWalkNodesCount].gridY1 = _platWalkDestY;
+ if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDestY)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = 0;
+ ++_platWalkDirXIncr;
+ ++_platWalkNodesCount;
+ } else {
+ _platWalkDeltaX = _platWalkDirXIncr;
+ }
+ }
+
+ while (_platWalkDirYIncr < _platWalkDeltaY) {
+ _platWalkNodes[_platWalkNodesCount].gridX1 = _platWalkDestX;
+ _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr;
+ if (!isPointBlocked(_platWalkDestX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = 0;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirYIncr;
+ ++_platWalkNodesCount;
+ } else {
+ _platWalkDeltaY = _platWalkDirYIncr;
+ }
+ }
+
+ if (gridX + _platWalkDirX * _platWalkDirXIncr != _platWalkDestX || gridY + _platWalkDirY * _platWalkDirYIncr != _platWalkDestY) {
+ _platWalkDestX = gridX + _platWalkDirX * _platWalkDirXIncr;
+ _platWalkDestY = gridY + _platWalkDirY * _platWalkDirYIncr;
+ result = false;
+ } else {
+ result = true;
+ }
+
+ return result;
+}
+
+bool GnapEngine::gridSub423CC1(int gridX, int gridY, int index) {
+ _platWalkNodesCount = index;
+ _platWalkDirXIncr = 0;
+ _platWalkDirYIncr = 0;
+ _platWalkDeltaX = ABS(_platWalkDestX - gridX);
+ _platWalkDeltaY = ABS(_platWalkDestY - gridY);
+
+ if (_platWalkDeltaX)
+ _platWalkDirX = (_platWalkDestX - gridX) / _platWalkDeltaX;
+ else
+ _platWalkDirX = 0;
+
+ if (_platWalkDeltaY)
+ _platWalkDirY = (_platWalkDestY - gridY) / _platWalkDeltaY;
+ else
+ _platWalkDirY = 0;
+
+ while (_platWalkDirXIncr < _platWalkDeltaX && _platWalkDirYIncr < _platWalkDeltaY) {
+ _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr;
+ _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr;
+ if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirXIncr;
+ ++_platWalkDirYIncr;
+ } else if (_platWalkDeltaY - _platWalkDirYIncr > _platWalkDeltaX - _platWalkDirXIncr) {
+ if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = 0;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirYIncr;
+ } else if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = 0;
+ ++_platWalkDirXIncr;
+ } else
+ return false;
+ } else {
+ if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = 0;
+ ++_platWalkDirXIncr;
+ } else if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = 0;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirYIncr;
+ } else
+ return false;
+ }
+ ++_platWalkNodesCount;
+ }
+
+ while (_platWalkDirXIncr < _platWalkDeltaX) {
+ _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr;
+ _platWalkNodes[_platWalkNodesCount].gridY1 = _platWalkDestY;
+ if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDestY)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = 0;
+ ++_platWalkDirXIncr;
+ ++_platWalkNodesCount;
+ } else
+ return false;
+ }
+
+ while (_platWalkDirYIncr < _platWalkDeltaY) {
+ _platWalkNodes[_platWalkNodesCount].gridX1 = _platWalkDestX;
+ _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr;
+ if (!isPointBlocked(_platWalkDestX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = 0;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirYIncr;
+ ++_platWalkNodesCount;
+ } else
+ return false;
+ }
+
+ return true;
+}
+
+bool GnapEngine::gridSub42419A(int gridX, int gridY, int index) {
+ _platWalkNodesCount = index;
+ _platWalkDirXIncr = 0;
+ _platWalkDirYIncr = 0;
+ _platWalkDeltaX = ABS(_platWalkDestX - gridX);
+ _platWalkDeltaY = ABS(_platWalkDestY - gridY);
+
+ if (_platWalkDeltaX)
+ _platWalkDirX = (_platWalkDestX - gridX) / _platWalkDeltaX;
+ else
+ _platWalkDirX = 0;
+
+ if (_platWalkDeltaY)
+ _platWalkDirY = (_platWalkDestY - gridY) / _platWalkDeltaY;
+ else
+ _platWalkDirY = 0;
+
+ while (_platWalkDeltaY < _platWalkDeltaX - _platWalkDirXIncr) {
+ _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr;
+ _platWalkNodes[_platWalkNodesCount].gridY1 = gridY;
+ if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, gridY)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = 0;
+ ++_platWalkDirXIncr;
+ ++_platWalkNodesCount;
+ } else
+ return false;
+ }
+
+ while (_platWalkDeltaX < _platWalkDeltaY - _platWalkDirYIncr) {
+ _platWalkNodes[_platWalkNodesCount].gridX1 = gridX;
+ _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr;
+ if (!isPointBlocked(gridX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = 0;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirYIncr;
+ ++_platWalkNodesCount;
+ } else
+ return false;
+ }
+
+ while (_platWalkDirXIncr < _platWalkDeltaX && _platWalkDirYIncr < _platWalkDeltaY) {
+ _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr;
+ _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr;
+ if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirXIncr;
+ ++_platWalkDirYIncr;
+ } else if (_platWalkDeltaY - _platWalkDirYIncr > _platWalkDeltaX - _platWalkDirXIncr) {
+ if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = 0;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirYIncr;
+ } else if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = 0;
+ ++_platWalkDirXIncr;
+ } else
+ return false;
+ } else {
+ if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = 0;
+ ++_platWalkDirXIncr;
+ } else if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = 0;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirYIncr;
+ } else
+ return false;
+ }
+ ++_platWalkNodesCount;
+ }
+
+ while (_platWalkDirXIncr < _platWalkDeltaX) {
+ _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr;
+ _platWalkNodes[_platWalkNodesCount].gridY1 = _platWalkDestY;
+ if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDestY)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX;
+ _platWalkNodes[_platWalkNodesCount].deltaY = 0;
+ ++_platWalkDirXIncr;
+ ++_platWalkNodesCount;
+ } else
+ return false;
+ }
+
+ while (_platWalkDirYIncr < _platWalkDeltaY) {
+ _platWalkNodes[_platWalkNodesCount].gridX1 = _platWalkDestX;
+ _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr;
+ if (!isPointBlocked(_platWalkDestX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) {
+ _platWalkNodes[_platWalkNodesCount].deltaX = 0;
+ _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY;
+ ++_platWalkDirYIncr;
+ ++_platWalkNodesCount;
+ } else
+ return false;
+ }
+
+ return true;
+}
+
+bool GnapEngine::platFindPath3(int gridX, int gridY) {
+ int gridIncr = 1;
+ bool done = false;
+
+ while (!done && gridIncr < _gridMaxX) {
+ if (!isPointBlocked(_platX + gridIncr, _platY) && gridSub423CC1(_platX + gridIncr, _platY, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX + i;
+ _platWalkNodes[i].gridY1 = _platY;
+ _platWalkNodes[i].deltaX = 1;
+ _platWalkNodes[i].deltaY = 0;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX - gridIncr, _platY) && gridSub423CC1(_platX - gridIncr, _platY, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX - i;
+ _platWalkNodes[i].gridY1 = _platY;
+ _platWalkNodes[i].deltaX = -1;
+ _platWalkNodes[i].deltaY = 0;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX, _platY + gridIncr) && gridSub423CC1(_platX, _platY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX;
+ _platWalkNodes[i].gridY1 = _platY + i;
+ _platWalkNodes[i].deltaX = 0;
+ _platWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX, _platY - gridIncr) && gridSub423CC1(_platX, _platY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX;
+ _platWalkNodes[i].gridY1 = _platY - i;
+ _platWalkNodes[i].deltaX = 0;
+ _platWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX + gridIncr, _platY + gridIncr) && gridSub423CC1(_platX + gridIncr, _platY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX + i;
+ _platWalkNodes[i].gridY1 = _platY + i;
+ _platWalkNodes[i].deltaX = 1;
+ _platWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX - gridIncr, _platY + gridIncr) && gridSub423CC1(_platX - gridIncr, _platY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX - i;
+ _platWalkNodes[i].gridY1 = _platY + i;
+ _platWalkNodes[i].deltaX = -1;
+ _platWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX + gridIncr, _platY - gridIncr) && gridSub423CC1(_platX + gridIncr, _platY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX + i;
+ _platWalkNodes[i].gridY1 = _platY - i;
+ _platWalkNodes[i].deltaX = 1;
+ _platWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX - gridIncr, _platY - gridIncr) && gridSub423CC1(_platX - gridIncr, _platY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX - i;
+ _platWalkNodes[i].gridY1 = _platY - i;
+ _platWalkNodes[i].deltaX = -1;
+ _platWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX + gridIncr, _platY) && gridSub42419A(_platX + gridIncr, _platY, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX + i;
+ _platWalkNodes[i].gridY1 = _platY;
+ _platWalkNodes[i].deltaX = 1;
+ _platWalkNodes[i].deltaY = 0;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX - gridIncr, _platY) && gridSub42419A(_platX - gridIncr, _platY, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX - i;
+ _platWalkNodes[i].gridY1 = _platY;
+ _platWalkNodes[i].deltaX = -1;
+ _platWalkNodes[i].deltaY = 0;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX, _platY + gridIncr) && gridSub42419A(_platX, _platY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX;
+ _platWalkNodes[i].gridY1 = _platY + i;
+ _platWalkNodes[i].deltaX = 0;
+ _platWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX, _platY - gridIncr) && gridSub42419A(_platX, _platY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX;
+ _platWalkNodes[i].gridY1 = _platY - i;
+ _platWalkNodes[i].deltaX = 0;
+ _platWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX + gridIncr, _platY + gridIncr) && gridSub42419A(_platX + gridIncr, _platY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX + i;
+ _platWalkNodes[i].gridY1 = _platY + i;
+ _platWalkNodes[i].deltaX = 1;
+ _platWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX - gridIncr, _platY + gridIncr) && gridSub42419A(_platX - gridIncr, _platY + gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX - i;
+ _platWalkNodes[i].gridY1 = _platY + i;
+ _platWalkNodes[i].deltaX = -1;
+ _platWalkNodes[i].deltaY = 1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX + gridIncr, _platY - gridIncr) && gridSub42419A(_platX + gridIncr, _platY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX + i;
+ _platWalkNodes[i].gridY1 = _platY - i;
+ _platWalkNodes[i].deltaX = 1;
+ _platWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ if (!isPointBlocked(_platX - gridIncr, _platY - gridIncr) && gridSub42419A(_platX - gridIncr, _platY - gridIncr, gridIncr)) {
+ for (int i = 0; i < gridIncr; ++i) {
+ _platWalkNodes[i].gridX1 = _platX - i;
+ _platWalkNodes[i].gridY1 = _platY - i;
+ _platWalkNodes[i].deltaX = -1;
+ _platWalkNodes[i].deltaY = -1;
+ }
+ done = true;
+ break;
+ }
+ ++gridIncr;
+ }
+
+ return done;
+}
+
+bool GnapEngine::platypusWalkTo(int gridX, int gridY, int animationIndex, int sequenceId, int flags) {
+
+ int datNum = flags & 3;
+ bool done = false;
+
+ _timers[1] = 60;
+
+ if (gridX < 0)
+ gridX = (_leftClickMouseX - _gridMinX + 37) / 75;
+
+ if (gridY < 0)
+ gridY = (_leftClickMouseY - _gridMinY + 24) / 48;
+
+ _platWalkDestX = CLIP(gridX, 0, _gridMaxX - 1);
+ _platWalkDestY = CLIP(gridY, 0, _gridMaxY - 1);
+
+ if (animationIndex >= 0 && _platWalkDestX == _gnapX && _platWalkDestY == _gnapY)
+ gnapWalkStep();
+
+ if (gridSub423CC1(_platX, _platY, 0))
+ done = true;
+
+ if (!done && gridSub42419A(_platX, _platY, 0))
+ done = true;
+
+ if (!done && platFindPath3(_platX, _platY))
+ done = true;
+
+ if (!done)
+ gridSub423750(_platX, _platY);
+
+ int platSequenceId = _beaverSequenceId;
+ int platId = _beaverId;
+ int platSequenceDatNum = _beaverSequenceDatNum;
+
+ for (int index = 0; index < _platWalkNodesCount; ++index) {
+ _platWalkNodes[index].id = index + 20 * _platWalkNodes[index].gridY1;
+ if (_platWalkNodes[index].deltaX == 1 && _platWalkNodes[index].deltaY == 0) {
+ if (index % 2) {
+ _gameSys->insertSequence(makeRid(datNum, 0x7CD), _platWalkNodes[index].id,
+ makeRid(platSequenceDatNum, platSequenceId), platId,
+ 9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY);
+ _platWalkNodes[index].sequenceId = 0x7CD;
+ platSequenceId = 0x7CD;
+ } else {
+ _gameSys->insertSequence(makeRid(datNum, 0x7CE), _platWalkNodes[index].id,
+ makeRid(platSequenceDatNum, platSequenceId), platId,
+ 9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY);
+ _platWalkNodes[index].sequenceId = 0x7CE;
+ platSequenceId = 0x7CE;
+ }
+ } else if (_platWalkNodes[index].deltaX == -1 && _platWalkNodes[index].deltaY == 0) {
+ if (index % 2) {
+ _gameSys->insertSequence(makeRid(datNum, 0x7CF), _platWalkNodes[index].id,
+ makeRid(platSequenceDatNum, platSequenceId), platId,
+ 9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY);
+ _platWalkNodes[index].sequenceId = 0x7CF;
+ platSequenceId = 0x7CF;
+ } else {
+ _gameSys->insertSequence(makeRid(datNum, 0x7D0), _platWalkNodes[index].id,
+ makeRid(platSequenceDatNum, platSequenceId), platId,
+ 9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY);
+ _platWalkNodes[index].sequenceId = 0x7D0;
+ platSequenceId = 0x7D0;
+ }
+ } else {
+ if (_platWalkNodes[index].deltaY == -1)
+ _platWalkNodes[index].id -= 10;
+ else
+ _platWalkNodes[index].id += 10;
+ int newSequenceId = getBeaverWalkSequenceId(_platWalkNodes[index].deltaX, _platWalkNodes[index].deltaY);
+ _gameSys->insertSequence(makeRid(datNum, newSequenceId), _platWalkNodes[index].id,
+ makeRid(platSequenceDatNum, platSequenceId), platId,
+ 9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY);
+ _platWalkNodes[index].sequenceId = newSequenceId;
+ platSequenceId = newSequenceId;
+ }
+ platId = _platWalkNodes[index].id;
+ platSequenceDatNum = datNum;
+ }
+
+ if (flags & 8) {
+ if (_platWalkNodesCount > 0) {
+ _beaverSequenceId = platSequenceId;
+ _beaverId = platId;
+ _beaverSequenceDatNum = datNum;
+ // CHECKME Not sure if this is correct...
+ if (_platWalkNodes[_platWalkNodesCount - 1].deltaX > 0)
+ _beaverFacing = 0;
+ else if (_platWalkNodes[_platWalkNodesCount - 1].deltaX < 0)
+ _beaverFacing = 4;
+ else if (_platWalkNodes[_platWalkNodesCount - 1].gridX1 % 2)
+ _beaverFacing = 4;
+ else
+ _beaverFacing = 0;
+ if (animationIndex >= 0)
+ _gameSys->setAnimation(makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, animationIndex);
+ } else if (animationIndex >= 0) {
+ _gameSys->setAnimation(0x107D3, 1, animationIndex);
+ _gameSys->insertSequence(0x107D3, 1, 0, 0, 0, 0, 0, 0);
+ }
+ } else {
+ if (sequenceId >= 0 && sequenceId != -1) {
+ _beaverSequenceId = ridToEntryIndex(sequenceId);
+ _beaverSequenceDatNum = ridToDatIndex(sequenceId);
+ if (_beaverSequenceId == 0x7C2) {
+ _beaverFacing = 0;
+ } else if (_beaverSequenceId == 0x7D2) {
+ _beaverFacing = 4;
+ }
+ } else {
+ if (_platWalkNodesCount > 0) {
+ if (_platWalkNodes[_platWalkNodesCount - 1].deltaX > 0) {
+ _beaverSequenceId = 0x7C2;
+ _beaverFacing = 0;
+ } else if (_platWalkNodes[_platWalkNodesCount - 1].deltaX < 0) {
+ _beaverSequenceId = 0x7D2;
+ _beaverFacing = 4;
+ } else if (_platWalkNodes[0].deltaX > 0) {
+ _beaverSequenceId = 0x7C2;
+ _beaverFacing = 0;
+ } else if (_platWalkNodes[0].deltaX < 0) {
+ _beaverSequenceId = 0x7D2;
+ _beaverFacing = 4;
+ } else {
+ _beaverSequenceId = 0x7D2;
+ _beaverFacing = 4;
+ }
+ } else if (_beaverFacing > 0) {
+ _beaverSequenceId = 0x7D2;
+ } else {
+ _beaverSequenceId = 0x7C2;
+ }
+ _beaverSequenceDatNum = datNum;
+ }
+
+ if (animationIndex < 0) {
+ _beaverId = 20 * _platWalkDestY;
+ } else {
+ _beaverId = animationIndex + 20 * _platWalkDestY;
+ _gameSys->setAnimation(makeRid(_beaverSequenceDatNum, _beaverSequenceId), animationIndex + 20 * _platWalkDestY, animationIndex);
+ }
+
+ if (flags & 4)
+ _gameSys->insertSequence(makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId,
+ makeRid(platSequenceDatNum, platSequenceId), platId,
+ 9, 0, 0, 0);
+ else
+ _gameSys->insertSequence(makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId,
+ makeRid(platSequenceDatNum, platSequenceId), platId,
+ 9, 0, 75 * _platWalkDestX - _platGridX, 48 * _platWalkDestY - _platGridY);
+ }
+
+ _platX = _platWalkDestX;
+ _platY = _platWalkDestY;
+
+ return done;
+}
+
+void GnapEngine::platypusWalkStep() {
+ bool done = false;
+ for (int i = 1; !done && i < _gridMaxX; ++i) {
+ done = true;
+ if (!isPointBlocked(_platX + i, _platY))
+ platypusWalkTo(_platX + i, _platY, -1, -1, 1);
+ else if (!isPointBlocked(_platX - i, _platY))
+ platypusWalkTo(_platX - i, _platY, -1, -1, 1);
+ else if (!isPointBlocked(_platX, _platY + 1))
+ platypusWalkTo(_platX, _platY + 1, -1, -1, 1);
+ else if (!isPointBlocked(_platX, _platY - 1))
+ platypusWalkTo(_platX, _platY - 1, -1, -1, 1);
+ else if (!isPointBlocked(_platX + 1, _platY + 1))
+ platypusWalkTo(_platX + 1, _platY + 1, -1, -1, 1);
+ else if (!isPointBlocked(_platX - 1, _platY + 1))
+ platypusWalkTo(_platX - 1, _platY + 1, -1, -1, 1);
+ else if (!isPointBlocked(_platX + 1, _platY - 1))
+ platypusWalkTo(_platX + 1, _platY - 1, -1, -1, 1);
+ else if (!isPointBlocked(_platX - 1, _platY - 1))
+ platypusWalkTo(_platX - 1, _platY - 1, -1, -1, 1);
+ else
+ done = false;
+ }
+}
+
+void GnapEngine::beaverMakeRoom() {
+ int rndGridX, rndGridY;
+ do {
+ rndGridY = getRandom(_gridMaxY);
+ rndGridX = getRandom(_gridMaxX);
+ } while (ABS(rndGridX - _platX) > 4 || ABS(rndGridY - _platY) > 3 ||
+ isPointBlocked(rndGridX, rndGridY));
+ platypusWalkTo(rndGridX, rndGridY, -1, -1, 1);
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/menu.cpp b/engines/gnap/menu.cpp
new file mode 100644
index 0000000000..e6fc073c53
--- /dev/null
+++ b/engines/gnap/menu.cpp
@@ -0,0 +1,811 @@
+/* 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"
+
+namespace Gnap {
+
+void GnapEngine::createMenuSprite() {
+ _menuBackgroundSurface = _gameSys->createSurface(0x10002);
+}
+
+void GnapEngine::freeMenuSprite() {
+ _gameSys->removeSpriteDrawItem(_menuBackgroundSurface, 260);
+ delayTicksCursor(5);
+ deleteSurface(&_menuBackgroundSurface);
+}
+
+void GnapEngine::initMenuHotspots1() {
+
+ int v0, v2 = 0;
+
+ for (int i = 0; i < 3; ++i) {
+ int v1 = 0;
+ while (v1 < 3) {
+ _hotspots[v2].x1 = 87 * v1 + 262;
+ _hotspots[v2].y1 = 74 * i + 69;
+ _hotspots[v2].x2 = _hotspots[v2].x1 + 79;
+ _hotspots[v2].y2 = _hotspots[v2].y1 + 66;
+ _hotspots[v2].flags = 0;
+ _hotspots[v2].id = v2;
+ ++v1;
+ ++v2;
+ }
+ }
+
+ _hotspots[v2].x1 = 330;
+ _hotspots[v2].y1 = 350;
+ _hotspots[v2].x2 = 430;
+ _hotspots[v2].y2 = 460;
+ _hotspots[v2].flags = 2;
+ _hotspots[v2].id = v2;
+
+ v0 = v2 + 1;
+ _hotspots[v0].x1 = 180;
+ _hotspots[v0].y1 = 15;
+ _hotspots[v0].x2 = 620;
+ _hotspots[v0].y2 = 580;
+ _hotspots[v0].flags = 0;
+ _hotspots[v0].id = v0;
+
+ ++v0;
+ _hotspots[v0].x1 = 0;
+ _hotspots[v0].y1 = 0;
+ _hotspots[v0].x2 = 799;
+ _hotspots[v0].y2 = 599;
+ _hotspots[v0].flags = 0;
+ _hotspots[v0].id = v0;
+
+ _hotspotsCount = v0 + 1;
+}
+
+void GnapEngine::initMenuHotspots2() {
+ int i, v0;
+
+ for (i = 0; i < 4; ++i) {
+ _hotspots[i].x1 = 312;
+ _hotspots[i].y1 = 48 * i + 85;
+ _hotspots[i].x2 = _hotspots[i].x1 + 153;
+ _hotspots[i].y2 = _hotspots[i].y1 + 37;
+ _hotspots[i].flags = SF_GRAB_CURSOR;
+ _hotspots[i].id = i;
+ }
+ _hotspots[i].x1 = 500;
+ _hotspots[i].y1 = 72;
+ _hotspots[i].x2 = 527;
+ _hotspots[i].y2 = 99;
+ _hotspots[i].flags = SF_DISABLED;
+ _hotspots[i].id = i;
+ v0 = i + 1;
+ _hotspots[v0].x1 = 330;
+ _hotspots[v0].y1 = 350;
+ _hotspots[v0].x2 = 430;
+ _hotspots[v0].y2 = 460;
+ _hotspots[v0].flags = SF_GRAB_CURSOR;
+ _hotspots[v0].id = v0;
+ ++v0;
+ _hotspots[v0].x1 = 180;
+ _hotspots[v0].y1 = 15;
+ _hotspots[v0].x2 = 620;
+ _hotspots[v0].y2 = 580;
+ _hotspots[v0].flags = 0;
+ _hotspots[v0].id = v0;
+ ++v0;
+ _hotspots[v0].x1 = 0;
+ _hotspots[v0].y1 = 0;
+ _hotspots[v0].x2 = 799;
+ _hotspots[v0].y2 = 599;
+ _hotspots[v0].flags = 0;
+ _hotspots[v0].id = v0;
+ _hotspotsCount = v0 + 1;
+}
+
+void GnapEngine::initMenuQuitQueryHotspots() {
+ _hotspots[0].x1 = 311;
+ _hotspots[0].y1 = 197;
+ _hotspots[0].x2 = 377;
+ _hotspots[0].y2 = 237;
+ _hotspots[0].flags = SF_GRAB_CURSOR;
+ _hotspots[0].id = 0;
+ _hotspots[1].x1 = 403;
+ _hotspots[1].y1 = 197;
+ _hotspots[1].x2 = 469;
+ _hotspots[1].y2 = 237;
+ _hotspots[1].flags = SF_GRAB_CURSOR;
+ _hotspots[1].id = 1;
+ _hotspots[2].x1 = 330;
+ _hotspots[2].y1 = 350;
+ _hotspots[2].x2 = 430;
+ _hotspots[2].y2 = 460;
+ _hotspots[2].flags = SF_GRAB_CURSOR;
+ _hotspots[2].id = 2;
+ _hotspots[3].x1 = 180;
+ _hotspots[3].y1 = 15;
+ _hotspots[3].x2 = 620;
+ _hotspots[3].y2 = 580;
+ _hotspots[3].flags = 0;
+ _hotspots[3].id = 3;
+ _hotspots[4].x1 = 0;
+ _hotspots[4].y1 = 0;
+ _hotspots[4].x2 = 799;
+ _hotspots[4].y2 = 599;
+ _hotspots[4].flags = 0;
+ _hotspots[4].id = 4;
+ _hotspotsCount = 5;
+}
+
+void GnapEngine::initSaveLoadHotspots() {
+ int i, v0;
+ for (i = 0; i < 7; ++i ) {
+ _hotspots[i].x1 = 288;
+ _hotspots[i].y1 = 31 * i + 74;
+ _hotspots[i].x2 = _hotspots[i].x1 + 91;
+ _hotspots[i].y2 = _hotspots[i].y1 + 22;
+ _hotspots[i].flags = SF_GRAB_CURSOR;
+ _hotspots[i].id = i;
+ }
+ if (_menuStatus == 2) {
+ _hotspots[i].x1 = 416;
+ _hotspots[i].y1 = 160;
+ _hotspots[i].x2 = 499;
+ _hotspots[i].y2 = 188;
+ _hotspots[i].flags = SF_GRAB_CURSOR;
+ _hotspots[i].id = i;
+ ++i;
+ }
+ _hotspots[i].x1 = 416;
+ _hotspots[i].y1 = 213;
+ _hotspots[i].x2 = 499;
+ _hotspots[i].y2 = 241;
+ _hotspots[i].flags = SF_GRAB_CURSOR;
+ _hotspots[i].id = i;
+ v0 = i + 1;
+ _hotspots[v0].x1 = 330;
+ _hotspots[v0].y1 = 350;
+ _hotspots[v0].x2 = 430;
+ _hotspots[v0].y2 = 460;
+ _hotspots[v0].flags = SF_GRAB_CURSOR;
+ _hotspots[v0].id = v0;
+ ++v0;
+ _hotspots[v0].x1 = 180;
+ _hotspots[v0].y1 = 15;
+ _hotspots[v0].x2 = 620;
+ _hotspots[v0].y2 = 580;
+ _hotspots[v0].flags = 0;
+ _hotspots[v0].id = v0;
+ ++v0;
+ _hotspots[v0].x1 = 0;
+ _hotspots[v0].y1 = 0;
+ _hotspots[v0].x2 = 799;
+ _hotspots[v0].y2 = 599;
+ _hotspots[v0].flags = 0;
+ _hotspots[v0].id = v0;
+ _hotspotsCount = v0 + 1;
+}
+
+void GnapEngine::drawInventoryFrames() {
+ for (int i = 0; i < 9; ++i)
+ _gameSys->drawSpriteToSurface(_menuBackgroundSurface, _hotspots[i].x1 - 93, _hotspots[i].y1, 0x10001);
+}
+
+void GnapEngine::insertInventorySprites() {
+
+ for (int i = 0; i < 9; ++i) {
+ _menuInventoryIndices[i] = -1;
+ _gameSys->removeSpriteDrawItem(_menuInventorySprites[_sceneClickedHotspot], 261);
+ _menuInventorySprites[i] = 0;
+ }
+
+ _menuSpritesIndex = 0;
+
+ for (int index = 0; index < 30 && _menuSpritesIndex < 9; ++index) {
+ if (invHas(index)) {
+ _gameSys->drawSpriteToSurface(_menuBackgroundSurface,
+ _hotspots[_menuSpritesIndex].x1 - 93, _hotspots[_menuSpritesIndex].y1, 0x10000);
+ _menuInventorySprites[_menuSpritesIndex] = _gameSys->createSurface(getInventoryItemSpriteNum(index) | 0x10000);
+ if (index != _grabCursorSpriteIndex) {
+ _menuInventoryIndices[_menuSpritesIndex] = index;
+ _gameSys->insertSpriteDrawItem(_menuInventorySprites[_menuSpritesIndex],
+ _hotspots[_menuSpritesIndex].x1 + ((79 - _menuInventorySprites[_menuSpritesIndex]->w) / 2),
+ _hotspots[_menuSpritesIndex].y1 + ((66 - _menuInventorySprites[_menuSpritesIndex]->h) / 2),
+ 261);
+ }
+ _hotspots[_menuSpritesIndex].flags = SF_GRAB_CURSOR;
+ ++_menuSpritesIndex;
+ }
+ }
+
+}
+
+void GnapEngine::removeInventorySprites() {
+ for (int i = 0; i < _menuSpritesIndex; ++i)
+ if (_menuInventorySprites[i])
+ _gameSys->removeSpriteDrawItem(_menuInventorySprites[i], 261);
+ delayTicksCursor(5);
+ for (int j = 0; j < _menuSpritesIndex; ++j) {
+ if (_menuInventorySprites[j]) {
+ deleteSurface(&_menuInventorySprites[j]);
+ _menuInventorySprites[j] = 0;
+ _menuInventoryIndices[j] = -1;
+ }
+ }
+ _menuSpritesIndex = 0;
+}
+
+void GnapEngine::runMenu() {
+
+ int v43;
+
+ _spriteHandle = 0;
+ _cursorSprite = 0;
+ _menuSprite1 = 0;
+ _menuSprite2 = 0;
+ _menuSaveLoadSprite = 0;
+ _menuQuitQuerySprite = 0;
+
+ _menuStatus = 0;
+ _menuDone = false;
+
+ createMenuSprite();//??? CHECKME Crashes when done in loadStockDat() find out why
+
+ insertDeviceIconActive();
+
+ for (int i = 0; i < 7; ++i) {
+ _savegameFilenames[i][0] = 0;
+ _savegameSprites[i] = 0;
+ }
+
+ v43 = 0;
+
+ if (_menuStatus == 0) {
+ invAdd(kItemMagazine);
+ setGrabCursorSprite(-1);
+ hideCursor();
+ initMenuHotspots1();
+ drawInventoryFrames();
+ insertInventorySprites();
+ _gameSys->insertSpriteDrawItem(_menuBackgroundSurface, 93, 0, 260);
+ showCursor();
+ // SetCursorPos(400, 300);
+ setVerbCursor(GRAB_CURSOR);
+ // pollMessages();
+ }
+
+ _timers[2] = 10;
+
+ while (!isKeyStatus1(8) && !isKeyStatus1(28) && !_sceneDone && !_menuDone) {
+
+ updateCursorByHotspot();
+
+ switch (_menuStatus) {
+ case 0:
+ updateMenuStatusInventory();
+ break;
+ case 1:
+ updateMenuStatusMainMenu();
+ break;
+ case 2:
+ updateMenuStatusSaveGame();
+ break;
+ case 3:
+ updateMenuStatusLoadGame();
+ break;
+ case 4:
+ updateMenuStatusQueryQuit();
+ break;
+ }
+
+ gameUpdateTick();
+
+ }
+
+ removeInventorySprites();
+ if (_spriteHandle)
+ _gameSys->removeSpriteDrawItem(_spriteHandle, 261);
+ if (_menuSprite1)
+ _gameSys->removeSpriteDrawItem(_menuSprite1, 262);
+ if (_menuSprite2)
+ _gameSys->removeSpriteDrawItem(_menuSprite2, 262);
+ for (int i = 0; i < 7; ++i)
+ if (_savegameSprites[i])
+ _gameSys->removeSpriteDrawItem(_savegameSprites[i], 263);
+ if (_cursorSprite)
+ _gameSys->removeSpriteDrawItem(_cursorSprite, 264);
+ if (_menuSaveLoadSprite)
+ _gameSys->removeSpriteDrawItem(_menuSaveLoadSprite, 262);
+ if (_menuQuitQuerySprite)
+ _gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262);
+ if (_menuBackgroundSurface)
+ _gameSys->removeSpriteDrawItem(_menuBackgroundSurface, 260);
+
+ delayTicksCursor(5);
+
+ deleteSurface(&_spriteHandle);
+ deleteSurface(&_menuSprite1);
+ deleteSurface(&_menuSprite2);
+ for (int i = 0; i < 7; ++i)
+ deleteSurface(&_savegameSprites[i]);
+ deleteSurface(&_cursorSprite);
+ deleteSurface(&_menuSaveLoadSprite);
+ deleteSurface(&_menuQuitQuerySprite);
+
+ _sceneClickedHotspot = -1;
+
+ _timers[2] = getRandom(20) + 30;
+ _timers[3] = getRandom(200) + 50;
+ _timers[0] = getRandom(75) + 75;
+ _timers[1] = getRandom(20) + 30;
+
+ clearAllKeyStatus1();
+
+ _mouseClickState.left = false;
+
+ removeDeviceIconActive();
+
+ freeMenuSprite();//??? CHECKME
+}
+
+void GnapEngine::updateMenuStatusInventory() {
+
+ static const struct {
+ int item1, item2, resultItem;
+ } kCombineItems[] = {
+ {kItemGrass, kItemMud, kItemDisguise},
+ {kItemDice, kItemQuarterWithHole, kItemDiceQuarterHole},
+ {kItemPill, kItemBucketWithBeer, kItemBucketWithPill}
+ };
+
+ updateGrabCursorSprite(0, 0);
+ _hotspots[0].x1 = 262;
+ _hotspots[0].y1 = 69;
+ _hotspots[0].x2 = 341;
+ _hotspots[0].y2 = 135;
+ _sceneClickedHotspot = -1;
+ if (_timers[2] == 0)
+ _sceneClickedHotspot = getClickedHotspotId();
+ if (_sceneClickedHotspot == -1 || _sceneClickedHotspot >= _menuSpritesIndex) {
+ if (_sceneClickedHotspot == _hotspotsCount - 3) {
+ if (_grabCursorSpriteIndex == -1) {
+ _timers[2] = 10;
+ playSound(0x108F4, 0);
+ _menuStatus = 1;
+ Common::Rect dirtyRect(_hotspots[0].x1, _hotspots[0].y1, _hotspots[2].x2, _hotspots[_hotspotsCount - 4].y2);
+ drawInventoryFrames();
+ initMenuHotspots2();
+ removeInventorySprites();
+ if (!_menuSprite1)
+ _menuSprite1 = _gameSys->createSurface(0x104F8);
+ _gameSys->insertSpriteDrawItem(_menuSprite1, 288, 79, 262);
+ _gameSys->insertDirtyRect(dirtyRect);
+ } else {
+ playSound(0x108F5, 0);
+ }
+ } else if (_sceneClickedHotspot == _hotspotsCount - 1) {
+ _timers[2] = 10;
+ playSound(0x108F5, 0);
+ _menuDone = true;
+ }
+ } else if (_sceneClickedHotspot != -1 && _menuInventoryIndices[_sceneClickedHotspot] != -1 && _grabCursorSpriteIndex == -1) {
+ _gameSys->removeSpriteDrawItem(_menuInventorySprites[_sceneClickedHotspot], 261);
+ setGrabCursorSprite(_menuInventoryIndices[_sceneClickedHotspot]);
+ _menuInventoryIndices[_sceneClickedHotspot] = -1;
+ } else if (_sceneClickedHotspot != -1 && _menuInventoryIndices[_sceneClickedHotspot] == -1 && _grabCursorSpriteIndex != -1) {
+ _menuInventoryIndices[_sceneClickedHotspot] = _grabCursorSpriteIndex;
+ _gameSys->insertSpriteDrawItem(_menuInventorySprites[_sceneClickedHotspot],
+ _hotspots[_sceneClickedHotspot].x1 + ((79 - _menuInventorySprites[_sceneClickedHotspot]->w) / 2),
+ _hotspots[_sceneClickedHotspot].y1 + (66 - _menuInventorySprites[_sceneClickedHotspot]->h) / 2,
+ 261);
+ setGrabCursorSprite(-1);
+ } else if (_sceneClickedHotspot != -1 && _menuInventoryIndices[_sceneClickedHotspot] != -1 && _grabCursorSpriteIndex != -1) {
+ int combineIndex = -1;
+ for (int i = 0; i < ARRAYSIZE(kCombineItems); ++i) {
+ if ((_grabCursorSpriteIndex == kCombineItems[i].item1 && _menuInventoryIndices[_sceneClickedHotspot] == kCombineItems[i].item2) ||
+ (_grabCursorSpriteIndex == kCombineItems[i].item2 && _menuInventoryIndices[_sceneClickedHotspot] == kCombineItems[i].item1)) {
+ combineIndex = i;
+ break;
+ }
+ }
+ if (combineIndex >= 0) {
+ invRemove(kCombineItems[combineIndex].item1);
+ invRemove(kCombineItems[combineIndex].item2);
+ invAdd(kCombineItems[combineIndex].resultItem);
+ playSound(0x108AE, 0);
+ deleteSurface(&_spriteHandle); // CHECKME
+ _spriteHandle = _gameSys->createSurface(0x10001);
+ _gameSys->insertSpriteDrawItem(_spriteHandle, _hotspots[_menuSpritesIndex - 1].x1, _hotspots[_menuSpritesIndex - 1].y1, 261);
+ setGrabCursorSprite(kCombineItems[combineIndex].resultItem);
+ removeInventorySprites();
+ insertInventorySprites();
+ delayTicksCursor(5);
+ } else {
+ playSound(0x108F5, 0);
+ }
+ }
+}
+
+void GnapEngine::updateMenuStatusMainMenu() {
+ _hotspots[0].x1 = 312;
+ _hotspots[0].y1 = 85;
+ _hotspots[0].x2 = 465;
+ _hotspots[0].y2 = 122;
+ _sceneClickedHotspot = -1;
+ if (!_timers[2])
+ _sceneClickedHotspot = getClickedHotspotId();
+
+ if (_sceneClickedHotspot != 1 && _sceneClickedHotspot != 0) {
+ if (_sceneClickedHotspot != 2 && _hotspotsCount - 1 != _sceneClickedHotspot) {
+ if (_sceneClickedHotspot == 3) {
+ _timers[2] = 10;
+ playSound(0x108F4, 0);
+ _gameSys->removeSpriteDrawItem(_menuSprite1, 262);
+ initMenuQuitQueryHotspots();
+ _menuStatus = 4;
+ if (!_menuQuitQuerySprite)
+ _menuQuitQuerySprite = _gameSys->createSurface(0x104FC);
+ _gameSys->insertSpriteDrawItem(_menuQuitQuerySprite, 254, 93, 262);
+ } else if (_sceneClickedHotspot == 4) {
+ playSound(0x108F4, 0);
+ Common::Rect dirtyRect(0, 0, 799, 599);
+ hideCursor();
+ _largeSprite = _gameSys->allocSurface(800, 600);
+
+ for (int i = 0; i < 3; ++i) {
+
+ _timers[2] = 10;
+
+ if (i == 0) {
+ _gameSys->drawSpriteToSurface(_largeSprite, 0, 0, 0x1078D);
+ _gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300);
+ /* TODO
+ if (_midiFlag) {
+ playMidi("pause.mid", 0);
+ }
+ */
+ } else if (i == 1) {
+ _gameSys->drawSpriteToSurface(_largeSprite, 0, 0, 0x1078E);
+ _gameSys->insertDirtyRect(dirtyRect);
+ } else if (i == 2) {
+ _gameSys->drawSpriteToSurface(_largeSprite, 0, 0, 0x1078F);
+ _gameSys->insertDirtyRect(dirtyRect);
+ }
+
+ while (!_mouseClickState.left && !isKeyStatus1(28) && !isKeyStatus1(30) && !isKeyStatus1(29) && !_timers[2]) {
+ gameUpdateTick();
+ }
+
+ playSound(0x108F5, 0);
+ _mouseClickState.left = false;
+ clearKeyStatus1(28);
+ clearKeyStatus1(29);
+ clearKeyStatus1(30);
+ }
+
+ _gameSys->removeSpriteDrawItem(_largeSprite, 300);
+ delayTicksCursor(5);
+ deleteSurface(&_largeSprite);
+ showCursor();
+ } else if (_hotspotsCount - 3 == _sceneClickedHotspot) {
+ _timers[2] = 10;
+ playSound(0x108F4, 0);
+ initMenuHotspots1();
+ /* TODO
+ if (_mouseX < 93 || _mouseX > 638 || _mouseY < 0 || _mouseY > 600)
+ SetCursorPos(400, 300);
+ */
+ _menuStatus = 0;
+ if (_menuSprite1)
+ _gameSys->removeSpriteDrawItem(_menuSprite1, 262);
+ insertInventorySprites();
+ Common::Rect dirtyRect(_hotspots[0].x1, _hotspots[0].y1, _hotspots[2].x2, _hotspots[_hotspotsCount - 4].y2);
+ _gameSys->insertDirtyRect(dirtyRect);
+ }
+ } else {
+ playSound(0x108F5, 0);
+ _menuDone = true;
+ }
+ } else {
+ _timers[2] = 10;
+ playSound(0x108F4, 0);
+ _gameSys->removeSpriteDrawItem(_menuSprite1, 262);
+ if (_menuSaveLoadSprite)
+ deleteSurface(&_menuSaveLoadSprite);
+ if (_sceneClickedHotspot == 1) {
+ _menuStatus = 2;
+ initSaveLoadHotspots();
+ _menuSaveLoadSprite = _gameSys->createSurface(0x104FB);
+ } else {
+ _menuStatus = 3;
+ initSaveLoadHotspots();
+ _menuSaveLoadSprite = _gameSys->createSurface(0x104FA);
+ }
+ _gameSys->insertSpriteDrawItem(_menuSaveLoadSprite, 403, 72, 262);
+ if (!_menuSprite2)
+ _menuSprite2 = _gameSys->createSurface(0x104F9);
+ _gameSys->insertSpriteDrawItem(_menuSprite2, 277, 66, 262);
+ for (int i = 0; i < 7; ++i) {
+ Common::String savegameDescription;
+ if (!_savegameSprites[i])
+ _savegameSprites[i] = _gameSys->allocSurface(111, 40);
+ if (readSavegameDescription(i + 1, savegameDescription) == 0)
+ strncpy(_savegameFilenames[i], savegameDescription.c_str(), 40);
+ _gameSys->drawTextToSurface(_savegameSprites[i], 0, 0, 255, 0, 0, _savegameFilenames[i]);
+ _gameSys->insertSpriteDrawItem(_savegameSprites[i], 288, _hotspots[i].y1, 263);
+ }
+ _savegameIndex = -1;
+ }
+}
+
+void GnapEngine::updateMenuStatusSaveGame() {
+#if 0 // TODO
+ _hotspots[0].x1 = 288;
+ _hotspots[0].y1 = 74;
+ _hotspots[0].x2 = 379;
+ _hotspots[0].y2 = 96;
+ _sceneClickedHotspot = -1;
+ if (!_timers[2])
+ _sceneClickedHotspot = getClickedHotspotId();
+ if (_hotspotsCount - 3 == _sceneClickedHotspot)
+ {
+ _timers[2] = 10;
+ playSound(0x108F4, 0);
+ _menuStatus = 1;
+ writeSavegame(_savegameIndex + 1, (int)&_savegameFilenames[30 * _savegameIndex], 1);
+ }
+ else if (_hotspotsCount - 4 == _sceneClickedHotspot)
+ {
+ _timers[2] = 10;
+ playSound(0x108F5, 0);
+ _menuStatus = 1;
+ if (strcmp(&v43, &_savegameFilenames[30 * _savegameIndex]) && _savegameIndex != -1)
+ {
+ strcpy((char *)&_savegameFilenames[30 * _savegameIndex], &v43);
+ if (_savegameSprites[_savegameIndex] != -1)
+ {
+ _gameSys->removeSpriteDrawItem(_savegameSprites[_savegameIndex], 263);
+ delayTicksCursor(5);
+ memFreeHandle(_savegameSprites[_savegameIndex]);
+ }
+ v16 = getSpriteWidthById(0x104F9);
+ _savegameSprites[_savegameIndex] = allocSprite(v16, 40, 128, 0);
+ }
+ }
+ else if (_hotspotsCount - 5 == _sceneClickedHotspot)
+ {
+ _timers[2] = 10;
+ playSound(0x108F4, 0);
+ if ((signed int)_savegameIndex > -1)
+ writeSavegame(_savegameIndex + 1, (int)&_savegameFilenames[30 * _savegameIndex], 1);
+ _menuStatus = 1;
+ }
+ else if (_hotspotsCount - 1 == _sceneClickedHotspot)
+ {
+ _menuDone = true;
+ }
+ else if (_sceneClickedHotspot != -1 && _hotspotsCount - 2 != _sceneClickedHotspot)
+ {
+ _timers[2] = 10;
+ playSound(0x108F4, 0);
+ v17 = strcmp(&v43, &_savegameFilenames[30 * _savegameIndex]);
+ if (!v17)
+ LOBYTE(v17) = 0;
+ if ((unsigned int8)v17 & (_savegameIndex < 0xFFFFFFFF))
+ {
+ strcpy((char *)&_savegameFilenames[30 * _savegameIndex], &v43);
+ if (_savegameSprites[_savegameIndex] != -1)
+ {
+ _gameSys->removeSpriteDrawItem(_savegameSprites[_savegameIndex], 263);
+ delayTicksCursor(5);
+ memFreeHandle(_savegameSprites[_savegameIndex]);
+ }
+ v18 = getSpriteWidthById(0x104F9);
+ _savegameSprites[_savegameIndex] = allocSprite(v18, 40, 128, 0);
+ drawTextToSurface(_savegameSprites[_savegameIndex], 0, 0, 255, 0, 0, &_savegameFilenames[30 * _savegameIndex]);
+ insertSpriteDrawItem(_savegameSprites[_savegameIndex], 288, _hotspots[_savegameIndex].y1, 263);
+ }
+ _savegameIndex = _sceneClickedHotspot;
+ v46 = strlen(&_savegameFilenames[30 * _sceneClickedHotspot]);
+ strcpy(&v43, &_savegameFilenames[30 * _sceneClickedHotspot]);
+ if (_cursorSprite == -1)
+ {
+ v19 = getTextHeight("_");
+ v20 = getTextWidth("_");
+ _cursorSprite = allocSprite(v20, v19, 128, 0);
+ drawTextToSurface(_cursorSprite, 0, 0, 255, 0, 0, "_");
+ }
+ else
+ {
+ _gameSys->removeSpriteDrawItem(_cursorSprite, 264);
+ }
+ v21 = _hotspots[_savegameIndex].x2;
+ v22 = v21 - getTextWidth("_");
+ if (v22 > getTextWidth(&_savegameFilenames[30 * _savegameIndex]) + 288)
+ {
+ v25 = getTextWidth(&_savegameFilenames[30 * _savegameIndex]) + 288;
+ insertSpriteDrawItem(_cursorSprite, v25, _hotspots[_savegameIndex].y1, 264);
+ }
+ else
+ {
+ v23 = _hotspots[_savegameIndex].x2;
+ v24 = v23 - getTextWidth("_");
+ insertSpriteDrawItem(_cursorSprite, v24, _hotspots[_savegameIndex].y1, 264);
+ }
+ }
+ if ((signed int)_savegameIndex > -1 && keybChar)
+ {
+ if ((keybChar < 'A' || keybChar > 'Z') && (keybChar < '0' || keybChar > '9') && keybChar != ' ')
+ {
+ if (keybChar == 8)
+ {
+ if ((signed int)v46 > 0)
+ --v46;
+ *(&_savegameFilenames[30 * _savegameIndex] + v46) = 0;
+ if (_savegameSprites[_savegameIndex] != -1)
+ {
+ _gameSys->removeSpriteDrawItem(_savegameSprites[_savegameIndex], 263);
+ memFreeHandle(_savegameSprites[_savegameIndex]);
+ }
+ v32 = getSpriteWidthById(0x104F9);
+ _savegameSprites[_savegameIndex] = allocSprite(v32, 40, 128, 0);
+ drawTextToSurface(_savegameSprites[_savegameIndex], 0, 0, 255, 0, 0, &_savegameFilenames[30 * _savegameIndex]);
+ insertSpriteDrawItem(_savegameSprites[_savegameIndex], 288, _hotspots[_savegameIndex].y1, 263);
+ _gameSys->removeSpriteDrawItem(_cursorSprite, 264);
+ v33 = _hotspots[_savegameIndex].y1;
+ v34 = getTextWidth(&_savegameFilenames[30 * _savegameIndex]);
+ insertSpriteDrawItem(_cursorSprite, LOWORD(_hotspots[_savegameIndex].x1) + v34, v33, 264);
+ }
+ else if (keybChar == 13)
+ {
+ _menuStatus = 1;
+ writeSavegame(_savegameIndex + 1, (int)&_savegameFilenames[30 * _savegameIndex], 1);
+ }
+ }
+ else
+ {
+ *(&_savegameFilenames[30 * _savegameIndex] + v46) = keybChar;
+ if ((signed int)v46 < 28)
+ ++v46;
+ *(&_savegameFilenames[30 * _savegameIndex] + v46) = 0;
+ if (getTextWidth(&_savegameFilenames[30 * _savegameIndex]) > 91)
+ {
+ --v46;
+ *(&_savegameFilenames[30 * _savegameIndex] + v46) = 0;
+ }
+ drawTextToSurface(_savegameSprites[_savegameIndex], 0, 0, 255, 0, 0, &_savegameFilenames[30 * _savegameIndex]);
+ v26 = getTextWidth(&_savegameFilenames[30 * _savegameIndex]);
+ rect.right = _hotspots[_savegameIndex].x1 + v26;
+ v27 = rect.right;
+ rect.left = v27 - 2 * getTextWidth("W");
+ rect.top = _hotspots[_savegameIndex].y1;
+ rect.bottom = _hotspots[_savegameIndex].y2;
+ insertDirtyRect(&rect);
+ _gameSys->removeSpriteDrawItem(_cursorSprite, 264);
+ v28 = _hotspots[_savegameIndex].x2;
+ v29 = getTextWidth("_");
+ if (v28 - v29 > rect.right)
+ {
+ insertSpriteDrawItem(_cursorSprite, SLOWORD(rect.right), SLOWORD(rect.top), 264);
+ }
+ else
+ {
+ v30 = _hotspots[_savegameIndex].x2;
+ v31 = v30 - getTextWidth("_");
+ insertSpriteDrawItem(_cursorSprite, v31, SLOWORD(rect.top), 264);
+ }
+ clearKeyStatus1(8);
+ }
+ }
+ keybChar = 0;
+ if (_menuStatus == 1 || _menuDone)
+ {
+ _gameSys->removeSpriteDrawItem(_menuSprite2, 262);
+ _gameSys->removeSpriteDrawItem(_menuSaveLoadSprite, 262);
+ for (i = 0; i < 7; ++i)
+ _gameSys->removeSpriteDrawItem(_savegameSprites[i], 263);
+ _gameSys->removeSpriteDrawItem(_cursorSprite, 264);
+ if (!_menuDone)
+ {
+ initMenuHotspots2();
+ insertSpriteDrawItem(_menuSprite1, 288, 79, 262);
+ }
+ }
+#endif
+}
+
+void GnapEngine::updateMenuStatusLoadGame() {
+ _hotspots[0].x1 = 288;
+ _hotspots[0].y1 = 74;
+ _hotspots[0].x2 = 379;
+ _hotspots[0].y2 = 96;
+ _sceneClickedHotspot = -1;
+ if (!_timers[2])
+ _sceneClickedHotspot = getClickedHotspotId();
+ if (_sceneClickedHotspot != -1 && _hotspotsCount - 2 != _sceneClickedHotspot) {
+ _timers[2] = 10;
+ if (_hotspotsCount - 4 <= _sceneClickedHotspot) {
+ playSound(0x108F5, 0);
+ _gameSys->removeSpriteDrawItem(_menuSprite2, 262);
+ _gameSys->removeSpriteDrawItem(_menuSaveLoadSprite, 262);
+ for (int i = 0; i < 7; ++i)
+ _gameSys->removeSpriteDrawItem(_savegameSprites[i], 263);
+ if (_hotspotsCount - 1 == _sceneClickedHotspot) {
+ _menuDone = true;
+ } else {
+ _menuStatus = 1;
+ initMenuHotspots2();
+ _gameSys->insertSpriteDrawItem(_menuSprite1, 288, 79, 262);
+ }
+ } else if (loadSavegame(_sceneClickedHotspot + 1)) {
+ playSound(0x108F5, 0);
+ } else {
+ playSound(0x108F4, 0);
+ _sceneDone = true;
+ }
+ }
+}
+
+void GnapEngine::updateMenuStatusQueryQuit() {
+
+ _hotspots[0].x1 = 311;
+ _hotspots[0].y1 = 197;
+ _hotspots[0].x2 = 377;
+ _hotspots[0].y2 = 237;
+
+ _sceneClickedHotspot = -1;
+
+ if (!_timers[2])
+ _sceneClickedHotspot = getClickedHotspotId();
+
+ /* _sceneClickedHotspot
+ 0 Yes
+ 1 No
+ 2 Button
+ 3 Display
+ 4 Background
+ */
+
+ if (_sceneClickedHotspot == 0) {
+ // Quit the game
+ playSound(0x108F5, 0);
+ _gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262);
+ _sceneDone = true;
+ _gameDone = true;
+ } else if (_sceneClickedHotspot == 4) {
+ // Exit the device
+ playSound(0x108F4, 0);
+ _gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262);
+ _menuDone = true;
+ } else if (_sceneClickedHotspot != -1) {
+ // Return to the main menu
+ playSound(0x108F4, 0);
+ _gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262);
+ _timers[2] = 10;
+ _menuStatus = 1;
+ initMenuHotspots2();
+ _gameSys->insertSpriteDrawItem(_menuSprite1, 288, 79, 262);
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/module.mk b/engines/gnap/module.mk
new file mode 100644
index 0000000000..78e2cce736
--- /dev/null
+++ b/engines/gnap/module.mk
@@ -0,0 +1,70 @@
+MODULE := engines/gnap
+
+MODULE_OBJS := \
+ datarchive.o \
+ detection.o \
+ gamesys.o \
+ gnap.o \
+ grid.o \
+ menu.o \
+ resource.o \
+ sound.o \
+ scenes/scene01.o \
+ scenes/scene02.o \
+ scenes/scene03.o \
+ scenes/scene04.o \
+ scenes/scene05.o \
+ scenes/scene06.o \
+ scenes/scene07.o \
+ scenes/scene08.o \
+ scenes/scene09.o \
+ scenes/scene10.o \
+ scenes/scene11.o \
+ scenes/scene12.o \
+ scenes/scene13.o \
+ scenes/scene14.o \
+ scenes/scene15.o \
+ scenes/scene16.o \
+ scenes/scene17.o \
+ scenes/scene18.o \
+ scenes/scene19.o \
+ scenes/scene20.o \
+ scenes/scene21.o \
+ scenes/scene22.o \
+ scenes/scene23.o \
+ scenes/scene24.o \
+ scenes/scene25.o \
+ scenes/scene26.o \
+ scenes/scene27.o \
+ scenes/scene28.o \
+ scenes/scene29.o \
+ scenes/scene30.o \
+ scenes/scene31.o \
+ scenes/scene32.o \
+ scenes/scene33.o \
+ scenes/scene38.o \
+ scenes/scene39.o \
+ scenes/scene40.o \
+ scenes/scene41.o \
+ scenes/scene42.o \
+ scenes/scene43.o \
+ scenes/scene44.o \
+ scenes/scene45.o \
+ scenes/scene46.o \
+ scenes/scene47.o \
+ scenes/scene48.o \
+ scenes/scene49.o \
+ scenes/scene50.o \
+ scenes/scene51.o \
+ scenes/scene52.o \
+ scenes/scene53.o \
+ scenes/scene54.o \
+ scenes/scenecore.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_GNAP), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/gnap/resource.cpp b/engines/gnap/resource.cpp
new file mode 100644
index 0000000000..ab83b1376b
--- /dev/null
+++ b/engines/gnap/resource.cpp
@@ -0,0 +1,118 @@
+/* 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/resource.h"
+
+namespace Gnap {
+
+// SequenceFrame
+
+void SequenceFrame::loadFromStream(Common::MemoryReadStream &stream) {
+ duration = stream.readUint16LE();
+ isScaled = stream.readUint16LE();
+ rect.left = stream.readUint32LE();
+ rect.top = stream.readUint32LE();
+ rect.right = stream.readUint32LE();
+ rect.bottom = stream.readUint32LE();
+ spriteId = stream.readUint32LE();
+ soundId = stream.readUint32LE();
+ unkValue = stream.readUint32LE();
+ //isScaled = 0;//DEBUG
+ debug(1, "SequenceFrame() spriteId: %d; soundId: %d", spriteId, soundId);
+}
+
+// SequenceAnimation
+
+void SequenceAnimation::loadFromStream(Common::MemoryReadStream &stream) {
+ field_0 = stream.readUint16LE();
+ field_2 = stream.readUint16LE();
+ field_4 = stream.readUint32LE();
+ framesCount = stream.readUint16LE();
+ field_A = stream.readUint16LE();
+ debug(1, "SequenceAnimation() framesCount: %d", framesCount);
+ frames = new SequenceFrame[framesCount];
+ for (int i = 0; i < framesCount; ++i)
+ frames[i].loadFromStream(stream);
+}
+
+// SequenceResource
+
+SequenceResource::SequenceResource(int resourceId, byte *data, uint32 size) {
+ Common::MemoryReadStream stream(data, size, DisposeAfterUse::NO);
+ _field_0 = stream.readUint32LE();
+ _sequenceId = stream.readUint32LE();
+ _field_8 = stream.readUint32LE();
+ _sequenceId2 = stream.readUint32LE();
+ _field_10 = stream.readUint32LE();
+ _flags = stream.readUint32LE();
+ _totalDuration = stream.readUint32LE();
+ _xOffs = stream.readUint16LE();
+ _yOffs = stream.readUint16LE();
+ _animationsCount = stream.readUint32LE();
+ _animations = new SequenceAnimation[_animationsCount];
+ debug(1, "SequenceResource() _animationsCount: %d", _animationsCount);
+ for (int i = 0; i < _animationsCount; ++i) {
+ uint32 animationOffs = stream.readUint32LE();
+ debug(1, "animationOffs: %08X", animationOffs);
+ uint32 oldOffs = stream.pos();
+ stream.seek(animationOffs);
+ _animations[i].loadFromStream(stream);
+ stream.seek(oldOffs);
+ }
+ // TODO Convert resourceIds
+}
+
+SequenceResource::~SequenceResource() {
+ delete[] _animations;
+}
+
+// SpriteResource
+
+SpriteResource::SpriteResource(int resourceId, byte *data, uint32 size) {
+ _data = data;
+ _width = READ_LE_UINT16(_data);
+ _height = READ_LE_UINT16(_data + 2);
+ _unk1 = READ_LE_UINT16(_data + 4);
+ _unk2 = READ_LE_UINT16(_data + 6);
+ _transparent = READ_LE_UINT16(_data + 8);
+ _colorsCount = READ_LE_UINT16(_data + 10);
+ _palette = (uint32*)(_data + 12);
+ _pixels = _data + 12 + _colorsCount * 4;
+ debug(1, "SpriteResource() width: %d; height: %d; colorsCount: %d", _width, _height, _colorsCount);
+}
+
+SpriteResource::~SpriteResource() {
+ delete[] _data;
+}
+
+// SoundResource
+
+SoundResource::SoundResource(int resourceId, byte *data, uint32 size) {
+ _data = data;
+ _size = size;
+}
+
+SoundResource::~SoundResource() {
+ delete[] _data;
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/resource.h b/engines/gnap/resource.h
new file mode 100644
index 0000000000..b0f6a6169b
--- /dev/null
+++ b/engines/gnap/resource.h
@@ -0,0 +1,196 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GNAP_RESOURCE_H
+#define GNAP_RESOURCE_H
+
+#include "common/array.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/memstream.h"
+#include "common/str.h"
+#include "common/stream.h"
+#include "common/substream.h"
+#include "common/system.h"
+
+#include "graphics/surface.h"
+
+#include "gnap/datarchive.h"
+
+namespace Gnap {
+
+enum {
+ kResTypeSprite = 0,
+ kResTypeBitmap = 1,
+ kResTypeSound = 2,
+ kResTypeSequence = 3
+};
+
+struct SequenceFrame {
+ int16 duration;
+ int16 isScaled;
+ Common::Rect rect;
+ int32 spriteId;
+ int32 soundId;
+ int32 unkValue;
+ void loadFromStream(Common::MemoryReadStream &stream);
+};
+
+struct SequenceAnimation {
+ int16 field_0;
+ int16 field_2;
+ int32 field_4;
+ int16 framesCount;
+ int16 field_A;
+ SequenceFrame *frames;
+ SequenceAnimation() : frames(0) {}
+ ~SequenceAnimation() { delete[] frames; }
+ void loadFromStream(Common::MemoryReadStream &stream);
+};
+
+class SequenceResource {
+public:
+ SequenceResource(int resourceId, byte *data, uint32 size);
+ ~SequenceResource();
+public:
+ uint32 _field_0;
+ int32 _sequenceId;
+ int32 _field_8;
+ int32 _sequenceId2;
+ uint32 _field_10;
+ uint32 _flags;
+ int32 _totalDuration;
+ int16 _xOffs;
+ int16 _yOffs;
+ int32 _animationsCount;
+ SequenceAnimation *_animations;
+};
+
+class SpriteResource {
+public:
+ SpriteResource(int resourceId, byte *data, uint32 size);
+ ~SpriteResource();
+public:
+ byte *_data;
+ byte *_pixels;
+ uint32 *_palette;
+ int16 _width, _height;
+ uint16 _unk1;
+ uint16 _unk2;
+ uint16 _transparent;
+ uint16 _colorsCount;
+};
+
+class SoundResource {
+public:
+ SoundResource(int resourceId, byte *data, uint32 size);
+ ~SoundResource();
+public:
+ byte *_data;
+ uint32 _size;
+};
+
+template <class ResourceClass, int ResourceType, bool FreeAfterLoad>
+class ResourceCacheTemplate {
+public:
+
+ ResourceCacheTemplate(DatManager *dat) : _dat(dat) {
+ }
+
+ ~ResourceCacheTemplate() {
+ }
+
+ ResourceClass *get(int resourceId) {
+ Resource *resource = find(resourceId);
+ if (!resource) {
+ debug(1, "Loading resource type %d with ID %08X from disk", ResourceType, resourceId);
+ resource = new Resource(load(resourceId));
+ _cache[resourceId] = resource;
+ } else {
+ debug(1, "Resource type %d with ID %08X was in cache", ResourceType, resourceId);
+ }
+ resource->_isLocked = true;
+ return resource->_obj;
+ }
+
+ void release(int resourceId) {
+ Resource *resource = find(resourceId);
+ if (resource)
+ resource->_isLocked = false;
+ }
+
+ void purge(bool force = false) {
+ debug("Count before purge: %d", _cache.size());
+ for (CacheMapIterator it = _cache.begin(); it != _cache.end(); ++it) {
+ Resource *resource = it->_value;
+ if (force || !resource->_isLocked) {
+ delete resource;
+ _cache.erase(it);
+ }
+ }
+ debug("Count after purge: %d", _cache.size());
+ }
+
+protected:
+
+ struct Resource {
+ ResourceClass *_obj;
+ bool _isLocked;
+ Resource(ResourceClass *obj) : _obj(obj), _isLocked(false) {}
+ ~Resource() { delete _obj; }
+ };
+
+ typedef Common::HashMap<int, Resource*> CacheMap;
+ typedef typename CacheMap::iterator CacheMapIterator;
+
+ DatManager *_dat;
+ CacheMap _cache;
+
+ Resource *find(int resourceId) {
+ CacheMapIterator it = _cache.find(resourceId);
+ if (it != _cache.end())
+ return it->_value;
+ return 0;
+ }
+
+ ResourceClass *load(int resourceId) {
+ if (_dat->getResourceType(resourceId) != ResourceType) {
+ error("ResourceCache::load() Wrong resource type: Expected %d, got %d", ResourceType, _dat->getResourceType(resourceId));
+ return 0;
+ }
+ byte *resourceData = _dat->loadResource(resourceId);
+ uint32 resourceSize = _dat->getResourceSize(resourceId);
+ ResourceClass *obj = new ResourceClass(resourceId, resourceData, resourceSize);
+ if (FreeAfterLoad)
+ delete[] resourceData;
+ return obj;
+ }
+
+};
+
+typedef ResourceCacheTemplate<SpriteResource, kResTypeSprite, false> SpriteCache;
+typedef ResourceCacheTemplate<SoundResource, kResTypeSound, false> SoundCache;
+typedef ResourceCacheTemplate<SequenceResource, kResTypeSequence, true> SequenceCache;
+
+} // End of namespace Gnap
+
+#endif // GNAP_RESOURCE_H
diff --git a/engines/gnap/scenes/scene01.cpp b/engines/gnap/scenes/scene01.cpp
new file mode 100644
index 0000000000..0e4695c619
--- /dev/null
+++ b/engines/gnap/scenes/scene01.cpp
@@ -0,0 +1,373 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitTruck = 1,
+ kHSMud = 2,
+ kHSPigs = 3,
+ kHSSpaceship = 4,
+ kHSDevice = 5,
+ kHSWalkArea1 = 6,
+ kHSWalkArea2 = 7,
+ kHSWalkArea3 = 8,
+ kHSWalkArea4 = 9,
+ kHSWalkArea5 = 10,
+ kHSWalkArea6 = 11,
+ kHSWalkArea7 = 12,
+ kHSWalkArea8 = 13
+};
+
+enum {
+ kASLookSpaceship = 1,
+ kASLookSpaceshipDone = 2,
+ kASLeaveScene = 3,
+ kASTakeMud = 5,
+ kASLookPigs = 6,
+ kASUsePigs = 7
+};
+
+int GnapEngine::scene01_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 3);
+ return 0x88;
+}
+
+void GnapEngine::scene01_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED | SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitTruck, 780, 226, 800, 455, SF_EXIT_R_CURSOR | SF_WALKABLE, 10, 6);
+ setHotspot(kHSMud, 138, 282, 204, 318, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 5);
+ setHotspot(kHSPigs, 408, 234, 578, 326, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 4);
+ setHotspot(kHSSpaceship, 0, 200, 94, 292, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 6);
+ setHotspot(kHSWalkArea1, 0, 0, 162, 426);
+ setHotspot(kHSWalkArea2, 162, 0, 237, 396);
+ setHotspot(kHSWalkArea3, 237, 0, 319, 363);
+ setHotspot(kHSWalkArea4, 520, 0, 800, 404);
+ setHotspot(kHSWalkArea5, 300, 447, 800, 600);
+ setHotspot(kHSWalkArea6, 678, 0, 800, 404);
+ setHotspot(kHSWalkArea7, 0, 0, 520, 351);
+ setHotspot(kHSWalkArea8, 0, 546, 300, 600);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(0))
+ _hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR;
+ if (isFlag(1))
+ _hotspots[kHSMud].flags = SF_WALKABLE | SF_DISABLED;
+ _hotspotsCount = 14;
+}
+
+void GnapEngine::scene01_run() {
+
+ // NOTE Removed _s01_dword_474380 which was set when the mud was taken
+ // which is also set in the global game flags.
+
+ playSound(0x1091C, 1);
+ startSoundTimerC(5);
+
+ _gameSys->setAnimation(134, 20, 4);
+ _gameSys->insertSequence(134, 20, 0, 0, kSeqNone, 0, 0, 0);
+
+ _gameSys->setAnimation(0x7F, 40, 2);
+ _gameSys->insertSequence(0x7F, 40, 0, 0, kSeqNone, 0, 0, 0);
+
+ _timers[4] = getRandom(100) + 300;
+
+ if (!isFlag(1))
+ _gameSys->insertSequence(129, 40, 0, 0, kSeqNone, 0, 0, 0);
+
+ queueInsertDeviceIcon();
+
+ if (_prevSceneNum == 2) {
+ initGnapPos(11, 6, 3);
+ if (isFlag(0))
+ initBeaverPos(12, 6, 4);
+ endSceneInit();
+ if (isFlag(0))
+ platypusWalkTo(9, 6, -1, 0x107C2, 1);
+ gnapWalkTo(8, 6, -1, 0x107B9, 1);
+ } else {
+ initGnapPos(1, 6, 1);
+ if (isFlag(0))
+ initBeaverPos(1, 7, 0);
+ endSceneInit();
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+ testWalk(0, 3, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene01_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0 && isFlag(0)) {
+ if (_grabCursorSpriteIndex == kItemDisguise) {
+ gnapUseDisguiseOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(5))
+ playGnapMoan1(_platX, _platY);
+ else
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSSpaceship:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 2);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ _gnapIdleFacing = 5;
+ if (gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1))
+ _gnapActionStatus = kASLookSpaceship;
+ break;
+ case GRAB_CURSOR:
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSMud:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 2, 3);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(3, 3);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 2, 3) | 0x10000, 1);
+ _gnapActionStatus = kASTakeMud;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSPigs:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 7, 2);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 7, 2) | 0x10000, 1);
+ _gnapActionStatus = kASLookPigs;
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 7, 2) | 0x10000, 1);
+ _gnapActionStatus = kASUsePigs;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskBrainPulsating, 7, 2) | 0x10000, 1);
+ _gnapActionStatus = kASLookPigs;
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitTruck:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ gnapWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 0, 0x107AB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(0))
+ platypusWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y + 1, -1, 0x107CD, 1);
+ _newSceneNum = 2;
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ case kHSWalkArea4:
+ case kHSWalkArea5:
+ case kHSWalkArea6:
+ case kHSWalkArea7:
+ case kHSWalkArea8:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene01_updateAnimations();
+
+ if (!isSoundPlaying(0x1091C))
+ playSound(0x1091C, 1);
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0 && isFlag(0))
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (_timers[4] == 0) {
+ // Update bird animation
+ _timers[4] = getRandom(100) + 300;
+ if (getRandom(1) == 0)
+ _gameSys->insertSequence(0x84, 180, 0, 0, kSeqNone, 0, 0, 0);
+ else
+ _gameSys->insertSequence(0x83, 180, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ playSoundC();
+ }
+
+ checkGameKeys();
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene01_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene01_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLookSpaceship:
+ _s01_spaceshipSurface = _gameSys->createSurface(47);
+ _gameSys->insertSpriteDrawItem(_s01_spaceshipSurface, 0, 0, 255);
+ _gameSys->setAnimation(133, 256, 0);
+ _gameSys->insertSequence(133, 256, 0, 0, kSeqNone, 0, 0, 0);
+ _gnapActionStatus = kASLookSpaceshipDone;
+ break;
+ case kASLookSpaceshipDone:
+ _gameSys->removeSequence(133, 256, 1);
+ _gameSys->removeSpriteDrawItem(_s01_spaceshipSurface, 255);
+ deleteSurface(&_s01_spaceshipSurface);
+ _gnapActionStatus = -1;
+ break;
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ case kASTakeMud:
+ playGnapPullOutDevice(2, 3);
+ playGnapUseDevice(0, 0);
+ _gameSys->insertSequence(128, 40, 129, 40, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(128, 40, 3);
+ _gnapActionStatus = -1;
+ break;
+ case kASLookPigs:
+ playSound(138, 0);
+ playSound(139, 0);
+ playSound(140, 0);
+ _gnapActionStatus = -1;
+ break;
+ case kASUsePigs:
+ playGnapPullOutDevice(7, 2);
+ playGnapUseDevice(0, 0);
+ _gameSys->insertSequence(135, 39, 0, 0, kSeqNone, 25, getRandom(140) - 40, 0);
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ _gameSys->setAnimation(0, 0, 3);
+ invAdd(kItemMud);
+ setGrabCursorSprite(kItemMud);
+ setFlag(1);
+ scene01_updateHotspots();
+ }
+
+ if (_gameSys->getAnimationStatus(4) == 2) {
+ _s01_smokeIdCtr = (_s01_smokeIdCtr + 1) % 2;
+ _gameSys->setAnimation(0x86, _s01_smokeIdCtr + 20, 4);
+ _gameSys->insertSequence(0x86, _s01_smokeIdCtr + 20,
+ 0x86, (_s01_smokeIdCtr + 1) % 2 + 20,
+ kSeqSyncWait, 0, 0, 0);
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ _s01_pigsIdCtr = (_s01_pigsIdCtr + 1) % 2;
+ _gameSys->setAnimation(0x7F, _s01_pigsIdCtr + 40, 2);
+ _gameSys->insertSequence(0x7F, _s01_pigsIdCtr + 40,
+ 0x7F, (_s01_pigsIdCtr + 1) % 2 + 40,
+ kSeqSyncWait, 0, 0, 0);
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene02.cpp b/engines/gnap/scenes/scene02.cpp
new file mode 100644
index 0000000000..5d740b906f
--- /dev/null
+++ b/engines/gnap/scenes/scene02.cpp
@@ -0,0 +1,539 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSChicken = 1,
+ kHSTruck1 = 2,
+ kHSTruck2 = 3,
+ kHSTruckGrill = 4,
+ kHSDevice = 5,
+ kHSExitHouse = 6,
+ kHSExitBarn = 7,
+ kHSExitCreek = 8,
+ kHSExitPigpen = 9,
+ kHSWalkArea1 = 10,
+ kHSWalkArea2 = 11,
+ kHSWalkArea3 = 12,
+ kHSWalkArea4 = 13
+};
+
+enum {
+ kASUseTruckNoKeys = 0,
+ kASUseGasWithTruck = 1,
+ kASUseTruckGas = 2,
+ kASUseTruckNoGas = 3,
+ kASGrabTruckGrill = 5,
+ kASLeaveScene = 6,
+ kASTalkChicken = 7,
+ kASGrabChicken = 8,
+ kASGrabChickenDone = 9,
+ kASUseTruckNoKeysDone = 11,
+ kASUseGasWithTruckDone = 12,
+ kASUseTwigWithChicken = 16
+};
+
+int GnapEngine::scene02_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ return isFlag(9) ? 0x15A : 0x15B;
+}
+
+void GnapEngine::scene02_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED | SF_WALKABLE);
+ setHotspot(kHSChicken, 606, 455, 702, 568, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8);
+ setHotspot(kHSTruck1, 385, 258, 464, 304, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 5);
+ setHotspot(kHSTruck2, 316, 224, 390, 376, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 6);
+ setHotspot(kHSTruckGrill, 156, 318, 246, 390, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 2, 7);
+ setHotspot(kHSExitHouse, 480, 120, 556, 240, SF_EXIT_U_CURSOR, 7, 5);
+ setHotspot(kHSExitBarn, 610, 0, 800, 164, SF_EXIT_U_CURSOR, 10, 5);
+ setHotspot(kHSExitCreek, 780, 336, 800, 556, SF_EXIT_R_CURSOR | SF_WALKABLE, 10, 8);
+ setHotspot(kHSExitPigpen, 0, 300, 20, 600, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 8);
+ setHotspot(kHSWalkArea1, 92, 140, 304, 430, 0, 3, 1);
+ setHotspot(kHSWalkArea2, 0, 0, 800, 380);
+ setHotspot(kHSWalkArea3, 0, 0, 386, 445);
+ setHotspot(kHSWalkArea4, 386, 0, 509, 410);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(0))
+ _hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR;
+ _hotspotsCount = 14;
+}
+
+void GnapEngine::scene02_run() {
+
+ playSound(0x1091C, 1);
+ startSoundTimerC(6);
+
+ _s02_currChickenSequenceId = 0x14B;
+ _gameSys->setAnimation(0x14B, 179, 2);
+ _gameSys->insertSequence(0x14B, 179, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s02_nextChickenSequenceId = -1;
+ _timers[5] = getRandom(20) + 30;
+ _timers[4] = getRandom(100) + 300;
+
+ queueInsertDeviceIcon();
+
+ switch (_prevSceneNum) {
+ case 3:
+ initGnapPos(11, 6, 3);
+ if (isFlag(0))
+ initBeaverPos(12, 6, 4);
+ endSceneInit();
+ if (isFlag(0))
+ platypusWalkTo(9, 6, -1, 0x107C2, 1);
+ gnapWalkTo(8, 6, -1, 0x107BA, 1);
+ break;
+ case 4:
+ initGnapPos(_hotspotsWalkPos[6].x, _hotspotsWalkPos[6].y, 3);
+ if (isFlag(0))
+ initBeaverPos(_hotspotsWalkPos[6].x + 1, _hotspotsWalkPos[6].y, 4);
+ endSceneInit();
+ gnapWalkTo(7, 6, 0, 0x107B9, 1);
+ if (isFlag(0))
+ platypusWalkTo(8, 6, 1, 0x107C2, 1);
+ scene02_updateHotspots();
+ _gameSys->waitForUpdate();
+ break;
+ case 47:
+ clearFlag(25);
+ initGnapPos(5, 6, 3);
+ initBeaverPos(6, 7, 4);
+ endSceneInit();
+ break;
+ case 49:
+ initGnapPos(5, 6, 1);
+ if (isFlag(0))
+ initBeaverPos(6, 7, 0);
+ endSceneInit();
+ break;
+ default:
+ initGnapPos(-1, 6, 1);
+ if (isFlag(0))
+ initBeaverPos(-1, 7, 0);
+ endSceneInit();
+ if (isFlag(0))
+ platypusWalkTo(2, 7, -1, 0x107C2, 1);
+ gnapWalkTo(2, 8, -1, 0x107B9, 1);
+ break;
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+
+ updateCursorByHotspot();
+
+ testWalk(0, 6, 7, 6, 8, 6);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene02_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0 && isFlag(0)) {
+ if (_grabCursorSpriteIndex == kItemDisguise) {
+ gnapUseDisguiseOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(5))
+ playGnapMoan1(_platX, _platY);
+ else
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSChicken:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemTwig) {
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y + 1,
+ 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASUseTwigWithChicken;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y + 1, 9, 8);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan2(9, 8);
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 1;
+ if (gnapWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1))
+ _gnapActionStatus = kASGrabChicken;
+ else
+ _gnapActionStatus = -1;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 1;
+ gnapWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkChicken;
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSTruck1:
+ case kHSTruck2:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemKeys) {
+ if (gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 2, 2) | 0x10000, 1)) {
+ setGrabCursorSprite(-1);
+ invRemove(kItemKeys);
+ if (isFlag(8))
+ _gnapActionStatus = kASUseTruckGas;
+ else
+ _gnapActionStatus = kASUseTruckNoGas;
+ }
+ } else if (_grabCursorSpriteIndex == kItemGas) {
+ _hotspots[kHSWalkArea4].flags |= SF_WALKABLE;
+ if (gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 2, 2) | 0x10000, 1))
+ _gnapActionStatus = kASUseGasWithTruck;
+ _hotspots[kHSWalkArea4].flags &= ~SF_WALKABLE;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 2, 2);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(2, 2);
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(9)) {
+ if (gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 2, 2) | 0x10000, 1)) {
+ if (isFlag(8))
+ _gnapActionStatus = kASUseTruckGas;
+ else
+ _gnapActionStatus = kASUseTruckNoGas;
+ }
+ } else {
+ _gnapIdleFacing = 4;
+ if (gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 2, 2) | 0x10000, 1))
+ _gnapActionStatus = kASUseTruckNoKeys;
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSTruckGrill:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 2, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan2(2, 4);
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASGrabTruckGrill;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitHouse:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[6].x, _hotspotsWalkPos[6].y, 0, 0x107AD, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(0))
+ platypusWalkTo(_hotspotsWalkPos[6].x + 1, _hotspotsWalkPos[6].y, -1, 0x107C1, 1);
+ scene02_updateHotspots();
+ _newSceneNum = 4;
+ }
+ break;
+
+ case kHSExitBarn:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[7].x, _hotspotsWalkPos[7].y, 0, 0x107AD, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(0))
+ platypusWalkTo(_hotspotsWalkPos[7].x + 1, _hotspotsWalkPos[7].y, -1, 0x107C1, 1);
+ scene02_updateHotspots();
+ _newSceneNum = 5;
+ }
+ break;
+
+ case kHSExitCreek:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[8].x, _hotspotsWalkPos[8].y, 0, 0x107AB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(0))
+ platypusWalkTo(_hotspotsWalkPos[8].x, _hotspotsWalkPos[8].y, -1, 0x107CD, 1);
+ _newSceneNum = 3;
+ }
+ break;
+
+ case kHSExitPigpen:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[9].x, _hotspotsWalkPos[9].y, 0, 0x107AF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(0))
+ platypusWalkTo(_hotspotsWalkPos[9].x, _hotspotsWalkPos[9].y, -1, 0x107CF, 1);
+ _newSceneNum = 1;
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ case kHSWalkArea4:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene02_updateAnimations();
+
+ if (!isSoundPlaying(0x1091C))
+ playSound(0x1091C, 1);
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0 && isFlag(0))
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ // Update bird animation
+ _timers[4] = getRandom(100) + 300;
+ if (getRandom(2) != 0)
+ _gameSys->insertSequence(0x156, 256, 0, 0, kSeqNone, 0, 0, 0);
+ else
+ _gameSys->insertSequence(0x154, 256, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ if (!_timers[5] && _s02_nextChickenSequenceId == -1 && _gnapActionStatus != 7 && _gnapActionStatus != 8) {
+ if (getRandom(6) != 0) {
+ _s02_nextChickenSequenceId = 0x14B;
+ _timers[5] = getRandom(20) + 30;
+ } else {
+ _s02_nextChickenSequenceId = 0x14D;
+ _timers[5] = getRandom(20) + 50;
+ }
+ }
+ playSoundC();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene02_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene02_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ switch (_gnapActionStatus) {
+ case kASUseTruckNoKeys:
+ _gameSys->insertSequence(0x14E, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x14E, _gnapId, 0);
+ _gnapSequenceId = 0x14E;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = kASUseTruckNoKeysDone;
+ break;
+ case kASUseGasWithTruck:
+ _gameSys->insertSequence(0x151, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x151, _gnapId, 0);
+ _gnapSequenceId = 0x151;
+ _gnapSequenceDatNum = 0;
+ invRemove(kItemGas);
+ setGrabCursorSprite(-1);
+ setFlag(8);
+ _gnapActionStatus = kASUseGasWithTruckDone;
+ break;
+ case kASUseTruckGas:
+ _timers[5] = 9999;
+ _timers[4] = 9999;
+ hideCursor();
+ setGrabCursorSprite(-1);
+ if (!isFlag(9)) {
+ _gameSys->insertSequence(0x14F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->waitForUpdate();
+ setFlag(9);
+ _gnapSequenceId = 0x14F;
+ _gnapSequenceDatNum = 0;
+ invRemove(kItemKeys);
+ setGrabCursorSprite(-1);
+ }
+ _newSceneNum = 47;
+ _sceneDone = true;
+ break;
+ case kASUseTruckNoGas:
+ hideCursor();
+ setGrabCursorSprite(-1);
+ _timers[4] = 250;
+ if (!isFlag(9)) {
+ _gameSys->insertSequence(0x14F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->waitForUpdate();
+ setFlag(9);
+ _gnapSequenceId = 0x14F;
+ _gnapSequenceDatNum = 0;
+ invRemove(kItemKeys);
+ setGrabCursorSprite(-1);
+ }
+ _newSceneNum = 47;
+ _sceneDone = true;
+ setFlag(25);
+ break;
+ case kASGrabTruckGrill:
+ switch (_s02_truckGrillCtr) {
+ case 0:
+ _s02_gnapTruckSequenceId = 0x158;
+ break;
+ case 1:
+ _s02_gnapTruckSequenceId = 0x159;
+ break;
+ case 2:
+ _s02_gnapTruckSequenceId = 0x157;
+ break;
+ }
+ _s02_truckGrillCtr = (_s02_truckGrillCtr + 1) % 3;
+ _gameSys->insertSequence(_s02_gnapTruckSequenceId, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s02_gnapTruckSequenceId, _gnapId, 0);
+ _gnapSequenceId = _s02_gnapTruckSequenceId;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = -1;
+ break;
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ case kASTalkChicken:
+ _s02_nextChickenSequenceId = 0x14C;
+ break;
+ case kASGrabChicken:
+ _s02_nextChickenSequenceId = 0x150;
+ _timers[2] = 100;
+ break;
+ case kASGrabChickenDone:
+ _gameSys->insertSequence(0x107B5, _gnapId, 0x150, 179, kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gnapSequenceId = 0x7B5;
+ _gnapSequenceDatNum = 1;
+ _s02_currChickenSequenceId = 0x14B;
+ _gameSys->setAnimation(0x14B, 179, 2);
+ _gameSys->insertSequence(_s02_currChickenSequenceId, 179, 0, 0, kSeqNone, 0, 0, 0);
+ _gnapActionStatus = -1;
+ _timers[5] = 30;
+ break;
+ case kASUseTwigWithChicken:
+ playGnapShowItem(5, 0, 0);
+ _gameSys->insertSequence(0x155, 179, _s02_currChickenSequenceId, 179, 32, 0, 0, 0);
+ _s02_currChickenSequenceId = 0x155;
+ _s02_nextChickenSequenceId = -1;
+ _gnapActionStatus = -1;
+ break;
+ case kASUseTruckNoKeysDone:
+ case kASUseGasWithTruckDone:
+ default:
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ if (_s02_nextChickenSequenceId == 0x150) {
+ _gameSys->setAnimation(_s02_nextChickenSequenceId, 179, 0);
+ _gameSys->insertSequence(_s02_nextChickenSequenceId, 179, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->removeSequence(_s02_currChickenSequenceId, 179, 1);
+ _s02_nextChickenSequenceId = -1;
+ _s02_currChickenSequenceId = -1;
+ _gnapActionStatus = kASGrabChickenDone;
+ _timers[5] = 500;
+ } else if (_s02_nextChickenSequenceId == 0x14C) {
+ _gameSys->setAnimation(_s02_nextChickenSequenceId, 179, 2);
+ _gameSys->insertSequence(_s02_nextChickenSequenceId, 179, _s02_currChickenSequenceId, 179, kSeqSyncWait, 0, 0, 0);
+ _s02_currChickenSequenceId = _s02_nextChickenSequenceId;
+ _s02_nextChickenSequenceId = -1;
+ _gnapActionStatus = -1;
+ } else if (_s02_nextChickenSequenceId != -1) {
+ _gameSys->setAnimation(_s02_nextChickenSequenceId, 179, 2);
+ _gameSys->insertSequence(_s02_nextChickenSequenceId, 179, _s02_currChickenSequenceId, 179, kSeqSyncWait, 0, 0, 0);
+ _s02_currChickenSequenceId = _s02_nextChickenSequenceId;
+ _s02_nextChickenSequenceId = -1;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene03.cpp b/engines/gnap/scenes/scene03.cpp
new file mode 100644
index 0000000000..6f191dc6e3
--- /dev/null
+++ b/engines/gnap/scenes/scene03.cpp
@@ -0,0 +1,517 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSGrass = 1,
+ kHSExitTruck = 2,
+ kHSCreek = 3,
+ kHSTrappedPlatypus = 4,
+ kHSDevice = 5,
+ kHSWalkAreas1 = 6,
+ kHSWalkAreas2 = 7,
+ kHSPlatypusWalkArea = 8,
+ kHSWalkAreas3 = 9
+};
+
+enum {
+ kASLeaveScene = 0,
+ kASFreePlatypus = 1,
+ kASHypnotizePlat = 2,
+ kASHypnotizeScaredPlat = 3,
+ kASFreePlatypusDone = 4,
+ kASGrabPlatypus = 5,
+ kASGrabCreek = 6,
+ kASGrabCreekDone = 7,
+ kASGrabScaredPlatypus = 8
+};
+
+int GnapEngine::scene03_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0, 0, 5);
+ return 0x1CC;
+}
+
+void GnapEngine::scene03_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED | SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSGrass, 646, 408, 722, 458, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 6);
+ setHotspot(kHSExitTruck, 218, 64, 371, 224, SF_EXIT_U_CURSOR | SF_WALKABLE, 4, 4);
+ setHotspot(kHSCreek, 187, 499, 319, 587, SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 7);
+ setHotspot(kHSTrappedPlatypus, 450, 256, 661, 414, SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 2, 5);
+ setHotspot(kHSWalkAreas1, 0, 500, 300, 600);
+ setHotspot(kHSWalkAreas2, 300, 447, 800, 600);
+ setHotspot(kHSPlatypusWalkArea, 235, 0, 800, 600);
+ setHotspot(kHSWalkAreas3, 0, 0, 800, 354);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(0))
+ _hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR;
+ if (isFlag(6))
+ _hotspots[kHSGrass].flags = SF_WALKABLE | SF_DISABLED;
+ if (isFlag(0))
+ _hotspots[kHSTrappedPlatypus].flags = SF_DISABLED;
+ if (isFlag(0) || _s03_platypusHypnotized)
+ _hotspots[kHSPlatypusWalkArea].flags |= SF_WALKABLE;
+ _hotspotsCount = 10;
+}
+
+void GnapEngine::scene03_run() {
+
+ playSound(0x10925, 1);
+
+ startSoundTimerC(7);
+
+ _gameSys->insertSequence(0x1CA, 251, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0x1CB, 251, 0, 0, kSeqLoop, 0, 0, 0);
+
+ _s03_platypusHypnotized = false;
+
+ initGnapPos(3, 4, 1);
+
+ _gameSys->insertSequence(0x1C6, 253, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s03_currFrogSequenceId = 0x1C6;
+ _s03_nextFrogSequenceId = -1;
+ _gameSys->setAnimation(0x1C6, 253, 2);
+
+ _timers[6] = getRandom(20) + 30;
+ _timers[4] = getRandom(100) + 300;
+ _timers[5] = getRandom(100) + 200;
+
+ if (isFlag(0)) {
+ initBeaverPos(5, 4, 0);
+ } else {
+ _timers[1] = getRandom(40) + 20;
+ _gameSys->setAnimation(0x1C2, 99, 1);
+ _gameSys->insertSequence(0x1C2, 99, 0, 0, kSeqNone, 0, 0, 0);
+ _beaverSequenceId = 0x1C2;
+ _beaverSequenceDatNum = 0;
+ }
+
+ _gameSys->insertSequence(0x1C4, 255, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (!isFlag(6))
+ _gameSys->insertSequence(0x1B2, 253, 0, 0, kSeqNone, 0, 0, 0);
+
+ queueInsertDeviceIcon();
+
+ endSceneInit();
+
+ if (isFlag(0))
+ platypusWalkTo(4, 7, -1, 0x107C2, 1);
+ gnapWalkTo(3, 6, -1, 0x107B9, 1);
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0 && isFlag(0)) {
+ if (_grabCursorSpriteIndex == kItemDisguise) {
+ gnapUseDisguiseOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(5))
+ playGnapMoan1(_platX, _platY);
+ else
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSGrass:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(6)) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowItem(_grabCursorSpriteIndex, 9, 6);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(9, 6);
+ break;
+ case GRAB_CURSOR:
+ playGnapPullOutDevice(9, 6);
+ playGnapUseDevice(0, 0);
+ _gameSys->insertSequence(0x1B3, 253, 0x1B2, 253, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x1B3, 253, 5);
+ _hotspots[kHSGrass].flags |= SF_WALKABLE | SF_DISABLED;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitTruck:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _hotspots[kHSPlatypusWalkArea].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, 0x107AD, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(0))
+ platypusWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, -1, 0x107C2, 1);
+ _hotspots[kHSPlatypusWalkArea].flags &= ~SF_WALKABLE;
+ if (_cursorValue == 1)
+ _newSceneNum = 2;
+ else
+ _newSceneNum = 33;
+ }
+ break;
+
+ case kHSCreek:
+ if (_gnapActionStatus == -1) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan2(2, 8);
+ break;
+ case GRAB_CURSOR:
+ if (!isFlag(0))
+ _hotspots[kHSPlatypusWalkArea].flags |= SF_WALKABLE;
+ if (gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[3].x + 1, _hotspotsWalkPos[3].y + 1) | 0x10000, 1))
+ _gnapActionStatus = kASGrabCreek;
+ if (!isFlag(0))
+ _hotspots[kHSPlatypusWalkArea].flags &= ~SF_WALKABLE;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSTrappedPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(0)) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowItem(_grabCursorSpriteIndex, 8, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(8, 4);
+ break;
+ case GRAB_CURSOR:
+ if (_s03_platypusHypnotized) {
+ gnapWalkTo(7, 6, 0, 0x107B5, 1);
+ _gnapActionStatus = kASFreePlatypus;
+ } else {
+ gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ if (_s03_platypusScared)
+ _gnapActionStatus = kASGrabScaredPlatypus;
+ else
+ _gnapActionStatus = kASGrabPlatypus;
+ }
+ break;
+ case TALK_CURSOR:
+ if (_s03_platypusHypnotized) {
+ playGnapBrainPulsating(8, 4);
+ } else {
+ _gnapIdleFacing = 1;
+ gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ if (_s03_platypusScared)
+ _gnapActionStatus = kASHypnotizeScaredPlat;
+ else
+ _gnapActionStatus = kASHypnotizePlat;
+ }
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene03_updateHotspots();
+ }
+ break;
+
+ case kHSWalkAreas1:
+ case kHSWalkAreas2:
+ case kHSWalkAreas3:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ case kHSPlatypusWalkArea:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(0) || _s03_platypusHypnotized) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ } else {
+ gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 0x107B5, 1);
+ if (_s03_platypusScared)
+ _gnapActionStatus = kASGrabScaredPlatypus;
+ else
+ _gnapActionStatus = kASGrabPlatypus;
+ }
+ }
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene03_updateAnimations();
+
+ if (!isSoundPlaying(0x10925))
+ playSound(0x10925, 1);
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0 && isFlag(0))
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (!_timers[1] && !_s03_platypusScared) {
+ _timers[1] = getRandom(40) + 20;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && !isFlag(0) && !_s03_platypusHypnotized)
+ _s03_nextPlatSequenceId = 450;
+ }
+ if (!_timers[6]) {
+ _timers[6] = getRandom(20) + 30;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s03_nextFrogSequenceId == -1) {
+ if (getRandom(5) == 1)
+ _s03_nextFrogSequenceId = 0x1C6;
+ else
+ _s03_nextFrogSequenceId = 0x1C7;
+ }
+ }
+ if (!_timers[4]) {
+ // Update bird animation
+ _timers[4] = getRandom(100) + 300;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0)
+ _gameSys->insertSequence(getRandom(2) != 0 ? 0x1C8 : 0x1C3, 253, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ if (!_timers[5]) {
+ _timers[5] = getRandom(100) + 200;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0) {
+ _gameSys->setAnimation(0x1C5, 253, 4);
+ _gameSys->insertSequence(0x1C5, 253, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ }
+ playSoundC();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene03_updateHotspots();
+ _timers[5] = getRandom(100) + 200;
+ _timers[4] = getRandom(100) + 300;
+ _timers[6] = getRandom(20) + 30;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene03_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ case kASFreePlatypus:
+ _s03_nextPlatSequenceId = 0x1BC;
+ break;
+ case kASFreePlatypusDone:
+ _gnapActionStatus = -1;
+ _platX = 6;
+ _platY = 6;
+ _beaverFacing = 4;
+ _beaverId = 120;
+ _gameSys->insertSequence(0x107CA, _beaverId, 0x1BC, 99,
+ kSeqSyncWait, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY);
+ _gameSys->insertSequence(0x1B7, 99, 0, 0, kSeqNone, 0, 0, 0);
+ _beaverSequenceDatNum = 1;
+ _beaverSequenceId = 0x7CA;
+ setFlag(0);
+ _s03_nextPlatSequenceId = -1;
+ scene03_updateHotspots();
+ break;
+ case kASHypnotizePlat:
+ playGnapBrainPulsating(0, 0);
+ addFullScreenSprite(0x106, 255);
+ _gameSys->setAnimation(0x1C9, 256, 1);
+ _gameSys->insertSequence(0x1C9, 256, 0, 0, kSeqNone, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(1) != 2)
+ gameUpdateTick();
+ removeFullScreenSprite();
+ _gameSys->setAnimation(0x1BA, 99, 1);
+ _gameSys->insertSequence(0x1BA, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, 32, 0, 0, 0);
+ _beaverSequenceDatNum = 0;
+ _beaverSequenceId = 0x1BA;
+ _gnapActionStatus = -1;
+ _s03_platypusHypnotized = true;
+ scene03_updateHotspots();
+ break;
+ case kASHypnotizeScaredPlat:
+ playGnapBrainPulsating(0, 0);
+ _gameSys->insertSequence(0x1BF, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, 32, 0, 0, 0);
+ _gameSys->setAnimation(0x1BF, 99, 1);
+ while (_gameSys->getAnimationStatus(1) != 2)
+ gameUpdateTick();
+ addFullScreenSprite(0x106, 255);
+ _gameSys->setAnimation(0x1C9, 256, 1);
+ _gameSys->insertSequence(0x1C9, 256, 0, 0, kSeqNone, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(1) != 2)
+ gameUpdateTick();
+ removeFullScreenSprite();
+ _gameSys->setAnimation(0x1BA, 99, 1);
+ _gameSys->insertSequence(0x1BA, 99, 447, 99, kSeqSyncWait, 0, 0, 0);
+ _beaverSequenceDatNum = 0;
+ _beaverSequenceId = 0x1BA;
+ _gnapActionStatus = -1;
+ _s03_platypusHypnotized = true;
+ scene03_updateHotspots();
+ break;
+ case kASGrabPlatypus:
+ _s03_nextPlatSequenceId = 0x1BD;
+ _s03_platypusHypnotized = false;
+ break;
+ case kASGrabScaredPlatypus:
+ _s03_nextPlatSequenceId = 0x1C0;
+ _s03_platypusHypnotized = false;
+ break;
+ case kASGrabCreek:
+ _gameSys->insertSequence(0x1B4, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x1B4, _gnapId, 0);
+ _gnapSequenceId = 0x1B4;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = kASGrabCreekDone;
+ break;
+ default:
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ if (_s03_nextPlatSequenceId == 0x1BD || _s03_nextPlatSequenceId == 0x1C0) {
+ _gameSys->setAnimation(0, 0, 1);
+ _s03_platypusScared = true;
+ _gameSys->insertSequence(0x1B5, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(_s03_nextPlatSequenceId, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x1B5;
+ _gnapSequenceDatNum = 0;
+ _gnapIdleFacing = 0;
+ _beaverSequenceId = _s03_nextPlatSequenceId;
+ _beaverSequenceDatNum = 0;
+ _gameSys->setAnimation(_s03_nextPlatSequenceId, 99, 1);
+ _s03_nextPlatSequenceId = -1;
+ _gnapActionStatus = -1;
+ } else if (_s03_nextPlatSequenceId == 0x1BC) {
+ _gnapX = 3;
+ _gnapY = 6;
+ _gameSys->insertSequence(0x1B6, 120, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x1BC, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x1BC, 99, 0);
+ _gnapId = 20 * _gnapY;
+ _gnapSequenceId = 0x1B6;
+ _gnapSequenceDatNum = 0;
+ _gnapIdleFacing = 0;
+ _gnapActionStatus = kASFreePlatypusDone;
+ _s03_nextPlatSequenceId = -1;
+ } else if (_s03_nextPlatSequenceId == 0x1C2 && !_s03_platypusScared) {
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->insertSequence(0x1C2, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, kSeqSyncWait, 0, 0, 0);
+ _beaverSequenceId = 0x1C2;
+ _beaverSequenceDatNum = 0;
+ _gameSys->setAnimation(0x1C2, 99, 1);
+ _s03_nextPlatSequenceId = -1;
+ } else if (_s03_nextPlatSequenceId == -1 && _s03_platypusScared && !_s03_platypusHypnotized) {
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0x1BE, 99, 1);
+ _gameSys->insertSequence(0x1BE, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, kSeqSyncWait, 0, 0, 0);
+ _beaverSequenceId = 0x1BE;
+ _beaverSequenceDatNum = 0;
+ _s03_nextPlatSequenceId = -1;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2 && _s03_nextFrogSequenceId != -1) {
+ _gameSys->setAnimation(_s03_nextFrogSequenceId, 253, 2);
+ _gameSys->insertSequence(_s03_nextFrogSequenceId, 253, _s03_currFrogSequenceId, 253, kSeqSyncWait, 0, 0, 0);
+ _s03_currFrogSequenceId = _s03_nextFrogSequenceId;
+ _s03_nextFrogSequenceId = -1;
+ }
+
+ if (_gameSys->getAnimationStatus(5) == 2) {
+ _gameSys->setAnimation(0, 0, 5);
+ invAdd(kItemGrass);
+ setGrabCursorSprite(kItemGrass);
+ setFlag(6);
+ scene03_updateHotspots();
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene04.cpp b/engines/gnap/scenes/scene04.cpp
new file mode 100644
index 0000000000..bc5ee855d3
--- /dev/null
+++ b/engines/gnap/scenes/scene04.cpp
@@ -0,0 +1,571 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSTwig = 1,
+ kHSDog = 2,
+ kHSAxe = 3,
+ kHSDoor = 4,
+ kHSExitTruck = 5,
+ kHSDevice = 6,
+ kHSWindow = 7,
+ kHSExitBarn = 8,
+ kHSWalkArea1 = 9,
+ kHSWalkArea2 = 10
+};
+
+enum {
+ kASOpenDoor = 1,
+ kASGetKeyFirst = 2,
+ kASGetKeyAnother = 3,
+ kASLeaveScene = 4,
+ kASGetKeyFirstDone = 6,
+ kASGetKeyFirst2 = 7,
+ kASGetKeyAnother2 = 8,
+ kASGetKeyAnotherDone = 9,
+ kASOpenDoorDone = 10,
+ kASGrabDog = 12,
+ kASGrabAxe = 13
+};
+
+int GnapEngine::scene04_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0, 0, 2);
+ return 0x214;
+}
+
+void GnapEngine::scene04_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED | SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSTwig, 690, 394, 769, 452, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 6);
+ setHotspot(kHSDog, 550, 442, 680, 552, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 8);
+ setHotspot(kHSAxe, 574, 342, 680, 412, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 7);
+ setHotspot(kHSDoor, 300, 244, 386, 410, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 7);
+ setHotspot(kHSExitTruck, 226, 580, 688, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9);
+ setHotspot(kHSWindow, 121, 295, 237, 342, SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 7);
+ setHotspot(kHSExitBarn, 585, 154, 800, 276, SF_EXIT_U_CURSOR, 10, 8);
+ setHotspot(kHSWalkArea1, 0, 0, 562, 461);
+ setHotspot(kHSWalkArea2, 562, 0, 800, 500);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(0))
+ _hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR;
+ if (isFlag(3))
+ _hotspots[kHSTwig].flags = SF_WALKABLE | SF_DISABLED;
+ if (isFlag(26) || _cursorValue == 1)
+ _hotspots[kHSAxe].flags = SF_DISABLED;
+ _hotspotsCount = 11;
+}
+
+void GnapEngine::scene04_run() {
+
+ playSound(0x1091C, 1);
+ startSoundTimerC(4);
+
+ _gameSys->insertSequence(0x210, 139 - _s04_dogIdCtr, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s04_currDogSequenceId = 0x210;
+ _s04_nextDogSequenceId = -1;
+
+ _gameSys->setAnimation(0x210, 139 - _s04_dogIdCtr, 3);
+ _s04_dogIdCtr = (_s04_dogIdCtr + 1) % 2;
+ _timers[6] = getRandom(20) + 60;
+ _timers[5] = getRandom(150) + 300;
+ _timers[7] = getRandom(150) + 200;
+ _timers[8] = getRandom(150) + 400;
+
+ if (!isFlag(26) && _cursorValue == 4)
+ _gameSys->insertSequence(0x212, 100, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (!isFlag(3))
+ _gameSys->insertSequence(0x1FE, 100, 0, 0, kSeqNone, 0, 0, 0);
+
+ queueInsertDeviceIcon();
+
+ if (isFlag(10)) {
+ _timers[3] = 300;
+ // TODO setCursor((LPCSTR)IDC_WAIT);
+ setGrabCursorSprite(kItemKeys);
+ _gnapX = 4;
+ _gnapY = 7;
+ _gnapId = 140;
+ _platX = 6;
+ _platY = 7;
+ _beaverId = 141;
+ _gameSys->insertSequence(0x107B5, 140, 0, 0, kSeqNone, 0, 300 - _gnapGridX, 336 - _gnapGridY);
+ _gameSys->insertSequence(0x20C, 141, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x208, 121, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x209, 121, 0x208, 121, kSeqSyncWait, 0, 0, 0);
+ endSceneInit();
+ invRemove(kItemDisguise);
+ invAdd(kItemKeys);
+ setFlag(5);
+ clearFlag(10);
+ _beaverSequenceId = 0x20C;
+ _beaverSequenceDatNum = 0;
+ _beaverFacing = 1;
+ _gnapSequenceId = 0x7B5;
+ _gnapSequenceDatNum = 1;
+ _gameSys->waitForUpdate();
+ } else {
+ _gameSys->insertSequence(0x209, 121, 0, 0, kSeqNone, 0, 0, 0);
+ if (_prevSceneNum == 2) {
+ initGnapPos(5, 11, 7);
+ if (isFlag(0))
+ initBeaverPos(6, 11, 5);
+ endSceneInit();
+ if (isFlag(0))
+ platypusWalkTo(5, 8, -1, 0x107C2, 1);
+ gnapWalkTo(6, 9, -1, 0x107BA, 1);
+ } else if (_prevSceneNum == 38) {
+ initGnapPos(5, 7, 1);
+ initBeaverPos(4, 7, 0);
+ endSceneInit();
+ } else {
+ initGnapPos(12, 9, 1);
+ if (isFlag(0))
+ initBeaverPos(12, 8, 0);
+ endSceneInit();
+ if (isFlag(0))
+ platypusWalkTo(9, 8, -1, 0x107C2, 1);
+ gnapWalkTo(9, 9, -1, 0x107BA, 1);
+ }
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 4, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene04_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0 && isFlag(0)) {
+ if (_grabCursorSpriteIndex == kItemDisguise) {
+ gnapUseDisguiseOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(5))
+ playGnapMoan1(_platX, _platY);
+ else
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ if (_cursorValue == 4)
+ gnapKissPlatypus(0);
+ else
+ playGnapMoan1(_platX, _platY);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSTwig:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowItem(_grabCursorSpriteIndex, 9, 6);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y);
+ break;
+ case GRAB_CURSOR:
+ playGnapPullOutDevice(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y);
+ playGnapUseDevice(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y);
+ _gameSys->insertSequence(0x1FD, 100, 510, 100, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x1FD, 100, 2);
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSAxe:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 9, 5);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan2(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y);
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASGrabAxe;
+ setFlag(26);
+ scene04_updateHotspots();
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSDog:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 9, 7);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (gnapWalkTo(_gnapX, _gnapY, 0, -1, 1)) {
+ playGnapMoan2(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y);
+ _s04_nextDogSequenceId = 0x20F;
+ }
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 1;
+ if (gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1))
+ _gnapActionStatus = kASGrabDog;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 1;
+ if (gnapWalkTo(_gnapX, _gnapY, 0, -1, 1)) {
+ playGnapBrainPulsating(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y);
+ _s04_nextDogSequenceId = 0x20E;
+ }
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSDoor:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 4, 3);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapScratchingHead(4, 3);
+ break;
+ case GRAB_CURSOR:
+ if (_cursorValue == 1) {
+ gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 0x107BC, 1);
+ _gnapActionStatus = kASOpenDoor;
+ _timers[5] = 300;
+ _gnapIdleFacing = 5;
+ } else {
+ _isLeavingScene = true;
+ gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 0x107BC, 1);
+ _gnapActionStatus = kASLeaveScene;
+ _newSceneNum = 38;
+ }
+ break;
+ case TALK_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitTruck:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[5].x, _hotspotsWalkPos[5].y, 0, 0x107AE, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(0))
+ platypusWalkTo(_hotspotsWalkPos[5].x, _hotspotsWalkPos[5].y, -1, 0x107C7, 1);
+ if (_cursorValue == 1)
+ _newSceneNum = 2;
+ else
+ _newSceneNum = 33;
+ }
+ break;
+
+ case kHSWindow:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 2, 3);
+ } else if (isFlag(5)) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (gnapWalkTo(_hotspotsWalkPos[7].x, _hotspotsWalkPos[7].y, 0, getGnapSequenceId(gskIdle, 10, 2) | 0x10000, 1)) {
+ if (_s04_triedWindow) {
+ _gnapActionStatus = kASGetKeyAnother;
+ } else {
+ _gnapActionStatus = kASGetKeyFirst;
+ _s04_triedWindow = true;
+ }
+ }
+ break;
+ case GRAB_CURSOR:
+ playGnapScratchingHead(_hotspotsWalkPos[7].x, _hotspotsWalkPos[7].y);
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitBarn:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[8].x, _hotspotsWalkPos[8].y, 0, 0x107AB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(0))
+ platypusWalkTo(_hotspotsWalkPos[8].x, _hotspotsWalkPos[8].y + 1, -1, 0x107C1, 1);
+ if (_cursorValue == 1)
+ _newSceneNum = 5;
+ else
+ _newSceneNum = 35;
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene04_updateAnimations();
+
+ if (!isSoundPlaying(0x1091C))
+ playSound(0x1091C, 1);
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0 && isFlag(0))
+ beaverSub426234();
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence2();
+ if (!_timers[5]) {
+ _timers[5] = getRandom(150) + 300;
+ if (_gnapActionStatus < 0)
+ _gameSys->insertSequence(0x20D, 79, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ if (!_timers[7]) {
+ _timers[7] = getRandom(150) + 200;
+ _gameSys->insertSequence(0x1FC, 59, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ if (!_timers[6]) {
+ _timers[6] = getRandom(20) + 60;
+ if (_s04_nextDogSequenceId == -1)
+ _s04_nextDogSequenceId = 0x210;
+ }
+ if (!_timers[8]) {
+ _timers[8] = getRandom(150) + 400;
+ _gameSys->insertSequence(0x213, 20, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ playSoundC();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene04_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene04_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ case kASOpenDoor:
+ _gameSys->insertSequence(0x205, _gnapId, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x207, 121, 521, 121, kSeqSyncWait, 0, 0, 0);
+ _gnapX = 6;
+ _gnapY = 7;
+ _gameSys->insertSequence(0x107B5, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ kSeqSyncWait, getSequenceTotalDuration(0x205) - 1, 450 - _gnapGridX, 336 - _gnapGridY);
+ _gameSys->setAnimation(0x107B5, _gnapId, 0);
+ _gnapSequenceId = 0x7B5;
+ _gnapSequenceDatNum = 1;
+ _gnapActionStatus = kASOpenDoorDone;
+ break;
+ case kASOpenDoorDone:
+ _gameSys->insertSequence(0x209, 121, 0x207, 121, kSeqSyncWait, 0, 0, 0);
+ _gnapActionStatus = -1;
+ break;
+ case kASGetKeyFirst:
+ _gameSys->insertSequence(0x204, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x204, _gnapId, 0);
+ _gnapSequenceId = 0x204;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = kASGetKeyFirst2;
+ break;
+ case kASGetKeyFirst2:
+ _gameSys->insertSequence(0x206, 255, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x1FF, 256, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x20B, 256, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->setAnimation(0x20B, 256, 0);
+ _gnapSequenceId = 0x206;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = kASGetKeyFirstDone;
+ break;
+ case kASGetKeyFirstDone:
+ _gameSys->requestRemoveSequence(0x1FF, 256);
+ _gameSys->requestRemoveSequence(0x20B, 256);
+ _gameSys->insertSequence(0x107B5, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), 255,
+ kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gnapIdleFacing = 1;
+ _gnapSequenceId = 0x7B5;
+ _gnapSequenceDatNum = 1;
+ _gnapActionStatus = -1;
+ break;
+ case kASGetKeyAnother:
+ _gameSys->insertSequence(0x202, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x202, _gnapId, 0);
+ _gnapSequenceId = 0x202;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = kASGetKeyAnother2;
+ break;
+ case kASGetKeyAnother2:
+ _gameSys->insertSequence(0x203, 255, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x1FF, 256, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x20A, 256, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->setAnimation(0x20A, 256, 0);
+ _gnapSequenceId = 0x203;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = kASGetKeyAnotherDone;
+ break;
+ case kASGetKeyAnotherDone:
+ _gameSys->removeSequence(0x1FF, 256, 1);
+ _gameSys->removeSequence(0x20A, 256, 1);
+ _gameSys->insertSequence(0x107B5, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), 255,
+ kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gnapSequenceId = 0x7B5;
+ _gnapSequenceDatNum = 1;
+ _gnapIdleFacing = 1;
+ _gnapActionStatus = -1;
+ break;
+ case kASGrabDog:
+ _s04_nextDogSequenceId = 0x201;
+ break;
+ case kASGrabAxe:
+ _gameSys->insertSequence(0x211, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->requestRemoveSequence(0x212, 100);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x211;
+ _gnapActionStatus = -1;
+ break;
+ default:
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ _gameSys->setAnimation(0, 0, 2);
+ invAdd(kItemTwig);
+ setGrabCursorSprite(kItemTwig);
+ setFlag(3);
+ scene04_updateHotspots();
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ if (_s04_nextDogSequenceId == 0x201) {
+ _gameSys->insertSequence(_s04_nextDogSequenceId, 139 - _s04_dogIdCtr,
+ _s04_currDogSequenceId, 139 - (_s04_dogIdCtr + 1) % 2,
+ kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x200, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s04_nextDogSequenceId, 139 - _s04_dogIdCtr, 3);
+ _s04_dogIdCtr = (_s04_dogIdCtr + 1) % 2;
+ _s04_currDogSequenceId = 0x201;
+ _gnapSequenceId = 0x200;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = -1;
+ _timers[6] = getRandom(20) + 60;
+ _s04_nextDogSequenceId = -1;
+ } else if (_s04_nextDogSequenceId != -1) {
+ _gameSys->insertSequence(_s04_nextDogSequenceId, 139 - _s04_dogIdCtr,
+ _s04_currDogSequenceId, 139 - (_s04_dogIdCtr + 1) % 2,
+ kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s04_nextDogSequenceId, 139 - _s04_dogIdCtr, 3);
+ _s04_dogIdCtr = (_s04_dogIdCtr + 1) % 2;
+ _s04_currDogSequenceId = _s04_nextDogSequenceId;
+ _s04_nextDogSequenceId = -1;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene05.cpp b/engines/gnap/scenes/scene05.cpp
new file mode 100644
index 0000000000..fdc6ba16fe
--- /dev/null
+++ b/engines/gnap/scenes/scene05.cpp
@@ -0,0 +1,467 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSHaystack = 1,
+ kHSPadlock = 2,
+ kHSLadder = 3,
+ kHSExitHouse = 4,
+ kHSChicken = 5,
+ kHSDevice = 6,
+ kHSWalkArea1 = 7,
+ kHSWalkArea2 = 8,
+ kHSWalkArea3 = 9
+};
+
+enum {
+ kASPlatSearchHaystack = 0,
+ kASTryPickPadlock = 1,
+ kASPickPadlock = 2,
+ kASTalkChicken = 3,
+ kASGrabChicken = 4,
+ kASGrabLadder = 5,
+ kASEnterBarn = 6,
+ kASUseTwigWithChicken = 11,
+ kASLeaveScene = 12
+};
+
+int GnapEngine::scene05_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0, 0, 3);
+ return isFlag(7) ? 0x151 : 0x150;
+}
+
+void GnapEngine::scene05_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED | SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSHaystack, 236, 366, 372, 442, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 7);
+ setHotspot(kHSPadlock, 386, 230, 626, 481, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 7);
+ setHotspot(kHSLadder, 108, 222, 207, 444, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7);
+ setHotspot(kHSExitHouse, 0, 395, 20, 600, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 8);
+ setHotspot(kHSChicken, 612, 462, 722, 564, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8);
+ setHotspot(kHSWalkArea1, 104, 0, 421, 480);
+ setHotspot(kHSWalkArea2, 422, 0, 800, 487);
+ setHotspot(kHSWalkArea3, 0, 0, 104, 499);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(0))
+ _hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR;
+ if (isFlag(7))
+ _hotspots[kHSPadlock].flags = SF_EXIT_U_CURSOR;
+ _hotspotsCount = 10;
+}
+
+void GnapEngine::scene05_run() {
+
+ playSound(0x1091C, 1);
+ startSoundTimerC(7);
+
+ _s05_currChickenSequenceId = 0x142;
+ _gameSys->setAnimation(0x142, 100, 3);
+ _gameSys->insertSequence(0x142, 100, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s05_nextChickenSequenceId = -1;
+
+ _timers[5] = getRandom(10) + 30;
+ _timers[6] = getRandom(150) + 300;
+
+ if (isFlag(7))
+ _gameSys->insertSequence(0x14A, 141, 0, 0, kSeqNone, 0, 0, 0);
+
+ queueInsertDeviceIcon();
+
+ if (_prevSceneNum != 6 && _prevSceneNum != 36) {
+ initGnapPos(-1, 8, 1);
+ if (isFlag(0))
+ initBeaverPos(-1, 9, 0);
+ endSceneInit();
+ if (isFlag(0))
+ platypusWalkTo(2, 8, -1, 0x107C2, 1);
+ gnapWalkTo(2, 9, -1, 0x107B9, 1);
+ } else {
+ initGnapPos(6, 8, 1);
+ if (isFlag(0))
+ initBeaverPos(7, 9, 0);
+ endSceneInit();
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 12, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene05_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0 && isFlag(0)) {
+ if (_grabCursorSpriteIndex == kItemDisguise) {
+ gnapUseDisguiseOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(5))
+ playGnapMoan1(_platX, _platY);
+ else
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSHaystack:
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[1].x - 2, _hotspotsWalkPos[1].y, 4, 5);
+ } else if (isFlag(2)) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y - 1);
+ break;
+ case GRAB_CURSOR:
+ case TALK_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case PLAT_CURSOR:
+ if (isFlag(0)) {
+ gnapUseDeviceOnBeaver();
+ if (platypusWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 1, 0x107C2, 1)) {
+ _beaverActionStatus = kASPlatSearchHaystack;
+ _beaverFacing = 4;
+ }
+ if (_gnapX == 4 && (_gnapY == 8 || _gnapY == 7))
+ gnapWalkStep();
+ playGnapIdle(_platX, _platY);
+ }
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSChicken:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemTwig) {
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y + 1,
+ 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASUseTwigWithChicken;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y + 1, 9, 7);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan2(9, 7);
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 1;
+ gnapWalkTo(_hotspotsWalkPos[5].x, _hotspotsWalkPos[5].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASGrabChicken;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 1;
+ gnapWalkTo(_hotspotsWalkPos[5].x, _hotspotsWalkPos[5].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkChicken;
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSLadder:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 2, 5);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan2(2, 4);
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 3;
+ gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASGrabLadder;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSPadlock:
+ if (isFlag(7)) {
+ _isLeavingScene = true;
+ gnapWalkTo(_hotspotsWalkPos[2].x - 1, _hotspotsWalkPos[2].y + 1, 0, -1, 1);
+ _gnapActionStatus = kASEnterBarn;
+ if (_cursorValue == 1)
+ _newSceneNum = 6;
+ else
+ _newSceneNum = 36;
+ } else if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemNeedle) {
+ if (gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0,
+ getGnapSequenceId(gskIdle, _hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y) | 0x10000, 1))
+ _gnapActionStatus = kASPickPadlock;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 7, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(7, 4);
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y,
+ 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTryPickPadlock;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitHouse:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 0x107AF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(0))
+ platypusWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y + 1, -1, 0x107C7, 1);
+ if (_cursorValue == 1)
+ _newSceneNum = 4;
+ else
+ _newSceneNum = 37;
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ case kHSWalkArea3:
+ // Nothing
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene05_updateAnimations();
+
+ if (!isSoundPlaying(0x1091C))
+ playSound(0x1091C, 1);
+
+ if (!_isLeavingScene) {
+ if (isFlag(0))
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!_timers[5]) {
+ _timers[5] = getRandom(20) + 30;
+ if (_gnapActionStatus != kASTalkChicken && _s05_nextChickenSequenceId == -1) {
+ if (getRandom(4) != 0)
+ _s05_nextChickenSequenceId = 0x142;
+ else
+ _s05_nextChickenSequenceId = 0x143;
+ }
+ }
+ if (!_timers[6]) {
+ _timers[6] = getRandom(150) + 300;
+ if (_gnapActionStatus < 0)
+ _gameSys->insertSequence(0x149, 39, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ playSoundC();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene05_updateHotspots();
+ _timers[5] = getRandom(20) + 30;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene05_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ _gnapActionStatus = -1;
+ break;
+ case kASTryPickPadlock:
+ _gameSys->insertSequence(0x148, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x148;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = -1;
+ break;
+ case kASPickPadlock:
+ _gameSys->setAnimation(0x147, _gnapId, 0);
+ _gameSys->insertSequence(0x147, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x147;
+ _gnapSequenceDatNum = 0;
+ setFlag(7);
+ setFlag(11);
+ setGrabCursorSprite(-1);
+ _newSceneNum = 6;
+ _timers[2] = 100;
+ invRemove(kItemNeedle);
+ _gnapActionStatus = kASLeaveScene;
+ break;
+ case kASTalkChicken:
+ _s05_nextChickenSequenceId = 0x144;
+ _gnapActionStatus = -1;
+ break;
+ case kASGrabChicken:
+ _s05_nextChickenSequenceId = 0x14B;
+ break;
+ case kASGrabLadder:
+ while (_gameSys->isSequenceActive(0x149, 39))
+ gameUpdateTick();
+ _gameSys->insertSequence(0x14E, _gnapId + 1, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x14D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x14D;
+ _gnapSequenceDatNum = 0;
+ _timers[2] = 200;
+ _timers[6] = 300;
+ _gnapActionStatus = -1;
+ break;
+ case kASEnterBarn:
+ _gameSys->insertSequence(0x107B1, 1,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gameSys->setAnimation(0x107B1, 1, 0);
+ _gnapActionStatus = kASLeaveScene;
+ break;
+ case kASUseTwigWithChicken:
+ playGnapShowItem(5, 0, 0);
+ _s05_nextChickenSequenceId = 0x14F;
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ if (_beaverSequenceId == 0x146) {
+ _platX = 4;
+ _platY = 8;
+ _gameSys->insertSequence(0x107C1, 160, 0x146, 256, kSeqSyncWait, 0, 300 - _platGridX, 384 - _platGridY);
+ _beaverSequenceId = 0x7C1;
+ _beaverSequenceDatNum = 1;
+ _beaverId = 20 * _platY;
+ invAdd(kItemNeedle);
+ setFlag(2);
+ setGrabCursorSprite(kItemNeedle);
+ showCursor();
+ _timers[1] = 30;
+ _beaverActionStatus = -1;
+ }
+ if (_beaverActionStatus == kASPlatSearchHaystack) {
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->insertSequence(0x145, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x146, 256, 0x145, _beaverId, kSeqSyncWait, 0, 0, 0);
+ hideCursor();
+ setGrabCursorSprite(-1);
+ _beaverSequenceId = 0x146;
+ _beaverSequenceDatNum = 0;
+ _gameSys->setAnimation(0x146, 256, 1);
+ _timers[1] = 300;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ if (_s05_nextChickenSequenceId == 0x14B) {
+ _gameSys->setAnimation(_s05_nextChickenSequenceId, 100, 3);
+ _gameSys->insertSequence(_s05_nextChickenSequenceId, 100, _s05_currChickenSequenceId, 100, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x14C, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x14C;
+ _s05_currChickenSequenceId = _s05_nextChickenSequenceId;
+ _s05_nextChickenSequenceId = -1;
+ _gnapActionStatus = -1;
+ } else if (_s05_nextChickenSequenceId != -1) {
+ _gameSys->setAnimation(_s05_nextChickenSequenceId, 100, 3);
+ _gameSys->insertSequence(_s05_nextChickenSequenceId, 100, _s05_currChickenSequenceId, 100, kSeqSyncWait, 0, 0, 0);
+ _s05_currChickenSequenceId = _s05_nextChickenSequenceId;
+ _s05_nextChickenSequenceId = -1;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene06.cpp b/engines/gnap/scenes/scene06.cpp
new file mode 100644
index 0000000000..3878d3514e
--- /dev/null
+++ b/engines/gnap/scenes/scene06.cpp
@@ -0,0 +1,446 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSGas = 1,
+ kHSLadder = 2,
+ kHSHorse = 3,
+ kHSExitOutsideBarn = 4,
+ kHSDevice = 5,
+ kHSWalkArea1 = 6,
+ kHSWalkArea2 = 7,
+ kHSWalkArea3 = 8,
+ kHSWalkArea4 = 9,
+ kHSWalkArea5 = 10
+};
+
+enum {
+ kASTryToGetGas = 0,
+ kASTryToClimbLadder = 1,
+ kASTryToClimbLadderDone = 2,
+ kASTalkToHorse = 3,
+ kASUseTwigOnHorse = 4,
+ kASLeaveScene = 5
+};
+
+int GnapEngine::scene06_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0, 0, 2);
+ if (isFlag(11)) {
+ playSound(0x11B, 0);
+ clearFlag(11);
+ }
+ return 0x101;
+}
+
+void GnapEngine::scene06_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSGas, 300, 120, 440, 232, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7);
+ setHotspot(kHSLadder, 497, 222, 614, 492, SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 8);
+ setHotspot(kHSHorse, 90, 226, 259, 376, SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7);
+ setHotspot(kHSExitOutsideBarn, 226, 580, 688, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 10);
+ setHotspot(kHSWalkArea1, 0, 0, 200, 515);
+ setHotspot(kHSWalkArea2, 200, 0, 285, 499);
+ setHotspot(kHSWalkArea3, 688, 0, 800, 499);
+ setHotspot(kHSWalkArea4, 475, 469, 800, 505);
+ setHotspot(kHSWalkArea5, 0, 0, 800, 504);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(29))
+ _hotspots[kHSLadder].flags = SF_DISABLED;
+ if (_cursorValue == 4) {
+ _hotspots[kHSLadder].flags = SF_DISABLED;
+ _hotspots[kHSGas].flags = SF_DISABLED;
+ }
+ _hotspotsCount = 11;
+}
+
+void GnapEngine::scene06_run() {
+ bool triedDeviceOnGas = false;
+
+ startSoundTimerC(7);
+
+ _s06_horseTurnedBack = false;
+ _gameSys->insertSequence(0xF1, 120, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s06_currHorseSequenceId = 0xF1;
+ _s06_nextHorseSequenceId = -1;
+
+ _gameSys->setAnimation(0xF1, 120, 2);
+
+ _timers[4] = getRandom(40) + 25;
+
+ if (isFlag(4))
+ _gameSys->insertSequence(0xF7, 20, 0, 0, kSeqNone, 0, 0, 0);
+ else
+ _gameSys->insertSequence(0xF8, 20, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (!isFlag(29) && _cursorValue != 4)
+ _gameSys->insertSequence(0xFE, 20, 0, 0, kSeqNone, 0, 0, 0);
+
+ queueInsertDeviceIcon();
+
+ initGnapPos(5, 12, 1);
+ initBeaverPos(6, 12, 0);
+ endSceneInit();
+
+ platypusWalkTo(6, 8, -1, 0x107C2, 1);
+ gnapWalkTo(5, 8, -1, 0x107B9, 1);
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 5, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene06_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemDisguise) {
+ gnapUseDisguiseOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(5))
+ playGnapMoan1(_platX, _platY);
+ else
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSGas:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 5, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(5, 0);
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(4)) {
+ playGnapImpossible(0, 0);
+ } else if (triedDeviceOnGas) {
+ _hotspots[kHSWalkArea5].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 0, 0x107BC, 1);
+ _hotspots[kHSWalkArea5].flags &= ~SF_WALKABLE;
+ _gnapActionStatus = kASTryToGetGas;
+ } else {
+ triedDeviceOnGas = true;
+ playGnapPullOutDeviceNonWorking(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y);
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ if (isFlag(4))
+ playGnapImpossible(0, 0);
+ else
+ playGnapScratchingHead(5, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSLadder:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 8, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(8, 4);
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(29))
+ playGnapImpossible(0, 0);
+ else {
+ gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, 0x107BB, 1);
+ _gnapActionStatus = kASTryToClimbLadder;
+ setFlag(29);
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSHorse:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemTwig && _s06_horseTurnedBack) {
+ _hotspots[kHSWalkArea5].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, 0x107BC, 1);
+ _hotspots[kHSWalkArea5].flags &= ~SF_WALKABLE;
+ _gnapIdleFacing = 5;
+ platypusWalkTo(6, 8, 1, 0x107C2, 1);
+ _beaverFacing = 0;
+ _gnapActionStatus = kASUseTwigOnHorse;
+ setGrabCursorSprite(-1);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 3, 2);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(3, 2);
+ break;
+ case TALK_CURSOR:
+ if (_s06_horseTurnedBack) {
+ gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskBrainPulsating, 3, 2) | 0x10000, 1);
+ } else {
+ _gnapIdleFacing = 3;
+ _hotspots[kHSWalkArea5].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _hotspots[kHSWalkArea5].flags &= ~SF_WALKABLE;
+ _gnapActionStatus = kASTalkToHorse;
+ }
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitOutsideBarn:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 0x107AE, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (_cursorValue == 1)
+ _newSceneNum = 5;
+ else
+ _newSceneNum = 35;
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ case kHSWalkArea4:
+ case kHSWalkArea5:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+
+ scene06_updateAnimations();
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0)
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(40) + 25;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s06_nextHorseSequenceId == -1) {
+ if (_s06_horseTurnedBack) {
+ _s06_nextHorseSequenceId = 0xF5;
+ } else {
+ switch (getRandom(5)) {
+ case 0:
+ case 1:
+ case 2:
+ _s06_nextHorseSequenceId = 0xF1;
+ break;
+ case 3:
+ _s06_nextHorseSequenceId = 0xF3;
+ break;
+ case 4:
+ _s06_nextHorseSequenceId = 0xF4;
+ break;
+ }
+ }
+ }
+ }
+ playSoundC();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene06_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene06_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ _gnapActionStatus = -1;
+ break;
+ case kASTryToGetGas:
+ _gameSys->insertSequence(0xFC, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0xFC;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = -1;
+ break;
+ case kASTryToClimbLadder:
+ _gameSys->insertSequence(0xFF, 20, 0xFE, 20, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0xFD, _gnapId, 0);
+ _gameSys->insertSequence(0xFD, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0xFD;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = kASTryToClimbLadderDone;
+ break;
+ case kASTryToClimbLadderDone:
+ _gnapX = 6;
+ _gnapY = 7;
+ _gnapActionStatus = -1;
+ break;
+ case kASTalkToHorse:
+ _s06_nextHorseSequenceId = 0xF6;
+ break;
+ case kASUseTwigOnHorse:
+ _s06_nextPlatSequenceId = 0xFB;
+ break;
+ default:
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ _gameSys->setAnimation(0, 0, 1);
+ if (_beaverSequenceId == 0xFA) {
+ _gameSys->setAnimation(0, 0, 1);
+ invAdd(kItemGas);
+ setFlag(29);
+ _hotspots[kHSLadder].flags = SF_DISABLED;
+ setGrabCursorSprite(kItemGas);
+ _beaverActionStatus = -1;
+ _platX = 6;
+ _platY = 8;
+ _gameSys->insertSequence(0x107C1, _beaverId, 0, 0, kSeqNone, 0, 450 - _platGridX, 384 - _platGridY);
+ _beaverSequenceId = 0x7C1;
+ _beaverSequenceDatNum = 1;
+ setFlag(4);
+ _gnapActionStatus = -1;
+ showCursor();
+ }
+ if (_s06_nextPlatSequenceId == 0xFB) {
+ _gameSys->setAnimation(0, 0, 1);
+ _s06_nextHorseSequenceId = 0xF2;
+ _beaverActionStatus = 6;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2 && _s06_nextHorseSequenceId != -1) {
+ switch (_s06_nextHorseSequenceId) {
+ case 0xF2:
+ setGrabCursorSprite(-1);
+ hideCursor();
+ _gameSys->setAnimation(0xFA, 256, 1);
+ _gameSys->insertSequence(0xF2, 120, _s06_currHorseSequenceId, 120, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x100, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xF7, 20, 0xF8, 20, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xFB, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xFA, 256, 0xFB, _beaverId, kSeqSyncWait, 0, 0, 0);
+ _beaverSequenceId = 0xFA;
+ _beaverSequenceDatNum = 0;
+ _gameSys->insertSequence(0x107B7, _gnapId, 0x100, _gnapId,
+ kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gnapSequenceId = 0x7B7;
+ _gnapSequenceDatNum = 1;
+ _s06_currHorseSequenceId = _s06_nextHorseSequenceId;
+ _s06_nextHorseSequenceId = -1;
+ _s06_nextPlatSequenceId = -1;
+ invRemove(kItemTwig);
+ break;
+ case 0xF6:
+ _gameSys->setAnimation(_s06_nextHorseSequenceId, 120, 2);
+ _gameSys->insertSequence(0xF6, 120, _s06_currHorseSequenceId, 120, kSeqSyncWait, 0, 0, 0);
+ _s06_horseTurnedBack = true;
+ _s06_currHorseSequenceId = _s06_nextHorseSequenceId;
+ _s06_nextHorseSequenceId = -1;
+ _gnapActionStatus = -1;
+ break;
+ default:
+ _gameSys->setAnimation(_s06_nextHorseSequenceId, 120, 2);
+ _gameSys->insertSequence(_s06_nextHorseSequenceId, 120, _s06_currHorseSequenceId, 120, kSeqSyncWait, 0, 0, 0);
+ _s06_currHorseSequenceId = _s06_nextHorseSequenceId;
+ _s06_nextHorseSequenceId = -1;
+ break;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene07.cpp b/engines/gnap/scenes/scene07.cpp
new file mode 100644
index 0000000000..9b8ee2975b
--- /dev/null
+++ b/engines/gnap/scenes/scene07.cpp
@@ -0,0 +1,275 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitHouse = 1,
+ kHSDice = 2,
+ kHSDevice = 3,
+ kHSWalkArea1 = 4,
+ kHSWalkArea2 = 5,
+ kHSWalkArea3 = 6
+};
+
+enum {
+ kASWait = 0,
+ kASLeaveScene = 1
+};
+
+int GnapEngine::scene07_init() {
+ return 0x92;
+}
+
+void GnapEngine::scene07_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitHouse, 700, 125, 799, 290, SF_EXIT_NE_CURSOR);
+ setHotspot(kHSDice, 200, 290, 270, 360, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSWalkArea1, 0, 0, 325, 445);
+ setHotspot(kHSWalkArea2, 325, 0, 799, 445, _isLeavingScene ? SF_WALKABLE : 0);
+ setHotspot(kHSWalkArea3, 160, 0, 325, 495);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(0))
+ _hotspots[kHSDice].flags = SF_DISABLED;
+ _hotspotsCount = 7;
+}
+
+void GnapEngine::scene07_run() {
+
+ queueInsertDeviceIcon();
+ _gameSys->insertSequence(0x8C, 1, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0x90, 1, 0, 0, kSeqLoop, 0, 0, 0);
+
+ invRemove(kItemGas);
+ invRemove(kItemNeedle);
+
+ if (!isFlag(0))
+ _gameSys->insertSequence(0x8D, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (_prevSceneNum == 8) {
+ initGnapPos(7, 7, 3);
+ initBeaverPos(9, 7, 4);
+ endSceneInit();
+ } else {
+ _gnapX = 6;
+ _gnapY = 7;
+ _gnapId = 140;
+ _gnapSequenceId = 0x8F;
+ _gnapSequenceDatNum = 0;
+ _gnapIdleFacing = 1;
+ _gameSys->insertSequence(0x8F, 140, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0);
+ _gnapActionStatus = kASWait;
+ _platX = 3;
+ _platY = 8;
+ _beaverId = 160;
+ _beaverSequenceId = 0x91;
+ _beaverSequenceDatNum = 0;
+ _beaverFacing = 0;
+ _gameSys->insertSequence(0x91, 160, 0, 0, kSeqNone, 0, 0, 0);
+ endSceneInit();
+ }
+
+ _timers[3] = 600;
+ _timers[4] = getRandom(40) + 50;
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x10919))
+ playSound(0x10919, 1);
+
+ if (testWalk(0, 1, 8, 7, 6, 7))
+ scene07_updateHotspots();
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSPlatypus:
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ break;
+ }
+ break;
+
+ case kHSExitHouse:
+ _isLeavingScene = true;
+ if (_gnapX > 8)
+ gnapWalkTo(_gnapX, 7, 0, 0x107AD, 1);
+ else
+ gnapWalkTo(8, 7, 0, 0x107AD, 1);
+ _gnapActionStatus = kASLeaveScene;
+ break;
+
+ case kHSDice:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(4, 8, 3, 3);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ break;
+ case GRAB_CURSOR:
+ setFlag(0);
+ invAdd(kItemDice);
+ scene07_updateHotspots();
+ playGnapPullOutDevice(3, 3);
+ _gameSys->setAnimation(0x8E, 1, 2);
+ _gameSys->insertSequence(0x8E, 1, 141, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(getGnapSequenceId(gskUseDevice, 0, 0) | 0x10000, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gnapSequenceId = getGnapSequenceId(gskUseDevice, 0, 0);
+ _gnapSequenceDatNum = 1;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene07_updateHotspots();
+ _timers[4] = getRandom(40) + 50;
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ case kHSWalkArea3:
+ // Nothing
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene07_updateAnimations();
+
+ if (!_isLeavingScene) {
+ updateGnapIdleSequence();
+ if (_beaverActionStatus < 0 && _gnapActionStatus < 0) {
+ if (_timers[0]) {
+ if (!_timers[1]) {
+ _timers[1] = getRandom(20) + 30;
+ _gnapRandomValue = getRandom(20);
+ // TODO Cleanup
+ if (_beaverFacing != 0) {
+ if (_gnapRandomValue != 0 || _beaverSequenceId != 0x7CA) {
+ if (_gnapRandomValue != 1 || _beaverSequenceId != 0x7CA) {
+ if (_platY == 9)
+ playBeaverSequence(0x107CA);
+ } else {
+ playBeaverSequence(0x10845);
+ }
+ } else {
+ playBeaverSequence(0x107CC);
+ }
+ } else if (_gnapRandomValue != 0 || _beaverSequenceId != 0x7C9) {
+ if (_gnapRandomValue != 1 || _beaverSequenceId != 0x7C9) {
+ if (_platY == 9)
+ playBeaverSequence(0x107C9);
+ } else {
+ playBeaverSequence(0x10844);
+ }
+ } else {
+ playBeaverSequence(0x107CB);
+ }
+ _gameSys->setAnimation(_beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, 1);
+ }
+ } else {
+ _timers[0] = getRandom(75) + 75;
+ beaverMakeRoom();
+ }
+ } else {
+ _timers[0] = 100;
+ _timers[1] = 35;
+ }
+ sceneXX_playRandomSound(4);
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene07_updateHotspots();
+ _timers[4] = getRandom(40) + 50;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene07_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _newSceneNum = 8;
+ _sceneDone = true;
+ break;
+ }
+ _gnapActionStatus = -1;
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ _gameSys->setAnimation(0, 0, 2);
+ setGrabCursorSprite(kItemDice);
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene08.cpp b/engines/gnap/scenes/scene08.cpp
new file mode 100644
index 0000000000..a4ebf92c71
--- /dev/null
+++ b/engines/gnap/scenes/scene08.cpp
@@ -0,0 +1,527 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitBackdoor = 1,
+ kHSExitCrash = 2,
+ kHSMan = 3,
+ kHSDoor = 4,
+ kHSMeat = 5,
+ kHSBone = 6,
+ kHSToy = 7,
+ kHSWalkArea1 = 8,
+ kHSDevice = 9,
+ kHSWalkArea2 = 10
+};
+
+enum {
+ kASLeaveScene = 0,
+ kASTalkMan = 1,
+ kASLookMan = 2,
+ kASLookDog = 3,
+ kASGrabDog = 4,
+ kASTalkDog = 5,
+ kASPlatWithMan = 6,
+ kASPlatWithDog = 7
+};
+
+int GnapEngine::scene08_init() {
+ return 0x150;
+}
+
+void GnapEngine::scene08_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitBackdoor, 0, 280, 10, 400, SF_EXIT_L_CURSOR | SF_WALKABLE);
+ setHotspot(kHSExitCrash, 200, 590, 400, 599, SF_EXIT_D_CURSOR | SF_WALKABLE);
+ setHotspot(kHSMan, 510, 150, 610, 380, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSDoor, 350, 170, 500, 410, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSMeat, 405, 450, 480, 485, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSBone, 200, 405, 270, 465, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSToy, 540, 430, 615, 465, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSWalkArea1, 290, 340, -1, -1);
+ setHotspot(kHSWalkArea2, 0, 0, 799, 420);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(7))
+ _hotspots[kHSMeat].flags = SF_WALKABLE | SF_DISABLED;
+ if (isFlag(8))
+ _hotspots[kHSBone].flags = SF_WALKABLE | SF_DISABLED;
+ if (isFlag(9))
+ _hotspots[kHSToy].flags = SF_WALKABLE | SF_DISABLED;
+ _hotspotsCount = 11;
+}
+
+void GnapEngine::scene08_updateAnimationsCb() {
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ _gameSys->setAnimation(_s08_nextDogSequenceId, 100, 3);
+ _gameSys->insertSequence(_s08_nextDogSequenceId, 100, _s08_currDogSequenceId, 100, kSeqSyncWait, 0, 0, 0);
+ _s08_currDogSequenceId = _s08_nextDogSequenceId;
+ if ( _s08_nextDogSequenceId != 0x135 )
+ _s08_nextDogSequenceId = 0x134;
+ }
+}
+
+void GnapEngine::scene08_run() {
+
+ queueInsertDeviceIcon();
+
+ _gameSys->insertSequence(0x14F, 1, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0x14E, 256, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s08_currDogSequenceId = 0x135;
+ _s08_nextDogSequenceId = 0x135;
+
+ _gameSys->setAnimation(0x135, 100, 3);
+ _gameSys->insertSequence(_s08_currDogSequenceId, 100, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s08_currManSequenceId = 0x140;
+ _s08_nextManSequenceId = -1;
+
+ _gameSys->setAnimation(0x140, 100, 2);
+ _gameSys->insertSequence(_s08_currManSequenceId, 100, 0, 0, kSeqNone, 0, 0, 0);
+
+ _timers[4] = getRandom(50) + 75;
+
+ if (!isFlag(7))
+ _gameSys->insertSequence(0x144, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (!isFlag(8))
+ _gameSys->insertSequence(0x145, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (!isFlag(9))
+ _gameSys->insertSequence(0x146, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ initGnapPos(-1, 8, 1);
+ initBeaverPos(-1, 7, 0);
+
+ endSceneInit();
+
+ gnapWalkTo(1, 8, -1, 0x107B9, 1);
+ platypusWalkTo(1, 7, -1, 0x107C2, 1);
+
+ _timers[5] = getRandom(40) + 50;
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x10919))
+ playSound(0x10919, 1);
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene08_updateHotspots();
+ _timers[4] = getRandom(50) + 75;
+ _timers[5] = getRandom(40) + 50;
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(11))
+ playGnapMoan1(_platX, _platY);
+ else
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapActionIdle(0x14D);
+ gnapKissPlatypus(8);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ break;
+ }
+ }
+ break;
+
+ case kHSExitBackdoor:
+ _isLeavingScene = 1;
+ gnapActionIdle(0x14D);
+ gnapWalkTo(0, 6, 0, 0x107AF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(0, 7, 1, 0x107CF, 1);
+ _newSceneNum = 9;
+ break;
+
+ case kHSExitCrash:
+ _isLeavingScene = 1;
+ gnapActionIdle(0x14D);
+ gnapWalkTo(3, 9, 0, 0x107AE, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(4, 9, 1, 0x107C1, 1);
+ _newSceneNum = 7;
+ break;
+
+ case kHSMan:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(6, 6, 7, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ gnapActionIdle(0x14D);
+ gnapWalkTo(6, 6, 0, 0x107BB, 1);
+ _gnapActionStatus = kASLookMan;
+ _gnapIdleFacing = 7;
+ break;
+ case GRAB_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 5;
+ gnapActionIdle(0x14D);
+ gnapWalkTo(8, 6, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkMan;
+ break;
+ case PLAT_CURSOR:
+ gnapActionIdle(0x14D);
+ gnapUseDeviceOnBeaver();
+ platypusWalkTo(6, 6, 1, 0x107C2, 1);
+ _beaverActionStatus = kASPlatWithMan;
+ _beaverFacing = 0;
+ playGnapIdle(6, 6);
+ break;
+ }
+ }
+ break;
+
+ case kHSDoor:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(4, 7, 5, 0);
+ _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0);
+ _gnapActionStatus = kASGrabDog;
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(6, 0);
+ _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0);
+ _gnapActionStatus = kASLookDog;
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(4, 7, 0, 0x107BB, 1);
+ _gnapActionStatus = kASGrabDog;
+ _gnapIdleFacing = 7;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapActionIdle(0x14D);
+ gnapWalkTo(4, 7, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkDog;
+ break;
+ case PLAT_CURSOR:
+ setFlag(11);
+ gnapActionIdle(0x14D);
+ gnapUseDeviceOnBeaver();
+ platypusWalkTo(3, 7, 1, 0x107C2, 1);
+ _beaverActionStatus = kASPlatWithDog;
+ _beaverFacing = 0;
+ playGnapIdle(3, 7);
+ break;
+ }
+ }
+ break;
+
+ case kHSMeat:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(6, 8, 5, 6);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(6, 7);
+ break;
+ case GRAB_CURSOR:
+ if (_s08_currDogSequenceId == 0x135) {
+ playGnapScratchingHead(6, 7);
+ } else {
+ gnapActionIdle(0x14D);
+ playGnapPullOutDevice(6, 7);
+ playGnapUseDevice(0, 0);
+ _s08_nextDogSequenceId = 0x149;
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSBone:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(2, 7, 3, 6);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(3, 6);
+ break;
+ case GRAB_CURSOR:
+ if (_s08_currDogSequenceId == 0x135) {
+ playGnapScratchingHead(3, 6);
+ } else {
+ gnapActionIdle(0x14D);
+ playGnapPullOutDevice(3, 6);
+ playGnapUseDevice(0, 0);
+ _s08_nextDogSequenceId = 0x14A;
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSToy:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(8, 7, 7, 6);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(7, 6);
+ break;
+ case GRAB_CURSOR:
+ if (_s08_currDogSequenceId == 0x135) {
+ playGnapScratchingHead(7, 6);
+ } else {
+ gnapActionIdle(0x14D);
+ playGnapPullOutDevice(7, 6);
+ playGnapUseDevice(0, 0);
+ _s08_nextDogSequenceId = 0x14B;
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ gnapActionIdle(0x14D);
+ gnapWalkTo(-1, 6, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapActionIdle(0x14D);
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene08_updateAnimations();
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(50) + 125;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s08_nextManSequenceId == -1 &&
+ (_s08_currDogSequenceId == 0x134 || _s08_currDogSequenceId == 0x135)) {
+ _gnapRandomValue = getRandom(4);
+ switch (_gnapRandomValue) {
+ case 0:
+ _s08_nextManSequenceId = 0x138;
+ break;
+ case 1:
+ _s08_nextManSequenceId = 0x136;
+ break;
+ case 2:
+ _s08_nextManSequenceId = 0x13B;
+ break;
+ case 3:
+ _s08_nextManSequenceId = 0x13A;
+ break;
+ }
+ }
+ }
+ sceneXX_playRandomSound(5);
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene08_updateHotspots();
+ _timers[4] = getRandom(50) + 75;
+ _timers[5] = getRandom(40) + 50;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene08_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ _gnapActionStatus = -1;
+ break;
+ case kASTalkMan:
+ _s08_nextManSequenceId = 0x13F;
+ _gnapActionStatus = -1;
+ break;
+ case kASLookMan:
+ _s08_nextManSequenceId = 0x140;
+ _gnapActionStatus = -1;
+ break;
+ case kASLookDog:
+ _s08_nextManSequenceId = 0x137;
+ _gnapActionStatus = -1;
+ break;
+ case kASGrabDog:
+ if (_s08_currDogSequenceId == 0x135)
+ _s08_nextDogSequenceId = 0x133;
+ else
+ _s08_nextDogSequenceId = 0x13C;
+ _gnapActionStatus = -1;
+ break;
+ case kASTalkDog:
+ if (_s08_currDogSequenceId == 0x135)
+ _s08_nextDogSequenceId = 0x133;
+ else
+ _s08_nextDogSequenceId = 0x13C;
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ _gameSys->setAnimation(0, 0, 1);
+ switch (_beaverActionStatus) {
+ case kASPlatWithDog:
+ _s08_nextDogSequenceId = 0x147;
+ break;
+ case kASPlatWithMan:
+ _s08_nextManSequenceId = 0x140;
+ _beaverActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2 && _s08_nextManSequenceId != -1) {
+ _gameSys->setAnimation(_s08_nextManSequenceId, 100, 2);
+ _gameSys->insertSequence(_s08_nextManSequenceId, 100, _s08_currManSequenceId, 100, kSeqSyncWait, 0, 0, 0);
+ _s08_currManSequenceId = _s08_nextManSequenceId;
+ _s08_nextManSequenceId = -1;
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ if (_s08_currDogSequenceId == 0x147)
+ _beaverActionStatus = -1;
+ if (_s08_currDogSequenceId == 0x149 || _s08_currDogSequenceId == 0x14A || _s08_currDogSequenceId == 0x14B) {
+ if (getRandom(2) != 0)
+ _s08_nextManSequenceId = 0x13D;
+ else
+ _s08_nextManSequenceId = 0x13E;
+ } else if (_s08_currDogSequenceId == 0x133)
+ _s08_nextManSequenceId = 0x139;
+ if (_s08_nextDogSequenceId == 0x149 || _s08_nextDogSequenceId == 0x14A || _s08_nextDogSequenceId == 0x14B) {
+ _gameSys->setAnimation(_s08_nextDogSequenceId, 100, 3);
+ _gameSys->insertSequence(_s08_nextDogSequenceId, 100, _s08_currDogSequenceId, 100, kSeqSyncWait, 0, 0, 0);
+ switch (_s08_nextDogSequenceId) {
+ case 0x149:
+ setFlag(7);
+ _hotspots[kHSMeat].flags = SF_DISABLED | SF_WALKABLE;
+ _gameSys->removeSequence(0x144, 1, 1);
+ break;
+ case 0x14A:
+ setFlag(8);
+ _hotspots[kHSBone].flags = SF_DISABLED | SF_WALKABLE;
+ _gameSys->removeSequence(0x145, 1, 1);
+ break;
+ case 0x14B:
+ setFlag(9);
+ _hotspots[kHSToy].flags = SF_DISABLED | SF_WALKABLE;
+ _gameSys->removeSequence(0x146, 1, 1);
+ break;
+ }
+ _s08_currDogSequenceId = _s08_nextDogSequenceId;
+ _s08_nextDogSequenceId = 0x134;
+ } else if (_s08_nextDogSequenceId == 0x147) {
+ _gameSys->setAnimation(_s08_nextDogSequenceId, 100, 3);
+ _gameSys->insertSequence(_s08_nextDogSequenceId, 100, _s08_currDogSequenceId, 100, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x148, 160, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0);
+ _s08_currDogSequenceId = _s08_nextDogSequenceId;
+ _s08_nextDogSequenceId = 0x134;
+ _platX = 1;
+ _platY = 8;
+ _beaverId = 160;
+ _beaverSequenceId = 0x148;
+ _beaverFacing = 4;
+ _beaverSequenceDatNum = 0;
+ if (_gnapX == 1 && _gnapY == 8)
+ gnapWalkStep();
+ } else if (_s08_nextDogSequenceId != -1) {
+ _gameSys->setAnimation(_s08_nextDogSequenceId, 100, 3);
+ _gameSys->insertSequence(_s08_nextDogSequenceId, 100, _s08_currDogSequenceId, 100, kSeqSyncWait, 0, 0, 0);
+ _s08_currDogSequenceId = _s08_nextDogSequenceId;
+ if (_s08_nextDogSequenceId != 0x135)
+ _s08_nextDogSequenceId = 0x134;
+ if (_s08_currDogSequenceId == 0x133) {
+ _timers[2] = getRandom(30) + 20;
+ _timers[3] = getRandom(50) + 200;
+ _gameSys->insertSequence(0x14D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x14D;
+ _gnapIdleFacing = 7;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = -1;
+ }
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene09.cpp b/engines/gnap/scenes/scene09.cpp
new file mode 100644
index 0000000000..4436d1e436
--- /dev/null
+++ b/engines/gnap/scenes/scene09.cpp
@@ -0,0 +1,241 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitKitchen = 1,
+ kHSExitHouse = 2,
+ kHSTrash = 3,
+ kHSDevice = 4,
+ kHSWalkArea1 = 5,
+ kHSWalkArea2 = 6,
+ kHSWalkArea3 = 7
+};
+
+enum {
+ kASLeaveScene = 0,
+ kASSearchTrash = 1,
+ kASSearchTrashDone = 2
+};
+
+int GnapEngine::scene09_init() {
+ return 0x4E;
+}
+
+void GnapEngine::scene09_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 200, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitKitchen, 280, 200, 380, 400, SF_EXIT_U_CURSOR);
+ setHotspot(kHSExitHouse, 790, 200, 799, 450, SF_EXIT_R_CURSOR | SF_WALKABLE);
+ setHotspot(kHSTrash, 440, 310, 680, 420, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSWalkArea1, 0, 0, 799, 400);
+ setHotspot(kHSWalkArea2, 0, 0, 630, 450);
+ setHotspot(kHSWalkArea2, 0, 0, 175, 495);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 8;
+}
+
+void GnapEngine::scene09_run() {
+
+ queueInsertDeviceIcon();
+
+ _gameSys->insertSequence(0x4D, 1, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0x4B, 2, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (_prevSceneNum == 8) {
+ initGnapPos(11, 8, 3);
+ initBeaverPos(12, 7, 4);
+ endSceneInit();
+ gnapWalkTo(9, 8, -1, 0x107BA, 1);
+ platypusWalkTo(9, 7, -1, 0x107D2, 1);
+ } else {
+ initGnapPos(4, 7, 1);
+ initBeaverPos(5, 7, 0);
+ endSceneInit();
+ }
+
+ _timers[4] = getRandom(150) + 50;
+ _timers[5] = getRandom(40) + 50;
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x10919))
+ playSound(0x10919, 1);
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene09_updateHotspots();
+ _timers[4] = getRandom(150) + 50;
+ _timers[5] = getRandom(40) + 50;
+ }
+ break;
+
+ case kHSPlatypus:
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ break;
+ }
+ break;
+
+ case kHSExitKitchen:
+ _isLeavingScene = 1;
+ _newSceneNum = 10;
+ gnapWalkTo(4, 7, 0, 0x107BF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(4, 8, -1, 0x107D2, 1);
+ _beaverFacing = 4;
+ break;
+
+ case kHSExitHouse:
+ _isLeavingScene = 1;
+ _newSceneNum = 8;
+ gnapWalkTo(10, -1, 0, 0x107AB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(10, -1, -1, 0x107CD, 1);
+ _beaverFacing = 4;
+ break;
+
+ case kHSTrash:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(9, 6, 8, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(8, 3);
+ break;
+ case GRAB_CURSOR:
+ _gnapActionStatus = kASSearchTrash;
+ gnapWalkTo(9, 6, 0, 0x107BC, 1);
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene09_updateAnimations();
+
+ if (!_isLeavingScene && _gnapActionStatus != 1 && _gnapActionStatus != 2) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(150) + 100;
+ if (_timers[4] & 1)
+ _gameSys->insertSequence(0x49, 1, 0, 0, kSeqNone, 0, 0, 0);
+ else
+ _gameSys->insertSequence(0x4A, 1, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ sceneXX_playRandomSound(5);
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene09_updateHotspots();
+ _timers[4] = getRandom(150) + 50;
+ _timers[5] = getRandom(40) + 50;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene09_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ _gnapActionStatus = -1;
+ break;
+ case kASSearchTrash:
+ _gameSys->setAnimation(0x4C, 120, 0);
+ _gameSys->insertSequence(0x4C, 120, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->removeSequence(0x4B, 2, 1);
+ _gnapSequenceId = 0x4C;
+ _gnapId = 120;
+ _gnapIdleFacing = 5;
+ _gnapSequenceDatNum = 0;
+ _gnapX = 9;
+ _gnapY = 6;
+ _gnapActionStatus = kASSearchTrashDone;
+ break;
+ case kASSearchTrashDone:
+ _gameSys->insertSequence(0x4B, 2, 0, 0, kSeqNone, 0, 0, 0);
+ _timers[2] = 360;
+ _timers[4] = getRandom(150) + 100;
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene10.cpp b/engines/gnap/scenes/scene10.cpp
new file mode 100644
index 0000000000..c6faf5a0ca
--- /dev/null
+++ b/engines/gnap/scenes/scene10.cpp
@@ -0,0 +1,500 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitBar = 1,
+ kHSExitBackdoor = 2,
+ kHSCook = 3,
+ kHSTongs = 4,
+ kHSBox = 5,
+ kHSOven = 6,
+ kHSWalkArea1 = 7,
+ kHSDevice = 8,
+ kHSWalkArea2 = 9,
+ kHSWalkArea3 = 10,
+ kHSWalkArea4 = 11
+};
+
+enum {
+ kASLeaveScene = 0,
+ kASAnnoyCook = 1,
+ kASPlatWithBox = 4
+};
+
+int GnapEngine::scene10_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0, 0, 2);
+ return 0x10F;
+}
+
+void GnapEngine::scene10_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitBar, 0, 75, 85, 455, SF_EXIT_NW_CURSOR);
+ setHotspot(kHSExitBackdoor, 75, 590, 500, 599, SF_EXIT_D_CURSOR | SF_WALKABLE);
+ setHotspot(kHSCook, 370, 205, 495, 460, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSTongs, 250, 290, 350, 337, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSBox, 510, 275, 565, 330, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSOven, 690, 280, 799, 420, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSWalkArea1, 59, 0, 495, 460);
+ setHotspot(kHSWalkArea2, 495, 0, 650, 420);
+ setHotspot(kHSWalkArea3, 651, 0, 725, 400);
+ setHotspot(kHSWalkArea4, 725, 0, 799, 441);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 12;
+}
+
+void GnapEngine::scene10_run() {
+
+ _s10_currCookSequenceId = 0x103;
+
+ _gameSys->setAnimation(0x103, 100, 2);
+ _gameSys->insertSequence(0x103, 100, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s10_nextCookSequenceId = 0x106;
+ if (!isFlag(1))
+ _gameSys->insertSequence(0x107, 100, 0, 0, kSeqNone, 0, 0, 0);
+
+ queueInsertDeviceIcon();
+
+ if (_prevSceneNum == 9) {
+ initGnapPos(11, 8, 3);
+ initBeaverPos(12, 7, 4);
+ endSceneInit();
+ gnapWalkTo(9, 8, -1, 0x107BA, 1);
+ platypusWalkTo(9, 7, -1, 0x107D2, 1);
+ } else {
+ initGnapPos(-1, 7, 1);
+ initBeaverPos(-2, 8, 0);
+ endSceneInit();
+ gnapWalkTo(1, 7, -1, 0x107B9, 1);
+ platypusWalkTo(1, 8, -1, 0x107C2, 1);
+ }
+
+ _timers[4] = getRandom(80) + 150;
+ _timers[5] = getRandom(100) + 100;
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x1091E))
+ playSound(0x1091E, 1);
+
+ if (!isSoundPlaying(0x1091A))
+ playSound(0x1091A, 1);
+
+ updateMouseCursor();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSPlatypus:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(1))
+ playGnapMoan1(_platX, _platY);
+ else
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(10);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ break;
+ }
+ }
+ break;
+
+ case kHSExitBar:
+ _isLeavingScene = 1;
+ gnapActionIdle(0x10C);
+ gnapWalkTo(0, 7, 0, 0x107AF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(0, 7, -1, 0x107CF, 1);
+ _newSceneNum = 11;
+ break;
+
+ case kHSExitBackdoor:
+ _isLeavingScene = 1;
+ gnapActionIdle(0x10C);
+ gnapWalkTo(2, 9, 0, 0x107AE, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(3, 9, -1, 0x107C7, 1);
+ _newSceneNum = 9;
+ break;
+
+ case kHSCook:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(4, 8, 6, 0);
+ _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0);
+ _gnapActionStatus = kASAnnoyCook;
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(6, 0);
+ break;
+ case GRAB_CURSOR:
+ playGnapImpossible(0, 0);
+ _gnapIdleFacing = 1;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapActionIdle(0x10C);
+ gnapWalkTo(4, 8, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASAnnoyCook;
+ break;
+ case PLAT_CURSOR:
+ gnapActionIdle(0x10C);
+ gnapUseDeviceOnBeaver();
+ platypusWalkTo(4, 6, -1, -1, 1);
+ gnapWalkTo(4, 8, 0, 0x107BB, 1);
+ _gnapActionStatus = kASAnnoyCook;
+ break;
+ }
+ }
+ break;
+
+ case kHSTongs:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(3, 7, 4, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(1))
+ playGnapMoan2(-1, -1);
+ else
+ playGnapScratchingHead(4, 3);
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(1))
+ playGnapMoan2(-1, -1);
+ else {
+ gnapActionIdle(0x10C);
+ gnapWalkTo(4, 8, 0, 0x107BB, 1);
+ _gnapActionStatus = kASAnnoyCook;
+ }
+ break;
+ case TALK_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case PLAT_CURSOR:
+ if (isFlag(1))
+ playGnapMoan2(-1, -1);
+ else {
+ gnapActionIdle(0x10C);
+ gnapUseDeviceOnBeaver();
+ platypusWalkTo(3, 7, -1, -1, 1);
+ gnapWalkTo(4, 8, 0, 0x107BB, 1);
+ _gnapActionStatus = kASAnnoyCook;
+ }
+ break;
+ }
+ }
+ break;
+
+ case kHSBox:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(7, 6, 6, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(7, 3);
+ break;
+ case GRAB_CURSOR:
+ gnapActionIdle(0x10C);
+ gnapWalkTo(4, 8, 0, 0x107BB, 1);
+ _gnapActionStatus = kASAnnoyCook;
+ break;
+ case TALK_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case PLAT_CURSOR:
+ if (isFlag(1))
+ playGnapMoan2(-1, -1);
+ else {
+ invAdd(kItemTongs);
+ setFlag(1);
+ gnapActionIdle(0x10C);
+ gnapUseDeviceOnBeaver();
+ platypusWalkTo(7, 6, 1, 0x107D2, 1);
+ _beaverActionStatus = kASPlatWithBox;
+ _beaverFacing = 4;
+ _largeSprite = _gameSys->createSurface(0xC3);
+ playGnapIdle(7, 6);
+ }
+ break;
+ }
+ }
+ break;
+
+ case kHSOven:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(9, 6, 10, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapSequence(getGnapSequenceId(gskDeflect, 10, 5) | 0x10000);
+ break;
+ case GRAB_CURSOR:
+ gnapActionIdle(0x10C);
+ gnapWalkTo(9, 6, 0, 0x107BB, 1);
+ _gameSys->insertSequence(0x10E, 120, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x10E;
+ _gnapId = 120;
+ _gnapIdleFacing = 7;
+ _gnapSequenceDatNum = 0;
+ _gnapX = 9;
+ _gnapY = 6;
+ _timers[2] = 360;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ case kHSWalkArea4:
+ gnapActionIdle(0x10C);
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene10_updateHotspots();
+ }
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapActionIdle(0x10C);
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene10_updateAnimations();
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(80) + 150;
+ playSound(0x12B, 0);
+ }
+ if (!_timers[5]) {
+ int sequenceId;
+ _timers[5] = getRandom(100) + 100;
+ _gnapRandomValue = getRandom(4);
+ if (_gnapRandomValue) {
+ if (_gnapRandomValue == 1) {
+ sequenceId = 0x8A5;
+ } else if (_gnapRandomValue == 2) {
+ sequenceId = 0x8A6;
+ } else {
+ sequenceId = 0x8A7;
+ }
+ _gameSys->insertSequence(sequenceId | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene10_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene10_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ case kASAnnoyCook:
+ _s10_nextCookSequenceId = 0x105;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ _gameSys->setAnimation(0, 0, 1);
+ switch (_beaverActionStatus) {
+ case kASPlatWithBox:
+ _s10_nextCookSequenceId = 0x109;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2 && _s10_nextCookSequenceId != -1) {
+
+ switch (_s10_nextCookSequenceId) {
+ case 0x109:
+ _platX = 4;
+ _platY = 8;
+ _gameSys->insertSequence(0x109, 100, _s10_currCookSequenceId, 100, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x107C9, 160,
+ _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId,
+ kSeqSyncWait, getSequenceTotalDuration(0x109) + getSequenceTotalDuration(0x10A) + getSequenceTotalDuration(0x10843),
+ 75 * _platX - _platGridX, 48 * _platY - _platGridY);
+ _gameSys->removeSequence(0x107, 100, 1);
+ _s10_currCookSequenceId = 0x109;
+ _s10_nextCookSequenceId = 0x843;
+ _beaverSequenceId = 0x7C9;
+ _beaverId = 160;
+ _beaverFacing = 0;
+ _beaverSequenceDatNum = 1;
+ break;
+ case 0x843:
+ hideCursor();
+ _gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300);
+ _gameSys->insertSequence(0x10843, 301, _s10_currCookSequenceId, 100, kSeqSyncWait, 0, 0, 0);
+ _s10_currCookSequenceId = 0x843;
+ _s10_nextCookSequenceId = 0x10A;
+ break;
+ case 0x10A:
+ _gameSys->insertSequence(_s10_nextCookSequenceId, 100, 0x10843, 301, kSeqSyncWait, 0, 0, 0);
+ _s10_currCookSequenceId = _s10_nextCookSequenceId;
+ _s10_nextCookSequenceId = 0x104;
+ showCursor();
+ _gameSys->removeSpriteDrawItem(_largeSprite, 300);
+ delayTicksCursor(5);
+ deleteSurface(&_largeSprite);
+ setGrabCursorSprite(kItemTongs);
+ if (_beaverActionStatus == kASPlatWithBox)
+ _beaverActionStatus = -1;
+ if (_gnapX == 4 && _gnapY == 8)
+ gnapWalkStep();
+ break;
+ default:
+ _gameSys->insertSequence(_s10_nextCookSequenceId, 100, _s10_currCookSequenceId, 100, kSeqSyncWait, 0, 0, 0);
+ _s10_currCookSequenceId = _s10_nextCookSequenceId;
+ break;
+ }
+
+ switch (_s10_currCookSequenceId) {
+ case 0x106:
+ _gnapRandomValue = getRandom(7);
+ if (_gnapActionStatus >= 0 || _beaverActionStatus >= 0)
+ _s10_nextCookSequenceId = 0x106;
+ else if (_gnapRandomValue == 0)
+ _s10_nextCookSequenceId = 0x104;
+ else if (_gnapRandomValue == 1)
+ _s10_nextCookSequenceId = 0x103;
+ else if (_gnapRandomValue == 2) {
+ _s10_nextCookSequenceId = 0x106;
+ _gameSys->insertSequence(0x10D, 1, 0, 0, kSeqNone, 0, 0, 0);
+ } else
+ _s10_nextCookSequenceId = 0x106;
+ break;
+ case 0x103:
+ _gnapRandomValue = getRandom(7);
+ if (_gnapActionStatus >= 0 || _beaverActionStatus >= 0)
+ _s10_nextCookSequenceId = 0x106;
+ else if (_gnapRandomValue == 0)
+ _s10_nextCookSequenceId = 0x104;
+ else
+ _s10_nextCookSequenceId = 0x106;
+ break;
+ case 0x104:
+ _gnapRandomValue = getRandom(7);
+ if (_gnapActionStatus >= 0 || _beaverActionStatus >= 0)
+ _s10_nextCookSequenceId = 0x106;
+ else if (_gnapRandomValue == 0)
+ _s10_nextCookSequenceId = 0x103;
+ else
+ _s10_nextCookSequenceId = 0x106;
+ break;
+ case 0x105:
+ _gnapRandomValue = getRandom(7);
+ if (_gnapActionStatus >= 0 || _beaverActionStatus >= 0)
+ _s10_nextCookSequenceId = 0x106;
+ else if (_gnapRandomValue == 0)
+ _s10_nextCookSequenceId = 0x104;
+ else if (_gnapRandomValue == 1)
+ _s10_nextCookSequenceId = 0x103;
+ else
+ _s10_nextCookSequenceId = 0x106;
+ _timers[2] = getRandom(30) + 20;
+ _timers[3] = 300;
+ _gameSys->insertSequence(0x10C, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x10C;
+ _gnapIdleFacing = 7;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = -1;
+ _beaverActionStatus = -1;
+ break;
+ }
+ if (_s10_currCookSequenceId == 0x843)
+ _gameSys->setAnimation(_s10_currCookSequenceId | 0x10000, 301, 2);
+ else
+ _gameSys->setAnimation(_s10_currCookSequenceId, 100, 2);
+ }
+
+}
+
+void GnapEngine::scene10_updateAnimationsCb() {
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ _gameSys->setAnimation(_s10_nextCookSequenceId, 100, 2);
+ _gameSys->insertSequence(_s10_nextCookSequenceId, 100, _s10_currCookSequenceId, 100, kSeqSyncWait, 0, 0, 0);
+ _s10_currCookSequenceId = _s10_nextCookSequenceId;
+ _s10_nextCookSequenceId = 0x106;
+ }
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene11.cpp b/engines/gnap/scenes/scene11.cpp
new file mode 100644
index 0000000000..6bbc542e90
--- /dev/null
+++ b/engines/gnap/scenes/scene11.cpp
@@ -0,0 +1,488 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitKitchen = 1,
+ kHSExitToilet = 2,
+ kHSExitLeft = 3,
+ kHSGoggleGuy = 4,
+ kHSHookGuy = 5,
+ kHSBillard = 6,
+ kHSWalkArea1 = 7,
+ kHSDevice = 8,
+ kHSWalkArea2 = 9,
+ kHSWalkArea3 = 10,
+ kHSWalkArea4 = 11,
+ kHSWalkArea5 = 12
+};
+
+enum {
+ kASLeaveScene = 0,
+ kASShowMagazineToGoggleGuy = 3,
+ kASTalkGoggleGuy = 4,
+ kASGrabHookGuy = 6,
+ kASShowItemToHookGuy = 8,
+ kASTalkHookGuy = 9,
+ kASGrabBillardBall = 11
+};
+
+int GnapEngine::scene11_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 3);
+ _gameSys->setAnimation(0, 0, 2);
+ if (_prevSceneNum == 10 || _prevSceneNum == 13) {
+ playSound(0x108EC, 0);
+ playSound(0x10928, 0);
+ }
+ return 0x209;
+}
+
+void GnapEngine::scene11_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitKitchen, 420, 140, 520, 345, SF_EXIT_U_CURSOR);
+ setHotspot(kHSExitToilet, 666, 130, 740, 364, SF_EXIT_R_CURSOR);
+ setHotspot(kHSExitLeft, 0, 350, 10, 599, SF_EXIT_L_CURSOR | SF_WALKABLE);
+ setHotspot(kHSGoggleGuy, 90, 185, 185, 340, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSHookGuy, 210, 240, 340, 430, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSBillard, 640, 475, 700, 530, SF_WALKABLE | SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSWalkArea1, 0, 0, 365, 453);
+ setHotspot(kHSWalkArea2, 0, 0, 629, 353);
+ setHotspot(kHSWalkArea3, 629, 0, 799, 364);
+ setHotspot(kHSWalkArea4, 735, 0, 799, 397);
+ setHotspot(kHSWalkArea5, 510, 540, 799, 599);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 13;
+}
+
+void GnapEngine::scene11_run() {
+ bool flag = true;
+
+ _timers[7] = 50;
+
+ _hotspots[kHSBillard].flags |= SF_DISABLED;
+
+ _s11_currGoggleGuySequenceId = 0x1F9;
+
+ _s11_currHookGuySequenceId = 0x201;
+
+ switch (_prevSceneNum) {
+ case 13:
+ initGnapPos(8, 5, 3);
+ initBeaverPos(9, 6, 4);
+ break;
+ case 47:
+ initGnapPos(8, 5, 3);
+ initBeaverPos(9, 5, 4);
+ _s11_currGoggleGuySequenceId = 0x1FA;
+ _s11_currHookGuySequenceId = 0x1FF;
+ _timers[7] = 180;
+ break;
+ case 12:
+ initGnapPos(-1, 9, 1);
+ initBeaverPos(-2, 8, 0);
+ break;
+ default:
+ initGnapPos(6, 6, 3);
+ initBeaverPos(6, 5, 4);
+ break;
+ }
+
+ queueInsertDeviceIcon();
+
+ _gameSys->insertSequence(_s11_currHookGuySequenceId, 120, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s11_nextHookGuySequenceId = -1;
+
+ _gameSys->setAnimation(_s11_currHookGuySequenceId, 120, 3);
+ _gameSys->insertSequence(_s11_currGoggleGuySequenceId, 121, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s11_nextGoggleGuySequenceId = -1;
+
+ _gameSys->setAnimation(_s11_currGoggleGuySequenceId, 121, 2);
+
+ _timers[5] = getRandom(100) + 75;
+ _timers[4] = getRandom(40) + 20;
+ _timers[6] = getRandom(100) + 100;
+ endSceneInit();
+
+ if (_prevSceneNum == 12) {
+ gnapWalkTo(2, 8, -1, 0x107B9, 1);
+ platypusWalkTo(1, 8, -1, 0x107C2, 1);
+ }
+
+ _gameSys->insertSequence(0x208, 256, 0, 0, kSeqNone, 40, 0, 0);
+
+ while (!_sceneDone) {
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSPlatypus:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ break;
+ }
+ }
+ break;
+
+ case kHSExitKitchen:
+ _isLeavingScene = true;
+ gnapWalkTo(6, 5, 0, 0x107BF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(6, 6, -1, -1, 1);
+ _newSceneNum = 10;
+ break;
+
+ case kHSExitToilet:
+ _isLeavingScene = true;
+ gnapWalkTo(8, 5, 0, 0x107BF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(8, 6, -1, -1, 1);
+ _newSceneNum = 13;
+ break;
+
+ case kHSExitLeft:
+ _isLeavingScene = true;
+ gnapWalkTo(-1, 8, 0, 0x107AF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(-1, 9, -1, 0x107CF, 1);
+ _newSceneNum = 12;
+ break;
+
+ case kHSGoggleGuy:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemMagazine) {
+ gnapWalkTo(3, 7, 0, 0x107BC, 1);
+ _gnapActionStatus = kASShowMagazineToGoggleGuy;
+ playGnapShowItem(_grabCursorSpriteIndex, 2, 0);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(3, 7, 2, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(1, 6);
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 5;
+ gnapWalkTo(3, 7, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkGoggleGuy;
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSHookGuy:
+ if (_gnapActionStatus < 0) {
+ _gnapIdleFacing = 7;
+ if (_grabCursorSpriteIndex >= 0) {
+ gnapWalkTo(5, 6, 0, 0x107BC, 9);
+ _gnapActionStatus = kASShowItemToHookGuy;
+ playGnapShowItem(_grabCursorSpriteIndex, 4, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapSequence(getGnapSequenceId(gskDeflect, 3, 6) | 0x10000);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(5, 6, 0, 0x107BC, 1);
+ _gnapActionStatus = kASGrabHookGuy;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 3;
+ gnapWalkTo(5, 6, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkHookGuy;
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSBillard:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(9, 8);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(9, 8);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(9, 8, 0, 0x107BA, 1);
+ _gnapActionStatus = kASGrabBillardBall;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(9, 8);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ case kHSWalkArea4:
+ case kHSWalkArea5:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene11_updateHotspots();
+ }
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene11_updateAnimations();
+
+ if (!_isLeavingScene) {
+ if (flag && !_timers[7]) {
+ flag = false;
+ _gameSys->setAnimation(0x207, 257, 4);
+ _gameSys->insertSequence(0x207, 257, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ beaverSub426234();
+ updateGnapIdleSequence2();
+ if (!_timers[5]) {
+ _timers[5] = getRandom(100) + 75;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s11_nextGoggleGuySequenceId == -1) {
+ _gnapRandomValue = getRandom(2);
+ if (_gnapRandomValue)
+ _s11_nextGoggleGuySequenceId = 0x1F6;
+ else
+ _s11_nextGoggleGuySequenceId = 0x1F9;
+ }
+ }
+ if (!_timers[4]) {
+ _timers[4] = getRandom(40) + 20;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s11_nextHookGuySequenceId == -1) {
+ if (_s11_currHookGuySequenceId == 0x201) {
+ _gnapRandomValue = getRandom(7);
+ switch (_gnapRandomValue) {
+ case 0:
+ _s11_nextHookGuySequenceId = 0x200;
+ break;
+ case 1:
+ _s11_nextHookGuySequenceId = 0x205;
+ break;
+ case 2:
+ _s11_nextHookGuySequenceId = 0x202;
+ break;
+ default:
+ _s11_nextHookGuySequenceId = 0x201;
+ break;
+ }
+ } else {
+ _s11_nextHookGuySequenceId = 0x201;
+ }
+ }
+ }
+ if (!_timers[6]) {
+ _timers[6] = getRandom(100) + 100;
+ _gnapRandomValue = getRandom(3);
+ switch (_gnapRandomValue) {
+ case 0:
+ _gameSys->insertSequence(0x8A5 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 1:
+ _gameSys->insertSequence(0x8A7 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 2:
+ _gameSys->insertSequence(0x8A6 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene11_updateHotspots();
+ _timers[5] = getRandom(50) + 75;
+ _timers[4] = getRandom(40) + 20;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene11_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ if (_gnapActionStatus != kASGrabBillardBall)
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ case kASShowMagazineToGoggleGuy:
+ _s11_nextGoggleGuySequenceId = 0x1F7;
+ break;
+ case kASTalkGoggleGuy:
+ _s11_nextGoggleGuySequenceId = 0x1FB;
+ break;
+ case kASGrabHookGuy:
+ _s11_nextHookGuySequenceId = 0x204;
+ break;
+ case kASShowItemToHookGuy:
+ _s11_nextHookGuySequenceId = 0x203;
+ break;
+ case kASTalkHookGuy:
+ _s11_nextHookGuySequenceId = 0x206;
+ break;
+ case kASGrabBillardBall:
+ if (_gameSys->getAnimationStatus(2) == 2 && _gameSys->getAnimationStatus(3) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ _timers[2] = getRandom(30) + 20;
+ _timers[3] = getRandom(50) + 200;
+ _gameSys->insertSequence(0x1F4, 255, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x1F4;
+ _gnapId = 255;
+ _gnapSequenceDatNum = 0;
+ _gameSys->removeSequence(0x207, 257, 1);
+ _gameSys->removeSequence(0x208, 256, 1);
+ _s11_nextGoggleGuySequenceId = 0x1F8;
+ _timers[5] = getRandom(100) + 75;
+ _gameSys->insertSequence(_s11_nextGoggleGuySequenceId, 121, _s11_currGoggleGuySequenceId, 121, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s11_nextGoggleGuySequenceId, 121, 2);
+ _s11_currGoggleGuySequenceId = _s11_nextGoggleGuySequenceId;
+ _s11_nextGoggleGuySequenceId = -1;
+ switch (_s11_billardBallCtr) {
+ case 0:
+ _s11_nextHookGuySequenceId = 0x1FC;
+ break;
+ case 1:
+ _s11_nextHookGuySequenceId = 0x1FD;
+ break;
+ default:
+ _s11_nextHookGuySequenceId = 0x1FE;
+ break;
+ }
+ ++_s11_billardBallCtr;
+ _gameSys->insertSequence(_s11_nextHookGuySequenceId, 120, _s11_currHookGuySequenceId, 120, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s11_nextHookGuySequenceId, 120, 3);
+ _s11_currHookGuySequenceId = _s11_nextHookGuySequenceId;
+ _s11_nextHookGuySequenceId = -1;
+ _timers[4] = getRandom(40) + 20;
+ _gameSys->insertSequence(0x208, 256, 0, 0, kSeqNone, getSequenceTotalDuration(0x1F4) - 5, 0, 0);
+ _hotspots[kHSBillard].flags |= SF_DISABLED;
+ _gameSys->setAnimation(0x207, 257, 4);
+ _gameSys->insertSequence(0x207, 257, 0, 0, kSeqNone, getSequenceTotalDuration(0x1FE), 0, 0);
+ _gnapActionStatus = -1;
+ }
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2 && _s11_nextGoggleGuySequenceId != -1) {
+ _timers[5] = getRandom(100) + 75;
+ _gameSys->insertSequence(_s11_nextGoggleGuySequenceId, 121, _s11_currGoggleGuySequenceId, 121, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s11_nextGoggleGuySequenceId, 121, 2);
+ _s11_currGoggleGuySequenceId = _s11_nextGoggleGuySequenceId;
+ _s11_nextGoggleGuySequenceId = -1;
+ if (_gnapActionStatus >= 1 && _gnapActionStatus <= 4)
+ _gnapActionStatus = -1;
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ if (_s11_nextHookGuySequenceId == 0x204) {
+ _gameSys->setAnimation(_s11_nextHookGuySequenceId, 120, 3);
+ _gameSys->insertSequence(0x204, 120, _s11_currHookGuySequenceId, 120, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x1F5, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _s11_currHookGuySequenceId = 0x204;
+ _s11_nextHookGuySequenceId = -1;
+ _gnapSequenceId = 0x1F5;
+ _gnapSequenceDatNum = 0;
+ _timers[4] = getRandom(40) + 20;
+ _timers[2] = getRandom(20) + 70;
+ _timers[3] = getRandom(50) + 200;
+ if (_gnapActionStatus == kASGrabHookGuy)
+ _gnapActionStatus = -1;
+ } else if (_s11_nextHookGuySequenceId != -1) {
+ _gameSys->insertSequence(_s11_nextHookGuySequenceId, 120, _s11_currHookGuySequenceId, 120, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s11_nextHookGuySequenceId, 120, 3);
+ _s11_currHookGuySequenceId = _s11_nextHookGuySequenceId;
+ _s11_nextHookGuySequenceId = -1;
+ _timers[4] = getRandom(40) + 20;
+ if (_gnapActionStatus >= 6 && _gnapActionStatus <= 9)
+ _gnapActionStatus = -1;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(4) == 2) {
+ _gameSys->setAnimation(0, 0, 4);
+ _hotspots[kHSBillard].flags &= ~SF_DISABLED;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene12.cpp b/engines/gnap/scenes/scene12.cpp
new file mode 100644
index 0000000000..076fa0408d
--- /dev/null
+++ b/engines/gnap/scenes/scene12.cpp
@@ -0,0 +1,564 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitRight = 1,
+ kHSToothGuy = 2,
+ kHSBarkeeper = 3,
+ kHSBeardGuy = 4,
+ kHSJukebox = 5,
+ kHSWalkArea1 = 6,
+ kHSDevice = 7,
+ kHSWalkArea2 = 8,
+ kHSWalkArea3 = 9,
+ kHSWalkArea4 = 10
+};
+
+enum {
+ kASLeaveScene = 0,
+ kASQuarterToToothGuyDone = 1,
+ kASTalkToothGuy = 2,
+ kASGrabToothGuy = 4,
+ kASShowItemToToothGuy = 5,
+ kASQuarterWithHoleToToothGuy = 6,
+ kASQuarterToToothGuy = 7,
+ kASTalkBeardGuy = 8,
+ kASLookBeardGuy = 9,
+ kASGrabBeardGuy = 10,
+ kASShowItemToBeardGuy = 11,
+ kASTalkBarkeeper = 12,
+ kASLookBarkeeper = 13,
+ kASShowItemToBarkeeper = 15,
+ kASQuarterWithBarkeeper = 16,
+ kASPlatWithBarkeeper = 17,
+ kASPlatWithToothGuy = 18,
+ kASPlatWithBeardGuy = 19
+};
+
+int GnapEngine::scene12_init() {
+ return 0x209;
+}
+
+void GnapEngine::scene12_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitRight, 790, 360, 799, 599, SF_EXIT_R_CURSOR);
+ setHotspot(kHSToothGuy, 80, 180, 160, 380, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSBarkeeper, 490, 175, 580, 238, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSBeardGuy, 620, 215, 720, 350, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSJukebox, 300, 170, 410, 355, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSWalkArea1, 0, 0, 260, 460);
+ setHotspot(kHSWalkArea2, 0, 0, 380, 410);
+ setHotspot(kHSWalkArea3, 0, 0, 799, 395);
+ setHotspot(kHSWalkArea4, 585, 0, 799, 455);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 11;
+}
+
+void GnapEngine::scene12_run() {
+ int v18 = 1;
+
+ queueInsertDeviceIcon();
+
+ _gameSys->insertSequence(0x207, 256, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x200, 50, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s12_currToothGuySequenceId = 0x200;
+ _s12_nextToothGuySequenceId = -1;
+
+ _gameSys->setAnimation(0x200, 50, 2);
+ _gameSys->insertSequence(0x202, 50, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s12_currBeardGuySequenceId = 0x202;
+ _s12_nextBeardGuySequenceId = -1;
+
+ _gameSys->setAnimation(0x202, 50, 4);
+ _gameSys->insertSequence(0x203, 50, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s12_currBarkeeperSequenceId = 0x203;
+ _s12_nextBarkeeperSequenceId = -1;
+
+ _gameSys->setAnimation(0x203, 50, 3);
+
+ _timers[4] = 30;
+ _timers[6] = getRandom(30) + 20;
+ _timers[5] = getRandom(30) + 20;
+ _timers[7] = getRandom(100) + 100;
+
+ if (_prevSceneNum == 15) {
+ initGnapPos(5, 6, 1);
+ initBeaverPos(3, 7, 0);
+ endSceneInit();
+ } else {
+ initGnapPos(11, 8, 3);
+ initBeaverPos(12, 8, 4);
+ endSceneInit();
+ gnapWalkTo(8, 8, -1, 0x107BA, 1);
+ platypusWalkTo(9, 8, -1, 0x107D2, 1);
+ }
+
+ while (!_sceneDone) {
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+ updateGrabCursorSprite(0, 0);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene12_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ break;
+ }
+ break;
+
+ case kHSExitRight:
+ _isLeavingScene = 1;
+ gnapWalkTo(10, -1, 0, 0x107AB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(10, -1, -1, -1, 1);
+ _newSceneNum = 11;
+ break;
+
+ case kHSToothGuy:
+ if (_grabCursorSpriteIndex == kItemQuarter) {
+ _largeSprite = _gameSys->createSurface(0x141);
+ gnapWalkTo(3, 7, 0, 0x107BC, 9);
+ _gnapIdleFacing = 5;
+ _gnapActionStatus = kASQuarterToToothGuy;
+ playGnapShowItem(_grabCursorSpriteIndex, 2, 0);
+ setGrabCursorSprite(-1);
+ } else if (_grabCursorSpriteIndex == kItemQuarterWithHole) {
+ gnapWalkTo(3, 7, 0, 0x107BC, 9);
+ _gnapIdleFacing = 5;
+ _gnapActionStatus = kASQuarterWithHoleToToothGuy;
+ playGnapShowItem(_grabCursorSpriteIndex, 2, 0);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ gnapWalkTo(3, 7, 0, 0x107BC, 9);
+ _gnapIdleFacing = 5;
+ _gnapActionStatus = kASShowItemToToothGuy;
+ playGnapShowItem(_grabCursorSpriteIndex, 2, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(1, 2);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(3, 7, 0, 0x107BC, 1);
+ _gnapActionStatus = kASGrabToothGuy;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 5;
+ gnapWalkTo(3, 7, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkToothGuy;
+ break;
+ case PLAT_CURSOR:
+ gnapUseDeviceOnBeaver();
+ platypusWalkTo(3, 7, 1, 0x107D2, 1);
+ _beaverActionStatus = kASPlatWithToothGuy;
+ _beaverFacing = 4;
+ playGnapIdle(2, 7);
+ break;
+ }
+ }
+ break;
+
+ case kHSBarkeeper:
+ if (_grabCursorSpriteIndex == kItemQuarter || _grabCursorSpriteIndex == kItemQuarterWithHole) {
+ gnapWalkTo(6, 6, 0, 0x107BB, 9);
+ _gnapIdleFacing = 7;
+ _gnapActionStatus = kASQuarterWithBarkeeper;
+ playGnapShowItem(_grabCursorSpriteIndex, 7, 0);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ gnapWalkTo(6, 6, 0, 0x107BB, 9);
+ _gnapIdleFacing = 7;
+ _gnapActionStatus = kASShowItemToBarkeeper;
+ playGnapShowItem(_grabCursorSpriteIndex, 7, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ gnapWalkTo(6, 6, 0, 0x107BB, 1);
+ _gnapIdleFacing = 7;
+ _gnapActionStatus = kASLookBarkeeper;
+ break;
+ case GRAB_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(6, 6, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkBarkeeper;
+ break;
+ case PLAT_CURSOR:
+ playGnapPullOutDevice(_platX, _platY);
+ _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0);
+ _gnapActionStatus = kASPlatWithBarkeeper;
+ break;
+ }
+ }
+ break;
+
+ case kHSBeardGuy:
+ if (_grabCursorSpriteIndex >= 0) {
+ gnapWalkTo(7, 6, 0, 0x107BB, 9);
+ _gnapIdleFacing = 7;
+ _gnapActionStatus = kASShowItemToBeardGuy;
+ playGnapShowItem(_grabCursorSpriteIndex, 8, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ gnapWalkTo(7, 6, 0, 0x107BB, 1);
+ _gnapIdleFacing = 7;
+ _gnapActionStatus = kASLookBeardGuy;
+ break;
+ case GRAB_CURSOR:
+ // NOTE Bug in the original. It has 9 as flags which seems wrong here.
+ gnapWalkTo(7, 6, 0, 0x107BB, 1);
+ _gnapIdleFacing = 7;
+ _gnapActionStatus = kASGrabBeardGuy;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(7, 6, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkBeardGuy;
+ break;
+ case PLAT_CURSOR:
+ gnapUseDeviceOnBeaver();
+ platypusWalkTo(7, 6, 1, 0x107C2, 1);
+ _beaverActionStatus = kASPlatWithBeardGuy;
+ _beaverFacing = 0;
+ playGnapIdle(7, 6);
+ break;
+ }
+ }
+ break;
+
+ case kHSJukebox:
+ _newSceneNum = 15;
+ _isLeavingScene = 1;
+ gnapWalkTo(5, 6, 0, 0x107BC, 1);
+ _gnapActionStatus = kASLeaveScene;
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ case kHSWalkArea4:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene12_updateAnimations();
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = 15;
+ if (_s12_nextToothGuySequenceId == -1) {
+ if (v18 == 0 && _s12_currBeardGuySequenceId == 0x202 && _s12_currBarkeeperSequenceId == 0x203 && _gnapActionStatus < 0 && _beaverActionStatus < 0) {
+ if (getRandom(2) != 0)
+ _s12_nextToothGuySequenceId = 0x1EC;
+ else
+ _s12_nextToothGuySequenceId = 0x204;
+ } else if (_s12_currToothGuySequenceId != 0x200)
+ _s12_nextToothGuySequenceId = 0x200;
+ v18 = (v18 + 1) % 15;
+ }
+ }
+ if (!_timers[5]) {
+ _timers[5] = getRandom(30) + 20;
+ if (_s12_nextBarkeeperSequenceId == -1 && _gnapActionStatus < 0 && _beaverActionStatus < 0) {
+ if (v18 == 0 && _s12_currToothGuySequenceId == 0x200 && _s12_currBeardGuySequenceId == 0x202 && _gnapActionStatus < 0 && _beaverActionStatus < 0) {
+ if (getRandom(2) != 0)
+ _s12_nextBarkeeperSequenceId = 0x208;
+ else
+ _s12_nextBarkeeperSequenceId = 0x1FB;
+ } else
+ _s12_nextBarkeeperSequenceId = 0x203;
+ v18 = (v18 + 1) % 15;
+ }
+ }
+ if (!_timers[6]) {
+ _timers[6] = getRandom(30) + 15;
+ if (_s12_nextBeardGuySequenceId == -1 && _gnapActionStatus < 0 && _beaverActionStatus < 0) {
+ if (v18 == 0 && _s12_currToothGuySequenceId == 0x200 && _s12_currBarkeeperSequenceId == 0x203 && _gnapActionStatus < 0 && _beaverActionStatus < 0)
+ _s12_nextBeardGuySequenceId = 0x1F2;
+ else
+ _s12_nextBeardGuySequenceId = 0x202;
+ v18 = (v18 + 1) % 15;
+ }
+ }
+ if (!_timers[7]) {
+ _timers[7] = getRandom(100) + 100;
+ _gnapRandomValue = getRandom(3);
+ switch (_gnapRandomValue) {
+ case 0:
+ _gameSys->insertSequence(0x8A5 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 1:
+ _gameSys->insertSequence(0x8A7 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 2:
+ _gameSys->insertSequence(0x8A6 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene12_updateHotspots();
+ _timers[4] = 30;
+ _timers[5] = getRandom(30) + 20;
+ _timers[6] = getRandom(30) + 20;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene12_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ case kASTalkToothGuy:
+ if (isKeyStatus1(Common::KEYCODE_j)) {
+ // Easter egg
+ clearKeyStatus1(Common::KEYCODE_j);
+ _s12_nextToothGuySequenceId = 0x206;
+ } else {
+ _s12_nextToothGuySequenceId = 0x1EE;
+ }
+ break;
+ case 3:
+ break;
+ case kASGrabToothGuy:
+ if (isKeyStatus1(Common::KEYCODE_j)) {
+ clearKeyStatus1(Common::KEYCODE_j);
+ _s12_nextToothGuySequenceId = 0x206;
+ } else {
+ _s12_nextToothGuySequenceId = 0x1EF;
+ }
+ break;
+ case kASShowItemToToothGuy:
+ if (isKeyStatus1(Common::KEYCODE_j)) {
+ clearKeyStatus1(Common::KEYCODE_j);
+ _s12_nextToothGuySequenceId = 0x206;
+ } else {
+ _s12_nextToothGuySequenceId = 0x1ED;
+ }
+ break;
+ case kASQuarterWithHoleToToothGuy:
+ if (isKeyStatus1(Common::KEYCODE_j)) {
+ clearKeyStatus1(Common::KEYCODE_j);
+ _s12_nextToothGuySequenceId = 0x206;
+ } else {
+ _s12_nextToothGuySequenceId = 0x1EA;
+ }
+ break;
+ case kASQuarterToToothGuy:
+ if (isKeyStatus1(Common::KEYCODE_j)) {
+ clearKeyStatus1(Common::KEYCODE_j);
+ _s12_nextToothGuySequenceId = 0x206;
+ } else {
+ _s12_nextToothGuySequenceId = 0x1E9;
+ }
+ break;
+ case kASQuarterToToothGuyDone:
+ _gnapActionStatus = -1;
+ showCursor();
+ _gameSys->removeSpriteDrawItem(_largeSprite, 300);
+ deleteSurface(&_largeSprite);
+ setGrabCursorSprite(kItemQuarterWithHole);
+ break;
+ case kASTalkBeardGuy:
+ _s12_nextBeardGuySequenceId = 0x1F4;
+ break;
+ case kASLookBeardGuy:
+ _s12_nextBeardGuySequenceId = 0x1F3;
+ break;
+ case kASGrabBeardGuy:
+ _s12_nextBeardGuySequenceId = 0x1F1;
+ break;
+ case kASShowItemToBeardGuy:
+ _s12_nextBeardGuySequenceId = 0x1F0;
+ break;
+ case kASTalkBarkeeper:
+ _gnapRandomValue = getRandom(2);
+ if (_gnapRandomValue != 0)
+ _s12_nextBarkeeperSequenceId = 0x1FD;
+ else
+ _s12_nextBarkeeperSequenceId = 0x1FF;
+ break;
+ case kASLookBarkeeper:
+ _s12_nextBarkeeperSequenceId = 0x1F8;
+ break;
+ case 14:
+ _s12_nextBarkeeperSequenceId = 0x1F6;
+ break;
+ case kASShowItemToBarkeeper:
+ _s12_nextBarkeeperSequenceId = 0x1F5;
+ break;
+ case kASQuarterWithBarkeeper:
+ _s12_nextBarkeeperSequenceId = 0x1FA;
+ break;
+ case kASPlatWithBarkeeper:
+ _s12_nextBarkeeperSequenceId = 0x1F9;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ _gameSys->setAnimation(0, 0, 1);
+ switch (_beaverActionStatus) {
+ case kASPlatWithToothGuy:
+ _s12_nextToothGuySequenceId = 0x1EB;
+ break;
+ case kASPlatWithBeardGuy:
+ _s12_nextBeardGuySequenceId = 0x1F3;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ if (_s12_currToothGuySequenceId == 0x1E9) {
+ _gameSys->setAnimation(0, 0, 2);
+ hideCursor();
+ _gameSys->setAnimation(0x10843, 301, 0);
+ _gnapActionStatus = kASQuarterToToothGuyDone;
+ _gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300);
+ _gameSys->insertSequence(0x10843, 301, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x107B7, _gnapId, 0x10843, 301,
+ kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gnapSequenceId = 0x7B7;
+ _gnapSequenceDatNum = 1;
+ setFlag(3);
+ invAdd(kItemQuarterWithHole);
+ invRemove(kItemQuarter);
+ }
+ if (_s12_nextToothGuySequenceId == 0x1EF) {
+ _gameSys->setAnimation(_s12_nextToothGuySequenceId, 50, 2);
+ _gameSys->insertSequence(_s12_nextToothGuySequenceId, 50, _s12_currToothGuySequenceId, 50, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x205, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _s12_currToothGuySequenceId = _s12_nextToothGuySequenceId;
+ _s12_nextToothGuySequenceId = -1;
+ _gnapSequenceId = 0x205;
+ _gnapSequenceDatNum = 0;
+ _timers[4] = 40;
+ _timers[2] = getRandom(20) + 70;
+ _timers[3] = getRandom(50) + 200;
+ if (_gnapActionStatus == kASGrabToothGuy)
+ _gnapActionStatus = -1;
+ } else if (_s12_nextToothGuySequenceId != -1) {
+ _gameSys->insertSequence(_s12_nextToothGuySequenceId, 50, _s12_currToothGuySequenceId, 50, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s12_nextToothGuySequenceId, 50, 2);
+ _s12_currToothGuySequenceId = _s12_nextToothGuySequenceId;
+ _s12_nextToothGuySequenceId = -1;
+ _timers[4] = 50;
+ if (_gnapActionStatus >= kASTalkToothGuy && _gnapActionStatus <= kASQuarterToToothGuy && _s12_currToothGuySequenceId != 0x1E9 &&
+ _s12_currToothGuySequenceId != 0x1EC && _s12_currToothGuySequenceId != 0x200)
+ _gnapActionStatus = -1;
+ if (_beaverActionStatus == kASPlatWithToothGuy)
+ _beaverActionStatus = -1;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ if (_gnapActionStatus == kASPlatWithBarkeeper && _s12_currBarkeeperSequenceId == 0x1F9) {
+ _gnapActionStatus = -1;
+ playGnapIdle(7, 6);
+ _timers[5] = 0;
+ }
+ if (_s12_nextBarkeeperSequenceId != -1) {
+ _gameSys->insertSequence(_s12_nextBarkeeperSequenceId, 50, _s12_currBarkeeperSequenceId, 50, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s12_nextBarkeeperSequenceId, 50, 3);
+ _s12_currBarkeeperSequenceId = _s12_nextBarkeeperSequenceId;
+ _s12_nextBarkeeperSequenceId = -1;
+ _timers[5] = getRandom(30) + 20;
+ if (_gnapActionStatus >= kASTalkBarkeeper && _gnapActionStatus <= kASQuarterWithBarkeeper && _s12_currBarkeeperSequenceId != 0x203 &&
+ _s12_currBarkeeperSequenceId != 0x1FB && _s12_currBarkeeperSequenceId != 0x208)
+ _gnapActionStatus = -1;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(4) == 2 && _s12_nextBeardGuySequenceId != -1) {
+ _gameSys->insertSequence(_s12_nextBeardGuySequenceId, 50, _s12_currBeardGuySequenceId, 50, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s12_nextBeardGuySequenceId, 50, 4);
+ _s12_currBeardGuySequenceId = _s12_nextBeardGuySequenceId;
+ _s12_nextBeardGuySequenceId = -1;
+ _timers[6] = getRandom(30) + 20;
+ if (_gnapActionStatus >= kASTalkBeardGuy && _gnapActionStatus <= kASShowItemToBeardGuy && _s12_currBeardGuySequenceId != 0x202 && _s12_currBeardGuySequenceId != 0x1F2)
+ _gnapActionStatus = -1;
+ if (_beaverActionStatus == kASPlatWithBeardGuy)
+ _beaverActionStatus = -1;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene13.cpp b/engines/gnap/scenes/scene13.cpp
new file mode 100644
index 0000000000..c9b4d53917
--- /dev/null
+++ b/engines/gnap/scenes/scene13.cpp
@@ -0,0 +1,455 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitBar = 1,
+ kHSWalkArea1 = 2,
+ kHSBackToilet = 3,
+ kHSFrontToilet = 4,
+ kHSUrinal = 5,
+ kHSScribble = 6,
+ kHSSink = 7,
+ kHSWalkArea2 = 8,
+ kHSDevice = 9,
+ kHSWalkArea3 = 10,
+ kHSWalkArea4 = 11,
+ kHSWalkArea5 = 12,
+ kHSWalkArea6 = 13,
+ kHSWalkArea7 = 14,
+ kHSWalkArea8 = 15,
+ kHSWalkArea9 = 16
+};
+
+enum {
+ kASLeaveScene = 0,
+ kASBackToilet = 1,
+ kASFrontToilet = 2,
+ kASLookScribble = 6,
+ kASGrabSink = 7,
+ kASGrabSinkDone = 8,
+ kASWait = 12,
+ kASGrabUrinal = 13
+};
+
+int GnapEngine::scene13_init() {
+ playSound(0x108EC, 0);
+ return 0xAC;
+}
+
+void GnapEngine::scene13_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitBar, 113, 160, 170, 455, SF_EXIT_L_CURSOR);
+ setHotspot(kHSBackToilet, 385, 195, 478, 367, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSFrontToilet, 497, 182, 545, 432, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSUrinal, 680, 265, 760, 445, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSScribble, 560, 270, 660, 370, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSSink, 310, 520, 560, 599, SF_WALKABLE | SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSWalkArea1, 268, 270, 325, 385);
+ setHotspot(kHSWalkArea2, 0, 0, 52, 599);
+ setHotspot(kHSWalkArea3, 0, 0, 113, 550);
+ setHotspot(kHSWalkArea4, 0, 0, 226, 438);
+ setHotspot(kHSWalkArea5, 0, 0, 268, 400);
+ setHotspot(kHSWalkArea6, 0, 0, 799, 367);
+ setHotspot(kHSWalkArea7, 478, 0, 799, 401);
+ setHotspot(kHSWalkArea8, 545, 0, 799, 473);
+ setHotspot(kHSWalkArea9, 0, 549, 799, 599);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 17;
+}
+
+void GnapEngine::scene13_showScribble() {
+ hideCursor();
+ _largeSprite = _gameSys->createSurface(0x6F);
+ _gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300);
+ 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);
+ _gameSys->removeSpriteDrawItem(_largeSprite, 300);
+ deleteSurface(&_largeSprite);
+ showCursor();
+}
+
+void GnapEngine::scene13_run() {
+ int currSoundId = 0;
+
+ queueInsertDeviceIcon();
+
+ _gameSys->insertSequence(0xAA, 256, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (_prevSceneNum == 14) {
+ initGnapPos(6, 6, 3);
+ initBeaverPos(9, 8, 0);
+ } else {
+ initGnapPos(3, 7, 1);
+ initBeaverPos(2, 7, 0);
+ }
+
+ endSceneInit();
+
+ _timers[4] = getRandom(20) + 20;
+ _timers[5] = getRandom(50) + 50;
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x1091A))
+ playSound(0x1091A, 1);
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene13_updateHotspots();
+ _timers[4] = getRandom(20) + 20;
+ _timers[5] = getRandom(50) + 50;
+ }
+ break;
+
+ case kHSPlatypus:
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0));
+ break;
+ case PLAT_CURSOR:
+ break;
+ }
+ break;
+
+ case kHSExitBar:
+ _isLeavingScene = 1;
+ gnapWalkTo(2, 7, 0, 0x107C0, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(2, 8, -1, -1, 1);
+ if (isFlag(14) || isFlag(15)) {
+ _newSceneNum = 11;
+ } else {
+ setFlag(15);
+ _newSceneNum = 47;
+ }
+ break;
+
+ case kHSBackToilet:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(5, 5, 6, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ case GRAB_CURSOR:
+ case TALK_CURSOR:
+ if (_gnapX == 5 && _gnapY == 5) {
+ _s13_backToiletCtr = MIN(5, _s13_backToiletCtr + 1);
+ _gameSys->setAnimation(_s13_backToiletCtr + 0xA3, _gnapId, 0);
+ _gameSys->insertSequence(_s13_backToiletCtr + 0xA3, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ 9, 0, 0, 0);
+ _gnapActionStatus = kASWait;
+ _gnapSequenceId = _s13_backToiletCtr + 0xA3;
+ _gnapIdleFacing = 7;
+ _gnapSequenceDatNum = 0;
+ } else {
+ gnapWalkTo(5, 5, 0, 0x107BB, 1);
+ _gnapActionStatus = kASBackToilet;
+ _gnapIdleFacing = 7;
+ }
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSFrontToilet:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(6, 7, 7, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ case GRAB_CURSOR:
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ gnapWalkTo(6, 7, 0, 0xA9, 5);
+ _gnapActionStatus = kASFrontToilet;
+ _gnapIdleFacing = 1;
+ break;
+ }
+ }
+ break;
+
+ case kHSScribble:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(7, 7, 8, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ gnapWalkTo(7, 7, 0, 0x107BB, 1);
+ _gnapActionStatus = kASLookScribble;
+ _gnapIdleFacing = 7;
+ break;
+ case GRAB_CURSOR:
+ playGnapScratchingHead(0, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(7, 7, -1, getGnapSequenceId(gskBrainPulsating, 0, 0), 1);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSUrinal:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(8, 7, 9, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapSequence(getGnapSequenceId(gskDeflect, 9, 6));
+ gnapWalkTo(_gnapX, _gnapY, 0, -1, 1);
+ _gnapActionStatus = kASWait;
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(8, 7, 0, -1, 1);
+ _gnapActionStatus = kASGrabUrinal;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSSink:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapSequence(getGnapSequenceId(gskDeflect, 5, 9));
+ gnapWalkTo(_gnapX, _gnapY, 0, -1, 1);
+ _gnapActionStatus = kASWait;
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(4, 8, 0, 0x107B9, 1);
+ _gnapActionStatus = kASGrabSink;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ case kHSWalkArea4:
+ case kHSWalkArea5:
+ case kHSWalkArea6:
+ case kHSWalkArea7:
+ case kHSWalkArea8:
+ case kHSWalkArea9:
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ case kHSWalkArea1:
+ // Nothing
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene13_updateAnimations();
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ if (_platY == 5 || _platY == 6)
+ platypusWalkTo(-1, 7, -1, -1, 1);
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(20) + 20;
+ _gnapRandomValue = getRandom(5);
+ switch (_gnapRandomValue) {
+ case 0:
+ playSound(0xD2, 0);
+ break;
+ case 1:
+ playSound(0xD3, 0);
+ break;
+ case 2:
+ playSound(0xD4, 0);
+ break;
+ case 3:
+ playSound(0xD5, 0);
+ break;
+ case 4:
+ playSound(0xD6, 0);
+ break;
+ }
+ }
+ if (!_timers[5]) {
+ int newSoundId;
+ _timers[5] = getRandom(50) + 50;
+ _gnapRandomValue = getRandom(7);
+ switch (_gnapRandomValue) {
+ case 0:
+ newSoundId = 0xD7;
+ _timers[5] = 2 * getRandom(50) + 100;
+ break;
+ case 1:
+ case 2:
+ newSoundId = 0xCF;
+ break;
+ case 3:
+ case 4:
+ newSoundId = 0xD0;
+ break;
+ default:
+ newSoundId = 0xD1;
+ break;
+ }
+ if (newSoundId != currSoundId) {
+ playSound(newSoundId, 0);
+ currSoundId = newSoundId;
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene13_updateHotspots();
+ _timers[4] = getRandom(20) + 20;
+ _timers[5] = getRandom(50) + 50;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene13_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ _gnapActionStatus = -1;
+ break;
+ case kASBackToilet:
+ _s13_backToiletCtr = MIN(5, _s13_backToiletCtr + 1);
+ _gameSys->insertSequence(_s13_backToiletCtr + 0xA3, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 9, 0, 0, 0);
+ _gnapSequenceId = _s13_backToiletCtr + 0xA3;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = -1;
+ break;
+ case kASFrontToilet:
+ _sceneDone = true;
+ _newSceneNum = 14;
+ break;
+ case kASLookScribble:
+ _gnapActionStatus = -1;
+ scene13_showScribble();
+ break;
+ case kASGrabSink:
+ _gameSys->setAnimation(0xAB, 160, 0);
+ _gameSys->insertSequence(0xAB, 160, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->removeSequence(0xAA, 256, 1);
+ _gnapSequenceId = 0xAB;
+ _gnapId = 160;
+ _gnapIdleFacing = 1;
+ _gnapSequenceDatNum = 0;
+ _gnapX = 4;
+ _gnapY = 8;
+ _timers[2] = 360;
+ _gnapActionStatus = kASGrabSinkDone;
+ break;
+ case kASGrabSinkDone:
+ _gameSys->insertSequence(0xAA, 256, 0, 0, kSeqNone, 0, 0, 0);
+ _gnapActionStatus = -1;
+ break;
+ case kASWait:
+ _gnapActionStatus = -1;
+ break;
+ case kASGrabUrinal:
+ _gameSys->setAnimation(0xA2, 120, 0);
+ _gameSys->insertSequence(0xA2, 120, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0xA2;
+ _gnapId = 120;
+ _gnapIdleFacing = 3;
+ _gnapSequenceDatNum = 0;
+ _gnapX = 4;
+ _gnapY = 6;
+ _timers[2] = 360;
+ _gnapActionStatus = kASWait;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ _gameSys->setAnimation(0, 0, 1);
+ _beaverActionStatus = -1;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene14.cpp b/engines/gnap/scenes/scene14.cpp
new file mode 100644
index 0000000000..4f799db977
--- /dev/null
+++ b/engines/gnap/scenes/scene14.cpp
@@ -0,0 +1,194 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExit = 1,
+ kHSCoin = 2,
+ kHSToilet = 3,
+ kHSDevice = 4
+};
+
+int GnapEngine::scene14_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ return 0x27;
+}
+
+void GnapEngine::scene14_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0);
+ setHotspot(kHSExit, 0, 590, 799, 599, SF_EXIT_D_CURSOR);
+ setHotspot(kHSCoin, 330, 390, 375, 440, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSToilet, 225, 250, 510, 500, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(2))
+ _hotspots[kHSCoin].flags = SF_DISABLED;
+ _hotspotsCount = 5;
+}
+
+void GnapEngine::scene14_run() {
+
+ _largeSprite = 0;
+
+ queueInsertDeviceIcon();
+
+ if (!isFlag(2))
+ _gameSys->insertSequence(0x23, 10, 0, 0, kSeqNone, 0, 0, 0);
+
+ endSceneInit();
+
+ if (!isFlag(2) && invHas(kItemTongs))
+ _largeSprite = _gameSys->createSurface(1);
+
+ if (!isFlag(2)) {
+ _gameSys->insertSequence(0x24, 10, 0x23, 10, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x24;
+ _timers[2] = getRandom(40) + 50;
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene14_updateHotspots();
+ }
+ break;
+
+ case kHSExit:
+ _sceneDone = true;
+ _newSceneNum = 13;
+ break;
+
+ case kHSCoin:
+ if (_grabCursorSpriteIndex == kItemTongs) {
+ invAdd(kItemQuarter);
+ setFlag(2);
+ setGrabCursorSprite(-1);
+ hideCursor();
+ _gameSys->setAnimation(0x26, 10, 0);
+ _gameSys->insertSequence(0x26, 10, _gnapSequenceId, 10, kSeqSyncWait, 0, 0, 0);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playSound(0x108E9, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playSound(0x108E9, 0);
+ break;
+ case GRAB_CURSOR:
+ _gameSys->insertSequence(0x25, 10, _gnapSequenceId, 10, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x23, 10, 0x25, 10, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x23;
+ break;
+ case TALK_CURSOR:
+ playSound((getRandom(5) + 0x8D5) | 0x10000, 0);
+ break;
+ case PLAT_CURSOR:
+ _gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY);
+ break;
+ }
+ }
+ break;
+
+ case kHSToilet:
+ if (_grabCursorSpriteIndex >= 0) {
+ _gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ case GRAB_CURSOR:
+ playSound(0x108B1, 0);
+ break;
+ case TALK_CURSOR:
+ playSound((getRandom(5) + 0x8D5) | 0x10000, 0);
+ break;
+ case PLAT_CURSOR:
+ _gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY);
+ break;
+ }
+ }
+ break;
+
+ default:
+ _mouseClickState.left = false;
+ break;
+
+ }
+
+ scene14_updateAnimations();
+
+ checkGameKeys();
+
+ if (!isFlag(2) && !_timers[2]) {
+ _gameSys->insertSequence(0x24, 10, _gnapSequenceId, 10, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x24;
+ _timers[2] = getRandom(40) + 50;
+ }
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene14_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+ if (_largeSprite)
+ deleteSurface(&_largeSprite);
+
+}
+
+void GnapEngine::scene14_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300);
+ _gameSys->setAnimation(0x10843, 301, 1);
+ _gameSys->insertSequence(0x10843, 301, 0x26, 10, kSeqSyncWait, 0, 0, 0);
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ _gameSys->setAnimation(0, 0, 1);
+ _sceneDone = true;
+ _newSceneNum = 13;
+ _grabCursorSpriteIndex = kItemQuarter;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene15.cpp b/engines/gnap/scenes/scene15.cpp
new file mode 100644
index 0000000000..54eb146fa5
--- /dev/null
+++ b/engines/gnap/scenes/scene15.cpp
@@ -0,0 +1,343 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExit = 1,
+ kHSButton1 = 2,
+ kHSButton2 = 3,
+ kHSButton3 = 4,
+ kHSButton4 = 5,
+ kHSButton5 = 6,
+ kHSButton6 = 7,
+ kHSButtonA = 8,
+ kHSButtonB = 9,
+ kHSButtonC = 10,
+ kHSButtonD = 11,
+ kHSButtonE = 12,
+ kHSButtonF = 13,
+ kHSCoinSlot = 14,
+ kHSPlayButton = 15,
+ kHSDevice = 16
+};
+
+int GnapEngine::scene15_init() {
+ return 0xDD;
+}
+
+void GnapEngine::scene15_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED);
+ setHotspot(kHSExit, 50, 590, 750, 599, SF_EXIT_D_CURSOR);
+ setHotspot(kHSButton1, 210, 425, 260, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSButton2, 280, 425, 325, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSButton3, 340, 425, 385, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSButton4, 400, 425, 445, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSButton5, 460, 425, 510, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSButton6, 520, 425, 560, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSButtonA, 205, 480, 250, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSButtonB, 270, 480, 320, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSButtonC, 335, 480, 380, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSButtonD, 395, 480, 445, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSButtonE, 460, 480, 505, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSButtonF, 515, 480, 560, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSCoinSlot, 585, 475, 620, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSPlayButton, 622, 431, 650, 482, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 17;
+}
+
+void GnapEngine::scene15_run() {
+
+ _s15_currSlotSequenceId = -1;
+ _s15_currUpperButtonSequenceId = -1;
+ _s15_currLowerButtonSequenceId = -1;
+ _s15_nextSlotSequenceId = -1;
+ _s15_nextUpperButtonSequenceId = -1;
+ _s15_nextLowerButtonSequenceId = -1;
+ _s15_currRecordSequenceId = 0xD5;
+ _s15_nextRecordSequenceId = -1;
+
+ _gameSys->setAnimation(0xD5, 1, 0);
+ _gameSys->insertSequence(_s15_currRecordSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ queueInsertDeviceIcon();
+
+ endSceneInit();
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _hotspots[kHSPlatypus].x1 = 0;
+ _hotspots[kHSPlatypus].y1 = 0;
+ _hotspots[kHSPlatypus].x2 = 0;
+ _hotspots[kHSPlatypus].y2 = 0;
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ if (_sceneClickedHotspot >= 0)
+ debug("_sceneClickedHotspot: %d; _verbCursor: %d", _sceneClickedHotspot, _verbCursor);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene15_updateHotspots();
+ }
+ break;
+
+ case kHSExit:
+ _newSceneNum = 12;
+ _isLeavingScene = true;
+ break;
+
+ case kHSCoinSlot:
+ if (_grabCursorSpriteIndex == kItemQuarter || _grabCursorSpriteIndex == kItemQuarterWithHole) {
+ _s15_nextSlotSequenceId = 0xDC; // Insert coin
+ } else if (_grabCursorSpriteIndex == kItemDiceQuarterHole) {
+ _s15_nextSlotSequenceId = 0xDB;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ _gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ case GRAB_CURSOR:
+ playSound(0x108E9, 0);
+ break;
+ case TALK_CURSOR:
+ playSound((getRandom(5) + 0x8D5) | 0x10000, 0);
+ break;
+ case PLAT_CURSOR:
+ _gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY);
+ break;
+ }
+ }
+ break;
+
+ case kHSPlayButton:
+ if (_grabCursorSpriteIndex >= 0) {
+ _gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(12) || isFlag(13))
+ playSound(0x108E9, 0);
+ else
+ _s15_nextSlotSequenceId = 0xDA;
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(12) || isFlag(13))
+ _s15_nextSlotSequenceId = 0xD9;
+ else
+ _s15_nextSlotSequenceId = 0xDA;
+ break;
+ case TALK_CURSOR:
+ playSound((getRandom(5) + 0x8D5) | 0x10000, 0);
+ break;
+ case PLAT_CURSOR:
+ _gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY);
+ break;
+ }
+ }
+ break;
+
+ case kHSButton1:
+ case kHSButton2:
+ case kHSButton3:
+ case kHSButton4:
+ case kHSButton5:
+ case kHSButton6:
+ if (_grabCursorSpriteIndex >= 0) {
+ _gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playSound(0x108E9, 0);
+ break;
+ case GRAB_CURSOR:
+ _s15_nextUpperButtonSequenceId = _sceneClickedHotspot + 0xC5;
+ break;
+ case TALK_CURSOR:
+ playSound((getRandom(5) + 0x8D5) | 0x10000, 0);
+ break;
+ case PLAT_CURSOR:
+ _gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY);
+ break;
+ }
+ }
+ break;
+
+ case kHSButtonA:
+ case kHSButtonB:
+ case kHSButtonC:
+ case kHSButtonD:
+ case kHSButtonE:
+ case kHSButtonF:
+ if (_grabCursorSpriteIndex >= 0) {
+ _gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playSound(0x108E9, 0);
+ break;
+ case GRAB_CURSOR:
+ _s15_nextLowerButtonSequenceId = _sceneClickedHotspot + 0xC5;
+ break;
+ case TALK_CURSOR:
+ playSound((getRandom(5) + 0x8D5) | 0x10000, 0);
+ break;
+ case PLAT_CURSOR:
+ _gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY);
+ break;
+ }
+ }
+ break;
+
+ default:
+ _mouseClickState.left = false;
+ break;
+
+ }
+
+ scene15_updateAnimations();
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene15_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene15_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ if (_isLeavingScene) {
+ _sceneDone = true;
+ } else if (_s15_nextSlotSequenceId != -1) {
+ _gameSys->setAnimation(_s15_nextSlotSequenceId, 1, 0);
+ _gameSys->insertSequence(_s15_nextSlotSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0);
+ _s15_currSlotSequenceId = _s15_nextSlotSequenceId;
+ _s15_nextSlotSequenceId = -1;
+ switch (_s15_currSlotSequenceId) {
+ case 0xDC:
+ if (_grabCursorSpriteIndex == kItemQuarter) {
+ invRemove(kItemQuarter);
+ } else {
+ invRemove(kItemQuarterWithHole);
+ setFlag(13);
+ }
+ setGrabCursorSprite(-1);
+ break;
+ case 0xDB:
+ setFlag(14);
+ setGrabCursorSprite(-1);
+ _s15_nextSlotSequenceId = 0xD8;
+ break;
+ case 0xD9:
+ if (isFlag(12)) {
+ clearFlag(12);
+ invAdd(kItemQuarter);
+ _newGrabCursorSpriteIndex = kItemQuarter;
+ } else if (isFlag(13)) {
+ clearFlag(13);
+ invAdd(kItemQuarterWithHole);
+ _newGrabCursorSpriteIndex = kItemQuarterWithHole;
+ }
+ _newSceneNum = 12;
+ _isLeavingScene = true;
+ break;
+ case 0xD8:
+ case 0xDA:
+ if (_s15_currUpperButtonSequenceId != -1) {
+ _gameSys->removeSequence(_s15_currUpperButtonSequenceId, 1, 1);
+ _s15_currUpperButtonSequenceId = -1;
+ }
+ if (_s15_currLowerButtonSequenceId != -1) {
+ _gameSys->removeSequence(_s15_currLowerButtonSequenceId, 1, 1);
+ _s15_currLowerButtonSequenceId = -1;
+ }
+ break;
+ }
+ } else if (_s15_nextRecordSequenceId != -1) {
+ _gameSys->setAnimation(_s15_nextRecordSequenceId, 1, 0);
+ _gameSys->insertSequence(_s15_nextRecordSequenceId, 1, _s15_currRecordSequenceId, 1, kSeqSyncWait, 0, 0, 0);
+ _s15_currRecordSequenceId = _s15_nextRecordSequenceId;
+ _s15_nextRecordSequenceId = -1;
+ if (_s15_currRecordSequenceId == 0xD3) {
+ invRemove(kItemDiceQuarterHole);
+ _newSceneNum = 16;
+ _isLeavingScene = true;
+ }
+ _gameSys->removeSequence(_s15_currUpperButtonSequenceId, 1, 1);
+ _s15_currUpperButtonSequenceId = -1;
+ _gameSys->removeSequence(_s15_currLowerButtonSequenceId, 1, 1);
+ _s15_currLowerButtonSequenceId = -1;
+ } else if (_s15_nextUpperButtonSequenceId != -1) {
+ _gameSys->setAnimation(_s15_nextUpperButtonSequenceId, 1, 0);
+ if (_s15_currUpperButtonSequenceId == -1)
+ _gameSys->insertSequence(_s15_nextUpperButtonSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0);
+ else
+ _gameSys->insertSequence(_s15_nextUpperButtonSequenceId, 1, _s15_currUpperButtonSequenceId, 1, kSeqSyncWait, 0, 0, 0);
+ _s15_currUpperButtonSequenceId = _s15_nextUpperButtonSequenceId;
+ _s15_nextUpperButtonSequenceId = -1;
+ if (_s15_currLowerButtonSequenceId != -1 && isFlag(14)) {
+ if (_s15_currUpperButtonSequenceId == 0xCC && _s15_currLowerButtonSequenceId == 0xCE)
+ _s15_nextRecordSequenceId = 0xD3;
+ else
+ _s15_nextRecordSequenceId = 0xD4;
+ }
+ } else if (_s15_nextLowerButtonSequenceId != -1) {
+ _gameSys->setAnimation(_s15_nextLowerButtonSequenceId, 1, 0);
+ if (_s15_currLowerButtonSequenceId == -1)
+ _gameSys->insertSequence(_s15_nextLowerButtonSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0);
+ else
+ _gameSys->insertSequence(_s15_nextLowerButtonSequenceId, 1, _s15_currLowerButtonSequenceId, 1, kSeqSyncWait, 0, 0, 0);
+ _s15_currLowerButtonSequenceId = _s15_nextLowerButtonSequenceId;
+ _s15_nextLowerButtonSequenceId = -1;
+ if (_s15_currUpperButtonSequenceId != -1 && isFlag(14)) {
+ if (_s15_currUpperButtonSequenceId == 0xCC && _s15_currLowerButtonSequenceId == 0xCE)
+ _s15_nextRecordSequenceId = 0xD3;
+ else
+ _s15_nextRecordSequenceId = 0xD4;
+ }
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene16.cpp b/engines/gnap/scenes/scene16.cpp
new file mode 100644
index 0000000000..dfc852293e
--- /dev/null
+++ b/engines/gnap/scenes/scene16.cpp
@@ -0,0 +1,82 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+void GnapEngine::scene16_initCutscene() {
+ _s99_dword_47F370[0] = 0x1F2;
+ _s99_dword_47F370[1] = 0x201;
+ _s99_dword_47F370[2] = 0x1FC;
+ _s99_dword_47F370[3] = 0x1F4;
+ _s99_dword_47F370[4] = 0x1FB;
+ _s99_dword_47F370[5] = 0x1F0;
+ _s99_dword_47F370[6] = 0x1FD;
+ _s99_dword_47F370[7] = 0x1FE;
+ _s99_dword_47F370[8] = 0x1F7;
+ _s99_dword_47F370[9] = 0x1F9;
+ _s99_dword_47F370[10] = 0x1F8;
+ _s99_dword_47F370[11] = 0x1F1;
+ _s99_dword_47F370[12] = 0x202;
+ _s99_dword_47F370[13] = 0x1F6;
+ _s99_dword_47F370[14] = 0x1F3;
+ _s99_dword_47F370[15] = 0x1FA;
+ _s99_dword_47F370[16] = 0x1FF;
+ _s99_dword_47F370[17] = 0x200;
+ _s99_dword_47F370[18] = 0x203;
+ _s99_dword_47F370[19] = 0x206;
+ _s99_dword_47F370[20] = 0x207;
+ _s99_dword_47F370[21] = 0x204;
+ _s99_dword_47F370[22] = 0x205;
+ _s99_dword_47F2F0[0] = 0x1C;
+ _s99_dword_47F2F0[1] = 2;
+ _s99_dword_47F2F0[2] = 0x1B;
+ _s99_dword_47F2F0[3] = 0;
+ _s99_dword_47F2F0[4] = 0x167;
+ _s99_dword_47F2F0[5] = 1;
+ _s99_dword_47F2F0[6] = 0x15B;
+ _s99_dword_47F2F0[7] = 0x15A;
+ _s99_dword_47F2F0[8] = 0x170;
+ _s99_dword_47F2F0[9] = 0x1EB;
+ _s99_dword_47F2F0[10] = 0x1EC;
+ _s99_dword_47F2F0[11] = 0x1BE;
+ _s99_dword_47F2F0[12] = 0x1BF;
+ _s99_dword_47F330[0] = 4;
+ _s99_dword_47F330[1] = 1;
+ _s99_dword_47F330[2] = 1;
+ _s99_dword_47F330[3] = 6;
+ _s99_dword_47F330[4] = 1;
+ _s99_dword_47F330[5] = 3;
+ _s99_dword_47F330[6] = 1;
+ _s99_dword_47F330[7] = 1;
+ _s99_dword_47F330[8] = 1;
+ _s99_dword_47F330[9] = 1;
+ _s99_dword_47F330[10] = 1;
+ _s99_dword_47F330[11] = 1;
+ _s99_dword_47F330[12] = 1;
+ _s99_itemsCount = 13;
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene17.cpp b/engines/gnap/scenes/scene17.cpp
new file mode 100644
index 0000000000..5b7c54c0a8
--- /dev/null
+++ b/engines/gnap/scenes/scene17.cpp
@@ -0,0 +1,846 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSPhone1 = 1,
+ kHSPhone2 = 2,
+ kHSExitGrubCity = 3,
+ kHSDevice = 4,
+ kHSExitToyStore = 5,
+ kHSWrench = 6,
+ kHSWalkArea1 = 7,
+ kHSWalkArea2 = 8,
+ kHSWalkArea3 = 9
+};
+
+enum {
+ kASTryGetWrench = 0,
+ kASGetWrench2 = 1,
+ kASGetWrenchDone = 2,
+ kASGetWrench1 = 3,
+ kASPlatUsePhone = 4,
+ kASPutCoinIntoPhone = 5,
+ kASGetCoinFromPhone = 6,
+ kASGetCoinFromPhoneDone = 7,
+ kASPutCoinIntoPhoneDone = 8,
+ kASGnapUsePhone = 9,
+ kASGetWrenchGnapReady = 10,
+ kASGnapHangUpPhone = 11,
+ kASPlatPhoningAssistant = 12,
+ kASPlatHangUpPhone = 14,
+ kASLeaveScene = 15
+};
+
+int GnapEngine::scene17_init() {
+ return 0x263;
+}
+
+void GnapEngine::scene17_updateHotspots() {
+ setHotspot(kHSPlatypus, 1, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSPhone1, 61, 280, 97, 322, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 7);
+ setHotspot(kHSPhone2, 80, 204, 178, 468, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 7);
+ setHotspot(kHSExitGrubCity, 196, 207, 280, 304, SF_EXIT_U_CURSOR, 3, 5);
+ setHotspot(kHSExitToyStore, 567, 211, 716, 322, SF_EXIT_U_CURSOR, 5, 6);
+ setHotspot(kHSWrench, 586, 455, 681, 547, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 7);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 434);
+ setHotspot(kHSWalkArea2, 541, 0, 800, 600);
+ setHotspot(kHSWalkArea3, 0, 204, 173, 468);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(6))
+ _hotspots[kHSWrench].flags = 0;
+ if (isFlag(26)) {
+ _hotspots[kHSDevice].flags = SF_DISABLED;
+ _hotspots[kHSPlatypus].flags = SF_DISABLED;
+ }
+ _hotspotsCount = 10;
+}
+
+void GnapEngine::scene17_update() {
+ gameUpdateTick();
+ updateMouseCursor();
+ updateGrabCursorSprite(0, 0);
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+}
+
+void GnapEngine::scene17_platHangUpPhone() {
+ int savedGnapActionStatus = _gnapActionStatus;
+
+ if (_beaverActionStatus == kASPlatPhoningAssistant) {
+ _gnapActionStatus = kASPlatHangUpPhone;
+ updateMouseCursor();
+ _s17_platPhoneCtr = 0;
+ _beaverActionStatus = -1;
+ _gameSys->setAnimation(0x257, 254, 4);
+ _gameSys->insertSequence(0x257, 254, _s17_currPhoneSequenceId, 254, 32, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(4) != 2)
+ gameUpdateTick();
+ _gameSys->setAnimation(0x25B, _beaverId, 1);
+ _gameSys->insertSequence(0x25B, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0);
+ _beaverSequenceId = 0x25B;
+ _beaverSequenceDatNum = 0;
+ _s17_currPhoneSequenceId = -1;
+ _s17_nextPhoneSequenceId = -1;
+ clearFlag(26);
+ while (_gameSys->getAnimationStatus(1) != 2)
+ gameUpdateTick();
+ _gnapActionStatus = savedGnapActionStatus;
+ updateMouseCursor();
+ }
+ scene17_updateHotspots();
+}
+
+void GnapEngine::scene17_run() {
+
+ playSound(0x10940, 1);
+ startSoundTimerA(8);
+ _sceneWaiting = false;
+ _timers[4] = getRandom(100) + 200;
+ _timers[3] = 200;
+ _timers[5] = getRandom(30) + 80;
+ _timers[6] = getRandom(30) + 200;
+ _timers[7] = getRandom(100) + 100;
+
+ if (isFlag(9)) {
+ _gameSys->insertSequence(0x25F, 20, 0, 0, kSeqNone, 0, 0, 0);
+ } else {
+ if (_s18_garbageCanPos >= 8) {
+ _gameSys->insertSequence(0x260, 20, 0, 0, kSeqNone, 0, 97, 1);
+ } else if (_s18_garbageCanPos >= 6) {
+ _gameSys->insertSequence(0x260, 20, 0, 0, kSeqNone, 0, 68, 2);
+ } else if (_s18_garbageCanPos >= 5) {
+ _gameSys->insertSequence(0x260, 20, 0, 0, kSeqNone, 0, 23, -1);
+ } else if (_s18_garbageCanPos >= 4) {
+ _gameSys->insertSequence(0x260, 20, 0, 0, kSeqNone, 0, -11, -5);
+ } else {
+ _gameSys->insertSequence(0x260, 20, 0, 0, kSeqNone, 0, -54, -8);
+ }
+ }
+
+ if (isFlag(19))
+ _gameSys->insertSequence(0x262, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ queueInsertDeviceIcon();
+
+ if (isFlag(6))
+ _s17_currWrenchSequenceId = 0x22D;
+ else
+ _s17_currWrenchSequenceId = 0x22F;
+
+ _s17_currCarWindowSequenceId = 0x244;
+
+ if (isFlag(14))
+ _gameSys->insertSequence(0x261, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ _gameSys->setAnimation(_s17_currWrenchSequenceId, 40, 2);
+ _gameSys->insertSequence(_s17_currWrenchSequenceId, 40, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(6)) {
+ _gameSys->setAnimation(0, 0, 3);
+ } else {
+ _gameSys->setAnimation(_s17_currCarWindowSequenceId, 40, 3);
+ _gameSys->insertSequence(_s17_currCarWindowSequenceId, 40, 0, 0, kSeqNone, 0, 0, 0);
+ }
+
+ _s17_canTryGetWrench = true;
+
+ if (isFlag(18))
+ _gameSys->insertSequence(0x24F, 100, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (_prevSceneNum == 53 || _prevSceneNum == 18 || _prevSceneNum == 20 || _prevSceneNum == 19) {
+ if (_prevSceneNum == 20) {
+ initGnapPos(4, 6, 1);
+ initBeaverPos(5, 6, 0);
+ endSceneInit();
+ platypusWalkTo(5, 9, -1, 0x107C2, 1);
+ gnapWalkTo(4, 8, -1, 0x107B9, 1);
+ } else if (isFlag(27)) {
+ initGnapPos(3, 9, 5);
+ _platX = _hotspotsWalkPos[2].x;
+ _platY = _hotspotsWalkPos[2].y;
+ _beaverId = 20 * _hotspotsWalkPos[2].y;
+ _gameSys->insertSequence(0x25A, 20 * _hotspotsWalkPos[2].y, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x257, 254, 0, 0, kSeqNone, 0, 0, 0);
+ _beaverSequenceId = 0x25A;
+ _beaverSequenceDatNum = 0;
+ endSceneInit();
+ clearFlag(15);
+ clearFlag(16);
+ _beaverActionStatus = kASPlatPhoningAssistant;
+ scene17_platHangUpPhone();
+ _gameSys->setAnimation(0, 0, 4);
+ clearFlag(26);
+ clearFlag(27);
+ scene17_updateHotspots();
+ } else if (isFlag(25)) {
+ clearFlag(15);
+ clearFlag(16);
+ initBeaverPos(7, 9, 0);
+ _gnapX = _hotspotsWalkPos[2].x;
+ _gnapY = _hotspotsWalkPos[2].y;
+ _gnapId = 20 * _hotspotsWalkPos[2].y;
+ _gameSys->insertSequence(601, 20 * _hotspotsWalkPos[2].y, 0, 0, kSeqNone, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 601;
+ _gnapActionStatus = kASGnapHangUpPhone;
+ clearFlag(25);
+ _gameSys->insertSequence(0x251, 254, 0, 0, kSeqNone, 0, 0, 0);
+ endSceneInit();
+ _gameSys->setAnimation(0x257, 254, 0);
+ _gameSys->insertSequence(0x257, 254, 0x251, 254, kSeqSyncWait, 0, 0, 0);
+ } else if (isFlag(26)) {
+ clearFlag(15);
+ clearFlag(16);
+ _sceneWaiting = true;
+ initGnapPos(3, 9, 5);
+ _platX = _hotspotsWalkPos[2].x;
+ _platY = _hotspotsWalkPos[2].y;
+ _beaverId = 20 * _hotspotsWalkPos[2].y;
+ _s17_currPhoneSequenceId = 0x251;
+ _gameSys->insertSequence(0x25A, 20 * _hotspotsWalkPos[2].y, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(_s17_currPhoneSequenceId, 254, 0, 0, kSeqNone, 0, 0, 0);
+ _beaverSequenceId = 0x25A;
+ _beaverSequenceDatNum = 0;
+ endSceneInit();
+ _gameSys->setAnimation(_s17_currPhoneSequenceId, 254, 1);
+ _beaverActionStatus = kASPlatPhoningAssistant;
+ scene17_updateHotspots();
+ } else if (_prevSceneNum == 18) {
+ initGnapPos(6, 6, 1);
+ initBeaverPos(5, 6, 0);
+ endSceneInit();
+ platypusWalkTo(5, 9, -1, 0x107C2, 1);
+ gnapWalkTo(4, 8, -1, 0x107B9, 1);
+ } else {
+ if (isFlag(15)) {
+ initGnapPos(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 1);
+ initBeaverPos(1, 9, 0);
+ endSceneInit();
+ } else {
+ initGnapPos(3, 7, 1);
+ initBeaverPos(1, 7, 0);
+ endSceneInit();
+ }
+ clearFlag(15);
+ clearFlag(16);
+ endSceneInit();
+ }
+ } else {
+ _gnapX = 3;
+ _gnapY = 6;
+ _gnapId = 120;
+ _gnapSequenceId = 0x23D;
+ _gnapSequenceDatNum = 0;
+ _gnapIdleFacing = 1;
+ _gameSys->insertSequence(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0, 0, kSeqNone, 0, 0, 0);
+ _platX = -1;
+ _platY = 8;
+ _beaverId = 160;
+ _gameSys->insertSequence(0x241, 160, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x107C1, _beaverId, 0x241, _beaverId,
+ 9, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY);
+ _gameSys->insertSequence(0x22C, 2, 0, 0, kSeqNone, 0, 0, 0);
+ // TODO delayTicksA(2, 9);
+ endSceneInit();
+ _beaverSequenceId = 0x7C1;
+ _beaverSequenceDatNum = 1;
+ _beaverFacing = 1;
+ platypusWalkTo(2, 9, -1, 0x107C2, 1);
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0 || _gnapActionStatus == 3) {
+ runMenu();
+ scene17_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ if (isFlag(6)) {
+ gnapUseJointOnPlatypus();
+ } else {
+ gnapUseDeviceOnBeaver();
+ platypusWalkTo(_hotspotsWalkPos[6].x, _hotspotsWalkPos[6].y, 1, 0x107C2, 1);
+ gnapWalkTo(_hotspotsWalkPos[6].x + 1, _hotspotsWalkPos[6].y, 0, 0x107BA, 1);
+ _beaverActionStatus = kASGetWrench1;
+ _gnapActionStatus = kASGetWrench1;
+ _timers[5] = getRandom(30) + 80;
+ setGrabCursorSprite(-1);
+ invRemove(kItemJoint);
+ }
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapScratchingHead(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ case GRAB_CURSOR:
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSWrench:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(6)) {
+ playGnapImpossible(0, 0);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 8, 7);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ case GRAB_CURSOR:
+ playGnapScratchingHead(8, 7);
+ break;
+ case TALK_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case PLAT_CURSOR:
+ if (_s17_canTryGetWrench) {
+ scene17_platHangUpPhone();
+ gnapUseDeviceOnBeaver();
+ platypusWalkTo(_hotspotsWalkPos[6].x + 1, _hotspotsWalkPos[6].y, 1, 0x107C2, 1);
+ _beaverActionStatus = kASTryGetWrench;
+ _gnapActionStatus = kASTryGetWrench;
+ _timers[5] = getRandom(30) + 80;
+ } else
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSPhone1:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemDiceQuarterHole) {
+ gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASPutCoinIntoPhone;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 1, 3);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(1, 3);
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(18)) {
+ scene17_platHangUpPhone();
+ gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y) | 0x10000, 1);
+ _gnapActionStatus = kASGetCoinFromPhone;
+ } else
+ playGnapImpossible(0, 0);
+ break;
+ case TALK_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case PLAT_CURSOR:
+ if (isFlag(18)) {
+ scene17_platHangUpPhone();
+ _isLeavingScene = true;
+ gnapUseDeviceOnBeaver();
+ _beaverFacing = 5;
+ platypusWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 1, 0x107C2, 1);
+ setFlag(16);
+ _beaverActionStatus = kASPlatUsePhone;
+ _gnapActionStatus = kASPlatUsePhone;
+ } else
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSPhone2:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemDiceQuarterHole) {
+ gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASPutCoinIntoPhone;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 1, 3);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(1, 3);
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(18)) {
+ scene17_platHangUpPhone();
+ _isLeavingScene = true;
+ _gnapIdleFacing = 5;
+ gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASGnapUsePhone;
+ setFlag(15);
+ } else
+ playGnapImpossible(0, 0);
+ break;
+ case TALK_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case PLAT_CURSOR:
+ if (isFlag(18)) {
+ scene17_platHangUpPhone();
+ _isLeavingScene = true;
+ gnapUseDeviceOnBeaver();
+ _beaverFacing = 5;
+ platypusWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 1, 0x107C2, 1);
+ setFlag(16);
+ _beaverActionStatus = kASPlatUsePhone;
+ _gnapActionStatus = kASPlatUsePhone;
+ } else
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitToyStore:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 18;
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[5].x, _hotspotsWalkPos[5].y, 0, 0x107BB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (_beaverActionStatus != kASPlatPhoningAssistant)
+ platypusWalkTo(_hotspotsWalkPos[5].x - 1, _hotspotsWalkPos[5].y, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSExitGrubCity:
+ if (_gnapActionStatus < 0) {
+ scene17_platHangUpPhone();
+ _isLeavingScene = true;
+ _newSceneNum = 20;
+ _gnapIdleFacing = 5;
+ gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, 0x107BC, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[3].x + 1, _hotspotsWalkPos[3].y, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = 0;
+ }
+ break;
+ }
+
+ scene17_updateAnimations();
+
+ if (!isSoundPlaying(0x10940))
+ playSound(0x10940, 1);
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0)
+ beaverSub426234();
+ updateGnapIdleSequence2();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(100) + 200;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0)
+ _gameSys->insertSequence(0x22B, 21, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ if (!_timers[7]) {
+ _timers[7] = getRandom(100) + 100;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0) {
+ switch (getRandom(3)) {
+ case 0:
+ _gameSys->insertSequence(0x25C, 255, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 1:
+ _gameSys->insertSequence(0x25D, 255, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 2:
+ _gameSys->insertSequence(0x25E, 255, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ }
+ }
+ }
+ if (_beaverActionStatus < 0 && !_timers[5]) {
+ _timers[5] = getRandom(30) + 80;
+ if (isFlag(6) && _s17_nextWrenchSequenceId == -1) {
+ _s17_nextWrenchSequenceId = 0x236;
+ } else if (_s17_canTryGetWrench) {
+ switch (getRandom(6)) {
+ case 0:
+ _s17_nextWrenchSequenceId = 0x231;
+ break;
+ case 1:
+ _s17_nextWrenchSequenceId = 0x232;
+ break;
+ case 2:
+ case 3:
+ _s17_nextWrenchSequenceId = 0x23C;
+ break;
+ case 4:
+ case 5:
+ _s17_nextWrenchSequenceId = 0x22E;
+ break;
+ }
+ } else {
+ --_s17_wrenchCtr;
+ if (_s17_wrenchCtr) {
+ switch (getRandom(6)) {
+ case 0:
+ _s17_nextWrenchSequenceId = 0x237;
+ break;
+ case 1:
+ _s17_nextWrenchSequenceId = 0x238;
+ break;
+ case 2:
+ _s17_nextWrenchSequenceId = 0x239;
+ break;
+ case 3:
+ _s17_nextWrenchSequenceId = 0x23A;
+ break;
+ case 4:
+ _s17_nextWrenchSequenceId = 0x23B;
+ break;
+ case 5:
+ _s17_nextWrenchSequenceId = 0x235;
+ break;
+ }
+ } else {
+ _s17_wrenchCtr = 2;
+ _s17_nextWrenchSequenceId = 0x235;
+ }
+ }
+ }
+ if (!_timers[6]) {
+ _timers[6] = getRandom(30) + 200;
+ if (_s17_nextCarWindowSequenceId == -1 && !isFlag(6))
+ _s17_nextCarWindowSequenceId = 0x246;
+ }
+ playSoundA();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene17_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene17_updateAnimations() {
+
+ static const int kPlatPhoneSequenceIds[] = {
+ 0x251, 0x252, 0x253, 0x254, 0x255, 0x256, 0x257
+ };
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASGetWrench1:
+ _gnapActionStatus = kASGetWrenchGnapReady;
+ break;
+ case kASGetCoinFromPhone:
+ playGnapPullOutDevice(1, 3);
+ playGnapUseDevice(0, 0);
+ _gameSys->setAnimation(0x250, 100, 0);
+ _gameSys->insertSequence(0x250, 100, 591, 100, kSeqSyncWait, 0, 0, 0);
+ invAdd(kItemDiceQuarterHole);
+ clearFlag(18);
+ _gnapActionStatus = kASGetCoinFromPhoneDone;
+ break;
+ case kASGetCoinFromPhoneDone:
+ setGrabCursorSprite(kItemDiceQuarterHole);
+ _gnapActionStatus = -1;
+ break;
+ case kASPutCoinIntoPhone:
+ _gameSys->setAnimation(0x24C, _gnapId, 0);
+ _gameSys->insertSequence(0x24C, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x24C;
+ invRemove(kItemDiceQuarterHole);
+ setGrabCursorSprite(-1);
+ setFlag(18);
+ _gnapActionStatus = kASPutCoinIntoPhoneDone;
+ break;
+ case kASPutCoinIntoPhoneDone:
+ _gameSys->insertSequence(0x24F, 100, 0, 0, kSeqNone, 0, 0, 0);
+ _gnapActionStatus = -1;
+ break;
+ case kASGnapUsePhone:
+ _gameSys->setAnimation(0x24D, _gnapId, 0);
+ _gameSys->insertSequence(0x24D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapActionStatus = kASLeaveScene;
+ _newSceneNum = 53;
+ break;
+ case kASGnapHangUpPhone:
+ _gameSys->insertSequence(0x258, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x258;
+ _gnapActionStatus = -1;
+ break;
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ _gameSys->setAnimation(0, 0, 1);
+ switch (_beaverActionStatus) {
+ case kASTryGetWrench:
+ _beaverActionStatus = -1;
+ ++_s17_platTryGetWrenchCtr;
+ if (_s17_platTryGetWrenchCtr % 2 != 0)
+ _s17_nextWrenchSequenceId = 0x233;
+ else
+ _s17_nextWrenchSequenceId = 0x234;
+ _s17_canTryGetWrench = false;
+ break;
+ case kASGetWrench1:
+ _s17_nextWrenchSequenceId = 0x230;
+ break;
+ case kASGetWrench2:
+ _s17_nextCarWindowSequenceId = 0x249;
+ break;
+ case kASGetWrenchDone:
+ _beaverActionStatus = -1;
+ invAdd(kItemWrench);
+ setGrabCursorSprite(kItemWrench);
+ break;
+ case kASPlatUsePhone:
+ _gameSys->setAnimation(0x24E, _beaverId, 1);
+ _gameSys->insertSequence(0x24E, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0);
+ _beaverSequenceDatNum = 0;
+ _beaverSequenceId = 0x24E;
+ _beaverActionStatus = kASLeaveScene;
+ _newSceneNum = 53;
+ break;
+ case kASPlatPhoningAssistant:
+ ++_s17_platPhoneCtr;
+ if (_s17_platPhoneCtr >= 7) {
+ _s17_platPhoneCtr = 0;
+ _s17_nextPhoneSequenceId = -1;
+ _s17_currPhoneSequenceId = -1;
+ _gameSys->insertSequence(0x25B, _beaverId, 0x25A, _beaverId, kSeqSyncWait, 0, 0, 0);
+ _beaverSequenceDatNum = 0;
+ _beaverSequenceId = 0x25B;
+ _beaverActionStatus = -1;
+ clearFlag(26);
+ _sceneWaiting = false;
+ scene17_updateHotspots();
+ } else {
+ _s17_nextPhoneSequenceId = kPlatPhoneSequenceIds[_s17_platPhoneCtr];
+ _gameSys->setAnimation(_s17_nextPhoneSequenceId, 254, 1);
+ _gameSys->insertSequence(_s17_nextPhoneSequenceId, 254, _s17_currPhoneSequenceId, 254, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x25A, _beaverId, 0x25A, _beaverId, kSeqSyncWait, 0, 0, 0);
+ _beaverSequenceDatNum = 0;
+ _beaverSequenceId = 0x25A;
+ _s17_currPhoneSequenceId = _s17_nextPhoneSequenceId;
+ }
+ break;
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ switch (_s17_nextWrenchSequenceId) {
+ case 0x233:
+ _gnapActionStatus = -1;
+ _gameSys->insertSequence(0x243, _beaverId,
+ _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId,
+ kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(_s17_nextWrenchSequenceId, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _s17_currWrenchSequenceId = _s17_nextWrenchSequenceId;
+ _s17_nextWrenchSequenceId = -1;
+ _beaverSequenceId = 0x243;
+ _beaverSequenceDatNum = 0;
+ _gameSys->setAnimation(0x243, _beaverId, 1);
+ break;
+ case 0x234:
+ _gnapActionStatus = -1;
+ _gameSys->insertSequence(0x242, _beaverId,
+ _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId,
+ kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(_s17_nextWrenchSequenceId, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _s17_currWrenchSequenceId = _s17_nextWrenchSequenceId;
+ _s17_nextWrenchSequenceId = -1;
+ _beaverSequenceId = 0x242;
+ _beaverSequenceDatNum = 0;
+ _gameSys->setAnimation(0x242, _beaverId, 1);
+ break;
+ case 0x231:
+ if (getRandom(2) != 0)
+ _s17_nextCarWindowSequenceId = 0x245;
+ else
+ _s17_nextCarWindowSequenceId = 0x248;
+ _gameSys->setAnimation(0, 0, 2);
+ break;
+ case 0x232:
+ _s17_nextCarWindowSequenceId = 0x247;
+ _gameSys->setAnimation(0, 0, 2);
+ break;
+ case 0x22E:
+ case 0x235:
+ if (_s17_nextWrenchSequenceId == 0x235)
+ _hotspots[kHSWrench].flags &= ~SF_DISABLED;
+ else
+ _hotspots[kHSWrench].flags |= SF_DISABLED;
+ _s17_canTryGetWrench = !_s17_canTryGetWrench;
+ _gameSys->setAnimation(_s17_nextWrenchSequenceId, 40, 2);
+ _gameSys->insertSequence(_s17_nextWrenchSequenceId, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _s17_currWrenchSequenceId = _s17_nextWrenchSequenceId;
+ _s17_nextWrenchSequenceId = -1;
+ break;
+ case 0x230:
+ if (_gnapActionStatus == kASGetWrenchGnapReady) {
+ _gameSys->setAnimation(0, 0, 2);
+ if (_s17_canTryGetWrench) {
+ _gameSys->insertSequence(0x22E, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _s17_currWrenchSequenceId = 0x22E;
+ _s17_canTryGetWrench = false;
+ }
+ _gameSys->setAnimation(0x23F, _beaverId, 1);
+ _gameSys->insertSequence(0x10875, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x23F, _beaverId,
+ _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId,
+ kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceDatNum = 1;
+ _beaverSequenceDatNum = 0;
+ _gnapSequenceId = 0x875;
+ _beaverSequenceId = 0x23F;
+ gnapWalkTo(3, 8, -1, 0x107B9, 1);
+ _beaverActionStatus = kASGetWrench2;
+ }
+ break;
+ default:
+ if (_s17_nextWrenchSequenceId != -1) {
+ _gameSys->setAnimation(_s17_nextWrenchSequenceId, 40, 2);
+ _gameSys->insertSequence(_s17_nextWrenchSequenceId, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _s17_currWrenchSequenceId = _s17_nextWrenchSequenceId;
+ _s17_nextWrenchSequenceId = -1;
+ }
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ switch (_s17_nextCarWindowSequenceId) {
+ case 0x246:
+ _gameSys->setAnimation(_s17_nextCarWindowSequenceId, 40, 3);
+ _gameSys->insertSequence(_s17_nextCarWindowSequenceId, 40, _s17_currCarWindowSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _s17_currCarWindowSequenceId = _s17_nextCarWindowSequenceId;
+ _s17_nextCarWindowSequenceId = -1;
+ break;
+ case 0x245:
+ case 0x247:
+ case 0x248:
+ _gameSys->setAnimation(_s17_nextWrenchSequenceId, 40, 2);
+ _gameSys->insertSequence(_s17_nextWrenchSequenceId, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(2) != 2)
+ scene17_update();
+ _gameSys->setAnimation(_s17_nextCarWindowSequenceId, 40, 3);
+ _gameSys->insertSequence(_s17_nextCarWindowSequenceId, 40, _s17_currCarWindowSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _s17_currCarWindowSequenceId = _s17_nextCarWindowSequenceId;
+ _s17_nextCarWindowSequenceId = -1;
+ _s17_currWrenchSequenceId = _s17_nextWrenchSequenceId;
+ _s17_nextWrenchSequenceId = -1;
+ break;
+ case 0x249:
+ _gameSys->setAnimation(0x230, 40, 2);
+ _gameSys->setAnimation(0x240, _beaverId, 1);
+ _gameSys->insertSequence(0x230, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(_s17_nextCarWindowSequenceId, 40, _s17_currCarWindowSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x240, _beaverId, _beaverSequenceId, _beaverId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x23E, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x23E;
+ _gnapSequenceDatNum = 0;
+ _beaverSequenceId = 0x240;
+ _beaverSequenceDatNum = 0;
+ _gameSys->setAnimation(0x24A, 40, 3);
+ _gameSys->insertSequence(0x24A, 40, _s17_nextCarWindowSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(2) != 2) {
+ scene17_update();
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ _gameSys->setAnimation(0x24A, 40, 3);
+ _gameSys->insertSequence(0x24A, 40, 586, 40, kSeqSyncWait, 0, 0, 0);
+ }
+ }
+ _gameSys->insertSequence(0x22D, 40, 560, 40, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x24B, 40, 3);
+ _gameSys->insertSequence(0x24B, 40, 586, 40, kSeqSyncWait, 0, 0, 0);
+ _s17_currCarWindowSequenceId = 0x24B;
+ _s17_nextCarWindowSequenceId = -1;
+ _s17_currWrenchSequenceId = 0x22D;
+ _s17_nextWrenchSequenceId = -1;
+ setFlag(6);
+ _gnapActionStatus = -1;
+ _beaverActionStatus = 2;
+ scene17_updateHotspots();
+ _timers[5] = getRandom(30) + 80;
+ break;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene18.cpp b/engines/gnap/scenes/scene18.cpp
new file mode 100644
index 0000000000..619d50f5e2
--- /dev/null
+++ b/engines/gnap/scenes/scene18.cpp
@@ -0,0 +1,1026 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+static const int kScene18SequenceIds[] = {
+ 0x219, 0x21A, 0x21B, 0x21C, 0x21D
+};
+
+enum {
+ kHSPlatypus = 0,
+ kHSGarbageCan = 1,
+ kHSDevice = 2,
+ kHSExitToyStore = 3,
+ kHSExitPhoneBooth = 4,
+ kHSExitGrubCity = 5,
+ kHSHydrantTopValve = 6,
+ kHSHydrantRightValve = 7,
+ kHSCowboyHat = 8,
+ kHSWalkArea1 = 9,
+ kHSWalkArea2 = 10
+};
+
+enum {
+ kASOpenRightValveNoGarbageCanDone = 0,
+ kASOpenRightValveNoGarbageCan = 1,
+ kASCloseRightValveNoGarbageCan = 2,
+ kASOpenTopValveDone = 3,
+ kASOpenTopValve = 4,
+ kASCloseTopValve = 5,
+ kASGrabGarbageCanFromStreet = 6,
+ kASGrabCowboyHat = 7,
+ kASGrabGarbageCanFromHydrant = 8,
+ kASPutGarbageCanOnRunningHydrant = 9,
+ kASPutGarbageCanOnRunningHydrant2 = 10,
+ kASGrabCowboyHatDone = 11,
+ kASStandingOnHydrant = 12,
+ kASOpenRightValveWithGarbageCan = 13,
+ kASOpenRightValveWithGarbageCanDone = 14,
+ kASCloseRightValveWithGarbageCan = 15,
+ kASPutGarbageCanOnHydrant = 16,
+ kASPutGarbageCanOnHydrantDone = 17,
+ kASPlatComesHere = 18,
+ kASCloseRightValveWithGarbageCanDone = 19,
+ kASLeaveScene = 20
+};
+
+int GnapEngine::scene18_init() {
+ _gameSys->setAnimation(0, 0, 3);
+ return 0x222;
+}
+
+void GnapEngine::scene18_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSGarbageCan, _gridMinX + 75 * _s18_garbageCanPos - 35, _gridMinY + 230, _gridMinX + 75 * _s18_garbageCanPos + 35, _gridMinY + 318,
+ SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, _s18_garbageCanPos, 7);
+ setHotspot(kHSExitToyStore, 460, 238, 592, 442, SF_EXIT_U_CURSOR, 7, 7);
+ setHotspot(kHSExitPhoneBooth, 275, 585, 525, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 10);
+ setHotspot(kHSExitGrubCity, 0, 350, 15, 600, SF_EXIT_L_CURSOR, 0, 9);
+ setHotspot(kHSHydrantTopValve, 100, 345, 182, 410, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 8);
+ setHotspot(kHSHydrantRightValve, 168, 423, 224, 470, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 7);
+ setHotspot(kHSCowboyHat, 184, 63, 289, 171, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 448);
+ setHotspot(kHSWalkArea2, 0, 0, 214, 515);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(8)) {
+ if (isFlag(9)) {
+ _hotspots[kHSHydrantTopValve].flags = SF_DISABLED;
+ _hotspots[kHSHydrantRightValve].x1 = 148;
+ _hotspots[kHSHydrantRightValve].y1 = 403;
+ _hotspots[kHSGarbageCan].flags = SF_DISABLED;
+ _hotspotsWalkPos[kHSGarbageCan].x = 3;
+ _hotspotsWalkPos[kHSGarbageCan].y = 7;
+ } else {
+ _hotspots[kHSHydrantTopValve].y1 = 246;
+ }
+ } else if (isFlag(7)) {
+ _hotspots[kHSHydrantRightValve].flags = SF_DISABLED;
+ _hotspots[kHSHydrantTopValve].x1 = 105;
+ _hotspots[kHSHydrantTopValve].x2 = 192;
+ } else if (isFlag(9)) {
+ _hotspots[kHSGarbageCan].x1 = 115;
+ _hotspots[kHSGarbageCan].y1 = 365;
+ _hotspots[kHSGarbageCan].x2 = 168;
+ _hotspots[kHSGarbageCan].y2 = 470;
+ _hotspots[kHSGarbageCan].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR;
+ _hotspotsWalkPos[kHSGarbageCan].x = 3;
+ _hotspotsWalkPos[kHSGarbageCan].y = 7;
+ }
+ if (isFlag(10))
+ _hotspots[kHSGarbageCan].flags = SF_DISABLED;
+ if (isFlag(26)) {
+ _hotspots[kHSDevice].flags = SF_DISABLED;
+ _hotspots[kHSHydrantTopValve].flags = SF_DISABLED;
+ _hotspots[kHSHydrantRightValve].flags = SF_DISABLED;
+ _hotspots[kHSPlatypus].flags = SF_DISABLED;
+ }
+ if (isFlag(14)) {
+ _hotspots[kHSHydrantTopValve].flags = SF_DISABLED;
+ _hotspots[kHSCowboyHat].flags = SF_DISABLED;
+ }
+ _hotspotsCount = 11;
+}
+
+void GnapEngine::scene18_gnapCarryGarbageCanTo(int x, int y, int animationIndex, int argC, int a5) {
+
+ // TODO Cleanup
+
+ static const int kSequenceIds[] = {
+ 0x203, 0x204
+ };
+
+ int gnapSeqId, gnapId, gnapDatNum, gnapGridX;
+ int v13, v12, v5, v10, v11, v15, v16, a2;
+
+ if (x >= 0)
+ v13 = x;
+ else
+ v13 = (_leftClickMouseX - _gridMinX + 37) / 75;
+ if (v13 >= _gnapX)
+ v10 = v13 - 1;
+ else
+ v10 = v13 + 1;
+
+ if (a5 < 0)
+ a5 = 4;
+ v5 = v10;
+ if (v10 <= a5)
+ v5 = a5;
+ v11 = v5;
+ v12 = _gridMaxX - 1;
+ if (_gridMaxX - 1 >= v11)
+ v12 = v11;
+
+ if (v12 == _gnapX) {
+ gnapSeqId = _gnapSequenceId;
+ gnapId = _gnapId;
+ gnapDatNum = _gnapSequenceDatNum;
+ gnapGridX = _gnapX;
+ if (_gnapX <= v13)
+ v15 = 1;
+ else
+ v15 = -1;
+ } else {
+ if (_gnapY == _platY) {
+ if (v12 >= _gnapX) {
+ if (v12 >= _platX && _gnapX <= _platX)
+ beaverMakeRoom();
+ } else if (v12 <= _platX && _gnapX >= _platX) {
+ beaverMakeRoom();
+ }
+ }
+ gnapSeqId = _gnapSequenceId;
+ gnapId = _gnapId;
+ gnapDatNum = _gnapSequenceDatNum;
+ gnapGridX = _gnapX;
+ if (v12 < _gnapX)
+ v15 = -1;
+ else
+ v15 = 1;
+ v16 = v15 == -1;
+ a2 = 20 * _gnapY + 1;
+ do {
+ if (isPointBlocked(gnapGridX + v15, _gnapY))
+ break;
+ a2 += v15;
+ _gameSys->insertSequence(kSequenceIds[v16], a2,
+ gnapSeqId | (gnapDatNum << 16), gnapId,
+ kSeqSyncWait, 0, 75 * gnapGridX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ gnapSeqId = kSequenceIds[v16];
+ gnapId = a2;
+ gnapDatNum = 0;
+ gnapGridX += v15;
+ } while (v12 != gnapGridX);
+ }
+
+ if (argC >= 0) {
+ _gnapSequenceId = ridToEntryIndex(argC);
+ _gnapSequenceDatNum = ridToDatIndex(argC);
+ } else {
+ if (v15 == 1)
+ _gnapSequenceId = 0x20A;
+ else
+ _gnapSequenceId = 0x209;
+ _gnapSequenceDatNum = 0;
+ }
+
+ if (v15 == 1)
+ _gnapIdleFacing = 1;
+ else
+ _gnapIdleFacing = 3;
+
+ _gnapId = 20 * _gnapY + 1;
+
+ if (animationIndex >= 0)
+ _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, animationIndex);
+
+ _gameSys->insertSequence(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ gnapSeqId | (gnapDatNum << 16), gnapId,
+ 9, 0, 75 * gnapGridX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+
+ _gnapX = gnapGridX;
+
+}
+
+void GnapEngine::scene18_putDownGarbageCan(int animationIndex) {
+ if (animationIndex >= 0) {
+ while (_gameSys->getAnimationStatus(animationIndex) != 2)
+ gameUpdateTick();
+ }
+ if (_gnapIdleFacing != 0 && _gnapIdleFacing != 1 && _gnapIdleFacing != 7)
+ _s18_garbageCanPos = _gnapX - 1;
+ else
+ _s18_garbageCanPos = _gnapX + 1;
+ clearFlag(10);
+ scene18_updateHotspots();
+ if (_gnapIdleFacing != 0 && _gnapIdleFacing != 1 && _gnapIdleFacing != 7) {
+ _gameSys->insertSequence(0x107BA, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gnapSequenceId = 0x7BA;
+ } else {
+ _gameSys->insertSequence(0x107B9, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gnapSequenceId = 0x7B9;
+ }
+ _gnapSequenceDatNum = 1;
+ _gameSys->insertSequence(0x1FB, 19, 0, 0, kSeqNone, 0, 15 * (5 * _s18_garbageCanPos - 40), 0);
+ _gameSys->setAnimation(0x1FA, 19, 4);
+ _gameSys->insertSequence(0x1FA, 19, 507, 19, kSeqSyncWait, 0, 15 * (5 * _s18_garbageCanPos - 40), 0);
+ while (_gameSys->getAnimationStatus(4) != 2)
+ gameUpdateTick();
+}
+
+void GnapEngine::scene18_platEndPhoning(int a1) {
+ if (isFlag(26)) {
+ _s18_platPhoneIter = 0;
+ _s18_platPhoneCtr = 0;
+ _beaverActionStatus = -1;
+ if (_s18_currPhoneSequenceId != -1) {
+ _gameSys->setAnimation(0x21E, 254, 3);
+ _gameSys->insertSequence(0x21E, 254, _s18_currPhoneSequenceId, 254, 32, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(3) != 2)
+ gameUpdateTick();
+ }
+ _gameSys->removeSequence(0x21F, 254, 1);
+ _gameSys->setAnimation(0, 0, 3);
+ clearFlag(26);
+ if (a1) {
+ _beaverActionStatus = kASPlatComesHere;
+ _timers[6] = 50;
+ _sceneWaiting = true;
+ }
+ _s18_currPhoneSequenceId = -1;
+ _s18_nextPhoneSequenceId = -1;
+ scene18_updateHotspots();
+ }
+}
+
+void GnapEngine::scene18_closeHydrantValve() {
+ _gnapActionStatus = kASLeaveScene;
+ updateMouseCursor();
+ if (isFlag(8)) {
+ gnapWalkTo(_hotspotsWalkPos[kHSHydrantRightValve].x, _hotspotsWalkPos[kHSHydrantRightValve].y, 0, 0x107BA, 1);
+ if (isFlag(9)) {
+ _gnapActionStatus = kASCloseRightValveWithGarbageCan;
+ scene18_waitForGnapAction();
+ } else {
+ _gnapActionStatus = kASCloseRightValveNoGarbageCan;
+ scene18_waitForGnapAction();
+ }
+ } else if (isFlag(7)) {
+ gnapWalkTo(_hotspotsWalkPos[kHSHydrantTopValve].x, _hotspotsWalkPos[kHSHydrantTopValve].y, 0, 0x107BA, 1);
+ _gnapActionStatus = kASCloseTopValve;
+ scene18_waitForGnapAction();
+ }
+}
+
+void GnapEngine::scene18_waitForGnapAction() {
+ while (_gnapActionStatus >= 0) {
+ scene18_updateAnimations();
+ gameUpdateTick();
+ }
+}
+
+void GnapEngine::scene18_run() {
+
+ _s18_cowboyHatSurface = 0;
+
+ playSound(0x10940, 1);
+ startSoundTimerA(4);
+
+ _timers[5] = getRandom(100) + 100;
+
+ queueInsertDeviceIcon();
+
+ clearFlag(10);
+
+ if (!isFlag(14))
+ _gameSys->insertSequence(0x1F8, 19, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(9)) {
+ if (isFlag(8)) {
+ _gameSys->insertSequence(0x214, 39, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0x20D, 39, 0, 0, kSeqLoop, 0, 0, 0);
+ playSound(0x22B, true);
+ } else {
+ _gameSys->insertSequence(0x1F9, 19, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ } else {
+ _gameSys->insertSequence(0x1FA, 19, 0, 0, kSeqNone, 0, 15 * (5 * _s18_garbageCanPos - 40), 0);
+ if (isFlag(8)) {
+ _gameSys->insertSequence(0x212, 39, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0x20D, 39, 0, 0, kSeqLoop, 0, 0, 0);
+ playSound(0x22B, true);
+ } else if (isFlag(7)) {
+ _gameSys->insertSequence(0x20E, 39, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0x217, 39, 0, 0, kSeqLoop, 0, 0, 0);
+ playSound(0x22B, true);
+ }
+ }
+
+ if (isFlag(26)) {
+ if (_prevSceneNum == 17)
+ initGnapPos(4, 11, 1);
+ else
+ initGnapPos(4, 7, 1);
+ _s18_platPhoneCtr = getRandom(5);
+ if (isFlag(27)) {
+ _gameSys->insertSequence(0x21E, 254, 0, 0, kSeqNone, 0, 0, 0);
+ endSceneInit();
+ _s18_currPhoneSequenceId = -1;
+ scene18_platEndPhoning(1);
+ clearFlag(27);
+ } else {
+ _s18_currPhoneSequenceId = kScene18SequenceIds[_s18_platPhoneCtr];
+ _s18_platPhoneIter = 0;
+ _gameSys->insertSequence(0x21F, 254, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(_s18_currPhoneSequenceId, 254, 0, 0, kSeqNone, 0, 0, 0);
+ endSceneInit();
+ }
+ if (isFlag(27)) {
+ scene18_platEndPhoning(1);
+ clearFlag(27);
+ } else {
+ _gameSys->setAnimation(_s18_currPhoneSequenceId, 254, 3);
+ }
+ gnapWalkTo(4, 8, -1, 0x107B9, 1);
+ } else {
+ if (isFlag(12)) {
+ clearFlag(12);
+ setGrabCursorSprite(kItemCowboyHat);
+ _prevSceneNum = 19;
+ }
+ if (_prevSceneNum == 17) {
+ initGnapPos(4, 11, 1);
+ initBeaverPos(5, 11, 0);
+ endSceneInit();
+ gnapWalkTo(4, 8, -1, 0x107B9, 1);
+ platypusWalkTo(5, 9, -1, 0x107C2, 1);
+ } else if (_prevSceneNum == 19) {
+ initGnapPos(7, 7, 1);
+ initBeaverPos(8, 7, 0);
+ endSceneInit();
+ gnapWalkTo(7, 8, -1, 0x107B9, 1);
+ platypusWalkTo(8, 8, -1, 0x107C2, 1);
+ } else {
+ initGnapPos(-1, 10, 1);
+ initBeaverPos(-1, 10, 0);
+ endSceneInit();
+ gnapWalkTo(3, 7, -1, 0x107B9, 1);
+ platypusWalkTo(3, 8, -1, 0x107C2, 1);
+ }
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 20, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ if (_sceneClickedHotspot >= 0)
+ debug("_sceneClickedHotspot: %d", _sceneClickedHotspot);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene18_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(10)) {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ }
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowItem(_grabCursorSpriteIndex, _platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSCowboyHat:
+ if (_gnapActionStatus == kASStandingOnHydrant) {
+ _gnapActionStatus = kASGrabCowboyHat;
+ _sceneWaiting = 0;
+ } else if (_gnapActionStatus < 0) {
+ if (isFlag(10)) {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ }
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSCowboyHat].x, _hotspotsWalkPos[kHSCowboyHat].y, 3, 2);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(3, 2);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(_hotspotsWalkPos[kHSCowboyHat].x, _hotspotsWalkPos[kHSCowboyHat].y, 0, getGnapSequenceId(gskPullOutDeviceNonWorking, 3, 2) | 0x10000, 1);
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSGarbageCan:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(14)) {
+ if (_grabCursorSpriteIndex >= 0)
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSGarbageCan].x, _hotspotsWalkPos[kHSGarbageCan].y, 1, 5);
+ else
+ playGnapImpossible(0, 0);
+ } else {
+ if (isFlag(26))
+ scene18_platEndPhoning(1);
+ if (_grabCursorSpriteIndex >= 0) {
+ if (!isFlag(9))
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSGarbageCan].x - (_gnapX < _s18_garbageCanPos ? 1 : -1),
+ _hotspotsWalkPos[kHSGarbageCan].y, _hotspotsWalkPos[kHSGarbageCan].x, _hotspotsWalkPos[kHSGarbageCan].y);
+ else
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSGarbageCan].x, _hotspotsWalkPos[kHSGarbageCan].y, 2, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (!isFlag(9))
+ playGnapScratchingHead(_hotspotsWalkPos[kHSGarbageCan].x - (_gnapX < _s18_garbageCanPos ? 1 : -1), _hotspotsWalkPos[kHSGarbageCan].y);
+ else if (!isFlag(8))
+ playGnapScratchingHead(2, 4);
+ break;
+ case GRAB_CURSOR:
+ if (!isFlag(9)) {
+ gnapWalkTo(_hotspotsWalkPos[kHSGarbageCan].x - (_gnapX < _s18_garbageCanPos ? 1 : -1), _hotspotsWalkPos[kHSGarbageCan].y,
+ -1, -1, 1);
+ gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _s18_garbageCanPos, _gnapY) | 0x10000, 1);
+ _gnapActionStatus = kASGrabGarbageCanFromStreet;
+ } else if (!isFlag(8)) {
+ if (gnapWalkTo(_hotspotsWalkPos[kHSGarbageCan].x, _hotspotsWalkPos[kHSGarbageCan].y, 0, -1, 1))
+ _gnapActionStatus = kASGrabGarbageCanFromHydrant;
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case kHSHydrantTopValve:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(10)) {
+ // While carrying garbage can
+ if (_grabCursorSpriteIndex >= 0) {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ playGnapShowItem(_grabCursorSpriteIndex, 0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ playGnapScratchingHead(0, 0);
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(8)) {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, 2);
+ _gnapActionStatus = kASPutGarbageCanOnRunningHydrant;
+ } else if (!isFlag(7)) {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, 2);
+ _gnapActionStatus = kASPutGarbageCanOnHydrant;
+ } else {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ playGnapImpossible(0, 0);
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ } else {
+ if (_grabCursorSpriteIndex == kItemWrench) {
+ gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, 2, 8) | 0x10000, 1);
+ _gnapActionStatus = kASOpenTopValve;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSHydrantTopValve].x, _hotspotsWalkPos[kHSHydrantTopValve].y, 1, 5);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(1, 5);
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(7)) {
+ _hotspots[kHSWalkArea2].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[kHSHydrantTopValve].x, _hotspotsWalkPos[kHSHydrantTopValve].y, 0, 0x107BA, 1);
+ _hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE;
+ _gnapActionStatus = kASCloseTopValve;
+ } else
+ playGnapImpossible(0, 0);
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case kHSHydrantRightValve:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(14)) {
+ if (_grabCursorSpriteIndex == -1) {
+ playGnapImpossible(0, 0);
+ } else {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSHydrantRightValve].x, _hotspotsWalkPos[kHSHydrantRightValve].y, 1, 5);
+ }
+ } else {
+ if (isFlag(10)) {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ }
+ if (_grabCursorSpriteIndex == kItemWrench) {
+ gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, 2, 8) | 0x10000, 1);
+ if (isFlag(9))
+ _gnapActionStatus = kASOpenRightValveWithGarbageCan;
+ else
+ _gnapActionStatus = kASOpenRightValveNoGarbageCan;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSHydrantRightValve].x, _hotspotsWalkPos[kHSHydrantRightValve].y, 1, 5);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(1, 5);
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(8)) {
+ gnapWalkTo(_hotspotsWalkPos[kHSHydrantRightValve].x, _hotspotsWalkPos[kHSHydrantRightValve].y, 0, 0x107BA, 1);
+ if (isFlag(9))
+ _gnapActionStatus = kASCloseRightValveWithGarbageCan;
+ else
+ _gnapActionStatus = kASCloseRightValveNoGarbageCan;
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case kHSExitToyStore:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(10)) {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ }
+ if (isFlag(20)) {
+ playGnapImpossible(0, 0);
+ } else {
+ _isLeavingScene = 1;
+ _newSceneNum = 19;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitToyStore].x, _hotspotsWalkPos[kHSExitToyStore].y, 0, 0x107C0, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (!isFlag(26))
+ platypusWalkTo(_hotspotsWalkPos[kHSExitToyStore].x + 1, _hotspotsWalkPos[kHSExitToyStore].y, -1, 0x107C2, 1);
+ }
+ }
+ break;
+
+ case kHSExitPhoneBooth:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(10)) {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ }
+ scene18_closeHydrantValve();
+ _isLeavingScene = 1;
+ _newSceneNum = 17;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitPhoneBooth].x, _hotspotsWalkPos[kHSExitPhoneBooth].y, 0, 0x107AE, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(26))
+ setFlag(27);
+ else
+ platypusWalkTo(_hotspotsWalkPos[kHSExitPhoneBooth].x + 1, _hotspotsWalkPos[kHSExitPhoneBooth].y, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSExitGrubCity:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(10)) {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ }
+ scene18_closeHydrantValve();
+ _isLeavingScene = 1;
+ _newSceneNum = 20;
+ _hotspots[kHSWalkArea2].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitGrubCity].x, _hotspotsWalkPos[kHSExitGrubCity].y, 0, 0x107B2, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(26))
+ scene18_platEndPhoning(0);
+ else
+ platypusWalkTo(_hotspotsWalkPos[kHSExitGrubCity].x, _hotspotsWalkPos[kHSExitGrubCity].y - 1, -1, 0x107CF, 1);
+ _hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE;
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(10)) {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ } else {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ }
+ _mouseClickState.left = false;
+ }
+ break;
+
+ default:
+ if (_gnapActionStatus != kASStandingOnHydrant && _mouseClickState.left) {
+ if (isFlag(10)) {
+ scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1);
+ scene18_putDownGarbageCan(0);
+ } else {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ }
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene18_updateAnimations();
+
+ if (!isSoundPlaying(0x10940))
+ playSound(0x10940, true);
+
+ if ((isFlag(8) || isFlag(7)) && !isSoundPlaying(0x22B) &&
+ _gnapActionStatus != kASOpenRightValveNoGarbageCanDone && _gnapActionStatus != kASOpenRightValveNoGarbageCan &&
+ _gnapActionStatus != kASOpenTopValve && _gnapActionStatus != kASOpenTopValveDone &&
+ _gnapActionStatus != kASOpenRightValveWithGarbageCan && _gnapActionStatus != kASOpenRightValveWithGarbageCanDone)
+ playSound(0x22B, true);
+
+ if (!_isLeavingScene) {
+ if (!isFlag(26)) {
+ if (_beaverActionStatus == kASPlatComesHere) {
+ if (!_timers[6]) {
+ _beaverActionStatus = -1;
+ _sceneWaiting = false;
+ initBeaverPos(-1, 10, 0);
+ platypusWalkTo(3, 9, -1, 0x107C2, 1);
+ clearFlag(26);
+ }
+ } else {
+ _hotspots[kHSWalkArea1].y2 += 48;
+ _hotspots[kHSWalkArea2].x1 += 75;
+ updateBeaverIdleSequence();
+ _hotspots[kHSWalkArea2].x1 -= 75;
+ _hotspots[kHSWalkArea1].y2 -= 48;
+ }
+ if (!_timers[5]) {
+ _timers[5] = getRandom(100) + 100;
+ if (_gnapActionStatus < 0) {
+ if (getRandom(2) == 1)
+ _gameSys->insertSequence(0x220, 255, 0, 0, kSeqNone, 0, 0, 0);
+ else
+ _gameSys->insertSequence(0x221, 255, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ }
+ playSoundA();
+ }
+ if (!isFlag(10))
+ updateGnapIdleSequence();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene18_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+ if (isFlag(12))
+ deleteSurface(&_s18_cowboyHatSurface);
+
+}
+
+void GnapEngine::scene18_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASGrabGarbageCanFromStreet:
+ if (_gnapIdleFacing != 7 && _gnapIdleFacing != 1) {
+ _gameSys->insertSequence(0x1FC, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ kSeqSyncWait, 0, 75 * _gnapX - 675, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x1FC;
+ } else {
+ _gameSys->insertSequence(0x1FD, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ kSeqSyncWait, 0, 75 * _gnapX - 525, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x1FD;
+ }
+ _gameSys->removeSequence(0x1FA, 19, 1);
+ setFlag(10);
+ scene18_updateHotspots();
+ _gnapActionStatus = -1;
+ break;
+ case kASGrabGarbageCanFromHydrant:
+ _gameSys->insertSequence(0x1FE, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->removeSequence(0x1F9, 19, 1);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x1FE;
+ clearFlag(9);
+ setFlag(10);
+ scene18_updateHotspots();
+ _gnapActionStatus = -1;
+ break;
+ case kASCloseRightValveNoGarbageCan:
+ _gameSys->insertSequence(0x205, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->removeSequence(0x20D, 39, 1);
+ _gameSys->removeSequence(0x212, 39, 1);
+ _gameSys->removeSequence(0x211, 39, 1);
+ stopSound(0x22B);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x205;
+ clearFlag(8);
+ invAdd(kItemWrench);
+ setGrabCursorSprite(kItemWrench);
+ scene18_updateHotspots();
+ _gnapActionStatus = -1;
+ break;
+ case kASOpenTopValve:
+ setFlag(7);
+ scene18_updateHotspots();
+ playGnapPullOutDevice(2, 7);
+ playGnapUseDevice(0, 0);
+ _gameSys->insertSequence(0x20C, 19, 0, 0, kSeqNone, 0, 0, 0);
+ _hotspots[kHSWalkArea2].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[kHSHydrantTopValve].x, _hotspotsWalkPos[kHSHydrantTopValve].y, 0, 0x107BB, 1);
+ _hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE;
+ _gnapActionStatus = kASOpenTopValveDone;
+ break;
+ case kASOpenTopValveDone:
+ setGrabCursorSprite(-1);
+ _gameSys->insertSequence(0x208, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x216, 39, 0, 0, kSeqNone, 21, 0, 0);
+ _gameSys->removeSequence(0x20C, 19, 1);
+ _gameSys->setAnimation(0x217, 39, 5);
+ _gameSys->insertSequence(0x217, 39, 0x216, 39, 10, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(5) != 2)
+ gameUpdateTick();
+ playSound(0x22B, true);
+ _gameSys->insertSequence(0x20E, 39, 0, 0, kSeqNone, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x208;
+ invRemove(kItemWrench);
+ setGrabCursorSprite(-1);
+ _gnapActionStatus = -1;
+ break;
+ case kASCloseTopValve:
+ _gameSys->insertSequence(0x206, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->removeSequence(0x20E, 39, 1);
+ _gameSys->removeSequence(0x216, 39, 1);
+ _gameSys->removeSequence(0x217, 39, 1);
+ stopSound(0x22B);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x206;
+ clearFlag(7);
+ invAdd(kItemWrench);
+ setGrabCursorSprite(kItemWrench);
+ scene18_updateHotspots();
+ _gnapActionStatus = -1;
+ break;
+ case kASGrabCowboyHat:
+ _gameSys->setAnimation(0x200, _gnapId, 0);
+ _gameSys->insertSequence(0x200, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x200;
+ _gnapActionStatus = kASGrabCowboyHatDone;
+ break;
+ case kASGrabCowboyHatDone:
+ hideCursor();
+ setGrabCursorSprite(-1);
+ _s18_cowboyHatSurface = addFullScreenSprite(0x1D2, 255);
+ _gameSys->setAnimation(0x218, 256, 0);
+ _gameSys->insertSequence(0x218, 256, 0, 0, kSeqNone, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(0) != 2)
+ gameUpdateTick();
+ _newSceneNum = 18;
+ invAdd(kItemCowboyHat);
+ invAdd(kItemWrench);
+ setFlag(12);
+ setFlag(14);
+ clearFlag(8);
+ setFlag(9);
+ setFlag(14);
+ scene18_updateHotspots();
+ _gnapActionStatus = kASLeaveScene;
+ break;
+ case kASLeaveScene:
+ _sceneDone = true;
+ _gnapActionStatus = -1;
+ break;
+ case kASPutGarbageCanOnRunningHydrant:
+ setFlag(9);
+ clearFlag(10);
+ _gameSys->requestRemoveSequence(0x211, 39);
+ _gameSys->requestRemoveSequence(0x212, 39);
+ _gameSys->insertSequence(0x210, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ stopSound(0x22B);
+ _gameSys->setAnimation(0x210, _gnapId, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x210;
+ _gnapActionStatus = kASPutGarbageCanOnRunningHydrant2;
+ break;
+ case kASPutGarbageCanOnRunningHydrant2:
+ playSound(0x22B, true);
+ _gameSys->setAnimation(0x1FF, _gnapId, 0);
+ _gameSys->insertSequence(0x1FF, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x1FF;
+ _sceneWaiting = true;
+ _gnapActionStatus = kASStandingOnHydrant;
+ break;
+ case kASStandingOnHydrant:
+ _gameSys->setAnimation(0x1FF, _gnapId, 0);
+ _gameSys->insertSequence(0x1FF, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ break;
+ case kASOpenRightValveNoGarbageCan:
+ case kASOpenRightValveWithGarbageCan:
+ setFlag(8);
+ scene18_updateHotspots();
+ playGnapPullOutDevice(2, 7);
+ playGnapUseDevice(0, 0);
+ _gameSys->insertSequence(0x20B, 19, 0, 0, kSeqNone, 0, 0, 0);
+ _hotspots[kHSWalkArea2].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[kHSHydrantRightValve].x, _hotspotsWalkPos[kHSHydrantRightValve].y, 0, 0x107BA, 1);
+ _hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE;
+ if (_gnapActionStatus == kASOpenRightValveNoGarbageCan)
+ _gnapActionStatus = kASOpenRightValveNoGarbageCanDone;
+ else
+ _gnapActionStatus = kASOpenRightValveWithGarbageCanDone;
+ break;
+ case kASOpenRightValveWithGarbageCanDone:
+ setGrabCursorSprite(-1);
+ _gameSys->insertSequence(0x207, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x213, 39, 0, 0, kSeqNone, 21, 0, 0);
+ _gameSys->requestRemoveSequence(0x1F9, 19);
+ _gameSys->removeSequence(0x20B, 19, 1);
+ _gameSys->setAnimation(0x213, 39, 5);
+ _gameSys->insertSequence(0x214, 39, 0x213, 39, 10, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(5) != 2)
+ gameUpdateTick();
+ playSound(555, true);
+ _gameSys->insertSequence(0x20D, 39, 0, 0, kSeqNone, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x207;
+ invRemove(kItemWrench);
+ _gnapActionStatus = -1;
+ break;
+ case kASOpenRightValveNoGarbageCanDone:
+ setGrabCursorSprite(-1);
+ _gameSys->insertSequence(0x207, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x211, 39, 0, 0, kSeqNone, 21, 0, 0);
+ _gameSys->removeSequence(0x20B, 19, 1);
+ _gameSys->setAnimation(0x211, 39, 5);
+ _gameSys->insertSequence(0x212, 39, 0x211, 39, 10, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(5) != 2)
+ gameUpdateTick();
+ playSound(0x22B, true);
+ _gameSys->insertSequence(0x20D, 39, 0, 0, kSeqNone, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x207;
+ invRemove(kItemWrench);
+ _gnapActionStatus = -1;
+ break;
+ case kASCloseRightValveWithGarbageCan:
+ _gameSys->insertSequence(0x205, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->removeSequence(0x20D, 39, 1);
+ _gameSys->insertSequence(0x215, 39, 0x214, 39, kSeqSyncWait, 0, 0, 0);
+ stopSound(0x22B);
+ _gameSys->setAnimation(0x1F9, 19, 0);
+ _gameSys->insertSequence(0x1F9, 19, 0x215, 39, kSeqSyncWait, 0, 0, 0);
+ clearFlag(8);
+ invAdd(kItemWrench);
+ setGrabCursorSprite(kItemWrench);
+ _gameSys->insertSequence(0x107B5, _gnapId, 517, _gnapId, kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ scene18_updateHotspots();
+ _gnapSequenceDatNum = 1;
+ _gnapSequenceId = 0x7B5;
+ _gnapActionStatus = kASCloseRightValveWithGarbageCanDone;
+ break;
+ case kASCloseRightValveWithGarbageCanDone:
+ _gnapActionStatus = -1;
+ break;
+ case kASPutGarbageCanOnHydrant:
+ setFlag(9);
+ clearFlag(10);
+ _gameSys->insertSequence(0x20F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x20F, _gnapId, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x20F;
+ _gnapActionStatus = kASPutGarbageCanOnHydrantDone;
+ break;
+ case kASPutGarbageCanOnHydrantDone:
+ _gameSys->insertSequence(0x1F9, 19, 0x20F, _gnapId, kSeqNone, 0, 0, 0);
+ scene18_updateHotspots();
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ _gameSys->setAnimation(0, 0, 3);
+ ++_s18_platPhoneIter;
+ if (_s18_platPhoneIter <= 4) {
+ ++_s18_platPhoneCtr;
+ _s18_nextPhoneSequenceId = kScene18SequenceIds[_s18_platPhoneCtr % 5];
+ _gameSys->setAnimation(_s18_nextPhoneSequenceId, 254, 3);
+ _gameSys->insertSequence(_s18_nextPhoneSequenceId, 254, _s18_currPhoneSequenceId, 254, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x21F, 254, 0x21F, 254, kSeqSyncWait, 0, 0, 0);
+ _s18_currPhoneSequenceId = _s18_nextPhoneSequenceId;
+ } else {
+ scene18_platEndPhoning(1);
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene19.cpp b/engines/gnap/scenes/scene19.cpp
new file mode 100644
index 0000000000..ebfdd728a1
--- /dev/null
+++ b/engines/gnap/scenes/scene19.cpp
@@ -0,0 +1,470 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+static const int kS19ShopAssistantSequenceIds[] = {
+ 0x6F, 0x70, 0x71, 0x72, 0x73
+};
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitOutsideToyStore = 1,
+ kHSDevice = 2,
+ kHSPicture = 3,
+ kHSShopAssistant = 4,
+ kHSToy1 = 5,
+ kHSToy2 = 6,
+ kHSToy3 = 7,
+ kHSPhone = 8,
+ kHSToy4 = 9,
+ kHSToy5 = 10,
+ kHSToy6 = 11,
+ kHSToy7 = 12,
+ kHSWalkArea1 = 13,
+ kHSWalkArea2 = 14,
+ kHSWalkArea3 = 15
+};
+
+enum {
+ kASUsePhone = 0,
+ kASGrabToy = 1,
+ kASGrabPicture = 2,
+ kASGrabPictureDone = 3,
+ kASTalkShopAssistant = 4,
+ kASLeaveScene = 5
+};
+
+int GnapEngine::scene19_init() {
+ playSound(0x79, 0);
+ return isFlag(26) ? 0x77 : 0x76;
+}
+
+void GnapEngine::scene19_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitOutsideToyStore, 36, 154, 142, 338, SF_EXIT_NW_CURSOR, 4, 6);
+ setHotspot(kHSPicture, 471, 237, 525, 283, SF_DISABLED, 7, 2);
+ setHotspot(kHSShopAssistant, 411, 151, 575, 279, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 7);
+ setHotspot(kHSPhone, 647, 166, 693, 234, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 0);
+ setHotspot(kHSToy1, 181, 11, 319, 149, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 0);
+ setHotspot(kHSToy2, 284, 85, 611, 216, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 0);
+ setHotspot(kHSToy3, 666, 38, 755, 154, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 0);
+ setHotspot(kHSToy4, 154, 206, 285, 327, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 3);
+ setHotspot(kHSToy5, 494, 301, 570, 448, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 5);
+ setHotspot(kHSToy6, 0, 320, 188, 600, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 6);
+ setHotspot(kHSToy7, 597, 434, 800, 600, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 8);
+ setHotspot(kHSWalkArea1, 0, 0, 170, 600);
+ setHotspot(kHSWalkArea2, 622, 0, 800, 600);
+ setHotspot(kHSWalkArea3, 0, 0, 800, 437);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(26)) {
+ _hotspots[kHSToy1].flags = SF_DISABLED;
+ _hotspots[kHSToy2].flags = SF_DISABLED;
+ _hotspots[kHSToy3].flags = SF_DISABLED;
+ _hotspots[kHSToy4].flags = SF_DISABLED;
+ _hotspots[kHSToy5].flags = SF_DISABLED;
+ _hotspots[kHSToy6].flags = SF_DISABLED;
+ _hotspots[kHSToy7].flags = SF_DISABLED;
+ _hotspots[kHSShopAssistant].flags = SF_DISABLED;
+ _hotspots[kHSPhone].flags = SF_DISABLED;
+ _hotspots[kHSPlatypus].flags = SF_DISABLED;
+ _hotspots[kHSPicture].flags = SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR;
+ }
+ _hotspotsCount = 16;
+}
+
+void GnapEngine::scene19_run() {
+
+ queueInsertDeviceIcon();
+
+ _s19_toyGrabCtr = 0;
+ _s19_pictureSurface = 0;
+
+ _gameSys->insertSequence(0x74, 254, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x75, 254, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (!isFlag(20))
+ _gameSys->insertSequence(0x69, 19, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(26)) {
+ initGnapPos(3, 6, 1);
+ _s19_currShopAssistantSequenceId = kS19ShopAssistantSequenceIds[getRandom(5)];
+ _s19_nextShopAssistantSequenceId = _s19_currShopAssistantSequenceId;
+ _gameSys->setAnimation(_s19_currShopAssistantSequenceId, 20, 4);
+ _gameSys->insertSequence(0x6E, 254, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(_s19_currShopAssistantSequenceId, 20, 0, 0, kSeqNone, 0, 0, 0);
+ _s19_shopAssistantCtr = 0;
+ endSceneInit();
+ gnapWalkTo(4, 9, -1, 0x107B9, 1);
+ scene19_updateHotspots();
+ } else {
+ _s19_currShopAssistantSequenceId = 0x6D;
+ _s19_nextShopAssistantSequenceId = -1;
+ _gameSys->setAnimation(0x6D, 20, 4);
+ _gameSys->insertSequence(_s19_currShopAssistantSequenceId, 20, 0, 0, kSeqNone, 0, 0, 0);
+ _timers[6] = getRandom(40) + 50;
+ initGnapPos(3, 6, 1);
+ initBeaverPos(4, 6, 0);
+ endSceneInit();
+ gnapWalkTo(4, 9, -1, 0x107B9, 1);
+ platypusWalkTo(5, 9, -1, 0x107C2, 1);
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 5, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene19_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitOutsideToyStore:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 18;
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 0, 0x107B2, 1);
+ _gnapActionStatus = kASLeaveScene;
+ if (isFlag(26))
+ setFlag(27);
+ else
+ platypusWalkTo(_hotspotsWalkPos[1].x + 1, _hotspotsWalkPos[1].y, -1, 0x107C5, 1);
+ _hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE;
+ }
+ break;
+
+ case kHSPicture:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 6, 2);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(6, 2);
+ break;
+ case GRAB_CURSOR:
+ if (!isFlag(20)) {
+ gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y) | 0x10000, 1);
+ _gnapActionStatus = kASGrabPicture;
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSShopAssistant:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 6, 2);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(6, 2);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkShopAssistant;
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSToy1:
+ case kHSToy2:
+ case kHSToy3:
+ case kHSToy4:
+ case kHSToy5:
+ case kHSToy6:
+ case kHSToy7:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan2(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 0, -1, 1);
+ playGnapIdle(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y);
+ _gnapActionStatus = kASGrabToy;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSPhone:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 9, 1);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(9, 1);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 0, -1, 1);
+ playGnapIdle(8, 2);
+ _gnapActionStatus = kASUsePhone;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = 0;
+ }
+ }
+
+ scene19_updateAnimations();
+
+ if (!_isLeavingScene) {
+ updateGnapIdleSequence();
+ if (!isFlag(26)) {
+ updateBeaverIdleSequence();
+ if (!_timers[6] && _s19_nextShopAssistantSequenceId == -1) {
+ _timers[6] = getRandom(40) + 50;
+ if (getRandom(4) != 0) {
+ _s19_nextShopAssistantSequenceId = 0x64;
+ } else if (isFlag(20)) {
+ _s19_nextShopAssistantSequenceId = 0x64;
+ } else {
+ _s19_nextShopAssistantSequenceId = 0x6C;
+ }
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene19_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+ if (_s19_pictureSurface)
+ deleteSurface(&_s19_pictureSurface);
+
+}
+
+void GnapEngine::scene19_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASUsePhone:
+ _s19_nextShopAssistantSequenceId = 0x67;
+ break;
+ case kASGrabToy:
+ ++_s19_toyGrabCtr;
+ switch (_s19_toyGrabCtr) {
+ case 1:
+ _s19_nextShopAssistantSequenceId = 0x62;
+ break;
+ case 2:
+ _s19_nextShopAssistantSequenceId = 0x6B;
+ break;
+ case 3:
+ _s19_nextShopAssistantSequenceId = 0x66;
+ break;
+ default:
+ _s19_nextShopAssistantSequenceId = 0x65;
+ break;
+ }
+ break;
+ case kASGrabPicture:
+ playGnapPullOutDevice(6, 2);
+ playGnapUseDevice(0, 0);
+ _gameSys->setAnimation(0x68, 19, 0);
+ _gameSys->insertSequence(0x68, 19, 105, 19, kSeqSyncWait, 0, 0, 0);
+ invAdd(kItemPicture);
+ setFlag(20);
+ scene19_updateHotspots();
+ _gnapActionStatus = kASGrabPictureDone;
+ break;
+ case kASGrabPictureDone:
+ setGrabCursorSprite(-1);
+ hideCursor();
+ _s19_pictureSurface = addFullScreenSprite(0xF, 255);
+ _gameSys->setAnimation(0x61, 256, 0);
+ _gameSys->insertSequence(0x61, 256, 0, 0, kSeqNone, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(0) != 2) {
+ // checkGameAppStatus();
+ gameUpdateTick();
+ }
+ setFlag(27);
+ showCursor();
+ _newSceneNum = 17;
+ _isLeavingScene = true;
+ _sceneDone = true;
+ _s19_nextShopAssistantSequenceId = -1;
+ break;
+ case kASTalkShopAssistant:
+ _s19_nextShopAssistantSequenceId = 0x6D;
+ _gnapActionStatus = -1;
+ break;
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(4) == 2) {
+ switch (_s19_nextShopAssistantSequenceId) {
+ case 0x6F:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ _s19_shopAssistantCtr = (_s19_shopAssistantCtr + 1) % 5;
+ _s19_nextShopAssistantSequenceId = kS19ShopAssistantSequenceIds[_s19_shopAssistantCtr];
+ _gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 4);
+ _gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x6E, 254, 0x6E, 254, kSeqSyncWait, 0, 0, 0);
+ _s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId;
+ break;
+ case 0x62:
+ case 0x66:
+ case 0x6B:
+ _gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 4);
+ _gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId;
+ _s19_nextShopAssistantSequenceId = -1;
+ _timers[5] = 10;
+ while (_timers[5]) {
+ gameUpdateTick();
+ }
+ playGnapIdle(6, 2);
+ _gnapActionStatus = -1;
+ break;
+ case 0x67:
+ _gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 4);
+ _gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId;
+ _s19_nextShopAssistantSequenceId = -1;
+ _gnapActionStatus = -1;
+ break;
+ case 0x65:
+ playGnapIdle(6, 2);
+ _gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 0);
+ _gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId;
+ _s19_nextShopAssistantSequenceId = -1;
+ _newSceneNum = 18;
+ _gnapActionStatus = kASLeaveScene;
+ break;
+ case 0x6D:
+ _gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 4);
+ _gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x69, 19, 0x69, 19, kSeqSyncWait, getSequenceTotalDuration(_s19_nextShopAssistantSequenceId), 0, 0);
+ _s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId;
+ _s19_nextShopAssistantSequenceId = -1;
+ break;
+ case 0x64:
+ case 0x6C:
+ _gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 4);
+ _gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId;
+ _s19_nextShopAssistantSequenceId = -1;
+ break;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene20.cpp b/engines/gnap/scenes/scene20.cpp
new file mode 100644
index 0000000000..136f234bce
--- /dev/null
+++ b/engines/gnap/scenes/scene20.cpp
@@ -0,0 +1,736 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSGroceryStoreHat = 1,
+ kHSExitParkingLot = 2,
+ kHSStonerGuy = 3,
+ kHSGroceryStoreGuy = 4,
+ kHSDevice = 5,
+ kHSExitInsideGrubCity = 6,
+ kHSExitOutsideCircusWorld = 7,
+ kHSExitOutsideToyStore = 8,
+ kHSExitPhone = 9,
+ kHSWalkArea1 = 10,
+ kHSWalkArea2 = 11
+};
+
+enum {
+ kASLeaveScene = 0,
+ kASTalkStonerGuyNoJoint = 2,
+ kASTalkStonerGuyHasJoint = 3,
+ kASGrabJoint = 4,
+ kASActionDone = 5,
+ kASTalkGroceryStoreGuy = 6,
+ kASGrabGroceryStoreGuy = 9,
+ kASGrabGroceryStoreHat = 10,
+ kASSwitchGroceryStoreHat = 11,
+ kASSwitchGroceryStoreHatDone = 12,
+ kASGrabJointDone = 13
+};
+
+int GnapEngine::scene20_init() {
+ return 0x186;
+}
+
+void GnapEngine::scene20_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSGroceryStoreHat, 114, 441, 174, 486, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 0, 7);
+ setHotspot(kHSExitParkingLot, 0, 300, 15, 600, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 7);
+ setHotspot(kHSStonerGuy, 276, 290, 386, 450, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 8);
+ setHotspot(kHSGroceryStoreGuy, 123, 282, 258, 462, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 7);
+ setHotspot(kHSExitInsideGrubCity, 519, 250, 581, 413, SF_EXIT_L_CURSOR, 8, 7);
+ setHotspot(kHSExitOutsideCircusWorld, 660, 222, 798, 442, SF_EXIT_NE_CURSOR, 9, 6);
+ setHotspot(kHSExitOutsideToyStore, 785, 350, 800, 600, SF_EXIT_R_CURSOR, 11, 8);
+ setHotspot(kHSExitPhone, 250, 585, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 10);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 468);
+ setHotspot(kHSWalkArea2, 605, 0, 800, 600);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 12;
+}
+
+void GnapEngine::scene20_updateAnimationsCb() {
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ switch (_s20_nextStonerGuySequenceId) {
+ case 0x16B:
+ if (!_timers[4]) {
+ _s20_stonerGuyShowingJoint = false;
+ _gameSys->insertSequence(0x16B, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0);
+ _s20_currStonerGuySequenceId = 0x16B;
+ _s20_nextStonerGuySequenceId = -1;
+ }
+ break;
+ case 0x16A:
+ // Grab joint
+ playGnapPullOutDevice(4, 4);
+ playGnapUseDevice(0, 0);
+ _gameSys->setAnimation(0x16A, 21, 0);
+ _gameSys->insertSequence(0x16A, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0);
+ _s20_currStonerGuySequenceId = 0x16A;
+ _s20_nextStonerGuySequenceId = -1;
+ invAdd(kItemJoint);
+ setFlag(17);
+ _s20_stonerGuyShowingJoint = false;
+ _gnapActionStatus = kASGrabJointDone;
+ break;
+ case 0x16E:
+ _gameSys->setAnimation(0x16E, 21, 2);
+ _gameSys->insertSequence(0x16E, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0);
+ _s20_currStonerGuySequenceId = 0x16E;
+ _s20_nextStonerGuySequenceId = -1;
+ _s20_nextGroceryStoreGuySequenceId = 0x175;
+ break;
+ case 0x16D:
+ _gameSys->setAnimation(_s20_nextStonerGuySequenceId, 21, 2);
+ _gameSys->setAnimation(_s20_nextStonerGuySequenceId, 21, 0);
+ _gameSys->insertSequence(_s20_nextStonerGuySequenceId, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0);
+ _s20_currStonerGuySequenceId = _s20_nextStonerGuySequenceId;
+ _s20_nextStonerGuySequenceId = -1;
+ _gnapActionStatus = kASActionDone;
+ break;
+ case 0x16F:
+ _gameSys->setAnimation(_s20_nextStonerGuySequenceId, 21, 2);
+ _gameSys->setAnimation(0x17A, 20, 3);
+ _gameSys->insertSequence(_s20_nextStonerGuySequenceId, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x17A, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _s20_currGroceryStoreGuySequenceId = 0x17A;
+ _s20_nextGroceryStoreGuySequenceId = -1;
+ _s20_currStonerGuySequenceId = _s20_nextStonerGuySequenceId;
+ _s20_nextStonerGuySequenceId = -1;
+ break;
+ case 0x171:
+ _s20_stonerGuyCtr = (_s20_stonerGuyCtr + 1) % 3;
+ switch (_s20_stonerGuyCtr) {
+ case 1:
+ _s20_nextStonerGuySequenceId = 0x171;
+ break;
+ case 2:
+ _s20_nextStonerGuySequenceId = 0x172;
+ break;
+ case 3:
+ _s20_nextStonerGuySequenceId = 0x173;
+ break;
+ default:
+ _s20_nextStonerGuySequenceId = 0x171;
+ break;
+ }
+ _gameSys->insertSequence(_s20_nextStonerGuySequenceId, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x17C, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x17C, 20, 3);
+ _gameSys->setAnimation(_s20_nextStonerGuySequenceId, 21, 2);
+ _s20_currGroceryStoreGuySequenceId = 0x17C;
+ _s20_nextGroceryStoreGuySequenceId = -1;
+ _s20_currStonerGuySequenceId = _s20_nextStonerGuySequenceId;
+ _s20_nextStonerGuySequenceId = -1;
+ break;
+ default:
+ _s20_nextStonerGuySequenceId = 0x16C;
+ _gameSys->setAnimation(0x16C, 21, 2);
+ _gameSys->insertSequence(_s20_nextStonerGuySequenceId, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0);
+ _s20_currStonerGuySequenceId = _s20_nextStonerGuySequenceId;
+ _s20_nextStonerGuySequenceId = -1;
+ break;
+ }
+ }
+
+}
+
+void GnapEngine::scene20_stopSounds() {
+ stopSound(0x18E);
+ stopSound(0x18F);
+ stopSound(0x190);
+ stopSound(0x191);
+ stopSound(0x194);
+ stopSound(0x195);
+ stopSound(0x192);
+ stopSound(0x193);
+ stopSound(0x196);
+ stopSound(0x197);
+ stopSound(0x198);
+ stopSound(0x199);
+ stopSound(0x19A);
+}
+
+void GnapEngine::scene20_run() {
+
+ playSound(0x10940, 1);
+
+ startSoundTimerA(8);
+
+ _s20_stonerGuyShowingJoint = false;
+ _timers[7] = getRandom(100) + 100;
+
+ _s20_stonerGuyCtr = (_s20_stonerGuyCtr + 1) % 3;
+ switch (_s20_stonerGuyCtr) {
+ case 1:
+ _s20_currStonerGuySequenceId = 0x171;
+ break;
+ case 2:
+ _s20_currStonerGuySequenceId = 0x172;
+ break;
+ case 3:
+ _s20_currStonerGuySequenceId = 0x173;
+ break;
+ }
+
+ _s20_nextStonerGuySequenceId = -1;
+ _gameSys->setAnimation(_s20_currStonerGuySequenceId, 21, 2);
+ _gameSys->insertSequence(_s20_currStonerGuySequenceId, 21, 0, 0, kSeqNone, 0, 0, 0);
+
+ _timers[6] = getRandom(20) + 30;
+
+ _s20_currGroceryStoreGuySequenceId = 0x17C;
+ _s20_nextGroceryStoreGuySequenceId = -1;
+ _gameSys->setAnimation(0x17C, 20, 3);
+ _gameSys->insertSequence(0x17C, 20, 0, 0, kSeqNone, 0, 0, 0);
+
+ _timers[5] = getRandom(50) + 130;
+ if (isFlag(19))
+ _gameSys->insertSequence(0x17F, 20, 0, 0, kSeqNone, 0, 0, 0);
+ else
+ _gameSys->insertSequence(0x174, 20, 0, 0, kSeqNone, 0, 0, 0);
+
+ queueInsertDeviceIcon();
+
+ if (isFlag(11)) {
+ clearFlag(11);
+ endSceneInit();
+ _gameSys->setAnimation(0x182, 140, 0);
+ _gameSys->insertSequence(0x182, 140, 0, 0, kSeqNone, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(0) != 2) {
+ // checkGameAppStatus();
+ gameUpdateTick();
+ }
+ initGnapPos(11, 8, 3);
+ initBeaverPos(11, 9, 4);
+ gnapWalkTo(5, 8, -1, 0x107BA, 1);
+ platypusWalkTo(6, 9, -1, 0x107C2, 1);
+ } else {
+ switch (_prevSceneNum) {
+ case 17:
+ initGnapPos(5, 11, 1);
+ initBeaverPos(6, 11, 0);
+ endSceneInit();
+ gnapWalkTo(5, 8, -1, 0x107B9, 1);
+ platypusWalkTo(6, 9, -1, 0x107C2, 1);
+ break;
+ case 18:
+ initGnapPos(11, 8, 3);
+ initBeaverPos(11, 9, 4);
+ endSceneInit();
+ gnapWalkTo(5, 8, -1, 0x107BA, 1);
+ platypusWalkTo(6, 9, -1, 0x107C2, 1);
+ break;
+ case 21:
+ initGnapPos(-1, 8, 3);
+ initBeaverPos(-1, 9, 4);
+ endSceneInit();
+ gnapWalkTo(3, 8, -1, 0x107B9, 1);
+ platypusWalkTo(3, 9, -1, 0x107C2, 1);
+ break;
+ case 22:
+ initGnapPos(7, 6, 1);
+ initBeaverPos(8, 6, 0);
+ endSceneInit();
+ gnapWalkTo(8, 8, -1, 0x107B9, 1);
+ platypusWalkTo(9, 9, -1, 0x107C2, 1);
+ break;
+ default:
+ initGnapPos(8, 6, 3);
+ initBeaverPos(9, 6, 4);
+ endSceneInit();
+ _hotspots[kHSWalkArea2].flags |= SF_WALKABLE;
+ gnapWalkTo(8, 8, -1, 0x107BA, 1);
+ platypusWalkTo(9, 9, -1, 0x107C2, 1);
+ _hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE;
+ break;
+ }
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+ testWalk(0, 1, 7, 9, 8, 9);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene20_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(20);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitParkingLot:
+ if (_gnapActionStatus < 0) {
+ if (_s20_stonerGuyShowingJoint)
+ _timers[4] = 0;
+ _isLeavingScene = 1;
+ _newSceneNum = 21;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitParkingLot].x, _hotspotsWalkPos[kHSExitParkingLot].y, 0, 0x107AF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitParkingLot].x, _hotspotsWalkPos[kHSExitParkingLot].y + 1, -1, 0x107CF, 1);
+ _beaverFacing = 4;
+ }
+ break;
+
+ case kHSExitPhone:
+ if (_gnapActionStatus < 0) {
+ if (_s20_stonerGuyShowingJoint)
+ _timers[4] = 0;
+ _isLeavingScene = 1;
+ _newSceneNum = 17;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitPhone].x, _hotspotsWalkPos[kHSExitPhone].y, 0, 0x107AE, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitPhone].x + 1, _hotspotsWalkPos[kHSExitPhone].y, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSExitOutsideToyStore:
+ if (_gnapActionStatus < 0) {
+ if (_s20_stonerGuyShowingJoint)
+ _timers[4] = 0;
+ _isLeavingScene = 1;
+ _newSceneNum = 18;
+ _hotspots[kHSWalkArea2].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideToyStore].x, _hotspotsWalkPos[kHSExitOutsideToyStore].y, 0, 0x107AB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideToyStore].x, _hotspotsWalkPos[kHSExitOutsideToyStore].y + 1, -1, 0x107CD, 1);
+ _hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE;
+ }
+ break;
+
+ case kHSExitInsideGrubCity:
+ if (_gnapActionStatus < 0) {
+ if (_s20_stonerGuyShowingJoint)
+ _timers[4] = 0;
+ _isLeavingScene = 1;
+ _newSceneNum = 22;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitInsideGrubCity].x, _hotspotsWalkPos[kHSExitInsideGrubCity].y - 1, 0, 0x107BB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitInsideGrubCity].x + 1, _hotspotsWalkPos[kHSExitInsideGrubCity].y, -1, 0x107C2, 1);
+ _beaverFacing = 4;
+ }
+ break;
+
+ case kHSExitOutsideCircusWorld:
+ if (_gnapActionStatus < 0) {
+ if (_s20_stonerGuyShowingJoint)
+ _timers[4] = 0;
+ _isLeavingScene = 1;
+ _newSceneNum = 24;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideCircusWorld].x, _hotspotsWalkPos[kHSExitOutsideCircusWorld].y, 0, 0x107BB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideCircusWorld].x + 1, _hotspotsWalkPos[kHSExitOutsideCircusWorld].y, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSStonerGuy:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSStonerGuy].x, _hotspotsWalkPos[kHSStonerGuy].y, 5, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan2(5, 4);
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[kHSStonerGuy].x, _hotspotsWalkPos[kHSStonerGuy].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ if (_s20_stonerGuyShowingJoint)
+ _gnapActionStatus = kASGrabJoint;
+ else
+ playGnapImpossible(0, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[kHSStonerGuy].x, _hotspotsWalkPos[kHSStonerGuy].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ if (isFlag(17))
+ _gnapActionStatus = kASTalkStonerGuyNoJoint;
+ else
+ _gnapActionStatus = kASTalkStonerGuyHasJoint;
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSGroceryStoreGuy:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSGroceryStoreGuy].x, _hotspotsWalkPos[kHSGroceryStoreGuy].y, 2, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(2, 3);
+ break;
+ case GRAB_CURSOR:
+ _s20_stonerGuyShowingJoint = false;
+ _gnapIdleFacing = 5;
+ gnapWalkTo(_hotspotsWalkPos[kHSGroceryStoreGuy].x, _hotspotsWalkPos[kHSGroceryStoreGuy].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASGrabGroceryStoreGuy;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 5;
+ gnapWalkTo(_hotspotsWalkPos[kHSGroceryStoreGuy].x, _hotspotsWalkPos[kHSGroceryStoreGuy].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkGroceryStoreGuy;
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSGroceryStoreHat:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemCowboyHat) {
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[kHSGroceryStoreHat].x, _hotspotsWalkPos[kHSGroceryStoreHat].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASSwitchGroceryStoreHat;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSGroceryStoreHat].x, _hotspotsWalkPos[kHSGroceryStoreHat].y, 1, 6);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(1, 6);
+ break;
+ case GRAB_CURSOR:
+ _s20_stonerGuyShowingJoint = false;
+ _gnapIdleFacing = 5;
+ gnapWalkTo(_hotspotsWalkPos[kHSGroceryStoreGuy].x, _hotspotsWalkPos[kHSGroceryStoreGuy].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASGrabGroceryStoreHat;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene20_updateAnimations();
+
+ if (!isSoundPlaying(0x10940))
+ playSound(0x10940, 1);
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0) {
+ _hotspots[kHSWalkArea1].y2 += 48;
+ updateBeaverIdleSequence();
+ _hotspots[kHSWalkArea1].y2 -= 48;
+ }
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (_gnapActionStatus < 0 && !_timers[5] && _s20_nextGroceryStoreGuySequenceId == -1) {
+ _timers[5] = getRandom(50) + 130;
+ if (getRandom(4) != 0)
+ _s20_nextGroceryStoreGuySequenceId = 0x17C;
+ else
+ _s20_nextGroceryStoreGuySequenceId = 0x17A;
+ }
+ if (!_timers[7]) {
+ _timers[7] = getRandom(100) + 100;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0) {
+ switch (getRandom(3)) {
+ case 0:
+ _gameSys->insertSequence(0x183, 253, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 1:
+ _gameSys->insertSequence(0x184, 253, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 2:
+ _gameSys->insertSequence(0x185, 253, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ }
+ }
+ }
+ playSoundA();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene20_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene20_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ case kASTalkStonerGuyNoJoint:
+ _gameSys->setAnimation(0x170, 21, 2);
+ _gameSys->setAnimation(0x17B, 20, 3);
+ _gameSys->insertSequence(0x17B, 20, _s20_currGroceryStoreGuySequenceId, 20, 32, 0, 0, 0);
+ _gameSys->insertSequence(0x170, 21, _s20_currStonerGuySequenceId, 21, 32, 0, 0, 0);
+ stopSound(0x1A1);
+ scene20_stopSounds();
+ _s20_currGroceryStoreGuySequenceId = 0x17B;
+ _s20_currStonerGuySequenceId = 0x170;
+ _s20_nextGroceryStoreGuySequenceId = -1;
+ _s20_nextStonerGuySequenceId = 0x16E;
+ _timers[5] = 100;
+ _timers[6] = 100;
+ break;
+ case kASTalkStonerGuyHasJoint:
+ _gameSys->setAnimation(0x168, 21, 2);
+ _gameSys->setAnimation(379, 20, 3);
+ _gameSys->insertSequence(0x17B, 20, _s20_currGroceryStoreGuySequenceId, 20, 32, 0, 0, 0);
+ _gameSys->insertSequence(0x170, 21, _s20_currStonerGuySequenceId, 21, 32, 0, 0, 0);
+ _gameSys->insertSequence(0x168, 21, 0x170, 21, kSeqSyncWait, 0, 0, 0);
+ stopSound(0x1A1);
+ scene20_stopSounds();
+ _s20_currGroceryStoreGuySequenceId = 0x17B;
+ _s20_currStonerGuySequenceId = 0x168;
+ _s20_nextGroceryStoreGuySequenceId = -1;
+ _s20_nextStonerGuySequenceId = 0x16B;
+ _timers[5] = 200;
+ _timers[6] = 200;
+ _timers[4] = 100;
+ _s20_stonerGuyShowingJoint = true;
+ _gnapActionStatus = -1;
+ break;
+ case kASGrabJoint:
+ _s20_nextStonerGuySequenceId = 0x16A;
+ break;
+ case kASActionDone:
+ _gnapActionStatus = -1;
+ break;
+ case kASTalkGroceryStoreGuy:
+ _gameSys->setAnimation(0x170, 21, 2);
+ _gameSys->setAnimation(0x17B, 20, 3);
+ _gameSys->insertSequence(0x17B, 20, _s20_currGroceryStoreGuySequenceId, 20, 32, 0, 0, 0);
+ _gameSys->insertSequence(0x170, 21, _s20_currStonerGuySequenceId, 21, 32, 0, 0, 0);
+ stopSound(0x1A1);
+ scene20_stopSounds();
+ _s20_currGroceryStoreGuySequenceId = 0x17B;
+ _s20_currStonerGuySequenceId = 0x170;
+ _s20_groceryStoreGuyCtr = (_s20_groceryStoreGuyCtr + 1) % 2;
+ if (_s20_groceryStoreGuyCtr != 0)
+ _s20_nextGroceryStoreGuySequenceId = 0x176;
+ else
+ _s20_nextGroceryStoreGuySequenceId = 0x177;
+ _timers[5] = 100;
+ _timers[6] = 100;
+ break;
+ case kASGrabGroceryStoreGuy:
+ _gameSys->setAnimation(0x170, 21, 2);
+ _gameSys->setAnimation(0x17B, 20, 3);
+ _gameSys->insertSequence(0x170, 21, _s20_currStonerGuySequenceId, 21, 32, 0, 0, 0);
+ _gameSys->insertSequence(0x17B, 20, _s20_currGroceryStoreGuySequenceId, 20, 32, 0, 0, 0);
+ stopSound(0x1A1);
+ scene20_stopSounds();
+ _s20_currGroceryStoreGuySequenceId = 0x17B;
+ _s20_currStonerGuySequenceId = 0x170;
+ _timers[5] = 120;
+ _timers[6] = 120;
+ _s20_nextGroceryStoreGuySequenceId = 0x178;
+ break;
+ case kASGrabGroceryStoreHat:
+ _gameSys->setAnimation(0x170, 21, 2);
+ _gameSys->setAnimation(0x17B, 20, 3);
+ _gameSys->insertSequence(0x17B, 20, _s20_currGroceryStoreGuySequenceId, 20, 32, 0, 0, 0);
+ _gameSys->insertSequence(0x170, 21, _s20_currStonerGuySequenceId, 21, 32, 0, 0, 0);
+ stopSound(0x1A1);
+ scene20_stopSounds();
+ _s20_currGroceryStoreGuySequenceId = 0x17B;
+ _s20_currStonerGuySequenceId = 0x170;
+ _s20_nextGroceryStoreGuySequenceId = 0x179;
+ break;
+ case kASSwitchGroceryStoreHat:
+ setGrabCursorSprite(-1);
+ _gameSys->setAnimation(0x180, _gnapId, 0);
+ _gameSys->insertSequence(0x180, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x180;
+ _gnapSequenceDatNum = 0;
+ invRemove(kItemCowboyHat);
+ invAdd(kItemGroceryStoreHat);
+ _gnapActionStatus = kASSwitchGroceryStoreHatDone;
+ break;
+ case kASSwitchGroceryStoreHatDone:
+ _gameSys->insertSequence(0x17F, 20, 372, 20, kSeqSyncWait, 0, 0, 0);
+ setFlag(19);
+ hideCursor();
+ setGrabCursorSprite(-1);
+ addFullScreenSprite(0x12C, 255);
+ _gameSys->setAnimation(0x181, 256, 0);
+ _gameSys->insertSequence(0x181, 256, 0, 0, kSeqNone, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(0) != 2)
+ gameUpdateTick();
+ removeFullScreenSprite();
+ showCursor();
+ setGrabCursorSprite(kItemGroceryStoreHat);
+ _gnapIdleFacing = 1;
+ gnapWalkTo(3, 8, -1, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = -1;
+ break;
+ case kASGrabJointDone:
+ setGrabCursorSprite(kItemJoint);
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ switch (_s20_nextGroceryStoreGuySequenceId) {
+ case 0x176:
+ case 0x177:
+ _gameSys->setAnimation(_s20_nextGroceryStoreGuySequenceId, 20, 3);
+ _gameSys->insertSequence(_s20_nextGroceryStoreGuySequenceId, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _s20_currGroceryStoreGuySequenceId = _s20_nextGroceryStoreGuySequenceId;
+ _s20_nextGroceryStoreGuySequenceId = -1;
+ _s20_nextStonerGuySequenceId = 0x16D;
+ break;
+ case 0x178:
+ _gameSys->setAnimation(_s20_nextGroceryStoreGuySequenceId, 20, 3);
+ _gameSys->setAnimation(0x17D, _gnapId, 0);
+ _gameSys->insertSequence(_s20_nextGroceryStoreGuySequenceId, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x17D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x17D;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = kASActionDone;
+ _gameSys->setAnimation(0x16D, 21, 2);
+ _gameSys->insertSequence(0x16D, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0);
+ _s20_currStonerGuySequenceId = 0x16D;
+ _s20_currGroceryStoreGuySequenceId = 0x178;
+ _s20_nextGroceryStoreGuySequenceId = -1;
+ _s20_nextStonerGuySequenceId = -1;
+ break;
+ case 0x179:
+ _gameSys->setAnimation(_s20_nextGroceryStoreGuySequenceId, 20, 3);
+ _gameSys->setAnimation(0x16D, 21, 0);
+ _gameSys->insertSequence(_s20_nextGroceryStoreGuySequenceId, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x17E, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x17E;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = kASActionDone;
+ _gameSys->setAnimation(0x16D, 21, 2);
+ _gameSys->insertSequence(0x16D, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0);
+ _s20_currStonerGuySequenceId = 0x16D;
+ _s20_currGroceryStoreGuySequenceId = 377;
+ _s20_nextGroceryStoreGuySequenceId = -1;
+ _s20_nextStonerGuySequenceId = -1;
+ gnapWalkTo(4, 8, -1, 0x107BB, 1);
+ break;
+ case 0x17C:
+ _gameSys->setAnimation(0, 0, 3);
+ _s20_nextStonerGuySequenceId = 0x171;
+ break;
+ case 0x17A:
+ _gameSys->setAnimation(0, 0, 3);
+ _s20_nextStonerGuySequenceId = 0x16F;
+ break;
+ case 0x175:
+ _gameSys->setAnimation(0x175, 20, 0);
+ _gameSys->setAnimation(0x175, 20, 3);
+ _gameSys->insertSequence(0x175, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _s20_currGroceryStoreGuySequenceId = 0x175;
+ _s20_nextGroceryStoreGuySequenceId = -1;
+ _gnapActionStatus = kASActionDone;
+ break;
+ default:
+ if (_s20_nextGroceryStoreGuySequenceId != -1) {
+ _gameSys->setAnimation(_s20_nextGroceryStoreGuySequenceId, 20, 3);
+ _gameSys->insertSequence(_s20_nextGroceryStoreGuySequenceId, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _s20_currGroceryStoreGuySequenceId = _s20_nextGroceryStoreGuySequenceId;
+ _s20_nextGroceryStoreGuySequenceId = -1;
+ }
+ break;
+ }
+ }
+
+ scene20_updateAnimationsCb();
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene21.cpp b/engines/gnap/scenes/scene21.cpp
new file mode 100644
index 0000000000..56da904ce1
--- /dev/null
+++ b/engines/gnap/scenes/scene21.cpp
@@ -0,0 +1,345 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSBanana = 1,
+ kHSOldLady = 2,
+ kHSDevice = 3,
+ kHSExitOutsideGrubCity = 4,
+ kHSWalkArea1 = 5,
+ kHSWalkArea2 = 6
+};
+
+enum {
+ kASTalkOldLady = 0,
+ kASGrabBanana = 1,
+ kASGrabBananaDone = 2,
+ kASGrabOldLady = 3,
+ kASUseHatWithOldLady = 4,
+ kASUseHatWithOldLadyDone = 5,
+ kASLeaveScene = 6
+};
+
+int GnapEngine::scene21_init() {
+ _gameSys->setAnimation(0, 0, 3);
+ return isFlag(3) ? 0x94 : 0x93;
+}
+
+void GnapEngine::scene21_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSBanana, 94, 394, 146, 430, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 2, 6);
+ setHotspot(kHSOldLady, 402, 220, 528, 430, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7);
+ setHotspot(kHSExitOutsideGrubCity, 522, 498, 800, 600, SF_EXIT_SE_CURSOR | SF_WALKABLE, 5, 10);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 440);
+ setHotspot(kHSWalkArea2, 698, 0, 800, 600);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(4) || !isFlag(3))
+ _hotspots[kHSBanana].flags = SF_WALKABLE | SF_DISABLED;
+ if (isFlag(3))
+ _hotspots[kHSOldLady].flags = SF_DISABLED;
+ _hotspotsCount = 7;
+}
+
+void GnapEngine::scene21_run() {
+
+ playSound(0x10940, 1);
+ startSoundTimerA(6);
+
+ _timers[5] = getRandom(100) + 100;
+
+ queueInsertDeviceIcon();
+
+ if (isFlag(3)) {
+ if (isFlag(5)) {
+ initGnapPos(5, 8, 1);
+ initBeaverPos(6, 8, 0);
+ _gameSys->insertSequence(0x8E, 2, 0, 0, kSeqNone, 0, 0, 0);
+ if (!isFlag(4))
+ _gameSys->insertSequence(0x8D, 59, 0, 0, kSeqNone, 0, 0, 0);
+ endSceneInit();
+ clearFlag(5);
+ } else {
+ initGnapPos(5, 11, 1);
+ initBeaverPos(6, 11, 0);
+ if (!isFlag(4))
+ _gameSys->insertSequence(0x8D, 59, 0, 0, kSeqNone, 0, 0, 0);
+ endSceneInit();
+ gnapWalkTo(5, 8, -1, 0x107B9, 1);
+ platypusWalkTo(6, 8, -1, 0x107C2, 1);
+ }
+ } else {
+ initGnapPos(5, 11, 1);
+ initBeaverPos(6, 11, 0);
+ _s21_currOldLadySequenceId = 0x89;
+ _gameSys->setAnimation(0x89, 79, 3);
+ _gameSys->insertSequence(_s21_currOldLadySequenceId, 79, 0, 0, kSeqNone, 0, 0, 0);
+ _s21_nextOldLadySequenceId = -1;
+ _timers[4] = getRandom(30) + 50;
+ endSceneInit();
+ gnapWalkTo(5, 8, -1, 0x107B9, 1);
+ platypusWalkTo(6, 8, -1, 0x107C2, 1);
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene21_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSBanana:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowItem(_grabCursorSpriteIndex, 2, 5);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(2, 5);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[kHSBanana].x, _hotspotsWalkPos[kHSBanana].y) | 0x10000, 1);
+ playGnapPullOutDevice(2, 5);
+ playGnapUseDevice(0, 0);
+ _gnapActionStatus = kASGrabBanana;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSOldLady:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemGroceryStoreHat) {
+ _newSceneNum = 47;
+ gnapWalkTo(4, 6, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASUseHatWithOldLady;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(4, 6, 7, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(7, 4);
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 5;
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ gnapWalkTo(7, 6, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASGrabOldLady;
+ _hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[kHSOldLady].x, _hotspotsWalkPos[kHSOldLady].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkOldLady;
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitOutsideGrubCity:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _newSceneNum = 20;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x, _hotspotsWalkPos[kHSExitOutsideGrubCity].y, 0, 0x107B3, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x + 1, _hotspotsWalkPos[kHSExitOutsideGrubCity].y, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene21_updateAnimations();
+
+ if (!isSoundPlaying(0x10940))
+ playSound(0x10940, 1);
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!isFlag(3) && !_timers[4] && _s21_nextOldLadySequenceId == -1 && _gnapActionStatus == -1) {
+ _timers[4] = getRandom(30) + 50;
+ switch (getRandom(5)) {
+ case 0:
+ _s21_nextOldLadySequenceId = 0x88;
+ break;
+ case 1:
+ _s21_nextOldLadySequenceId = 0x8A;
+ break;
+ default:
+ _s21_nextOldLadySequenceId = 0x89;
+ break;
+ }
+ }
+ if (!_timers[5]) {
+ _timers[5] = getRandom(100) + 100;
+ _gameSys->insertSequence(0x92, 255, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ playSoundA();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene21_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene21_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASTalkOldLady:
+ _s21_nextOldLadySequenceId = 0x8B;
+ _gnapActionStatus = -1;
+ break;
+ case kASGrabBanana:
+ _gameSys->setAnimation(0x8C, 59, 0);
+ _gameSys->insertSequence(0x8C, 59, 141, 59, kSeqSyncWait, 0, 0, 0);
+ setFlag(4);
+ invAdd(kItemBanana);
+ scene21_updateHotspots();
+ _gnapActionStatus = kASGrabBananaDone;
+ break;
+ case kASGrabBananaDone:
+ setGrabCursorSprite(kItemBanana);
+ _gnapActionStatus = -1;
+ break;
+ case kASGrabOldLady:
+ _timers[4] = getRandom(30) + 50;
+ _s21_nextOldLadySequenceId = 0x87;
+ break;
+ case kASUseHatWithOldLady:
+ _gameSys->setAnimation(0x8F, _gnapId, 0);
+ _gameSys->insertSequence(0x8F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x8F;
+ _gnapActionStatus = kASUseHatWithOldLadyDone;
+ invAdd(kItemTickets);
+ invRemove(kItemGroceryStoreHat);
+ setGrabCursorSprite(-1);
+ break;
+ case kASUseHatWithOldLadyDone:
+ _s21_nextOldLadySequenceId = 0x91;
+ break;
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2 && _s21_nextOldLadySequenceId != -1) {
+ if (_s21_nextOldLadySequenceId == 0x87) {
+ _gameSys->setAnimation(_s21_nextOldLadySequenceId, 79, 3);
+ _gameSys->insertSequence(_s21_nextOldLadySequenceId, 79, _s21_currOldLadySequenceId, 79, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x86, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x86;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = -1;
+ _s21_currOldLadySequenceId = _s21_nextOldLadySequenceId;
+ _s21_nextOldLadySequenceId = -1;
+ } else if (_s21_nextOldLadySequenceId == 0x91) {
+ _gameSys->setAnimation(0x91, 79, 0);
+ _gameSys->insertSequence(_s21_nextOldLadySequenceId, 79, _s21_currOldLadySequenceId, 79, kSeqSyncWait, 0, 0, 0);
+ _gnapActionStatus = kASLeaveScene;
+ _s21_currOldLadySequenceId = _s21_nextOldLadySequenceId;
+ _s21_nextOldLadySequenceId = -1;
+ } else {
+ _gameSys->setAnimation(_s21_nextOldLadySequenceId, 79, 3);
+ _gameSys->insertSequence(_s21_nextOldLadySequenceId, 79, _s21_currOldLadySequenceId, 79, kSeqSyncWait, 0, 0, 0);
+ _s21_currOldLadySequenceId = _s21_nextOldLadySequenceId;
+ _s21_nextOldLadySequenceId = -1;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene22.cpp b/engines/gnap/scenes/scene22.cpp
new file mode 100644
index 0000000000..0290666daa
--- /dev/null
+++ b/engines/gnap/scenes/scene22.cpp
@@ -0,0 +1,294 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitOutsideGrubCity = 1,
+ kHSExitBackGrubCity = 2,
+ kHSCashier = 3,
+ kHSDevice = 4,
+ kHSWalkArea1 = 5,
+ kHSWalkArea2 = 6
+};
+
+enum {
+ kASLeaveScene = 0,
+ kASTalkCashier = 1
+};
+
+int GnapEngine::scene22_init() {
+ return 0x5E;
+}
+
+void GnapEngine::scene22_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitOutsideGrubCity, 0, 180, 184, 472, SF_EXIT_L_CURSOR, 3, 6);
+ setHotspot(kHSExitBackGrubCity, 785, 405, 800, 585, SF_EXIT_R_CURSOR, 11, 9);
+ setHotspot(kHSCashier, 578, 230, 660, 376, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 8);
+ setHotspot(kHSWalkArea1, 553, 0, 800, 542);
+ setHotspot(kHSWalkArea2, 0, 0, 552, 488);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 7;
+}
+
+void GnapEngine::scene22_run() {
+
+ _gameSys->insertSequence(0x5D, 254, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s22_currCashierSequenceId = 0x59;
+ _s22_nextCashierSequenceId = -1;
+
+ _gameSys->setAnimation(0x59, 1, 3);
+ _gameSys->insertSequence(_s22_currCashierSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ _timers[6] = getRandom(30) + 20;
+
+ queueInsertDeviceIcon();
+
+ if (_prevSceneNum == 20) {
+ initGnapPos(2, 8, 1);
+ initBeaverPos(1, 8, 0);
+ endSceneInit();
+ } else {
+ initGnapPos(11, _hotspotsWalkPos[kHSExitBackGrubCity].y, 1);
+ initBeaverPos(11, _hotspotsWalkPos[kHSExitBackGrubCity].y + 1, 0);
+ endSceneInit();
+ gnapWalkTo(8, 8, -1, 0x107B9, 1);
+ platypusWalkTo(9, 8, -1, 0x107C2, 1);
+ }
+
+ if (isFlag(11)) {
+ int storeDetectiveSeqId;
+ setGrabCursorSprite(-1);
+ invRemove(kItemCereals);
+ if (_s22_caughtBefore) {
+ switch (getRandom(3)) {
+ case 0:
+ storeDetectiveSeqId = 0x55;
+ break;
+ case 1:
+ storeDetectiveSeqId = 0x56;
+ break;
+ case 2:
+ storeDetectiveSeqId = 0x57;
+ break;
+ }
+ } else {
+ _s22_caughtBefore = true;
+ storeDetectiveSeqId = 0x54;
+ }
+ _gameSys->waitForUpdate();
+ _gameSys->requestClear1();
+ _gameSys->drawSpriteToBackground(0, 0, 0x44);
+ _gameSys->setAnimation(storeDetectiveSeqId, 256, 4);
+ _gameSys->insertSequence(storeDetectiveSeqId, 256, 0, 0, kSeqNone, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(4) != 2) {
+ gameUpdateTick();
+ }
+ _sceneDone = true;
+ _newSceneNum = 20;
+ _s22_caughtBefore = true;
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene22_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitOutsideGrubCity:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _newSceneNum = 20;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x, _hotspotsWalkPos[kHSExitOutsideGrubCity].y, 0, 0x107AF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x, _hotspotsWalkPos[kHSExitOutsideGrubCity].y + 1, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSExitBackGrubCity:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _newSceneNum = 23;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitBackGrubCity].x, _hotspotsWalkPos[kHSExitBackGrubCity].y, 0, 0x107AB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitBackGrubCity].x, _hotspotsWalkPos[kHSExitBackGrubCity].y + 1, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSCashier:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSCashier].x, _hotspotsWalkPos[kHSCashier].y, 8, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(8, 4);
+ break;
+ case GRAB_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[kHSCashier].x, _hotspotsWalkPos[kHSCashier].y,
+ 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkCashier;
+ break;
+ case PLAT_CURSOR:
+ gnapUseDeviceOnBeaver();
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene22_updateAnimations();
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!_timers[6] && _s22_nextCashierSequenceId == -1) {
+ _timers[6] = getRandom(30) + 20;
+ if (getRandom(8) != 0) {
+ _s22_nextCashierSequenceId = 0x59;
+ } else {
+ _s22_cashierCtr = (_s22_cashierCtr + 1) % 3;
+ switch (_s22_cashierCtr) {
+ case 1:
+ _s22_nextCashierSequenceId = 0x58;
+ break;
+ case 2:
+ _s22_nextCashierSequenceId = 0x5A;
+ break;
+ case 3:
+ _s22_nextCashierSequenceId = 0x5B;
+ break;
+ default:
+ _s22_nextCashierSequenceId = 0x58;
+ break;
+ }
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene22_updateHotspots();
+ _timers[2] = getRandom(30) + 20;
+ _timers[3] = 400;
+ _timers[1] = getRandom(20) + 30;
+ _timers[0] = getRandom(75) + 75;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene22_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ case kASTalkCashier:
+ _s22_nextCashierSequenceId = 0x5C;
+ break;
+ }
+ _gnapActionStatus = -1;
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2 && _s22_nextCashierSequenceId != -1) {
+ _gameSys->setAnimation(_s22_nextCashierSequenceId, 1, 3);
+ _gameSys->insertSequence(_s22_nextCashierSequenceId, 1, _s22_currCashierSequenceId, 1, kSeqSyncWait, 0, 0, 0);
+ _s22_currCashierSequenceId = _s22_nextCashierSequenceId;
+ _s22_nextCashierSequenceId = -1;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene23.cpp b/engines/gnap/scenes/scene23.cpp
new file mode 100644
index 0000000000..cafeb71a56
--- /dev/null
+++ b/engines/gnap/scenes/scene23.cpp
@@ -0,0 +1,297 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitFrontGrubCity = 1,
+ kHSDevice = 2,
+ kHSCereals = 3,
+ kHSWalkArea1 = 4,
+ kHSWalkArea2 = 5
+};
+
+enum {
+ kASLookCereals = 0,
+ kASGrabCereals = 1,
+ kASGrabCerealsDone = 2,
+ kASLeaveScene = 3
+};
+
+int GnapEngine::scene23_init() {
+ return 0xC0;
+}
+
+void GnapEngine::scene23_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitFrontGrubCity, 0, 250, 15, 550, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 7);
+ setHotspot(kHSCereals, 366, 332, 414, 408, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7);
+ setHotspot(kHSWalkArea1, 0, 0, 340, 460);
+ setHotspot(kHSWalkArea2, 340, 0, 800, 501);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 6;
+}
+
+void GnapEngine::scene23_run() {
+
+ _timers[4] = getRandom(100) + 200;
+ _timers[5] = getRandom(100) + 200;
+
+ _s23_currStoreClerkSequenceId = 0xB4;
+ _s23_nextStoreClerkSequenceId = -1;
+
+ _gameSys->setAnimation(0xB4, 1, 4);
+ _gameSys->insertSequence(_s23_currStoreClerkSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ queueInsertDeviceIcon();
+
+ initGnapPos(-1, 7, 1);
+ initBeaverPos(-2, 7, 0);
+ _gameSys->insertSequence(0xBD, 255, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0xBF, 2, 0, 0, kSeqNone, 0, 0, 0);
+ endSceneInit();
+
+ platypusWalkTo(1, 7, -1, 0x107C2, 1);
+
+ if (isFlag(24)) {
+ gnapWalkTo(2, 7, -1, 0x107B9, 1);
+ } else {
+ gnapWalkTo(2, 7, 0, 0x107B9, 1);
+ while (_gameSys->getAnimationStatus(0) != 2)
+ gameUpdateTick();
+ playSequences(0x48, 0xBA, 0xBB, 0xBC);
+ setFlag(24);
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 3, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene23_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSCereals:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSCereals].x, _hotspotsWalkPos[kHSCereals].y, 5, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(11))
+ playGnapMoan2(0, 0);
+ else {
+ gnapWalkTo(_hotspotsWalkPos[kHSCereals].x, _hotspotsWalkPos[kHSCereals].y,
+ 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASLookCereals;
+ }
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(11))
+ playGnapImpossible(0, 0);
+ else {
+ _gnapIdleFacing = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSCereals].x, _hotspotsWalkPos[kHSCereals].y,
+ 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ setFlag(11);
+ _gnapActionStatus = kASGrabCereals;
+ invAdd(kItemCereals);
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitFrontGrubCity:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 22;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitFrontGrubCity].x, _hotspotsWalkPos[kHSExitFrontGrubCity].y, 0, 0x107AF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitFrontGrubCity].x, _hotspotsWalkPos[kHSExitFrontGrubCity].y - 1, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene23_updateAnimations();
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!_timers[4] && _gnapActionStatus == -1) {
+ _timers[4] = getRandom(100) + 200;
+ switch (getRandom(4)) {
+ case 0:
+ _gameSys->insertSequence(0xB7, 256, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 1:
+ _gameSys->insertSequence(0xB8, 256, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 2:
+ case 3:
+ _gameSys->insertSequence(0xB9, 256, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ }
+ }
+ if (!_timers[5]) {
+ _timers[5] = getRandom(100) + 200;
+ switch (getRandom(3)) {
+ case 0:
+ playSound(0xCE, 0);
+ break;
+ case 1:
+ playSound(0xD0, 0);
+ break;
+ case 2:
+ playSound(0xCF, 0);
+ break;
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene23_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene23_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASLookCereals:
+ showFullScreenSprite(0x48);
+ _gnapActionStatus = -1;
+ break;
+ case kASGrabCereals:
+ _gameSys->setAnimation(0xBE, _gnapId, 0);
+ _gameSys->insertSequence(0xBE, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->requestRemoveSequence(0xBF, 2);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0xBE;
+ _gnapActionStatus = kASGrabCerealsDone;
+ break;
+ case kASGrabCerealsDone:
+ setGrabCursorSprite(kItemCereals);
+ _gnapActionStatus = -1;
+ break;
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(4) == 2 && _s23_nextStoreClerkSequenceId == -1) {
+ switch (getRandom(8)) {
+ case 0:
+ case 1:
+ case 2:
+ _s23_nextStoreClerkSequenceId = 0xB4;
+ break;
+ case 3:
+ case 4:
+ case 5:
+ _s23_nextStoreClerkSequenceId = 0xB5;
+ break;
+ default:
+ _s23_nextStoreClerkSequenceId = 0xB6;
+ break;
+ }
+ _gameSys->setAnimation(_s23_nextStoreClerkSequenceId, 1, 4);
+ _gameSys->insertSequence(_s23_nextStoreClerkSequenceId, 1, _s23_currStoreClerkSequenceId, 1, kSeqSyncWait, 0, 0, 0);
+ _s23_currStoreClerkSequenceId = _s23_nextStoreClerkSequenceId;
+ _s23_nextStoreClerkSequenceId = -1;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene24.cpp b/engines/gnap/scenes/scene24.cpp
new file mode 100644
index 0000000000..236ee7d30a
--- /dev/null
+++ b/engines/gnap/scenes/scene24.cpp
@@ -0,0 +1,261 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitCircusWorld = 1,
+ kHSExitOutsideGrubCity = 2,
+ kHSDevice = 3,
+ kHSWalkArea1 = 4,
+ kHSWalkArea2 = 5,
+ kHSWalkArea3 = 6
+};
+
+enum {
+ kASLeaveScene = 0
+};
+
+int GnapEngine::scene24_init() {
+ return 0x3B;
+}
+
+void GnapEngine::scene24_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitCircusWorld, 785, 128, 800, 600, SF_EXIT_R_CURSOR, 8, 7);
+ setHotspot(kHSExitOutsideGrubCity, 0, 213, 91, 600, SF_EXIT_NW_CURSOR, 1, 8);
+ setHotspot(kHSWalkArea1, 0, 0, 0, 0);
+ setHotspot(kHSWalkArea2, 530, 0, 800, 600);
+ setHotspot(kHSWalkArea3, 0, 0, 800, 517);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 7;
+}
+
+void GnapEngine::scene24_run() {
+ int counter = 0;
+
+ playSound(0x10940, 1);
+
+ startSoundTimerA(9);
+
+ _timers[7] = getRandom(100) + 100;
+
+ _gameSys->insertSequence(0x2F, 256, 0, 0, kSeqNone, 0, 0, 0);
+
+ _timers[4] = getRandom(20) + 50;
+ _timers[5] = getRandom(20) + 40;
+ _timers[6] = getRandom(50) + 30;
+
+ _gameSys->insertSequence(0x36, 20, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x30, 20, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x35, 20, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s24_currWomanSequenceId = 0x35;
+ _s24_girlSequenceId = 0x36;
+ _s24_boySequenceId = 0x30;
+
+ if (_debugLevel == 4)
+ startIdleTimer(8);
+
+ queueInsertDeviceIcon();
+
+ if (_prevSceneNum == 20) {
+ initGnapPos(1, 8, 1);
+ initBeaverPos(2, 8, 0);
+ endSceneInit();
+ gnapWalkTo(1, 9, -1, 0x107B9, 1);
+ platypusWalkTo(2, 9, -1, 0x107C2, 1);
+ } else {
+ initGnapPos(8, 8, 3);
+ initBeaverPos(8, 8, 4);
+ endSceneInit();
+ gnapWalkTo(2, 8, -1, 0x107BA, 1);
+ platypusWalkTo(3, 8, -1, 0x107C2, 1);
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene24_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitCircusWorld:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 25;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitCircusWorld].x, _hotspotsWalkPos[kHSExitCircusWorld].y, 0, 0x107AB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitCircusWorld].x + 1, _hotspotsWalkPos[kHSExitCircusWorld].y, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSExitOutsideGrubCity:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 20;
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x, _hotspotsWalkPos[kHSExitOutsideGrubCity].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x + 1, _hotspotsWalkPos[kHSExitOutsideGrubCity].y, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ if (_gnapActionStatus == -1)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene24_updateAnimations();
+
+ if (!isSoundPlaying(0x10940))
+ playSound(0x10940, 1);
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(20) + 50;
+ _gameSys->insertSequence(0x37, 20, _s24_girlSequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _s24_girlSequenceId = 0x37;
+ }
+ if (!_timers[5]) {
+ _timers[5] = getRandom(20) + 40;
+ _gameSys->insertSequence(0x31, 20, _s24_boySequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _s24_boySequenceId = 0x31;
+ }
+ if (!_timers[6]) {
+ _timers[6] = getRandom(50) + 30;
+ counter = (counter + 1) % 3;
+ switch (counter) {
+ case 0:
+ _s24_nextWomanSequenceId = 0x32;
+ break;
+ case 1:
+ _s24_nextWomanSequenceId = 0x33;
+ break;
+ case 2:
+ _s24_nextWomanSequenceId = 0x34;
+ break;
+ }
+ _gameSys->insertSequence(_s24_nextWomanSequenceId, 20, _s24_currWomanSequenceId, 20, kSeqSyncWait, 0, 0, 0);
+ _s24_currWomanSequenceId = _s24_nextWomanSequenceId;
+ }
+ if (!_timers[7]) {
+ _timers[7] = getRandom(100) + 100;
+ switch (getRandom(3)) {
+ case 0:
+ _gameSys->insertSequence(0x38, 253, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 1:
+ _gameSys->insertSequence(0x39, 253, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ case 2:
+ _gameSys->insertSequence(0x3A, 253, 0, 0, kSeqNone, 0, 0, 0);
+ break;
+ }
+ }
+ if (_debugLevel == 4)
+ updateIdleTimer();
+ playSoundA();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene24_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene24_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ if (_gnapActionStatus == kASLeaveScene)
+ _sceneDone = true;
+ _gnapActionStatus = -1;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene25.cpp b/engines/gnap/scenes/scene25.cpp
new file mode 100644
index 0000000000..cb82658cc2
--- /dev/null
+++ b/engines/gnap/scenes/scene25.cpp
@@ -0,0 +1,401 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSTicketVendor = 1,
+ kHSExitOutsideCircusWorld = 2,
+ kHSExitInsideCircusWorld = 3,
+ kHSDevice = 4,
+ kHSPosters1 = 5,
+ kHSPosters2 = 6,
+ kHSPosters3 = 7,
+ kHSPosters4 = 8,
+ kHSWalkArea1 = 9,
+ kHSWalkArea2 = 10
+};
+
+enum {
+ kASTalkTicketVendor = 0,
+ kASEnterCircusWihoutTicket = 1,
+ kASShowTicketToVendor = 2,
+ kASShowTicketToVendorDone = 3,
+ kASEnterCircusWihoutTicketDone = 4,
+ kASLeaveScene = 5
+};
+
+int GnapEngine::scene25_init() {
+ return 0x62;
+}
+
+void GnapEngine::scene25_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSTicketVendor, 416, 94, 574, 324, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 5);
+ setHotspot(kHSExitOutsideCircusWorld, 0, 519, 205, 600, SF_EXIT_SW_CURSOR, 5, 10);
+ setHotspot(kHSExitInsideCircusWorld, 321, 70, 388, 350, SF_EXIT_NE_CURSOR, 3, 6);
+ setHotspot(kHSPosters1, 0, 170, 106, 326, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 7);
+ setHotspot(kHSPosters2, 146, 192, 254, 306, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 7);
+ setHotspot(kHSPosters3, 606, 162, 654, 368, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 7);
+ setHotspot(kHSPosters4, 708, 114, 754, 490, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 439);
+ setHotspot(kHSWalkArea2, 585, 0, 800, 600);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 11;
+}
+
+void GnapEngine::scene25_playAnims(int index) {
+
+ if (index > 4)
+ return;
+
+ hideCursor();
+ setGrabCursorSprite(-1);
+ switch (index) {
+ case 1:
+ _largeSprite = _gameSys->createSurface(0x25);
+ break;
+ case 2:
+ _largeSprite = _gameSys->createSurface(0x26);
+ break;
+ case 3:
+ _largeSprite = _gameSys->createSurface(0x27);
+ break;
+ case 4:
+ _largeSprite = _gameSys->createSurface(0x28);
+ break;
+ }
+ _gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300);
+ delayTicksCursor(5);
+ 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);
+ _gameSys->removeSpriteDrawItem(_largeSprite, 300);
+ delayTicksCursor(5);
+ deleteSurface(&_largeSprite);
+ showCursor();
+}
+
+void GnapEngine::scene25_run() {
+
+ playSound(0x10940, 1);
+
+ startSoundTimerA(5);
+
+ _s25_currTicketVendorSequenceId = 0x52;
+ _gameSys->setAnimation(0x52, 39, 3);
+ _gameSys->insertSequence(_s25_currTicketVendorSequenceId, 39, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s25_nextTicketVendorSequenceId = -1;
+ _timers[4] = getRandom(20) + 20;
+
+ queueInsertDeviceIcon();
+
+ if (_prevSceneNum == 24) {
+ initGnapPos(5, 11, 5);
+ initBeaverPos(6, 11, 4);
+ endSceneInit();
+ gnapWalkTo(5, 7, -1, 0x107BA, 1);
+ platypusWalkTo(6, 7, -1, 0x107C2, 1);
+ } else {
+ initGnapPos(5, 6, 1);
+ initBeaverPos(6, 6, 0);
+ endSceneInit();
+ gnapWalkTo(5, 8, -1, 0x107B9, 1);
+ platypusWalkTo(6, 8, -1, 0x107C2, 1);
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene25_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSTicketVendor:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemTickets) {
+ _gnapActionStatus = kASShowTicketToVendor;
+ gnapWalkTo(_hotspotsWalkPos[kHSTicketVendor].x, _hotspotsWalkPos[kHSTicketVendor].y,
+ 0, getGnapSequenceId(gskIdle, 9, 4) | 0x10000, 1);
+ playGnapPullOutDevice(0, 0);
+ playGnapUseDevice(0, 0);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSTicketVendor].x, _hotspotsWalkPos[kHSTicketVendor].y, 6, 1);
+ _s25_nextTicketVendorSequenceId = 0x5B;
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(6, 1);
+ _s25_nextTicketVendorSequenceId = (getRandom(2) == 1) ? 0x59 : 0x56;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[kHSTicketVendor].x, _hotspotsWalkPos[kHSTicketVendor].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkTicketVendor;
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitOutsideCircusWorld:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 24;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideCircusWorld].x, _hotspotsWalkPos[kHSExitOutsideCircusWorld].y, 0, 0x107B4, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideCircusWorld].x + 1, _hotspotsWalkPos[kHSExitOutsideCircusWorld].y, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSExitInsideCircusWorld:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(2)) {
+ _isLeavingScene = true;
+ _newSceneNum = 26;
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitInsideCircusWorld].x, _hotspotsWalkPos[kHSExitInsideCircusWorld].y, 0, 0x107B1, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitInsideCircusWorld].x + 1, _hotspotsWalkPos[kHSExitInsideCircusWorld].y, -1, 0x107C2, 1);
+ _hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE;
+ } else {
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ gnapWalkTo(4, 5, 0, 0x107BB, 1);
+ _gnapActionStatus = kASEnterCircusWihoutTicket;
+ _hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE;
+ }
+ }
+ break;
+
+ case kHSPosters1:
+ case kHSPosters2:
+ case kHSPosters3:
+ case kHSPosters4:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, -1, -1, 1);
+ if (_sceneClickedHotspot == 5 || _sceneClickedHotspot == 6)
+ _gnapIdleFacing = 5;
+ else if (_sceneClickedHotspot == 8)
+ _gnapIdleFacing = 1;
+ else
+ _gnapIdleFacing = 7;
+ playGnapIdle(0, 0);
+ scene25_playAnims(8 - _sceneClickedHotspot + 1);
+ break;
+ case GRAB_CURSOR:
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapMoan2(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene25_updateAnimations();
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!_timers[4] && _s25_nextTicketVendorSequenceId == -1 && _gnapActionStatus == -1) {
+ _timers[4] = getRandom(20) + 20;
+ switch (getRandom(13)) {
+ case 0:
+ _s25_nextTicketVendorSequenceId = 0x54;
+ break;
+ case 1:
+ _s25_nextTicketVendorSequenceId = 0x58;
+ break;
+ case 2:
+ _s25_nextTicketVendorSequenceId = 0x55;
+ break;
+ case 3:
+ _s25_nextTicketVendorSequenceId = 0x5A;
+ break;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ _s25_nextTicketVendorSequenceId = 0x5B;
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ _s25_nextTicketVendorSequenceId = 0x5C;
+ break;
+ case 12:
+ _s25_nextTicketVendorSequenceId = 0x5D;
+ break;
+ default:
+ _s25_nextTicketVendorSequenceId = 0x52;
+ break;
+ }
+ }
+ playSoundA();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene25_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene25_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASTalkTicketVendor:
+ _s25_nextTicketVendorSequenceId = (getRandom(2) == 1) ? 0x57 : 0x5F;
+ _gnapActionStatus = -1;
+ break;
+ case kASEnterCircusWihoutTicket:
+ _s25_nextTicketVendorSequenceId = 0x5E;
+ _gameSys->setAnimation(0x5E, 39, 0);
+ _gameSys->setAnimation(_s25_nextTicketVendorSequenceId, 39, 3);
+ _gameSys->insertSequence(_s25_nextTicketVendorSequenceId, 39, _s25_currTicketVendorSequenceId, 39, 32, 0, 0, 0);
+ _gameSys->insertSequence(0x60, 2, 0, 0, kSeqNone, 0, 0, 0);
+ _s25_currTicketVendorSequenceId = _s25_nextTicketVendorSequenceId;
+ _s25_nextTicketVendorSequenceId = -1;
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ playGnapIdle(0, 0);
+ gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, -1, 0x107BB, 1);
+ _hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE;
+ _gnapActionStatus = kASEnterCircusWihoutTicketDone;
+ break;
+ case kASEnterCircusWihoutTicketDone:
+ _gnapActionStatus = -1;
+ break;
+ case kASShowTicketToVendor:
+ setGrabCursorSprite(-1);
+ invRemove(kItemTickets);
+ setFlag(2);
+ _gameSys->setAnimation(0x61, 40, 0);
+ _gameSys->insertSequence(0x61, 40, 0, 0, kSeqNone, 0, 0, 0);
+ _gnapActionStatus = kASShowTicketToVendorDone;
+ break;
+ case kASShowTicketToVendorDone:
+ _s25_nextTicketVendorSequenceId = 0x53;
+ break;
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ if (_s25_nextTicketVendorSequenceId == 0x53) {
+ _gameSys->insertSequence(_s25_nextTicketVendorSequenceId, 39, _s25_currTicketVendorSequenceId, 39, kSeqSyncWait, 0, 0, 0);
+ _s25_currTicketVendorSequenceId = _s25_nextTicketVendorSequenceId;
+ _s25_nextTicketVendorSequenceId = -1;
+ _gnapActionStatus = -1;
+ } else if (_s25_nextTicketVendorSequenceId != -1) {
+ _gameSys->setAnimation(_s25_nextTicketVendorSequenceId, 39, 3);
+ _gameSys->insertSequence(_s25_nextTicketVendorSequenceId, 39, _s25_currTicketVendorSequenceId, 39, kSeqSyncWait, 0, 0, 0);
+ _s25_currTicketVendorSequenceId = _s25_nextTicketVendorSequenceId;
+ _s25_nextTicketVendorSequenceId = -1;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene26.cpp b/engines/gnap/scenes/scene26.cpp
new file mode 100644
index 0000000000..644db6b3fd
--- /dev/null
+++ b/engines/gnap/scenes/scene26.cpp
@@ -0,0 +1,256 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitOutsideCircusWorld = 1,
+ kHSExitOutsideClown = 2,
+ kHSExitArcade = 3,
+ kHSExitElephant = 4,
+ kHSExitBeerStand = 5,
+ kHSDevice = 6,
+ kHSWalkArea1 = 7,
+ kHSWalkArea2 = 8
+};
+
+enum {
+ kASLeaveScene = 0
+};
+
+int GnapEngine::scene26_init() {
+ return isFlag(23) ? 0x61 : 0x60;
+}
+
+void GnapEngine::scene26_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitOutsideCircusWorld, 0, 590, 300, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 1, 10);
+ setHotspot(kHSExitOutsideClown, 200, 265, 265, 350, SF_EXIT_U_CURSOR, 3, 8);
+ setHotspot(kHSExitArcade, 0, 295, 150, 400, SF_EXIT_NW_CURSOR, 2, 8);
+ setHotspot(kHSExitElephant, 270, 290, 485, 375, SF_EXIT_U_CURSOR, 5, 8);
+ setHotspot(kHSExitBeerStand, 530, 290, 620, 350, SF_EXIT_NE_CURSOR, 5, 8);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 500);
+ setHotspot(kHSWalkArea2, 281, 0, 800, 600);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 9;
+}
+
+void GnapEngine::scene26_run() {
+
+ startSoundTimerB(7);
+ playSound(0x1093B, 1);
+
+ _s26_currKidSequenceId = 0x5B;
+ _s26_nextKidSequenceId = -1;
+ _gameSys->setAnimation(0x5B, 160, 3);
+ _gameSys->insertSequence(_s26_currKidSequenceId, 160, 0, 0, kSeqNone, 0, 0, 0);
+
+ _timers[5] = getRandom(20) + 50;
+ _timers[4] = getRandom(20) + 50;
+ _timers[6] = getRandom(50) + 100;
+
+ queueInsertDeviceIcon();
+
+ _gameSys->insertSequence(0x58, 40, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0x5C, 40, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0x5D, 40, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0x5E, 40, 0, 0, kSeqLoop, 0, 0, 0);
+
+ if (_prevSceneNum == 25) {
+ initGnapPos(-1, 8, 1);
+ initBeaverPos(-2, 8, 0);
+ endSceneInit();
+ gnapWalkTo(2, 8, -1, 0x107B9, 1);
+ platypusWalkTo(1, 8, -1, 0x107C2, 1);
+ } else {
+ initGnapPos(2, 8, 1);
+ initBeaverPos(3, 8, 0);
+ endSceneInit();
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene26_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitOutsideCircusWorld:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 25;
+ gnapWalkTo(-1, _hotspotsWalkPos[kHSExitOutsideCircusWorld].y, 0, 0x107AE, 1);
+ _gnapActionStatus = kASLeaveScene;
+ }
+ break;
+
+ case kHSExitOutsideClown:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 27;
+ gnapWalkTo(-1, _hotspotsWalkPos[kHSExitOutsideClown].y, 0, 0x107BC, 1);
+ _gnapActionStatus = kASLeaveScene;
+ }
+ break;
+
+ case kHSExitArcade:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 29;
+ gnapWalkTo(-1, _hotspotsWalkPos[kHSExitArcade].y, 0, 0x107BC, 1);
+ _gnapActionStatus = kASLeaveScene;
+ }
+ break;
+
+ case kHSExitElephant:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 30;
+ gnapWalkTo(-1, _hotspotsWalkPos[4].y, 0, 0x107BC, 1);
+ _gnapActionStatus = kASLeaveScene;
+ }
+ break;
+
+ case kHSExitBeerStand:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 31;
+ gnapWalkTo(-1, _hotspotsWalkPos[kHSExitBeerStand].y, 0, 0x107BB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene26_updateAnimations();
+
+ if (!isSoundPlaying(0x1093B))
+ playSound(0x1093B, 1);
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!_timers[5] && _s26_nextKidSequenceId == -1) {
+ _timers[5] = getRandom(20) + 50;
+ if (getRandom(5) != 0)
+ _s26_nextKidSequenceId = 0x5B;
+ else
+ _s26_nextKidSequenceId = 0x5A;
+ }
+ if (!_timers[4]) {
+ _timers[4] = getRandom(20) + 130;
+ _gameSys->insertSequence(0x59, 40, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ if (!_timers[6]) {
+ _timers[6] = getRandom(50) + 100;
+ _gameSys->insertSequence(0x5F, 40, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ playSoundB();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene26_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene26_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ if (_gnapActionStatus == kASLeaveScene)
+ _sceneDone = true;
+ _gnapActionStatus = -1;
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2 && _s26_nextKidSequenceId != -1) {
+ _gameSys->insertSequence(_s26_nextKidSequenceId, 160, _s26_currKidSequenceId, 160, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s26_nextKidSequenceId, 160, 3);
+ _s26_currKidSequenceId = _s26_nextKidSequenceId;
+ _s26_nextKidSequenceId = -1;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene27.cpp b/engines/gnap/scenes/scene27.cpp
new file mode 100644
index 0000000000..000a94203c
--- /dev/null
+++ b/engines/gnap/scenes/scene27.cpp
@@ -0,0 +1,423 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSJanitor = 1,
+ kHSDevice = 2,
+ kHSBucket = 3,
+ kHSExitCircus = 4,
+ kHSExitArcade = 5,
+ kHSExitBeerStand = 6,
+ kHSExitClown = 7,
+ kHSWalkArea1 = 8
+};
+
+enum {
+ kASTalkJanitor = 0,
+ kASGrabBucket = 1,
+ kASGrabBucketDone = 2,
+ kASShowPictureToJanitor = 3,
+ kASTryEnterClownTent = 4,
+ kASTryEnterClownTentDone = 5,
+ kASEnterClownTent = 6,
+ kASLeaveScene = 7
+};
+
+int GnapEngine::scene27_init() {
+ return 0xD5;
+}
+
+void GnapEngine::scene27_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSJanitor, 488, 204, 664, 450, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 8, 8);
+ setHotspot(kHSBucket, 129, 406, 186, 453, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 6);
+ setHotspot(kHSExitCircus, 200, 585, 700, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9);
+ setHotspot(kHSExitArcade, 0, 0, 15, 600, SF_EXIT_L_CURSOR, 0, 6);
+ setHotspot(kHSExitBeerStand, 785, 0, 800, 600, SF_EXIT_R_CURSOR, 11, 7);
+ setHotspot(kHSExitClown, 340, 240, 460, 420, SF_EXIT_U_CURSOR, 6, 8);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 507);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(13))
+ _hotspots[kHSBucket].flags = SF_DISABLED;
+ _hotspotsCount = 9;
+}
+
+void GnapEngine::scene27_run() {
+
+ playSound(0x1093B, 1);
+ startSoundTimerB(4);
+ _timers[7] = getRandom(100) + 300;
+ queueInsertDeviceIcon();
+
+ if (!isFlag(13))
+ _gameSys->insertSequence(0xD3, 39, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (_debugLevel == 4)
+ startIdleTimer(6);
+
+ _gameSys->insertSequence(0xCB, 39, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s27_currJanitorSequenceId = 0xCB;
+ _s27_nextJanitorSequenceId = -1;
+
+ _gameSys->setAnimation(0xCB, 39, 3);
+
+ _timers[5] = getRandom(20) + 60;
+
+ switch (_prevSceneNum) {
+ case 26:
+ initGnapPos(7, 12, 1);
+ initBeaverPos(6, 12, 0);
+ endSceneInit();
+ gnapWalkTo(7, 8, -1, 0x107B9, 1);
+ platypusWalkTo(6, 8, -1, 0x107C2, 1);
+ break;
+ case 29:
+ initGnapPos(-1, 8, 1);
+ initBeaverPos(-1, 9, 0);
+ endSceneInit();
+ gnapWalkTo(3, 8, -1, 0x107B9, 1);
+ platypusWalkTo(3, 9, -1, 0x107C2, 1);
+ break;
+ case 31:
+ initGnapPos(12, 8, 3);
+ initBeaverPos(12, 9, 4);
+ endSceneInit();
+ gnapWalkTo(8, 8, -1, 0x107BA, 1);
+ platypusWalkTo(8, 9, -1, 0x107C2, 1);
+ break;
+ default:
+ initGnapPos(6, 8, 1);
+ initBeaverPos(5, 9, 0);
+ endSceneInit();
+ break;
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+ _sceneClickedHotspot = -1;
+ if (_gnapActionStatus < 0)
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene27_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSJanitor:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemPicture) {
+ _gnapIdleFacing = 5;
+ if (gnapWalkTo(_hotspotsWalkPos[kHSJanitor].x, _hotspotsWalkPos[kHSJanitor].y, 0, 0x107BC, 1))
+ _gnapActionStatus = kASShowPictureToJanitor;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSJanitor].x, _hotspotsWalkPos[kHSJanitor].y, 7, 3);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(6, 3);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 5;
+ gnapWalkTo(_hotspotsWalkPos[kHSJanitor].x, _hotspotsWalkPos[kHSJanitor].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = kASTalkJanitor;
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSBucket:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowItem(_grabCursorSpriteIndex, 3, 3);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(3, 3);
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 5;
+ gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[kHSBucket].x, _hotspotsWalkPos[kHSBucket].y) | 0x10000, 1);
+ _gnapActionStatus = kASGrabBucket;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitCircus:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 26;
+ gnapWalkTo(-1, _hotspotsWalkPos[kHSExitCircus].y, 0, 0x107AE, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitCircus].x + 1, _hotspotsWalkPos[kHSExitCircus].y, -1, 0x107C7, 1);
+ }
+ break;
+
+ case kHSExitArcade:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 29;
+ gnapWalkTo(-1, _hotspotsWalkPos[kHSExitArcade].y, 0, 0x107AF, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitArcade].x, _hotspotsWalkPos[kHSExitArcade].y + 1, -1, 0x107CF, 1);
+ }
+ break;
+
+ case kHSExitBeerStand:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _newSceneNum = 31;
+ gnapWalkTo(-1, _hotspotsWalkPos[kHSExitBeerStand].y, 0, 0x107AB, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitBeerStand].x, _hotspotsWalkPos[kHSExitBeerStand].y + 1, -1, 0x107CD, 1);
+ }
+ break;
+
+ case kHSExitClown:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(0)) {
+ _isLeavingScene = true;
+ _newSceneNum = 28;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitClown].x, _hotspotsWalkPos[kHSExitClown].y, 0, 0x107AD, 1);
+ _gnapActionStatus = kASLeaveScene;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitClown].x + 1, _hotspotsWalkPos[kHSExitClown].y, -1, 0x107C4, 1);
+ } else {
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitClown].x, 7, 0, 0x107BC, 1);
+ _hotspots[kHSWalkArea1].flags &= SF_WALKABLE;
+ _gnapActionStatus = kASTryEnterClownTent;
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene27_updateAnimations();
+
+ if (!isSoundPlaying(0x1093B))
+ playSound(0x1093B, 1);
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (_debugLevel == 4)
+ updateIdleTimer();
+ if (!_timers[5]) {
+ _timers[5] = getRandom(20) + 60;
+ if (_gnapActionStatus < 0) {
+ if (getRandom(3) != 0)
+ _s27_nextJanitorSequenceId = 0xCB;
+ else
+ _s27_nextJanitorSequenceId = 0xCF;
+ }
+ }
+ if (!_timers[7]) {
+ _timers[7] = getRandom(100) + 300;
+ if (_gnapActionStatus < 0)
+ _gameSys->insertSequence(0xD4, 120, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ playSoundB();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene27_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene27_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case kASTalkJanitor:
+ switch (getRandom(3)) {
+ case 0:
+ _s27_nextJanitorSequenceId = 0xCC;
+ break;
+ case 1:
+ _s27_nextJanitorSequenceId = 0xCD;
+ break;
+ case 2:
+ _s27_nextJanitorSequenceId = 0xCE;
+ break;
+ }
+ break;
+ case kASGrabBucket:
+ playGnapPullOutDevice(0, 0);
+ playGnapUseDevice(0, 0);
+ _hotspots[kHSBucket].flags = SF_DISABLED;
+ invAdd(kItemEmptyBucket);
+ setFlag(13);
+ _gameSys->setAnimation(0xD2, 39, 0);
+ _gameSys->insertSequence(0xD2, 39, 211, 39, kSeqSyncWait, 0, 0, 0);
+ _gnapActionStatus = kASGrabBucketDone;
+ break;
+ case kASGrabBucketDone:
+ setGrabCursorSprite(kItemEmptyBucket);
+ _gnapActionStatus = -1;
+ break;
+ case kASShowPictureToJanitor:
+ _s27_nextJanitorSequenceId = 0xD0;
+ break;
+ case kASTryEnterClownTent:
+ _s27_nextJanitorSequenceId = 0xD1;
+ _gameSys->insertSequence(0xD1, 39, _s27_currJanitorSequenceId, 39, 32, 0, 0, 0);
+ _gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 3);
+ _gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 0);
+ _s27_currJanitorSequenceId = _s27_nextJanitorSequenceId;
+ _s27_nextJanitorSequenceId = -1;
+ _gnapActionStatus = kASTryEnterClownTentDone;
+ break;
+ case kASTryEnterClownTentDone:
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[7].x, 9, -1, 0x107BC, 1);
+ _hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE;
+ _gnapActionStatus = -1;
+ break;
+ case kASEnterClownTent:
+ gnapWalkTo(_gnapX, _gnapY, 0, 0x107B2, 1);
+ _gnapActionStatus = kASLeaveScene;
+ break;
+ case kASLeaveScene:
+ _sceneDone = true;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ switch (_s27_nextJanitorSequenceId) {
+ case -1:
+ _s27_nextJanitorSequenceId = 0xCB;
+ _gameSys->insertSequence(0xCB, 39, _s27_currJanitorSequenceId, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 3);
+ _s27_currJanitorSequenceId = _s27_nextJanitorSequenceId;
+ _s27_nextJanitorSequenceId = -1;
+ break;
+ case 0xCC:
+ case 0xCD:
+ case 0xCE:
+ _gnapActionStatus = -1;
+ _gameSys->insertSequence(_s27_nextJanitorSequenceId, 39, _s27_currJanitorSequenceId, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 3);
+ _gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 0);
+ _s27_currJanitorSequenceId = _s27_nextJanitorSequenceId;
+ _s27_nextJanitorSequenceId = -1;
+ break;
+ case 0xD0:
+ // Show picture to janitor
+ playGnapPullOutDevice(0, 0);
+ playGnapUseDevice(0, 0);
+ _gameSys->insertSequence(_s27_nextJanitorSequenceId, 39, _s27_currJanitorSequenceId, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 0);
+ _gnapActionStatus = kASEnterClownTent;
+ _s27_currJanitorSequenceId = _s27_nextJanitorSequenceId;
+ _s27_nextJanitorSequenceId = -1;
+ setFlag(0);
+ setGrabCursorSprite(-1);
+ invRemove(kItemPicture);
+ _newSceneNum = 28;
+ break;
+ default:
+ _gameSys->insertSequence(_s27_nextJanitorSequenceId, 39, _s27_currJanitorSequenceId, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 3);
+ _s27_currJanitorSequenceId = _s27_nextJanitorSequenceId;
+ _s27_nextJanitorSequenceId = -1;
+ break;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene28.cpp b/engines/gnap/scenes/scene28.cpp
new file mode 100644
index 0000000000..23c3e52974
--- /dev/null
+++ b/engines/gnap/scenes/scene28.cpp
@@ -0,0 +1,435 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSHorn = 1,
+ kHSClown = 2,
+ kHSExitOutsideClown = 3,
+ kHSUnknown = 4,
+ kHSDevice = 5,
+ kHSWalkArea1 = 6,
+ kHSWalkArea2 = 7
+};
+
+int GnapEngine::scene28_init() {
+ return 0x125;
+}
+
+void GnapEngine::scene28_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSHorn, 148, 352, 215, 383, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 7);
+ setHotspot(kHSClown, 130, 250, 285, 413, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 5);
+ setHotspot(kHSExitOutsideClown, 660, 190, 799, 400, SF_EXIT_R_CURSOR, 9, 6);
+ setHotspot(kHSUnknown, 582, 421, 643, 478, SF_WALKABLE | SF_DISABLED, 9, 7);
+ setHotspot(kHSWalkArea1, 0, 0, 799, 523);
+ setHotspot(kHSWalkArea2, 0, 0, 0, 0, 7, SF_DISABLED);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (invHas(kItemHorn))
+ _hotspots[kHSHorn].flags = SF_DISABLED;
+ if (isFlag(22))
+ _hotspots[kHSUnknown].flags = SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR;
+ _hotspotsCount = 8;
+}
+
+void GnapEngine::scene28_run() {
+
+ playSound(0x1093C, 1);
+ _s28_dword_47EA60 = -1;
+ queueInsertDeviceIcon();
+ _gameSys->insertSequence(0x124, 255, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(22))
+ _gameSys->insertSequence(0x112, 99, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(1)) {
+ if (isFlag(21)) {
+ _gameSys->setAnimation(0x11C, 39, 3);
+ _gameSys->insertSequence(0x11C, 39, 0, 0, kSeqNone, 0, 0, 0);
+ if (!invHas(kItemHorn))
+ _gameSys->insertSequence(0x118, 59, 0, 0, kSeqNone, 0, 0, 0);
+ _s28_dword_47EA5C = 0x11C;
+ } else {
+ _s28_dword_47EA5C = 0x11B;
+ _gameSys->setAnimation(0x11B, 39, 3);
+ _gameSys->insertSequence(_s28_dword_47EA5C, 39, 0, 0, kSeqNone, 0, 0, 0);
+ _timers[4] = getRandom(20) + 80;
+ }
+ initGnapPos(8, 8, 3);
+ initBeaverPos(9, 8, 4);
+ endSceneInit();
+ } else {
+ _gameSys->insertSequence(0x11B, 39, 0, 0, kSeqNone, 0, 0, 0);
+ initGnapPos(8, 8, 3);
+ initBeaverPos(9, 8, 4);
+ endSceneInit();
+ playSequences(0xF7, 0x121, 0x122, 0x123);
+ _s28_dword_47EA5C = 0x115;
+ setFlag(1);
+ _gameSys->setAnimation(0x115, 39, 3);
+ _gameSys->insertSequence(_s28_dword_47EA5C, 39, 283, 39, kSeqSyncWait, 0, 0, 0);
+ _s28_dword_47EA60 = -1;
+ _timers[4] = getRandom(20) + 80;
+ _gnapActionStatus = 9;
+ while (_gameSys->getAnimationStatus(3) != 2) {
+ gameUpdateTick();
+ updateMouseCursor();
+ }
+ _gnapActionStatus = -1;
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene28_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSHorn:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(2, 8, 3, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(2, 4);
+ break;
+ case GRAB_CURSOR:
+ if (isFlag(21)) {
+ if (!invHas(kItemHorn)) {
+ gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[kHSHorn].x, _hotspotsWalkPos[kHSHorn].y) | 0x10000, 1);
+ _gnapActionStatus = 4;
+ }
+ } else {
+ _gnapIdleFacing = 5;
+ gnapWalkTo(2, 8, 0, 0x107BB, 1);
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[kHSHorn].x, _hotspotsWalkPos[kHSHorn].y, 0, 0x107BB, 1);
+ _hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE;
+ _gnapActionStatus = 2;
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSClown:
+ if (_gnapActionStatus < 0) {
+ if (isFlag(21)) {
+ if (_verbCursor == LOOK_CURSOR)
+ playGnapScratchingHead(5, 2);
+ else
+ playGnapImpossible(0, 0);
+ } else if (_grabCursorSpriteIndex == kItemBucketWithBeer) {
+ _gnapIdleFacing = 5;
+ gnapWalkTo(_hotspotsWalkPos[kHSClown].x, _hotspotsWalkPos[kHSClown].y, 0, 0x107BC, 1);
+ playGnapPullOutDevice(0, 0);
+ playGnapUseDevice(0, 0);
+ _gnapActionStatus = 0;
+ } else if (_grabCursorSpriteIndex == kItemBucketWithPill) {
+ _gnapIdleFacing = 5;
+ gnapWalkTo(_hotspotsWalkPos[kHSClown].x, _hotspotsWalkPos[kHSClown].y, 0, 0x107BC, 1);
+ playGnapPullOutDevice(0, 0);
+ playGnapUseDevice(0, 0);
+ _gnapActionStatus = 1;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSClown].x, _hotspotsWalkPos[kHSClown].y, 2, 4);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(5, 2);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 5;
+ gnapWalkTo(5, 8, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = 8;
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitOutsideClown:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ _newSceneNum = 27;
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideClown].x, _hotspotsWalkPos[kHSExitOutsideClown].y, 0, 0x107BF, 1);
+ _gnapActionStatus = 10;
+ _hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideClown].x - 1, _hotspotsWalkPos[kHSExitOutsideClown].y, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSUnknown:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowItem(_grabCursorSpriteIndex, 8, 6);
+ } else if (isFlag(21)) {
+ playGnapImpossible(8, 6);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(8, 6);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[kHSUnknown].x, _hotspotsWalkPos[kHSUnknown].y) | 0x10000, 1);
+ _gnapActionStatus = 3;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene28_updateAnimations();
+
+ if (!isSoundPlaying(0x1093C))
+ playSound(0x1093C, 1);
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(20) + 80;
+ if (_gnapActionStatus < 0 && !isFlag(21))
+ _s28_dword_47EA60 = 0x114;
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene28_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene28_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case 0:
+ setFlag(22);
+ _s28_dword_47EA60 = 275;
+ invRemove(kItemBucketWithBeer);
+ scene28_updateHotspots();
+ break;
+ case 1:
+ _s28_dword_47EA60 = 0x116;
+ invRemove(kItemBucketWithPill);
+ setFlag(22);
+ setFlag(21);
+ scene28_updateHotspots();
+ break;
+ case 2:
+ _s28_dword_47EA60 = 0x119;
+ break;
+ case 3:
+ playGnapPullOutDevice(0, 0);
+ playGnapUseDevice(0, 0);
+ _gameSys->setAnimation(0x111, 99, 0);
+ _gameSys->insertSequence(0x111, 99, 274, 99, kSeqSyncWait, 0, 0, 0);
+ _gnapActionStatus = 6;
+ break;
+ case 4:
+ playGnapPullOutDevice(0, 0);
+ playGnapUseDevice(0, 0);
+ _gameSys->setAnimation(0x117, 59, 0);
+ _gameSys->insertSequence(0x117, 59, 280, 59, kSeqSyncWait, 0, 0, 0);
+ _gnapActionStatus = 5;
+ break;
+ case 5:
+ hideCursor();
+ setGrabCursorSprite(-1);
+ addFullScreenSprite(0xF6, 255);
+ _gameSys->setAnimation(0x120, 256, 0);
+ _gameSys->insertSequence(0x120, 256, 0, 0, kSeqNone, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(0) != 2)
+ gameUpdateTick();
+ removeFullScreenSprite();
+ showCursor();
+ setGrabCursorSprite(kItemHorn);
+ invAdd(kItemHorn);
+ scene28_updateHotspots();
+ _gnapActionStatus = -1;
+ break;
+ case 6:
+ setGrabCursorSprite(kItemEmptyBucket);
+ clearFlag(22);;
+ scene28_updateHotspots();
+ invAdd(kItemEmptyBucket);
+ _gnapActionStatus = -1;
+ break;
+ case 7:
+ _gameSys->insertSequence(0x107B5, _gnapId, 281, 39, kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gnapSequenceId = 0x7B5;
+ _gnapSequenceDatNum = 1;
+ _gameSys->insertSequence(0x11B, 39, 0, 0, kSeqNone, 0, 0, 0);
+ _s28_dword_47EA5C = 0x11B;
+ _s28_dword_47EA60 = -1;
+ _gnapActionStatus = -1;
+ gnapWalkTo(2, 8, -1, 0x107BB, 1);
+ break;
+ case 8:
+ _s28_dword_474938 = (_s28_dword_474938 + 1) % 2;
+ if (_s28_dword_474938 == 0)
+ _s28_dword_47EA60 = 0x11D;
+ else if (_s28_dword_474938 == 1)
+ _s28_dword_47EA60 = 0x11E;
+ else if (_s28_dword_474938 == 2)
+ _s28_dword_47EA60 = 0x11F; // NOTE CHECKME Never set, bug in the original?
+ break;
+ case 9:
+ _gnapActionStatus = -1;
+ break;
+ case 10:
+ _sceneDone = true;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ switch (_s28_dword_47EA60) {
+ case 0x113:
+ setGrabCursorSprite(-1);
+ _gameSys->setAnimation(_s28_dword_47EA60, 39, 0);
+ _gameSys->insertSequence(0x112, 99, 0, 0, kSeqNone, getSequenceTotalDuration(_s28_dword_47EA60), 0, 0);
+ _gameSys->insertSequence(_s28_dword_47EA60, 39, _s28_dword_47EA5C, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x11B, 39, _s28_dword_47EA60, 39, kSeqSyncWait, 0, 0, 0);
+ _s28_dword_47EA5C = 0x11B;
+ _s28_dword_47EA60 = -1;
+ _gnapActionStatus = 9;
+ break;
+ case 0x116:
+ setGrabCursorSprite(-1);
+ _gameSys->setAnimation(_s28_dword_47EA60, 39, 0);
+ _gameSys->insertSequence(0x112, 99, 0, 0, kSeqNone, getSequenceTotalDuration(_s28_dword_47EA60), 0, 0);
+ _gameSys->insertSequence(_s28_dword_47EA60, 39, _s28_dword_47EA5C, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x11C, 39, _s28_dword_47EA60, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0x118, 59, 0, 0, kSeqNone, getSequenceTotalDuration(_s28_dword_47EA60), 0, 0);
+ _s28_dword_47EA5C = _s28_dword_47EA60;
+ _s28_dword_47EA60 = -1;
+ _gnapActionStatus = 9;
+ break;
+ case 0x11D:
+ case 0x11E:
+ case 0x11F:
+ _gnapActionStatus = -1;
+ break;
+ case 0x119:
+ _gameSys->insertSequence(_s28_dword_47EA60, 39, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s28_dword_47EA60, 39, 0);
+ _gameSys->removeSequence(_s28_dword_47EA5C, 39, 1);
+ _gnapActionStatus = 7;
+ _gnapSequenceId = _s28_dword_47EA60;
+ _gnapSequenceDatNum = 0;
+ _s28_dword_47EA60 = -1;
+ break;
+ }
+ if (_s28_dword_47EA60 != -1) {
+ _gameSys->insertSequence(_s28_dword_47EA60, 39, _s28_dword_47EA5C, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s28_dword_47EA60, 39, 3);
+ _s28_dword_47EA5C = _s28_dword_47EA60;
+ _s28_dword_47EA60 = -1;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene29.cpp b/engines/gnap/scenes/scene29.cpp
new file mode 100644
index 0000000000..3a78107db5
--- /dev/null
+++ b/engines/gnap/scenes/scene29.cpp
@@ -0,0 +1,352 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSMonkey = 1,
+ kHSDevice = 2,
+ kHSExitCircus = 3,
+ kHSExitOutsideClown = 4,
+ kHSAracde = 5,
+ kHSWalkArea1 = 6
+};
+
+int GnapEngine::scene29_init() {
+ return 0xF6;
+}
+
+void GnapEngine::scene29_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSMonkey, 410, 374, 518, 516, SF_WALKABLE | SF_DISABLED, 3, 7);
+ setHotspot(kHSExitCircus, 150, 585, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9);
+ setHotspot(kHSExitOutsideClown, 785, 0, 800, 600, SF_EXIT_R_CURSOR | SF_WALKABLE, 11, 9);
+ setHotspot(kHSAracde, 88, 293, 155, 384, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 8);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 478);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (invHas(kItemHorn))
+ _hotspots[kHSMonkey].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR;
+ _hotspotsCount = 7;
+}
+
+void GnapEngine::scene29_run() {
+
+ playSound(0x1093B, 1);
+ startSoundTimerB(6);
+ queueInsertDeviceIcon();
+
+ if (invHas(kItemHorn)) {
+ _s29_dword_47EA74 = 0xE8;
+ _s29_dword_47EA78 = -1;
+ _gameSys->setAnimation(0xE8, 159, 4);
+ _gameSys->insertSequence(_s29_dword_47EA74, 159, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0xED, 39, 0, 0, kSeqNone, 0, 0, 0);
+ _s29_dword_47EA7C = 0xED;
+ _s29_dword_47EA80 = -1;
+ _gameSys->setAnimation(0xED, 39, 3);
+ _timers[4] = getRandom(20) + 60;
+ } else {
+ _gameSys->insertSequence(0xF4, 19, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->setAnimation(0, 0, 4);
+ _gameSys->insertSequence(0xED, 39, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->setAnimation(0, 0, 3);
+ }
+
+ _gameSys->insertSequence(0xF3, 39, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0xF5, 38, 0, 0, kSeqLoop, 0, 0, 0);
+
+ if (_prevSceneNum == 27) {
+ initGnapPos(12, 7, 1);
+ initBeaverPos(12, 8, 0);
+ endSceneInit();
+ gnapWalkTo(8, 7, -1, 0x107B9, 1);
+ platypusWalkTo(8, 8, -1, 0x107C2, 1);
+ } else {
+ initGnapPos(-1, 7, 1);
+ initBeaverPos(-2, 7, 0);
+ endSceneInit();
+ gnapWalkTo(2, 7, -1, 0x107B9, 1);
+ platypusWalkTo(1, 7, -1, 0x107C2, 1);
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene29_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSMonkey:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemBanana) {
+ _gnapIdleFacing = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSMonkey].x, _hotspotsWalkPos[kHSMonkey].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = 0;
+ _newSceneNum = 51;
+ _isLeavingScene = 1;
+ setGrabCursorSprite(-1);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSMonkey].x, _hotspotsWalkPos[kHSMonkey].y, 5, 6);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(5, 6);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_hotspotsWalkPos[kHSMonkey].x, _hotspotsWalkPos[kHSMonkey].y);
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitCircus:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _newSceneNum = 26;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitCircus].x, _hotspotsWalkPos[kHSExitCircus].y, 0, 0x107AE, 1);
+ _gnapActionStatus = 2;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitCircus].x + 1, _hotspotsWalkPos[kHSExitCircus].y, -1, -1, 1);
+ }
+ break;
+
+ case kHSExitOutsideClown:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _newSceneNum = 27;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideClown].x, _hotspotsWalkPos[kHSExitOutsideClown].y, 0, 0x107AB, 1);
+ _gnapActionStatus = 2;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideClown].x, _hotspotsWalkPos[kHSExitOutsideClown].y - 1, -1, 0x107CD, 1);
+ }
+ break;
+
+ case kHSAracde:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemDiceQuarterHole) {
+ setGrabCursorSprite(-1);
+ _isLeavingScene = 1;
+ _newSceneNum = 52;
+ gnapWalkTo(_hotspotsWalkPos[kHSAracde].x, _hotspotsWalkPos[kHSAracde].y, 0, -1, 1);
+ playGnapIdle(_hotspotsWalkPos[kHSAracde].x, _hotspotsWalkPos[kHSAracde].y);
+ _gnapActionStatus = 2;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSAracde].x, _hotspotsWalkPos[kHSAracde].y, 2, 3);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan2(0, 0);
+ break;
+ case GRAB_CURSOR:
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+ }
+
+ scene29_updateAnimations();
+
+ if (!isSoundPlaying(0x1093B))
+ playSound(0x1093B, 1);
+
+ if (!_isLeavingScene) {
+ if (_gnapActionStatus < 0) {
+ updateGnapIdleSequence();
+ updateBeaverIdleSequence();
+ }
+ if (!_timers[4]) {
+ if (invHas(kItemHorn)) {
+ _timers[4] = getRandom(20) + 60;
+ if (_gnapActionStatus < 0) {
+ switch (getRandom(5)) {
+ case 0:
+ _s29_dword_47EA80 = 0xED;
+ break;
+ case 1:
+ _s29_dword_47EA80 = 0xEE;
+ break;
+ case 2:
+ _s29_dword_47EA80 = 0xEF;
+ break;
+ case 3:
+ _s29_dword_47EA80 = 0xF0;
+ break;
+ case 4:
+ _s29_dword_47EA80 = 0xF1;
+ break;
+ }
+ }
+ }
+ }
+ playSoundB();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene29_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene29_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case 0:
+ _s29_dword_47EA78 = 0xE5;
+ break;
+ case 1:
+ case 2:
+ _sceneDone = true;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2 && _s29_dword_47EA80 != -1) {
+ _gameSys->insertSequence(_s29_dword_47EA80, 39, _s29_dword_47EA7C, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s29_dword_47EA80, 39, 3);
+ _s29_dword_47EA7C = _s29_dword_47EA80;
+ _s29_dword_47EA80 = -1;
+ }
+
+ if (_gameSys->getAnimationStatus(4) == 2) {
+ if (_s29_dword_47EA78 == 0xE5) {
+ _gameSys->insertSequence(0xF2, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0xF2;
+ _gameSys->setAnimation(0xE6, 159, 0);
+ _gameSys->setAnimation(0, 159, 4);
+ _gameSys->insertSequence(_s29_dword_47EA78, 159, _s29_dword_47EA74, 159, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xE6, 159, _s29_dword_47EA78, 159, kSeqSyncWait, 0, 0, 0);
+ _gnapActionStatus = 1;
+ _s29_dword_47EA74 = 0xE6;
+ _s29_dword_47EA78 = -1;
+ _timers[5] = 30;
+ while (_timers[5])
+ gameUpdateTick();
+ platypusWalkTo(0, 8, 1, 0x107CF, 1);
+ while (_gameSys->getAnimationStatus(1) != 2)
+ gameUpdateTick();
+ } else if (_s29_dword_47EA78 == -1) {
+ switch (getRandom(6)) {
+ case 0:
+ _s29_dword_47EA78 = 0xE8;
+ break;
+ case 1:
+ _s29_dword_47EA78 = 0xE9;
+ break;
+ case 2:
+ _s29_dword_47EA78 = 0xEA;
+ break;
+ case 3:
+ _s29_dword_47EA78 = 0xEB;
+ break;
+ case 4:
+ _s29_dword_47EA78 = 0xEC;
+ break;
+ case 5:
+ _s29_dword_47EA78 = 0xE7;
+ break;
+ }
+ _gameSys->insertSequence(_s29_dword_47EA78, 159, _s29_dword_47EA74, 159, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s29_dword_47EA78, 159, 4);
+ _s29_dword_47EA74 = _s29_dword_47EA78;
+ _s29_dword_47EA78 = -1;
+ } else {
+ _gameSys->insertSequence(_s29_dword_47EA78, 159, _s29_dword_47EA74, 159, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s29_dword_47EA78, 159, 4);
+ _s29_dword_47EA74 = _s29_dword_47EA78;
+ _s29_dword_47EA78 = -1;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene30.cpp b/engines/gnap/scenes/scene30.cpp
new file mode 100644
index 0000000000..341caee618
--- /dev/null
+++ b/engines/gnap/scenes/scene30.cpp
@@ -0,0 +1,281 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSPillMachine = 1,
+ kHSDevice = 2,
+ kHSExitCircus = 3,
+ kHSWalkArea1 = 4
+};
+
+int GnapEngine::scene30_init() {
+ return isFlag(23) ? 0x10B : 0x10A;
+}
+
+void GnapEngine::scene30_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSPillMachine, 598, 342, 658, 426, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 7);
+ setHotspot(kHSExitCircus, 100, 590, 700, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9);
+ setHotspot(kHSExitCircus, 0, 0, 800, 514);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 5;
+}
+
+void GnapEngine::scene30_run() {
+ bool hasTakenPill = false;
+
+ playSound(0x1093B, 1);
+ startSoundTimerB(6);
+
+ queueInsertDeviceIcon();
+
+ if (isFlag(23))
+ _gameSys->insertSequence(0x106, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (!isFlag(13))
+ _gameSys->insertSequence(0x107, 1, 0, 0, kSeqNone, 0, 0, 0);
+ _timers[5] = getRandom(50) + 180;
+
+ _gameSys->insertSequence(0x101, 40, 0, 0, kSeqNone, 0, 0, 0);
+ _timers[4] = getRandom(100) + 300;
+
+ _s30_dword_47EA88 = 0x101;
+ initGnapPos(7, 12, 1);
+ initBeaverPos(6, 12, 0);
+ endSceneInit();
+ gnapWalkTo(7, 8, -1, 0x107B9, 1);
+ platypusWalkTo(6, 8, -1, 0x107C2, 1);
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene30_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSPillMachine:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemDiceQuarterHole && !isFlag(23)) {
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[kHSPillMachine].x, _hotspotsWalkPos[kHSPillMachine].y, 0, 0x107BC, 1);
+ _hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE;
+ _gnapActionStatus = 1;
+ hasTakenPill = true;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSPillMachine].x, _hotspotsWalkPos[kHSPillMachine].y, 8, 5);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ gnapWalkTo(9, 8, 0, 0x107BC, 1);
+ _gnapActionStatus = 3;
+ break;
+ case GRAB_CURSOR:
+ playGnapScratchingHead(8, 5);
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(8, 5);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitCircus:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = true;
+ if (hasTakenPill)
+ _newSceneNum = 47;
+ else
+ _newSceneNum = 26;
+ gnapWalkTo(-1, _hotspotsWalkPos[kHSExitCircus].y, 0, 0x107AE, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitCircus].x + 1, _hotspotsWalkPos[kHSExitCircus].y, -1, 0x107C2, 1);
+ }
+ break;
+
+ case kHSWalkArea1:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene30_updateAnimations();
+
+ if (!isSoundPlaying(0x1093B))
+ playSound(0x1093B, 1);
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(100) + 300;
+ if (_gnapActionStatus < 0) {
+ if (getRandom(5) == 1) {
+ _gameSys->insertSequence(0xFF, 40, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x100, 40, _s30_dword_47EA88, 40, kSeqSyncWait, 0, 0, 0);
+ _s30_dword_47EA88 = 0x100;
+ } else {
+ _gameSys->insertSequence(0xFE, 40, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ }
+ }
+ if (!_timers[5]) {
+ _timers[5] = getRandom(50) + 180;
+ if (_gnapActionStatus < 0) {
+ if (!isFlag(23) || hasTakenPill)
+ _s30_dword_47EA8C = 0x109;
+ else
+ _s30_dword_47EA8C = 0x108;
+ _gameSys->insertSequence(_s30_dword_47EA8C, 20, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ }
+ playSoundB();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene30_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene30_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case 0:
+ _sceneDone = true;
+ break;
+ case 1:
+ setGrabCursorSprite(-1);
+ _gameSys->setAnimation(0x105, _gnapId, 0);
+ _gameSys->insertSequence(0x105, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x105;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = 2;
+ break;
+ case 2:
+ hideCursor();
+ setGrabCursorSprite(-1);
+ addFullScreenSprite(0x3F, 255);
+ _gameSys->removeSequence(0x105, _gnapId, 1);
+ _gameSys->setAnimation(0x102, 256, 0);
+ _gameSys->insertSequence(0x102, 256, 0, 0, kSeqNone, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(0) != 2) {
+ // checkGameAppStatus();
+ gameUpdateTick();
+ }
+ _gameSys->setAnimation(0x103, _gnapId, 0);
+ _gameSys->insertSequence(0x103, _gnapId, 0, 0, kSeqNone, 0, 0, 0);
+ removeFullScreenSprite();
+ showCursor();
+ _gnapActionStatus = 4;
+ invAdd(kItemPill);
+ setFlag(23);
+ break;
+ case 3:
+ if (isFlag(23))
+ showFullScreenSprite(0xE3);
+ else
+ showFullScreenSprite(0xE2);
+ _gnapActionStatus = -1;
+ break;
+ case 4:
+ _gameSys->setAnimation(0x104, _gnapId, 0);
+ _gameSys->insertSequence(0x104, _gnapId, makeRid(_gnapSequenceDatNum, 0x103), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x104;
+ _gnapSequenceDatNum = 0;
+ _gnapActionStatus = 5;
+ setGrabCursorSprite(kItemDiceQuarterHole);
+ break;
+ case 5:
+ _gameSys->insertSequence(0x106, 1, 0, 0, kSeqNone, 0, 0, 0);
+ gnapWalkTo(_hotspotsWalkPos[kHSPillMachine].x, _hotspotsWalkPos[kHSPillMachine].y + 1, -1, 0x107BC, 1);
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene31.cpp b/engines/gnap/scenes/scene31.cpp
new file mode 100644
index 0000000000..864dbf90bc
--- /dev/null
+++ b/engines/gnap/scenes/scene31.cpp
@@ -0,0 +1,398 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSMeasuringClown = 1,
+ kHSBeerBarrel = 2,
+ kHSDevice = 3,
+ kHSExitCircus = 4,
+ kHSExitOutsideClown = 5,
+ kHSWalkArea1 = 6
+};
+
+int GnapEngine::scene31_init() {
+ return 0x105;
+}
+
+void GnapEngine::scene31_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSMeasuringClown, 34, 150, 256, 436, SF_WALKABLE | SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 0, 6);
+ setHotspot(kHSBeerBarrel, 452, 182, 560, 306, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 7);
+ setHotspot(kHSExitCircus, 150, 585, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9);
+ setHotspot(kHSExitOutsideClown, 0, 0, 15, 600, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 8);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 480);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 7;
+}
+
+void GnapEngine::scene31_run() {
+
+ playSound(0x1093B, 1);
+ startSoundTimerB(6);
+
+ queueInsertDeviceIcon();
+
+ _s31_beerGuyDistracted = false;
+ _gameSys->insertSequence(0xFB, 39, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s31_dword_47EAA8 = 0xFB;
+ _s31_dword_47EAAC = -1;
+
+ _gameSys->setAnimation(0xFB, 39, 3);
+
+ _timers[4] = getRandom(20) + 60;
+ _timers[5] = getRandom(50) + 180;
+
+ if (_prevSceneNum == 27) {
+ initGnapPos(-1, 8, 3);
+ initBeaverPos(-1, 9, 4);
+ endSceneInit();
+ gnapWalkTo(3, 8, -1, 0x107BA, 1);
+ platypusWalkTo(3, 9, -1, 0x107D2, 1);
+ } else {
+ initGnapPos(7, 12, 1);
+ initBeaverPos(6, 12, 0);
+ endSceneInit();
+ gnapWalkTo(7, 8, -1, 0x107BA, 1);
+ platypusWalkTo(6, 8, -1, 0x107D2, 1);
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0 || _gnapActionStatus == 4) {
+ runMenu();
+ scene31_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemJoint) {
+ gnapUseJointOnPlatypus();
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSMeasuringClown:
+ if (_gnapActionStatus < 0 || _gnapActionStatus == 4) {
+ if (_gnapActionStatus == 4) {
+ if (_verbCursor == LOOK_CURSOR)
+ playGnapScratchingHead(2, 2);
+ else
+ playGnapImpossible(0, 0);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSMeasuringClown].x, _hotspotsWalkPos[kHSMeasuringClown].y + 1, 2, 2);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(2, 2);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(_hotspotsWalkPos[kHSMeasuringClown].x, _hotspotsWalkPos[kHSMeasuringClown].y + 1, -1, -1, 1);
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ gnapWalkTo(_hotspotsWalkPos[kHSMeasuringClown].x, _hotspotsWalkPos[kHSMeasuringClown].y, 0, 0x107B9, 1);
+ _hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE;
+ _gnapActionStatus = 5;
+ _timers[4] = 300;
+ break;
+ case TALK_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case PLAT_CURSOR:
+ if (!invHas(kItemBucketWithBeer)) {
+ gnapUseDeviceOnBeaver();
+ platypusWalkTo(_hotspotsWalkPos[kHSMeasuringClown].x, _hotspotsWalkPos[kHSMeasuringClown].y + 1, 1, 0x107C2, 1);
+ _hotspots[kHSWalkArea1].flags |= SF_WALKABLE;
+ platypusWalkTo(_hotspotsWalkPos[kHSMeasuringClown].x, _hotspotsWalkPos[kHSMeasuringClown].y, 1, 0x107C2, 1);
+ _hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE;
+ _beaverActionStatus = 4;
+ _gnapActionStatus = 4;
+ _timers[4] = 300;
+ } else
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSBeerBarrel:
+ if (_gnapActionStatus < 0 || _gnapActionStatus == 4) {
+ if (_grabCursorSpriteIndex == kItemEmptyBucket && _s31_beerGuyDistracted) {
+ setGrabCursorSprite(-1);
+ gnapWalkTo(_gnapX, _gnapY, -1, getGnapSequenceId(gskIdle, _hotspotsWalkPos[kHSBeerBarrel].x, _hotspotsWalkPos[kHSBeerBarrel].y) | 0x10000, 1);
+ _s31_dword_474940 += 5;
+ _gameSys->insertSequence(0xF8, 59, 0, 0, kSeqNone, 0, 0, 0);
+ playGnapPullOutDevice(6, 8);
+ playGnapUseDevice(0, 0);
+ gnapWalkTo(_hotspotsWalkPos[kHSBeerBarrel].x, _hotspotsWalkPos[kHSBeerBarrel].y, 0, 0x107BC, 1);
+ _gnapActionStatus = 2;
+ _timers[4] = 300;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSBeerBarrel].x, _hotspotsWalkPos[kHSBeerBarrel].y, 6, 2);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(6, 2);
+ break;
+ case GRAB_CURSOR:
+ if (_s31_beerGuyDistracted) {
+ playGnapScratchingHead(6, 2);
+ } else {
+ gnapWalkTo(_hotspotsWalkPos[kHSBeerBarrel].x, _hotspotsWalkPos[kHSBeerBarrel].y, 0, 0x107BC, 1);
+ _gnapActionStatus = 1;
+ _gnapIdleFacing = 5;
+ }
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitCircus:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _newSceneNum = 26;
+ gnapWalkTo(-1, _hotspotsWalkPos[kHSExitCircus].y, 0, 0x107AE, 1);
+ _gnapActionStatus = 6;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitCircus].x + 1, _hotspotsWalkPos[kHSExitCircus].y, -1, -1, 1);
+ }
+ break;
+
+ case kHSExitOutsideClown:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _newSceneNum = 27;
+ gnapWalkTo(-1, _hotspotsWalkPos[kHSExitOutsideClown].y, 0, 0x107AF, 1);
+ _gnapActionStatus = 6;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideClown].x, _hotspotsWalkPos[kHSExitOutsideClown].y + 1, -1, 0x107CF, 1);
+ }
+ break;
+
+ case kHSWalkArea1:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+ }
+
+ scene31_updateAnimations();
+
+ if (!isSoundPlaying(0x1093B))
+ playSound(0x1093B, 1);
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0)
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(20) + 60;
+ if (_gnapActionStatus < 0 && _s31_dword_47EAAC == -1) {
+ switch (getRandom(6)){
+ case 0:
+ _s31_dword_47EAAC = 0xFF;
+ break;
+ case 1:
+ _s31_dword_47EAAC = 0x100;
+ break;
+ case 2:
+ _s31_dword_47EAAC = 0x101;
+ break;
+ default:
+ _s31_dword_47EAAC = 0xFB;
+ break;
+ }
+ }
+ }
+ if (!_timers[5]) {
+ _timers[5] = getRandom(50) + 180;
+ if (_gnapActionStatus < 0) {
+ if (getRandom(2) != 0)
+ _s31_dword_47EAB4 = 0x104;
+ else
+ _s31_dword_47EAB4 = 0x103;
+ _gameSys->insertSequence(_s31_dword_47EAB4, 20, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ }
+ playSoundB();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene31_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene31_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case 1:
+ _s31_dword_47EAAC = 0xFE;
+ break;
+ case 2:
+ _gameSys->setAnimation(0x102, 59, 0);
+ _gameSys->insertSequence(0x102, 59, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapX = 5;
+ _gnapY = 7;
+ _gnapSequenceDatNum = 0;
+ _gnapSequenceId = 0x102;
+ _gnapId = 59;
+ _gnapActionStatus = 3;
+ break;
+ case 3:
+ _gnapIdleFacing = 3;
+ playGnapPullOutDevice(0, 0);
+ playGnapUseDevice(0, 0);
+ _gameSys->insertSequence(0xF9, 59, 0xF8, 59, kSeqSyncWait, 0, 0, 0);
+ _gnapActionStatus = -1;
+ invAdd(kItemBucketWithBeer);
+ invRemove(kItemEmptyBucket);
+ setGrabCursorSprite(kItemBucketWithBeer);
+ break;
+ case 5:
+ _s31_dword_47EAAC = 0xFA;
+ _s31_dword_474940 = 1;
+ break;
+ case 6:
+ _sceneDone = true;
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ _gameSys->setAnimation(0, 0, 1);
+ if (_beaverActionStatus == 4) {
+ _sceneWaiting = 1;
+ _s31_beerGuyDistracted = true;
+ _s31_dword_47EAAC = 0xFA;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ switch (_s31_dword_47EAAC) {
+ case 0xFA:
+ _gameSys->insertSequence(_s31_dword_47EAAC, 39, _s31_dword_47EAA8, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xFC, 39, _s31_dword_47EAAC, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0xFC, 39, 3);
+ _s31_dword_47EAA8 = 0xFC;
+ _s31_dword_47EAAC = 0xFC;
+ _s31_dword_47EAB0 = 0;
+ break;
+ case 0xFC:
+ ++_s31_dword_47EAB0;
+ if (_s31_dword_47EAB0 >= _s31_dword_474940) {
+ if (_gnapActionStatus != 5)
+ _beaverActionStatus = -1;
+ _timers[0] = 40;
+ _gameSys->insertSequence(0xFD, 39, _s31_dword_47EAA8, 39, kSeqSyncWait, 0, 0, 0);
+ _s31_dword_47EAA8 = 0xFD;
+ _s31_dword_47EAAC = -1;
+ if (_gnapActionStatus != 3 && _gnapActionStatus != 2)
+ _gnapActionStatus = -1;
+ _s31_beerGuyDistracted = false;
+ _s31_dword_474940 = 3;
+ _gameSys->setAnimation(0xFD, 39, 3);
+ _sceneWaiting = 0;
+ } else {
+ _gameSys->insertSequence(_s31_dword_47EAAC, 39, _s31_dword_47EAA8, 39, kSeqSyncWait, 0, 0, 0);
+ _s31_dword_47EAA8 = _s31_dword_47EAAC;
+ _s31_dword_47EAAC = 0xFC;
+ _gameSys->setAnimation(0xFC, 39, 3);
+ }
+ break;
+ case 0xFE:
+ _gameSys->insertSequence(_s31_dword_47EAAC, 39, _s31_dword_47EAA8, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s31_dword_47EAAC, 39, 3);
+ _s31_dword_47EAA8 = _s31_dword_47EAAC;
+ _s31_dword_47EAAC = -1;
+ _gnapActionStatus = -1;
+ break;
+ default:
+ if (_s31_dword_47EAAC != -1) {
+ _gameSys->insertSequence(_s31_dword_47EAAC, 39, _s31_dword_47EAA8, 39, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s31_dword_47EAAC, 39, 3);
+ _s31_dword_47EAA8 = _s31_dword_47EAAC;
+ _s31_dword_47EAAC = -1;
+ }
+ break;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene32.cpp b/engines/gnap/scenes/scene32.cpp
new file mode 100644
index 0000000000..3edd3db2cd
--- /dev/null
+++ b/engines/gnap/scenes/scene32.cpp
@@ -0,0 +1,201 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitTruck = 1,
+ kHSDevice = 2,
+ kHSWalkArea1 = 3,
+ kHSWalkArea2 = 4,
+ kHSWalkArea3 = 5,
+ kHSWalkArea4 = 6,
+ kHSWalkArea5 = 7,
+ kHSWalkArea6 = 8,
+ kHSWalkArea7 = 9,
+ kHSWalkArea8 = 10
+};
+
+int GnapEngine::scene32_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ return isFlag(26) ? 0xF : 0x10;
+}
+
+void GnapEngine::scene32_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitTruck, 780, 226, 800, 455, SF_EXIT_R_CURSOR | SF_WALKABLE, 10, 6);
+ setHotspot(kHSWalkArea1, 0, 0, 162, 426);
+ setHotspot(kHSWalkArea2, 162, 0, 237, 396);
+ setHotspot(kHSWalkArea3, 237, 0, 319, 363);
+ setHotspot(kHSWalkArea4, 520, 0, 800, 404);
+ setHotspot(kHSWalkArea5, 300, 447, 800, 600);
+ setHotspot(kHSWalkArea6, 678, 0, 800, 404);
+ setHotspot(kHSWalkArea7, 0, 0, 520, 351);
+ setHotspot(kHSWalkArea8, 0, 546, 300, 600);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 11;
+}
+
+void GnapEngine::scene32_run() {
+
+ playSound(0x1091C, 1);
+ startSoundTimerC(5);
+ queueInsertDeviceIcon();
+ _s32_dword_47EADC = -1;
+ _timers[4] = getRandom(100) + 300;
+
+ if (_prevSceneNum == 33) {
+ initGnapPos(11, 6, 3);
+ initBeaverPos(12, 6, 4);
+ endSceneInit();
+ platypusWalkTo(9, 6, -1, 0x107D2, 1);
+ gnapWalkTo(8, 6, -1, 0x107BA, 1);
+ } else {
+ initGnapPos(1, 6, 1);
+ initBeaverPos(1, 7, 0);
+ endSceneInit();
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene32_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(_platX, _platY);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitTruck:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ setGrabCursorSprite(-1);
+ gnapWalkTo(_hotspotsWalkPos[kHSExitTruck].x, _hotspotsWalkPos[kHSExitTruck].y, 0, 0x107AB, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitTruck].x, _hotspotsWalkPos[kHSExitTruck].y + 1, -1, 0x107CD, 1);
+ _newSceneNum = 33;
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ case kHSWalkArea4:
+ case kHSWalkArea5:
+ case kHSWalkArea6:
+ case kHSWalkArea7:
+ case kHSWalkArea8:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ }
+
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = 0;
+ }
+
+ scene32_updateAnimations();
+
+ if (!isSoundPlaying(0x1091C))
+ playSound(0x1091C, 1);
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0)
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(100) + 300;
+ if (getRandom(2) != 0)
+ _s32_dword_47EADC = 14;
+ else
+ _s32_dword_47EADC = 13;
+ _gameSys->insertSequence(_s32_dword_47EADC, 180, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ playSoundC();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene32_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene32_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ if (_gnapActionStatus == 0)
+ _sceneDone = true;
+ }
+
+}
+
+} // End of namespace Gnap
+ \ No newline at end of file
diff --git a/engines/gnap/scenes/scene33.cpp b/engines/gnap/scenes/scene33.cpp
new file mode 100644
index 0000000000..f9471abcd5
--- /dev/null
+++ b/engines/gnap/scenes/scene33.cpp
@@ -0,0 +1,327 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSChicken = 1,
+ kHSDevice = 2,
+ kHSExitHouse = 3,
+ kHSExitBarn = 4,
+ kHSExitCreek = 5,
+ kHSExitPigpen = 6,
+ kHSWalkArea1 = 7,
+ kHSWalkArea2 = 8
+};
+
+int GnapEngine::scene33_init() {
+ return isFlag(26) ? 0x84 : 0x85;
+}
+
+void GnapEngine::scene33_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSChicken, 606, 455, 702, 568, SF_WALKABLE | SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8);
+ setHotspot(kHSExitHouse, 480, 120, 556, 240, SF_EXIT_U_CURSOR, 7, 3);
+ setHotspot(kHSExitBarn, 610, 75, 800, 164, SF_EXIT_U_CURSOR, 10, 3);
+ setHotspot(kHSExitCreek, 780, 336, 800, 556, SF_EXIT_R_CURSOR | SF_WALKABLE, 10, 8);
+ setHotspot(kHSExitPigpen, 0, 300, 20, 600, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 8);
+ setHotspot(kHSWalkArea1, 120, 0, 514, 458);
+ setHotspot(kHSWalkArea2, 0, 0, 800, 452);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 9;
+}
+
+void GnapEngine::scene33_run() {
+
+ playSound(0x1091C, 1);
+ startSoundTimerC(6);
+ queueInsertDeviceIcon();
+
+ _s33_dword_47EAEC = 0x7E;
+ _gameSys->setAnimation(0x7E, 179, 2);
+ _gameSys->insertSequence(_s33_dword_47EAEC, 179, 0, 0, kSeqNone, 0, 0, 0);
+ _s33_dword_47EAE4 = -1;
+ _timers[5] = getRandom(20) + 30;
+ _s33_dword_47EAE8 = -1;
+ _timers[4] = getRandom(100) + 300;
+
+ switch (_prevSceneNum) {
+ case 34:
+ initGnapPos(11, 7, 3);
+ initBeaverPos(12, 7, 4);
+ endSceneInit();
+ gnapWalkTo(8, 7, -1, 0x107BA, 1);
+ platypusWalkTo(9, 7, -1, 0x107D2, 1);
+ break;
+ case 37:
+ initGnapPos(7, 7, 1);
+ initBeaverPos(8, 7, 0);
+ endSceneInit();
+ break;
+ case 32:
+ initGnapPos(-1, 6, 1);
+ initBeaverPos(-1, 7, 0);
+ endSceneInit();
+ platypusWalkTo(2, 7, -1, 0x107C2, 1);
+ gnapWalkTo(2, 8, -1, 0x107B9, 1);
+ break;
+ default:
+ initGnapPos(3, 7, 1);
+ initBeaverPos(2, 7, 0);
+ endSceneInit();
+ break;
+ }
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+ testWalk(0, 0, 7, 6, 8, 6);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene33_updateHotspots();
+ }
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(_platX, _platY);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSChicken:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(7, 9, 9, 8);
+ } else {
+ switch (_verbCursor) {
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 1;
+ if (gnapWalkTo(_hotspotsWalkPos[kHSChicken].x, _hotspotsWalkPos[kHSChicken].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1))
+ _gnapActionStatus = 2;
+ else
+ _gnapActionStatus = -1;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSChicken].x, _hotspotsWalkPos[kHSChicken].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = 1;
+ break;
+ case LOOK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitHouse:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _gnapActionStatus = 0;
+ _newSceneNum = 37;
+ if (_gnapX > 6)
+ gnapWalkTo(_gnapX, _gnapY, 0, 0x107AD, 1);
+ else
+ gnapWalkTo(6, 7, 0, 0x107B1, 1);
+ }
+ break;
+
+ case kHSExitBarn:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _gnapActionStatus = 0;
+ _newSceneNum = 35;
+ if (_gnapX > 7)
+ gnapWalkTo(_gnapX, _gnapY, 0, 0x107AD, 1);
+ else
+ gnapWalkTo(7, 7, 0, 0x107B1, 1);
+ }
+ break;
+
+ case kHSExitCreek:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitCreek].x, _hotspotsWalkPos[kHSExitCreek].y, 0, 0x107AB, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitCreek].x, _hotspotsWalkPos[kHSExitCreek].y, -1, 0x107CD, 1);
+ _newSceneNum = 34;
+ }
+ break;
+
+ case kHSExitPigpen:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitPigpen].x, _hotspotsWalkPos[kHSExitPigpen].y, 0, 0x107AF, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitPigpen].x, _hotspotsWalkPos[kHSExitPigpen].y, -1, 0x107CF, 1);
+ _newSceneNum = 32;
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene33_updateAnimations();
+
+ if (!isSoundPlaying(0x1091C))
+ playSound(0x1091C, 1);
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0)
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(100) + 300;
+ if (getRandom(2) != 0)
+ _s33_dword_47EAE8 = 0x83;
+ else
+ _s33_dword_47EAE8 = 0x82;
+ _gameSys->insertSequence(_s33_dword_47EAE8, 256, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ if (!_timers[5] && _s33_dword_47EAE4 == -1 && _gnapActionStatus != 1 && _gnapActionStatus != 2) {
+ if (getRandom(6) != 0) {
+ _s33_dword_47EAE4 = 0x7E;
+ _timers[5] = getRandom(20) + 30;
+ } else {
+ _s33_dword_47EAE4 = 0x80;
+ _timers[5] = getRandom(20) + 50;
+ }
+ }
+ playSoundC();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene33_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene33_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ switch (_gnapActionStatus) {
+ case 0:
+ _sceneDone = true;
+ break;
+ case 1:
+ _s33_dword_47EAE4 = 0x7F;
+ break;
+ case 2:
+ _s33_dword_47EAE4 = 0x81;
+ _timers[2] = 100;
+ break;
+ case 3:
+ _gameSys->insertSequence(0x107B5, _gnapId, 0x81, 179, kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gnapSequenceId = 0x7B5;
+ _gnapSequenceDatNum = 1;
+ _s33_dword_47EAEC = 0x7E;
+ _gameSys->setAnimation(0x7E, 179, 2);
+ _gameSys->insertSequence(_s33_dword_47EAEC, 179, 0, 0, kSeqNone, 0, 0, 0);
+ _gnapActionStatus = -1;
+ _timers[5] = 30;
+ break;
+ default:
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ if (_s33_dword_47EAE4 == 0x81) {
+ _gameSys->setAnimation(_s33_dword_47EAE4, 179, 0);
+ _gameSys->insertSequence(_s33_dword_47EAE4, 179, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->removeSequence(_s33_dword_47EAEC, 179, 1);
+ _s33_dword_47EAE4 = -1;
+ _s33_dword_47EAEC = -1;
+ _gnapActionStatus = 3;
+ _timers[5] = 500;
+ } else if (_s33_dword_47EAE4 == 0x7F) {
+ _gameSys->setAnimation(_s33_dword_47EAE4, 179, 2);
+ _gameSys->insertSequence(_s33_dword_47EAE4, 179, _s33_dword_47EAEC, 179, kSeqSyncWait, 0, 0, 0);
+ _s33_dword_47EAEC = _s33_dword_47EAE4;
+ _s33_dword_47EAE4 = -1;
+ _gnapActionStatus = -1;
+ } else if (_s33_dword_47EAE4 != -1) {
+ _gameSys->setAnimation(_s33_dword_47EAE4, 179, 2);
+ _gameSys->insertSequence(_s33_dword_47EAE4, 179, _s33_dword_47EAEC, 179, kSeqSyncWait, 0, 0, 0);
+ _s33_dword_47EAEC = _s33_dword_47EAE4;
+ _s33_dword_47EAE4 = -1;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
+ \ No newline at end of file
diff --git a/engines/gnap/scenes/scene38.cpp b/engines/gnap/scenes/scene38.cpp
new file mode 100644
index 0000000000..cfbaf9dcaf
--- /dev/null
+++ b/engines/gnap/scenes/scene38.cpp
@@ -0,0 +1,355 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitHouse = 1,
+ kHSExitCave = 2,
+ kHSTrapDoorLid1 = 3,
+ kHSTrapDoorLid2 = 4,
+ kHSHuntingTrophy = 5,
+ kHSWalkArea1 = 6,
+ kHSDevice = 7,
+ kHSWalkArea2 = 8,
+ kHSWalkArea3 = 9,
+ kHSWalkArea4 = 10,
+ kHSWalkArea5 = 11,
+ kHSWalkArea6 = 12
+};
+
+int GnapEngine::scene38_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ return 0xA5;
+}
+
+void GnapEngine::scene38_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitHouse, 150, 585, 650, 600, SF_EXIT_D_CURSOR, 0, 8);
+ setHotspot(kHSExitCave, 430, 440, 655, 470, SF_WALKABLE, 0, 8);
+ setHotspot(kHSTrapDoorLid1, 525, 265, 640, 350, SF_DISABLED);
+ setHotspot(kHSTrapDoorLid2, 555, 350, 670, 430, SF_DISABLED);
+ setHotspot(kHSHuntingTrophy, 170, 85, 250, 190, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 0, 8);
+ setHotspot(kHSWalkArea1, 330, 270, 640, 380, SF_DISABLED | SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 0, 8);
+ setHotspot(kHSWalkArea2, 0, 0, 799, 396);
+ setHotspot(kHSWalkArea3, 0, 585, 799, 599, SF_WALKABLE | SF_DISABLED);
+ setHotspot(kHSWalkArea4, 0, 0, 97, 445);
+ setHotspot(kHSWalkArea5, 770, 0, 799, 445);
+ setHotspot(kHSWalkArea6, 393, 0, 698, 445, SF_WALKABLE | SF_DISABLED);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (_beaverActionStatus == 6)
+ _hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_DISABLED;
+ if (_beaverActionStatus == 6)
+ _hotspots[kHSExitCave].flags = SF_EXIT_D_CURSOR;
+ else if (_gnapActionStatus == 3)
+ _hotspots[kHSExitCave].flags = SF_EXIT_D_CURSOR;
+ if (_beaverActionStatus == 6)
+ _hotspots[kHSTrapDoorLid1].flags = SF_DISABLED;
+ else if (_gnapActionStatus == 3)
+ _hotspots[kHSTrapDoorLid1].flags = SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR;
+ if (_beaverActionStatus == 6)
+ _hotspots[kHSTrapDoorLid2].flags = SF_DISABLED;
+ else if (_gnapActionStatus == 3)
+ _hotspots[kHSTrapDoorLid2].flags = SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR;
+ if (_beaverActionStatus == 6)
+ _hotspots[kHSWalkArea6].flags = 0;
+ _hotspotsCount = 13;
+}
+
+void GnapEngine::scene38_run() {
+
+ queueInsertDeviceIcon();
+ _gameSys->insertSequence(0x9B, 0, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (_prevSceneNum == 39) {
+ initGnapPos(3, 7, 3);
+ initBeaverPos(4, 7, 4);
+ } else {
+ initGnapPos(3, 8, 1);
+ initBeaverPos(4, 8, 0);
+ }
+ endSceneInit();
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ runMenu();
+ scene38_updateHotspots();
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus == 3) {
+ _gnapActionStatus = 4;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(_platX, _platY);
+ break;
+ }
+ }
+ break;
+
+ case kHSExitHouse:
+ if (_gnapActionStatus == 3) {
+ _gnapActionStatus = 4;
+ } else {
+ _isLeavingScene = 1;
+ gnapWalkTo(-1, -1, 0, 0x107AE, 1);
+ _gnapActionStatus = 0;
+ _newSceneNum = 37;
+ }
+ break;
+
+ case kHSExitCave:
+ if (_gnapActionStatus == 3) {
+ _gnapActionStatus = 4;
+ if (_beaverActionStatus == 6)
+ _isLeavingScene = 1;
+ } else if (_beaverActionStatus == 6) {
+ _sceneWaiting = 0;
+ _isLeavingScene = 1;
+ gnapWalkTo(5, 7, 0, 0x107BB, 1);
+ _newSceneNum = 39;
+ _gnapActionStatus = 1;
+ }
+ break;
+
+ case kHSTrapDoorLid1:
+ case kHSTrapDoorLid2:
+ if (_gnapActionStatus == 3) {
+ if (_beaverActionStatus == 6 && _verbCursor == PLAT_CURSOR)
+ _gnapActionStatus = 5;
+ else
+ _gnapActionStatus = 4;
+ }
+ break;
+
+ case kHSHuntingTrophy:
+ if (_gnapActionStatus != 3) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(3, 6, 2, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(0, 0);
+ break;
+ case GRAB_CURSOR:
+ if (_beaverActionStatus == 6)
+ playGnapImpossible(0, 0);
+ else {
+ gnapWalkTo(3, 6, 0, 0x107BB, 1);
+ platypusWalkTo(4, 8, -1, -1, 1);
+ _gnapActionStatus = 2;
+ }
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(2, 0);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ // Nothing
+ break;
+
+ case kHSWalkArea2:
+ case kHSWalkArea3:
+ case kHSWalkArea4:
+ case kHSWalkArea5:
+ case kHSWalkArea6:
+ if (_gnapActionStatus == 3)
+ _gnapActionStatus = 4;
+ else if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left) {
+ if (_gnapActionStatus == 3)
+ _gnapActionStatus = 4;
+ else if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene38_updateAnimations();
+
+ if (!_isLeavingScene) {
+ updateBeaverIdleSequence();
+ updateGnapIdleSequence();
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene38_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene38_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case 0:
+ _sceneDone = true;
+ break;
+ case 1:
+ _gameSys->removeSequence(_beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, 1);
+ _gameSys->insertSequence(0xA3, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0xA3;
+ _gnapSequenceDatNum = 0;
+ _gameSys->setAnimation(0xA3, _gnapId, 0);
+ _gnapActionStatus = 0;
+ break;
+ case 2:
+ _gameSys->removeSequence(0x9B, 0, 1);
+ _gameSys->insertSequence(0x9C, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x9C;
+ _gnapSequenceDatNum = 0;
+ _gameSys->setAnimation(0x9C, _gnapId, 0);
+ _gnapActionStatus = 3;
+ scene38_updateHotspots();
+ break;
+ case 3:
+ if (_beaverActionStatus != 6)
+ _sceneWaiting = 1;
+ if (_gnapSequenceId == 0xA4) {
+ _gameSys->insertSequence(0x9D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x9D;
+ } else {
+ _gameSys->insertSequence(0xA4, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0xA4;
+ }
+ _gnapSequenceDatNum = 0;
+ _gameSys->setAnimation(_gnapSequenceId, _gnapId, 0);
+ break;
+ case 4:
+ if (_gnapSequenceId == 0x9E) {
+ _gameSys->insertSequence(0x9B, 0, 0, 0, kSeqNone, 0, 0, 0);
+ _gnapActionStatus = -1;
+ } else if (_beaverActionStatus == 6) {
+ _gameSys->insertSequence(0xA0, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0xA0;
+ _gnapSequenceDatNum = 0;
+ _gnapX = 3;
+ _gnapY = 6;
+ _gnapIdleFacing = 1;
+ if (_isLeavingScene) {
+ _sceneWaiting = 0;
+ gnapWalkTo(5, 7, 0, 0x107BB, 1);
+ _newSceneNum = 39;
+ _gnapActionStatus = 1;
+ } else {
+ _gnapActionStatus = -1;
+ }
+ } else {
+ _gameSys->insertSequence(0x9E, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x9E;
+ _gnapSequenceDatNum = 0;
+ _gnapX = 3;
+ _gnapY = 6;
+ _gnapIdleFacing = 1;
+ _gameSys->setAnimation(0x9E, _gnapId, 0);
+ _sceneWaiting = 0;
+ scene38_updateHotspots();
+ }
+ break;
+ case 5:
+ _sceneWaiting = 0;
+ _gameSys->insertSequence(0x9F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x9F;
+ _gnapSequenceDatNum = 0;
+ _gameSys->setAnimation(0x9F, _gnapId, 0);
+ _gnapActionStatus = 3;
+ if (_beaverFacing)
+ playBeaverSequence(0x107D5);
+ else
+ playBeaverSequence(0x107D4);
+ platypusWalkTo(8, 7, -1, 0x107D2, 1);
+ _gameSys->insertSequence(0xA1, _gnapId + 1, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0);
+ _beaverSequenceId = 0xA1;
+ _beaverSequenceDatNum = 0;
+ _beaverId = _gnapId + 1;
+ _gameSys->setAnimation(0xA1, _gnapId + 1, 1);
+ _beaverActionStatus = 6;
+ scene38_updateHotspots();
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ _gameSys->setAnimation(0, 0, 1);
+ if (_beaverActionStatus == 6) {
+ _gameSys->insertSequence(0xA2, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0);
+ _beaverSequenceId = 0xA2;
+ _beaverSequenceDatNum = 0;
+ scene38_updateHotspots();
+ _sceneWaiting = true;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
+ \ No newline at end of file
diff --git a/engines/gnap/scenes/scene39.cpp b/engines/gnap/scenes/scene39.cpp
new file mode 100644
index 0000000000..7bf04de240
--- /dev/null
+++ b/engines/gnap/scenes/scene39.cpp
@@ -0,0 +1,237 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitInsideHouse = 1,
+ kHSExitUfoParty = 2,
+ kHSSign = 3,
+ kHSDevice = 4,
+ kHSWalkArea1 = 5,
+ kHSWalkArea2 = 6
+};
+
+int GnapEngine::scene39_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ return 0x35;
+}
+
+void GnapEngine::scene39_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitInsideHouse, 0, 0, 140, 206, SF_EXIT_U_CURSOR, 4, 8);
+ setHotspot(kHSExitUfoParty, 360, 204, 480, 430, SF_EXIT_R_CURSOR, 6, 8);
+ setHotspot(kHSSign, 528, 232, 607, 397, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 3);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 466);
+ setHotspot(kHSWalkArea2, 502, 466, 800, 600);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 7;
+}
+
+void GnapEngine::scene39_run() {
+
+ queueInsertDeviceIcon();
+ _s39_dword_47EAF8 = 0x33;
+
+ _gameSys->setAnimation(0x33, 21, 3);
+ _gameSys->insertSequence(_s39_dword_47EAF8, 21, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x34, 21, 0, 0, kSeqLoop, 0, 0, 0);
+
+ _s39_dword_47EAFC = -1;
+ if (_prevSceneNum == 38) {
+ initGnapPos(3, 7, 7);
+ initBeaverPos(2, 7, 5);
+ endSceneInit();
+ } else {
+ initGnapPos(4, 7, 1);
+ initBeaverPos(5, 7, 0);
+ endSceneInit();
+ }
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x1094B)) {
+ playSound(0x1094B, 1);
+ setSoundVolume(0x1094B, 60);
+ }
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ runMenu();
+ scene39_updateHotspots();
+ _timers[5] = getRandom(20) + 50;
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(_platX, _platY);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitUfoParty:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ _sceneDone = true;
+ gnapWalkTo(_gnapX, _gnapY, 0, 0x107AB, 1);
+ _gnapActionStatus = 0;
+ _newSceneNum = 40;
+ }
+ break;
+
+ case kHSSign:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(0, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ gnapWalkTo(_hotspotsWalkPos[kHSSign].x, _hotspotsWalkPos[kHSSign].y, 0, -1, 1);
+ playGnapIdle(_hotspotsWalkPos[kHSSign].x, _hotspotsWalkPos[kHSSign].y);
+ showFullScreenSprite(0x1C);
+ break;
+ case GRAB_CURSOR:
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitInsideHouse:
+ if (_gnapActionStatus < 0) {
+ _sceneDone = true;
+ _isLeavingScene = 1;
+ _newSceneNum = 38;
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ _mouseClickState.left = false;
+ }
+ break;
+
+ }
+
+ scene39_updateAnimations();
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0)
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0)
+ updateGnapIdleSequence();
+ if (!_timers[5]) {
+ _timers[5] = getRandom(20) + 50;
+ switch (getRandom(4)) {
+ case 0:
+ _s39_dword_47EAFC = 0x30;
+ break;
+ case 1:
+ _s39_dword_47EAFC = 0x31;
+ break;
+ case 2:
+ _s39_dword_47EAFC = 0x32;
+ break;
+ case 3:
+ _s39_dword_47EAFC = 0x33;
+ break;
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene39_updateHotspots();
+ _timers[5] = getRandom(20) + 50;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene39_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ if (_gnapActionStatus == 0)
+ _sceneDone = true;
+ else
+ _gnapActionStatus = -1;
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2 && _s39_dword_47EAFC != -1) {
+ _gameSys->setAnimation(_s39_dword_47EAFC, 21, 3);
+ _gameSys->insertSequence(_s39_dword_47EAFC, 21, _s39_dword_47EAF8, 21, kSeqSyncWait, 0, 0, 0);
+ _s39_dword_47EAF8 = _s39_dword_47EAFC;
+ _s39_dword_47EAFC = -1;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene40.cpp b/engines/gnap/scenes/scene40.cpp
new file mode 100644
index 0000000000..fe91dbf777
--- /dev/null
+++ b/engines/gnap/scenes/scene40.cpp
@@ -0,0 +1,193 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitCave = 1,
+ kHSExitToyStand = 2,
+ kHSExitBBQ = 3,
+ kHSExitUfo = 4,
+ kHSExitKissinBooth = 5,
+ kHSExitDancefloor = 6,
+ kHSExitShoe = 7,
+ kHSDevice = 8
+};
+
+int GnapEngine::scene40_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ return isFlag(23) ? 0x01 : 0x00;
+}
+
+void GnapEngine::scene40_updateHotspots() {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_DISABLED | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitCave, 169, 510, 264, 600, SF_EXIT_D_CURSOR, 0, 8);
+ setHotspot(kHSExitToyStand, 238, 297, 328, 376, SF_EXIT_L_CURSOR, 0, 8);
+ setHotspot(kHSExitBBQ, 328, 220, 401, 306, SF_EXIT_L_CURSOR, 0, 8);
+ setHotspot(kHSExitUfo, 421, 215, 501, 282, SF_EXIT_U_CURSOR, 0, 8);
+ setHotspot(kHSExitKissinBooth, 476, 284, 556, 345, SF_EXIT_R_CURSOR, 0, 8);
+ setHotspot(kHSExitDancefloor, 317, 455, 445, 600, SF_EXIT_D_CURSOR, 0, 8);
+ setHotspot(kHSExitShoe, 455, 346, 549, 417, SF_EXIT_D_CURSOR, 0, 8);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 9;
+}
+
+void GnapEngine::scene40_run() {
+
+ queueInsertDeviceIcon();
+ endSceneInit();
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x1094B))
+ playSound(0x1094B, 1);
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ runMenu();
+ scene40_updateHotspots();
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(_platX, _platY);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitCave:
+ if (_gnapActionStatus < 0) {
+ _newSceneNum = 39;
+ _sceneDone = true;
+ }
+ break;
+
+ case kHSExitToyStand:
+ if (_gnapActionStatus < 0) {
+ _newSceneNum = 41;
+ _sceneDone = true;
+ }
+ break;
+
+ case kHSExitBBQ:
+ if (_gnapActionStatus < 0) {
+ _newSceneNum = 42;
+ _sceneDone = true;
+ }
+ break;
+
+ case kHSExitUfo:
+ if (_gnapActionStatus < 0) {
+ _newSceneNum = 43;
+ _sceneDone = true;
+ }
+ break;
+
+ case kHSExitKissinBooth:
+ if (_gnapActionStatus < 0) {
+ _newSceneNum = 44;
+ _sceneDone = true;
+ }
+ break;
+
+ case kHSExitDancefloor:
+ if (_gnapActionStatus < 0) {
+ _newSceneNum = 45;
+ _sceneDone = true;
+ }
+ break;
+
+ case kHSExitShoe:
+ if (_gnapActionStatus < 0) {
+ _newSceneNum = 46;
+ _sceneDone = true;
+ }
+ break;
+
+ default:
+ if (_mouseClickState.left && _gnapActionStatus < 0)
+ _mouseClickState.left = false;
+ break;
+
+ }
+
+ scene40_updateAnimations();
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene40_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene40_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ if (_gnapActionStatus)
+ _gnapActionStatus = -1;
+ else
+ _sceneDone = true;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene41.cpp b/engines/gnap/scenes/scene41.cpp
new file mode 100644
index 0000000000..60c5979ae7
--- /dev/null
+++ b/engines/gnap/scenes/scene41.cpp
@@ -0,0 +1,577 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitCave = 1,
+ kHSExit = 2,
+ kHSExitBBQ = 3,
+ kHSToyVendor = 4,
+ kHSKid = 5,
+ kHSToyUfo = 6,
+ kHSDevice = 7,
+ kHSWalkArea1 = 8
+};
+
+enum {
+ kHSUfoExitLeft = 1,
+ kHSUfoExitRight = 2,
+ kHSUfoDevice = 3,
+ kHSUfoWalkArea1 = 4
+};
+
+int GnapEngine::scene41_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0, 0, 2);
+ return 0x129;
+}
+
+void GnapEngine::scene41_updateHotspots() {
+ if (isFlag(12)) {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED);
+ setHotspot(kHSUfoExitLeft, 0, 0, 10, 500, SF_EXIT_L_CURSOR | SF_DISABLED);
+ setHotspot(kHSUfoExitRight, 790, 0, 799, 500, SF_EXIT_R_CURSOR);
+ setHotspot(kHSUfoWalkArea1, 0, 0, 800, 470, SF_DISABLED);
+ setDeviceHotspot(kHSUfoDevice, -1, -1, -1, -1);
+ _hotspotsCount = 5;
+ } else {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitCave, 150, 590, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9);
+ setHotspot(kHSExit, 0, 100, 10, 599, SF_EXIT_L_CURSOR | SF_DISABLED, 0, 8);
+ setHotspot(kHSExitBBQ, 790, 100, 799, 599, SF_EXIT_R_CURSOR | SF_WALKABLE, 10, 8);
+ setHotspot(kHSToyVendor, 320, 150, 430, 310, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSKid, 615, 340, 710, 460, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSToyUfo, 0, 0, 0, 0, SF_GRAB_CURSOR);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 470);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 9;
+ }
+}
+
+void GnapEngine::scene41_run() {
+
+ queueInsertDeviceIcon();
+
+ if (isFlag(12)) {
+ _toyUfoX = 770;
+ if (_toyUfoY < 0 || _toyUfoY > 300)
+ _toyUfoY = 150;
+ if (!_timers[9])
+ _gnapActionStatus = 6;
+ } else {
+ if (!isFlag(16) && !isFlag(17) && !isFlag(18) && !isFlag(19))
+ toyUfoSetStatus(16);
+ _toyUfoX = 600;
+ _toyUfoY = 200;
+ }
+
+ _toyUfoId = 0;
+ _toyUfoActionStatus = -1;
+ _toyUfoSequenceId = toyUfoGetSequenceId();
+ _toyUfoNextSequenceId = _toyUfoSequenceId;
+
+ _gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 2);
+ _gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128);
+ _gameSys->insertSequence(0x128, 0, 0, 0, kSeqLoop, 0, 0, 0);
+
+ if (isFlag(12))
+ _s41_dword_47F2C4 = 0x11B;
+ else
+ _s41_dword_47F2C4 = 0x11D;
+
+ _s41_dword_47F2C0 = -1;
+
+ _gameSys->setAnimation(_s41_dword_47F2C4, 1, 4);
+ _gameSys->insertSequence(_s41_dword_47F2C4, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s41_dword_47F2CC = 0x118;
+ _s41_dword_47F2C8 = -1;
+
+ _gameSys->setAnimation(0x118, 1, 3);
+ _gameSys->insertSequence(_s41_dword_47F2CC, 1, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(0x127, 2, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(12)) {
+ _gnapSequenceId = 0x120;
+ _gnapSequenceDatNum = 0;
+ _gnapIdleFacing = 7;
+ _gnapX = 7;
+ _gnapY = 7;
+ _gnapId = 140;
+ _gameSys->insertSequence(0x120, 140, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0);
+ initBeaverPos(8, 10, 3);
+ endSceneInit();
+ } else if (_prevSceneNum == 45) {
+ initGnapPos(-1, 8, 7);
+ initBeaverPos(-2, 8, 5);
+ endSceneInit();
+ platypusWalkTo(1, 8, -1, 0x107C2, 1);
+ gnapWalkTo(2, 8, -1, 0x107B9, 1);
+ } else if (_prevSceneNum == 42) {
+ initGnapPos(11, 8, 7);
+ initBeaverPos(11, 9, 5);
+ endSceneInit();
+ gnapWalkTo(8, 8, -1, 0x107BA, 1);
+ platypusWalkTo(9, 8, -1, 0x107D2, 1);
+ } else {
+ initGnapPos(5, 8, 1);
+ initBeaverPos(6, 8, 3);
+ endSceneInit();
+ }
+
+ _timers[4] = getRandom(100) + 100;
+ _timers[5] = getRandom(30) + 20;
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x1094B))
+ playSound(0x1094B, 1);
+
+ if (!isFlag(12)) {
+ _hotspots[kHSToyUfo].x1 = _toyUfoX - 25;
+ _hotspots[kHSToyUfo].y1 = _toyUfoY - 20;
+ _hotspots[kHSToyUfo].x2 = _toyUfoX + 25;
+ _hotspots[kHSToyUfo].y2 = _toyUfoY + 20;
+ }
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ if (isFlag(12)) {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSUfoExitLeft:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = 1;
+ _toyUfoActionStatus = 7;
+ _newSceneNum = 45;
+ toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 2);
+ }
+ break;
+
+ case kHSUfoExitRight:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = 1;
+ _toyUfoActionStatus = 7;
+ _newSceneNum = 42;
+ toyUfoFlyTo(835, -1, 0, 835, 0, 300, 2);
+ }
+ break;
+
+ case kHSUfoDevice:
+ runMenu();
+ scene41_updateHotspots();
+ _timers[4] = getRandom(100) + 100;
+ _timers[5] = getRandom(30) + 20;
+ break;
+
+ }
+
+ } else {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ runMenu();
+ scene41_updateHotspots();
+ _timers[4] = getRandom(100) + 100;
+ _timers[5] = getRandom(30) + 20;
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(_platX, _platY);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitCave:
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitCave].x, _hotspotsWalkPos[kHSExitCave].y, 0, 0x107AE, 1);
+ _gnapActionStatus = 0;
+ _newSceneNum = 40;
+ break;
+
+ case kHSExit:
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExit].x, -1, 0, 0x107AF, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExit].x, -1, -1, 0x107CF, 1);
+ _newSceneNum = 45;
+ break;
+
+ case kHSExitBBQ:
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitBBQ].x, -1, 0, 0x107AB, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitBBQ].x, -1, -1, 0x107CD, 1);
+ _newSceneNum = 42;
+ break;
+
+ case kHSToyVendor:
+ if (_grabCursorSpriteIndex == kItemDiceQuarterHole) {
+ _gnapActionStatus = 1;
+ gnapWalkTo(4, 7, 0, 0x107BB, 9);
+ playGnapShowItem(_grabCursorSpriteIndex, 5, 0);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(4, 7, 5, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(5, 0);
+ break;
+ case GRAB_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(4, 7, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = 2;
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSKid:
+ if (_grabCursorSpriteIndex == kItemChickenBucket) {
+ gnapWalkTo(7, 7, 0, 0x107BB, 1);
+ _gnapIdleFacing = 7;
+ _gnapActionStatus = 4;
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(7, 7, 8, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(9, 0);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(7, 7, 0, 0x107BB, 1);
+ _gnapIdleFacing = 7;
+ _gnapActionStatus = 5;
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(7, 7, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSToyUfo:
+ if (_grabCursorSpriteIndex == kItemGum) {
+ playGnapPullOutDevice(9, 0);
+ _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0);
+ _gnapActionStatus = 3;
+ }
+ break;
+
+ case kHSWalkArea1:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+ }
+
+ }
+
+ if (isFlag(12)) {
+ if (!_timers[9] && _gnapActionStatus < 0) {
+ _gnapActionStatus = 6;
+ if (_gnapSequenceId == 0x121 || _gnapSequenceId == 0x122) {
+ _gameSys->insertSequence(0x123, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x123;
+ _gnapSequenceDatNum = 0;
+ _gameSys->setAnimation(0x123, _gnapId, 0);
+ }
+ }
+ }
+
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ _mouseClickState.left = false;
+ if (isFlag(12)) {
+ int sequenceId;
+ if (_leftClickMouseX >= 400) {
+ if (_gnapSequenceId == 0x11F || _gnapSequenceId == 0x120 || _gnapSequenceId == 0x123 || _gnapSequenceId == 0x126)
+ sequenceId = 0x120;
+ else if (_leftClickMouseX - _toyUfoX >= 400)
+ sequenceId = 0x126;
+ else
+ sequenceId = 0x123;
+ } else {
+ if (_gnapSequenceId == 0x121 || _gnapSequenceId == 0x125 || _gnapSequenceId == 0x122)
+ sequenceId = 0x122;
+ else if (_toyUfoX - _leftClickMouseX >= 400)
+ sequenceId = 0x125;
+ else
+ sequenceId = 0x121;
+ }
+ _gameSys->insertSequence(sequenceId, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = sequenceId;
+ _gnapSequenceDatNum = 0;
+ _gameSys->setAnimation(sequenceId, _gnapId, 0);
+ _toyUfoActionStatus = 8;
+ toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 2);
+ } else {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ }
+ }
+
+ scene41_updateAnimations();
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0)
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0 && !isFlag(12))
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(100) + 100;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _toyUfoActionStatus == -1 && _s41_dword_47F2C8 == -1) {
+ _gnapRandomValue = getRandom(3);
+ switch (_gnapRandomValue) {
+ case 0:
+ _s41_dword_47F2C8 = 0x113;
+ break;
+ case 1:
+ _s41_dword_47F2C8 = 0x117;
+ break;
+ case 2:
+ _s41_dword_47F2C8 = 0x119;
+ break;
+ }
+ if (_s41_dword_47F2C8 == _s41_dword_47F2CC)
+ _s41_dword_47F2C8 = -1;
+ }
+ }
+ if (!_timers[5]) {
+ _timers[5] = getRandom(30) + 20;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _toyUfoActionStatus == -1 && _s41_dword_47F2C0 == -1) {
+ if (isFlag(12))
+ _s41_dword_47F2C0 = 0x11B;
+ else if (getRandom(3) != 0)
+ _s41_dword_47F2C0 = 0x11D;
+ else
+ _s41_dword_47F2C0 = 0x11E;
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene41_updateHotspots();
+ _timers[4] = getRandom(100) + 100;
+ _timers[5] = getRandom(30) + 20;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene41_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ switch (_gnapActionStatus) {
+ case 0:
+ _gameSys->setAnimation(0, 0, 0);
+ _sceneDone = true;
+ _gnapActionStatus = -1;
+ break;
+ case 1:
+ _gameSys->setAnimation(0, 0, 0);
+ _s41_dword_47F2C8 = 0x114;
+ _gnapActionStatus = -1;
+ break;
+ case 2:
+ _gameSys->setAnimation(0, 0, 0);
+ _s41_dword_47F2C8 = 0x116;
+ _gnapActionStatus = -1;
+ break;
+ case 3:
+ _gameSys->setAnimation(0, 0, 0);
+ playGnapUseDevice(9, 0);
+ _gnapActionStatus = -1;
+ setGrabCursorSprite(-1);
+ invRemove(kItemGum);
+ _toyUfoActionStatus = 9;
+ break;
+ case 4:
+ if (_gameSys->getAnimationStatus(4) == 2) {
+ _timers[2] = getRandom(30) + 20;
+ _timers[3] = getRandom(50) + 200;
+ setGrabCursorSprite(-1);
+ _gameSys->insertSequence(0x11F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x11F;
+ _gnapSequenceDatNum = 0;
+ _gameSys->setAnimation(0x11F, _gnapId, 0);
+ _s41_dword_47F2C0 = 0x11A;
+ _gameSys->insertSequence(0x11A, 1, _s41_dword_47F2C4, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s41_dword_47F2C0, 1, 4);
+ _s41_dword_47F2C4 = _s41_dword_47F2C0;
+ _s41_dword_47F2C0 = 0x11B;
+ _timers[5] = getRandom(30) + 20;
+ _gnapActionStatus = -1;
+ setFlag(12);
+ scene41_updateHotspots();
+ _timers[9] = 600;
+ }
+ break;
+ case 5:
+ if (_gameSys->getAnimationStatus(3) == 2 && _gameSys->getAnimationStatus(4) == 2) {
+ _timers[2] = getRandom(30) + 20;
+ _timers[3] = getRandom(50) + 200;
+ _gameSys->insertSequence(0x110, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x110;
+ _gnapSequenceDatNum = 0;
+ _gameSys->setAnimation(0x110, _gnapId, 0);
+ _s41_dword_47F2C8 = 0x111;
+ _gameSys->insertSequence(0x111, 1, _s41_dword_47F2CC, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s41_dword_47F2C8, 1, 3);
+ _s41_dword_47F2CC = _s41_dword_47F2C8;
+ _s41_dword_47F2C8 = -1;
+ _timers[4] = getRandom(100) + 100;
+ _s41_dword_47F2C0 = 0x10F;
+ _gameSys->insertSequence(0x10F, 1, _s41_dword_47F2C4, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s41_dword_47F2C0, 1, 4);
+ _s41_dword_47F2C4 = _s41_dword_47F2C0;
+ _s41_dword_47F2C0 = -1;
+ _timers[5] = getRandom(30) + 20;
+ _gnapActionStatus = -1;
+ }
+ break;
+ case 6:
+ if (_gameSys->getAnimationStatus(3) == 2 && _gameSys->getAnimationStatus(4) == 2) {
+ _timers[2] = getRandom(30) + 20;
+ _timers[3] = getRandom(50) + 200;
+ _gameSys->insertSequence(0x124, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x124;
+ _gnapSequenceDatNum = 0;
+ _gameSys->setAnimation(0x124, _gnapId, 0);
+ _s41_dword_47F2C8 = 0x112;
+ _gameSys->insertSequence(0x112, 1, _s41_dword_47F2CC, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s41_dword_47F2C8, 1, 3);
+ _s41_dword_47F2CC = _s41_dword_47F2C8;
+ _s41_dword_47F2C8 = -1;
+ _timers[4] = getRandom(100) + 100;
+ _s41_dword_47F2C0 = 0x11C;
+ _gameSys->insertSequence(0x11C, 1, _s41_dword_47F2C4, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s41_dword_47F2C0, 1, 4);
+ _s41_dword_47F2C4 = _s41_dword_47F2C0;
+ _s41_dword_47F2C0 = -1;
+ _timers[5] = getRandom(30) + 20;
+ _gnapActionStatus = -1;
+ clearFlag(12);
+ scene41_updateHotspots();
+ }
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ switch (_toyUfoActionStatus) {
+ case 7:
+ _sceneDone = true;
+ break;
+ case 9:
+ _toyUfoNextSequenceId = 0x873;
+ _gameSys->insertSequence(0x10873, _toyUfoId, _toyUfoSequenceId | 0x10000, _toyUfoId,
+ kSeqSyncWait, 0, _toyUfoX - 365, _toyUfoY - 128);
+ _toyUfoSequenceId = _toyUfoNextSequenceId;
+ _gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 2);
+ toyUfoSetStatus(17);
+ break;
+ default:
+ _toyUfoNextSequenceId = toyUfoGetSequenceId();
+ _gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, _toyUfoId + 1, _toyUfoSequenceId | 0x10000, _toyUfoId,
+ kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128);
+ _toyUfoSequenceId = _toyUfoNextSequenceId;
+ ++_toyUfoId;
+ _gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 2);
+ break;
+ }
+ _toyUfoActionStatus = -1;
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2 && _s41_dword_47F2C8 != -1) {
+ _gameSys->insertSequence(_s41_dword_47F2C8, 1, _s41_dword_47F2CC, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s41_dword_47F2C8, 1, 3);
+ _s41_dword_47F2CC = _s41_dword_47F2C8;
+ _s41_dword_47F2C8 = -1;
+ _timers[4] = getRandom(100) + 100;
+ }
+
+ if (_gameSys->getAnimationStatus(4) == 2 && _s41_dword_47F2C0 != -1) {
+ _gameSys->insertSequence(_s41_dword_47F2C0, 1, _s41_dword_47F2C4, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s41_dword_47F2C0, 1, 4);
+ _s41_dword_47F2C4 = _s41_dword_47F2C0;
+ _s41_dword_47F2C0 = -1;
+ _timers[5] = getRandom(30) + 20;
+ if (_s41_dword_47F2C4 == 0x11E) {
+ _toyUfoActionStatus = 8;
+ toyUfoFlyTo(getRandom(300) + 500, getRandom(225) + 75, 0, 799, 0, 300, 2);
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene42.cpp b/engines/gnap/scenes/scene42.cpp
new file mode 100644
index 0000000000..2f98a820a2
--- /dev/null
+++ b/engines/gnap/scenes/scene42.cpp
@@ -0,0 +1,494 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitUfoParty = 1,
+ kHSExitToyStand = 2,
+ kHSExitUfo = 3,
+ kHSBBQVendor = 4,
+ kHSChickenLeg = 5,
+ kHSDevice = 6,
+ kHSWalkArea1 = 7,
+ kHSWalkArea2 = 8
+};
+
+enum {
+ kHSUfoExitLeft = 1,
+ kHSUfoExitRight = 2,
+ kHSUfoHotSauce = 3,
+ kHSUfoDevice = 4
+};
+
+int GnapEngine::scene42_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0, 0, 2);
+ if (isFlag(20) || (isFlag(18) && isFlag(23)))
+ return 0x153;
+ return 0x152;
+}
+
+void GnapEngine::scene42_updateHotspots() {
+ if (isFlag(12)) {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED);
+ setHotspot(kHSUfoExitLeft, 0, 0, 10, 599, SF_EXIT_L_CURSOR);
+ setHotspot(kHSUfoExitRight, 790, 0, 799, 599, SF_EXIT_R_CURSOR);
+ setHotspot(kHSUfoHotSauce, 335, 110, 440, 175, SF_DISABLED);
+ setDeviceHotspot(kHSUfoDevice, -1, 534, -1, 599);
+ if ((isFlag(20) || isFlag(18)) && isFlag(23) && !isFlag(24))
+ _hotspots[kHSUfoHotSauce].flags = SF_GRAB_CURSOR;
+ _hotspotsCount = 5;
+ } else {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitUfoParty, 150, 585, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9);
+ setHotspot(kHSExitToyStand, 0, 100, 10, 599, SF_EXIT_L_CURSOR, 0, 8);
+ setHotspot(kHSExitUfo, 790, 100, 799, 599, SF_EXIT_R_CURSOR, 10, 8);
+ setHotspot(kHSBBQVendor, 410, 200, 520, 365, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 8);
+ setHotspot(kHSChickenLeg, 530, 340, 620, 430, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 8, 7);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 445);
+ setHotspot(kHSWalkArea2, 240, 0, 550, 495);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 9;
+ }
+}
+
+void GnapEngine::scene42_run() {
+
+ queueInsertDeviceIcon();
+
+ _s42_dword_47F2B8 = 0x14A;
+ _s42_dword_47F2BC = -1;
+
+ _gameSys->setAnimation(0x14A, 1, 2);
+ _gameSys->insertSequence(_s42_dword_47F2B8, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(12)) {
+ _toyUfoId = 0;
+ _toyUfoActionStatus = -1;
+ if (_prevSceneNum == 43 && isFlag(18)) {
+ _toyUfoSequenceId = 0x872;
+ _toyUfoNextSequenceId = toyUfoGetSequenceId();
+ _gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, 0, 0);
+ _toyUfoX = 317;
+ _toyUfoY = 61;
+ toyUfoSetStatus(17);
+ setFlag(20);
+ _timers[9] = 600;
+ } else {
+ _toyUfoSequenceId = toyUfoGetSequenceId();
+ _toyUfoNextSequenceId = _toyUfoSequenceId;
+ if (_prevSceneNum == 41)
+ _toyUfoX = 30;
+ else
+ _toyUfoX = 770;
+ _gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128);
+ }
+ _gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 3);
+ endSceneInit();
+ if (_toyUfoSequenceId == 0x872)
+ setGrabCursorSprite(-1);
+ } else if (_prevSceneNum == 41) {
+ initGnapPos(-1, 8, 7);
+ initBeaverPos(-1, 9, 5);
+ endSceneInit();
+ gnapWalkTo(2, 8, -1, 0x107B9, 1);
+ platypusWalkTo(1, 8, -1, 0x107C2, 1);
+ } else if (_prevSceneNum == 43) {
+ initGnapPos(11, 8, 7);
+ initBeaverPos(11, 9, 5);
+ endSceneInit();
+ gnapWalkTo(8, 8, -1, 0x107BA, 1);
+ platypusWalkTo(9, 8, -1, 0x107D2, 1);
+ } else {
+ initGnapPos(5, 11, 7);
+ initBeaverPos(6, 11, 5);
+ endSceneInit();
+ gnapWalkTo(5, 8, -1, 0x107BA, 1);
+ platypusWalkTo(6, 8, -1, 0x107C2, 1);
+ }
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x1094B))
+ playSound(0x1094B, 1);
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ if (isFlag(12)) {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSUfoExitLeft:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = true;
+ _toyUfoActionStatus = 5;
+ _newSceneNum = 41;
+ toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 3);
+ }
+ break;
+
+ case kHSUfoExitRight:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = true;
+ _toyUfoActionStatus = 5;
+ _newSceneNum = 43;
+ toyUfoFlyTo(835, -1, 0, 835, 0, 300, 3);
+ }
+ break;
+
+ case kHSUfoHotSauce:
+ if (isFlag(17)) {
+ _toyUfoActionStatus = 7;
+ toyUfoFlyTo(384, 77, 0, 799, 0, 300, 3);
+ _timers[9] = 600;
+ } else {
+ _toyUfoActionStatus = 6;
+ toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 3);
+ }
+ break;
+
+ case kHSUfoDevice:
+ runMenu();
+ scene42_updateHotspots();
+ break;
+
+ }
+
+ } else {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ runMenu();
+ scene42_updateHotspots();
+ _timers[4] = getRandom(20) + 30;
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(_platX, _platY);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitUfoParty:
+ _isLeavingScene = true;
+ gnapWalkTo(_gnapX, _hotspotsWalkPos[kHSExitUfoParty].y, 0, 0x107AE, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_platX, _hotspotsWalkPos[kHSExitUfoParty].y, -1, 0x107C7, 1);
+ _newSceneNum = 40;
+ break;
+
+ case kHSExitToyStand:
+ _isLeavingScene = true;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitToyStand].x, _gnapY, 0, 0x107AF, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitToyStand].x, _hotspotsWalkPos[kHSExitToyStand].y, -1, 0x107CF, 1);
+ _newSceneNum = 41;
+ break;
+
+ case kHSExitUfo:
+ _isLeavingScene = true;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitUfo].x, _gnapY, 0, 0x107AB, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitUfo].x, _hotspotsWalkPos[kHSExitUfo].y, -1, 0x107CD, 1);
+ _newSceneNum = 43;
+ break;
+
+ case kHSBBQVendor:
+ if (_grabCursorSpriteIndex == kItemDiceQuarterHole) {
+ gnapWalkTo(_hotspotsWalkPos[kHSBBQVendor].x, _hotspotsWalkPos[kHSBBQVendor].y, 0, 0x107BB, 1);
+ _gnapActionStatus = 2;
+ if (_platY < 9)
+ platypusWalkTo(_platX, 9, -1, -1, 1);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSBBQVendor].x, _hotspotsWalkPos[kHSBBQVendor].y, _hotspotsWalkPos[kHSBBQVendor].x + 1, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(_hotspotsWalkPos[kHSBBQVendor].x - 1, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[kHSBBQVendor].x, _hotspotsWalkPos[kHSBBQVendor].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = 1;
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSChickenLeg:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSChickenLeg].x, _hotspotsWalkPos[kHSChickenLeg].y, _hotspotsWalkPos[kHSChickenLeg].x - 1, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(_hotspotsWalkPos[kHSChickenLeg].x - 1, 0);
+ break;
+ case GRAB_CURSOR:
+ gnapWalkTo(_hotspotsWalkPos[kHSChickenLeg].x, _hotspotsWalkPos[kHSChickenLeg].y, 0, 0x107BC, 1);
+ _gnapActionStatus = 4;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ }
+
+ }
+
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ _mouseClickState.left = false;
+ if (isFlag(12)) {
+ _toyUfoActionStatus = 6;
+ toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 3);
+ } else {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ }
+ }
+
+ scene42_updateAnimations();
+
+ toyUfoCheckTimer();
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0 && !isFlag(12))
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0 && !isFlag(12))
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(20) + 30;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s42_dword_47F2BC == -1) {
+ _gnapRandomValue = getRandom(8);
+ switch (_gnapRandomValue) {
+ case 0:
+ _s42_dword_47F2BC = 0x14C;
+ break;
+ case 1:
+ case 2:
+ _s42_dword_47F2BC = 0x149;
+ break;
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ _s42_dword_47F2BC = 0x14D;
+ break;
+ case 7:
+ _s42_dword_47F2BC = 0x14A;
+ break;
+ }
+ if (_s42_dword_47F2BC == _s42_dword_47F2B8 && _s42_dword_47F2BC != 0x14D)
+ _s42_dword_47F2BC = -1;
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene42_updateHotspots();
+ _timers[4] = getRandom(20) + 30;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene42_updateAnimations() {
+ int sequenceId;
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ switch (_gnapActionStatus) {
+ case 0:
+ _gameSys->setAnimation(0, 0, 0);
+ _gnapActionStatus = -1;
+ _sceneDone = true;
+ break;
+ case 1:
+ _gameSys->setAnimation(0, 0, 0);
+ _gnapActionStatus = -1;
+ _s42_dword_47F2BC = 0x14B;
+ break;
+ case 3:
+ _gameSys->setAnimation(0, 0, 0);
+ setGrabCursorSprite(kItemChickenBucket);
+ _gnapActionStatus = -1;
+ break;
+ case 2:
+ case 4:
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ if (_gnapActionStatus == 2) {
+ invRemove(kItemDiceQuarterHole);
+ invAdd(kItemChickenBucket);
+ setGrabCursorSprite(-1);
+ sequenceId = 0x150;
+ _s42_dword_47F2BC = 0x148;
+ } else if (isFlag(27)) {
+ if (isFlag(28)) {
+ sequenceId = 0x7B7;
+ _s42_dword_47F2BC = 0x145;
+ } else {
+ setFlag(28);
+ sequenceId = 0x14F;
+ _s42_dword_47F2BC = 0x147;
+ }
+ } else {
+ setFlag(27);
+ sequenceId = 0x14E;
+ _s42_dword_47F2BC = 0x146;
+ }
+ if (sequenceId == 0x7B7) {
+ _gameSys->insertSequence(0x107B7, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ kSeqSyncWait, getSequenceTotalDuration(_s42_dword_47F2BC),
+ 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ _gnapSequenceDatNum = 1;
+ } else {
+ _gameSys->insertSequence(sequenceId, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceDatNum = 0;
+ }
+ _gnapSequenceId = sequenceId;
+ _gameSys->setAnimation(sequenceId | (_gnapSequenceDatNum << 16), _gnapId, 0);
+ if (_gnapActionStatus == 2)
+ _gnapActionStatus = 3;
+ else
+ _gnapActionStatus = -1;
+ _gameSys->insertSequence(_s42_dword_47F2BC, 1, _s42_dword_47F2B8, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s42_dword_47F2BC, 1, 2);
+ _s42_dword_47F2B8 = _s42_dword_47F2BC;
+ if (_s42_dword_47F2BC == 0x145)
+ _s42_dword_47F2BC = 0x14A;
+ else
+ _s42_dword_47F2BC = -1;
+ _timers[4] = getRandom(20) + 30;
+ _timers[2] = getRandom(30) + 20;
+ _timers[3] = getRandom(50) + 200;
+ }
+ break;
+ default:
+ _gameSys->setAnimation(0, 0, 0);
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2 && _s42_dword_47F2BC != -1) {
+ _gameSys->insertSequence(_s42_dword_47F2BC, 1, _s42_dword_47F2B8, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s42_dword_47F2BC, 1, 2);
+ _s42_dword_47F2B8 = _s42_dword_47F2BC;
+ _s42_dword_47F2BC = -1;
+ _timers[4] = getRandom(20) + 30;
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ switch (_toyUfoActionStatus) {
+ case 5:
+ _sceneDone = true;
+ break;
+ case 7:
+ _gameSys->insertSequence(0x10870, _toyUfoId, _toyUfoSequenceId | 0x10000, _toyUfoId, kSeqSyncWait, 0, 0, 0);
+ setFlag(24);
+ scene42_updateHotspots();
+ toyUfoSetStatus(19);
+ _toyUfoSequenceId = 0x870;
+ _gameSys->setAnimation(0x10870, _toyUfoId, 3);
+ _toyUfoActionStatus = -1;
+ _toyUfoX = 0x181;
+ _toyUfoY = 53;
+ break;
+ default:
+ if (_toyUfoSequenceId == 0x872) {
+ hideCursor();
+ addFullScreenSprite(0x13E, 255);
+ _gameSys->setAnimation(0x151, 256, 0);
+ _gameSys->insertSequence(0x151, 256, 0, 0, kSeqNone, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(0) != 2)
+ gameUpdateTick();
+ removeFullScreenSprite();
+ showCursor();
+ }
+ _toyUfoNextSequenceId = toyUfoGetSequenceId();
+ _gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, (_toyUfoId + 1) % 10, 3);
+ _gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, (_toyUfoId + 1) % 10,
+ _toyUfoSequenceId | 0x10000, _toyUfoId,
+ kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128);
+ _toyUfoSequenceId = _toyUfoNextSequenceId;
+ _toyUfoId = (_toyUfoId + 1) % 10;
+ break;
+ }
+ _toyUfoActionStatus = -1;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene43.cpp b/engines/gnap/scenes/scene43.cpp
new file mode 100644
index 0000000000..3510cb4d99
--- /dev/null
+++ b/engines/gnap/scenes/scene43.cpp
@@ -0,0 +1,484 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSDevice = 1,
+ kHSExitUfoParty = 2,
+ kHSExitBBQ = 3,
+ kHSExitKissinBooth = 4,
+ kHSTwoHeadedGuy = 5,
+ kHSKey = 6,
+ kHSUfo = 7,
+ kHSWalkArea1 = 8,
+ kHSWalkArea2 = 9
+};
+
+enum {
+ kHSUfoExitLeft = 1,
+ kHSUfoExitRight = 2,
+ kHSUfoKey = 3,
+ kHSUfoBucket = 4,
+ kHSUfoDevice = 5
+};
+
+int GnapEngine::scene43_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0, 0, 2);
+ return 0x13F;
+}
+
+void GnapEngine::scene43_updateHotspots() {
+ if (isFlag(12)) {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED);
+ setHotspot(kHSUfoExitLeft, 0, 0, 10, 599, SF_EXIT_L_CURSOR);
+ setHotspot(kHSUfoExitRight, 790, 0, 799, 599, SF_EXIT_R_CURSOR);
+ setHotspot(kHSUfoKey, 140, 170, 185, 260, SF_GRAB_CURSOR);
+ setHotspot(kHSUfoBucket, 475, 290, 545, 365, SF_DISABLED);
+ setDeviceHotspot(kHSUfoDevice, -1, 534, -1, 599);
+ if (isFlag(19))
+ _hotspots[kHSUfoBucket].flags = SF_GRAB_CURSOR;
+ // NOTE Bug in the original. Key hotspot wasn't disabled.
+ if (isFlag(14))
+ _hotspots[kHSUfoKey].flags = SF_DISABLED;
+ _hotspotsCount = 6;
+ } else {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitUfoParty, 150, 580, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9);
+ setHotspot(kHSExitBBQ, 0, 100, 10, 599, SF_EXIT_L_CURSOR, 0, 8);
+ setHotspot(kHSExitKissinBooth, 790, 100, 799, 599, SF_EXIT_R_CURSOR, 10, 8);
+ setHotspot(kHSTwoHeadedGuy, 470, 240, 700, 470, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSKey, 140, 170, 185, 260, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSUfo, 110, 0, 690, 350, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 445);
+ setHotspot(kHSWalkArea2, 465, 0, 800, 493);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(14))
+ _hotspots[kHSKey].flags = SF_DISABLED;
+ _hotspotsCount = 10;
+ }
+}
+
+void GnapEngine::scene43_run() {
+
+ queueInsertDeviceIcon();
+
+ if (!isFlag(14))
+ _gameSys->insertSequence(0x1086F, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s43_dword_47F2B0 = 0x13C;
+ _s43_dword_47F2B4 = -1;
+
+ _gameSys->setAnimation(0x13C, 1, 2);
+ _gameSys->insertSequence(_s43_dword_47F2B0, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(12)) {
+ _toyUfoId = 0;
+ _toyUfoActionStatus = -1;
+ _toyUfoSequenceId = toyUfoGetSequenceId();
+ _toyUfoNextSequenceId = _toyUfoSequenceId;
+ if (_prevSceneNum == 42)
+ _toyUfoX = 30;
+ else
+ _toyUfoX = 770;
+ _gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 3);
+ _gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128);
+ endSceneInit();
+ } else {
+ switch (_prevSceneNum) {
+ case 42:
+ initGnapPos(-1, 8, 7);
+ initBeaverPos(-1, 9, 5);
+ endSceneInit();
+ gnapWalkTo(2, 8, -1, 0x107B9, 1);
+ platypusWalkTo(1, 8, -1, 0x107C2, 1);
+ break;
+ case 44:
+ initGnapPos(11, 8, 7);
+ initBeaverPos(11, 9, 5);
+ endSceneInit();
+ gnapWalkTo(8, 8, -1, 0x107BA, 1);
+ platypusWalkTo(9, 8, -1, 0x107D2, 1);
+ break;
+ case 54:
+ initGnapPos(4, 7, 3);
+ initBeaverPos(11, 8, 5);
+ endSceneInit();
+ platypusWalkTo(9, 8, -1, 0x107D2, 1);
+ break;
+ default:
+ initGnapPos(5, 11, 7);
+ initBeaverPos(6, 11, 5);
+ endSceneInit();
+ gnapWalkTo(5, 8, -1, 0x107BA, 1);
+ platypusWalkTo(6, 8, -1, 0x107C2, 1);
+ break;
+ }
+ }
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x1094B))
+ playSound(0x1094B, 1);
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ if (isFlag(12)) {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSUfoDevice:
+ runMenu();
+ scene43_updateHotspots();
+ _timers[4] = getRandom(100) + 100;
+ break;
+
+ case kHSUfoExitLeft:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = 1;
+ _toyUfoActionStatus = 4;
+ _newSceneNum = 42;
+ toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 3);
+ }
+ break;
+
+ case kHSUfoExitRight:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = 1;
+ _toyUfoActionStatus = 4;
+ _newSceneNum = 44;
+ toyUfoFlyTo(835, -1, 0, 835, 0, 300, 3);
+ }
+ break;
+
+ case kHSUfoKey:
+ if (isFlag(17)) {
+ _toyUfoActionStatus = 6;
+ toyUfoFlyTo(163, 145, 0, 799, 0, 300, 3);
+ } else {
+ _toyUfoActionStatus = 5;
+ toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 3);
+ }
+ break;
+
+ case kHSUfoBucket:
+ _toyUfoActionStatus = 7;
+ toyUfoFlyTo(497, 143, 0, 799, 0, 300, 3);
+ _timers[9] = 600;
+ break;
+ }
+
+ } else {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ runMenu();
+ scene43_updateHotspots();
+ _timers[4] = getRandom(100) + 100;
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(_platX, _platY);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitUfoParty:
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitUfoParty].x, _hotspotsWalkPos[kHSExitUfoParty].y, 0, 0x107AE, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitUfoParty].x, _hotspotsWalkPos[kHSExitUfoParty].y, -1, 0x107C7, 1);
+ _newSceneNum = 40;
+ break;
+
+ case kHSExitBBQ:
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitBBQ].x, _gnapY, 0, 0x107AF, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitBBQ].x, _hotspotsWalkPos[kHSExitBBQ].y, -1, 0x107CF, 1);
+ _newSceneNum = 42;
+ break;
+
+ case kHSExitKissinBooth:
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitKissinBooth].x, _gnapY, 0, 0x107AB, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitKissinBooth].x, _hotspotsWalkPos[kHSExitKissinBooth].y, -1, 0x107CD, 1);
+ _newSceneNum = 44;
+ break;
+
+ case kHSTwoHeadedGuy:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(6, 8, 7, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(7, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(5, 8, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = 2;
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSKey:
+ case kHSUfo:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(3, 7, 2, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(0, 0);
+ break;
+ case GRAB_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(3, 7, 0, 67515, 1);
+ _gnapActionStatus = 1;
+ break;
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ }
+
+ }
+
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ _mouseClickState.left = false;
+ if (isFlag(12) && (_toyUfoActionStatus == 5 || _toyUfoActionStatus == -1)) {
+ _toyUfoActionStatus = 5;
+ toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 3);
+ } else {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ }
+ }
+
+ scene43_updateAnimations();
+
+ toyUfoCheckTimer();
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0 && !isFlag(12))
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0 && !isFlag(12))
+ updateGnapIdleSequence();
+ if (!_timers[4] && (!isFlag(12) || !isFlag(19))) {
+ _timers[4] = getRandom(100) + 100;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s43_dword_47F2B4 == -1) {
+ _gnapRandomValue = getRandom(5);
+ switch (_gnapRandomValue) {
+ case 0:
+ _s43_dword_47F2B4 = 0x13C;
+ break;
+ case 1:
+ _s43_dword_47F2B4 = 0x134;
+ break;
+ case 2:
+ _s43_dword_47F2B4 = 0x135;
+ break;
+ case 3:
+ _s43_dword_47F2B4 = 0x136;
+ break;
+ case 4:
+ _s43_dword_47F2B4 = 0x13A;
+ break;
+ }
+ if (_s43_dword_47F2B4 == _s43_dword_47F2B0)
+ _s43_dword_47F2B4 = -1;
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene43_updateHotspots();
+ _timers[4] = getRandom(100) + 100;
+ }
+
+ gameUpdateTick();
+
+ }
+
+ if (_newSceneNum == 54)
+ clearFlag(12);
+
+}
+
+void GnapEngine::scene43_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ switch (_gnapActionStatus) {
+ case 0:
+ _gameSys->setAnimation(0, 0, 0);
+ _sceneDone = true;
+ break;
+ case 1:
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ _timers[2] = getRandom(30) + 20;
+ _timers[3] = getRandom(50) + 200;
+ _gameSys->insertSequence(0x13D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x13D;
+ _gnapSequenceDatNum = 0;
+ _gameSys->setAnimation(0x13D, _gnapId, 0);
+ _s43_dword_47F2B4 = 0x13B;
+ _gameSys->insertSequence(0x13B, 1, _s43_dword_47F2B0, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s43_dword_47F2B4, 1, 2);
+ _s43_dword_47F2B0 = _s43_dword_47F2B4;
+ _s43_dword_47F2B4 = -1;
+ _timers[4] = getRandom(100) + 100;
+ _gnapActionStatus = -1;
+ }
+ break;
+ default:
+ _gameSys->setAnimation(0, 0, 0);
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ if (_s43_dword_47F2B0 == 0x13A) {
+ if (isFlag(19)) {
+ _s43_dword_47F2B4 = 0x13E;
+ stopSound(0x108F6);
+ } else if (getRandom(2) != 0) {
+ _s43_dword_47F2B4 = 0x137;
+ } else {
+ _s43_dword_47F2B4 = 0x138;
+ }
+ } else if (_s43_dword_47F2B0 == 0x13E) {
+ _sceneDone = true;
+ _newSceneNum = 54;
+ }
+ if (_s43_dword_47F2B4 != -1) {
+ _gameSys->insertSequence(_s43_dword_47F2B4, 1, _s43_dword_47F2B0, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s43_dword_47F2B4, 1, 2);
+ _s43_dword_47F2B0 = _s43_dword_47F2B4;
+ _s43_dword_47F2B4 = -1;
+ _timers[4] = getRandom(100) + 100;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ switch (_toyUfoActionStatus) {
+ case 4:
+ _sceneDone = true;
+ _toyUfoActionStatus = -1;
+ break;
+ case 6:
+ _gameSys->insertSequence(0x10871, _toyUfoId, _toyUfoSequenceId | 0x10000, _toyUfoId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->removeSequence(0x1086F, 1, 1);
+ setFlag(14);
+ scene43_updateHotspots();
+ toyUfoSetStatus(18);
+ _toyUfoSequenceId = 0x871;
+ _gameSys->setAnimation(0x10871, _toyUfoId, 3);
+ _toyUfoActionStatus = -1;
+ _toyUfoX = 96;
+ _toyUfoY = 131;
+ break;
+ case 7:
+ _gameSys->insertSequence(0x10874, _toyUfoId, _toyUfoSequenceId | 0x10000, _toyUfoId, kSeqSyncWait, 0, 0, 0);
+ _toyUfoSequenceId = 0x874;
+ _gameSys->setAnimation(0x10874, _toyUfoId, 3);
+ _toyUfoActionStatus = 8;
+ setFlag(17);
+ _gnapActionStatus = 3;
+ break;
+ case 8:
+ _s43_dword_47F2B4 = 0x13A;
+ _toyUfoX = 514;
+ _toyUfoY = 125;
+ toyUfoFlyTo(835, 125, 0, 835, 0, 300, 3);
+ _toyUfoActionStatus = 9;
+ break;
+ case 9:
+ // Nothing
+ break;
+ default:
+ _toyUfoNextSequenceId = toyUfoGetSequenceId();
+ _gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, _toyUfoId + 1,
+ _toyUfoSequenceId | 0x10000, _toyUfoId,
+ kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128);
+ _toyUfoSequenceId = _toyUfoNextSequenceId;
+ ++_toyUfoId;
+ _gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 3);
+ _toyUfoActionStatus = -1;
+ break;
+ }
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene44.cpp b/engines/gnap/scenes/scene44.cpp
new file mode 100644
index 0000000000..b2c711898c
--- /dev/null
+++ b/engines/gnap/scenes/scene44.cpp
@@ -0,0 +1,529 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitUfoParty = 1,
+ kHSExitUfo = 2,
+ kHSExitShow = 3,
+ kHSKissingLady = 4,
+ kHSSpring = 5,
+ kHSSpringGuy = 6,
+ kHSDevice = 7,
+ kHSWalkArea1 = 8,
+ kHSWalkArea2 = 9
+};
+
+enum {
+ kHSUfoExitLeft = 1,
+ kHSUfoExitRight = 2,
+ kHSUfoDevice = 3
+};
+
+int GnapEngine::scene44_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0, 0, 2);
+ _gameSys->setAnimation(0, 0, 3);
+ return 0xFF;
+}
+
+void GnapEngine::scene44_updateHotspots() {
+ if (isFlag(12)) {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED);
+ setHotspot(kHSUfoExitLeft, 0, 0, 10, 599, SF_EXIT_L_CURSOR);
+ setHotspot(kHSUfoExitRight, 790, 0, 799, 599, SF_EXIT_R_CURSOR);
+ setDeviceHotspot(kHSUfoDevice, -1, 534, -1, 599);
+ _hotspotsCount = 4;
+ } else {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitUfoParty, 150, 580, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9);
+ setHotspot(kHSExitUfo, 0, 100, 10, 599, SF_EXIT_L_CURSOR, 0, 8);
+ setHotspot(kHSExitShow, 790, 100, 799, 599, SF_EXIT_R_CURSOR, 10, 8);
+ setHotspot(kHSKissingLady, 300, 160, 400, 315, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 7);
+ setHotspot(kHSSpring, 580, 310, 635, 375, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8);
+ setHotspot(kHSSpringGuy, 610, 375, 690, 515, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 445);
+ setHotspot(kHSWalkArea2, 617, 0, 800, 600);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(13))
+ _hotspots[kHSKissingLady].flags = SF_DISABLED;
+ if (isFlag(15))
+ _hotspots[kHSSpring].flags = SF_DISABLED;
+ _hotspotsCount = 10;
+ }
+}
+
+void GnapEngine::scene44_run() {
+
+ queueInsertDeviceIcon();
+
+ _gameSys->insertSequence(0xF7, 0, 0, 0, kSeqLoop, 0, 0, 0);
+ _gameSys->insertSequence(0xFC, 256, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(15))
+ _s44_dword_47EB0C = 0xF8;
+ else
+ _s44_dword_47EB0C = 0xF9;
+
+ _s44_dword_47EB04 = -1;
+ _gameSys->setAnimation(_s44_dword_47EB0C, 1, 4);
+ _gameSys->insertSequence(_s44_dword_47EB0C, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(13)) {
+ if (_prevSceneNum != 50 || _sceneSavegameLoaded) {
+ _s44_dword_47EB10 = 0xF6;
+ _s44_dword_47EB08 = -1;
+ } else {
+ setGrabCursorSprite(kItemGum);
+ _s44_dword_47EB10 = 0xF5;
+ _s44_dword_47EB08 = 0xF6;
+ _gameSys->setAnimation(0xF5, 1, 2);
+ }
+ } else {
+ _s44_dword_47EB10 = 0xEC;
+ _s44_dword_47EB08 = -1;
+ _gameSys->setAnimation(0xEC, 1, 2);
+ }
+
+ _gameSys->insertSequence(_s44_dword_47EB10, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(12)) {
+ _toyUfoId = 0;
+ _toyUfoActionStatus = -1;
+ _toyUfoSequenceId = toyUfoGetSequenceId();
+ _toyUfoNextSequenceId = _toyUfoSequenceId;
+ if (_prevSceneNum == 43)
+ _toyUfoX = 30;
+ else
+ _toyUfoX = 770;
+ _gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 3);
+ _gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128);
+ endSceneInit();
+ } else {
+ switch (_prevSceneNum) {
+ case 43:
+ initGnapPos(-1, 8, 7);
+ initBeaverPos(-1, 7, 5);
+ endSceneInit();
+ gnapWalkTo(2, 8, -1, 0x107B9, 1);
+ platypusWalkTo(1, 8, -1, 0x107C2, 1);
+ break;
+ case 46:
+ initGnapPos(11, 8, 7);
+ initBeaverPos(11, 8, 5);
+ endSceneInit();
+ gnapWalkTo(6, 8, -1, 0x107BA, 1);
+ platypusWalkTo(7, 8, -1, 0x107D2, 1);
+ break;
+ case 50:
+ initGnapPos(4, 8, 1);
+ if (_sceneSavegameLoaded) {
+ initBeaverPos(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 4);
+ } else if (!isFlag(13)) {
+ _timers[0] = 50;
+ _timers[1] = 20;
+ _platX = 5;
+ _platY = 8;
+ _beaverSequenceId = 0xFD;
+ _beaverFacing = 0;
+ _beaverId = 160;
+ _beaverSequenceDatNum = 0;
+ _gameSys->insertSequence(0xFD, 160, 0, 0, kSeqNone, 0, 0, 0);
+ }
+ endSceneInit();
+ break;
+ default:
+ initGnapPos(5, 11, 7);
+ initBeaverPos(6, 11, 5);
+ endSceneInit();
+ platypusWalkTo(6, 8, -1, 0x107C2, 1);
+ gnapWalkTo(5, 8, -1, 0x107BA, 1);
+ break;
+ }
+ }
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x1094B))
+ playSound(0x1094B, 1);
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ if (isFlag(12)) {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSUfoExitLeft:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = 1;
+ _toyUfoActionStatus = 6;
+ _newSceneNum = 43;
+ toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 3);
+ }
+ break;
+
+ case kHSUfoExitRight:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = 1;
+ _toyUfoActionStatus = 6;
+ _newSceneNum = 46;
+ toyUfoFlyTo(835, -1, 0, 835, 0, 300, 3);
+ }
+ break;
+
+ case kHSUfoDevice:
+ runMenu();
+ scene44_updateHotspots();
+ _timers[4] = getRandom(20) + 20;
+ break;
+
+ }
+
+ } else if (_sceneClickedHotspot <= 9) {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ runMenu();
+ scene44_updateHotspots();
+ _timers[4] = getRandom(20) + 20;
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(_platX, _platY);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitUfoParty:
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitUfoParty].x, _hotspotsWalkPos[kHSExitUfoParty].y, 0, 0x107AE, 1);
+ _gnapActionStatus = 0;
+ _newSceneNum = 40;
+ break;
+
+ case kHSExitUfo:
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitUfo].x, _gnapY, 0, 0x107AF, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitUfo].x, _platY, -1, 0x107CF, 1);
+ _newSceneNum = 43;
+ break;
+
+ case kHSExitShow:
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitShow].x, _hotspotsWalkPos[kHSExitShow].y, 0, 0x107AB, 1);
+ _gnapActionStatus = 0;
+ _newSceneNum = 46;
+ break;
+
+ case kHSKissingLady:
+ if (_grabCursorSpriteIndex >= 0) {
+ _gnapActionStatus = 2;
+ gnapWalkTo(_hotspotsWalkPos[kHSKissingLady].x, _hotspotsWalkPos[kHSKissingLady].y, 0, -1, 9);
+ playGnapShowItem(_grabCursorSpriteIndex, _hotspotsWalkPos[kHSKissingLady].x - 1, _hotspotsWalkPos[kHSKissingLady].y);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(4, 3);
+ break;
+ case GRAB_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 5;
+ gnapWalkTo(_hotspotsWalkPos[kHSKissingLady].x, _hotspotsWalkPos[kHSKissingLady].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = 1;
+ break;
+ case PLAT_CURSOR:
+ gnapUseDeviceOnBeaver();
+ platypusWalkTo(6, 7, 1, 0x107D2, 1);
+ if (_gnapX == 7 && _gnapY == 7)
+ gnapWalkStep();
+ playGnapIdle(5, 7);
+ _beaverActionStatus = 4;
+ break;
+ }
+ }
+ break;
+
+ case kHSSpring:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSSpring].x, _hotspotsWalkPos[kHSSpring].y, 8, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(8, 7);
+ break;
+ case GRAB_CURSOR:
+ playGnapPullOutDevice(8, 0);
+ playGnapUseDevice(8, 0);
+ _s44_dword_47EB04 = 0xFB;
+ invAdd(kItemSpring);
+ setFlag(15);
+ scene44_updateHotspots();
+ break;
+ case TALK_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSSpringGuy:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSSpringGuy].x, _hotspotsWalkPos[kHSSpringGuy].y, 8, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ if (isFlag(15))
+ playGnapMoan1(8, 7);
+ else
+ playGnapScratchingHead(8, 7);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[kHSSpringGuy].x, _hotspotsWalkPos[kHSSpringGuy].y, -1, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ case kHSWalkArea2:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ }
+
+ }
+
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ _mouseClickState.left = false;
+ if (isFlag(12)) {
+ _toyUfoActionStatus = 7;
+ toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 3);
+ } else {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ }
+ }
+
+ scene44_updateAnimations();
+
+ toyUfoCheckTimer();
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0 && !isFlag(12) && _s44_dword_47EB10 != 0xF5)
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0 && !isFlag(12))
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(20) + 20;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s44_dword_47EB08 == -1) {
+ _gnapRandomValue = getRandom(20);
+ switch (_gnapRandomValue) {
+ case 0:
+ _s44_dword_47EB08 = 0xED;
+ break;
+ case 1:
+ _s44_dword_47EB08 = 0xEE;
+ break;
+ case 2:
+ _s44_dword_47EB08 = 0xF0;
+ break;
+ case 3:
+ _s44_dword_47EB08 = 0xF3;
+ break;
+ case 4:
+ _s44_dword_47EB08 = 0xF4;
+ break;
+ default:
+ _s44_dword_47EB08 = 0xEC;
+ break;
+ }
+ if (_s44_dword_47EB08 != 0xEC && _s44_dword_47EB08 == _s44_dword_47EB10)
+ _s44_dword_47EB08 = -1;
+ }
+ }
+ if (!_timers[5]) {
+ _timers[5] = getRandom(20) + 20;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s44_dword_47EB04 == -1) {
+ _gnapRandomValue = getRandom(5);
+ if (_gnapRandomValue != 0) {
+ if (!isFlag(15))
+ _s44_dword_47EB04 = 0xF9;
+ } else {
+ if (isFlag(15))
+ _s44_dword_47EB04 = 0xF8;
+ else
+ _s44_dword_47EB04 = 0xFA;
+ }
+ }
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene44_updateHotspots();
+ _timers[4] = getRandom(20) + 20;
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene44_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case 0:
+ _sceneDone = true;
+ break;
+ case 1:
+ _s44_dword_47EB08 = 0xEF;
+ break;
+ case 2:
+ _s44_dword_47EB08 = 0xF2;
+ break;
+ }
+ _gnapActionStatus = -1;
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ _gameSys->setAnimation(0, 0, 1);
+ switch (_beaverActionStatus) {
+ case 4:
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ _gameSys->insertSequence(0xFE, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0);
+ _beaverSequenceId = 0xFE;
+ _beaverSequenceDatNum = 0;
+ _gameSys->setAnimation(0xFE, _beaverId, 1);
+ _gameSys->removeSequence(_s44_dword_47EB10, 1, 1);
+ _beaverActionStatus = 5;
+ }
+ break;
+ case 5:
+ _sceneDone = true;
+ _newSceneNum = 50;
+ break;
+ default:
+ _beaverActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ if (_s44_dword_47EB08 == 0xF6) {
+ _gameSys->insertSequence(_s44_dword_47EB08, 1, _s44_dword_47EB10, 1, kSeqSyncWait, 0, 0, 0);
+ initBeaverPos(5, 8, 0);
+ _s44_dword_47EB10 = _s44_dword_47EB08;
+ _s44_dword_47EB08 = -1;
+ _gameSys->setAnimation(0, 0, 2);
+ } else if (_s44_dword_47EB08 != -1) {
+ _gameSys->insertSequence(_s44_dword_47EB08, 1, _s44_dword_47EB10, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s44_dword_47EB08, 1, 2);
+ _s44_dword_47EB10 = _s44_dword_47EB08;
+ _s44_dword_47EB08 = -1;
+ _timers[4] = getRandom(20) + 20;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(4) == 2) {
+ if (_s44_dword_47EB0C == 0xFB) {
+ setGrabCursorSprite(kItemSpring);
+ _s44_dword_47EB04 = 0xF8;
+ }
+ if (_s44_dword_47EB04 != -1) {
+ _gameSys->insertSequence(_s44_dword_47EB04, 1, _s44_dword_47EB0C, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s44_dword_47EB04, 1, 4);
+ _s44_dword_47EB0C = _s44_dword_47EB04;
+ _s44_dword_47EB04 = -1;
+ _timers[5] = getRandom(20) + 20;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2) {
+ switch (_toyUfoActionStatus) {
+ case 6:
+ _sceneDone = true;
+ break;
+ default:
+ _toyUfoNextSequenceId = toyUfoGetSequenceId();
+ _gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, _toyUfoId + 1,
+ _toyUfoSequenceId | 0x10000, _toyUfoId,
+ kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128);
+ _toyUfoSequenceId = _toyUfoNextSequenceId;
+ ++_toyUfoId;
+ _gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 3);
+ break;
+ }
+ _toyUfoActionStatus = -1;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene45.cpp b/engines/gnap/scenes/scene45.cpp
new file mode 100644
index 0000000000..ba583045e5
--- /dev/null
+++ b/engines/gnap/scenes/scene45.cpp
@@ -0,0 +1,430 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitUfoParty = 1,
+ kHSExitShoe = 2,
+ kHSExitRight = 3,
+ kHSExitDiscoBall = 4,
+ kHSDiscoBall = 5,
+ kHSDevice = 6,
+ kHSWalkArea1 = 7
+};
+
+enum {
+ kHSUfoExitLeft = 1,
+ kHSUfoExitRight = 2,
+ kHSUfoDevice = 3
+};
+
+int GnapEngine::scene45_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0, 0, 2);
+ _gameSys->setAnimation(0, 0, 3);
+ _gameSys->setAnimation(0, 0, 4);
+ _gameSys->setAnimation(0, 0, 5);
+ return isFlag(23) ? 0xA2 : 0xA1;
+}
+
+void GnapEngine::scene45_updateHotspots() {
+ if (isFlag(12)) {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED);
+ setHotspot(kHSUfoExitLeft, 0, 0, 10, 599, SF_EXIT_L_CURSOR);
+ setHotspot(kHSUfoExitRight, 794, 0, 799, 599, SF_EXIT_R_CURSOR | SF_DISABLED);
+ setDeviceHotspot(kHSUfoDevice, -1, 534, -1, 599);
+ _hotspotsCount = 4;
+ } else {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitUfoParty, 150, 580, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9);
+ setHotspot(kHSExitShoe, 0, 100, 10, 599, SF_EXIT_L_CURSOR, 0, 8);
+ setHotspot(kHSExitRight, 794, 100, 799, 599, SF_EXIT_R_CURSOR | SF_DISABLED, 10, 8);
+ setHotspot(kHSExitDiscoBall, 200, 0, 600, 10, SF_DISABLED);
+ setHotspot(kHSDiscoBall, 370, 10, 470, 125, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 7);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 472);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ if (isFlag(22)) {
+ _hotspots[kHSPlatypus].flags = SF_DISABLED;
+ _hotspots[kHSExitUfoParty].flags = SF_DISABLED;
+ _hotspots[kHSExitShoe].flags = SF_DISABLED;
+ _hotspots[kHSExitRight].flags = SF_DISABLED;
+ _hotspots[kHSExitDiscoBall].flags = SF_EXIT_U_CURSOR;
+ }
+ if (isFlag(23) || isFlag(22))
+ _hotspots[kHSDiscoBall].flags = SF_DISABLED;
+ _hotspotsCount = 8;
+ }
+}
+
+void GnapEngine::scene45_run() {
+
+ if (!isSoundPlaying(0x1094A))
+ playSound(0x1094A, 1);
+
+ queueInsertDeviceIcon();
+
+ _gameSys->insertSequence(0x96, 1, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->setAnimation(0x96, 1, 3);
+ _gameSys->insertSequence(0x99, 1, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->setAnimation(0x99, 1, 4);
+ _s45_dword_4749BC = 0x8F;
+ _gameSys->setAnimation(0x8F, 1, 2);
+ _gameSys->insertSequence(_s45_dword_4749BC, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(12)) {
+ _toyUfoId = 0;
+ _toyUfoActionStatus = -1;
+ _toyUfoSequenceId = toyUfoGetSequenceId();
+ _toyUfoNextSequenceId = _toyUfoSequenceId;
+ if (_prevSceneNum == 46)
+ _toyUfoX = 30;
+ else
+ _toyUfoX = 770;
+ _gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 5);
+ _gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128);
+ endSceneInit();
+ } else if (isFlag(22)) {
+ _gnapSequenceId = 0x9E;
+ _gnapSequenceDatNum = 0;
+ _gnapId = 1;
+ _gameSys->setAnimation(0x9E, 1, 0);
+ _gnapActionStatus = 1;
+ _gameSys->insertSequence(_gnapSequenceId, _gnapId, 0, 0, kSeqNone, 0, 0, 0);
+ initBeaverPos(4, 8, 0);
+ endSceneInit();
+ } else if (_prevSceneNum == 46) {
+ initGnapPos(-1, 8, 7);
+ initBeaverPos(-1, 9, 5);
+ endSceneInit();
+ platypusWalkTo(4, 8, -1, 0x107C2, 1);
+ gnapWalkTo(2, 7, -1, 0x107B9, 1);
+ } else if (_prevSceneNum == 41) {
+ initGnapPos(11, 8, 7);
+ initBeaverPos(11, 9, 5);
+ endSceneInit();
+ platypusWalkTo(4, 8, -1, 0x107D2, 1);
+ gnapWalkTo(10, 9, -1, 0x107BA, 1);
+ } else {
+ initGnapPos(2, 11, 7);
+ initBeaverPos(6, 11, 5);
+ endSceneInit();
+ platypusWalkTo(4, 8, -1, 0x107C2, 1);
+ gnapWalkTo(2, 7, -1, 0x107B9, 1);
+ }
+
+ if (!isFlag(21) && !isFlag(12)) {
+ setFlag(21);
+ setGrabCursorSprite(-1);
+ _gameSys->setAnimation(0x9D, _gnapId, 0);
+ _gameSys->insertSequence(0x9D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(0) != 2) {
+ gameUpdateTick();
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ _gameSys->setAnimation(0, 0, 2);
+ _gnapRandomValue = getRandom(7);
+ _s45_dword_4749C0 = _gnapRandomValue + 0x8F;
+ _gameSys->insertSequence(_gnapRandomValue + 0x8F, 1, _s45_dword_4749BC, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s45_dword_4749C0, 1, 2);
+ _s45_dword_4749BC = _s45_dword_4749C0;
+ }
+ if (_gameSys->getAnimationStatus(3) == 2 && _gameSys->getAnimationStatus(4) == 2) {
+ _gameSys->insertSequence(0x96, 1, 0x96, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x96, 1, 3);
+ _gameSys->insertSequence(0x99, 1, 0x99, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x99, 1, 4);
+ }
+ }
+ _gnapSequenceId = 0x9D;
+ _gnapSequenceDatNum = 0;
+ hideCursor();
+ addFullScreenSprite(0x8A, 255);
+ _gameSys->setAnimation(0xA0, 256, 0);
+ _gameSys->insertSequence(0xA0, 256, 0, 0, kSeqNone, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(0) != 2)
+ gameUpdateTick();
+ _gameSys->setAnimation(0x107BD, _gnapId, 0);
+ _gameSys->insertSequence(0x107BD, _gnapId,
+ makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId,
+ kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY);
+ removeFullScreenSprite();
+ showCursor();
+ _gnapSequenceId = 0x7BD;
+ _gnapSequenceDatNum = 1;
+ }
+
+ playBeaverSequence(0x9A);
+ _gameSys->setAnimation(_beaverSequenceId, _beaverId, 1);
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x1094A))
+ playSound(0x1094A, 1);
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ if (isFlag(12)) {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSUfoExitLeft:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = 1;
+ _toyUfoActionStatus = 2;
+ _newSceneNum = 46;
+ toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 5);
+ }
+ break;
+
+ case kHSUfoExitRight:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = 1;
+ _toyUfoActionStatus = 2;
+ _newSceneNum = 41;
+ toyUfoFlyTo(835, -1, 0, 835, 0, 300, 5);
+ }
+ break;
+
+ case kHSUfoDevice:
+ runMenu();
+ scene45_updateHotspots();
+ break;
+
+ }
+
+ } else {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ runMenu();
+ scene45_updateHotspots();
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ playBeaverSequence(0x9A);
+ _gameSys->setAnimation(_beaverSequenceId, _beaverId, 1);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(_platX, _platY);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSExitUfoParty:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_gnapX, _hotspotsWalkPos[kHSExitUfoParty].y, 0, 0x107AE, 1);
+ _gnapActionStatus = 0;
+ _newSceneNum = 40;
+ }
+ break;
+
+ case kHSExitShoe:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitShoe].x, _gnapY, 0, 0x107AF, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitShoe].x, _platY, -1, 0x107CF, 1);
+ _newSceneNum = 46;
+ }
+ break;
+
+ case kHSExitRight:
+ if (_gnapActionStatus < 0) {
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitRight].x, _gnapY, 0, 0x107AB, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitRight].x, _platY, -1, 0x107CD, 1);
+ _newSceneNum = 41;
+ }
+ break;
+
+ case kHSExitDiscoBall:
+ clearFlag(22);
+ setFlag(23);
+ _sceneDone = true;
+ _newSceneNum = 54;
+ break;
+
+ case kHSDiscoBall:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex == kItemSpring) {
+ gnapWalkTo(_hotspotsWalkPos[kHSDiscoBall].x, _hotspotsWalkPos[kHSDiscoBall].y, 0, 0x9F, 5);
+ _gnapActionStatus = 1;
+ setGrabCursorSprite(-1);
+ invRemove(kItemSpring);
+ } else if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowItem(_grabCursorSpriteIndex, 5, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapScratchingHead(5, 0);
+ break;
+ case GRAB_CURSOR:
+ case TALK_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSWalkArea1:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ }
+
+ }
+
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ _mouseClickState.left = false;
+ if (isFlag(12)) {
+ _toyUfoActionStatus = 3;
+ toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 5);
+ } else {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ }
+ }
+
+ scene45_updateAnimations();
+ toyUfoCheckTimer();
+
+ if (!_isLeavingScene && _gnapActionStatus < 0 && !isFlag(12))
+ updateGnapIdleSequence();
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene45_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+ _sceneWaiting = 0;
+
+}
+
+void GnapEngine::scene45_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case 0:
+ _sceneDone = true;
+ break;
+ case 1:
+ _sceneWaiting = 1;
+ setFlag(22);
+ scene45_updateHotspots();
+ _gameSys->insertSequence(0x9E, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0);
+ _gnapSequenceId = 0x9E;
+ _gnapSequenceDatNum = 0;
+ _gameSys->setAnimation(0x9E, _gnapId, 0);
+ break;
+ default:
+ _gnapActionStatus = -1;
+ break;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ _gameSys->setAnimation(0, 0, 1);
+ if (getRandom(2) != 0)
+ playBeaverSequence(0x9B);
+ else
+ playBeaverSequence(0x9C);
+ _gameSys->setAnimation(_beaverSequenceId, _beaverId, 1);
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ _gameSys->setAnimation(0, 0, 2);
+ _gnapRandomValue = getRandom(7);
+ _s45_dword_4749C0 = _gnapRandomValue + 0x8F;
+ _gameSys->insertSequence(_gnapRandomValue + 0x8F, 1, _s45_dword_4749BC, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s45_dword_4749C0, 1, 2);
+ _s45_dword_4749BC = _s45_dword_4749C0;
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2 && _gameSys->getAnimationStatus(4) == 2) {
+ _gameSys->insertSequence(0x96, 1, 0x96, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x96, 1, 3);
+ _gameSys->insertSequence(0x99, 1, 0x99, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0x99, 1, 4);
+ }
+
+ if (_gameSys->getAnimationStatus(5) == 2) {
+ switch (_toyUfoActionStatus) {
+ case 2:
+ _sceneDone = true;
+ break;
+ default:
+ _toyUfoNextSequenceId = toyUfoGetSequenceId();
+ _gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, _toyUfoId + 1,
+ _toyUfoSequenceId | 0x10000, _toyUfoId,
+ kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128);
+ _toyUfoSequenceId = _toyUfoNextSequenceId;
+ ++_toyUfoId;
+ _gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 5);
+ break;
+ }
+ _toyUfoActionStatus = -1;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene46.cpp b/engines/gnap/scenes/scene46.cpp
new file mode 100644
index 0000000000..86855bbdf2
--- /dev/null
+++ b/engines/gnap/scenes/scene46.cpp
@@ -0,0 +1,378 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+enum {
+ kHSPlatypus = 0,
+ kHSExitUfoParty = 1,
+ kHSExitKissinBooth = 2,
+ kHSExitDisco = 3,
+ kHSSackGuy = 4,
+ kHSItchyGuy = 5,
+ kHSDevice = 6,
+ kHSWalkArea1 = 7
+};
+
+enum {
+ kHSUfoExitLeft = 1,
+ kHSUfoExitRight = 2,
+ kHSUfoDevice = 3
+};
+
+int GnapEngine::scene46_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ _gameSys->setAnimation(0, 0, 2);
+ _gameSys->setAnimation(0, 0, 3);
+ _gameSys->setAnimation(0, 0, 4);
+ return 0x4E;
+}
+
+void GnapEngine::scene46_updateHotspots() {
+ if (isFlag(12)) {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED);
+ setHotspot(kHSUfoExitLeft, 0, 0, 10, 599, SF_EXIT_L_CURSOR);
+ setHotspot(kHSUfoExitRight, 790, 0, 799, 599, SF_EXIT_R_CURSOR);
+ setDeviceHotspot(kHSUfoDevice, -1, 534, -1, 599);
+ _hotspotsCount = 4;
+ } else {
+ setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(kHSExitUfoParty, 150, 580, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9);
+ setHotspot(kHSExitKissinBooth, 0, 100, 10, 599, SF_EXIT_L_CURSOR, 0, 8);
+ setHotspot(kHSExitDisco, 790, 100, 799, 599, SF_EXIT_R_CURSOR, 10, 8);
+ setHotspot(kHSSackGuy, 180, 370, 235, 490, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 8);
+ setHotspot(kHSItchyGuy, 535, 210, 650, 480, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 8);
+ setHotspot(kHSWalkArea1, 0, 0, 800, 485);
+ setDeviceHotspot(kHSDevice, -1, -1, -1, -1);
+ _hotspotsCount = 8;
+ }
+}
+
+void GnapEngine::scene46_run() {
+
+ queueInsertDeviceIcon();
+
+ _gameSys->insertSequence(0x4D, 0, 0, 0, kSeqLoop, 0, 0, 0);
+
+ _s46_dword_47EB18 = 0x4B;
+ _s46_dword_47EB20 = -1;
+ _gameSys->setAnimation(0x4B, 1, 3);
+ _gameSys->insertSequence(_s46_dword_47EB18, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ _s46_dword_47EB24 = 0x47;
+ _s46_dword_47EB1C = -1;
+ _gameSys->setAnimation(0x47, 1, 4);
+ _gameSys->insertSequence(_s46_dword_47EB24, 1, 0, 0, kSeqNone, 0, 0, 0);
+
+ if (isFlag(12)) {
+ _toyUfoId = 0;
+ _toyUfoActionStatus = -1;
+ _toyUfoSequenceId = toyUfoGetSequenceId();
+ _toyUfoNextSequenceId = _toyUfoSequenceId;
+ if (_prevSceneNum == 44)
+ _toyUfoX = 30;
+ else
+ _toyUfoX = 770;
+ _gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 2);
+ _gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128);
+ endSceneInit();
+ } else if (_prevSceneNum == 44) {
+ initGnapPos(-1, 8, 7);
+ initBeaverPos(-1, 8, 5);
+ endSceneInit();
+ platypusWalkTo(1, 8, -1, 0x107C2, 1);
+ gnapWalkTo(2, 8, -1, 0x107B9, 1);
+ } else if (_prevSceneNum == 45) {
+ initGnapPos(11, 8, 7);
+ initBeaverPos(12, 8, 5);
+ endSceneInit();
+ gnapWalkTo(8, 8, -1, 0x107BA, 1);
+ platypusWalkTo(9, 8, -1, 0x107D2, 1);
+ } else {
+ initGnapPos(5, 11, 7);
+ initBeaverPos(6, 11, 5);
+ endSceneInit();
+ platypusWalkTo(5, 8, -1, 0x107C2, 1);
+ gnapWalkTo(6, 8, -1, 0x107BA, 1);
+ }
+
+ _timers[4] = getRandom(50) + 80;
+ _timers[5] = getRandom(50) + 80;
+
+ while (!_sceneDone) {
+
+ if (!isSoundPlaying(0x1094B))
+ playSound(0x1094B, 1);
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ if (isFlag(12)) {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSUfoExitLeft:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = 1;
+ _toyUfoActionStatus = 3;
+ _newSceneNum = 44;
+ toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 2);
+ }
+ break;
+
+ case kHSUfoExitRight:
+ if (_toyUfoActionStatus < 0) {
+ _isLeavingScene = 1;
+ _toyUfoActionStatus = 3;
+ _newSceneNum = 45;
+ toyUfoFlyTo(835, -1, 0, 835, 0, 300, 2);
+ }
+ break;
+
+ case kHSUfoDevice:
+ runMenu();
+ scene46_updateHotspots();
+ break;
+ }
+
+ } else {
+
+ switch (_sceneClickedHotspot) {
+
+ case kHSDevice:
+ runMenu();
+ scene46_updateHotspots();
+ break;
+
+ case kHSPlatypus:
+ if (_gnapActionStatus < 0) {
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapImpossible(_platX, _platY);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_platX, _platY);
+ break;
+ case GRAB_CURSOR:
+ gnapKissPlatypus(0);
+ break;
+ case TALK_CURSOR:
+ playGnapBrainPulsating(_platX, _platY);
+ playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000);
+ break;
+ case PLAT_CURSOR:
+ playGnapImpossible(_platX, _platY);
+ break;
+ }
+ }
+ }
+ break;
+
+ case kHSSackGuy:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSSackGuy].x, _hotspotsWalkPos[kHSSackGuy].y, 2, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_hotspotsWalkPos[kHSSackGuy].x + 1, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 5;
+ gnapWalkTo(_hotspotsWalkPos[kHSSackGuy].x, _hotspotsWalkPos[kHSSackGuy].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = 2;
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSItchyGuy:
+ if (_grabCursorSpriteIndex >= 0) {
+ playGnapShowCurrItem(_hotspotsWalkPos[kHSItchyGuy].x, _hotspotsWalkPos[kHSItchyGuy].y, 7, 0);
+ } else {
+ switch (_verbCursor) {
+ case LOOK_CURSOR:
+ playGnapMoan1(_hotspotsWalkPos[kHSItchyGuy].x - 1, 0);
+ break;
+ case TALK_CURSOR:
+ _gnapIdleFacing = 7;
+ gnapWalkTo(_hotspotsWalkPos[kHSItchyGuy].x, _hotspotsWalkPos[kHSItchyGuy].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1);
+ _gnapActionStatus = 1;
+ break;
+ case GRAB_CURSOR:
+ case PLAT_CURSOR:
+ playGnapImpossible(0, 0);
+ break;
+ }
+ }
+ break;
+
+ case kHSExitUfoParty:
+ _isLeavingScene = 1;
+ gnapWalkTo(_gnapX, _hotspotsWalkPos[kHSExitUfoParty].y, 0, 0x107AE, 1);
+ _gnapActionStatus = 0;
+ _newSceneNum = 40;
+ break;
+
+ case kHSExitKissinBooth:
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitKissinBooth].x, _gnapY, 0, 0x107AF, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitKissinBooth].x, _platY, -1, 0x107CF, 1);
+ _newSceneNum = 44;
+ break;
+
+ case kHSExitDisco:
+ _isLeavingScene = 1;
+ gnapWalkTo(_hotspotsWalkPos[kHSExitDisco].x, _gnapY, 0, 0x107AB, 1);
+ _gnapActionStatus = 0;
+ platypusWalkTo(_hotspotsWalkPos[kHSExitDisco].x, _platY, -1, 0x107CD, 1);
+ _newSceneNum = 45;
+ break;
+
+ case kHSWalkArea1:
+ if (_gnapActionStatus < 0)
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ break;
+
+ }
+
+ }
+
+ if (_mouseClickState.left && _gnapActionStatus < 0) {
+ _mouseClickState.left = false;
+ if (isFlag(12)) {
+ _toyUfoActionStatus = 4;
+ toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 2);
+ } else {
+ gnapWalkTo(-1, -1, -1, -1, 1);
+ }
+ }
+
+ scene46_updateAnimations();
+
+ toyUfoCheckTimer();
+
+ if (!_isLeavingScene) {
+ if (_beaverActionStatus < 0 && !isFlag(12))
+ updateBeaverIdleSequence();
+ if (_gnapActionStatus < 0 && !isFlag(12))
+ updateGnapIdleSequence();
+ if (!_timers[4]) {
+ _timers[4] = getRandom(50) + 80;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s46_dword_47EB1C == -1) {
+ _gnapRandomValue = getRandom(2);
+ if (_gnapRandomValue != 0)
+ _s46_dword_47EB1C = 0x49;
+ else
+ _s46_dword_47EB1C = 0x48;
+ }
+ }
+ if (!_timers[5]) {
+ _timers[5] = getRandom(50) + 80;
+ if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s46_dword_47EB20 == -1)
+ _s46_dword_47EB20 = 0x4C;
+ }
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene46_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+void GnapEngine::scene46_updateAnimations() {
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ _gameSys->setAnimation(0, 0, 0);
+ switch (_gnapActionStatus) {
+ case 0:
+ _sceneDone = true;
+ break;
+ case 1:
+ _s46_dword_47EB1C = 0x46;
+ break;
+ case 2:
+ _s46_dword_47EB20 = 0x4A;
+ break;
+ }
+ _gnapActionStatus = -1;
+ }
+
+ if (_gameSys->getAnimationStatus(3) == 2 && _s46_dword_47EB20 != -1) {
+ _gameSys->insertSequence(_s46_dword_47EB20, 1, _s46_dword_47EB18, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s46_dword_47EB20, 1, 3);
+ _s46_dword_47EB18 = _s46_dword_47EB20;
+ _s46_dword_47EB20 = -1;
+ _timers[5] = getRandom(50) + 80;
+ }
+
+ if (_gameSys->getAnimationStatus(4) == 2 && _s46_dword_47EB1C != -1) {
+ _gameSys->insertSequence(_s46_dword_47EB1C, 1, _s46_dword_47EB24, 1, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(_s46_dword_47EB1C, 1, 4);
+ _s46_dword_47EB24 = _s46_dword_47EB1C;
+ _s46_dword_47EB1C = -1;
+ _timers[4] = getRandom(50) + 80;
+ }
+
+ if (_gameSys->getAnimationStatus(2) == 2) {
+ switch (_toyUfoActionStatus) {
+ case 3:
+ _sceneDone = true;
+ break;
+ default:
+ _toyUfoNextSequenceId = toyUfoGetSequenceId();
+ _gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, _toyUfoId + 1,
+ _toyUfoSequenceId | 0x10000, _toyUfoId,
+ kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128);
+ _toyUfoSequenceId = _toyUfoNextSequenceId;
+ ++_toyUfoId;
+ _gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 2);
+ break;
+ }
+ _toyUfoActionStatus = -1;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene47.cpp b/engines/gnap/scenes/scene47.cpp
new file mode 100644
index 0000000000..2e735e3650
--- /dev/null
+++ b/engines/gnap/scenes/scene47.cpp
@@ -0,0 +1,171 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+void GnapEngine::scene47_initCutscene1() {
+ _s99_dword_47F370[0] = 0x301;
+ _s99_dword_47F370[1] = 0x305;
+ _s99_dword_47F370[2] = 0x302;
+ _s99_dword_47F370[3] = 0x304;
+ _s99_dword_47F370[4] = 0x300;
+ _s99_dword_47F2F0[0] = 3;
+ _s99_dword_47F2F0[1] = 0;
+ _s99_dword_47F2F0[2] = 1;
+ _s99_dword_47F2F0[3] = 0;
+ _s99_dword_47F2F0[4] = 2;
+ _s99_dword_47F330[0] = 1;
+ _s99_dword_47F330[1] = 1;
+ _s99_dword_47F330[2] = 1;
+ _s99_dword_47F330[3] = 1;
+ _s99_dword_47F330[4] = 1;
+ _s99_canSkip[0] = 0;
+ _s99_canSkip[1] = 0;
+ _s99_canSkip[2] = 0;
+ _s99_canSkip[3] = 0;
+ _s99_canSkip[4] = 0;
+ _s99_itemsCount = 5;
+}
+
+void GnapEngine::scene47_initCutscene2() {
+ _s99_dword_47F370[0] = 0x306;
+ _s99_dword_47F370[1] = 0x309;
+ _s99_dword_47F370[2] = 0x307;
+ _s99_dword_47F370[3] = 0x308;
+ _s99_dword_47F370[4] = 0x30A;
+ _s99_dword_47F2F0[0] = 0x8E;
+ _s99_dword_47F2F0[1] = 0x90;
+ _s99_dword_47F2F0[2] = 0x8F;
+ _s99_dword_47F2F0[3] = 0x91;
+ _s99_dword_47F330[0] = 2;
+ _s99_dword_47F330[1] = 1;
+ _s99_dword_47F330[2] = 1;
+ _s99_dword_47F330[3] = 1;
+ _s99_canSkip[0] = 0;
+ _s99_canSkip[1] = 0;
+ _s99_canSkip[2] = 0;
+ _s99_canSkip[3] = 0;
+ _s99_itemsCount = 4;
+}
+
+void GnapEngine::scene47_initCutscene3() {
+ _s99_dword_47F370[0] = 0x320;
+ _s99_dword_47F370[1] = 0x321;
+ _s99_dword_47F2F0[0] = 0x142;
+ _s99_dword_47F2F0[1] = 0x143;
+ _s99_dword_47F330[0] = 1;
+ _s99_dword_47F330[1] = 1;
+ _s99_canSkip[0] = 0;
+ _s99_canSkip[1] = 0;
+ _s99_itemsCount = 2;
+}
+
+void GnapEngine::scene47_initCutscene4() {
+ _s99_dword_47F370[0] = 0x30C;
+ _s99_dword_47F370[1] = 0x30D;
+ _s99_dword_47F370[2] = 0x30B;
+ _s99_dword_47F2F0[0] = 0x142;
+ _s99_dword_47F2F0[1] = 0x141;
+ _s99_dword_47F2F0[2] = 0x177;
+ _s99_dword_47F330[0] = 1;
+ _s99_dword_47F330[1] = 1;
+ _s99_dword_47F330[2] = 1;
+ _s99_canSkip[0] = 0;
+ _s99_canSkip[1] = 0;
+ _s99_canSkip[2] = 0;
+ _s99_itemsCount = 3;
+}
+
+void GnapEngine::scene47_initCutscene5() {
+ _s99_dword_47F370[0] = 0x30E;
+ _s99_dword_47F370[1] = 0x30F;
+ _s99_dword_47F370[2] = 0x310;
+ _s99_dword_47F370[3] = 0x311;
+ _s99_dword_47F2F0[0] = 0x206;
+ _s99_dword_47F2F0[1] = 0x207;
+ _s99_dword_47F330[0] = 3;
+ _s99_dword_47F330[1] = 1;
+ _s99_canSkip[0] = 0;
+ _s99_canSkip[1] = 0;
+ _s99_itemsCount = 2;
+}
+
+void GnapEngine::scene47_initCutscene6() {
+ _s99_dword_47F370[0] = 0x31E;
+ _s99_dword_47F370[1] = 0x31F;
+ _s99_dword_47F2F0[0] = 0x2FA;
+ _s99_dword_47F330[0] = 2;
+ _s99_canSkip[0] = 0;
+ _s99_itemsCount = 1;
+}
+
+void GnapEngine::scene47_initCutscene7() {
+ int v1 = 4, v0, v4, v2, v3;
+
+ _s99_dword_47F370[0] = 0x316;
+ _s99_dword_47F370[1] = 0x31A;
+ _s99_dword_47F370[2] = 0x314;
+ _s99_dword_47F370[3] = 0x31B;
+ v1 = 4;
+ if (!isFlag(3)) {
+ _s99_dword_47F370[4] = 0x31C;
+ v1 = 5;
+ }
+ if (!isFlag(26))
+ _s99_dword_47F370[v1++] = 0x31D;
+ v4 = v1;
+ _s99_dword_47F370[v1] = 0x319;
+ v0 = v1 + 1;
+ v3 = v0;
+ _s99_dword_47F370[v0++] = 0x317;
+ _s99_dword_47F370[v0++] = 0x312;
+ _s99_dword_47F370[v0] = 0x31A;
+ v2 = v0 + 1;
+ if (!isFlag(3))
+ _s99_dword_47F370[v2++] = 0x31C;
+ if (!isFlag(26))
+ _s99_dword_47F370[v2++] = 0x31D;
+ _s99_dword_47F370[v2] = 0x313;
+ _s99_dword_47F370[v2 + 1] = 0x315;
+ _s99_dword_47F2F0[0] = 0x2B8;
+ _s99_dword_47F2F0[1] = 0x20C;
+ _s99_dword_47F2F0[2] = 0x2B8;
+ _s99_dword_47F2F0[3] = 0x20B;
+ _s99_dword_47F2F0[4] = 0x20B;
+ _s99_dword_47F330[0] = v4;
+ _s99_dword_47F330[1] = 1;
+ _s99_dword_47F330[2] = v2 - v3;
+ _s99_dword_47F330[3] = 1;
+ _s99_dword_47F330[4] = 1;
+ _s99_canSkip[0] = 0;
+ _s99_canSkip[1] = 0;
+ _s99_canSkip[2] = 0;
+ _s99_canSkip[3] = 0;
+ _s99_canSkip[4] = 0;
+ _s99_itemsCount = 5;
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene48.cpp b/engines/gnap/scenes/scene48.cpp
new file mode 100644
index 0000000000..3b24d57a8c
--- /dev/null
+++ b/engines/gnap/scenes/scene48.cpp
@@ -0,0 +1,85 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+void GnapEngine::scene48_initCutscene() {
+ _s99_dword_47F370[0] = 390;
+ _s99_dword_47F370[1] = 391;
+ _s99_dword_47F370[2] = 392;
+ _s99_dword_47F370[3] = 393;
+ _s99_dword_47F370[4] = 394;
+ _s99_dword_47F370[5] = 395;
+ _s99_dword_47F370[6] = 396;
+ _s99_dword_47F370[7] = 397;
+ _s99_dword_47F370[8] = 398;
+ _s99_dword_47F370[9] = 399;
+ _s99_dword_47F370[10] = 400;
+ _s99_dword_47F370[11] = 401;
+ _s99_dword_47F370[12] = 402;
+ _s99_dword_47F2F0[0] = 238;
+ _s99_dword_47F2F0[1] = 42;
+ _s99_dword_47F2F0[2] = 2;
+ _s99_dword_47F2F0[3] = 37;
+ _s99_dword_47F2F0[4] = 35;
+ _s99_dword_47F2F0[5] = 38;
+ _s99_dword_47F2F0[6] = 39;
+ _s99_dword_47F2F0[7] = 40;
+ _s99_dword_47F2F0[8] = 41;
+ _s99_dword_47F2F0[9] = 36;
+ _s99_dword_47F2F0[10] = 41;
+ _s99_dword_47F2F0[11] = 388;
+ _s99_dword_47F2F0[12] = 387;
+ _s99_dword_47F330[0] = 1;
+ _s99_dword_47F330[1] = 1;
+ _s99_dword_47F330[2] = 1;
+ _s99_dword_47F330[3] = 1;
+ _s99_dword_47F330[4] = 1;
+ _s99_dword_47F330[5] = 1;
+ _s99_dword_47F330[6] = 1;
+ _s99_dword_47F330[7] = 1;
+ _s99_dword_47F330[8] = 1;
+ _s99_dword_47F330[9] = 1;
+ _s99_dword_47F330[10] = 1;
+ _s99_dword_47F330[11] = 1;
+ _s99_dword_47F330[12] = 1;
+ _s99_canSkip[0] = 0;
+ _s99_canSkip[1] = 0;
+ _s99_canSkip[2] = 0;
+ _s99_canSkip[3] = 0;
+ _s99_canSkip[4] = 0;
+ _s99_canSkip[5] = 0;
+ _s99_canSkip[6] = 0;
+ _s99_canSkip[7] = 0;
+ _s99_canSkip[8] = 0;
+ _s99_canSkip[9] = 0;
+ _s99_canSkip[10] = 0;
+ _s99_canSkip[11] = 0;
+ _s99_canSkip[12] = 0;
+ _s99_itemsCount = 13;
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene49.cpp b/engines/gnap/scenes/scene49.cpp
new file mode 100644
index 0000000000..e8415bbc9f
--- /dev/null
+++ b/engines/gnap/scenes/scene49.cpp
@@ -0,0 +1,513 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+struct ObstacleDef {
+ int sequenceId, ticks;
+};
+
+static const ObstacleDef kObstacleDefs[] = {
+ {0xB4, 15}, {0xCB, 14}, {0xCD, 13}, {0xCF, 15}, {0xBA, 14},
+ {0xCD, 13}, {0xCF, 12}, {0xCB, 15}, {0xBD, 13}, {0xCF, 12},
+ {0xCD, 11}, {0xCB, 15}, {0xB7, 12}, {0xCD, 11}, {0xCB, 10},
+ {0xCF, 15}, {0xCF, 14}, {0xBD, 13}, {0xCF, 12}, {0xCD, 11},
+ {0xCB, 15}, {0xCB, 13}, {0xB4, 12}, {0xCB, 11}, {0xCD, 10},
+ {0xCF, 15}, {0xCD, 12}, {0xBA, 12}, {0xCD, 12}, {0xCF, 12},
+ {0xCB, 15}, {0xCB, 9}, {0xCD, 9}, {0xCF, 9}, {0xCD, 9},
+ {0xCB, 9}, {0xCD, 9}, {0xCF, 5}, {0xBD, 13}, {0xCF, 8},
+ {0xCB, 8}, {0xCD, 15}, {0xB4, 1}, {0xBD, 7}, {0xCF, 7},
+ {0xCD, 7}, {0xCB, 7}, {0xCD, 7}, {0xCF, 15}, {0xCF, 15}
+};
+
+int GnapEngine::scene49_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ for (int i = 0; i < 5; ++i)
+ _gameSys->setAnimation(0, 0, i + 2);
+ _timers[2] = 0;
+ _timers[0] = 0;
+ _timers[1] = 0;
+ clearKeyStatus1(28);
+ clearKeyStatus1(54);
+ clearKeyStatus1(52);
+ return 0xD5;
+}
+
+void GnapEngine::scene49_updateHotspots() {
+ _hotspotsCount = 0;
+}
+
+void GnapEngine::scene49_checkObstacles() {
+
+ if (_timers[2] == 0) {
+
+ if (_timers[3] == 0)
+ for (int i = 0; i < 5; ++i)
+ scene49_clearObstacle(i);
+
+ for (int j = 0; j < 5; ++j) {
+ if (_s49_obstacles[j].currSequenceId == 0) {
+ _timers[3] = 35;
+ _s49_obstacles[j].currSequenceId = kObstacleDefs[_s49_obstacleIndex].sequenceId;
+ switch (_s49_obstacles[j].currSequenceId) {
+ case 0xB4:
+ _s49_obstacles[j].laneNum = 1;
+ _s49_obstacles[j].closerSequenceId = 180;
+ _s49_obstacles[j].passedSequenceId = 181;
+ _s49_obstacles[j].splashSequenceId = 182;
+ _s49_obstacles[j].collisionSequenceId = 192;
+ break;
+ case 0xB7:
+ _s49_obstacles[j].laneNum = 2;
+ _s49_obstacles[j].closerSequenceId = 183;
+ _s49_obstacles[j].passedSequenceId = 184;
+ _s49_obstacles[j].splashSequenceId = 185;
+ _s49_obstacles[j].collisionSequenceId = 193;
+ break;
+ case 0xBD:
+ _s49_obstacles[j].laneNum = 3;
+ _s49_obstacles[j].closerSequenceId = 189;
+ _s49_obstacles[j].passedSequenceId = 190;
+ _s49_obstacles[j].splashSequenceId = 191;
+ _s49_obstacles[j].collisionSequenceId = 195;
+ break;
+ case 0xBA:
+ _s49_obstacles[j].laneNum = 2;
+ _s49_obstacles[j].closerSequenceId = 186;
+ _s49_obstacles[j].passedSequenceId = 187;
+ _s49_obstacles[j].splashSequenceId = 188;
+ _s49_obstacles[j].collisionSequenceId = 194;
+ break;
+ case 0xCB:
+ _s49_obstacles[j].laneNum = 1;
+ _s49_obstacles[j].closerSequenceId = 203;
+ _s49_obstacles[j].passedSequenceId = 204;
+ _s49_obstacles[j].splashSequenceId = 0;
+ _s49_obstacles[j].collisionSequenceId = 209;
+ break;
+ case 0xCD:
+ _s49_obstacles[j].laneNum = 2;
+ _s49_obstacles[j].closerSequenceId = 205;
+ _s49_obstacles[j].passedSequenceId = 206;
+ _s49_obstacles[j].splashSequenceId = 0;
+ _s49_obstacles[j].collisionSequenceId = 210;
+ break;
+ case 0xCF:
+ _s49_obstacles[j].laneNum = 3;
+ _s49_obstacles[j].closerSequenceId = 207;
+ _s49_obstacles[j].passedSequenceId = 208;
+ _s49_obstacles[j].splashSequenceId = 0;
+ _s49_obstacles[j].collisionSequenceId = 211;
+ break;
+ }
+ _s49_obstacles[j].prevId = _s49_truckId;
+ _s49_obstacles[j].currId = _s49_obstacles[j].prevId;
+ _gameSys->setAnimation(_s49_obstacles[j].currSequenceId, _s49_obstacles[j].currId, j + 2);
+ _gameSys->insertSequence(_s49_obstacles[j].currSequenceId, _s49_obstacles[j].currId, 0, 0, kSeqNone, 0, 0, -50);
+ _timers[2] = kObstacleDefs[_s49_obstacleIndex].ticks;
+ ++_s49_obstacleIndex;
+ if (_s49_obstacleIndex == 50)
+ _s49_obstacleIndex = 0;
+ break;
+ }
+ }
+
+ }
+
+}
+
+void GnapEngine::scene49_updateObstacle(int i) {
+
+ Scene49Obstacle &obstacle = _s49_obstacles[i];
+
+ obstacle.currId = obstacle.prevId;
+
+ switch (obstacle.laneNum) {
+ case 1:
+ obstacle.prevId = _s49_truckId + 1;
+ break;
+ case 2:
+ if (_s49_truckLaneNum != 2 && _s49_truckLaneNum != 3)
+ obstacle.prevId = _s49_truckId - 1;
+ else
+ obstacle.prevId = _s49_truckId + 1;
+ break;
+ case 3:
+ if (_s49_truckLaneNum != 1 && _s49_truckLaneNum != 2)
+ obstacle.prevId = _s49_truckId;
+ else
+ obstacle.prevId = _s49_truckId - 1;
+ break;
+ }
+
+ if (obstacle.currSequenceId == obstacle.closerSequenceId) {
+ if (_s49_truckLaneNum == obstacle.laneNum) {
+ if (obstacle.splashSequenceId) {
+ _gameSys->setAnimation(obstacle.collisionSequenceId, obstacle.prevId, i + 2);
+ _gameSys->insertSequence(obstacle.collisionSequenceId, obstacle.prevId,
+ obstacle.currSequenceId, obstacle.currId,
+ kSeqSyncWait, 0, 0, -50);
+ obstacle.currSequenceId = obstacle.collisionSequenceId;
+ playSound(224, 0);
+ scene49_increaseScore(30);
+ } else if ((obstacle.laneNum == 1 && _s49_truckSequenceId == 0xB0) ||
+ (obstacle.laneNum == 2 && (_s49_truckSequenceId == 0xB1 || _s49_truckSequenceId == 0xB2)) ||
+ (obstacle.laneNum == 3 && _s49_truckSequenceId == 0xB3)) {
+ _gameSys->setAnimation(obstacle.passedSequenceId, obstacle.prevId, i + 2);
+ _gameSys->insertSequence(obstacle.passedSequenceId, obstacle.prevId,
+ obstacle.currSequenceId, obstacle.currId,
+ kSeqSyncWait, 0, 0, -50);
+ obstacle.currSequenceId = obstacle.passedSequenceId;
+ } else {
+ _gameSys->setAnimation(obstacle.collisionSequenceId, 256, 0);
+ _gameSys->setAnimation(obstacle.passedSequenceId, obstacle.prevId, i + 2);
+ _gameSys->insertSequence(obstacle.passedSequenceId, obstacle.prevId,
+ obstacle.currSequenceId, obstacle.currId,
+ kSeqSyncWait, 0, 0, -50);
+ _gameSys->insertSequence(obstacle.collisionSequenceId, 256,
+ _s49_truckSequenceId, _s49_truckId,
+ 32, 0, 0, -50);
+ _s49_truckSequenceId = obstacle.collisionSequenceId;
+ _s49_truckId = 256;
+ obstacle.currSequenceId = obstacle.passedSequenceId;
+ playSound(225, 0);
+ scene49_decreaseScore(30);
+ }
+ } else {
+ _gameSys->setAnimation(obstacle.passedSequenceId, obstacle.prevId, i + 2);
+ _gameSys->insertSequence(obstacle.passedSequenceId, obstacle.prevId,
+ obstacle.currSequenceId, obstacle.currId,
+ kSeqSyncWait, 0, 0, -50);
+ obstacle.currSequenceId = obstacle.passedSequenceId;
+ }
+ } else if (obstacle.currSequenceId == obstacle.passedSequenceId) {
+ if (_s49_truckLaneNum == obstacle.laneNum) {
+ if (obstacle.splashSequenceId) {
+ _gameSys->setAnimation(obstacle.collisionSequenceId, obstacle.prevId, i + 2);
+ _gameSys->insertSequence(obstacle.collisionSequenceId, obstacle.prevId,
+ obstacle.currSequenceId, obstacle.currId,
+ kSeqSyncWait, 0, 0, -50);
+ obstacle.currSequenceId = obstacle.collisionSequenceId;
+ playSound(224, 0);
+ scene49_increaseScore(30);
+ }
+ } else if (obstacle.splashSequenceId) {
+ _gameSys->setAnimation(obstacle.splashSequenceId, obstacle.prevId, i + 2);
+ _gameSys->insertSequence(obstacle.splashSequenceId, obstacle.prevId,
+ obstacle.currSequenceId, obstacle.currId,
+ kSeqSyncWait, 0, 0, -50);
+ obstacle.currSequenceId = obstacle.splashSequenceId;
+ }
+ } else {
+ _gameSys->setAnimation(0, 0, i + 2);
+ scene49_clearObstacle(i);
+ }
+
+}
+
+void GnapEngine::scene49_increaseScore(int amount) {
+ if (_s49_scoreBarPos + amount <= 556) {
+ _s49_scoreBarPos += amount;
+ _gameSys->fillSurface(0, _s49_scoreBarPos, 508, amount, 22, 255, 0, 0);
+ }
+ _s49_scoreLevel = _s49_scoreBarPos + amount >= 556;
+}
+
+void GnapEngine::scene49_decreaseScore(int amount) {
+ if (_s49_scoreBarPos >= 226 && _s49_scoreLevel == 0) {
+ if (_s49_scoreBarFlash)
+ scene49_refreshScoreBar();
+ _gameSys->fillSurface(0, _s49_scoreBarPos, 508, amount, 22, 89, 0, 5);
+ _s49_scoreBarPos -= amount;
+ _s49_scoreLevel = 0;
+ }
+}
+
+void GnapEngine::scene49_refreshScoreBar() {
+ if (_s49_scoreBarFlash)
+ _gameSys->fillSurface(0, 226, 508, 330, 22, 255, 0, 0);
+ else
+ _gameSys->fillSurface(0, 226, 508, 330, 22, 89, 0, 5);
+ _s49_scoreBarFlash = !_s49_scoreBarFlash;
+}
+
+void GnapEngine::scene49_clearObstacle(int index) {
+ _s49_obstacles[index].currSequenceId = 0;
+ _s49_obstacles[index].closerSequenceId = 0;
+ _s49_obstacles[index].passedSequenceId = 0;
+ _s49_obstacles[index].splashSequenceId = 0;
+ _s49_obstacles[index].collisionSequenceId = 0;
+ _s49_obstacles[index].prevId = 0;
+ _s49_obstacles[index].currId = 0;
+ _s49_obstacles[index].laneNum = 0;
+}
+
+void GnapEngine::scene49_run() {
+
+ bool animToggle6 = false;
+ bool animToggle5 = false;
+ bool animToggle4 = false;
+ bool animToggle3 = false;
+ bool streetAnimToggle = false;
+ bool bgAnimToggle = false;
+
+ playSound(0xE2, 1);
+ setSoundVolume(0xE2, 75);
+
+ hideCursor();
+ setGrabCursorSprite(-1);
+
+ _s49_scoreBarPos = 196;
+ _s49_scoreLevel = 0;
+ _s49_scoreBarFlash = false;
+
+ switch (getRandom(3)) {
+ case 0:
+ _s49_truckSequenceId = 0xAD;
+ _s49_truckLaneNum = 1;
+ break;
+ case 1:
+ _s49_truckSequenceId = 0xAE;
+ _s49_truckLaneNum = 2;
+ break;
+ case 2:
+ _s49_truckSequenceId = 0xAF;
+ _s49_truckLaneNum = 3;
+ break;
+ }
+
+ int bgWidth1 = _gameSys->getSpriteWidthById(0x5E);
+ int bgX1 = 600;
+
+ int bgWidth2 = _gameSys->getSpriteWidthById(0x5F);
+ int bgX2 = 400;
+
+ int bgWidth3 = _gameSys->getSpriteWidthById(4);
+ int bgX3 = 700;
+
+ int bgWidth4 = _gameSys->getSpriteWidthById(5);
+ int bgX4 = 500;
+
+ int bgWidth5 = _gameSys->getSpriteWidthById(6);
+ int bgX5 = 300;
+
+ int bgWidth6 = _gameSys->getSpriteWidthById(7);
+ int bgX6 = 100;
+
+ _gameSys->setAnimation(0xC8, 251, 1);
+ _gameSys->setAnimation(_s49_truckSequenceId, 256, 0);
+ _gameSys->insertSequence(0xC9, 256, 0, 0, kSeqNone, 0, 600, 85);
+ _gameSys->insertSequence(0xCA, 257, 0, 0, kSeqNone, 0, 400, 100);
+ _gameSys->insertSequence(0xC4, 256, 0, 0, kSeqNone, 0, 700, 140);
+ _gameSys->insertSequence(0xC5, 257, 0, 0, kSeqNone, 0, 500, 160);
+ _gameSys->insertSequence(0xC6, 258, 0, 0, kSeqNone, 0, 300, 140);
+ _gameSys->insertSequence(0xC7, 259, 0, 0, kSeqNone, 0, 100, 140);
+ _gameSys->insertSequence(0xC8, 251, 0, 0, kSeqNone, 0, 0, -50);
+ _gameSys->insertSequence(_s49_truckSequenceId, 256, 0, 0, kSeqNone, 0, 0, -50);
+
+ _timers[0] = 2;
+
+ for (int i = 0; i < 5; ++i)
+ scene49_clearObstacle(i);
+
+ _s49_obstacleIndex = 0;
+
+ _timers[2] = getRandom(20) + 10;
+
+ _s49_truckId = 256;
+ _timers[3] = 35;
+
+ while (!_sceneDone) {
+
+ if (_timers[0] == 0) {
+ // Update background animations (clouds etc.)
+ --bgX1;
+ bgX2 -= 2;
+ bgX3 -= 5;
+ --bgX4;
+ --bgX5;
+ --bgX6;
+ if (bgX1 <= -bgWidth1)
+ bgX1 = 799;
+ if (bgX2 <= -bgWidth2)
+ bgX2 = 799;
+ if (bgX3 <= -bgWidth3)
+ bgX3 = 799;
+ if (bgX4 <= -bgWidth4)
+ bgX4 = 799;
+ if (bgX5 <= -bgWidth5)
+ bgX5 = 799;
+ if (bgX6 <= -bgWidth6)
+ bgX6 = 799;
+ bgAnimToggle = !bgAnimToggle;
+ _gameSys->insertSequence(0xC9, (bgAnimToggle ? 1 : 0) + 256, 0xC9, (bgAnimToggle ? 0 : 1) + 256, kSeqSyncWait, 0, bgX1, 85);
+ _gameSys->insertSequence(0xCA, (bgAnimToggle ? 1 : 0) + 257, 0xCA, (bgAnimToggle ? 0 : 1) + 257, kSeqSyncWait, 0, bgX2, 100);
+ _gameSys->insertSequence(0xC4, (bgAnimToggle ? 1 : 0) + 256, 0xC4, (bgAnimToggle ? 0 : 1) + 256, kSeqSyncWait, 0, bgX3, 140);
+ _gameSys->insertSequence(0xC5, (bgAnimToggle ? 1 : 0) + 257, 0xC5, (bgAnimToggle ? 0 : 1) + 257, kSeqSyncWait, 0, bgX4, 160);
+ _gameSys->insertSequence(0xC6, (bgAnimToggle ? 1 : 0) + 258, 0xC6, (bgAnimToggle ? 0 : 1) + 258, kSeqSyncWait, 0, bgX5, 140);
+ _gameSys->insertSequence(0xC7, (bgAnimToggle ? 1 : 0) + 259, 0xC7, (bgAnimToggle ? 0 : 1) + 259, kSeqSyncWait, 0, bgX6, 140);
+ _timers[0] = 2;
+ }
+
+ if (_gameSys->getAnimationStatus(1) == 2) {
+ streetAnimToggle = !streetAnimToggle;
+ _gameSys->setAnimation(0xC8, (streetAnimToggle ? 1 : 0) + 251, 1);
+ _gameSys->insertSequence(0xC8, (streetAnimToggle ? 1 : 0) + 251, 200, (streetAnimToggle ? 0 : 1) + 251, kSeqSyncWait, 0, 0, -50);
+ }
+
+ scene49_checkObstacles();
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ switch (_s49_truckSequenceId) {
+ case 0xB1:
+ _s49_truckLaneNum = 1;
+ break;
+ case 0xB0:
+ case 0xB3:
+ _s49_truckLaneNum = 2;
+ break;
+ case 0xB2:
+ _s49_truckLaneNum = 3;
+ break;
+ }
+ animToggle3 = !animToggle3;
+ if (_s49_truckLaneNum == 1) {
+ _gameSys->setAnimation(0xAD, (animToggle3 ? 1 : 0) + 256, 0);
+ _gameSys->insertSequence(0xAD, (animToggle3 ? 1 : 0) + 256, _s49_truckSequenceId, _s49_truckId, kSeqSyncWait, 0, 0, -50);
+ _s49_truckSequenceId = 0xAD;
+ } else if (_s49_truckLaneNum == 2) {
+ _gameSys->setAnimation(0xAE, (animToggle3 ? 1 : 0) + 256, 0);
+ _gameSys->insertSequence(0xAE, (animToggle3 ? 1 : 0) + 256, _s49_truckSequenceId, _s49_truckId, kSeqSyncWait, 0, 0, -50);
+ _s49_truckSequenceId = 0xAE;
+ } else {
+ _gameSys->setAnimation(0xAF, (animToggle3 ? 1 : 0) + 256, 0);
+ _gameSys->insertSequence(0xAF, (animToggle3 ? 1 : 0) + 256, _s49_truckSequenceId, _s49_truckId, kSeqSyncWait, 0, 0, -50);
+ _s49_truckSequenceId = 0xAF;
+ }
+ _s49_truckId = (animToggle3 ? 1 : 0) + 256;
+ if (_s49_scoreLevel == 1) {
+ if (!_gameSys->isSequenceActive(0xD4, 266)) {
+ _gameSys->setAnimation(0xD4, 266, 8);
+ _gameSys->insertSequence(0xD4, 266, 0, 0, kSeqNone, 0, 0, -50);
+ }
+ ++_s49_scoreLevel;
+ _timers[1] = 2;
+ animToggle4 = false;
+ animToggle5 = false;
+ animToggle6 = false;
+ _s49_scoreBarFlash = false;
+ }
+ }
+
+ if (_s49_scoreLevel != 0 && !_timers[1]) {
+ scene49_refreshScoreBar();
+ _timers[1] = 8;
+ if (animToggle6) {
+ if (animToggle5) {
+ if (animToggle4 && !_gameSys->isSequenceActive(212, 266))
+ _gameSys->insertSequence(212, 266, 0, 0, kSeqNone, 0, 0, -50);
+ animToggle4 = !animToggle4;
+ }
+ animToggle5 = !animToggle5;
+ }
+ animToggle6 = !animToggle6;
+ }
+
+ scene49_updateAnimations();
+
+ if (sceneXX_sub_4466B1()) {
+ _sceneDone = true;
+ _newSceneNum = 2;
+ _newCursorValue = 1;
+ }
+
+ if (isKeyStatus1(Common::KEYCODE_RIGHT)) {
+ // Steer right
+ if (_s49_truckSequenceId == 0xB3)
+ _s49_truckLaneNum = 2;
+ if (_s49_truckSequenceId == 0xB1)
+ _s49_truckLaneNum = 1;
+ if (_s49_truckLaneNum != 3 && _s49_truckLaneNum != 2) {
+ if (_s49_scoreLevel) {
+ _sceneDone = true;
+ _newSceneNum = 47;
+ }
+ } else {
+ int steerSequenceId = (_s49_truckLaneNum == 3) ? 0xB3 : 0xB1;
+ if (_s49_truckSequenceId == 0xAE || _s49_truckSequenceId == 0xAF) {
+ _gameSys->setAnimation(steerSequenceId, 256, 0);
+ _gameSys->insertSequence(steerSequenceId, 256, _s49_truckSequenceId, _s49_truckId, 32, 0, 0, -50);
+ _s49_truckSequenceId = steerSequenceId;
+ _s49_truckId = 256;
+ }
+ }
+ clearKeyStatus1(Common::KEYCODE_RIGHT);
+ }
+
+ if (isKeyStatus1(Common::KEYCODE_LEFT)) {
+ // Steer left
+ if (_s49_truckSequenceId == 0xB0)
+ _s49_truckLaneNum = 2;
+ if (_s49_truckSequenceId == 0xB2)
+ _s49_truckLaneNum = 3;
+ if (_s49_truckLaneNum == 1 || _s49_truckLaneNum == 2) {
+ int steerSequenceId = (_s49_truckLaneNum == 1) ? 0xB0 : 0xB2;
+ if (_s49_truckSequenceId == 0xAD || _s49_truckSequenceId == 0xAE) {
+ _gameSys->setAnimation(steerSequenceId, 256, 0);
+ _gameSys->insertSequence(steerSequenceId, 256, _s49_truckSequenceId, _s49_truckId, 32, 0, 0, -50);
+ _s49_truckSequenceId = steerSequenceId;
+ _s49_truckId = 256;
+ }
+ }
+ clearKeyStatus1(Common::KEYCODE_LEFT);
+ }
+
+ gameUpdateTick();
+
+ }
+
+ stopSound(0xE2);
+
+}
+
+void GnapEngine::scene49_updateAnimations() {
+
+ for (int i = 0; i < 5; ++i) {
+ if (_gameSys->getAnimationStatus(i + 2) == 2) {
+ if (_s49_obstacles[i].currSequenceId)
+ scene49_updateObstacle(i);
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(8) == 2) {
+ _sceneDone = true;
+ _newSceneNum = 47;
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene50.cpp b/engines/gnap/scenes/scene50.cpp
new file mode 100644
index 0000000000..ce24354be0
--- /dev/null
+++ b/engines/gnap/scenes/scene50.cpp
@@ -0,0 +1,479 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+int GnapEngine::scene50_init() {
+ return 0xC7;
+}
+
+void GnapEngine::scene50_updateHotspots() {
+ _hotspotsCount = 0;
+}
+
+bool GnapEngine::scene50_tongueWinsRound(int tongueNum) {
+ if (tongueNum == 1)
+ ++_s50_leftTongueRoundsWon;
+ else
+ ++_s50_rightTongueRoundsWon;
+ scene50_playWinBadgeAnim(tongueNum);
+ bool fightOver = _s50_rightTongueRoundsWon == 2 || _s50_leftTongueRoundsWon == 2;
+ scene50_playWinAnim(tongueNum, fightOver);
+ return fightOver;
+}
+
+void GnapEngine::scene50_playWinAnim(int tongueNum, bool fightOver) {
+ if (tongueNum == 1) {
+ if (fightOver) {
+ _gameSys->insertSequence(0xAD, 140, 0xAC, 140, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xB4, 100, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xBD, 100, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xBC, 100, 0xBD, 100, kSeqSyncWait, 0, 0, 0);
+ _s50_leftTongueSequenceId = 0xB4;
+ _s50_rightTongueSequenceId = 0xBC;
+ _s50_rightTongueId = 100;
+ _s50_leftTongueId = 100;
+ _gameSys->setAnimation(0xB4, 100, 6);
+ _gameSys->setAnimation(_s50_rightTongueSequenceId, 100, 5);
+ scene50_waitForAnim(6);
+ scene50_waitForAnim(5);
+ invAdd(kItemGum);
+ setFlag(13);
+ } else {
+ _gameSys->insertSequence(0xB4, 100, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xBD, 100, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xBC, 100, 0xBD, 100, kSeqSyncWait, 0, 0, 0);
+ _s50_leftTongueSequenceId = 0xB4;
+ _s50_rightTongueSequenceId = 0xBC;
+ _s50_rightTongueId = 100;
+ _s50_leftTongueId = 100;
+ _gameSys->setAnimation(0xB4, 100, 6);
+ _gameSys->setAnimation(_s50_rightTongueSequenceId, 100, 5);
+ scene50_waitForAnim(6);
+ scene50_waitForAnim(5);
+ }
+ } else {
+ _gameSys->insertSequence(0xBE, 100, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0xBE, 100, 5);
+ scene50_waitForAnim(5);
+ _gameSys->insertSequence(0xBF, 100, 0xBE, 100, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xB5, 100, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0);
+ _s50_rightTongueSequenceId = 0xBF;
+ _s50_leftTongueSequenceId = 0xB5;
+ _s50_rightTongueId = 100;
+ _s50_leftTongueId = 100;
+ _gameSys->setAnimation(0xB5, 100, 6);
+ _gameSys->setAnimation(_s50_rightTongueSequenceId, 100, 5);
+ scene50_waitForAnim(6);
+ scene50_waitForAnim(5);
+ }
+ // TODO delayTicksA(1, 7);
+}
+
+void GnapEngine::scene50_delayTicks() {
+ // TODO delayTicksA(3, 7);
+}
+
+void GnapEngine::scene50_initRound() {
+ _s50_leftTongueEnergy = 10;
+ _s50_rightTongueEnergy = 10;
+ _s50_fightDone = false;
+ _timers[3] = scene50_getRightTongueActionTicks();
+ _timers[4] = 0;
+ _timers[6] = 0;
+ _gameSys->fillSurface(0, 91, 73, 260, 30, 212, 0, 0);
+ _gameSys->fillSurface(0, 450, 73, 260, 30, 212, 0, 0);
+ _s50_timeRemaining = 40;
+ scene50_drawCountdown(40);
+}
+
+bool GnapEngine::scene50_updateCountdown() {
+ if (!_timers[5]) {
+ --_s50_timeRemaining;
+ if (_s50_timeRemaining < 0) {
+ return true;
+ } else {
+ _timers[5] = 15;
+ scene50_drawCountdown(_s50_timeRemaining);
+ }
+ }
+ return false;
+}
+
+void GnapEngine::scene50_drawCountdown(int value) {
+ char str[8];
+ sprintf(str, "%02d", value);
+ _gameSys->fillSurface(0, 371, 505, 50, 27, 0, 0, 0);
+ _gameSys->drawTextToSurface(0, 381, 504, 255, 255, 255, str);
+}
+
+void GnapEngine::scene50_playTonguesIdle() {
+ _gameSys->insertSequence(0xBA, 100, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xC2, 100, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0);
+ _s50_leftTongueSequenceId = 0xBA;
+ _s50_rightTongueSequenceId = 0xC2;
+ _s50_rightTongueNextSequenceId = -1;
+ _s50_leftTongueNextSequenceId = -1;
+ _s50_leftTongueId = 100;
+ _s50_rightTongueId = 100;
+ _gameSys->setAnimation(0xC2, 100, 5);
+ _gameSys->setAnimation(_s50_leftTongueSequenceId, _s50_leftTongueId, 6);
+}
+
+void GnapEngine::scene50_playRoundAnim(int roundNum) {
+ int sequenceId;
+
+ switch (roundNum) {
+ case 1:
+ sequenceId = 0xAF;
+ break;
+ case 2:
+ sequenceId = 0xB0;
+ break;
+ case 3:
+ sequenceId = 0xB1;
+ break;
+ }
+
+ _gameSys->insertSequence(sequenceId, 256, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->setAnimation(sequenceId, 256, 7);
+ scene50_waitForAnim(7);
+
+ _gameSys->insertSequence(0xAB, 256, sequenceId, 256, kSeqSyncWait, 0, 0, 0);
+ _gameSys->setAnimation(0xAB, 256, 7);
+ scene50_waitForAnim(7);
+
+}
+
+bool GnapEngine::scene50_updateEnergyBars(int newLeftBarPos, int newRightBarPos) {
+
+ if (newLeftBarPos != _s50_leftTongueEnergyBarPos) {
+ if (newLeftBarPos < 0)
+ newLeftBarPos = 0;
+ _s50_leftTongueEnergyBarPos = newLeftBarPos;
+ _gameSys->fillSurface(0, 26 * newLeftBarPos + 91, 73, 260 - 26 * newLeftBarPos, 30, 0, 0, 0);
+ }
+
+ if (newRightBarPos != _s50_rightTongueEnergyBarPos) {
+ if (newRightBarPos < 0)
+ newRightBarPos = 0;
+ _s50_rightTongueEnergyBarPos = newRightBarPos;
+ if (newRightBarPos != 10)
+ _gameSys->fillSurface(0, 26 * (9 - newRightBarPos) + 450, 73, 26, 30, 0, 0, 0);
+ }
+
+ if (newLeftBarPos * newRightBarPos > 0)
+ return false;
+
+ _s50_leftTongueEnergyBarPos = 10;
+ _s50_rightTongueEnergyBarPos = 10;
+ return true;
+}
+
+void GnapEngine::scene50_waitForAnim(int animationIndex) {
+ while (_gameSys->getAnimationStatus(animationIndex) != 2) {
+ gameUpdateTick();
+ }
+ _gameSys->setAnimation(0, 0, animationIndex);
+}
+
+int GnapEngine::scene50_checkInput() {
+ int sequenceId = -1;
+
+ if (isKeyStatus1(Common::KEYCODE_RIGHT)) {
+ clearKeyStatus1(Common::KEYCODE_RIGHT);
+ sequenceId = 0xB6;
+ } else if (isKeyStatus1(Common::KEYCODE_LEFT)) {
+ clearKeyStatus1(Common::KEYCODE_LEFT);
+ sequenceId = 0xB3;
+ } else if (isKeyStatus1(Common::KEYCODE_ESCAPE)) {
+ clearKeyStatus1(Common::KEYCODE_ESCAPE);
+ _s50_fightDone = true;
+ }
+
+ return sequenceId;
+}
+
+int GnapEngine::scene50_getRightTongueAction() {
+ int sequenceId = -1;
+
+ if (!_timers[3]) {
+ _timers[3] = scene50_getRightTongueActionTicks();
+ if (_s50_rightTongueEnergy >= _s50_leftTongueEnergy) {
+ switch (getRandom(5)) {
+ case 0:
+ sequenceId = 0xBE;
+ break;
+ case 1:
+ sequenceId = 0xBE;
+ break;
+ case 2:
+ sequenceId = 0xBB;
+ break;
+ case 3:
+ sequenceId = 0xBB;
+ break;
+ case 4:
+ sequenceId = 0xBB;
+ break;
+ }
+ } else {
+ switch (getRandom(4)) {
+ case 0:
+ sequenceId = 0xBE;
+ break;
+ case 1:
+ sequenceId = 0xBB;
+ break;
+ case 2:
+ sequenceId = 0xBE;
+ break;
+ case 3:
+ sequenceId = 0xBE;
+ break;
+ }
+ }
+ }
+
+ return sequenceId;
+}
+
+void GnapEngine::scene50_updateAnimations() {
+
+ if (!_timers[4])
+ _s50_attackCounter = 0;
+
+ if (_gameSys->getAnimationStatus(5) == 2) {
+ if (_s50_rightTongueSequenceId == 0xBE) {
+ if (_s50_leftTongueSequenceId != 0xB3 && _s50_leftTongueSequenceId != 0xB8)
+ _s50_rightTongueNextSequenceId = 0xBF;
+ else
+ _s50_rightTongueNextSequenceId = 0xC0;
+ }
+ if (_s50_rightTongueNextSequenceId == -1)
+ _s50_rightTongueNextSequenceId = 0xC2;
+ if (_s50_rightTongueNextSequenceId == 0xBF) {
+ _s50_leftTongueNextId = scene50_getLeftTongueNextId();
+ _s50_rightTongueNextId = scene50_getRightTongueNextId();
+ _gameSys->setAnimation(_s50_rightTongueNextSequenceId, _s50_rightTongueNextId, 5);
+ _gameSys->setAnimation(0xB9, _s50_leftTongueNextId, 6);
+ _gameSys->insertSequence(_s50_rightTongueNextSequenceId, _s50_rightTongueNextId, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xB9, _s50_leftTongueNextId, _s50_leftTongueSequenceId, _s50_leftTongueId, 32, 0, 0, 0);
+ _s50_rightTongueSequenceId = _s50_rightTongueNextSequenceId;
+ _s50_rightTongueNextSequenceId = -1;
+ _s50_leftTongueSequenceId = 0xB9;
+ _s50_leftTongueNextSequenceId = -1;
+ _s50_rightTongueId = _s50_rightTongueNextId;
+ _s50_leftTongueId = _s50_leftTongueNextId;
+ _s50_leftTongueEnergy -= getRandom(2) + 1;//CHECKME
+ } else {
+ _s50_rightTongueNextId = scene50_getRightTongueNextId();
+ _gameSys->setAnimation(_s50_rightTongueNextSequenceId, _s50_rightTongueNextId, 5);
+ _gameSys->insertSequence(_s50_rightTongueNextSequenceId, _s50_rightTongueNextId, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0);
+ _s50_rightTongueSequenceId = _s50_rightTongueNextSequenceId;
+ _s50_rightTongueNextSequenceId = -1;
+ _s50_rightTongueId = _s50_rightTongueNextId;
+ }
+ }
+
+ if (_gameSys->getAnimationStatus(6) == 2) {
+ if (_s50_leftTongueSequenceId == 0xB6) {
+ ++_s50_attackCounter;
+ if (_s50_timesPlayedModifier + 3 <= _s50_attackCounter) {
+ _s50_leftTongueNextSequenceId = 0xB8;
+ } else {
+ _timers[4] = 20;
+ //CHECKME
+ if (_s50_rightTongueSequenceId != 0xBB && _s50_rightTongueSequenceId != 0xC0 && getRandom(8) != _s50_roundNum)
+ _s50_leftTongueNextSequenceId = 0xB7;
+ else
+ _s50_leftTongueNextSequenceId = 0xB8;
+ }
+ }
+ if (_s50_leftTongueNextSequenceId == 0xB3)
+ --_s50_attackCounter;
+ if (_s50_leftTongueNextSequenceId == -1)
+ _s50_leftTongueNextSequenceId = 0xBA;
+ if (_s50_leftTongueNextSequenceId == 0xB7) {
+ _s50_leftTongueNextId = scene50_getLeftTongueNextId();
+ _s50_rightTongueNextId = scene50_getRightTongueNextId();
+ _gameSys->setAnimation(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, 6);
+ _gameSys->setAnimation(0xC1, _s50_rightTongueNextId, 5);
+ _gameSys->insertSequence(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xC1, _s50_rightTongueNextId, _s50_rightTongueSequenceId, _s50_rightTongueId, 32, 0, 0, 0);
+ _s50_leftTongueSequenceId = _s50_leftTongueNextSequenceId;
+ _s50_leftTongueNextSequenceId = -1;
+ _s50_rightTongueSequenceId = 0xC1;
+ _s50_rightTongueNextSequenceId = -1;
+ _s50_rightTongueId = _s50_rightTongueNextId;
+ _s50_leftTongueId = _s50_leftTongueNextId;
+ --_s50_rightTongueEnergy;
+ } else if (_s50_leftTongueNextSequenceId != 0xB8 || _s50_rightTongueSequenceId != 0xC2) {
+ _s50_leftTongueNextId = scene50_getLeftTongueNextId();
+ _gameSys->setAnimation(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, 6);
+ _gameSys->insertSequence(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0);
+ _s50_leftTongueSequenceId = _s50_leftTongueNextSequenceId;
+ _s50_leftTongueNextSequenceId = -1;
+ _s50_leftTongueId = _s50_leftTongueNextId;
+ } else {
+ _s50_leftTongueNextId = scene50_getLeftTongueNextId();
+ _s50_rightTongueNextId = scene50_getRightTongueNextId();
+ _gameSys->setAnimation(0xBB, _s50_rightTongueNextId, 5);
+ _gameSys->setAnimation(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, 6);
+ _gameSys->insertSequence(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0);
+ _gameSys->insertSequence(0xBB, _s50_rightTongueNextId, _s50_rightTongueSequenceId, _s50_rightTongueId, 32, 0, 0, 0);
+ _s50_rightTongueSequenceId = 0xBB;
+ _s50_rightTongueId = _s50_rightTongueNextId;
+ _s50_rightTongueNextSequenceId = -1;
+ _s50_leftTongueSequenceId = _s50_leftTongueNextSequenceId;
+ _s50_leftTongueNextSequenceId = -1;
+ _s50_leftTongueId = _s50_leftTongueNextId;
+ }
+ }
+
+}
+
+int GnapEngine::scene50_getRightTongueActionTicks() {
+ return 15 - 5 * _s50_roundNum + 1;
+}
+
+int GnapEngine::scene50_getLeftTongueNextId() {
+ _s50_leftTongueNextIdCtr = (_s50_leftTongueNextIdCtr + 1) % 3;
+ return _s50_leftTongueNextIdCtr + 100;
+}
+
+int GnapEngine::scene50_getRightTongueNextId() {
+ _s50_rightTongueNextIdCtr = (_s50_rightTongueNextIdCtr + 1) % 3;
+ return _s50_rightTongueNextIdCtr + 100;
+}
+
+void GnapEngine::scene50_playWinBadgeAnim(int tongueNum) {
+ int sequenceId;
+
+ if (tongueNum == 1) {
+ if (_s50_leftTongueRoundsWon == 1)
+ sequenceId = 0xC3;
+ else
+ sequenceId = 0xC4;
+ } else {
+ if (_s50_rightTongueRoundsWon == 1)
+ sequenceId = 0xC5;
+ else
+ sequenceId = 0xC6;
+ }
+
+ _gameSys->setAnimation(sequenceId, 120, 7);
+ _gameSys->insertSequence(sequenceId, 120, 0, 0, kSeqNone, 0, 0, 0);
+ scene50_waitForAnim(7);
+
+}
+
+void GnapEngine::scene50_run() {
+
+ ++_s50_timesPlayed;
+ _s50_timesPlayedModifier = _s50_timesPlayed / 4;
+ _s50_leftTongueRoundsWon = 0;
+ _s50_rightTongueRoundsWon = 0;
+ // scene50_initFont();
+ _s50_leftTongueSequenceId = 186;
+ _s50_rightTongueSequenceId = 194;
+ _s50_rightTongueNextSequenceId = -1;
+ _s50_leftTongueNextSequenceId = -1;
+ _s50_leftTongueId = 100;
+ _s50_rightTongueId = 100;
+
+ _gameSys->setAnimation(194, 100, 5);
+ _gameSys->setAnimation(_s50_leftTongueSequenceId, _s50_leftTongueId, 6);
+ _gameSys->insertSequence(_s50_leftTongueSequenceId, _s50_leftTongueId, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(_s50_rightTongueSequenceId, _s50_rightTongueId, 0, 0, kSeqNone, 0, 0, 0);
+ _gameSys->insertSequence(172, 140, 0, 0, kSeqNone, 0, 0, 0);
+ endSceneInit();
+
+ scene50_initRound();
+
+ _s50_roundNum = 1;
+
+ setGrabCursorSprite(-1);
+ hideCursor();
+
+ // TODO delayTicksA(1, 7);
+
+ scene50_playRoundAnim(_s50_roundNum);
+
+ _timers[5] = 15;
+
+ while (!_s50_fightDone) {
+
+ /* TODO
+ if (sceneXX_sub_4466B1())
+ _s50_fightDone = true;
+ */
+
+ int playerSequenceId = scene50_checkInput();
+ if (playerSequenceId != -1)
+ _s50_leftTongueNextSequenceId = playerSequenceId;
+
+ int rightSequenceId = scene50_getRightTongueAction();
+ if (rightSequenceId != -1)
+ _s50_rightTongueNextSequenceId = rightSequenceId;
+
+ scene50_updateAnimations();
+
+ if (scene50_updateCountdown() ||
+ scene50_updateEnergyBars(_s50_leftTongueEnergy, _s50_rightTongueEnergy)) {
+ int v0;
+ if (_s50_rightTongueEnergy < _s50_leftTongueEnergy)
+ v0 = scene50_tongueWinsRound(1);
+ else
+ v0 = scene50_tongueWinsRound(2);
+ if (v0) {
+ scene50_delayTicks();
+ _s50_fightDone = true;
+ } else {
+ ++_s50_roundNum;
+ scene50_initRound();
+ scene50_playTonguesIdle();
+ scene50_updateEnergyBars(_s50_leftTongueEnergy, _s50_rightTongueEnergy);
+ scene50_playRoundAnim(_s50_roundNum);
+ _timers[5] = 15;
+ }
+ }
+
+ gameUpdateTick();
+
+ }
+
+ // scene50_freeFont();
+
+ _gameSys->setAnimation(0, 0, 7);
+ _gameSys->setAnimation(0, 0, 6);
+ _gameSys->setAnimation(0, 0, 5);
+ _gameSys->setAnimation(0, 0, 3);
+
+ showCursor();
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene51.cpp b/engines/gnap/scenes/scene51.cpp
new file mode 100644
index 0000000000..1313c1d2db
--- /dev/null
+++ b/engines/gnap/scenes/scene51.cpp
@@ -0,0 +1,880 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+static const int kDigitSequenceIds[] = {
+ 0xCA, 0xCB, 0xCC, 0xCD, 0xCE,
+ 0xCF, 0xD0, 0xD1, 0xD2, 0xD3
+};
+
+static const int kDigitPositions[4] = {
+ 0, 34, 83, 119
+};
+
+/*
+ 0xBA Falling banana peel
+ 0xBC Banana peel goes away
+ 0xBD Falling coin
+ 0xBE Fallen coin
+ 0xC0 Falling banknote
+ 0xB6 Platypus tripping (right)
+ 0xB7 Platypus tripping (left)
+ 0x76 Platypus jumping (right)
+*/
+
+int GnapEngine::scene51_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ for (int i = 0; i < 6; ++i)
+ _gameSys->setAnimation(0, 0, i + 1);
+ return 0xD4;
+}
+
+void GnapEngine::scene51_updateHotspots() {
+ _hotspotsCount = 0;
+}
+
+void GnapEngine::scene51_clearItem(Scene51Item *item) {
+ item->currSequenceId = 0;
+ item->droppedSequenceId = 0;
+ item->x = 0;
+ item->y = 0;
+ item->x2 = 0;
+ item->collisionX = 0;
+ item->canCatch = 0;
+}
+
+void GnapEngine::scene51_dropNextItem() {
+
+ if (_timers[0])
+ return;
+
+ int index = 0;
+
+ while (index < 6 && _s51_items[index].currSequenceId)
+ ++index;
+
+ if (index == 6)
+ return;
+
+ switch (_s51_nextDropItemKind) {
+
+ case 0:
+ if (getRandom(10) != 0 || _s51_itemsCtr2 >= 2) {
+ _s51_items[index].currSequenceId = 0xBD;
+ } else {
+ --_s51_itemsCtr1;
+ _s51_items[index].currSequenceId = 0xBA;
+ ++_s51_itemsCtr2;
+ }
+ break;
+
+ case 1:
+ if (getRandom(8) != 0 || _s51_itemsCtr2 >= 2) {
+ if (getRandom(5) == 0) {
+ if (_s51_itemInsertDirection)
+ _s51_itemInsertX -= 70;
+ else
+ _s51_itemInsertX += 70;
+ }
+ _s51_items[index].currSequenceId = 0xBD;
+ } else {
+ --_s51_itemsCtr1;
+ _s51_items[index].currSequenceId = 0xBA;
+ ++_s51_itemsCtr2;
+ }
+ break;
+
+ case 2:
+ if (getRandom(6) != 0 || _s51_itemsCtr2 >= 2) {
+ _s51_items[index].currSequenceId = 0xBD;
+ } else {
+ --_s51_itemsCtr1;
+ _s51_items[index].currSequenceId = 0xBA;
+ ++_s51_itemsCtr2;
+ }
+ break;
+
+ case 3:
+ case 4:
+ if (_s51_itemsCtr == 0)
+ _s51_itemsCtr1 = 3;
+ _s51_items[index].currSequenceId = 0xC0;
+ break;
+
+ case 5:
+ case 6:
+ if (getRandom(5) != 0 || _s51_itemsCtr2 >= 2) {
+ if (getRandom(5) != 0)
+ _s51_items[index].currSequenceId = 0xBD;
+ else
+ _s51_items[index].currSequenceId = 0xC0;
+ } else {
+ --_s51_itemsCtr1;
+ _s51_items[index].currSequenceId = 0xBA;
+ ++_s51_itemsCtr2;
+ }
+ break;
+
+ case 7:
+ if (getRandom(5) != 0 || _s51_itemsCtr2 >= 2) {
+ if (getRandom(5) == 0) {
+ if (_s51_itemInsertDirection)
+ _s51_itemInsertX -= 40;
+ else
+ _s51_itemInsertX += 40;
+ }
+ if (getRandom(9) != 0)
+ _s51_items[index].currSequenceId = 0xBD;
+ else
+ _s51_items[index].currSequenceId = 0xC0;
+ } else {
+ --_s51_itemsCtr1;
+ _s51_items[index].currSequenceId = 0xBA;
+ ++_s51_itemsCtr2;
+ }
+ break;
+
+ default:
+ if (getRandom(4) != 0 || _s51_itemsCtr2 >= 2) {
+ if (getRandom(9) != 0)
+ _s51_items[index].currSequenceId = 0xBD;
+ else
+ _s51_items[index].currSequenceId = 0xC0;
+ } else {
+ --_s51_itemsCtr1;
+ _s51_items[index].currSequenceId = 0xBA;
+ ++_s51_itemsCtr2;
+ }
+ break;
+
+ }
+
+ if (_s51_itemInsertDirection) {
+ _s51_itemInsertX -= 73;
+ if (_s51_itemInsertX < 129) {
+ _s51_itemInsertX += 146;
+ _s51_itemInsertDirection = 0;
+ }
+ } else {
+ _s51_itemInsertX += 73;
+ if (_s51_itemInsertX > 685) {
+ _s51_itemInsertX -= 146;
+ _s51_itemInsertDirection = 1;
+ }
+ }
+
+ if (_s51_itemInsertX > 685)
+ _s51_itemInsertX = 685;
+
+ if (_s51_itemInsertX < 129)
+ _s51_itemInsertX = 129;
+
+ if (_s51_items[index].currSequenceId == 0xBA) {
+ _s51_items[index].x2 = getRandom(350) + 200;
+ _s51_items[index].x = _s51_items[index].x2 - 362;
+ _s51_items[index].y = 15;
+ _s51_items[index].id = 249 - index;
+ } else {
+ _s51_items[index].collisionX = _s51_itemInsertX;
+ _s51_items[index].x = _s51_items[index].collisionX - 395;
+ if (_s51_items[index].currSequenceId == 0xC0)
+ _s51_items[index].x -= 65;
+ _s51_items[index].id = index + 250;
+ _s51_items[index].canCatch = 1;
+ }
+
+ _gameSys->setAnimation(_s51_items[index].currSequenceId, _s51_items[index].id, index + 1);
+ _gameSys->insertSequence(_s51_items[index].currSequenceId, _s51_items[index].id, 0, 0,
+ kSeqNone, 0, _s51_items[index].x, _s51_items[index].y);
+
+ _timers[0] = _s51_dropSpeedTicks;
+
+ if (_s51_nextDropItemKind >= 3)
+ _timers[0] = 20;
+
+ if (_s51_nextDropItemKind >= 5)
+ _timers[0] = 5;
+
+ if (_s51_nextDropItemKind == 8)
+ _timers[0] = 4;
+
+ ++_s51_itemsCtr;
+
+}
+
+void GnapEngine::scene51_updateItemAnimations() {
+ for (int i = 0; i < 6; ++i)
+ if (_gameSys->getAnimationStatus(i + 1) == 2)
+ scene51_updateItemAnimation(&_s51_items[i], i);
+}
+
+int GnapEngine::scene51_checkCollision(int sequenceId) {
+ bool jumpingLeft = false, jumpingRight = false;
+ int v6 = 0;
+ int v2 = 0;
+ int v5 = 0;
+ int v8, v4;
+ int result = 0;
+
+ if (!scene51_isJumping(sequenceId))
+ return false;
+
+ while (v6 < 6)
+ v2 += _s51_items[v6++].isCollision;
+
+ if (!v2)
+ return false;
+
+ if (scene51_isJumpingRight(sequenceId)) {
+ v8 = scene51_getPosRight(sequenceId);
+ v4 = scene51_getPosRight(sequenceId + 1);
+ jumpingRight = true;
+ } else if (scene51_isJumpingLeft(sequenceId)) {
+ v4 = scene51_getPosLeft(sequenceId - 1) + 33;
+ v8 = scene51_getPosLeft(sequenceId) + 33;
+ jumpingLeft = true;
+ }
+
+ if (jumpingRight || jumpingLeft) {
+ int i;
+ for (i = 0; i < 6; ++i) {
+ if (_s51_items[i].isCollision) {
+ if (jumpingRight && _s51_items[i].x2 > v8 && _s51_items[i].x2 < v4) {
+ v5 = v8 - 359;
+ if (v8 == 359)
+ v5 = 1;
+ _s51_platypusNextSequenceId = 0xB6;
+ break;
+ } else if (jumpingLeft && _s51_items[i].x2 < v4 && _s51_items[i].x2 > v8) {
+ v5 = v8 - 344;
+ if (v8 == 344)
+ v5 = 1;
+ _s51_platypusNextSequenceId = 0xB7;
+ break;
+ }
+ }
+ }
+ if (v5) {
+ _gameSys->setAnimation(0xBC, _s51_items[i].id, i + 1);
+ _gameSys->insertSequence(0xBC, _s51_items[i].id, _s51_items[i].currSequenceId, _s51_items[i].id, kSeqSyncWait, 0, _s51_items[i].x, 15);
+ _s51_items[i].isCollision = 0;
+ _s51_items[i].currSequenceId = 0xBC;
+ --_s51_itemsCtr2;
+ }
+ result = v5;
+ }
+
+ return result;
+}
+
+void GnapEngine::scene51_updateItemAnimation(Scene51Item *item, int index) {
+
+ switch (item->currSequenceId) {
+
+ case 0xBD:
+ case 0xC0:
+ case 0xC1:
+ // Falling coin and banknote
+ if (!scene51_itemIsCaught(item)) {
+ if (_s51_dropLoseCash) {
+ if (item->currSequenceId == 0xBD)
+ _s51_cashAmount -= 2;
+ else
+ _s51_cashAmount -= 25;
+ if (_s51_cashAmount < 0)
+ _s51_cashAmount = 0;
+ scene51_updateCash(_s51_cashAmount);
+ }
+ item->droppedSequenceId = item->currSequenceId + 1;
+ if (item->currSequenceId != 0xC0) {
+ item->canCatch = 0;
+ _s51_dropLoseCash = true;
+ _s51_itemsCtr = 0;
+ _timers[0] = 10;
+ }
+ if (item->droppedSequenceId) {
+ _gameSys->setAnimation(item->droppedSequenceId, item->id, index + 1);
+ _gameSys->insertSequence(item->droppedSequenceId, item->id, item->currSequenceId, item->id, kSeqSyncWait, 0, item->x, item->y);
+ item->currSequenceId = item->droppedSequenceId;
+ item->y = 0;
+ }
+ } else {
+ _gameSys->removeSequence(item->currSequenceId, item->id, 1);
+ _gameSys->setAnimation(0, 0, index + 1);
+ playSound(218, 0);
+ if (scene51_incCashAmount(item->currSequenceId) == 1995) {
+ scene51_winMinigame();
+ _sceneDone = true;
+ } else {
+ scene51_clearItem(item);
+ ++_s51_itemsCaughtCtr;
+ if (_s51_itemsCaughtCtr == 5)
+ --_s51_dropSpeedTicks;
+ if (_s51_itemsCaughtCtr == 8)
+ --_s51_dropSpeedTicks;
+ if (_s51_itemsCaughtCtr == 11)
+ --_s51_dropSpeedTicks;
+ if (_s51_itemsCaughtCtr == 14)
+ --_s51_dropSpeedTicks;
+ if (_s51_itemsCaughtCtr >= 15 && _s51_dropSpeedTicks > 4)
+ --_s51_dropSpeedTicks;
+ if (_s51_itemsCtr1 <= _s51_itemsCaughtCtr) {
+ ++_s51_nextDropItemKind;
+ _s51_dropSpeedTicks = 10;
+ _s51_itemsCtr = 0;
+ _s51_itemsCtr1 = 20;
+ _s51_dropLoseCash = false;
+ _s51_itemsCaughtCtr = 0;
+ scene51_removeCollidedItems();
+ }
+ }
+ }
+ break;
+
+ case 0xBE:
+ // Fallen coin
+ item->droppedSequenceId = item->currSequenceId + 1;
+ if (item->droppedSequenceId) {
+ _gameSys->setAnimation(item->droppedSequenceId, item->id, index + 1);
+ _gameSys->insertSequence(item->droppedSequenceId, item->id, item->currSequenceId, item->id, kSeqSyncWait, 0, item->x, item->y);
+ item->currSequenceId = item->droppedSequenceId;
+ item->y = 0;
+ }
+ break;
+
+ case 0xBF:
+ case 0xC2:
+ // Bouncing coin and banknote
+ _gameSys->setAnimation(0, 0, index + 1);
+ _gameSys->removeSequence(item->currSequenceId, item->id, 1);
+ scene51_clearItem(item);
+ break;
+
+ case 0xBA:
+ // Falling banana peel
+ item->droppedSequenceId = 0xBB;
+ item->y = 15;
+ if (item->droppedSequenceId) {
+ _gameSys->setAnimation(item->droppedSequenceId, item->id, index + 1);
+ _gameSys->insertSequence(item->droppedSequenceId, item->id, item->currSequenceId, item->id, kSeqSyncWait, 0, item->x, item->y);
+ item->currSequenceId = item->droppedSequenceId;
+ item->y = 0;
+ }
+ break;
+
+ case 0xBB:
+ item->isCollision = 1;
+ item->droppedSequenceId = 0;
+ _gameSys->setAnimation(0, 0, index + 1);
+ break;
+
+ case 0xBC:
+ _gameSys->removeSequence(item->currSequenceId, item->id, 1);
+ _gameSys->setAnimation(0, 0, index + 1);
+ scene51_clearItem(item);
+ break;
+
+ default:
+ if (item->droppedSequenceId) {
+ _gameSys->setAnimation(item->droppedSequenceId, item->id, index + 1);
+ _gameSys->insertSequence(item->droppedSequenceId, item->id, item->currSequenceId, item->id, kSeqSyncWait, 0, item->x, item->y);
+ item->currSequenceId = item->droppedSequenceId;
+ item->y = 0;
+ }
+ break;
+
+ }
+
+}
+
+void GnapEngine::scene51_removeCollidedItems() {
+ for (int i = 0; i < 6; ++i) {
+ if (_s51_items[i].isCollision) {
+ _gameSys->removeSequence(_s51_items[i].currSequenceId, _s51_items[i].id, 1);
+ _gameSys->setAnimation(0, 0, i + 1);
+ scene51_clearItem(&_s51_items[i]);
+ }
+ }
+ _s51_itemsCtr2 = 0;
+}
+
+int GnapEngine::scene51_itemIsCaught(Scene51Item *item) {
+
+ if (!item->canCatch)
+ return 0;
+
+ if (scene51_isJumpingRight(_s51_platypusJumpSequenceId)) {
+ int v4 = scene51_getPosRight(_s51_platypusJumpSequenceId) + 97;
+ if (item->collisionX < v4 && v4 - item->collisionX < 56)
+ return 1;
+ } else {
+ int v2 = scene51_getPosLeft(_s51_platypusJumpSequenceId);
+ if (item->collisionX > v2 && item->collisionX - v2 < 56)
+ return 1;
+ }
+
+ if (item->currSequenceId == 0xC1) {
+ int v3 = item->collisionX + 100;
+ if (scene51_isJumpingRight(_s51_platypusJumpSequenceId)) {
+ if (ABS(scene51_getPosRight(_s51_platypusJumpSequenceId) + 46 - v3) < 56)
+ return 1;
+ } else if (ABS(scene51_getPosLeft(_s51_platypusJumpSequenceId) + 46 - v3) < 56) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+bool GnapEngine::scene51_isJumpingRight(int sequenceId) {
+ return sequenceId >= 0x76 && sequenceId <= 0x95;
+}
+
+bool GnapEngine::scene51_isJumpingLeft(int sequenceId) {
+ return sequenceId >= 0x96 && sequenceId <= 0xB5;
+}
+
+bool GnapEngine::scene51_isJumping(int sequenceId) {
+ return sequenceId >= 0x76 && sequenceId <= 0xB5;
+}
+
+void GnapEngine::scene51_waitForAnim(int animationIndex) {
+ while (_gameSys->getAnimationStatus(animationIndex) != 2) {
+ // pollMessages();
+ scene51_updateItemAnimations();
+ gameUpdateTick();
+ }
+}
+
+int GnapEngine::scene51_getPosRight(int sequenceId) {
+ static const int kRightPosTbl[] = {
+ 131, 159, 178, 195, 203, 219, 238, 254,
+ 246, 274, 293, 310, 318, 334, 353, 369,
+ 362, 390, 409, 426, 434, 450, 469, 485,
+ 477, 505, 524, 541, 549, 565, 584, 600
+ };
+
+ if (sequenceId >= 118 && sequenceId <= 149)
+ return kRightPosTbl[sequenceId - 118];
+ return -1;
+}
+
+int GnapEngine::scene51_getPosLeft(int sequenceId) {
+ static const int kLeftPosTbl[] = {
+ 580, 566, 550, 536, 526, 504, 488, 469,
+ 460, 446, 430, 416, 406, 384, 368, 349,
+ 342, 328, 312, 298, 288, 266, 250, 231,
+ 220, 206, 190, 176, 166, 144, 128, 109
+ };
+
+ if (sequenceId >= 150 && sequenceId <= 181)
+ return kLeftPosTbl[sequenceId - 150];
+ return -1;
+}
+
+void GnapEngine::scene51_playIntroAnim() {
+ int soundCtr = 0;
+
+ _s51_platypusSequenceId = 0x76;
+ _s51_platypusNextSequenceId = 0x76;
+
+ for (int i = 0; i < 6; ++i)
+ scene51_clearItem(&_s51_items[i]);
+
+ _s51_items[0].currSequenceId = 0xBA;
+ _s51_items[0].x2 = 320;
+ _s51_items[0].x = -42;
+ _s51_items[0].y = 15;
+ _s51_items[0].id = 249;
+ _s51_items[0].isCollision = 1;
+
+ _gameSys->insertSequence(_s51_platypusSequenceId, 256, 0, 0, kSeqNone, 0, -179, 0);
+ _gameSys->insertSequence(0xBA, 249, 0, 0, kSeqNone, 0, _s51_items[0].x, _s51_items[0].y);
+ _gameSys->setAnimation(0xBA, 249, 1);
+ _gameSys->setAnimation(_s51_platypusSequenceId, 256, 0);
+
+ while (_s51_platypusSequenceId < 0x80) {
+ scene51_waitForAnim(0);
+ ++_s51_platypusNextSequenceId;
+ _gameSys->setAnimation(_s51_platypusNextSequenceId, 256, 0);
+ _gameSys->insertSequence(_s51_platypusNextSequenceId, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, -179, 0);
+ _s51_platypusSequenceId = _s51_platypusNextSequenceId;
+ ++soundCtr;
+ if (soundCtr % 4 == 0)
+ playSound(214, 0);
+ }
+
+ _s51_platypusNextSequenceId = 0x75;
+
+ while (_s51_platypusSequenceId != 0x84) {
+ scene51_waitForAnim(0);
+ ++_s51_platypusNextSequenceId;
+ int oldSequenceId = _s51_platypusNextSequenceId;
+ int v0 = scene51_checkCollision(_s51_platypusNextSequenceId);
+ _gameSys->setAnimation(_s51_platypusNextSequenceId, 256, 0);
+ _gameSys->insertSequence(_s51_platypusNextSequenceId, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, v0, 0);
+ _s51_platypusSequenceId = _s51_platypusNextSequenceId;
+ if (v0) {
+ _s51_platypusNextSequenceId = oldSequenceId;
+ } else {
+ ++soundCtr;
+ if (soundCtr % 4 == 0)
+ playSound(214, 0);
+ }
+ }
+
+ scene51_waitForAnim(0);
+
+}
+
+void GnapEngine::scene51_updateGuyAnimation() {
+
+ if (!_timers[4]) {
+ _timers[4] = getRandom(20) + 60;
+
+ switch (getRandom(5)) {
+ case 0:
+ _s51_guyNextSequenceId = 0xC3;
+ break;
+ case 1:
+ _s51_guyNextSequenceId = 0xC4;
+ break;
+ case 2:
+ _s51_guyNextSequenceId = 0xC5;
+ break;
+ case 3:
+ _s51_guyNextSequenceId = 0xC6;
+ break;
+ case 4:
+ _s51_guyNextSequenceId = 0xC7;
+ break;
+ }
+
+ _gameSys->insertSequence(_s51_guyNextSequenceId, 39, _s51_guySequenceId, 39, kSeqSyncWait, 0, 0, 0);
+ _s51_guySequenceId = _s51_guyNextSequenceId;
+ _s51_guyNextSequenceId = -1;
+
+ }
+
+}
+
+int GnapEngine::scene51_incCashAmount(int sequenceId) {
+ switch (sequenceId) {
+ case 0xBD:
+ _s51_cashAmount += 10;
+ break;
+ case 0xC0:
+ case 0xC1:
+ _s51_cashAmount += 100;
+ break;
+ case 0xB6:
+ case 0xB7:
+ _s51_cashAmount -= 10 * getRandom(5) + 50;
+ if (_s51_cashAmount < 0)
+ _s51_cashAmount = 0;
+ break;
+ }
+ if (_s51_cashAmount > 1995)
+ _s51_cashAmount = 1995;
+ scene51_updateCash(_s51_cashAmount);
+ return _s51_cashAmount;
+}
+
+void GnapEngine::scene51_winMinigame() {
+ scene51_updateCash(1995);
+ playSound(218, 0);
+ // TODO delayTicksA(1, 5);
+ _newSceneNum = 48;
+ invRemove(kItemBanana);
+}
+
+void GnapEngine::scene51_playCashAppearAnim() {
+ _gameSys->setAnimation(0xC8, 252, 0);
+ _gameSys->insertSequence(0xC8, 252, 0, 0, kSeqNone, 0, -20, -20);
+ while (_gameSys->getAnimationStatus(0) != 2) {
+ gameUpdateTick();
+ // checkGameAppStatus();
+ }
+}
+
+void GnapEngine::scene51_updateCash(int amount) {
+ scene51_drawDigit(amount / 1000, 0);
+ scene51_drawDigit(amount / 100 % 10, 1);
+ scene51_drawDigit(amount / 10 % 10, 2);
+ scene51_drawDigit(amount % 10, 3);
+}
+
+void GnapEngine::scene51_drawDigit(int digit, int position) {
+ if (digit != _s51_digits[position]) {
+ _gameSys->insertSequence(kDigitSequenceIds[digit], 253,
+ _s51_digitSequenceIds[position], 253,
+ kSeqSyncWait, 0, kDigitPositions[position] - 20, -20);
+ _s51_digitSequenceIds[position] = kDigitSequenceIds[digit];
+ _s51_digits[position] = digit;
+ }
+}
+
+void GnapEngine::scene51_initCashDisplay() {
+ for (int position = 0; position < 4; ++position) {
+ _s51_digits[position] = 0;
+ _s51_digitSequenceIds[position] = kDigitSequenceIds[0];
+ _gameSys->insertSequence(kDigitSequenceIds[0], 253, 0, 0,
+ kSeqNone, 0, kDigitPositions[position] - 20, -20);
+ }
+ _s51_cashAmount = 0;
+}
+
+void GnapEngine::scene51_run() {
+
+ int soundCtr = 0;
+ bool isIdle = true;
+
+ _s51_itemsCtr = 0;
+ _newSceneNum = _prevSceneNum;
+ _s51_cashAmount = 0;
+ _s51_platypusJumpSequenceId = 0x84;
+ endSceneInit();
+
+ hideCursor();
+ setGrabCursorSprite(-1);
+
+ _s51_guySequenceId = 0xC3;
+ _s51_guyNextSequenceId = -1;
+
+ _gameSys->insertSequence(0xC3, 39, 0, 0, kSeqNone, 0, 0, 0);
+
+ _timers[4] = getRandom(20) + 60;
+
+ scene51_playCashAppearAnim();
+ scene51_initCashDisplay();
+ scene51_playIntroAnim();
+
+ _s51_platypusNextSequenceId = 0x74;
+ _gameSys->setAnimation(0x74, 256, 0);
+ _gameSys->insertSequence(_s51_platypusNextSequenceId, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosRight(_s51_platypusJumpSequenceId) - 362, 0);
+ _s51_platypusSequenceId = _s51_platypusNextSequenceId;
+
+ _s51_itemInsertDirection = 0;
+ _s51_itemInsertX = 685;
+ _s51_dropSpeedTicks = 10;
+ _s51_nextDropItemKind = 0;
+
+ for (int i = 0; i < 6; ++i)
+ scene51_clearItem(&_s51_items[i]);
+
+ _s51_itemInsertX = getRandom(556) + 129;
+
+ _timers[0] = 15;
+
+ _s51_itemsCaughtCtr = 0;
+ _s51_dropLoseCash = false;
+ _s51_itemsCtr1 = 20;
+
+ clearKeyStatus1(Common::KEYCODE_RIGHT);
+ clearKeyStatus1(Common::KEYCODE_LEFT);
+ clearKeyStatus1(Common::KEYCODE_UP);
+ clearKeyStatus1(Common::KEYCODE_SPACE);
+ clearKeyStatus1(Common::KEYCODE_ESCAPE);
+
+ bool isCollision = false;
+ bool startWalk = true;
+
+ while (!_sceneDone) {
+
+ if (sceneXX_sub_4466B1())
+ _sceneDone = true;
+
+ gameUpdateTick();
+
+ scene51_updateGuyAnimation();
+ scene51_dropNextItem();
+ scene51_updateItemAnimations();
+
+ if (isKeyStatus2(Common::KEYCODE_UP) || isKeyStatus2(Common::KEYCODE_SPACE)) {
+ clearKeyStatus1(Common::KEYCODE_UP);
+ clearKeyStatus1(Common::KEYCODE_SPACE);
+ if (scene51_isJumpingRight(_s51_platypusJumpSequenceId)) {
+ scene51_waitForAnim(0);
+ _gameSys->setAnimation(0xB8, 256, 0);
+ _gameSys->insertSequence(0xB8, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosRight(_s51_platypusJumpSequenceId) - 348, 0);
+ _s51_platypusSequenceId = 0xB8;
+ scene51_waitForAnim(0);
+ _s51_platypusNextSequenceId += 6;
+ if (_s51_platypusNextSequenceId > 0x95)
+ _s51_platypusNextSequenceId = 0x95;
+ _s51_platypusJumpSequenceId = _s51_platypusNextSequenceId;
+ } else {
+ scene51_waitForAnim(0);
+ _gameSys->setAnimation(0xB9, 256, 0);
+ _gameSys->insertSequence(0xB9, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosLeft(_s51_platypusJumpSequenceId) - 338, 0);
+ _s51_platypusSequenceId = 0xB9;
+ scene51_waitForAnim(0);
+ _s51_platypusNextSequenceId += 6;
+ if (_s51_platypusNextSequenceId > 0xB5)
+ _s51_platypusNextSequenceId = 0xB5;
+ _s51_platypusJumpSequenceId = _s51_platypusNextSequenceId;
+ }
+ isIdle = false;
+ }
+
+ while (isKeyStatus2(Common::KEYCODE_RIGHT) && _s51_platypusNextSequenceId != 0x96) {
+ // pollMessages();
+ if (_s51_platypusNextSequenceId == 0xB6)
+ _s51_platypusNextSequenceId = 0x76;
+ scene51_updateItemAnimations();
+ if (startWalk) {
+ _s51_platypusNextSequenceId = 0x86;
+ startWalk = false;
+ }
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ int collisionX = scene51_checkCollision(_s51_platypusNextSequenceId);
+ if (collisionX)
+ scene51_incCashAmount(_s51_platypusNextSequenceId);
+ _gameSys->setAnimation(_s51_platypusNextSequenceId, 256, 0);
+ _gameSys->insertSequence(_s51_platypusNextSequenceId, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, collisionX, 0);
+ _s51_platypusSequenceId = _s51_platypusNextSequenceId;
+ if (collisionX) {
+ isCollision = true;
+ ++_s51_platypusJumpSequenceId;
+ _s51_platypusNextSequenceId = _s51_platypusJumpSequenceId;
+ } else {
+ _s51_platypusJumpSequenceId = _s51_platypusNextSequenceId;
+ }
+ if (scene51_isJumpingRight(_s51_platypusJumpSequenceId)) {
+ ++_s51_platypusNextSequenceId;
+ if (!isCollision) {
+ if (isKeyStatus2(Common::KEYCODE_UP) || isKeyStatus2(Common::KEYCODE_SPACE)) {
+ clearKeyStatus1(Common::KEYCODE_UP);
+ clearKeyStatus1(Common::KEYCODE_SPACE);
+ scene51_waitForAnim(0);
+ _gameSys->setAnimation(0xB8, 256, 0);
+ _gameSys->insertSequence(0xB8, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosRight(_s51_platypusJumpSequenceId) - 348, 0);
+ _s51_platypusSequenceId = 0xB8;
+ scene51_waitForAnim(0);
+ _s51_platypusNextSequenceId += 6;
+ if (_s51_platypusNextSequenceId > 0x95)
+ _s51_platypusNextSequenceId = 0x95;
+ _s51_platypusJumpSequenceId = _s51_platypusNextSequenceId;
+ } else {
+ ++soundCtr;
+ if (soundCtr % 4 == 0)
+ playSound(214, 0);
+ }
+ }
+ } else {
+ _s51_platypusNextSequenceId = 150 - (_s51_platypusJumpSequenceId - 150);
+ }
+ isCollision = false;
+ isIdle = false;
+ }
+ gameUpdateTick();
+ }
+
+ while (isKeyStatus2(Common::KEYCODE_LEFT) && _s51_platypusNextSequenceId != 0xB6) {
+ // pollMessages();
+ scene51_updateItemAnimations();
+ if (startWalk) {
+ _s51_platypusNextSequenceId = 0xA5;
+ startWalk = false;
+ }
+
+ if (_gameSys->getAnimationStatus(0) == 2) {
+ int collisionX = scene51_checkCollision(_s51_platypusNextSequenceId);
+ if (collisionX)
+ scene51_incCashAmount(_s51_platypusNextSequenceId);
+ _gameSys->setAnimation(_s51_platypusNextSequenceId, 256, 0);
+ _gameSys->insertSequence(_s51_platypusNextSequenceId, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, collisionX, 0);
+ _s51_platypusSequenceId = _s51_platypusNextSequenceId;
+ if (collisionX) {
+ isCollision = true;
+ ++_s51_platypusJumpSequenceId;
+ _s51_platypusNextSequenceId = _s51_platypusJumpSequenceId;
+ } else {
+ _s51_platypusJumpSequenceId = _s51_platypusNextSequenceId;
+ }
+ if (scene51_isJumpingLeft(_s51_platypusJumpSequenceId)) {
+ ++_s51_platypusNextSequenceId;
+ if (!isCollision) {
+ if (isKeyStatus2(Common::KEYCODE_UP) || isKeyStatus2(Common::KEYCODE_SPACE)) {
+ clearKeyStatus1(Common::KEYCODE_UP);
+ clearKeyStatus1(Common::KEYCODE_SPACE);
+ scene51_waitForAnim(0);
+ _gameSys->setAnimation(0xB9, 256, 0);
+ _gameSys->insertSequence(0xB9, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosLeft(_s51_platypusJumpSequenceId) - 338, 0);
+ _s51_platypusSequenceId = 0xB9;
+ scene51_waitForAnim(0);
+ _s51_platypusNextSequenceId += 6;
+ if (_s51_platypusNextSequenceId > 0xB5)
+ _s51_platypusNextSequenceId = 0xB5;
+ _s51_platypusJumpSequenceId = _s51_platypusNextSequenceId;
+ } else {
+ ++soundCtr;
+ if (soundCtr % 4 == 0)
+ playSound(214, 0);
+ }
+ }
+ } else {
+ _s51_platypusNextSequenceId = 182 - (_s51_platypusJumpSequenceId - 118);
+ }
+ isCollision = false;
+ isIdle = false;
+ }
+ gameUpdateTick();
+ }
+
+ if (!isIdle && _gameSys->getAnimationStatus(0) == 2) {
+ if (scene51_isJumpingRight(_s51_platypusJumpSequenceId)) {
+ _gameSys->setAnimation(0x74, 256, 0);
+ _gameSys->insertSequence(0x74, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosRight(_s51_platypusJumpSequenceId) - 362, 0);
+ _s51_platypusSequenceId = 0x74;
+ } else {
+ _gameSys->setAnimation(0x75, 256, 0);
+ _gameSys->insertSequence(0x75, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosLeft(_s51_platypusJumpSequenceId) - 341, 0);
+ _s51_platypusSequenceId = 0x75;
+ }
+ scene51_waitForAnim(0);
+ isIdle = true;
+ }
+
+ }
+
+ clearKeyStatus1(Common::KEYCODE_ESCAPE);
+ clearKeyStatus1(Common::KEYCODE_UP);
+ clearKeyStatus1(Common::KEYCODE_SPACE);
+ clearKeyStatus1(Common::KEYCODE_RIGHT);
+ clearKeyStatus1(Common::KEYCODE_LEFT);
+
+ _gameSys->setAnimation(0, 0, 0);
+ for (int i = 0; i < 6; ++i)
+ _gameSys->setAnimation(0, 0, i + 1);
+
+ showCursor();
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene52.cpp b/engines/gnap/scenes/scene52.cpp
new file mode 100644
index 0000000000..62cc2f3728
--- /dev/null
+++ b/engines/gnap/scenes/scene52.cpp
@@ -0,0 +1,907 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+int GnapEngine::scene52_init() {
+ scene52_initAnims();
+ return 0x2B;
+}
+
+void GnapEngine::scene52_updateHotspots() {
+ _hotspotsCount = 0;
+}
+
+void GnapEngine::scene52_update() {
+
+ for (int rowNum = 0; rowNum < 7; ++rowNum) {
+ gameUpdateTick();
+ if (_gameSys->getAnimationStatus(_s52_alienRowAnims[rowNum]) == 2) {
+ scene52_updateAlienRow(rowNum);
+ rowNum = 0;
+ }
+ }
+
+ if (_s52_liveAlienRows == 0 && !_s52_alienSingle) {
+ _s52_alienWave = false;
+ playSound(48, 0);
+ ++_s52_alienCounter;
+ if (_s52_alienCounter != 3) {
+ _timers[0] = 50;
+ _timers[2] = 100;
+ _s52_alienRowDownCtr = 0;
+ _s52_alienSingle = true;
+ }
+ }
+
+ if (_s52_alienSingle && !_timers[0]) {
+ scene52_initAliens();
+ _s52_alienSingle = false;
+ _timers[2] = 5;
+ _s52_alienWave = true;
+ }
+
+ if ((_s52_alienRowDownCtr || _s52_liveAlienRows == 0) && !_s52_alienSingle) {
+ scene52_moveDownAlienRow();
+ _s52_alienRowDownCtr = 0;
+ }
+
+ if (isKeyStatus1(Common::KEYCODE_UP) || isKeyStatus1(Common::KEYCODE_SPACE)) {
+ clearKeyStatus1(Common::KEYCODE_SPACE);
+ clearKeyStatus1(Common::KEYCODE_UP);
+ if (!_s52_aliensCount)
+ scene52_fireShipCannon(_s52_shipPosX);
+ }
+
+ if (_s52_shipCannonFiring)
+ scene52_updateShipCannon();
+
+ scene52_fireAlienCannon();
+ scene52_updateAlienCannons();
+
+ if (_s52_aliensCount == 1) {
+ _s52_alienWave = false;
+ _timers[3] = 20;
+ _timers[2] = 100;
+ ++_s52_aliensCount;
+ }
+
+ if (_s52_aliensCount && !_timers[3]) {
+ scene52_updateAliens();
+ scene52_loseShip();
+ if (_s52_shipsLeft != 0) {
+ _timers[3] = 40;
+ while (_timers[3]) {
+ scene52_updateAlienCannons();
+ if (_s52_shipCannonFiring)
+ scene52_updateShipCannon();
+ gameUpdateTick();
+ }
+ scene52_initAliens();
+ _s52_shipPosX = (800 - _s52_shipMidX) / 2;
+ _gameSys->setAnimation(_s52_nextUfoSequenceId, 256, 7);
+ _gameSys->insertSequence(_s52_nextUfoSequenceId, 256, 0, 0, kSeqNone, 0, _s52_shipPosX, _s52_arcadeScreenBottom);
+ _s52_ufoSequenceId = _s52_nextUfoSequenceId;
+ _timers[2] = 5;
+ _s52_alienWave = true;
+ } else {
+ _sceneDone = true;
+ }
+ }
+
+ if (_timers[1] || scene52_getFreeShipCannon() == -1) {
+ _s52_nextUfoSequenceId = 34;
+ if (_s52_ufoSequenceId != 34)
+ _s52_shipFlag = true;
+ } else {
+ _s52_nextUfoSequenceId = 34;
+ if (_s52_ufoSequenceId != 34)
+ _s52_shipFlag = true;
+ }
+
+ if (_s52_shipFlag) {
+ if (_gameSys->getAnimationStatus(7) == 2) {
+ _gameSys->setAnimation(_s52_nextUfoSequenceId, 256, 7);
+ _gameSys->insertSequence(_s52_nextUfoSequenceId, 256, _s52_ufoSequenceId, 256, kSeqSyncWait, 0, _s52_shipPosX, _s52_arcadeScreenBottom);
+ _s52_ufoSequenceId = _s52_nextUfoSequenceId;
+ }
+ _s52_shipFlag = false;
+ }
+
+ if (_s52_alienWave && !_timers[0]) {
+ scene52_playSound();
+ int v0 = _s52_alienSpeed;
+ if (_s52_alienSpeed >= 10)
+ v0 = 10;
+ int v1 = v0;
+ if (v0 < 2)
+ v1 = 2;
+ _timers[0] = v1;
+ }
+}
+
+void GnapEngine::scene52_initShipCannon(int bottomY) {
+ _s52_shipCannonFired = 0;
+ _s52_shipCannonWidth = MAX(_gameSys->getSpriteWidthById(14), _gameSys->getSpriteWidthById(16));
+ _s52_shipCannonHeight = MAX(_gameSys->getSpriteHeightById(14), _gameSys->getSpriteHeightById(16));
+ _s52_shipCannonTopY = bottomY - _s52_shipCannonHeight;
+ _s52_shipCannonFiring = 0;
+}
+
+void GnapEngine::scene52_initAlienCannons() {
+ for (int i = 0; i < 3; ++i) {
+ _s52_alienCannonIds[i] = 0;
+ _s52_alienCannonFired[i] = 0;
+ }
+ _s52_alienCannonSequenceIds[0] = 30;
+ _s52_alienCannonSequenceIds[1] = 31;
+ _s52_alienCannonSequenceIds[2] = 32;
+}
+
+void GnapEngine::scene52_fireShipCannon(int posX) {
+
+ if (_timers[1])
+ return;
+
+ int cannonNum = scene52_getFreeShipCannon();
+ if (cannonNum != -1) {
+ _s52_shipCannonPosX = _s52_shipMidX / 2 + posX - _s52_shipCannonWidth / 2;
+ _s52_shipCannonPosY = _s52_shipCannonTopY;
+ _gameSys->setAnimation(0x23, cannonNum + 256, cannonNum + 8);
+ _gameSys->insertSequence(0x23, cannonNum + 256, 0, 0, kSeqNone, 0, _s52_shipCannonPosX, _s52_shipCannonPosY);
+ playSound(0x2D, 0);
+ if (scene52_shipCannonHitShield(cannonNum)) {
+ _gameSys->setAnimation(0, 0, cannonNum + 8);
+ _gameSys->removeSequence(0x23, cannonNum + 256, 1);
+ } else {
+ _s52_shipCannonFired = 1;
+ _s52_shipCannonPosY -= 13;
+ _s52_shipCannonFiring = 1;
+ }
+ _timers[1] = 5;
+ }
+
+}
+
+void GnapEngine::scene52_fireAlienCannon() {
+
+ if (_timers[2])
+ return;
+
+ int cannonNum = scene52_getFreeAlienCannon();
+ if (cannonNum != -1) {
+ int alienX1 = _s52_alienLeftX + _s52_alienRowXOfs[0];
+ int alienX2 = _s52_alienLeftX + _s52_alienRowXOfs[0] + 5 * _s52_alienWidth - (_s52_alienWidth / 2 - 15);
+ _s52_alienCannonPosX[cannonNum] = getRandom(alienX2 - alienX1) + alienX1;
+ _s52_alienCannonPosY[cannonNum] = 104;
+ _s52_alienCannonFired[cannonNum] = 1;
+ _gameSys->setAnimation(_s52_alienCannonSequenceIds[cannonNum], _s52_alienCannonIds[cannonNum] + 256, cannonNum + 9);
+ _gameSys->insertSequence(_s52_alienCannonSequenceIds[cannonNum], _s52_alienCannonIds[cannonNum] + 256, 0, 0,
+ kSeqNone, 0, _s52_alienCannonPosX[cannonNum], _s52_alienCannonPosY[cannonNum]);
+ _s52_alienCannonPosY[cannonNum] -= 13;
+ _timers[2] = 5;
+ }
+
+}
+
+int GnapEngine::scene52_getFreeShipCannon() {
+ if (!_s52_shipCannonFired)
+ return 0;
+ return -1;
+}
+
+int GnapEngine::scene52_getFreeAlienCannon() {
+ for (int i = 0; i < 3; ++i)
+ if (!_s52_alienCannonFired[i])
+ return i;
+ return -1;
+}
+
+void GnapEngine::scene52_updateShipCannon() {
+ if (_s52_shipCannonFired && _gameSys->getAnimationStatus(8) == 2) {
+ _s52_shipCannonPosY -= 13;
+ if (_s52_shipCannonPosY - 13 >= 135) {
+ if (scene52_updateHitAlien()) {
+ _gameSys->setAnimation(0, 0, 8);
+ _gameSys->removeSequence(35, 256, 1);
+ _s52_shipCannonFired = 0;
+ scene52_drawScore(_s52_gameScore);
+ } else {
+ _gameSys->setAnimation(35, 256, 8);
+ _gameSys->insertSequence(35, 256, 35, 256, kSeqSyncWait, 0, _s52_shipCannonPosX, _s52_shipCannonPosY);
+ _s52_shipCannonPosY -= 13;
+ }
+ } else {
+ _gameSys->setAnimation(0, 0, 8);
+ _gameSys->removeSequence(35, 256, 1);
+ _s52_shipCannonFired = 0;
+ }
+ }
+}
+
+void GnapEngine::scene52_updateAlienCannons() {
+ for (int i = 0; i < 3; ++i) {
+ if (_s52_alienCannonFired[i] && _gameSys->getAnimationStatus(i + 9) == 2) {
+ _s52_alienCannonPosY[i] += 13;
+ if (_s52_shipCannonHeight + _s52_alienCannonPosY[i] + 13 <= 550) {
+ if (scene52_alienCannonHitShip(i)) {
+ _gameSys->setAnimation(0, 0, i + 9);
+ _s52_alienCannonFired[i] = 0;
+ scene52_shipExplode();
+ } else if (scene52_alienCannonHitShield(i)) {
+ _s52_alienCannonFired[i] = 0;
+ } else {
+ _gameSys->insertSequence(_s52_alienCannonSequenceIds[i], 1 - _s52_alienCannonIds[i] + 256, 0, 0,
+ kSeqNone, 0, _s52_alienCannonPosX[i], _s52_alienCannonPosY[i]);
+ _gameSys->setAnimation(_s52_alienCannonSequenceIds[i], 1 - _s52_alienCannonIds[i] + 256, i + 9);
+ _s52_alienCannonIds[i] = 1 - _s52_alienCannonIds[i];
+ _s52_alienCannonPosY[i] += 13;
+ }
+ } else {
+ _gameSys->setAnimation(0, 0, i + 9);
+ _s52_alienCannonFired[i] = 0;
+ }
+ }
+ }
+}
+
+void GnapEngine::scene52_initAliens() {
+
+ if (!_s52_aliensInitialized) {
+ scene52_initAlienSize();
+ _s52_aliensInitialized = true;
+ }
+
+ _s52_liveAlienRows = 0;
+ _s52_alienSpeed = 0;
+ _s52_bottomAlienFlag = false;
+ _s52_aliensCount = 0;
+ _s52_alienSingle = false;
+ _s52_alienRowDownCtr = 0;
+
+ scene52_initShields();
+
+ _s52_alienRowKind[0] = -1;
+ _s52_alienRowKind[1] = -1;
+ _s52_alienRowKind[2] = -1;
+ _s52_alienRowKind[3] = -1;
+ _s52_alienRowKind[4] = getRandom(2) != 0 ? 24 : 27;
+ _s52_alienRowKind[5] = getRandom(2) != 0 ? 25 : 28;
+ _s52_alienRowKind[6] = getRandom(2) != 0 ? 26 : 29;
+
+ for (int i = 0; i < 7; ++i) {
+ _s52_alienRowAnims[i] = i;
+ _s52_alienRowXOfs[i] = 0;
+ scene52_initAlienRowKind(i, _s52_alienRowKind[i]);
+ scene52_insertAlienRow(i);
+ }
+
+}
+
+void GnapEngine::scene52_initAlienRowKind(int rowNum, int alienKind) {
+ for (int i = 0; i < 5; ++i)
+ _s52_items[rowNum][i] = alienKind;
+}
+
+void GnapEngine::scene52_insertAlienRow(int rowNum) {
+ if (_s52_alienRowKind[rowNum] >= 0) {
+ scene52_insertAlienRowAliens(rowNum);
+ _s52_alienRowIds[rowNum] = 256;
+ _gameSys->setAnimation(_s52_alienRowKind[rowNum], _s52_alienRowIds[rowNum], _s52_alienRowAnims[rowNum]);
+ ++_s52_liveAlienRows;
+ }
+}
+
+void GnapEngine::scene52_insertAlienRowAliens(int rowNum) {
+ int xOffs = _s52_alienLeftX;
+ int yOffs = _s52_alienTopY - 52 * rowNum - _s52_alienHeight + 10;
+ for (int i = 0; i < 5; ++i) {
+ if (_s52_items[rowNum][i] >= 0) {
+ _gameSys->insertSequence(_s52_items[rowNum][i], i + 256, 0, 0, kSeqNone, 0, xOffs, yOffs);
+ ++_s52_alienSpeed;
+ }
+ xOffs += _s52_alienWidth;
+ }
+}
+
+void GnapEngine::scene52_updateAlienRow(int rowNum) {
+
+ if (_s52_alienRowKind[rowNum] != -1 && !scene52_checkAlienRow(rowNum)) {
+ scene52_updateAlienRowXOfs();
+ _s52_alienRowIds[rowNum] = -1;
+ int xOffs = _s52_alienLeftX + _s52_alienRowXOfs[rowNum];
+ int yOffs = _s52_alienTopY - 52 * rowNum - _s52_alienHeight + 10;
+ for (int i = 0; i < 5; ++i) {
+ if (_s52_items[rowNum][i] >= 0) {
+ _gameSys->insertSequence(_s52_items[rowNum][i], i + 256, _s52_items[rowNum][i], i + 256, kSeqSyncWait, 0, xOffs, yOffs);
+ if (_s52_alienRowIds[rowNum] == -1)
+ _s52_alienRowIds[rowNum] = i + 256;
+ } else if (_s52_items[rowNum][i] == -2) {
+ _gameSys->removeSequence(_s52_alienRowKind[rowNum], i + 256, 1);
+ _s52_items[rowNum][i] = -1;
+ --_s52_alienSpeed;
+ }
+ xOffs += _s52_alienWidth;
+ }
+ if (_s52_alienRowIds[rowNum] == -1) {
+ _gameSys->setAnimation(0, 0, _s52_alienRowAnims[rowNum]);
+ // MessageBoxA(0, "No live aliens!", "Error 3:", 0x30u);
+ } else {
+ _gameSys->setAnimation(_s52_alienRowKind[rowNum], _s52_alienRowIds[rowNum], _s52_alienRowAnims[rowNum]);
+ }
+ if (rowNum == 1) {
+ for (int j = 0; j < 3; ++j) {
+ if (_s52_shieldSpriteIds[j] != -1) {
+ _gameSys->fillSurface(0, _s52_shieldPosX[j], _s52_arcadeScreenBottom - 44, 33, 44, 0, 0, 0);
+ _s52_shieldSpriteIds[j] = -1;
+ }
+ }
+ }
+ if (rowNum == 0 && _s52_bottomAlienFlag)
+ scene52_shipExplode();
+ }
+}
+
+void GnapEngine::scene52_moveDownAlienRow() {
+
+ int v2[5], v3, v1, v0, v4;
+
+ for (int i = 0; i < 5; ++i)
+ v2[i] = _s52_items[0][i];
+
+ v3 = _s52_alienRowIds[0];
+ v1 = _s52_alienRowAnims[0];
+ v0 = _s52_alienRowKind[0];
+ v4 = _s52_alienRowXOfs[0];
+
+ for (int j = 0; j < 7; ++j) {
+ for (int i = 0; i < 5; ++i)
+ _s52_items[j][i] = _s52_items[j + 1][i];
+ _s52_alienRowIds[j] = _s52_alienRowIds[j + 1];
+ _s52_alienRowAnims[j] = _s52_alienRowAnims[j + 1];
+ _s52_alienRowKind[j] = _s52_alienRowKind[j + 1];
+ _s52_alienRowXOfs[j] = _s52_alienRowXOfs[j + 1];
+ }
+
+ for (int i = 0; i < 5; ++i)
+ _s52_items[6][i] = v2[i];
+
+ _s52_alienRowIds[6] = v3;
+ _s52_alienRowAnims[6] = v1;
+ _s52_alienRowKind[6] = v0;
+ _s52_alienRowXOfs[6] = v4;
+
+ scene52_updateAlien(6);
+ scene52_initAlienRowKind(6, _s52_alienRowKind[6]);
+ scene52_insertAlienRow(6);
+
+ _s52_bottomAlienFlag = _s52_alienRowKind[0] > -1;
+}
+
+int GnapEngine::scene52_updateHitAlien() {
+ int result = 0, rowNum, ya;
+
+ int y = _s52_shipCannonTopY - _s52_shipCannonPosY;
+
+ if (y == 26) {
+ rowNum = 1;
+ ya = _s52_shipCannonPosY + 26;
+ } else {
+ if (y % 52)
+ return 0;
+ rowNum = y / 52 + 1;
+ ya = _s52_shipCannonPosY;
+ }
+
+ if (rowNum < 7) {
+ int hitAlienNum = scene52_getHitAlienNum(rowNum);
+ if (hitAlienNum != -1 && _s52_items[rowNum][hitAlienNum] >= 0) {
+ _s52_gameScore = ((_s52_items[rowNum][hitAlienNum] - 24) % 3 + _s52_gameScore + 1) % 1000;
+ _s52_items[rowNum][hitAlienNum] = -2;
+ playSound(44, 0);
+ _gameSys->insertSequence(0x21, 266, 0, 0,
+ kSeqNone, 0, _s52_alienLeftX + hitAlienNum * _s52_alienWidth + _s52_alienRowXOfs[rowNum] - 10, ya - _s52_alienHeight);
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+int GnapEngine::scene52_getHitAlienNum(int rowNum) {
+
+ int result = -1;
+
+ int v3 = _s52_alienLeftX + _s52_alienRowXOfs[rowNum];
+
+ if (_s52_shipCannonPosX >= v3) {
+ int v8 = _s52_alienWidth / 2 - 15;
+ if (v3 + 5 * _s52_alienWidth - v8 >= _s52_shipCannonPosX) {
+ int v4 = v3 + _s52_alienWidth;
+ if (_s52_shipCannonPosX >= v4 - v8) {
+ int v5 = v4 + _s52_alienWidth;
+ if (_s52_shipCannonPosX >= v5 - v8) {
+ int v6 = v5 + _s52_alienWidth;
+ if (_s52_shipCannonPosX >= v6 - v8) {
+ int v7 = v6 + _s52_alienWidth;
+ if (_s52_shipCannonPosX >= v7 - v8) {
+ if (_s52_shipCannonPosX >= v7 + _s52_alienWidth - v8)
+ result = -1;
+ else
+ result = 4;
+ } else {
+ result = 3;
+ }
+ } else {
+ result = 2;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 0;
+ }
+ } else {
+ result = -1;
+ }
+ } else {
+ result = -1;
+ }
+ return result;
+}
+
+int GnapEngine::scene52_alienCannonHitShip(int cannonNum) {
+ int result = 0;
+
+ if (_s52_aliensCount) {
+ result = 0;
+ } else {
+ int cannonY = _s52_alienCannonPosY[cannonNum] - 13;
+ if (_s52_arcadeScreenBottom <= cannonY) {
+ if (_s52_shipMidY + _s52_arcadeScreenBottom > cannonY) {
+ if (_s52_alienCannonPosX[cannonNum] >= _s52_shipPosX)
+ result = _s52_alienCannonPosX[cannonNum] < _s52_shipMidX + _s52_shipPosX;
+ else
+ result = 0;
+ } else {
+ result = 0;
+ }
+ } else {
+ result = 0;
+ }
+ }
+ return result;
+}
+
+int GnapEngine::scene52_alienCannonHitShield(int cannonNum) {
+ int result = 0;
+
+ int v3 = _s52_alienCannonPosY[cannonNum] + 39;
+ if (_s52_arcadeScreenBottom - 44 > v3)
+ return 0;
+
+ if (_s52_arcadeScreenBottom <= v3)
+ return 0;
+
+ if (_s52_alienCannonPosX[cannonNum] < _s52_shieldPosX[0])
+ return 0;
+
+ if (_s52_alienCannonPosX[cannonNum] > _s52_shieldPosX[2] + 33)
+ return 0;
+
+ int shieldNum = -1;
+ if (_s52_alienCannonPosX[cannonNum] < _s52_shieldPosX[0] + 33)
+ shieldNum = 0;
+
+ if (shieldNum < 0 && _s52_alienCannonPosX[cannonNum] < _s52_shieldPosX[1])
+ return 0;
+
+ if (shieldNum < 0 && _s52_alienCannonPosX[cannonNum] < _s52_shieldPosX[1] + 33)
+ shieldNum = 1;
+
+ if (shieldNum < 0) {
+ if (_s52_alienCannonPosX[cannonNum] < _s52_shieldPosX[2])
+ return 0;
+ shieldNum = 2;
+ }
+
+ if (_s52_shieldSpriteIds[shieldNum] == -1) {
+ result = 0;
+ } else {
+ ++_s52_shieldSpriteIds[shieldNum];
+ if (_s52_shieldSpriteIds[shieldNum] <= 21) {
+ _gameSys->drawSpriteToBackground(_s52_shieldPosX[shieldNum], _s52_arcadeScreenBottom - 44, _s52_shieldSpriteIds[shieldNum]);
+ } else {
+ _gameSys->fillSurface(0, _s52_shieldPosX[shieldNum], _s52_arcadeScreenBottom - 44, 33, 44, 0, 0, 0);
+ _s52_shieldSpriteIds[shieldNum] = -1;
+ }
+ _gameSys->setAnimation(0, 0, cannonNum + 9);
+ _gameSys->insertSequence(0x21, shieldNum + 257, 0, 0, kSeqNone, 0, _s52_alienCannonPosX[cannonNum] - 18, _s52_arcadeScreenBottom - 44);
+ playSound(0x2C, 0);
+ result = 1;
+ }
+
+ return result;
+}
+
+int GnapEngine::scene52_shipCannonHitShield(int cannonNum) {
+ int result = 0;
+
+ if (_s52_shipCannonPosX < _s52_shieldPosX[0])
+ return 0;
+
+ if (_s52_shipCannonPosX > _s52_shieldPosX[2] + 33)
+ return 0;
+
+ int shieldNum = -1;
+ if (_s52_shipCannonPosX < _s52_shieldPosX[0] + 33)
+ shieldNum = 0;
+
+ if (shieldNum < 0 && _s52_shipCannonPosX < _s52_shieldPosX[1])
+ return 0;
+
+ if (shieldNum < 0 && _s52_shipCannonPosX < _s52_shieldPosX[1] + 33)
+ shieldNum = 1;
+
+ if (shieldNum < 0) {
+ if (_s52_shipCannonPosX < _s52_shieldPosX[2])
+ return 0;
+ shieldNum = 2;
+ }
+
+ if (_s52_shieldSpriteIds[shieldNum] == -1) {
+ result = 0;
+ } else {
+ ++_s52_shieldSpriteIds[shieldNum];
+ if (_s52_shieldSpriteIds[shieldNum] <= 21) {
+ _gameSys->drawSpriteToBackground(_s52_shieldPosX[shieldNum], _s52_arcadeScreenBottom - 44, _s52_shieldSpriteIds[shieldNum]);
+ } else {
+ _gameSys->fillSurface(0, _s52_shieldPosX[shieldNum], _s52_arcadeScreenBottom - 44, 33, 44, 0, 0, 0);
+ _s52_shieldSpriteIds[shieldNum] = -1;
+ }
+ _gameSys->insertSequence(0x21, shieldNum + 257, 0, 0, kSeqNone, 0, _s52_shipCannonPosX - 18, _s52_arcadeScreenBottom - 44);
+ playSound(0x2C, 0);
+ result = 1;
+ }
+
+ return result;
+}
+
+int GnapEngine::scene52_shipCannonHitAlien() {
+ int result = 0;
+
+ if (_s52_aliensCount) {
+ result = 0;
+ } else if (scene52_checkAlienRow(0)) {
+ result = 0;
+ } else {
+ int v1 = _s52_alienLeftX + _s52_alienRowXOfs[0];
+ if (_s52_shipMidX + _s52_shipPosX >= _s52_alienLeftX + _s52_alienRowXOfs[0]) {
+ int v7 = _s52_alienWidth / 2 - 15;
+ if (v1 + 5 * _s52_alienWidth - v7 >= _s52_shipPosX) {
+ int v2 = v1 + _s52_alienWidth;
+ if (_s52_items[0][0] <= -1 || v2 - v7 <= _s52_shipPosX) {
+ int v3 = v2 + _s52_alienWidth;
+ if (_s52_items[0][1] <= -1 || v3 - v7 <= _s52_shipPosX) {
+ int v4 = v3 + _s52_alienWidth;
+ if (_s52_items[0][2] <= -1 || v4 - v7 <= _s52_shipPosX) {
+ int v5 = v4 + _s52_alienWidth;
+ if (_s52_items[0][3] <= -1 || v5 - v7 <= _s52_shipPosX) {
+ int v6 = v5 + _s52_alienWidth;
+ result = _s52_items[0][4] > -1 && v6 - v7 > _s52_shipPosX;
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 0;
+ }
+ } else {
+ result = 0;
+ }
+ }
+
+ return result;
+}
+
+void GnapEngine::scene52_shipExplode() {
+ if (!_s52_aliensCount) {
+ _gameSys->setAnimation(0, 0, 7);
+ _gameSys->removeSequence(_s52_ufoSequenceId, 256, 1);
+ playSound(44, 0);
+ _gameSys->insertSequence(0x21, 266, 0, 0, kSeqNone, 0, _s52_shipPosX, _s52_arcadeScreenBottom);
+ _s52_aliensCount = 1;
+ playSound(0x31, 0);
+ }
+}
+
+int GnapEngine::scene52_checkAlienRow(int rowNum) {
+
+ int v4 = 0;
+
+ for (int i = 0; i < 5; ++i)
+ if (_s52_items[rowNum][i] >= 0)
+ return 0;
+
+ for (int j = 0; j < 5; ++j)
+ if (_s52_items[rowNum][j] == -2) {
+ _gameSys->removeSequence(_s52_alienRowKind[rowNum], j + 256, 1);
+ _s52_items[rowNum][j] = -1;
+ --_s52_alienSpeed;
+ v4 = 1;
+ }
+
+ if (v4) {
+ _gameSys->setAnimation(0, 0, _s52_alienRowAnims[rowNum]);
+ --_s52_liveAlienRows;
+ }
+
+ if (_s52_liveAlienRows < 0)
+ _s52_liveAlienRows = 0;
+
+ return 1;
+}
+
+void GnapEngine::scene52_updateAlienRowXOfs() {
+
+ int amount = 2 * (3 - _s52_liveAlienRows) + 1;
+
+ if (_s52_alienSpeed == 2)
+ amount *= 4;
+ else if (_s52_alienSpeed == 1)
+ amount *= 10;
+
+ if (_s52_alienDirection) {
+ for (int i = 0; i < 7; ++i) {
+ _s52_alienRowXOfs[i] -= amount;
+ if (_s52_alienRowXOfs[i] <= -100) {
+ _s52_alienRowXOfs[i] = -100;
+ _s52_alienDirection = 0;
+ ++_s52_alienRowDownCtr;
+ }
+ }
+ } else {
+ for (int j = 0; j < 7; ++j) {
+ _s52_alienRowXOfs[j] += amount;
+ if (_s52_alienRowXOfs[j] >= 100) {
+ _s52_alienRowXOfs[j] = 100;
+ _s52_alienDirection = 1;
+ ++_s52_alienRowDownCtr;
+ }
+ }
+ }
+
+}
+
+void GnapEngine::scene52_initAlienSize() {
+
+ _s52_alienWidth = _gameSys->getSpriteWidthById(0);
+ if (_gameSys->getSpriteWidthById(1) > _s52_alienWidth)
+ _s52_alienWidth = _gameSys->getSpriteWidthById(1);
+ if (_gameSys->getSpriteWidthById(4) > _s52_alienWidth)
+ _s52_alienWidth = _gameSys->getSpriteWidthById(4);
+ if (_gameSys->getSpriteWidthById(5) > _s52_alienWidth)
+ _s52_alienWidth = _gameSys->getSpriteWidthById(5);
+ if (_gameSys->getSpriteWidthById(12) > _s52_alienWidth)
+ _s52_alienWidth = _gameSys->getSpriteWidthById(12);
+ if (_gameSys->getSpriteWidthById(13) > _s52_alienWidth)
+ _s52_alienWidth = _gameSys->getSpriteWidthById(13);
+
+ _s52_alienHeight = _gameSys->getSpriteHeightById(0);
+ if (_gameSys->getSpriteHeightById(1) > _s52_alienHeight)
+ _s52_alienHeight = _gameSys->getSpriteHeightById(1);
+ if (_gameSys->getSpriteHeightById(4) > _s52_alienHeight)
+ _s52_alienHeight = _gameSys->getSpriteHeightById(4);
+ if (_gameSys->getSpriteHeightById(5) > _s52_alienHeight)
+ _s52_alienHeight = _gameSys->getSpriteHeightById(5);
+ if (_gameSys->getSpriteHeightById(12) > _s52_alienHeight)
+ _s52_alienHeight = _gameSys->getSpriteHeightById(12);
+ if (_gameSys->getSpriteHeightById(13) > _s52_alienHeight)
+ _s52_alienHeight = _gameSys->getSpriteHeightById(13);
+
+ _s52_alienTopY = _s52_shipCannonTopY + 52;
+ _s52_alienLeftX = (800 - 5 * _s52_alienWidth) / 2;
+
+}
+
+void GnapEngine::scene52_playSound() {
+ if (_s52_soundToggle) {
+ playSound(0x2F, 0);
+ _s52_soundToggle = false;
+ } else {
+ playSound(0x2E, 0);
+ _s52_soundToggle = true;
+ }
+}
+
+void GnapEngine::scene52_updateAliens() {
+ for (int i = 0; i < 7; ++i)
+ scene52_updateAlien(i);
+}
+
+void GnapEngine::scene52_updateAlien(int rowNum) {
+ if (_s52_alienRowKind[rowNum] >= 0 && !scene52_checkAlienRow(rowNum)) {
+ for (int i = 0; i < 5; ++i)
+ if (_s52_items[rowNum][i] >= 0)
+ _s52_items[rowNum][i] = -2;
+ scene52_checkAlienRow(rowNum);
+ }
+}
+
+void GnapEngine::scene52_loseShip() {
+ --_s52_shipsLeft;
+ if (_s52_shipsLeft == 2) {
+ _gameSys->fillSurface(0, 120, 140, _s52_shipMidX, _s52_shipMidY, 0, 0, 0);
+ } else if (_s52_shipsLeft == 1) {
+ _gameSys->fillSurface(0, 120, 185, _s52_shipMidX, _s52_shipMidY, 0, 0, 0);
+ }
+}
+
+void GnapEngine::scene52_initShields() {
+ for (int i = 0; i < 3; ++i) {
+ _gameSys->drawSpriteToBackground(_s52_shieldPosX[i], _s52_arcadeScreenBottom - 44, 17);
+ _s52_shieldSpriteIds[i] = 17;
+ }
+}
+
+void GnapEngine::scene52_initAnims() {
+ for (int i = 0; i < 7; ++i)
+ _gameSys->setAnimation(0, 0, i);
+ _gameSys->setAnimation(0, 0, 7);
+ for (int j = 0; j < 1; ++j)
+ _gameSys->setAnimation(0, 0, j + 8);
+ for (int k = 0; k < 3; ++k)
+ _gameSys->setAnimation(0, 0, k + 9);
+}
+
+void GnapEngine::scene52_drawScore(int a1) {
+ char str[4];
+ sprintf(str, "%03d", a1);
+ _gameSys->fillSurface(0, 420, 80, 48, 30, 0, 0, 0);
+ _gameSys->drawTextToSurface(0, 420, 80, 255, 255, 255, str);
+}
+
+void GnapEngine::scene52_run() {
+
+ _timers[1] = 0;
+
+ hideCursor();
+
+ // TODO loadFont("maturasc", "Matura MT Script Capitals", 2000);
+ // TODO setFontSize(24);
+
+ _s52_gameScore = 0;
+ _gameSys->drawTextToSurface(0, 300, 80, 255, 255, 255, "SCORE");
+ _gameSys->drawTextToSurface(0, 468, 80, 255, 255, 255, "0");
+
+ scene52_drawScore(0);
+
+ _s52_shipMidX = 33;
+ _s52_shipMidY = _gameSys->getSpriteHeightById(15);
+ _s52_shipPosX = (800 - _s52_shipMidX) / 2;
+ _s52_arcadeScreenBottom = 496;
+ _s52_arcadeScreenRight = 595 - _s52_shipMidX;
+ _s52_arcadeScreenLeft = 210;
+ _s52_shipsLeft = 3;
+ _s52_alienCounter = 0;
+
+ _s52_shieldPosX[0] = 247;
+ _s52_shieldPosX[1] = 387;
+ _s52_shieldPosX[2] = 525;
+
+ for (int i = 0; i < 3; ++i)
+ _s52_shieldSpriteIds[i] = -1;
+
+ _gameSys->drawSpriteToBackground(120, 140, 0xF);
+ _gameSys->drawSpriteToBackground(120, 185, 0xF);
+
+ scene52_initShipCannon(_s52_arcadeScreenBottom);
+ scene52_initAlienCannons();
+ scene52_initAliens();
+
+ _s52_nextUfoSequenceId = 0x22;
+ _gameSys->setAnimation(0x22, 256, 7);
+ _gameSys->insertSequence(_s52_nextUfoSequenceId, 256, 0, 0, kSeqNone, 0, _s52_shipPosX, _s52_arcadeScreenBottom);
+
+ _s52_ufoSequenceId = _s52_nextUfoSequenceId;
+
+ clearKeyStatus1(Common::KEYCODE_RIGHT);
+ clearKeyStatus1(Common::KEYCODE_LEFT);
+ clearKeyStatus1(Common::KEYCODE_SPACE);
+ clearKeyStatus1(Common::KEYCODE_UP);
+ clearKeyStatus1(Common::KEYCODE_ESCAPE);
+
+ _timers[2] = 5;
+ _s52_shipFlag = false;
+
+ _timers[0] = 10;
+ _s52_alienWave = true;
+
+ while (!_sceneDone) {
+
+ gameUpdateTick();
+
+ while (isKeyStatus2(Common::KEYCODE_RIGHT)) {
+ scene52_update();
+ if (_gameSys->getAnimationStatus(7) == 2) {
+ if (_s52_shipPosX < _s52_arcadeScreenRight) {
+ _s52_shipPosX += 15;
+ if (_s52_shipPosX > _s52_arcadeScreenRight)
+ _s52_shipPosX = _s52_arcadeScreenRight;
+ _gameSys->setAnimation(_s52_nextUfoSequenceId, 256, 7);
+ _gameSys->insertSequence(_s52_nextUfoSequenceId, 256, _s52_ufoSequenceId, 256, kSeqSyncWait, 0, _s52_shipPosX, _s52_arcadeScreenBottom);
+ _s52_ufoSequenceId = _s52_nextUfoSequenceId;
+ if (_s52_bottomAlienFlag && scene52_shipCannonHitAlien())
+ scene52_shipExplode();
+ }
+ break;
+ }
+ }
+
+ while (isKeyStatus2(Common::KEYCODE_LEFT)) {
+ scene52_update();
+ if (_gameSys->getAnimationStatus(7) == 2) {
+ if (_s52_shipPosX > _s52_arcadeScreenLeft) {
+ _s52_shipPosX -= 15;
+ if (_s52_shipPosX < _s52_arcadeScreenLeft)
+ _s52_shipPosX = _s52_arcadeScreenLeft;
+ _gameSys->setAnimation(_s52_nextUfoSequenceId, 256, 7);
+ _gameSys->insertSequence(_s52_nextUfoSequenceId, 256, _s52_ufoSequenceId, 256, kSeqSyncWait, 0, _s52_shipPosX, _s52_arcadeScreenBottom);
+ _s52_ufoSequenceId = _s52_nextUfoSequenceId;
+ if (_s52_bottomAlienFlag && scene52_shipCannonHitAlien())
+ scene52_shipExplode();
+ }
+ break;
+ }
+ }
+
+ scene52_update();
+
+ if (sceneXX_sub_4466B1()) {
+ _s52_alienWave = false;
+ _gameSys->waitForUpdate();
+ scene52_initAnims();
+ clearKeyStatus1(30);
+ _sceneDone = true;
+ }
+
+ }
+
+ // TODO freeFont();
+
+ _gameSys->waitForUpdate();
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene53.cpp b/engines/gnap/scenes/scene53.cpp
new file mode 100644
index 0000000000..20486eb34e
--- /dev/null
+++ b/engines/gnap/scenes/scene53.cpp
@@ -0,0 +1,383 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+int GnapEngine::scene53_init() {
+ _gameSys->setAnimation(0, 0, 0);
+ _gameSys->setAnimation(0, 0, 1);
+ return 0x75;
+}
+
+void GnapEngine::scene53_updateHotspots() {
+ setHotspot(0, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR);
+ setHotspot(2, 336, 361, 238, 270, SF_GRAB_CURSOR);
+ setHotspot(3, 376, 405, 243, 274, SF_GRAB_CURSOR);
+ setHotspot(4, 415, 441, 248, 276, SF_GRAB_CURSOR);
+ setHotspot(5, 329, 358, 276, 303, SF_GRAB_CURSOR);
+ setHotspot(6, 378, 408, 282, 311, SF_GRAB_CURSOR);
+ setHotspot(7, 417, 446, 286, 319, SF_GRAB_CURSOR);
+ setHotspot(8, 332, 361, 311, 342, SF_GRAB_CURSOR);
+ setHotspot(9, 376, 407, 318, 349, SF_GRAB_CURSOR);
+ setHotspot(10, 417, 447, 320, 353, SF_GRAB_CURSOR);
+ setHotspot(11, 377, 405, 352, 384, SF_GRAB_CURSOR);
+ setHotspot(12, 419, 450, 358, 394, SF_GRAB_CURSOR);
+ setHotspot(13, 328, 359, 346, 379, SF_GRAB_CURSOR);
+ setHotspot(14, 150, 650, 585, 600, SF_EXIT_D_CURSOR);
+ setDeviceHotspot(1, -1, -1, -1, -1);
+ _hotspotsCount = 15;
+}
+
+int GnapEngine::scene53_pressPhoneNumberButton(int phoneNumber, int buttonNum) {
+
+ static const int kGnapHandSequenceIds[13] = {
+ 0x00,
+ 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B,
+ 0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x4F
+ };
+
+ static const int kPlatypusHandSequenceIds[13] = {
+ 0x00,
+ 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5A, 0x5C, 0x5D, 0x5B
+ };
+
+ if (_s53_isGnapPhoning) {
+ _gameSys->setAnimation(kGnapHandSequenceIds[buttonNum], 40, 6);
+ _gameSys->insertSequence(kGnapHandSequenceIds[buttonNum], 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _s53_currHandSequenceId = kGnapHandSequenceIds[buttonNum];
+ } else {
+ _gameSys->setAnimation(kPlatypusHandSequenceIds[buttonNum], 40, 6);
+ _gameSys->insertSequence(kPlatypusHandSequenceIds[buttonNum], 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _s53_currHandSequenceId = kPlatypusHandSequenceIds[buttonNum];
+ }
+
+ _gnapActionStatus = 6;
+ while (_gameSys->getAnimationStatus(6) != 2) {
+ // checkGameAppStatus();
+ updateMouseCursor();
+ gameUpdateTick();
+ }
+ _gnapActionStatus = -1;
+
+ if (buttonNum < 11)
+ phoneNumber = buttonNum % 10 + 10 * phoneNumber;
+
+ return phoneNumber;
+}
+
+int GnapEngine::scene53_getRandomCallIndex() {
+ int index, tries = 0;
+ if (_s53_callsRndUsed == 0x7FFF)
+ _s53_callsRndUsed = 0;
+ do {
+ index = getRandom(16);
+ if (++tries == 300)
+ _s53_callsRndUsed = 0;
+ } while (_s53_callsRndUsed & (1 << index));
+ _s53_callsRndUsed |= (1 << index);
+ return index;
+}
+
+void GnapEngine::scene53_runRandomCall() {
+
+ static const int kCallSequenceIds[15] = {
+ 0x60, 0x61, 0x62, 0x63, 0x64,
+ 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6A, 0x6B, 0x6C, 0x6D, 0x71
+ };
+
+ int index;
+
+ ++_s53_callsMadeCtr;
+
+ if (_s53_callsMadeCtr <= 10) {
+ do {
+ index = scene53_getRandomCallIndex();
+ } while (!_s53_isGnapPhoning && (index == 0 || index == 3 || index == 4 || index == 11));
+ _gameSys->setAnimation(kCallSequenceIds[index], 1, 6);
+ _gameSys->insertSequence(kCallSequenceIds[index], 1, 0, 0, kSeqNone, 16, 0, 0);
+ } else {
+ _gameSys->setAnimation(0x74, 1, 6);
+ _gameSys->insertSequence(0x74, 1, 0, 0, kSeqNone, 16, 0, 0);
+ _s53_callsMadeCtr = 0;
+ }
+
+ _gnapActionStatus = 1;
+ while (_gameSys->getAnimationStatus(6) != 2) {
+ updateMouseCursor();
+ // checkGameAppStatus();
+ gameUpdateTick();
+ }
+ _gnapActionStatus = -1;
+
+}
+
+void GnapEngine::scene53_runChitChatLine() {
+ bool flag = false;
+ int sequenceId;
+
+ _gameSys->setAnimation(0x6E, 1, 6);
+ _gameSys->insertSequence(0x6E, 1, 0, 0, kSeqNone, 16, 0, 0);
+
+ _gnapActionStatus = 1;
+ while (_gameSys->getAnimationStatus(6) != 2) {
+ updateMouseCursor();
+ // checkGameAppStatus();
+ gameUpdateTick();
+ }
+ _gnapActionStatus = -1;
+
+ if (isFlag(15)) {
+ _gameSys->insertSequence(0x45, 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _s53_currHandSequenceId = 0x45;
+ } else {
+ _gameSys->insertSequence(0x45, 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ _s53_currHandSequenceId = 0x5E;
+ }
+
+ _hotspots[1].flags = SF_DISABLED;
+
+ while (!flag) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+ case 2:
+ sequenceId = 0x6F;
+ flag = 1;
+ break;
+ case 3:
+ sequenceId = 0x70;
+ flag = 1;
+ break;
+ case 4:
+ sequenceId = 0x71;
+ flag = 1;
+ break;
+ case 14:
+ sequenceId = -1;
+ flag = 1;
+ _isLeavingScene = true;
+ _sceneDone = 1;
+ _gnapActionStatus = 0;
+ _newSceneNum = 17;
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ scene53_pressPhoneNumberButton(0, _sceneClickedHotspot - 1);
+ break;
+ }
+
+ if (flag && sequenceId != -1) {
+ stopSound(0xA0);
+ scene53_pressPhoneNumberButton(0, _sceneClickedHotspot - 1);
+ _gnapActionStatus = 1;
+ _gameSys->setAnimation(sequenceId, 1, 6);
+ _gameSys->insertSequence(sequenceId, 1, 0, 0, kSeqNone, 16, 0, 0);
+ _gnapActionStatus = 1;
+ while (_gameSys->getAnimationStatus(6) != 2) {
+ updateMouseCursor();
+ // checkGameAppStatus();
+ gameUpdateTick();
+ }
+ _gnapActionStatus = -1;
+ _gameSys->setAnimation(0x72, 1, 6);
+ _gameSys->insertSequence(0x72, 1, 0, 0, kSeqNone, 16, 0, 0);
+ _gnapActionStatus = 1;
+ while (_gameSys->getAnimationStatus(6) != 2) {
+ updateMouseCursor();
+ // checkGameAppStatus();
+ gameUpdateTick();
+ }
+ _gnapActionStatus = -1;
+ }
+
+ }
+
+ scene53_updateHotspots();
+
+ _gnapActionStatus = 1;
+
+ if (isFlag(15)) {
+ _gameSys->setAnimation(0x73, 40, 6);
+ _gameSys->insertSequence(0x73, 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(6) != 2) {
+ updateMouseCursor();
+ // checkGameAppStatus();
+ gameUpdateTick();
+ }
+ _s53_currHandSequenceId = 0x73;
+ _gnapActionStatus = -1;
+ }
+
+}
+
+void GnapEngine::scene53_run() {
+ int phoneNumber = 0;
+ int phoneNumberLen = 0;
+
+ queueInsertDeviceIcon();
+
+ if (isFlag(15)) {
+ _s53_currHandSequenceId = 0x45;
+ _s53_isGnapPhoning = true;
+ } else {
+ _s53_currHandSequenceId = 0x5E;
+ _s53_isGnapPhoning = false;
+ }
+
+ _gameSys->insertSequence(_s53_currHandSequenceId, 40, 0, 0, kSeqNone, 0, 0, 0);
+
+ endSceneInit();
+
+ setVerbCursor(GRAB_CURSOR);
+
+ playSound(0xA0, 1);
+
+ while (!_sceneDone) {
+
+ updateMouseCursor();
+ updateCursorByHotspot();
+
+ testWalk(0, 0, -1, -1, -1, -1);
+
+ _sceneClickedHotspot = getClickedHotspotId();
+ updateGrabCursorSprite(0, 0);
+
+ switch (_sceneClickedHotspot) {
+ case 1:
+ if (_gnapActionStatus < 0) {
+ runMenu();
+ scene53_updateHotspots();
+ }
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ stopSound(0xA0);
+ ++phoneNumberLen;
+ phoneNumber = scene53_pressPhoneNumberButton(phoneNumber, _sceneClickedHotspot - 1);
+ debug("phoneNumber: %d", phoneNumber);
+ if (phoneNumberLen == 7) {
+ _gnapActionStatus = 1;
+ if (isFlag(15)) {
+ _gameSys->setAnimation(0x73, 40, 6);
+ _gameSys->insertSequence(0x73, 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(6) != 2) {
+ updateMouseCursor();
+ // checkGameAppStatus();
+ gameUpdateTick();
+ }
+ _s53_currHandSequenceId = 0x73;
+ _gnapActionStatus = -1;
+ }
+ if (phoneNumber == 7284141) {
+ scene53_runChitChatLine();
+ phoneNumber = 0;
+ phoneNumberLen = 0;
+ _sceneDone = 1;
+ _newSceneNum = 17;
+ } else if (phoneNumber != 5556789 || isFlag(20)) {
+ scene53_runRandomCall();
+ phoneNumber = 0;
+ phoneNumberLen = 0;
+ _sceneDone = 1;
+ _newSceneNum = 17;
+ } else {
+ phoneNumber = 0;
+ phoneNumberLen = 0;
+ _sceneDone = 1;
+ _newSceneNum = 17;
+ if (_s53_isGnapPhoning)
+ setFlag(25);
+ else
+ setFlag(26);
+ }
+ }
+ break;
+ case 12:
+ case 13:
+ scene53_pressPhoneNumberButton(0, _sceneClickedHotspot - 1);
+ break;
+ case 14:
+ if (_gnapActionStatus < 0) {
+ _gnapActionStatus = 1;
+ if (isFlag(15)) {
+ _gameSys->setAnimation(0x73, 40, 6);
+ _gameSys->insertSequence(0x73, 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0);
+ while (_gameSys->getAnimationStatus(6) != 2) {
+ updateMouseCursor();
+ // checkGameAppStatus();
+ gameUpdateTick();
+ }
+ _s53_currHandSequenceId = 0x73;
+ _gnapActionStatus = -1;
+ }
+ _isLeavingScene = true;
+ _sceneDone = 1;
+ _gnapActionStatus = 0;
+ _newSceneNum = 17;
+ }
+ break;
+ }
+
+ checkGameKeys();
+
+ if (isKeyStatus1(8)) {
+ clearKeyStatus1(8);
+ runMenu();
+ scene53_updateHotspots();
+ }
+
+ gameUpdateTick();
+
+ }
+
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scene54.cpp b/engines/gnap/scenes/scene54.cpp
new file mode 100644
index 0000000000..76bc66b9f3
--- /dev/null
+++ b/engines/gnap/scenes/scene54.cpp
@@ -0,0 +1,127 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+void GnapEngine::scene54_initCutscene1() {
+ _s99_dword_47F370[0] = 0x1BE;
+ _s99_dword_47F370[1] = 0x1BF;
+ _s99_dword_47F370[2] = 0x1BA;
+ _s99_dword_47F370[3] = 0x1BB;
+ _s99_dword_47F370[4] = 0x1BD;
+ _s99_dword_47F370[5] = 0x1BC;
+ _s99_dword_47F2F0[0] = 0x3C;
+ _s99_dword_47F2F0[1] = 0x43;
+ _s99_dword_47F2F0[2] = 0x44;
+ if (isFlag(20))
+ _s99_dword_47F2F0[3] = 0x47;
+ else
+ _s99_dword_47F2F0[3] = 0x46;
+ _s99_dword_47F2F0[4] = 0x45;
+ _s99_dword_47F330[0] = 1;
+ _s99_dword_47F330[1] = 1;
+ _s99_dword_47F330[2] = 1;
+ _s99_dword_47F330[3] = 2;
+ _s99_dword_47F330[4] = 1;
+ _s99_canSkip[0] = 0;
+ _s99_canSkip[1] = 0;
+ _s99_canSkip[2] = 0;
+ _s99_canSkip[3] = 0;
+ _s99_canSkip[4] = 0;
+ _s99_itemsCount = 5;
+}
+
+void GnapEngine::scene54_initCutscene2() {
+ _s99_dword_47F370[0] = 0x1C9;
+ _s99_dword_47F370[1] = 0x1C7;
+ _s99_dword_47F370[2] = 0x1CC;
+ _s99_dword_47F370[3] = 0x1C8;
+ _s99_dword_47F370[4] = 0x1CB;
+ _s99_dword_47F370[5] = 0x1C0;
+ _s99_dword_47F370[6] = 0x1CA;
+ _s99_dword_47F370[7] = 0x1CE;
+ _s99_dword_47F370[8] = 0x1CD;
+ _s99_dword_47F370[9] = 0x1C1;
+ _s99_dword_47F370[10] = 0x1C2;
+ _s99_dword_47F370[11] = 0x1C3;
+ _s99_dword_47F370[12] = 0x1C4;
+ _s99_dword_47F370[13] = 0x1C6;
+ _s99_dword_47F370[14] = 0x1C5;
+ _s99_dword_47F370[15] = 0x1D0;
+ _s99_dword_47F370[16] = 0x1D0;
+ _s99_dword_47F370[17] = 0x1D0;
+ _s99_dword_47F2F0[0] = 0xD5;
+ _s99_dword_47F2F0[1] = 0x14C;
+ _s99_dword_47F2F0[2] = 0xD5;
+ _s99_dword_47F2F0[3] = 0xBF;
+ _s99_dword_47F2F0[4] = 0xD6;
+ _s99_dword_47F2F0[5] = 0x154;
+ _s99_dword_47F2F0[6] = 0x155;
+ _s99_dword_47F2F0[7] = 0xB9;
+ _s99_dword_47F2F0[8] = 0xBA;
+ _s99_dword_47F2F0[9] = 0x17B;
+ _s99_dword_47F2F0[10] = 0x17A;
+ _s99_dword_47F2F0[11] = 0x17C;
+ _s99_dword_47F2F0[12] = 0x17A;
+ _s99_dword_47F2F0[13] = 0x1B7;
+ _s99_dword_47F2F0[14] = 0x1B8;
+ _s99_dword_47F2F0[15] = 0x1B9;
+ _s99_dword_47F330[0] = 2;
+ _s99_dword_47F330[1] = 1;
+ _s99_dword_47F330[2] = 2;
+ _s99_dword_47F330[3] = 1;
+ _s99_dword_47F330[4] = 1;
+ _s99_dword_47F330[5] = 1;
+ _s99_dword_47F330[6] = 1;
+ _s99_dword_47F330[7] = 1;
+ _s99_dword_47F330[8] = 1;
+ _s99_dword_47F330[9] = 1;
+ _s99_dword_47F330[10] = 1;
+ _s99_dword_47F330[11] = 1;
+ _s99_dword_47F330[12] = 1;
+ _s99_dword_47F330[13] = 1;
+ _s99_dword_47F330[14] = 1;
+ _s99_dword_47F330[15] = 1;
+ _s99_canSkip[0] = 0;
+ _s99_canSkip[1] = 0;
+ _s99_canSkip[2] = 0;
+ _s99_canSkip[3] = 0;
+ _s99_canSkip[4] = 0;
+ _s99_canSkip[5] = 0;
+ _s99_canSkip[6] = 0;
+ _s99_canSkip[7] = 0;
+ _s99_canSkip[8] = 0;
+ _s99_canSkip[9] = 0;
+ _s99_canSkip[10] = 0;
+ _s99_canSkip[11] = 0;
+ _s99_canSkip[12] = 0;
+ _s99_canSkip[13] = 1;
+ _s99_canSkip[14] = 1;
+ _s99_canSkip[15] = 0;
+ _s99_itemsCount = 16;
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/scenes/scenecore.cpp b/engines/gnap/scenes/scenecore.cpp
new file mode 100644
index 0000000000..2736addb31
--- /dev/null
+++ b/engines/gnap/scenes/scenecore.cpp
@@ -0,0 +1,658 @@
+/* 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/gamesys.h"
+#include "gnap/resource.h"
+
+namespace Gnap {
+
+int GnapEngine::initSceneLogic() {
+
+ int backgroundId = -1;
+
+ switch (_currentSceneNum) {
+#if 0 // TODO
+ case 0:
+ backgroundId = scene00_init();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ break;
+#endif
+ case 1:
+ backgroundId = scene01_init();
+ scene01_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 2:
+ backgroundId = scene02_init();
+ scene02_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 3:
+ backgroundId = scene03_init();
+ scene03_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 4:
+ backgroundId = scene04_init();
+ scene04_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 5:
+ backgroundId = scene05_init();
+ scene05_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 6:
+ backgroundId = scene06_init();
+ scene06_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 7:
+ backgroundId = scene07_init();
+ scene07_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 8:
+ backgroundId = scene08_init();
+ scene08_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 9:
+ backgroundId = scene09_init();
+ scene09_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 10:
+ backgroundId = scene10_init();
+ scene10_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 11:
+ backgroundId = scene11_init();
+ scene11_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 12:
+ backgroundId = scene12_init();
+ scene12_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 13:
+ backgroundId = scene13_init();
+ scene13_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 14:
+ backgroundId = scene14_init();
+ scene14_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ break;
+ case 15:
+ backgroundId = scene15_init();
+ scene15_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ break;
+ case 16:
+ case 47:
+ case 48:
+ case 54:
+ backgroundId = cutscene_init();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ break;
+ case 17:
+ backgroundId = scene17_init();
+ scene17_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 18:
+ backgroundId = scene18_init();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ scene18_updateHotspots();
+ break;
+ case 19:
+ backgroundId = scene19_init();
+ scene19_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 20:
+ backgroundId = scene20_init();
+ scene20_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 21:
+ backgroundId = scene21_init();
+ scene21_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 22:
+ backgroundId = scene22_init();
+ scene22_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 23:
+ backgroundId = scene23_init();
+ scene23_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 24:
+ backgroundId = scene24_init();
+ scene24_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 136, 11, 10);
+ break;
+ case 25:
+ backgroundId = scene25_init();
+ scene25_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 26:
+ backgroundId = scene26_init();
+ scene26_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 27:
+ backgroundId = scene27_init();
+ scene27_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 28:
+ backgroundId = scene28_init();
+ scene28_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 29:
+ backgroundId = scene29_init();
+ scene29_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 30:
+ backgroundId = scene30_init();
+ scene30_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 31:
+ backgroundId = scene31_init();
+ scene31_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 32:
+ backgroundId = scene32_init();
+ scene32_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 33:
+ backgroundId = scene33_init();
+ scene33_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 34:
+ backgroundId = scene03_init();
+ scene03_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 35:
+ backgroundId = scene05_init();
+ scene05_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 36:
+ backgroundId = scene06_init();
+ scene06_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 37:
+ backgroundId = scene04_init();
+ scene04_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 38:
+ backgroundId = scene38_init();
+ scene38_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 39:
+ backgroundId = scene39_init();
+ scene39_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 40:
+ backgroundId = scene40_init();
+ scene40_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 41:
+ backgroundId = scene41_init();
+ scene41_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 42:
+ backgroundId = scene42_init();
+ scene42_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 43:
+ backgroundId = scene43_init();
+ scene43_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 44:
+ backgroundId = scene44_init();
+ scene44_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 45:
+ backgroundId = scene45_init();
+ scene45_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 46:
+ backgroundId = scene46_init();
+ scene46_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 49:
+ backgroundId = scene49_init();
+ scene49_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 50:
+ backgroundId = scene50_init();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 51:
+ backgroundId = scene51_init();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 52:
+ backgroundId = scene52_init();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ case 53:
+ backgroundId = scene53_init();
+ scene53_updateHotspots();
+ _gameSys->setScaleValues(0, 500, 1, 1000);
+ initSceneGrid(21, 146, 11, 10);
+ break;
+ }
+
+ return backgroundId;
+}
+
+void GnapEngine::runSceneLogic() {
+ switch (_currentSceneNum) {
+ case 0:
+#if 0 // TODO
+ scene00_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 8;
+ break;
+#endif
+ case 1:
+ scene01_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 4;
+ break;
+ case 2:
+ scene02_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 4;
+ break;
+ case 3:
+ scene03_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 4;
+ break;
+ case 4:
+ scene04_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 4;
+ break;
+ case 5:
+ scene05_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 4;
+ break;
+ case 6:
+ scene06_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 4;
+ break;
+ case 7:
+ scene07_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 8;
+ break;
+ case 8:
+ scene08_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 9;
+ break;
+ case 9:
+ scene09_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 10;
+ break;
+ case 10:
+ scene10_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 11;
+ break;
+ case 11:
+ scene11_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 12;
+ break;
+ case 12:
+ scene12_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 11;
+ break;
+ case 13:
+ scene13_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 11;
+ break;
+ case 14:
+ scene14_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 13;
+ break;
+ case 15:
+ scene15_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 12;
+ break;
+ case 16:
+ scene16_initCutscene();
+ _newSceneNum = 17;
+ _newCursorValue = 3;
+ cutscene_run();
+ break;
+ case 17:
+ scene17_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 18:
+ scene18_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 19:
+ scene19_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 19;
+ break;
+ case 20:
+ scene20_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 22;
+ break;
+ case 21:
+ scene21_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 22:
+ scene22_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 23:
+ scene23_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 24:
+ scene24_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 25:
+ scene25_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 26:
+ scene26_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 27:
+ scene27_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 28:
+ scene28_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 29:
+ scene29_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 30:
+ scene30_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 31:
+ scene31_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 20;
+ break;
+ case 32:
+ scene32_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 33:
+ scene33_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 34:
+ scene03_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 35:
+ scene05_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 36:
+ scene06_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 37:
+ scene04_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 38:
+ scene38_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 39:
+ scene39_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 40:
+ scene40_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 41:
+ scene41_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 42:
+ scene42_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 43:
+ scene43_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 44:
+ scene44_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 45:
+ scene45_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 46:
+ scene46_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 37;
+ break;
+ case 47:
+ if (_prevSceneNum == 49) {
+ scene47_initCutscene1();
+ _newSceneNum = 7;
+ _newCursorValue = 2;
+ } else if (_prevSceneNum == 13) {
+ scene47_initCutscene2();
+ _newSceneNum = 11;
+ } else if (!isFlag(10) && _prevSceneNum == 2) {//CHECKME
+ if (isFlag(25)) {
+ scene47_initCutscene3();
+ _newSceneNum = 2;
+ } else {
+ scene47_initCutscene4();
+ _newSceneNum = 49;
+ }
+ } else if (_prevSceneNum == 21) {
+ scene47_initCutscene5();
+ _newSceneNum = 21;
+ setFlag(3);
+ setFlag(5);
+ } else if (_prevSceneNum == 30) {
+ scene47_initCutscene6();
+ _newSceneNum = 26;
+ } else if (isFlag(10) && _cursorValue == 1) {
+ scene47_initCutscene7();
+ _newSceneNum = 4;
+ }
+ cutscene_run();
+ break;
+ case 48:
+ scene48_initCutscene();
+ _newSceneNum = 33;
+ _newCursorValue = 4;
+ cutscene_run();
+ break;
+ case 49:
+ scene49_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 47;
+ break;
+ case 50:
+ scene50_run();
+ _newSceneNum = _prevSceneNum;
+ break;
+ case 51:
+ scene51_run();
+ break;
+ case 52:
+ scene52_run();
+ _newSceneNum = _prevSceneNum;
+ break;
+ case 53:
+ scene53_run();
+ if (_newSceneNum == 55)
+ _newSceneNum = 53;
+ break;
+ case 54:
+ if (_prevSceneNum == 45) {
+ scene54_initCutscene1();
+ _newSceneNum = 43;
+ cutscene_run();
+ } else {
+ scene54_initCutscene2();
+ cutscene_run();
+ _gameDone = true;
+ }
+ break;
+ }
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/sound.cpp b/engines/gnap/sound.cpp
new file mode 100644
index 0000000000..9471d12a67
--- /dev/null
+++ b/engines/gnap/sound.cpp
@@ -0,0 +1,91 @@
+/* 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/sound.h"
+#include "audio/audiostream.h"
+#include "audio/decoders/wave.h"
+
+namespace Gnap {
+
+SoundMan::SoundMan(GnapEngine *vm)
+ : _vm(vm) {
+}
+
+SoundMan::~SoundMan() {
+}
+
+void SoundMan::playSound(int resourceId, bool looping) {
+ SoundItem soundItem;
+ soundItem.resourceId = resourceId;
+
+ SoundResource *soundResource = _vm->_soundCache->get(resourceId);
+ Common::MemoryReadStream *stream = new Common::MemoryReadStream(soundResource->_data, soundResource->_size, DisposeAfterUse::NO);
+ Audio::AudioStream *audioStream = Audio::makeLoopingAudioStream(Audio::makeWAVStream(stream, DisposeAfterUse::YES), looping ? 0 : 1);
+
+ _vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &soundItem.handle, audioStream);
+
+ _items.push_back(soundItem);
+
+}
+
+void SoundMan::stopSound(int resourceId) {
+ const int index = find(resourceId);
+ if (index >= 0) {
+ _vm->_soundCache->release(_items[index].resourceId);
+ _vm->_mixer->stopHandle(_items[index].handle);
+ _items.remove_at(index);
+ }
+}
+
+void SoundMan::setSoundVolume(int resourceId, int volume) {
+ // TODO
+}
+
+bool SoundMan::isSoundPlaying(int resourceId) {
+ const int index = find(resourceId);
+ return index >= 0 && _vm->_mixer->isSoundHandleActive(_items[index].handle);
+}
+
+void SoundMan::stopAll() {
+ for (int index = 0; index < (int)_items.size(); ++index) {
+ _vm->_soundCache->release(_items[index].resourceId);
+ _vm->_mixer->stopHandle(_items[index].handle);
+ }
+}
+
+void SoundMan::update() {
+ for (int index = 0; index < (int)_items.size(); ++index)
+ if (!_vm->_mixer->isSoundHandleActive(_items[index].handle)) {
+ _vm->_soundCache->release(_items[index].resourceId);
+ _items.remove_at(index);
+ --index;
+ }
+}
+
+int SoundMan::find(int resourceId) {
+ for (int index = 0; index < (int)_items.size(); ++index)
+ if (_items[index].resourceId == resourceId)
+ return index;
+ return -1;
+}
+
+} // End of namespace Gnap
diff --git a/engines/gnap/sound.h b/engines/gnap/sound.h
new file mode 100644
index 0000000000..ec5888ed1b
--- /dev/null
+++ b/engines/gnap/sound.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GNAP_SOUND_H
+#define GNAP_SOUND_H
+
+#include "gnap/gnap.h"
+#include "gnap/resource.h"
+#include "audio/mixer.h"
+#include "common/array.h"
+
+namespace Gnap {
+
+struct SoundItem {
+ int resourceId;
+ Audio::SoundHandle handle;
+};
+
+class SoundMan {
+public:
+ SoundMan(GnapEngine *vm);
+ ~SoundMan();
+ void playSound(int resourceId, bool looping);
+ void stopSound(int resourceId);
+ void setSoundVolume(int resourceId, int volume);
+ bool isSoundPlaying(int resourceId);
+ void stopAll();
+ void update();
+protected:
+ GnapEngine *_vm;
+ Common::Array<SoundItem> _items;
+ int find(int resourceId);
+};
+
+} // End of namespace Gnap
+
+#endif // GNAP_SOUND_H