From d80c7605a0892ae401953da4b889543598292986 Mon Sep 17 00:00:00 2001 From: johndoe123 Date: Tue, 7 Jan 2014 21:37:29 +0100 Subject: GNAP: Initial commit --- engines/gnap/datarchive.cpp | 121 ++ engines/gnap/datarchive.h | 80 ++ engines/gnap/detection.cpp | 195 +++ engines/gnap/fontdata.h | 851 +++++++++++++ engines/gnap/gamesys.cpp | 1303 ++++++++++++++++++++ engines/gnap/gamesys.h | 216 ++++ engines/gnap/gnap.cpp | 2404 +++++++++++++++++++++++++++++++++++++ engines/gnap/gnap.h | 1117 +++++++++++++++++ engines/gnap/grid.cpp | 1392 +++++++++++++++++++++ engines/gnap/menu.cpp | 811 +++++++++++++ engines/gnap/module.mk | 70 ++ engines/gnap/resource.cpp | 118 ++ engines/gnap/resource.h | 196 +++ engines/gnap/scenes/scene01.cpp | 373 ++++++ engines/gnap/scenes/scene02.cpp | 539 +++++++++ engines/gnap/scenes/scene03.cpp | 517 ++++++++ engines/gnap/scenes/scene04.cpp | 571 +++++++++ engines/gnap/scenes/scene05.cpp | 467 +++++++ engines/gnap/scenes/scene06.cpp | 446 +++++++ engines/gnap/scenes/scene07.cpp | 275 +++++ engines/gnap/scenes/scene08.cpp | 527 ++++++++ engines/gnap/scenes/scene09.cpp | 241 ++++ engines/gnap/scenes/scene10.cpp | 500 ++++++++ engines/gnap/scenes/scene11.cpp | 488 ++++++++ engines/gnap/scenes/scene12.cpp | 564 +++++++++ engines/gnap/scenes/scene13.cpp | 455 +++++++ engines/gnap/scenes/scene14.cpp | 194 +++ engines/gnap/scenes/scene15.cpp | 343 ++++++ engines/gnap/scenes/scene16.cpp | 82 ++ engines/gnap/scenes/scene17.cpp | 846 +++++++++++++ engines/gnap/scenes/scene18.cpp | 1026 ++++++++++++++++ engines/gnap/scenes/scene19.cpp | 470 ++++++++ engines/gnap/scenes/scene20.cpp | 736 ++++++++++++ engines/gnap/scenes/scene21.cpp | 345 ++++++ engines/gnap/scenes/scene22.cpp | 294 +++++ engines/gnap/scenes/scene23.cpp | 297 +++++ engines/gnap/scenes/scene24.cpp | 261 ++++ engines/gnap/scenes/scene25.cpp | 401 +++++++ engines/gnap/scenes/scene26.cpp | 256 ++++ engines/gnap/scenes/scene27.cpp | 423 +++++++ engines/gnap/scenes/scene28.cpp | 435 +++++++ engines/gnap/scenes/scene29.cpp | 352 ++++++ engines/gnap/scenes/scene30.cpp | 281 +++++ engines/gnap/scenes/scene31.cpp | 398 ++++++ engines/gnap/scenes/scene32.cpp | 201 ++++ engines/gnap/scenes/scene33.cpp | 327 +++++ engines/gnap/scenes/scene38.cpp | 355 ++++++ engines/gnap/scenes/scene39.cpp | 237 ++++ engines/gnap/scenes/scene40.cpp | 193 +++ engines/gnap/scenes/scene41.cpp | 577 +++++++++ engines/gnap/scenes/scene42.cpp | 494 ++++++++ engines/gnap/scenes/scene43.cpp | 484 ++++++++ engines/gnap/scenes/scene44.cpp | 529 ++++++++ engines/gnap/scenes/scene45.cpp | 430 +++++++ engines/gnap/scenes/scene46.cpp | 378 ++++++ engines/gnap/scenes/scene47.cpp | 171 +++ engines/gnap/scenes/scene48.cpp | 85 ++ engines/gnap/scenes/scene49.cpp | 513 ++++++++ engines/gnap/scenes/scene50.cpp | 479 ++++++++ engines/gnap/scenes/scene51.cpp | 880 ++++++++++++++ engines/gnap/scenes/scene52.cpp | 907 ++++++++++++++ engines/gnap/scenes/scene53.cpp | 383 ++++++ engines/gnap/scenes/scene54.cpp | 127 ++ engines/gnap/scenes/scenecore.cpp | 658 ++++++++++ engines/gnap/sound.cpp | 91 ++ engines/gnap/sound.h | 56 + 66 files changed, 30832 insertions(+) create mode 100644 engines/gnap/datarchive.cpp create mode 100644 engines/gnap/datarchive.h create mode 100644 engines/gnap/detection.cpp create mode 100644 engines/gnap/fontdata.h create mode 100644 engines/gnap/gamesys.cpp create mode 100644 engines/gnap/gamesys.h create mode 100644 engines/gnap/gnap.cpp create mode 100644 engines/gnap/gnap.h create mode 100644 engines/gnap/grid.cpp create mode 100644 engines/gnap/menu.cpp create mode 100644 engines/gnap/module.mk create mode 100644 engines/gnap/resource.cpp create mode 100644 engines/gnap/resource.h create mode 100644 engines/gnap/scenes/scene01.cpp create mode 100644 engines/gnap/scenes/scene02.cpp create mode 100644 engines/gnap/scenes/scene03.cpp create mode 100644 engines/gnap/scenes/scene04.cpp create mode 100644 engines/gnap/scenes/scene05.cpp create mode 100644 engines/gnap/scenes/scene06.cpp create mode 100644 engines/gnap/scenes/scene07.cpp create mode 100644 engines/gnap/scenes/scene08.cpp create mode 100644 engines/gnap/scenes/scene09.cpp create mode 100644 engines/gnap/scenes/scene10.cpp create mode 100644 engines/gnap/scenes/scene11.cpp create mode 100644 engines/gnap/scenes/scene12.cpp create mode 100644 engines/gnap/scenes/scene13.cpp create mode 100644 engines/gnap/scenes/scene14.cpp create mode 100644 engines/gnap/scenes/scene15.cpp create mode 100644 engines/gnap/scenes/scene16.cpp create mode 100644 engines/gnap/scenes/scene17.cpp create mode 100644 engines/gnap/scenes/scene18.cpp create mode 100644 engines/gnap/scenes/scene19.cpp create mode 100644 engines/gnap/scenes/scene20.cpp create mode 100644 engines/gnap/scenes/scene21.cpp create mode 100644 engines/gnap/scenes/scene22.cpp create mode 100644 engines/gnap/scenes/scene23.cpp create mode 100644 engines/gnap/scenes/scene24.cpp create mode 100644 engines/gnap/scenes/scene25.cpp create mode 100644 engines/gnap/scenes/scene26.cpp create mode 100644 engines/gnap/scenes/scene27.cpp create mode 100644 engines/gnap/scenes/scene28.cpp create mode 100644 engines/gnap/scenes/scene29.cpp create mode 100644 engines/gnap/scenes/scene30.cpp create mode 100644 engines/gnap/scenes/scene31.cpp create mode 100644 engines/gnap/scenes/scene32.cpp create mode 100644 engines/gnap/scenes/scene33.cpp create mode 100644 engines/gnap/scenes/scene38.cpp create mode 100644 engines/gnap/scenes/scene39.cpp create mode 100644 engines/gnap/scenes/scene40.cpp create mode 100644 engines/gnap/scenes/scene41.cpp create mode 100644 engines/gnap/scenes/scene42.cpp create mode 100644 engines/gnap/scenes/scene43.cpp create mode 100644 engines/gnap/scenes/scene44.cpp create mode 100644 engines/gnap/scenes/scene45.cpp create mode 100644 engines/gnap/scenes/scene46.cpp create mode 100644 engines/gnap/scenes/scene47.cpp create mode 100644 engines/gnap/scenes/scene48.cpp create mode 100644 engines/gnap/scenes/scene49.cpp create mode 100644 engines/gnap/scenes/scene50.cpp create mode 100644 engines/gnap/scenes/scene51.cpp create mode 100644 engines/gnap/scenes/scene52.cpp create mode 100644 engines/gnap/scenes/scene53.cpp create mode 100644 engines/gnap/scenes/scene54.cpp create mode 100644 engines/gnap/scenes/scenecore.cpp create mode 100644 engines/gnap/sound.cpp create mode 100644 engines/gnap/sound.h 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 _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 _soundIds; + + //////////////////////////////////////////////////////////////////////////// + + Common::Array _seqItems; + Common::Array _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 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 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 SpriteCache; +typedef ResourceCacheTemplate SoundCache; +typedef ResourceCacheTemplate 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 _items; + int find(int resourceId); +}; + +} // End of namespace Gnap + +#endif // GNAP_SOUND_H -- cgit v1.2.3